From 72f37f80d1a66725c583bd4db2663b98b71a9503 Mon Sep 17 00:00:00 2001 From: scannito Date: Mon, 16 Mar 2026 13:21:40 +0100 Subject: [PATCH 001/347] Add possibility to switch running mode --- .../Strangeness/phiStrangeCorrelator.cxx | 4 +- .../Strangeness/phiStrangeCorrelation.cxx | 142 +++++++++++++++++- 2 files changed, 136 insertions(+), 10 deletions(-) diff --git a/PWGLF/TableProducer/Strangeness/phiStrangeCorrelator.cxx b/PWGLF/TableProducer/Strangeness/phiStrangeCorrelator.cxx index 211302881a7..9c52a6e5285 100644 --- a/PWGLF/TableProducer/Strangeness/phiStrangeCorrelator.cxx +++ b/PWGLF/TableProducer/Strangeness/phiStrangeCorrelator.cxx @@ -419,9 +419,9 @@ struct K0sReducedCandProducer { { 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}]"}; + AxisSpec massK0SAxis = {200, 0.45f, 0.55f, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; - histos.add("h3K0sCandidatesMass", "K^{0}_{S} candidate invariant mass", kTH3F, {binnedmultAxis, binnedpTK0SAxis, massK0sAxis}); + histos.add("h3K0sCandidatesMass", "K^{0}_{S} candidate invariant mass", kTH3F, {binnedmultAxis, binnedpTK0SAxis, massK0SAxis}); } // Single track selection for strangeness sector diff --git a/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx b/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx index b427eafa899..eea9f239ee2 100644 --- a/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx +++ b/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx @@ -77,7 +77,14 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -static constexpr std::array phiMassRegionLabels{"Signal", "Sideband"}; +enum AnalysisMode { + kOldNormalization = 0, + kMassvsMass, + kDeltaYvsDeltaPhi +}; + +static constexpr std::array + phiMassRegionLabels{"Signal", "Sideband"}; enum ParticleOfInterest { Phi = 0, @@ -155,7 +162,7 @@ struct PhiStrangenessCorrelation { 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"}; + Configurable analysisMode{"analysisMode", kMassvsMass, "Analysis mode: 0 - old method with online normalization, 1 - new method with offline normlization, 2 - deltay vs deltaphi"}; // Configurable for event selection Configurable cutZVertex{"cutZVertex", 10.0f, "Accepted z-vertex range (cm)"}; // TO BE REMOVED @@ -258,12 +265,23 @@ struct PhiStrangenessCorrelation { AxisSpec massPhiAxis = {200, 0.9f, 1.2f, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; AxisSpec pTPhiAxis = {120, 0.0f, 12.0f, "#it{p}_{T} (GeV/#it{c})"}; AxisSpec binnedpTPhiAxis{(std::vector)binspTPhi, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec massK0SAxis = {200, 0.45f, 0.55f, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; AxisSpec pTK0SAxis = {100, 0.0f, 10.0f, "#it{p}_{T} (GeV/#it{c})"}; AxisSpec binnedpTK0SAxis{(std::vector)binspTK0S, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec nSigmaPiAxis = {100, -10.0f, 10.0f, "N#sigma #pi"}; AxisSpec pTPiAxis = {50, 0.0f, 5.0f, "#it{p}_{T} (GeV/#it{c})"}; AxisSpec binnedpTPiAxis{(std::vector)binspTPi, "#it{p}_{T} (GeV/#it{c})"}; histos.add("phi/h3PhiData", "Invariant mass of Phi in Data", kTH3F, {binnedmultAxis, binnedpTPhiAxis, massPhiAxis}); + + histos.add("phiK0S/h6PhiK0SData", "Invariant mass of Phi vs Invariant mass of K0Short in Data", kTHnSparseF, {binnedmultAxis, binnedpTPhiAxis, binnedpTK0SAxis, deltayAxis, massPhiAxis, massK0SAxis}); + histos.add("phiPi/h6PhiPiTPCData", "Invariant mass of Phi vs nSigmaTPC Pion in Data", kTHnSparseF, {binnedmultAxis, binnedpTPhiAxis, binnedpTPiAxis, deltayAxis, massPhiAxis, nSigmaPiAxis}); + histos.add("phiPi/h6PhiPiTOFData", "Invariant mass of Phi vs nSigmaTOF Pion in Data", kTHnSparseF, {binnedmultAxis, binnedpTPhiAxis, binnedpTPiAxis, deltayAxis, massPhiAxis, nSigmaPiAxis}); + + histos.add("phiK0S/h6PhiK0SDataME", "Invariant mass of Phi vs Invariant mass of K0Short in Data ME", kTHnSparseF, {binnedmultAxis, binnedpTPhiAxis, binnedpTK0SAxis, deltayAxis, massPhiAxis, massK0SAxis}); + histos.add("phiPi/h6PhiPiTPCDataME", "Invariant mass of Phi vs nSigmaTPC Pion in Data ME", kTHnSparseF, {binnedmultAxis, binnedpTPhiAxis, binnedpTPiAxis, deltayAxis, massPhiAxis, nSigmaPiAxis}); + histos.add("phiPi/h6PhiPiTOFDataME", "Invariant mass of Phi vs nSigmaTOF Pion in Data ME", kTHnSparseF, {binnedmultAxis, binnedpTPhiAxis, binnedpTPiAxis, deltayAxis, massPhiAxis, nSigmaPiAxis}); + for (const auto& label : phiMassRegionLabels) { histos.add(fmt::format("phiK0S/h5PhiK0SData{}", label).c_str(), "Deltay vs deltaphi for Phi and K0Short in Data", kTHnSparseF, {binnedmultAxis, binnedpTPhiAxis, binnedpTK0SAxis, deltayAxis, deltaphiAxis}); histos.add(fmt::format("phiPi/h5PhiPiData{}", label).c_str(), "Deltay vs deltaphi for Phi and Pion in Data", kTHnSparseF, {binnedmultAxis, binnedpTPhiAxis, binnedpTPiAxis, deltayAxis, deltaphiAxis}); @@ -344,7 +362,56 @@ struct PhiStrangenessCorrelation { histos.fill(HIST("phi/h3PhiData"), multiplicity, phiCand.pt(), phiCand.m(), weightPhi); - static_for<0, phiMassRegionLabels.size() - 1>([&](auto i_idx) { + auto processCorrelations = [&](auto fillK0S, auto fillPion) { + // 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, k0s.pt(), k0s.y())); + fillK0S(k0s, weightPhiK0S); + } + + // Loop over all primary pion candidates + for (const auto& pionTrack : pionTracks) { + float weightPhiPion = computeWeight(BoundEfficiencyMap(effMaps[Phi], multiplicity, phiCand.pt(), phiCand.y()), + BoundEfficiencyMap(effMaps[Pion], multiplicity, pionTrack.pt(), pionTrack.y())); + fillPion(pionTrack, weightPhiPion); + } + }; + + if (analysisMode == kMassvsMass) { + processCorrelations( + [&](const auto& k0s, float w) { + histos.fill(HIST("phiK0S/h6PhiK0SData"), multiplicity, phiCand.pt(), k0s.pt(), phiCand.y() - k0s.y(), phiCand.m(), k0s.m(), w); + }, + [&](const auto& pion, float w) { + histos.fill(HIST("phiPi/h6PhiPiTPCData"), multiplicity, phiCand.pt(), pion.pt(), phiCand.y() - pion.y(), phiCand.m(), pion.nSigmaTPC(), w); + histos.fill(HIST("phiPi/h6PhiPiTOFData"), multiplicity, phiCand.pt(), pion.pt(), phiCand.y() - pion.y(), phiCand.m(), pion.nSigmaTOF(), w); + }); + } else if (analysisMode == kDeltaYvsDeltaPhi) { + static_for<0, phiMassRegionLabels.size() - 1>([&](auto i_idx) { + constexpr unsigned int i = i_idx.value; + + const auto& [minMassPhi, maxMassPhi] = phiMassRegions[i]; + if (!phiCand.inMassRegion(minMassPhi, maxMassPhi)) + return; + + processCorrelations( + [&](const auto& k0s, float w) { + histos.fill(HIST("phiK0S/h5PhiK0SData") + HIST(phiMassRegionLabels[i]), multiplicity, phiCand.pt(), k0s.pt(), phiCand.y() - k0s.y(), getDeltaPhi(phiCand.phi(), k0s.phi()), w); + }, + [&](const auto& pion, float w) { + histos.fill(HIST("phiPi/h5PhiPiData") + HIST(phiMassRegionLabels[i]), multiplicity, phiCand.pt(), pion.pt(), phiCand.y() - pion.y(), getDeltaPhi(phiCand.phi(), pion.phi()), w); + }); + }); + } + + /*static_for<0, phiMassRegionLabels.size() - 1>([&](auto i_idx) { constexpr unsigned int i = i_idx.value; const auto& [minMassPhi, maxMassPhi] = phiMassRegions[i]; @@ -372,7 +439,7 @@ struct PhiStrangenessCorrelation { histos.fill(HIST("phiPi/h5PhiPiData") + HIST(phiMassRegionLabels[i]), multiplicity, phiCand.pt(), pionTrack.pt(), phiCand.y() - pionTrack.y(), getDeltaPhi(phiCand.phi(), pionTrack.phi()), weightPhiPion); } - }); + });*/ } } @@ -390,7 +457,39 @@ struct PhiStrangenessCorrelation { float multiplicity = c1.centFT0M(); for (const auto& [phiCand, k0s] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(phiCands, k0sRed))) { - static_for<0, phiMassRegionLabels.size() - 1>([&](auto i_idx) { + auto processCorrelations = [&](auto fillK0S) { + 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, k0s.pt(), k0s.y())); + fillK0S(k0s, weightPhiK0S); + }; + + if (analysisMode == kMassvsMass) { + processCorrelations( + [&](const auto& k0s, float w) { + histos.fill(HIST("phiK0S/h6PhiK0SDataMe"), multiplicity, phiCand.pt(), k0s.pt(), phiCand.y() - k0s.y(), phiCand.m(), k0s.m(), w); + }); + } else if (analysisMode == kDeltaYvsDeltaPhi) { + static_for<0, phiMassRegionLabels.size() - 1>([&](auto i_idx) { + constexpr unsigned int i = i_idx.value; + + const auto& [minMassPhi, maxMassPhi] = phiMassRegions[i]; + if (!phiCand.inMassRegion(minMassPhi, maxMassPhi)) + return; + + processCorrelations( + [&](const auto& k0s, float w) { + histos.fill(HIST("phiK0S/h5PhiK0SDataME") + HIST(phiMassRegionLabels[i]), multiplicity, phiCand.pt(), k0s.pt(), phiCand.y() - k0s.y(), getDeltaPhi(phiCand.phi(), k0s.phi()), w); + }); + }); + } + + /*static_for<0, phiMassRegionLabels.size() - 1>([&](auto i_idx) { constexpr unsigned int i = i_idx.value; const auto& [minMassPhi, maxMassPhi] = phiMassRegions[i]; @@ -407,7 +506,7 @@ struct PhiStrangenessCorrelation { BoundEfficiencyMap(effMaps[K0S], multiplicity, k0s.pt(), k0s.y())); histos.fill(HIST("phiK0S/h5PhiK0SDataME") + HIST(phiMassRegionLabels[i]), multiplicity, phiCand.pt(), k0s.pt(), phiCand.y() - k0s.y(), getDeltaPhi(phiCand.phi(), k0s.phi()), weightPhiK0S); - }); + });*/ } } } @@ -426,7 +525,34 @@ struct PhiStrangenessCorrelation { float multiplicity = c1.centFT0M(); for (const auto& [phiCand, piTrack] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(phiCands, piTracks))) { - static_for<0, phiMassRegionLabels.size() - 1>([&](auto i_idx) { + auto processCorrelations = [&](auto fillPion) { + float weightPhiPion = computeWeight(BoundEfficiencyMap(effMaps[Phi], multiplicity, phiCand.pt(), phiCand.y()), + BoundEfficiencyMap(effMaps[Pion], multiplicity, piTrack.pt(), piTrack.y())); + fillPion(piTrack, weightPhiPion); + }; + + if (analysisMode == kMassvsMass) { + processCorrelations( + [&](const auto& pion, float w) { + histos.fill(HIST("phiPi/h6PhiPiTPCDataME"), multiplicity, phiCand.pt(), pion.pt(), phiCand.y() - pion.y(), phiCand.m(), pion.nSigmaTPC(), w); + histos.fill(HIST("phiPi/h6PhiPiTOFDataME"), multiplicity, phiCand.pt(), pion.pt(), phiCand.y() - pion.y(), phiCand.m(), pion.nSigmaTOF(), w); + }); + } else if (analysisMode == kDeltaYvsDeltaPhi) { + static_for<0, phiMassRegionLabels.size() - 1>([&](auto i_idx) { + constexpr unsigned int i = i_idx.value; + + const auto& [minMassPhi, maxMassPhi] = phiMassRegions[i]; + if (!phiCand.inMassRegion(minMassPhi, maxMassPhi)) + return; + + processCorrelations( + [&](const auto& pion, float w) { + histos.fill(HIST("phiPi/h5PhiPiDataME") + HIST(phiMassRegionLabels[i]), multiplicity, phiCand.pt(), pion.pt(), phiCand.y() - pion.y(), getDeltaPhi(phiCand.phi(), pion.phi()), w); + }); + }); + } + + /*static_for<0, phiMassRegionLabels.size() - 1>([&](auto i_idx) { constexpr unsigned int i = i_idx.value; const auto& [minMassPhi, maxMassPhi] = phiMassRegions[i]; @@ -437,7 +563,7 @@ struct PhiStrangenessCorrelation { BoundEfficiencyMap(effMaps[Pion], multiplicity, piTrack.pt(), piTrack.y())); histos.fill(HIST("phiPi/h5PhiPiDataME") + HIST(phiMassRegionLabels[i]), multiplicity, phiCand.pt(), piTrack.pt(), phiCand.y() - piTrack.y(), getDeltaPhi(phiCand.phi(), piTrack.phi()), weightPhiPion); - }); + });*/ } } } From 53172ca8becc7a377154003163871d3e93c11860 Mon Sep 17 00:00:00 2001 From: scannito Date: Mon, 16 Mar 2026 14:47:49 +0100 Subject: [PATCH 002/347] Rework K0s inclusion condition --- .../Strangeness/phiStrangeCorrelation.cxx | 29 +++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx b/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx index eea9f239ee2..e45cbf23968 100644 --- a/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx +++ b/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx @@ -357,6 +357,13 @@ struct PhiStrangenessCorrelation { const std::array, 2> phiMassRegions = {phiConfigs.rangeMPhiSignal, phiConfigs.rangeMPhiSideband}; + const bool applyK0sMassCut = (analysisMode == kDeltaYvsDeltaPhi) && k0sConfigs.selectK0sInSigRegion; + const auto& [minMassK0s, maxMassK0s] = k0sConfigs.rangeMK0sSignal.value; + + auto isK0sValid = [&](const auto& k0s) { + return !applyK0sMassCut || k0s.inMassRegion(minMassK0s, maxMassK0s); + }; + for (const auto& phiCand : phiCandidates) { float weightPhi = computeWeight(BoundEfficiencyMap(effMaps[Phi], multiplicity, phiCand.pt(), phiCand.y())); @@ -365,11 +372,13 @@ struct PhiStrangenessCorrelation { auto processCorrelations = [&](auto fillK0S, auto fillPion) { // Loop over all reduced K0S candidates for (const auto& k0s : k0sReduced) { - if (k0sConfigs.selectK0sInSigRegion) { + /*if (k0sConfigs.selectK0sInSigRegion) { const auto& [minMassK0s, maxMassK0s] = k0sConfigs.rangeMK0sSignal.value; if (!k0s.inMassRegion(minMassK0s, maxMassK0s)) continue; - } + }*/ + if (!isK0sValid(k0s)) + continue; float weightPhiK0S = computeWeight(BoundEfficiencyMap(effMaps[Phi], multiplicity, phiCand.pt(), phiCand.y()), BoundEfficiencyMap(effMaps[K0S], multiplicity, k0s.pt(), k0s.y())); @@ -449,6 +458,13 @@ struct PhiStrangenessCorrelation { { const std::array, 2> phiMassRegions = {phiConfigs.rangeMPhiSignal, phiConfigs.rangeMPhiSideband}; + const bool applyK0sMassCut = (analysisMode == kDeltaYvsDeltaPhi) && k0sConfigs.selectK0sInSigRegion; + const auto& [minMassK0s, maxMassK0s] = k0sConfigs.rangeMK0sSignal.value; + + auto isK0sValid = [&](const auto& k0s) { + return !applyK0sMassCut || k0s.inMassRegion(minMassK0s, maxMassK0s); + }; + auto tuplePhiK0S = std::make_tuple(phiCandidates, k0sReduced); Pair pairPhiK0S{binningOnVertexAndCent, cfgNoMixedEvents, -1, collisions, tuplePhiK0S, &cache}; @@ -457,12 +473,15 @@ struct PhiStrangenessCorrelation { float multiplicity = c1.centFT0M(); for (const auto& [phiCand, k0s] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(phiCands, k0sRed))) { + if (!isK0sValid(k0s)) + continue; + auto processCorrelations = [&](auto fillK0S) { - if (k0sConfigs.selectK0sInSigRegion) { + /*if (k0sConfigs.selectK0sInSigRegion) { const auto& [minMassK0s, maxMassK0s] = k0sConfigs.rangeMK0sSignal.value; if (!k0s.inMassRegion(minMassK0s, maxMassK0s)) - return; - } + continue; + }*/ float weightPhiK0S = computeWeight(BoundEfficiencyMap(effMaps[Phi], multiplicity, phiCand.pt(), phiCand.y()), BoundEfficiencyMap(effMaps[K0S], multiplicity, k0s.pt(), k0s.y())); From d3dc1876b51f0775c121f713f7340a6814fe8bc7 Mon Sep 17 00:00:00 2001 From: scannito Date: Mon, 16 Mar 2026 15:37:03 +0100 Subject: [PATCH 003/347] Allow for MC Clsoure with PDG --- .../Strangeness/phiStrangeCorrelation.cxx | 57 +++++++++++++++++-- 1 file changed, 51 insertions(+), 6 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx b/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx index e45cbf23968..d24782985c3 100644 --- a/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx +++ b/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx @@ -351,7 +351,8 @@ struct PhiStrangenessCorrelation { return RecoDecay::constrainAngle(phiTrigger - phiAssociated, -o2::constants::math::PIHalf); } - void processPhiK0SPionData(SelCollisions::iterator const& collision, aod::PhimesonCandidatesData const& phiCandidates, aod::K0sReducedCandidatesData const& k0sReduced, aod::PionTracksData const& pionTracks) + template + void processPhiK0SPionSE(TCollision const& collision, TPhiCands const& phiCandidates, TK0SCands const& k0sReduced, TPionCands const& pionTracks) { float multiplicity = collision.centFT0M(); @@ -452,9 +453,24 @@ struct PhiStrangenessCorrelation { } } - PROCESS_SWITCH(PhiStrangenessCorrelation, processPhiK0SPionData, "Process function for Phi-K0S and Phi-Pion Deltay and Deltaphi 2D Correlations in Data", true); + // PROCESS_SWITCH(PhiStrangenessCorrelation, processPhiK0SPionSE, "Process function for Phi-K0S and Phi-Pion Deltay and Deltaphi 2D Correlations in SE", true); - void processPhiK0SDataME(SelCollisions const& collisions, aod::PhimesonCandidatesData const& phiCandidates, aod::K0sReducedCandidatesData const& k0sReduced) + void processPhiK0SPionSEDataLike(SelCollisions::iterator const& collision, aod::PhimesonCandidatesData const& phiCandidates, aod::K0sReducedCandidatesData const& k0sReduced, aod::PionTracksData const& pionTracks) + { + processPhiK0SPionSE(collision, phiCandidates, k0sReduced, pionTracks); + } + + PROCESS_SWITCH(PhiStrangenessCorrelation, processPhiK0SPionSEDataLike, "Process function for Phi-K0S and Phi-Pion 2D Correlations in Data or MC w/o PDG SE", true); + + void processPhiK0SPionSEMCWithPDG(SimCollisions::iterator const& collision, aod::PhimesonCandidatesMcReco const& phiCandidates, aod::K0sReducedCandidatesMcReco const& k0sReduced, aod::PionTracksMcReco const& pionTracks) + { + processPhiK0SPionSE(collision, phiCandidates, k0sReduced, pionTracks); + } + + PROCESS_SWITCH(PhiStrangenessCorrelation, processPhiK0SPionSEMCWithPDG, "Process function for Phi-K0S and Phi-Pion 2D Correlations in MC with PDG SE", true); + + template + void processPhiK0SME(TCollisions const& collisions, TPhiCands const& phiCandidates, TK0SCands const& k0sReduced) { const std::array, 2> phiMassRegions = {phiConfigs.rangeMPhiSignal, phiConfigs.rangeMPhiSideband}; @@ -530,9 +546,24 @@ struct PhiStrangenessCorrelation { } } - PROCESS_SWITCH(PhiStrangenessCorrelation, processPhiK0SDataME, "Process function for Phi-K0S and Deltay and Deltaphi 2D Correlations in Data ME", false); + // PROCESS_SWITCH(PhiStrangenessCorrelation, processPhiK0SME, "Process function for Phi-K0S and Deltay and Deltaphi 2D Correlations in Data ME", false); + + void processPhiK0SMEDataLike(SelCollisions const& collisions, aod::PhimesonCandidatesData const& phiCandidates, aod::K0sReducedCandidatesData const& k0sReduced) + { + processPhiK0SME(collisions, phiCandidates, k0sReduced); + } + + PROCESS_SWITCH(PhiStrangenessCorrelation, processPhiK0SMEDataLike, "Process function for Phi-K0S 2D Correlations in Data or MC w/o PDG ME", true); - void processPhiPionDataME(SelCollisions const& collisions, aod::PhimesonCandidatesData const& phiCandidates, aod::PionTracksData const& pionTracks) + void processPhiK0SMEMCWithPDG(SimCollisions const& collisions, aod::PhimesonCandidatesMcReco const& phiCandidates, aod::K0sReducedCandidatesMcReco const& k0sReduced) + { + processPhiK0SME(collisions, phiCandidates, k0sReduced); + } + + PROCESS_SWITCH(PhiStrangenessCorrelation, processPhiK0SMEMCWithPDG, "Process function for Phi-K0S 2D Correlations in MC with PDG ME", true); + + template + void processPhiPionME(TCollisions const& collisions, TPhiCands const& phiCandidates, TPionCands const& pionTracks) { const std::array, 2> phiMassRegions = {phiConfigs.rangeMPhiSignal, phiConfigs.rangeMPhiSideband}; @@ -587,7 +618,21 @@ struct PhiStrangenessCorrelation { } } - PROCESS_SWITCH(PhiStrangenessCorrelation, processPhiPionDataME, "Process function for Phi-Pion Deltay and Deltaphi 2D Correlations in Data ME", false); + // PROCESS_SWITCH(PhiStrangenessCorrelation, processPhiPionME, "Process function for Phi-Pion Deltay and Deltaphi 2D Correlations in Data ME", false); + + void processPhiPionMEDataLike(SelCollisions const& collisions, aod::PhimesonCandidatesData const& phiCandidates, aod::PionTracksData const& pionTracks) + { + processPhiPionME(collisions, phiCandidates, pionTracks); + } + + PROCESS_SWITCH(PhiStrangenessCorrelation, processPhiPionMEDataLike, "Process function for Phi-Pion 2D Correlations in Data or MC w/o PDG ME", true); + + void processPhiPionMEMCWithPDG(SimCollisions const& collisions, aod::PhimesonCandidatesMcReco const& phiCandidates, aod::PionTracksMcReco const& pionTracks) + { + processPhiPionME(collisions, phiCandidates, pionTracks); + } + + PROCESS_SWITCH(PhiStrangenessCorrelation, processPhiPionMEMCWithPDG, "Process function for Phi-Pion 2D Correlations in MC with PDG ME", true); void processParticleEfficiency(MCCollisions const& mcCollisions, SimCollisions const& collisions, aod::PhimesonCandidatesMcReco const& phiCandidates, aod::K0sReducedCandidatesMcReco const& k0sReduced, aod::PionTracksMcReco const& pionTracks, aod::McParticles const& mcParticles) { From c693b974829c9aadae8b30c9cb39dba11a090975 Mon Sep 17 00:00:00 2001 From: scannito Date: Mon, 16 Mar 2026 15:40:55 +0100 Subject: [PATCH 004/347] Fix types --- 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 d24782985c3..189a306f065 100644 --- a/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx +++ b/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx @@ -482,7 +482,7 @@ struct PhiStrangenessCorrelation { }; auto tuplePhiK0S = std::make_tuple(phiCandidates, k0sReduced); - Pair pairPhiK0S{binningOnVertexAndCent, cfgNoMixedEvents, -1, collisions, tuplePhiK0S, &cache}; + Pair pairPhiK0S{binningOnVertexAndCent, cfgNoMixedEvents, -1, collisions, tuplePhiK0S, &cache}; for (const auto& [c1, phiCands, c2, k0sRed] : pairPhiK0S) { @@ -568,7 +568,7 @@ struct PhiStrangenessCorrelation { const std::array, 2> phiMassRegions = {phiConfigs.rangeMPhiSignal, phiConfigs.rangeMPhiSideband}; auto tuplePhiPion = std::make_tuple(phiCandidates, pionTracks); - Pair pairPhiPion{binningOnVertexAndCent, cfgNoMixedEvents, -1, collisions, tuplePhiPion, &cache}; + Pair pairPhiPion{binningOnVertexAndCent, cfgNoMixedEvents, -1, collisions, tuplePhiPion, &cache}; for (const auto& [c1, phiCands, c2, piTracks] : pairPhiPion) { From 714240fcbfc2f54c05d874f7a9e3c344a3f4763a Mon Sep 17 00:00:00 2001 From: scannito Date: Tue, 17 Mar 2026 12:08:55 +0100 Subject: [PATCH 005/347] Fix preslice --- PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx b/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx index 189a306f065..3288138cc32 100644 --- a/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx +++ b/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx @@ -83,8 +83,7 @@ enum AnalysisMode { kDeltaYvsDeltaPhi }; -static constexpr std::array - phiMassRegionLabels{"Signal", "Sideband"}; +static constexpr std::array phiMassRegionLabels{"Signal", "Sideband"}; enum ParticleOfInterest { Phi = 0, @@ -231,7 +230,8 @@ struct PhiStrangenessCorrelation { struct : PresliceGroup { Preslice phiCandDataPerCollision = aod::lf_selection_phi_candidate::collisionId; - PresliceUnsorted phiCandMcRecoPerCollision = aod::lf_selection_phi_candidate::collisionId; + // PresliceUnsorted phiCandMcRecoPerCollision = aod::lf_selection_phi_candidate::collisionId; + Preslice phiCandMcRecoPerCollision = aod::lf_selection_phi_candidate::collisionId; Preslice k0sDataPerCollision = aod::v0::collisionId; Preslice k0sMcRecoPerCollision = aod::v0::collisionId; @@ -309,10 +309,6 @@ struct PhiStrangenessCorrelation { histos.add("pi/h3PiMCGen", "Pion in MC Gen", kTH3F, {binnedmultAxis, binnedpTPiAxis, yAxis}); histos.add("pi/h4PiMCGenAssocReco", "Pion in MC Gen Assoc Reco", kTHnSparseF, {vertexZAxis, binnedmultAxis, binnedpTPiAxis, yAxis}); - histos.add("pi/h2RecMCDCAxyPrimPi", "Dcaxy distribution vs pt for Primary Pions", kTH2F, {binnedpTPiAxis, {2000, -0.05, 0.05, "DCA_{xy} (cm)"}}); - histos.add("pi/h2RecMCDCAxySecWeakDecayPi", "Dcaz distribution vs pt for Secondary Pions from Weak Decay", kTH2F, {binnedpTPiAxis, {2000, -0.05, 0.05, "DCA_{xy} (cm)"}}); - histos.add("pi/h2RecMCDCAxySecMaterialPi", "Dcaxy distribution vs pt for Secondary Pions from Material", kTH2F, {binnedpTPiAxis, {2000, -0.05, 0.05, "DCA_{xy} (cm)"}}); - // Load efficiency maps from CCDB if (applyEfficiency) { ccdb->setURL(ccdbUrl); From c7dd24107919c83d9a21e47e175a551c57bd606d Mon Sep 17 00:00:00 2001 From: scannito Date: Tue, 17 Mar 2026 14:39:43 +0100 Subject: [PATCH 006/347] Change default efficiency path --- 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 3288138cc32..dad4880bf63 100644 --- a/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx +++ b/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx @@ -207,7 +207,7 @@ struct PhiStrangenessCorrelation { // Configurables for CCDB 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"}; + Configurable ccdbEfficiencyPath{"ccdbEfficiencyPath", "Users/s/scannito/Efficiencies/h3EffMap", "Correction path to file"}; // Configurables for minimum pt selection in McGen struct : ConfigurableGroup { @@ -324,7 +324,7 @@ struct PhiStrangenessCorrelation { void loadEfficiencyMapFromCCDB(ParticleOfInterest poi) { - effMaps[poi] = std::shared_ptr(ccdb->get(fmt::format("{}/h3EffMap{}", ccdbEfficiencyPath.value, particleOfInterestLabels[poi]))); + effMaps[poi] = std::shared_ptr(ccdb->get(fmt::format("{}{}", ccdbEfficiencyPath.value, particleOfInterestLabels[poi]))); if (!effMaps[poi]) LOG(fatal) << "Could not load efficiency map for " << particleOfInterestLabels[poi] << "!"; LOG(info) << "Efficiency map for " << particleOfInterestLabels[poi] << " loaded from CCDB"; From 91ca93ac15373600475c59b911f94807e8afd4ca Mon Sep 17 00:00:00 2001 From: scannito Date: Tue, 17 Mar 2026 17:24:04 +0100 Subject: [PATCH 007/347] Make pion selection flexible --- .../DataModel/LFPhiStrangeCorrelationTables.h | 22 +++++++++- .../Strangeness/phiStrangeCorrelator.cxx | 44 +++++++++++++++---- .../Strangeness/phiStrangeCorrelation.cxx | 36 ++++++++++++++- 3 files changed, 89 insertions(+), 13 deletions(-) diff --git a/PWGLF/DataModel/LFPhiStrangeCorrelationTables.h b/PWGLF/DataModel/LFPhiStrangeCorrelationTables.h index e72662a92e5..b0fcea7fa61 100644 --- a/PWGLF/DataModel/LFPhiStrangeCorrelationTables.h +++ b/PWGLF/DataModel/LFPhiStrangeCorrelationTables.h @@ -148,6 +148,18 @@ DECLARE_SOA_COLUMN(NSigmaTOF, nSigmaTOF, float); DECLARE_SOA_COLUMN(Pt, pt, float); DECLARE_SOA_COLUMN(Y, y, float); DECLARE_SOA_COLUMN(Phi, phi, float); +DECLARE_SOA_COLUMN(HasTOF, hasTOF, bool); + +DECLARE_SOA_DYNAMIC_COLUMN(InNSigmaRegion, inNSigmaRegion, + [](float nSigmaTPC, float pt, bool hasTOF, float nSigmaTOF, float pidTPCMax, float tofPIDThreshold, float pidTOFMax) -> bool { + if (std::abs(nSigmaTPC) >= pidTPCMax) { + return false; // TPC check failed + } + if (pt >= tofPIDThreshold && hasTOF && std::abs(nSigmaTOF) >= pidTOFMax) { + return false; // TOF check failed + }; + return true; + }); } // namespace lf_selection_pion_track DECLARE_SOA_TABLE(PionTracksData, "AOD", "PITRACKSDATA", @@ -157,7 +169,10 @@ DECLARE_SOA_TABLE(PionTracksData, "AOD", "PITRACKSDATA", lf_selection_pion_track::NSigmaTOF, lf_selection_pion_track::Pt, lf_selection_pion_track::Y, - lf_selection_pion_track::Phi); + lf_selection_pion_track::Phi, + lf_selection_pion_track::HasTOF, + lf_selection_pion_track::InNSigmaRegion); DECLARE_SOA_TABLE(PionTracksMcReco, "AOD", "PITRACKSMCRECO", soa::Index<>, @@ -166,7 +181,10 @@ DECLARE_SOA_TABLE(PionTracksMcReco, "AOD", "PITRACKSMCRECO", lf_selection_pion_track::NSigmaTOF, lf_selection_pion_track::Pt, lf_selection_pion_track::Y, - lf_selection_pion_track::Phi); + lf_selection_pion_track::Phi, + lf_selection_pion_track::HasTOF, + lf_selection_pion_track::InNSigmaRegion); } // namespace o2::aod #endif // PWGLF_DATAMODEL_LFPHISTRANGECORRELATIONTABLES_H_ diff --git a/PWGLF/TableProducer/Strangeness/phiStrangeCorrelator.cxx b/PWGLF/TableProducer/Strangeness/phiStrangeCorrelator.cxx index 9c52a6e5285..b4f266b96b1 100644 --- a/PWGLF/TableProducer/Strangeness/phiStrangeCorrelator.cxx +++ b/PWGLF/TableProducer/Strangeness/phiStrangeCorrelator.cxx @@ -527,7 +527,7 @@ struct PionTrackProducer { HistogramRegistry histos{"pionTracks", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; // Configurable for analysis mode - Configurable analysisMode{"analysisMode", 1, "Analysis mode: 0 - old method with online normalization, 1 - new method with correlations"}; + // Configurable analysisMode{"analysisMode", 1, "Analysis mode: 0 - old method with online normalization, 1 - new method with correlations"}; // 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"}; @@ -547,11 +547,11 @@ struct PionTrackProducer { 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 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> trkPIDspecies{"trkPIDspecies", std::vector{o2::track::PID::Kaon, o2::track::PID::Proton}, "Trk sel: Particles species for PID rejection, kaon, proton"}; + Configurable> pidTPCMax{"pidTPCMax", std::vector{2.0f, 2.0f}, "maximum nSigma TPC"}; + Configurable> pidTOFMax{"pidTOFMax", std::vector{2.0f, 2.0f}, "maximum nSigma TOF"}; Configurable cfgYAcceptance{"cfgYAcceptance", 0.5f, "Rapidity acceptance"}; } trackConfigs; @@ -590,7 +590,7 @@ struct PionTrackProducer { 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 + /*// PID selection for Pions template bool pidSelectionPion(const T& track) { @@ -626,6 +626,29 @@ struct PionTrackProducer { } } + return true; + }*/ + + // PID Hypotheses rejection for Pions + template + bool pidHypothesesRejection(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 (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; } @@ -657,7 +680,10 @@ struct PionTrackProducer { if (trackConfigs.cfgIsTOFChecked && track.pt() >= trackConfigs.tofPIDThreshold && !track.hasTOF()) return false; - if (analysisMode == 1 && !pidSelectionPion(track)) + /*if (analysisMode == 1 && !pidSelectionPion(track)) + return false;*/ + + if (!pidHypothesesRejection(track)) return false; /* @@ -685,7 +711,7 @@ struct PionTrackProducer { histos.fill(HIST("h3PionTPCnSigma"), collision.centFT0M(), track.pt(), track.tpcNSigmaPi()); histos.fill(HIST("h3PionTOFnSigma"), collision.centFT0M(), track.pt(), track.tofNSigmaPi()); - pionTracksData(collision.globalIndex(), track.tpcNSigmaPi(), track.tofNSigmaPi(), track.pt(), track.rapidity(massPi), track.phi()); + pionTracksData(collision.globalIndex(), track.tpcNSigmaPi(), track.tofNSigmaPi(), track.pt(), track.rapidity(massPi), track.phi(), track.hasTOF()); } } @@ -715,7 +741,7 @@ struct PionTrackProducer { continue; } - pionTracksMcReco(collision.globalIndex(), track.tpcNSigmaPi(), track.tofNSigmaPi(), track.pt(), track.rapidity(massPi), track.phi()); + pionTracksMcReco(collision.globalIndex(), track.tpcNSigmaPi(), track.tofNSigmaPi(), track.pt(), track.rapidity(massPi), track.phi(), track.hasTOF()); } } diff --git a/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx b/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx index dad4880bf63..310d284a3b9 100644 --- a/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx +++ b/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx @@ -181,6 +181,14 @@ struct PhiStrangenessCorrelation { Configurable> rangeMK0sSignal{"rangeMK0sSignal", {0.47f, 0.53f}, "K0S mass range for signal extraction"}; } k0sConfigs; + // Configurables for Pions selection + struct : ConfigurableGroup { + Configurable selectPionInSigRegion{"selectPionInSigRegion", false, "Select Pion candidates in signal region"}; + Configurable pidTPCMax{"pidTPCMax", 2.0f, "Maximum nSigma TPC"}; + Configurable pidTOFMax{"pidTPCMax", 2.0f, "Maximum nSigma TOF"}; + Configurable tofPIDThreshold{"tofPIDThreshold", 0.5f, "Minimum pT after which TOF PID is applicable"}; + } pionConfigs; + // 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"}; @@ -356,12 +364,21 @@ struct PhiStrangenessCorrelation { const bool applyK0sMassCut = (analysisMode == kDeltaYvsDeltaPhi) && k0sConfigs.selectK0sInSigRegion; const auto& [minMassK0s, maxMassK0s] = k0sConfigs.rangeMK0sSignal.value; - auto isK0sValid = [&](const auto& k0s) { return !applyK0sMassCut || k0s.inMassRegion(minMassK0s, maxMassK0s); }; - for (const auto& phiCand : phiCandidates) { + const bool applyPionNSigmaCut = (analysisMode == kDeltaYvsDeltaPhi) && pionConfigs.selectPionInSigRegion; + const float& pidTPCMax = pionConfigs.pidTPCMax; + const float& pidTOFMax = pionConfigs.pidTOFMax; + const float& tofPIDThreshold = pionConfigs.tofPIDThreshold; + + auto isPionValid = [&](const auto& pion) { + return !applyPionNSigmaCut || pion.inNSigmaRegion(pidTPCMax, tofPIDThreshold, pidTOFMax); + } + + for (const auto& phiCand : phiCandidates) + { float weightPhi = computeWeight(BoundEfficiencyMap(effMaps[Phi], multiplicity, phiCand.pt(), phiCand.y())); histos.fill(HIST("phi/h3PhiData"), multiplicity, phiCand.pt(), phiCand.m(), weightPhi); @@ -384,6 +401,9 @@ struct PhiStrangenessCorrelation { // Loop over all primary pion candidates for (const auto& pionTrack : pionTracks) { + if (!isPionValid(pionTrack)) + continue; + float weightPhiPion = computeWeight(BoundEfficiencyMap(effMaps[Phi], multiplicity, phiCand.pt(), phiCand.y()), BoundEfficiencyMap(effMaps[Pion], multiplicity, pionTrack.pt(), pionTrack.y())); fillPion(pionTrack, weightPhiPion); @@ -563,6 +583,15 @@ struct PhiStrangenessCorrelation { { const std::array, 2> phiMassRegions = {phiConfigs.rangeMPhiSignal, phiConfigs.rangeMPhiSideband}; + const bool applyPionNSigmaCut = (analysisMode == kDeltaYvsDeltaPhi) && pionConfigs.selectPionInSigRegion; + const float& pidTPCMax = pionConfigs.pidTPCMax; + const float& pidTOFMax = pionConfigs.pidTOFMax; + const float& tofPIDThreshold = pionConfigs.tofPIDThreshold; + + auto isPionValid = [&](const auto& pion) { + return !applyPionNSigmaCut || pion.inNSigmaRegion(pidTPCMax, tofPIDThreshold, pidTOFMax); + } + auto tuplePhiPion = std::make_tuple(phiCandidates, pionTracks); Pair pairPhiPion{binningOnVertexAndCent, cfgNoMixedEvents, -1, collisions, tuplePhiPion, &cache}; @@ -571,6 +600,9 @@ struct PhiStrangenessCorrelation { float multiplicity = c1.centFT0M(); for (const auto& [phiCand, piTrack] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(phiCands, piTracks))) { + if (!isPionValid(piTrack)) + continue; + auto processCorrelations = [&](auto fillPion) { float weightPhiPion = computeWeight(BoundEfficiencyMap(effMaps[Phi], multiplicity, phiCand.pt(), phiCand.y()), BoundEfficiencyMap(effMaps[Pion], multiplicity, piTrack.pt(), piTrack.y())); From 25d397216e0258b4c27848cd28f3d107cc88b7ab Mon Sep 17 00:00:00 2001 From: scannito Date: Tue, 17 Mar 2026 17:25:53 +0100 Subject: [PATCH 008/347] Fix --- PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx b/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx index 310d284a3b9..0106fe4837a 100644 --- a/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx +++ b/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx @@ -375,10 +375,9 @@ struct PhiStrangenessCorrelation { auto isPionValid = [&](const auto& pion) { return !applyPionNSigmaCut || pion.inNSigmaRegion(pidTPCMax, tofPIDThreshold, pidTOFMax); - } + }; - for (const auto& phiCand : phiCandidates) - { + for (const auto& phiCand : phiCandidates) { float weightPhi = computeWeight(BoundEfficiencyMap(effMaps[Phi], multiplicity, phiCand.pt(), phiCand.y())); histos.fill(HIST("phi/h3PhiData"), multiplicity, phiCand.pt(), phiCand.m(), weightPhi); @@ -590,7 +589,7 @@ struct PhiStrangenessCorrelation { auto isPionValid = [&](const auto& pion) { return !applyPionNSigmaCut || pion.inNSigmaRegion(pidTPCMax, tofPIDThreshold, pidTOFMax); - } + }; auto tuplePhiPion = std::make_tuple(phiCandidates, pionTracks); Pair pairPhiPion{binningOnVertexAndCent, cfgNoMixedEvents, -1, collisions, tuplePhiPion, &cache}; From de3c0cc993f93d0d0637f0f3d0c3c47e8cfe33fb Mon Sep 17 00:00:00 2001 From: scannito Date: Tue, 17 Mar 2026 19:59:33 +0100 Subject: [PATCH 009/347] FIx name --- PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx b/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx index 0106fe4837a..0f34d16e327 100644 --- a/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx +++ b/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx @@ -185,7 +185,7 @@ struct PhiStrangenessCorrelation { struct : ConfigurableGroup { Configurable selectPionInSigRegion{"selectPionInSigRegion", false, "Select Pion candidates in signal region"}; Configurable pidTPCMax{"pidTPCMax", 2.0f, "Maximum nSigma TPC"}; - Configurable pidTOFMax{"pidTPCMax", 2.0f, "Maximum nSigma TOF"}; + Configurable pidTOFMax{"pidTOFMax", 2.0f, "Maximum nSigma TOF"}; Configurable tofPIDThreshold{"tofPIDThreshold", 0.5f, "Minimum pT after which TOF PID is applicable"}; } pionConfigs; From c0e4e201d6f9fe2b21544fb84e40fdf74dee2cde Mon Sep 17 00:00:00 2001 From: scannito Date: Tue, 17 Mar 2026 20:07:08 +0100 Subject: [PATCH 010/347] Add check for efficiency after selection reworking --- .../Strangeness/phiStrangeCorrelation.cxx | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx b/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx index 0f34d16e327..d5d30fe0841 100644 --- a/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx +++ b/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx @@ -663,7 +663,21 @@ struct PhiStrangenessCorrelation { 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()); + const bool applyK0sMassCut = (analysisMode == kDeltaYvsDeltaPhi) && k0sConfigs.selectK0sInSigRegion; + const auto& [minMassK0s, maxMassK0s] = k0sConfigs.rangeMK0sSignal.value; + auto isK0sValid = [&](const auto& k0s) { + return !applyK0sMassCut || k0s.inMassRegion(minMassK0s, maxMassK0s); + }; + + const bool applyPionNSigmaCut = (analysisMode == kDeltaYvsDeltaPhi) && pionConfigs.selectPionInSigRegion; + const float& pidTPCMax = pionConfigs.pidTPCMax; + const float& pidTOFMax = pionConfigs.pidTOFMax; + const float& tofPIDThreshold = pionConfigs.tofPIDThreshold; + + auto isPionValid = [&](const auto& pion) { + return !applyPionNSigmaCut || pion.inNSigmaRegion(pidTPCMax, tofPIDThreshold, pidTOFMax); + }; + std::unordered_map> collsGrouped; collsGrouped.reserve(mcCollisions.size()); @@ -705,10 +719,16 @@ struct PhiStrangenessCorrelation { const auto pionTracksThisColl = pionTracks.sliceBy(preslices.pionTrackMcRecoPerCollision, collision.globalIndex()); for (const auto& k0s : k0sThisColl) { + if (!isK0sValid(k0s)) + continue; + histos.fill(HIST("k0s/h4K0SMCReco"), collision.posZ(), mcCollision.centFT0M(), k0s.pt(), k0s.y()); } for (const auto& pionTrack : pionTracksThisColl) { + if (!isPionValid(pionTrack)) + continue; + histos.fill(HIST("pi/h4PiMCReco"), collision.posZ(), mcCollision.centFT0M(), pionTrack.pt(), pionTrack.y()); } From 1beb1be0e716b5074759aaba815dae43f31b2e51 Mon Sep 17 00:00:00 2001 From: scannito Date: Tue, 17 Mar 2026 20:28:31 +0100 Subject: [PATCH 011/347] Fix semicolon --- PWGLF/DataModel/LFPhiStrangeCorrelationTables.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWGLF/DataModel/LFPhiStrangeCorrelationTables.h b/PWGLF/DataModel/LFPhiStrangeCorrelationTables.h index b0fcea7fa61..aca738fe6f2 100644 --- a/PWGLF/DataModel/LFPhiStrangeCorrelationTables.h +++ b/PWGLF/DataModel/LFPhiStrangeCorrelationTables.h @@ -157,7 +157,7 @@ DECLARE_SOA_DYNAMIC_COLUMN(InNSigmaRegion, inNSigmaRegion, } if (pt >= tofPIDThreshold && hasTOF && std::abs(nSigmaTOF) >= pidTOFMax) { return false; // TOF check failed - }; + } return true; }); } // namespace lf_selection_pion_track From 4d43e2d86824b5a58c170ab58ae8b4d937f97405 Mon Sep 17 00:00:00 2001 From: Francesca Ercolessi Date: Sat, 21 Feb 2026 19:23:10 +0100 Subject: [PATCH 012/347] [PWGLF] Strangeness in jets: add efficiency histograms in events with jet (#15085) --- PWGLF/Tasks/Strangeness/strangenessInJets.cxx | 89 +++++++++++++++++-- 1 file changed, 80 insertions(+), 9 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/strangenessInJets.cxx b/PWGLF/Tasks/Strangeness/strangenessInJets.cxx index 319051c6578..571fe9b7292 100644 --- a/PWGLF/Tasks/Strangeness/strangenessInJets.cxx +++ b/PWGLF/Tasks/Strangeness/strangenessInJets.cxx @@ -344,15 +344,6 @@ struct StrangenessInJets { registryMC.add("K0s_generated_fullevent", "K0s_generated_fullevent", HistType::kTH2F, {multAxis, ptAxis}); registryMC.add("Lambda_generated_fullevent", "Lambda_generated_fullevent", HistType::kTH2F, {multAxis, ptAxis}); registryMC.add("AntiLambda_generated_fullevent", "AntiLambda_generated_fullevent", HistType::kTH2F, {multAxis, ptAxis}); - registryMC.add("K0s_generated_recoevent", "K0s_generated_recoevent", HistType::kTH2F, {multAxis, ptAxis}); - registryMC.add("Lambda_generated_recoevent", "Lambda_generated_recoevent", HistType::kTH2F, {multAxis, ptAxis}); - registryMC.add("AntiLambda_generated_recoevent", "AntiLambda_generated_recoevent", HistType::kTH2F, {multAxis, ptAxis}); - registryMC.add("K0s_generated_recojet_jet", "K0s_generated_recojet_jet", HistType::kTH2F, {multAxis, ptAxis}); - registryMC.add("Lambda_generated_recojet_jet", "Lambda_generated_recojet_jet", HistType::kTH2F, {multAxis, ptAxis}); - registryMC.add("AntiLambda_generated_recojet_jet", "AntiLambda_generated_recojet_jet", HistType::kTH2F, {multAxis, ptAxis}); - registryMC.add("K0s_generated_recojet_ue", "K0s_generated_recojet_ue", HistType::kTH2F, {multAxis, ptAxis}); - registryMC.add("Lambda_generated_recojet_ue", "Lambda_generated_recojet_ue", HistType::kTH2F, {multAxis, ptAxis}); - registryMC.add("AntiLambda_generated_recojet_ue", "AntiLambda_generated_recojet_ue", HistType::kTH2F, {multAxis, ptAxis}); } if (enabledSignals.value[ParticleOfInterest::kCascades]) { registryMC.add("XiPos_generated_jet", "XiPos_generated_jet", HistType::kTH2F, {multAxis, ptAxis}); @@ -428,6 +419,21 @@ struct StrangenessInJets { registryMC.add("K0s_reconstructed_fullevent", "K0s_reconstructed_fullevent", HistType::kTH2F, {multAxis, ptAxis}); registryMC.add("Lambda_reconstructed_fullevent", "Lambda_reconstructed_fullevent", HistType::kTH2F, {multAxis, ptAxis}); registryMC.add("AntiLambda_reconstructed_fullevent", "AntiLambda_reconstructed_fullevent", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("K0s_reconstructed_eventwjet", "K0s_reconstructed_eventwjet", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("Lambda_reconstructed_eventwjet", "Lambda_reconstructed_eventwjet", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("AntiLambda_reconstructed_eventwjet", "AntiLambda_reconstructed_eventwjet", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("K0s_generated_eventwjet", "K0s_generated_eventwjet", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("Lambda_generated_eventwjet", "Lambda_generated_eventwjet", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("AntiLambda_generated_eventwjet", "AntiLambda_generated_eventwjet", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("K0s_generated_recoevent", "K0s_generated_recoevent", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("Lambda_generated_recoevent", "Lambda_generated_recoevent", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("AntiLambda_generated_recoevent", "AntiLambda_generated_recoevent", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("K0s_generated_recojet_jet", "K0s_generated_recojet_jet", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("Lambda_generated_recojet_jet", "Lambda_generated_recojet_jet", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("AntiLambda_generated_recojet_jet", "AntiLambda_generated_recojet_jet", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("K0s_generated_recojet_ue", "K0s_generated_recojet_ue", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("Lambda_generated_recojet_ue", "Lambda_generated_recojet_ue", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("AntiLambda_generated_recojet_ue", "AntiLambda_generated_recojet_ue", HistType::kTH2F, {multAxis, ptAxis}); } if (enabledSignals.value[ParticleOfInterest::kCascades]) { @@ -1863,6 +1869,71 @@ struct StrangenessInJets { registryMC.fill(HIST("number_of_events_mc_rec"), 4.5); registryMC.fill(HIST("number_of_events_vsmultiplicity_rec"), multiplicity); + // V0 particles + if (enabledSignals.value[ParticleOfInterest::kV0Particles]) { + for (const auto& v0 : v0sPerColl) { + const auto& pos = v0.posTrack_as(); + const auto& neg = v0.negTrack_as(); + + // Get MC particles + if (!pos.has_mcParticle() || !neg.has_mcParticle()) + continue; + auto posParticle = pos.mcParticle_as(); + auto negParticle = neg.mcParticle_as(); + if (!posParticle.has_mothers() || !negParticle.has_mothers()) + continue; + + // Get Mothers + auto motherPos = mcParticles.iteratorAt(posParticle.mothersIds()[0]); + auto motherNeg = mcParticles.iteratorAt(negParticle.mothersIds()[0]); + if (motherPos != motherNeg) + continue; + if (!motherPos.isPhysicalPrimary()) + continue; + + if (std::abs(motherPos.eta()) > 0.8) + continue; + + // K0s + if (passedK0ShortSelection(v0, pos, neg) && motherPos.pdgCode() == kK0Short) { + registryMC.fill(HIST("K0s_reconstructed_eventwjet"), multiplicity, v0.pt()); + } + // Lambda + if (passedLambdaSelection(v0, pos, neg) && motherPos.pdgCode() == kLambda0) { + registryMC.fill(HIST("Lambda_reconstructed_eventwjet"), multiplicity, v0.pt()); + } + // AntiLambda + if (passedAntiLambdaSelection(v0, pos, neg) && motherPos.pdgCode() == kLambda0Bar) { + registryMC.fill(HIST("AntiLambda_reconstructed_eventwjet"), multiplicity, v0.pt()); + } + } + } + + for (auto& particle : mcParticlesPerColl) { + + if (particle.isPhysicalPrimary() && std::abs(particle.eta()) <= 0.8) { + switch (particle.pdgCode()) { + case kK0Short: + if (enabledSignals.value[ParticleOfInterest::kV0Particles]) { + registryMC.fill(HIST("K0s_generated_eventwjet"), multiplicity, particle.pt()); + } + break; + case kLambda0: + if (enabledSignals.value[ParticleOfInterest::kV0Particles]) { + registryMC.fill(HIST("Lambda_generated_eventwjet"), multiplicity, particle.pt()); + } + break; + case kLambda0Bar: + if (enabledSignals.value[ParticleOfInterest::kV0Particles]) { + registryMC.fill(HIST("AntiLambda_generated_eventwjet"), multiplicity, particle.pt()); + } + break; + default: + break; + } + } + } + // Loop over selected jets for (int i = 0; i < static_cast(selectedJet.size()); i++) { From 34d24433b2f2aa532337872ec99549a331c2950e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?BiaoZhang=20=28=E5=BC=A0=E5=BD=AA=29?= <52267892+zhangbiao-phy@users.noreply.github.com> Date: Sat, 21 Feb 2026 21:12:45 +0100 Subject: [PATCH 013/347] [PWGHF] Fix typo and missing filter for anti particle in Cd task (#15090) --- PWGHF/D2H/Tasks/taskCd.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/PWGHF/D2H/Tasks/taskCd.cxx b/PWGHF/D2H/Tasks/taskCd.cxx index 1aa5fcb35c1..665e640a87b 100644 --- a/PWGHF/D2H/Tasks/taskCd.cxx +++ b/PWGHF/D2H/Tasks/taskCd.cxx @@ -136,7 +136,7 @@ struct HfTaskCd { using CdCandidates = soa::Filtered>; using HFTracks = soa::Join; - Filter filterSelectCandidates = aod::hf_sel_candidate_cd::isSelCdToDeKPi >= selectionFlagCd; + Filter filterSelectCandidates = aod::hf_sel_candidate_cd::isSelCdToDeKPi >= selectionFlagCd || aod::hf_sel_candidate_cd::isSelCdToPiKDe >= selectionFlagCd; Preslice candCdPerCollision = aod::hf_cand::collisionId; ConfigurableAxis thnConfigAxisPt{"thnConfigAxisPt", {72, 0, 36}, ""}; @@ -213,8 +213,8 @@ struct HfTaskCd { registry.add("Data/hNsigmaTPCDeVsP", "deuteron;#it{p} (GeV/#it{c}); n#sigma^{TPC}_{d}", {HistType::kTH2F, {{200, -10.f, 10.f}, {200, -6.f, 6.f}}}); registry.add("Data/hNsigmaTOFDeVsP", "deuteron;#it{p} (GeV/#it{c}); n#sigma^{TOF}_{d}", {HistType::kTH2F, {{200, -10.f, 10.f}, {200, -6.f, 6.f}}}); registry.add("Data/hNsigmaITSDeVsP", "deuteron;#it{p} (GeV/#it{c}); n#sigma^{ITS}_{d}", {HistType::kTH2F, {{200, -10.f, 10.f}, {200, -6.f, 6.f}}}); - registry.add("Data/hTPCSignalDeVsP", "deuteron;#it{p} (GeV/#it{c}); n#sigma^{ITS}_{d}", {HistType::kTH2F, {{200, -10.f, 10.f}, {2000, 0, 2000}}}); - registry.add("Data/hITSSignalDeVsP", "deuteron;#it{p} (GeV/#it{c}); n#sigma^{ITS}_{d}", {HistType::kTH2F, {{200, -10.f, 10.f}, {20, 0, 20}}}); + registry.add("Data/hTPCSignalDeVsP", "deuteron;#it{p} (GeV/#it{c}); TPC signals", {HistType::kTH2F, {{200, -10.f, 10.f}, {2000, 0, 2000}}}); + registry.add("Data/hITSSignalDeVsP", "deuteron;#it{p} (GeV/#it{c}); ITS signals", {HistType::kTH2F, {{200, -10.f, 10.f}, {20, 0, 20}}}); registry.add("Data/hNsigmaTPCPiVsP", "Pion;#it{p} (GeV/#it{c});n#sigma^{TPC}_{pi};", {HistType::kTH2F, {{200, -10.f, 10.f}, {200, -6.f, 6.f}}}); registry.add("Data/hNsigmaTOFPiVsP", "Pion;#it{p} (GeV/#it{c});n#sigma^{TOF}_{pi};", {HistType::kTH2F, {{200, -10.f, 10.f}, {200, -6.f, 6.f}}}); registry.add("Data/hNsigmaTPCKaVsP", "Kaon;#it{p} (GeV/#it{c}); n#sigma^{TPC}_{Kaon}", {HistType::kTH2F, {{200, -10.f, 10.f}, {200, -6.f, 6.f}}}); From e39c95d0d99bfd38bd52bb2f6e34746390bea9cc Mon Sep 17 00:00:00 2001 From: Subhadeep Mandal <147193283+5ub-Man@users.noreply.github.com> Date: Sun, 22 Feb 2026 02:54:04 +0530 Subject: [PATCH 014/347] [PWGLF] Added process function to cross check MC (#15092) --- PWGLF/Tasks/Resonances/kstar892LightIon.cxx | 274 +++++++++++++++++++- 1 file changed, 272 insertions(+), 2 deletions(-) diff --git a/PWGLF/Tasks/Resonances/kstar892LightIon.cxx b/PWGLF/Tasks/Resonances/kstar892LightIon.cxx index f6ac93d840f..238ff319118 100644 --- a/PWGLF/Tasks/Resonances/kstar892LightIon.cxx +++ b/PWGLF/Tasks/Resonances/kstar892LightIon.cxx @@ -32,6 +32,7 @@ #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" +#include "Framework/O2DatabasePDGPlugin.h" #include "Framework/StepTHn.h" #include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/Track.h" @@ -153,6 +154,11 @@ struct Kstar892LightIon { // Fixed variables float lowPtCutPID = 0.5; + + Configurable selHasFT0{"selHasFT0", true, "Has FT0?"}; + Configurable isZvtxPosSelMC{"isZvtxPosSelMC", true, "Zvtx position selection for MC events?"}; + Configurable selTVXMC{"selTVXMC", true, "apply TVX selection in MC?"}; + Configurable selINELgt0{"selINELgt0", true, "Select INEL > 0?"}; } selectionConfig; Configurable calcLikeSign{"calcLikeSign", true, "Calculate Like Sign"}; @@ -168,6 +174,12 @@ struct Kstar892LightIon { Configurable reflectionType{"reflectionType", 0, "Reflection: 0=Rho, 1=Omega, 2=Phi, 3=Kstar (for processRecReflection)"}; + Configurable nchAcceptance{"nchAcceptance", 0.5, "Eta window to measure Nch MC for Nch vs Cent distribution"}; + + Configurable nBinsNch{"nBinsNch", 400, "N bins Nch (|eta|<0.8)"}; + Configurable minNch{"minNch", 0, "Min Nch (|eta|<0.8)"}; + Configurable maxNch{"maxNch", 400, "Max Nch (|eta|<0.8)"}; + // Configurable for histograms ConfigurableAxis binsCentPlot{"binsCentPlot", {110, 0.0, 110}, "Centrality axis"}; ConfigurableAxis axisdEdx{"axisdEdx", {1, 0.0f, 200.0f}, "dE/dx (a.u.)"}; @@ -369,6 +381,39 @@ struct Kstar892LightIon { if (doprocessRecReflection) { hMC.add("Reflections/hReflection", "Refelction template of Rho", kTH3F, {ptAxis, centralityAxis, invmassAxis}); } + + if (doprocessMCCheck) { + hMC.add("MCCheck/CentVsFoundFT0", "Found(=1.5) NOT Found(=0.5);;Status;", kTH2F, {{{centralityAxis}, {2, 0, 2}}}); + hMC.add("MCCheck/zPosMC", "Generated Events With at least One Rec. Collision + Sel. criteria;;Entries;", kTH1F, {vertexZAxis}); + hMC.add("MCCheck/zPos", "With Event Selection;;Entries;", kTH1F, {vertexZAxis}); + hMC.add("MCCheck/Cent", ";;Entries", kTH1F, {centralityAxis}); + hMC.add("MCCheck/NchVsCent", "Measured Nch v.s. Centrality (At least Once Rec. Coll. + Sel. criteria);;Nch", kTH2F, {{centralityAxis, {nBinsNch, minNch, maxNch}}}); + + // MC events passing the TVX requirement + hMC.add("MCCheck/NchMCcentVsTVX", ";Passed(=1.5) NOT Passed(=0.5);", kTH2F, {{{nBinsNch, minNch, maxNch}, {2, 0, 2}}}); + + hMC.add("MCCheck/NumberOfRecoCollisions", "Number of times Gen. Coll.are reconstructed;N;Entries", kTH1F, {{10, -0.5, 9.5}}); + + // Needed for the Gen. Nch to Centrality conversion + hMC.add("MCCheck/NchMCVsCent", "Generated Nch v.s. Centrality (At least Once Rec. Coll. + Sel. criteria);;Gen. Nch MC (|#eta|<0.8)", kTH2F, {{centralityAxis, {nBinsNch, minNch, maxNch}}}); + + // Needed to measure Event Loss + hMC.add("MCCheck/NchMC_WithRecoEvt", "Generated Nch of Evts With at least one Rec. Coll. + Sel. criteria;Gen. Nch MC (|#eta|<0.8);Entries", kTH1F, {{nBinsNch, minNch, maxNch}}); + hMC.add("MCCheck/NchMC_AllGen", "Generated Nch of All Gen. Evts.;Gen. Nch;Entries", kTH1F, {{nBinsNch, minNch, maxNch}}); + + // Needed to measure Event Splitting + hMC.add("MCCheck/Centrality_WRecoEvt", "Generated Events With at least One Rec. Collision And NO Sel. criteria;;Entries", kTH1F, {centralityAxis}); + hMC.add("MCCheck/Centrality_WRecoEvtWSelCri", "Generated Events With at least One Rec. Collision + Sel. criteria;;Entries", kTH1F, {centralityAxis}); + hMC.add("MCCheck/Centrality_AllRecoEvt", "Generated Events Irrespective of the number of times it was reconstructed + Evt. Selections;;Entries", kTH1F, {centralityAxis}); + + hMC.add("MCCheck/PtKstarVsCentMC_WithRecoEvt", "Generated Events With at least One Rec. Collision;;;", kTH2F, {ptAxis, centralityAxis}); + + // Needed to calculate the numerator of the Signal Loss correction + hMC.add("MCCheck/PtKstarVsNchMC_WithRecoEvt", "Generated Events With at least One Rec. Collision;;Gen. Nch (|#eta|<0.8);", kTH2F, {{ptAxis, {nBinsNch, minNch, maxNch}}}); + + // Needed to calculate the denominator of the Signal Loss correction + hMC.add("MCCheck/PtKstarVsNchMC_AllGen", "All Generated Events;;Gen. Nch (|#eta|<0.8);", kTH2F, {{ptAxis, {nBinsNch, minNch, maxNch}}}); + } } double massPi = o2::constants::physics::MassPiPlus; @@ -1551,7 +1596,8 @@ struct Kstar892LightIon { hMC.fill(HIST("ImpactCorr/hImpactParameterGen"), impactPar); bool isSelectedEvent = false; - auto centrality = -999.; + centrality = -1.f; + for (const auto& RecCollision : recCollisions) { if (!RecCollision.has_mcCollision()) continue; @@ -1602,7 +1648,7 @@ struct Kstar892LightIon { hMC.fill(HIST("LossMult/hMultMC"), multMC); bool isSelectedEvent = false; - float centrality = -1.f; + centrality = -1.f; for (auto const& collision : recCollisions) { @@ -1949,6 +1995,230 @@ struct Kstar892LightIon { } } PROCESS_SWITCH(Kstar892LightIon, processRecReflection, "Process particle reflection", false); + + Service pdg; + + void processMCCheck(aod::McCollisions::iterator const& mccollision, soa::SmallGroups const& collisions, aod::McParticles const& mcParticles, TrackCandidatesMC const&) + { + + //--------------------------- + // Only INEL > 0 generated collisions + // By counting number of primary charged particles in |eta| < 1 + //--------------------------- + int nChMC{0}; + int nChMCEta08{0}; + int nChFT0A{0}; + int nChFT0C{0}; + static constexpr float MinCharge{3.f}; + static constexpr float MinFT0A{3.5f}; + static constexpr float MaxFT0A{4.9f}; + static constexpr float MinFT0C{-3.3f}; + static constexpr float MaxFT0C{-2.1f}; + static constexpr float One{1.0f}; + static constexpr int ZeroInt{0}; + + for (const auto& particle : mcParticles) { + + auto charge{0.}; + // Get the MC particle + const auto* pdgParticle = pdg->GetParticle(particle.pdgCode()); + if (pdgParticle != nullptr) { + charge = pdgParticle->Charge(); + } else { + continue; + } + + // Is it a charged particle? + if (std::abs(charge) < MinCharge) + continue; + + // Is it a primary particle? + if (!particle.isPhysicalPrimary()) + continue; + + const float eta{particle.eta()}; + + // TVX requirement + if (eta > MinFT0A && eta < MaxFT0A) { + nChFT0A++; + } + + if (eta > MinFT0C && eta < MaxFT0C) { + nChFT0C++; + } + + if (std::abs(eta) < nchAcceptance) { + nChMCEta08++; + } + + // INEL > 0 + if (std::abs(eta) > One) + continue; + + nChMC++; + } + + //--------------------------- + // Only events with at least one charged particle in the FT0A and FT0C acceptances + //--------------------------- + if (selectionConfig.selTVXMC) { + if (!(nChFT0A > ZeroInt && nChFT0C > ZeroInt)) { + hMC.fill(HIST("MCCheck/NchMCcentVsTVX"), nChMC, 0.5); + return; + } + hMC.fill(HIST("MCCheck/NchMCcentVsTVX"), nChMC, 1.5); + } + + //--------------------------- + // Only MC events with |Vtx Z| < 10 cm + //--------------------------- + if (selectionConfig.isZvtxPosSelMC && (std::fabs(mccollision.posZ()) > selectionConfig.cfgVrtxZCut)) { + return; + } + + //--------------------------- + // Only INEL > 0 generated events + //--------------------------- + if (selectionConfig.selINELgt0) { + if (!(nChMC > ZeroInt)) { + return; + } + } + + const auto& nRecColls{collisions.size()}; + hMC.fill(HIST("MCCheck/NumberOfRecoCollisions"), nRecColls); + + //--------------------------- + // Only Generated evets with at least one reconstrued collision + //--------------------------- + if (nRecColls > ZeroInt) { + + // Finds the collisions with the largest number of contributors + // in case nRecColls is larger than One + int biggestNContribs{-1}; + int bestCollisionIndex{-1}; + centrality = -1.f; + for (const auto& collision : collisions) { + + if (selectCentEstimator == kFT0M) { + centrality = collision.centFT0M(); + } else if (selectCentEstimator == kFT0A) { + centrality = collision.centFT0A(); + } else if (selectCentEstimator == kFT0C) { + centrality = collision.centFT0C(); + } else if (selectCentEstimator == kFV0A) { + centrality = collision.centFV0A(); + } else { + centrality = collision.centFT0M(); // default + } + + if (selectionConfig.selHasFT0 && !collision.has_foundFT0()) { + continue; + } + + if (biggestNContribs < collision.numContrib()) { + biggestNContribs = collision.numContrib(); + bestCollisionIndex = collision.globalIndex(); + } + + // Needed to calculate denominator of the Event Splitting correction + if (selectionEvent(collision, false)) { + hMC.fill(HIST("MCCheck/Centrality_AllRecoEvt"), centrality); + } + } + + //--------------------------- + // Loop over the reconstructed collisions + // Only that one with the largest number of contributors is considered + //--------------------------- + centrality = -1.f; + for (const auto& collision : collisions) { + + if (selectCentEstimator == kFT0M) { + centrality = collision.centFT0M(); + } else if (selectCentEstimator == kFT0A) { + centrality = collision.centFT0A(); + } else if (selectCentEstimator == kFT0C) { + centrality = collision.centFT0C(); + } else if (selectCentEstimator == kFV0A) { + centrality = collision.centFV0A(); + } else { + centrality = collision.centFT0M(); // default + } + + //--------------------------- + // Reject collisions if has_foundFT0() returns false + //--------------------------- + if (selectionConfig.selHasFT0 && !collision.has_foundFT0()) { + hMC.fill(HIST("MCCheck/CentVsFoundFT0"), centrality, 0.5); + continue; + } + hMC.fill(HIST("MCCheck/CentVsFoundFT0"), centrality, 1.5); + + //--------------------------- + // Pick the collisions with the largest number of contributors + //--------------------------- + if (bestCollisionIndex != collision.globalIndex()) { + continue; + } + + //--------------------------- + // Needed to construct the correlation between MC Nch v.s. centrality + //--------------------------- + + hMC.fill(HIST("MCCheck/Centrality_WRecoEvt"), centrality); + hMC.fill(HIST("MCCheck/zPosMC"), mccollision.posZ()); + + //--------------------------- + // Event selection + // for reconstructed collisions + //--------------------------- + if (!selectionEvent(collision, false)) { + continue; + } + + hMC.fill(HIST("MCCheck/Centrality_WRecoEvtWSelCri"), centrality); + hMC.fill(HIST("MCCheck/NchMCVsCent"), centrality, nChMCEta08); + hMC.fill(HIST("MCCheck/NchMC_WithRecoEvt"), nChMCEta08); // Numerator of event loss correction + hMC.fill(HIST("MCCheck/zPos"), collision.posZ()); + hMC.fill(HIST("MCCheck/Cent"), centrality); + + //--------------------------- + // All Generated events with at least one associated reconstructed collision + // The Generated events are not subjected to any selection criteria + // However, the associated reconstructed collisions pass the selection criteria + // This histograms are used for the denominator of the tracking efficiency + //--------------------------- + for (const auto& mcPart : mcParticles) { + if ((mcPart.y() < selectionConfig.motherRapidityMin || mcPart.y() > selectionConfig.motherRapidityMax) || std::abs(mcPart.pdgCode()) != o2::constants::physics::kK0Star892) + continue; + + hMC.fill(HIST("MCCheck/PtKstarVsCentMC_WithRecoEvt"), mcPart.pt(), centrality); + hMC.fill(HIST("MCCheck/PtKstarVsNchMC_WithRecoEvt"), mcPart.pt(), nChMCEta08); // Numerator of signal loss + } // Loop over generated particles per generated collision + // hMC.fill(HIST("MCCheck/NchVsCent"), centrality, nCh); + } // Loop over Reco. Collisions: Only the collisions with the largest number of contributors + } // If condition: Only simulated evets with at least one reconstrued collision + + //--------------------------- + // All Generated events irrespective of whether there is an associated reconstructed collision + // Consequently, the centrality being a reconstructed quantity, might not always be available + // Therefore it is expressed as a function of the generated pT and the generated Nch in ∣eta∣ < 0.8 + // This is used for the denominator of the signal loss correction + //--------------------------- + for (const auto& mcPart : mcParticles) { + if ((mcPart.y() < selectionConfig.motherRapidityMin || mcPart.y() > selectionConfig.motherRapidityMax) || std::abs(mcPart.pdgCode()) != o2::constants::physics::kK0Star892) + continue; + + hMC.fill(HIST("MCCheck/PtKstarVsNchMC_AllGen"), mcPart.pt(), nChMCEta08); + } // Loop over Generated Particles + + //--------------------------- + // This is used for the denominator of the event loss correction + //--------------------------- + hMC.fill(HIST("MCCheck/NchMC_AllGen"), nChMCEta08); + } + PROCESS_SWITCH(Kstar892LightIon, processMCCheck, "Cross-check MC analysis", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) From cf0ba72176049f2b33a3cd7baf2796c750594524 Mon Sep 17 00:00:00 2001 From: ikantak <149821212+ikantak@users.noreply.github.com> Date: Sun, 22 Feb 2026 07:50:42 +0100 Subject: [PATCH 015/347] [PWGEM] Add and update ML-based photon cuts (#15076) --- PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h | 7 +- PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h | 7 +- PWGEM/PhotonMeson/Core/V0PhotonCandidate.h | 62 ++++-- PWGEM/PhotonMeson/Core/V0PhotonCut.cxx | 12 +- PWGEM/PhotonMeson/Core/V0PhotonCut.h | 49 ++--- PWGEM/PhotonMeson/DataModel/gammaTables.h | 11 +- .../TableProducer/photonconversionbuilder.cxx | 109 +++++++--- PWGEM/PhotonMeson/Tasks/CMakeLists.txt | 10 + .../Tasks/Pi0EtaToGammaGammaMCPCMPCMML.cxx | 37 ++++ .../Tasks/Pi0EtaToGammaGammaPCMPCMML.cxx | 36 ++++ PWGEM/PhotonMeson/Tasks/pcmQC.cxx | 176 +++++++++++++++- PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx | 188 ++++++++++++++++-- 12 files changed, 592 insertions(+), 112 deletions(-) create mode 100644 PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaMCPCMPCMML.cxx create mode 100644 PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaPCMPCMML.cxx diff --git a/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h b/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h index 8cc1efd73dd..83e934bbdd0 100644 --- a/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h +++ b/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h @@ -147,7 +147,6 @@ struct Pi0EtaToGammaGamma { o2::framework::Configurable cfg_load_ml_models_from_ccdb{"cfg_load_ml_models_from_ccdb", true, "flag to load ML models from CCDB"}; o2::framework::Configurable cfg_timestamp_ccdb{"cfg_timestamp_ccdb", -1, "timestamp for CCDB"}; o2::framework::Configurable cfg_nclasses_ml{"cfg_nclasses_ml", static_cast(o2::analysis::em_cuts_ml::NCutScores), "number of classes for ML"}; - o2::framework::Configurable cfg_cent_type_ml{"cfg_cent_type_ml", "CentFT0C", "centrality type for 2D ML application: CentFT0C, CentFT0M, or CentFT0A"}; o2::framework::Configurable> cfg_cut_dir_ml{"cfg_cut_dir_ml", std::vector{o2::analysis::em_cuts_ml::vecCutDir}, "cut direction for ML"}; o2::framework::Configurable> cfg_input_feature_names{"cfg_input_feature_names", std::vector{"feature1", "feature2"}, "input feature names for ML models"}; o2::framework::Configurable> cfg_model_paths_ccdb{"cfg_model_paths_ccdb", std::vector{"path_ccdb/BDT_PCM/"}, "CCDB paths for ML models"}; @@ -508,7 +507,9 @@ struct Pi0EtaToGammaGamma { fV0PhotonCut.SetNClassesMl(pcmcuts.cfg_nclasses_ml); fV0PhotonCut.SetMlTimestampCCDB(pcmcuts.cfg_timestamp_ccdb); fV0PhotonCut.SetCcdbUrl(ccdburl); - fV0PhotonCut.SetCentralityTypeMl(pcmcuts.cfg_cent_type_ml); + CentType mCentralityTypeMlEnum; + mCentralityTypeMlEnum = static_cast(cfgCentEstimator.value); + fV0PhotonCut.SetCentralityTypeMl(mCentralityTypeMlEnum); fV0PhotonCut.SetCutDirMl(pcmcuts.cfg_cut_dir_ml); fV0PhotonCut.SetMlModelPathsCCDB(pcmcuts.cfg_model_paths_ccdb); fV0PhotonCut.SetMlOnnxFileNames(pcmcuts.cfg_onnx_file_names); @@ -702,7 +703,6 @@ struct Pi0EtaToGammaGamma { { for (const auto& collision : collisions) { initCCDB(collision); - fV0PhotonCut.SetCentrality(collision.centFT0A(), collision.centFT0C(), collision.centFT0M()); int ndiphoton = 0; if ((pairtype == o2::aod::pwgem::photonmeson::photonpair::PairType::kPHOSPHOS || pairtype == o2::aod::pwgem::photonmeson::photonpair::PairType::kPCMPHOS) && !collision.alias_bit(triggerAliases::kTVXinPHOS)) { continue; @@ -718,6 +718,7 @@ struct Pi0EtaToGammaGamma { } const float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; + fV0PhotonCut.SetCentrality(centralities[cfgCentEstimator]); if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { continue; } diff --git a/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h b/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h index 48dacaddee8..729f76ce5de 100644 --- a/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h +++ b/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h @@ -136,7 +136,6 @@ struct Pi0EtaToGammaGammaMC { o2::framework::Configurable cfg_load_ml_models_from_ccdb{"cfg_load_ml_models_from_ccdb", true, "flag to load ML models from CCDB"}; o2::framework::Configurable cfg_timestamp_ccdb{"cfg_timestamp_ccdb", -1, "timestamp for CCDB"}; o2::framework::Configurable cfg_nclasses_ml{"cfg_nclasses_ml", static_cast(o2::analysis::em_cuts_ml::NCutScores), "number of classes for ML"}; - o2::framework::Configurable cfg_cent_type_ml{"cfg_cent_type_ml", "CentFT0C", "centrality type for 2D ML application: CentFT0C, CentFT0M, or CentFT0A"}; o2::framework::Configurable> cfg_cut_dir_ml{"cfg_cut_dir_ml", std::vector{o2::analysis::em_cuts_ml::vecCutDir}, "cut direction for ML"}; o2::framework::Configurable> cfg_input_feature_names{"cfg_input_feature_names", std::vector{"feature1", "feature2"}, "input feature names for ML models"}; o2::framework::Configurable> cfg_model_paths_ccdb{"cfg_model_paths_ccdb", std::vector{"path_ccdb/BDT_PCM/"}, "CCDB paths for ML models"}; @@ -348,7 +347,9 @@ struct Pi0EtaToGammaGammaMC { fV0PhotonCut.SetNClassesMl(pcmcuts.cfg_nclasses_ml); fV0PhotonCut.SetMlTimestampCCDB(pcmcuts.cfg_timestamp_ccdb); fV0PhotonCut.SetCcdbUrl(ccdburl); - fV0PhotonCut.SetCentralityTypeMl(pcmcuts.cfg_cent_type_ml); + CentType mCentralityTypeMlEnum; + mCentralityTypeMlEnum = static_cast(cfgCentEstimator.value); + fV0PhotonCut.SetCentralityTypeMl(mCentralityTypeMlEnum); fV0PhotonCut.SetCutDirMl(pcmcuts.cfg_cut_dir_ml); fV0PhotonCut.SetMlModelPathsCCDB(pcmcuts.cfg_model_paths_ccdb); fV0PhotonCut.SetMlOnnxFileNames(pcmcuts.cfg_onnx_file_names); @@ -560,7 +561,6 @@ struct Pi0EtaToGammaGammaMC { { for (auto& collision : collisions) { initCCDB(collision); - fV0PhotonCut.SetCentrality(collision.centFT0A(), collision.centFT0C(), collision.centFT0M()); if ((pairtype == o2::aod::pwgem::photonmeson::photonpair::PairType::kPHOSPHOS || pairtype == o2::aod::pwgem::photonmeson::photonpair::PairType::kPCMPHOS) && !collision.alias_bit(triggerAliases::kTVXinPHOS)) { continue; } @@ -575,6 +575,7 @@ struct Pi0EtaToGammaGammaMC { } const float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; + fV0PhotonCut.SetCentrality(centralities[cfgCentEstimator]); if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { continue; } diff --git a/PWGEM/PhotonMeson/Core/V0PhotonCandidate.h b/PWGEM/PhotonMeson/Core/V0PhotonCandidate.h index 2df1c5e08a1..d81c803ca2c 100644 --- a/PWGEM/PhotonMeson/Core/V0PhotonCandidate.h +++ b/PWGEM/PhotonMeson/Core/V0PhotonCandidate.h @@ -23,11 +23,19 @@ #include +enum CentType : uint8_t { + CentFT0M = 0, + CentFT0A = 1, + CentFT0C = 2 +}; + struct V0PhotonCandidate { public: - // Constructor for photonconversionbuilder - V0PhotonCandidate(const KFParticle& v0, const KFParticle& pos, const KFParticle& ele, const auto& collision, float cospa, float d_bz) : cospa(cospa) + // Empty Constructor + V0PhotonCandidate() = default; + // Set method for photonconversionbuilder + void setPhotonCandidate(const KFParticle& v0, const KFParticle& pos, const KFParticle& ele, const auto& collision, float cospa, float psipair, float phiv, CentType centType) { px = v0.GetPx(); py = v0.GetPy(); @@ -57,18 +65,27 @@ struct V0PhotonCandidate { alpha = v0_alpha(posPx, posPy, posPz, elePx, elePy, elePz); qt = v0_qt(posPx, posPy, posPz, elePx, elePy, elePz); - int posSign = (pos.GetQ() > 0) - (pos.GetQ() < 0); - int eleSign = (ele.GetQ() > 0) - (ele.GetQ() < 0); - phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(posPx, posPy, posPz, elePx, elePy, elePz, posSign, eleSign, d_bz); - psipair = o2::aod::pwgem::dilepton::utils::pairutil::getPsiPair(posPx, posPy, posPz, elePx, elePy, elePz); - - centFT0M = collision.centFT0M(); - centFT0C = collision.centFT0C(); - centFT0A = collision.centFT0A(); + + this->cospa = cospa; + this->psipair = psipair; + this->phiv = phiv; + this->centType = centType; + + switch (centType) { + case CentType::CentFT0A: + cent = collision.centFT0A(); + break; + case CentType::CentFT0C: + cent = collision.centFT0C(); + break; + case CentType::CentFT0M: + cent = collision.centFT0M(); + break; + } } - // Constructor for V0PhotonCut - V0PhotonCandidate(const auto& v0, const auto& pos, const auto& ele, float centFT0A, float centFT0C, float centFT0M, float d_bz) : centFT0A(centFT0A), centFT0C(centFT0C), centFT0M(centFT0M) + // Set-Method for V0PhotonCut + void setPhoton(const auto& v0, const auto& pos, const auto& ele, float cent, CentType centType) { px = v0.px(); py = v0.py(); @@ -93,9 +110,14 @@ struct V0PhotonCandidate { cospa = v0.cospa(); alpha = v0.alpha(); qt = v0.qtarm(); - - phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(posPx, posPy, posPz, elePx, elePy, elePz, pos.sign(), ele.sign(), d_bz); - psipair = o2::aod::pwgem::dilepton::utils::pairutil::getPsiPair(posPx, posPy, posPz, elePx, elePy, elePz); + psipair = 999.f; // default if V0PhotonPhiVPsi table is not included + phiv = 999.f; // default if V0PhotonPhiVPsi table is not included + if constexpr (requires { v0.psipair(); v0.phiv(); }) { + psipair = v0.psipair(); + phiv = v0.phiv(); + } + this->cent = cent; + this->centType = centType; } // Getter functions @@ -119,10 +141,9 @@ struct V0PhotonCandidate { float getElePx() const { return elePx; } float getElePy() const { return elePy; } float getElePz() const { return elePz; } - float getCentFT0M() const { return centFT0M; } - float getCentFT0C() const { return centFT0C; } - float getCentFT0A() const { return centFT0A; } + float getCent() const { return cent; } float getPCA() const { return pca; } + CentType getCentType() const { return centType; } private: float px; @@ -145,10 +166,9 @@ struct V0PhotonCandidate { float psipair; float cospa; float chi2ndf; - float centFT0A; - float centFT0C; - float centFT0M; + float cent; float pca; + CentType centType; }; #endif // PWGEM_PHOTONMESON_CORE_V0PHOTONCANDIDATE_H_ diff --git a/PWGEM/PhotonMeson/Core/V0PhotonCut.cxx b/PWGEM/PhotonMeson/Core/V0PhotonCut.cxx index 9c45ed9156c..5abc97c5d1c 100644 --- a/PWGEM/PhotonMeson/Core/V0PhotonCut.cxx +++ b/PWGEM/PhotonMeson/Core/V0PhotonCut.cxx @@ -306,20 +306,20 @@ void V0PhotonCut::SetCutsMl(const std::vector& cuts) void V0PhotonCut::SetNClassesMl(int nClasses) { mNClassesMl = nClasses; + mOutputML.reserve(mNClassesMl); LOG(info) << "V0 Photon Cut, set number of classes ML: " << mNClassesMl; } void V0PhotonCut::SetNamesInputFeatures(const std::vector& featureNames) { mNamesInputFeatures = featureNames; + mMlInputFeatures.reserve(mNamesInputFeatures.size()); LOG(info) << "V0 Photon Cut, set ML input feature names with size:" << mNamesInputFeatures.size(); } -void V0PhotonCut::SetCentrality(float centFT0A, float centFT0C, float centFT0M) +void V0PhotonCut::SetCentrality(float cent) { - mCentFT0A = centFT0A; - mCentFT0C = centFT0C; - mCentFT0M = centFT0M; + mCent = cent; } void V0PhotonCut::SetD_Bz(float d_bz) { @@ -332,10 +332,10 @@ void V0PhotonCut::SetCutDirMl(const std::vector& cutDirMl) LOG(info) << "V0 Photon Cut, set ML cut directions with size:" << mCutDirMl.size(); } -void V0PhotonCut::SetCentralityTypeMl(const std::string& centType) +void V0PhotonCut::SetCentralityTypeMl(CentType centType) { mCentralityTypeMl = centType; - LOG(info) << "V0 Photon Cut, set centrality type ML: " << mCentralityTypeMl; + LOG(info) << "V0 Photon Cut, set centrality type ML: " << mCentralityTypeMl << " (0: CentFT0M, 1: CentFT0A, 2: CentFT0C)"; } void V0PhotonCut::SetLabelsBinsMl(const std::vector& labelsBins) diff --git a/PWGEM/PhotonMeson/Core/V0PhotonCut.h b/PWGEM/PhotonMeson/Core/V0PhotonCut.h index 7f0d18d6d8e..7f5ecaecb64 100644 --- a/PWGEM/PhotonMeson/Core/V0PhotonCut.h +++ b/PWGEM/PhotonMeson/Core/V0PhotonCut.h @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -145,7 +146,7 @@ static const std::vector labelsCent = { "Cent bin 10"}; // column labels -static const std::vector labelsCutScore = {"score primary photons", "score background"}; +static const std::vector labelsCutScore = {"score background", "score primary photons"}; } // namespace em_cuts_ml } // namespace o2::analysis @@ -584,30 +585,22 @@ class V0PhotonCut : public TNamed } } if (mApplyMlCuts) { - if (!mEmMlResponse) { + if (mEmMlResponse == nullptr) { LOG(error) << "EM ML Response is not initialized!"; return false; } - bool mIsSelectedMl = false; - std::vector mOutputML; - V0PhotonCandidate v0photoncandidate(v0, pos, ele, mCentFT0A, mCentFT0C, mCentFT0M, mD_Bz); - std::vector mlInputFeatures = mEmMlResponse->getInputFeatures(v0photoncandidate, pos, ele); + mIsSelectedMl = false; + mV0PhotonForMl.setPhoton(v0, pos, ele, mCent, mCentralityTypeMl); + mMlInputFeatures = mEmMlResponse->getInputFeatures(mV0PhotonForMl, pos, ele); if (mUse2DBinning) { - if (mCentralityTypeMl == "CentFT0C") { - mIsSelectedMl = mEmMlResponse->isSelectedMl(mlInputFeatures, v0photoncandidate.getPt(), v0photoncandidate.getCentFT0C(), mOutputML); - } else if (mCentralityTypeMl == "CentFT0A") { - mIsSelectedMl = mEmMlResponse->isSelectedMl(mlInputFeatures, v0photoncandidate.getPt(), v0photoncandidate.getCentFT0A(), mOutputML); - } else if (mCentralityTypeMl == "CentFT0M") { - mIsSelectedMl = mEmMlResponse->isSelectedMl(mlInputFeatures, v0photoncandidate.getPt(), v0photoncandidate.getCentFT0M(), mOutputML); - } else { - LOG(fatal) << "Unsupported centTypePCMMl: " << mCentralityTypeMl << " , please choose from CentFT0C, CentFT0A, CentFT0M."; - } + mIsSelectedMl = mEmMlResponse->isSelectedMl(mMlInputFeatures, mV0PhotonForMl.getPt(), mV0PhotonForMl.getCent(), mOutputML); } else { - mIsSelectedMl = mEmMlResponse->isSelectedMl(mlInputFeatures, v0photoncandidate.getPt(), mOutputML); + mIsSelectedMl = mEmMlResponse->isSelectedMl(mMlInputFeatures, mV0PhotonForMl.getPt(), mOutputML); } if (!mIsSelectedMl) { return false; } + mMlBDTScores = std::span(mOutputML.data(), mOutputML.size()); } if (doQA) { fillAfterPhotonHistogram(v0, pos, ele, fRegistry); @@ -860,7 +853,7 @@ class V0PhotonCut : public TNamed void initV0MlModels(o2::ccdb::CcdbApi& ccdbApi) { - if (!mEmMlResponse) { + if (mEmMlResponse == nullptr) { mEmMlResponse = new o2::analysis::EmMlResponsePCM(); } if (mUse2DBinning) { @@ -914,6 +907,11 @@ class V0PhotonCut : public TNamed mEmMlResponse->init(); } + const std::span getBDTValue() const + { + return mMlBDTScores; + } + template bool IsConversionPointInAcceptance(TMCPhoton const& mcphoton, float convRadius) const { @@ -983,10 +981,10 @@ class V0PhotonCut : public TNamed void SetLoadMlModelsFromCCDB(bool flag = true); void SetNClassesMl(int nClasses); void SetMlTimestampCCDB(int timestamp); - void SetCentrality(float centFT0A, float centFT0C, float centFT0M); + void SetCentralityTypeMl(CentType centType); + void SetCentrality(float cent); void SetD_Bz(float d_bz); void SetCcdbUrl(const std::string& url = "http://alice-ccdb.cern.ch"); - void SetCentralityTypeMl(const std::string& centType); void SetCutDirMl(const std::vector& cutDirMl); void SetMlModelPathsCCDB(const std::vector& modelPaths); void SetMlOnnxFileNames(const std::vector& onnxFileNamesVec); @@ -1026,22 +1024,25 @@ class V0PhotonCut : public TNamed bool mLoadMlModelsFromCCDB{true}; int mTimestampCCDB{-1}; int mNClassesMl{static_cast(o2::analysis::em_cuts_ml::NCutScores)}; - float mCentFT0A{0.f}; - float mCentFT0C{0.f}; - float mCentFT0M{0.f}; + float mCent{0.f}; float mD_Bz{0.f}; std::string mCcdbUrl{"http://alice-ccdb.cern.ch"}; - std::string mCentralityTypeMl{"CentFT0C"}; std::vector mCutDirMl{std::vector{o2::analysis::em_cuts_ml::vecCutDir}}; std::vector mModelPathsCCDB{std::vector{"path_ccdb/BDT_PCM/"}}; std::vector mOnnxFileNames{std::vector{"ModelHandler_onnx_PCM.onnx"}}; std::vector mNamesInputFeatures{std::vector{"feature1", "feature2"}}; std::vector mLabelsBinsMl{std::vector{"bin 0", "bin 1"}}; - std::vector mLabelsCutScoresMl{std::vector{"score primary photons", "score background"}}; + std::vector mLabelsCutScoresMl{std::vector{o2::analysis::em_cuts_ml::labelsCutScore}}; std::vector mBinsPtMl{std::vector{o2::analysis::em_cuts_ml::vecBinsPt}}; std::vector mBinsCentMl{std::vector{o2::analysis::em_cuts_ml::vecBinsCent}}; std::vector mCutsMlFlat{std::vector{0.5}}; o2::analysis::EmMlResponsePCM* mEmMlResponse{nullptr}; + mutable bool mIsSelectedMl{false}; + mutable std::vector mOutputML{}; + mutable std::vector mMlInputFeatures{}; + mutable std::span mMlBDTScores{}; + CentType mCentralityTypeMl{CentType::CentFT0C}; + mutable V0PhotonCandidate mV0PhotonForMl; // pid cuts float mMinTPCNsigmaEl{-5}, mMaxTPCNsigmaEl{+5}; diff --git a/PWGEM/PhotonMeson/DataModel/gammaTables.h b/PWGEM/PhotonMeson/DataModel/gammaTables.h index e1ca0cc8d54..f840f771db1 100644 --- a/PWGEM/PhotonMeson/DataModel/gammaTables.h +++ b/PWGEM/PhotonMeson/DataModel/gammaTables.h @@ -416,15 +416,16 @@ using EMPrimaryElectronsFromDalitz = EMPrimaryElectronsFromDalitz_001; // iterators using EMPrimaryElectronFromDalitz = EMPrimaryElectronsFromDalitz::iterator; -namespace v0photonsphiv +namespace v0photonsphivpsi { DECLARE_SOA_INDEX_COLUMN(EMEvent, emevent); //! DECLARE_SOA_COLUMN(PhiV, phiv, float); //! -} // namespace v0photonsphiv -DECLARE_SOA_TABLE(V0PhotonsPhiV, "AOD", "V0PHOTONPHIV", //! - o2::soa::Index<>, v0photonsphiv::PhiV); +DECLARE_SOA_COLUMN(PsiPair, psipair, float); +} // namespace v0photonsphivpsi +DECLARE_SOA_TABLE(V0PhotonsPhiVPsi, "AOD", "V0PHOTONPHIVPSI", //! + o2::soa::Index<>, v0photonsphivpsi::PhiV, v0photonsphivpsi::PsiPair); // iterators -using V0PhotonsPhiV = V0PhotonsPhiV; +using V0PhotonsPhiVPsi = V0PhotonsPhiVPsi; namespace dalitzee { diff --git a/PWGEM/PhotonMeson/TableProducer/photonconversionbuilder.cxx b/PWGEM/PhotonMeson/TableProducer/photonconversionbuilder.cxx index 227ffe00564..d8f9edbf43a 100644 --- a/PWGEM/PhotonMeson/TableProducer/photonconversionbuilder.cxx +++ b/PWGEM/PhotonMeson/TableProducer/photonconversionbuilder.cxx @@ -98,7 +98,7 @@ struct PhotonConversionBuilder { Produces v0legs; Produces v0legsXYZ; Produces v0legsDeDxMC; - Produces v0photonsphiv; + Produces v0photonsphivpsi; // Produces v0photonskfcov; // Produces events_ngpcm; @@ -165,7 +165,7 @@ struct PhotonConversionBuilder { Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; Configurable nClassesPCMMl{"nClassesPCMMl", static_cast(o2::analysis::em_cuts_ml::NCutScores), "Number of classes in ML model"}; Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB"}; - Configurable centTypePCMMl{"centTypePCMMl", "CentFT0C", "Centrality type for 2D ML application: CentFT0C, CentFT0M, or CentFT0A"}; + Configurable centTypePCMMl{"centTypePCMMl", 2, "Centrality type for 2D ML application: FT0M:0, FT0A:1, FT0C:2"}; Configurable> cutDirPCMMl{"cutDirPCMMl", std::vector{o2::analysis::em_cuts_ml::vecCutDir}, "Whether to reject score values greater or smaller than the threshold"}; Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"feature1", "feature2"}, "Names of ML model input features"}; Configurable> modelPathsCCDB{"modelPathsCCDB", std::vector{"path_ccdb/BDT_PCM/"}, "Paths of models on CCDB"}; @@ -176,8 +176,11 @@ struct PhotonConversionBuilder { Configurable> binsCentPCMMl{"binsCentPCMMl", std::vector{0.0, 100.0}, "Centrality bin limits for ML application"}; Configurable> cutsPCMMlFlat{"cutsPCMMlFlat", {0.5}, "Flattened ML cuts: [bin0_score0, bin0_score1, ..., binN_scoreM]"}; + Configurable propV0LegsRadius{"propV0LegsRadius", 60.f, "Radius to which the V0 legs are propagated to calculate psipair and phiV"}; + o2::analysis::EmMlResponsePCM emMlResponse; std::vector outputML; + V0PhotonCandidate v0photoncandidate; o2::ccdb::CcdbApi ccdbApi; int mRunNumber; @@ -213,9 +216,7 @@ struct PhotonConversionBuilder { {"V0/hRxy_minX_ITSTPC_TPC", "min trackiu X vs. R_{xy};trackiu X (cm);min trackiu X - R_{xy} (cm)", {HistType::kTH2F, {{100, 0.0f, 100.f}, {100, -50.0, 50.0f}}}}, {"V0/hRxy_minX_TPC_TPC", "min trackiu X vs. R_{xy};trackiu X (cm);min trackiu X - R_{xy} (cm)", {HistType::kTH2F, {{100, 0.0f, 100.f}, {100, -50.0, 50.0f}}}}, {"V0/hPCA_diffX", "PCA vs. trackiu X - R_{xy};distance btween 2 legs (cm);min trackiu X - R_{xy} (cm)", {HistType::kTH2F, {{500, 0.0f, 5.f}, {100, -50.0, 50.0f}}}}, - {"V0/hPhiV", "#phi_{V}; #phi_{V} (rad.)", {HistType::kTH1F, {{500, 0.0f, o2::constants::math::TwoPI}}}}, - {"V0/hBDTvalueBeforeCutVsPt", "BDT response before cut vs pT; pT (GeV/c); BDT response", {HistType::kTH2F, {{1000, 0.0f, 20.0f}, {1000, 0.0f, 1.0f}}}}, - {"V0/hBDTvalueAfterCutVsPt", "BDT response after cut vs pT; pT (GeV/c); BDT response", {HistType::kTH2F, {{1000, 0.0f, 20.0f}, {1000, 0.0f, 1.0f}}}}, + {"V0/hPhiVPsiPair", "phiV vs. psi pair;#psi_{pair} (rad.);#phi_{V} (rad.)", {HistType::kTH2F, {{500, -o2::constants::math::PI, o2::constants::math::PI}, {500, 0.0f, o2::constants::math::TwoPI}}}}, {"V0Leg/hPt", "pT of leg at SV;p_{T,e} (GeV/c)", {HistType::kTH1F, {{1000, 0.0f, 10.0f}}}}, {"V0Leg/hEtaPhi", "#eta vs. #varphi of leg at SV;#varphi (rad.);#eta", {HistType::kTH2F, {{72, 0.0f, o2::constants::math::TwoPI}, {200, -1, +1}}}}, {"V0Leg/hRelDeltaPt", "pT resolution;p_{T} (GeV/c);#Deltap_{T}/p_{T}", {HistType::kTH2F, {{1000, 0.f, 10.f}, {100, 0, 1}}}}, @@ -305,6 +306,22 @@ struct PhotonConversionBuilder { } emMlResponse.cacheInputFeaturesIndices(namesInputFeatures); emMlResponse.init(); + if (nClassesPCMMl == 2) { + registry.add("V0/hBDTBackgroundScoreBeforeCutVsPt", "BDT background score before cut vs pT; pT (GeV/c); BDT background score", {HistType::kTH2F, {{1000, 0.0f, 20.0f}, {1000, 0.0f, 1.0f}}}); + registry.add("V0/hBDTBackgroundScoreAfterCutVsPt", "BDT background score after cut vs pT; pT (GeV/c); BDT background score", {HistType::kTH2F, {{1000, 0.0f, 20.0f}, {1000, 0.0f, 1.0f}}}); + registry.add("V0/hBDTSignalScoreBeforeCutVsPt", "BDT signal score before cut vs pT; pT (GeV/c); BDT signal score", {HistType::kTH2F, {{1000, 0.0f, 20.0f}, {1000, 0.0f, 1.0f}}}); + registry.add("V0/hBDTSignalScoreAfterCutVsPt", "BDT signal score after cut vs pT; pT (GeV/c); BDT signal score", {HistType::kTH2F, {{1000, 0.0f, 20.0f}, {1000, 0.0f, 1.0f}}}); + } else if (nClassesPCMMl == 3) { + registry.add("V0/hBDTBackgroundScoreBeforeCutVsPt", "BDT background score before cut vs pT; pT (GeV/c); BDT background score", {HistType::kTH2F, {{1000, 0.0f, 20.0f}, {1000, 0.0f, 1.0f}}}); + registry.add("V0/hBDTBackgroundScoreAfterCutVsPt", "BDT background score after cut vs pT; pT (GeV/c); BDT background score", {HistType::kTH2F, {{1000, 0.0f, 20.0f}, {1000, 0.0f, 1.0f}}}); + registry.add("V0/hBDTPrimaryPhotonScoreBeforeCutVsPt", "BDT primary photon score before cut vs pT; pT (GeV/c); BDT primary photon score", {HistType::kTH2F, {{1000, 0.0f, 20.0f}, {1000, 0.0f, 1.0f}}}); + registry.add("V0/hBDTPrimaryPhotonScoreAfterCutVsPt", "BDT primary photon score after cut vs pT; pT (GeV/c); BDT primary photon score", {HistType::kTH2F, {{1000, 0.0f, 20.0f}, {1000, 0.0f, 1.0f}}}); + registry.add("V0/hBDTSecondaryPhotonScoreBeforeCutVsPt", "BDT secondary photon score before cut vs pT; pT (GeV/c); BDT secondary photon score", {HistType::kTH2F, {{1000, 0.0f, 20.0f}, {1000, 0.0f, 1.0f}}}); + registry.add("V0/hBDTSecondaryPhotonScoreAfterCutVsPt", "BDT secondary photon score after cut vs pT; pT (GeV/c); BDT secondary photon score", {HistType::kTH2F, {{1000, 0.0f, 20.0f}, {1000, 0.0f, 1.0f}}}); + } else { + registry.add("V0/hBDTScoreBeforeCutVsPt", "BDT score before cut vs pT; pT (GeV/c); BDT score", {HistType::kTH2F, {{1000, 0.0f, 20.0f}, {1000, 0.0f, 1.0f}}}); + registry.add("V0/hBDTScoreAfterCutVsPt", "BDT score after cut vs pT; pT (GeV/c); BDT score", {HistType::kTH2F, {{1000, 0.0f, 20.0f}, {1000, 0.0f, 1.0f}}}); + } } } @@ -468,17 +485,17 @@ struct PhotonConversionBuilder { return cospaRZ; } - template - void fillTrackTable(TTrack const& track, TShiftedTrack const& shiftedtrack, TKFParticle const& kfp, const float dcaXY, const float dcaZ) + template + void fillTrackTable(TTrack const& track, TShiftedTrack const& shiftedtrack, const float dcaXY, const float dcaZ) { v0legs(track.collisionId(), track.globalIndex(), track.sign(), - kfp.GetPx(), kfp.GetPy(), kfp.GetPz(), dcaXY, dcaZ, + shiftedtrack.GetPx(), shiftedtrack.GetPy(), shiftedtrack.GetPz(), dcaXY, dcaZ, track.tpcNClsFindable(), track.tpcNClsFindableMinusFound(), track.tpcNClsFindableMinusCrossedRows(), track.tpcNClsShared(), track.tpcChi2NCl(), track.tpcInnerParam(), track.tpcSignal(), track.tpcNSigmaEl(), track.tpcNSigmaPi(), track.itsClusterSizes(), track.itsChi2NCl(), track.detectorMap()); - v0legsXYZ(shiftedtrack.getX(), shiftedtrack.getY(), shiftedtrack.getZ()); + v0legsXYZ(shiftedtrack.GetX(), shiftedtrack.GetY(), shiftedtrack.GetZ()); if constexpr (isMC) { v0legsDeDxMC(track.mcTunedTPCSignal()); @@ -564,6 +581,37 @@ struct PhotonConversionBuilder { return; // RZ line cut } + float phiv = 999.f; + float psipair = 999.f; + float baseR = std::hypot(xyz[0], xyz[1]); + float offsetsR[3] = {propV0LegsRadius, 30.f, 10.f}; + bool pPropagatedSuccess = false; + bool nPropagatedSuccess = false; + auto pTrackProp = pTrack; + auto nTrackProp = nTrack; + for (float offsetR : offsetsR) { + pTrackProp = pTrack; + pTrackProp.setPID(o2::track::PID::Electron); + nTrackProp = nTrack; + nTrackProp.setPID(o2::track::PID::Electron); + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, pTrackProp, 2.f, matCorr, &dcaInfo); + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, nTrackProp, 2.f, matCorr, &dcaInfo); + pPropagatedSuccess = o2::base::Propagator::Instance()->propagateToR(pTrackProp, baseR + offsetR); + nPropagatedSuccess = o2::base::Propagator::Instance()->propagateToR(nTrackProp, baseR + offsetR); + if (pPropagatedSuccess && nPropagatedSuccess) { + KFPTrack kfp_track_posProp = createKFPTrackFromTrackParCov(pTrackProp, pos.sign(), pos.tpcNClsFound(), pos.tpcChi2NCl()); + KFPTrack kfp_track_eleProp = createKFPTrackFromTrackParCov(nTrackProp, ele.sign(), ele.tpcNClsFound(), ele.tpcChi2NCl()); + phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(kfp_track_posProp.GetPx(), kfp_track_posProp.GetPy(), kfp_track_posProp.GetPz(), kfp_track_eleProp.GetPx(), kfp_track_eleProp.GetPy(), kfp_track_eleProp.GetPz(), pos.sign(), ele.sign(), d_bz); + psipair = o2::aod::pwgem::dilepton::utils::pairutil::getPsiPair(kfp_track_posProp.GetPx(), kfp_track_posProp.GetPy(), kfp_track_posProp.GetPz(), kfp_track_eleProp.GetPx(), kfp_track_eleProp.GetPy(), kfp_track_eleProp.GetPz()); + break; + } else { + LOG(debug) << "Propagation to offset" << offsetR << " cm failed for " << (pPropagatedSuccess ? "negative" : "positive") << " track. Trying smaller offset."; + } + } + if (phiv == 999.f || psipair == 999.f) { + LOG(debug) << "Propagation failed for all radii (" << propV0LegsRadius << ", 30, 10 cm). Using default values for phiv and psipair (999.f)."; + } + KFPTrack kfp_track_pos = createKFPTrackFromTrackParCov(pTrack, pos.sign(), pos.tpcNClsFound(), pos.tpcChi2NCl()); KFPTrack kfp_track_ele = createKFPTrackFromTrackParCov(nTrack, ele.sign(), ele.tpcNClsFound(), ele.tpcChi2NCl()); KFParticle kfp_pos(kfp_track_pos, kPositron); @@ -674,7 +722,8 @@ struct PhotonConversionBuilder { kfp_pos_DecayVtx.TransportToPoint(xyz); // Don't set Primary Vertex kfp_ele_DecayVtx.TransportToPoint(xyz); // Don't set Primary Vertex - V0PhotonCandidate v0photoncandidate(gammaKF_DecayVtx, kfp_pos_DecayVtx, kfp_ele_DecayVtx, collision, cospa_kf, d_bz); + CentType centType = static_cast(centTypePCMMl.value); + v0photoncandidate.setPhotonCandidate(gammaKF_DecayVtx, kfp_pos_DecayVtx, kfp_ele_DecayVtx, collision, cospa_kf, psipair, phiv, centType); if (!ele.hasITS() && !pos.hasITS()) { // V0s with TPConly-TPConly if (max_r_itsmft_ss < rxy && rxy < maxX + margin_r_tpc) { @@ -724,26 +773,36 @@ struct PhotonConversionBuilder { bool isSelectedML = false; std::vector mlInputFeatures = emMlResponse.getInputFeatures(v0photoncandidate, pos, ele); if (use2DBinning) { - if (std::string(centTypePCMMl) == "CentFT0C") { - isSelectedML = emMlResponse.isSelectedMl(mlInputFeatures, v0photoncandidate.getPt(), v0photoncandidate.getCentFT0C(), outputML); - } else if (std::string(centTypePCMMl) == "CentFT0A") { - isSelectedML = emMlResponse.isSelectedMl(mlInputFeatures, v0photoncandidate.getPt(), v0photoncandidate.getCentFT0A(), outputML); - } else if (std::string(centTypePCMMl) == "CentFT0M") { - isSelectedML = emMlResponse.isSelectedMl(mlInputFeatures, v0photoncandidate.getPt(), v0photoncandidate.getCentFT0M(), outputML); - } else { - LOG(fatal) << "Unsupported centTypePCMMl: " << centTypePCMMl << " , please choose from CentFT0C, CentFT0A, CentFT0M."; - } + isSelectedML = emMlResponse.isSelectedMl(mlInputFeatures, v0photoncandidate.getPt(), v0photoncandidate.getCent(), outputML); } else { isSelectedML = emMlResponse.isSelectedMl(mlInputFeatures, v0photoncandidate.getPt(), outputML); } if (filltable) { - registry.fill(HIST("V0/hBDTvalueBeforeCutVsPt"), v0photoncandidate.getPt(), outputML[0]); + if (nClassesPCMMl == 2) { + registry.fill(HIST("V0/hBDTBackgroundScoreBeforeCutVsPt"), v0photoncandidate.getPt(), outputML[0]); + registry.fill(HIST("V0/hBDTSignalScoreBeforeCutVsPt"), v0photoncandidate.getPt(), outputML[1]); + } else if (nClassesPCMMl == 3) { + registry.fill(HIST("V0/hBDTPrimaryPhotonScoreBeforeCutVsPt"), v0photoncandidate.getPt(), outputML[0]); + registry.fill(HIST("V0/hBDTSecondaryPhotonScoreBeforeCutVsPt"), v0photoncandidate.getPt(), outputML[1]); + registry.fill(HIST("V0/hBDTBackgroundScoreBeforeCutVsPt"), v0photoncandidate.getPt(), outputML[2]); + } else { + registry.fill(HIST("V0/hBDTScoreBeforeCutVsPt"), v0photoncandidate.getPt(), outputML[0]); + } } if (!isSelectedML) { return; } if (filltable) { - registry.fill(HIST("V0/hBDTvalueAfterCutVsPt"), v0photoncandidate.getPt(), outputML[0]); + if (nClassesPCMMl == 2) { + registry.fill(HIST("V0/hBDTBackgroundScoreAfterCutVsPt"), v0photoncandidate.getPt(), outputML[0]); + registry.fill(HIST("V0/hBDTSignalScoreAfterCutVsPt"), v0photoncandidate.getPt(), outputML[1]); + } else if (nClassesPCMMl == 3) { + registry.fill(HIST("V0/hBDTPrimaryPhotonScoreAfterCutVsPt"), v0photoncandidate.getPt(), outputML[0]); + registry.fill(HIST("V0/hBDTSecondaryPhotonScoreAfterCutVsPt"), v0photoncandidate.getPt(), outputML[1]); + registry.fill(HIST("V0/hBDTBackgroundScoreAfterCutVsPt"), v0photoncandidate.getPt(), outputML[2]); + } else { + registry.fill(HIST("V0/hBDTScoreAfterCutVsPt"), v0photoncandidate.getPt(), outputML[0]); + } } } @@ -760,7 +819,7 @@ struct PhotonConversionBuilder { registry.fill(HIST("V0/hPCA_Rxy"), rxy, v0photoncandidate.getPCA()); registry.fill(HIST("V0/hDCAxyz"), v0photoncandidate.getDcaXYToPV(), v0photoncandidate.getDcaZToPV()); registry.fill(HIST("V0/hPCA_diffX"), v0photoncandidate.getPCA(), std::min(pTrack.getX(), nTrack.getX()) - rxy); // trackiu.x() - rxy should be positive - registry.fill(HIST("V0/hPhiV"), v0photoncandidate.getPhiV()); + registry.fill(HIST("V0/hPhiVPsiPair"), v0photoncandidate.getPsiPair(), v0photoncandidate.getPhiV()); float cospaXY_kf = cospaXY_KF(gammaKF_DecayVtx, KFPV); float cospaRZ_kf = cospaRZ_KF(gammaKF_DecayVtx, KFPV); @@ -797,12 +856,12 @@ struct PhotonConversionBuilder { v0_sv.M(), v0photoncandidate.getDcaXYToPV(), v0photoncandidate.getDcaZToPV(), cospa_kf, cospaXY_kf, cospaRZ_kf, v0photoncandidate.getPCA(), v0photoncandidate.getAlpha(), v0photoncandidate.getQt(), v0photoncandidate.getChi2NDF()); - v0photonsphiv(v0photoncandidate.getPhiV()); + v0photonsphivpsi(v0photoncandidate.getPhiV(), v0photoncandidate.getPsiPair()); // v0photonskfcov(gammaKF_PV.GetCovariance(9), gammaKF_PV.GetCovariance(14), gammaKF_PV.GetCovariance(20), gammaKF_PV.GetCovariance(13), gammaKF_PV.GetCovariance(19), gammaKF_PV.GetCovariance(18)); - fillTrackTable(pos, pTrack, kfp_pos_DecayVtx, posdcaXY, posdcaZ); // positive leg first - fillTrackTable(ele, nTrack, kfp_ele_DecayVtx, eledcaXY, eledcaZ); // negative leg second + fillTrackTable(pos, kfp_pos_DecayVtx, posdcaXY, posdcaZ); // positive leg first + fillTrackTable(ele, kfp_ele_DecayVtx, eledcaXY, eledcaZ); // negative leg second } // end of fill table } diff --git a/PWGEM/PhotonMeson/Tasks/CMakeLists.txt b/PWGEM/PhotonMeson/Tasks/CMakeLists.txt index 69cc178395c..ba160a3080f 100644 --- a/PWGEM/PhotonMeson/Tasks/CMakeLists.txt +++ b/PWGEM/PhotonMeson/Tasks/CMakeLists.txt @@ -91,6 +91,11 @@ o2physics_add_dpl_workflow(pi0eta-to-gammagamma-pcmpcm PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore O2Physics::MLCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(pi0eta-to-gammagamma-pcmpcm-ml + SOURCES Pi0EtaToGammaGammaPCMPCMML.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore O2Physics::MLCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(pi0eta-to-gammagamma-pcmdalitzee SOURCES Pi0EtaToGammaGammaPCMDalitzEE.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore O2Physics::MLCore @@ -111,6 +116,11 @@ o2physics_add_dpl_workflow(pi0eta-to-gammagamma-mc-pcmpcm PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore O2Physics::MLCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(pi0eta-to-gammagamma-mc-pcmpcm-ml + SOURCES Pi0EtaToGammaGammaMCPCMPCMML.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore O2Physics::MLCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(pi0eta-to-gammagamma-mc-pcmdalitzee SOURCES Pi0EtaToGammaGammaMCPCMDalitzEE.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore O2Physics::MLCore diff --git a/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaMCPCMPCMML.cxx b/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaMCPCMPCMML.cxx new file mode 100644 index 00000000000..c5b06741e75 --- /dev/null +++ b/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaMCPCMPCMML.cxx @@ -0,0 +1,37 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +// +/// \file Pi0EtaToGammaGammaMCPCMPCMML.cxx +/// \brief This code loops over photons and makes pairs for neutral mesons analyses in MC for PCM-PCM with additional ML-based photon cuts. +/// \author Isabel Kantak, isabel.kantak@cern.ch + +#include "PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h" +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "PWGEM/PhotonMeson/Utils/PairUtilities.h" + +#include +#include +#include + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::aod::pwgem::photonmeson::photonpair; + +using MyV0Photons = o2::soa::Filtered>; +using MyMCV0Legs = soa::Join; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask>(cfgc, TaskName{"pi0eta-to-gammagamma-mc-pcmpcm"}), + }; +} diff --git a/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaPCMPCMML.cxx b/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaPCMPCMML.cxx new file mode 100644 index 00000000000..2d0fa9f2120 --- /dev/null +++ b/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaPCMPCMML.cxx @@ -0,0 +1,36 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +// +/// \file Pi0EtaToGammaGammaPCMPCMML.cxx +/// \brief This code loops over photons and makes pairs for neutral mesons analyses for PCM-PCM with additional ML cuts to photons. +/// \author Isabel Kantak, isabel.kantak@cern.ch + +#include "PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h" +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "PWGEM/PhotonMeson/Utils/PairUtilities.h" + +#include +#include +#include + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::aod::pwgem::photonmeson::photonpair; + +using MyV0Photons = o2::soa::Filtered>; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask>(cfgc, TaskName{"pi0eta-to-gammagamma-pcmpcm"}), + }; +} diff --git a/PWGEM/PhotonMeson/Tasks/pcmQC.cxx b/PWGEM/PhotonMeson/Tasks/pcmQC.cxx index 3f8130abe0d..c741b283be3 100644 --- a/PWGEM/PhotonMeson/Tasks/pcmQC.cxx +++ b/PWGEM/PhotonMeson/Tasks/pcmQC.cxx @@ -25,6 +25,8 @@ #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" #include +#include +#include #include #include #include @@ -52,10 +54,18 @@ using MyCollision = MyCollisions::iterator; using MyV0Photons = soa::Join; using MyV0Photon = MyV0Photons::iterator; +using MyV0PhotonsML = soa::Join; +using MyV0PhotonML = MyV0PhotonsML::iterator; + struct PCMQC { Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; Configurable cfgCentMin{"cfgCentMin", 0, "min. centrality"}; Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; + Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; + Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + Configurable skipGRPOquery{"skipGRPOquery", true, "skip grpo query"}; + Configurable d_bz_input{"d_bz_input", -999, "bz field in kG, -999 is automatic"}; EMPhotonEventCut fEMEventCut; struct : ConfigurableGroup { @@ -106,8 +116,28 @@ struct PCMQC { Configurable cfg_max_TPCNsigmaEl{"cfg_max_TPCNsigmaEl", +3.0, "max. TPC n sigma for electron"}; Configurable cfg_disable_itsonly_track{"cfg_disable_itsonly_track", false, "flag to disable ITSonly tracks"}; Configurable cfg_disable_tpconly_track{"cfg_disable_tpconly_track", false, "flag to disable TPConly tracks"}; + Configurable cfg_dEdx_postcalibration{"cfg_dEdx_postcalibration", false, "flag to enable dEdx post calibration"}; + // for ML cuts + Configurable cfg_apply_ml_cuts{"cfg_apply_ml", false, "flag to apply ML cut"}; + Configurable cfg_use_2d_binning{"cfg_use_2d_binning", false, "flag to use 2D binning (pT, cent)"}; + Configurable cfg_load_ml_models_from_ccdb{"cfg_load_ml_models_from_ccdb", true, "flag to load ML models from CCDB"}; + Configurable cfg_timestamp_ccdb{"cfg_timestamp_ccdb", -1, "timestamp for CCDB"}; + Configurable cfg_nclasses_ml{"cfg_nclasses_ml", static_cast(o2::analysis::em_cuts_ml::NCutScores), "number of classes for ML"}; + Configurable> cfg_cut_dir_ml{"cfg_cut_dir_ml", std::vector{o2::analysis::em_cuts_ml::vecCutDir}, "cut direction for ML"}; + Configurable> cfg_input_feature_names{"cfg_input_feature_names", std::vector{"feature1", "feature2"}, "input feature names for ML models"}; + Configurable> cfg_model_paths_ccdb{"cfg_model_paths_ccdb", std::vector{"path_ccdb/BDT_PCM/"}, "CCDB paths for ML models"}; + Configurable> cfg_onnx_file_names{"cfg_onnx_file_names", std::vector{"ModelHandler_onnx_PCM.onnx"}, "ONNX file names for ML models"}; + Configurable> cfg_labels_bins_ml{"cfg_labels_bins_ml", std::vector{"bin 0", "bin 1"}, "Labels for bins"}; + Configurable> cfg_labels_cut_scores_ml{"cfg_labels_cut_scores_ml", std::vector{o2::analysis::em_cuts_ml::labelsCutScore}, "Labels for cut scores"}; + Configurable> cfg_bins_pt_ml{"cfg_bins_pt_ml", std::vector{0.0, +1e+10}, "pT bin limits for ML application"}; + Configurable> cfg_bins_cent_ml{"cfg_bins_cent_ml", std::vector{o2::analysis::em_cuts_ml::vecBinsCent}, "centrality bins for ML"}; + Configurable> cfg_cuts_ml_flat{"cfg_cuts_ml_flat", {0.5}, "Flattened ML cuts: [bin0_score0, bin0_score1, ..., binN_scoreM]"}; } pcmcuts; + o2::ccdb::CcdbApi ccdbApi; + o2::framework::Service ccdb; + int mRunNumber; + float d_bz; static constexpr std::string_view event_types[2] = {"before/", "after/"}; HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; @@ -116,6 +146,54 @@ struct PCMQC { addhistograms(); DefineEMEventCut(); DefinePCMCut(); + + mRunNumber = 0; + d_bz = 0; + + ccdb->setURL(ccdburl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + } + + template + void initCCDB(TCollision const& collision) + { + if (mRunNumber == collision.runNumber()) { + return; + } + + // In case override, don't proceed, please - no CCDB access required + if (d_bz_input > -990) { + d_bz = d_bz_input; + o2::parameters::GRPMagField grpmag; + if (std::fabs(d_bz) > 1e-5) { + grpmag.setL3Current(30000.f / (d_bz / 5.0f)); + } + mRunNumber = collision.runNumber(); + return; + } + + auto run3grp_timestamp = collision.timestamp(); + o2::parameters::GRPObject* grpo = 0x0; + o2::parameters::GRPMagField* grpmag = 0x0; + if (!skipGRPOquery) + grpo = ccdb->getForTimeStamp(grpPath, run3grp_timestamp); + if (grpo) { + // Fetch magnetic field from ccdb for current collision + d_bz = grpo->getNominalL3Field(); + LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; + } else { + grpmag = ccdb->getForTimeStamp(grpmagPath, run3grp_timestamp); + if (!grpmag) { + LOG(fatal) << "Got nullptr from CCDB for path " << grpmagPath << " of object GRPMagField and " << grpPath << " of object GRPObject for timestamp " << run3grp_timestamp; + } + // Fetch magnetic field from ccdb for current collision + d_bz = std::lround(5.f * grpmag->getL3Current() / 30000.f); + LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; + } + fV0PhotonCut.SetD_Bz(d_bz); + mRunNumber = collision.runNumber(); } void addhistograms() @@ -165,6 +243,22 @@ struct PCMQC { fRegistry.add("V0/hsConvPoint", "photon conversion point;r_{xy} (cm);#varphi (rad.);#eta;", kTHnSparseF, {{100, 0.0f, 100}, {90, 0, o2::constants::math::TwoPI}, {80, -2, +2}}, false); fRegistry.add("V0/hNgamma", "Number of #gamma candidates per collision", kTH1F, {{101, -0.5f, 100.5f}}); + if (pcmcuts.cfg_apply_ml_cuts) { + if (pcmcuts.cfg_nclasses_ml == 2) { + fRegistry.add("V0/hBDTBackgroundScoreVsPt", "BDT background score vs pT; pT (GeV/c); BDT background score", {HistType::kTH2F, {{1000, 0.0f, 20.0f}, {1000, 0.0f, 1.0f}}}); + fRegistry.add("V0/hBDTSignalScoreVsPt", "BDT signal score vs pT; pT (GeV/c); BDT signal score", {HistType::kTH2F, {{1000, 0.0f, 20.0f}, {1000, 0.0f, 1.0f}}}); + fRegistry.add("V0/hPhiVPsi", "#varphi vs. #psi angle;#psi (rad.); #varphi (rad.)", kTH2F, {{200, -o2::constants::math::PI, o2::constants::math::PI}, {200, 0, o2::constants::math::TwoPI}}, false); + } else if (pcmcuts.cfg_nclasses_ml == 3) { + fRegistry.add("V0/hBDTBackgroundScoreVsPt", "BDT background score vs pT; pT (GeV/c); BDT background score", {HistType::kTH2F, {{1000, 0.0f, 20.0f}, {1000, 0.0f, 1.0f}}}); + fRegistry.add("V0/hBDTPrimaryPhotonScoreVsPt", "BDT primary photon score vs pT; pT (GeV/c); BDT primary photon score", {HistType::kTH2F, {{1000, 0.0f, 20.0f}, {1000, 0.0f, 1.0f}}}); + fRegistry.add("V0/hBDTSecondaryPhotonScoreVsPt", "BDT secondary photon score vs pT; pT (GeV/c); BDT secondary photon score", {HistType::kTH2F, {{1000, 0.0f, 20.0f}, {1000, 0.0f, 1.0f}}}); + fRegistry.add("V0/hPhiVPsi", "#varphi vs. #psi angle;#psi (rad.); #varphi (rad.)", kTH2F, {{200, -o2::constants::math::PI, o2::constants::math::PI}, {200, 0, o2::constants::math::TwoPI}}, false); + } else { + fRegistry.add("V0/hBDTScoreVsPt", "BDT score vs pT; pT (GeV/c); BDT score", {HistType::kTH2F, {{1000, 0.0f, 20.0f}, {1000, 0.0f, 1.0f}}}); + fRegistry.add("V0/hPhiVPsi", "#varphi vs. #psi angle;#psi (rad.); #varphi (rad.)", kTH2F, {{200, -o2::constants::math::PI, o2::constants::math::PI}, {200, 0, o2::constants::math::TwoPI}}, false); + } + } + // v0leg info fRegistry.add("V0Leg/hPt", "pT;p_{T,e} (GeV/c)", kTH1F, {{1000, 0.0f, 10}}, false); fRegistry.add("V0Leg/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", kTH1F, {{1000, -50, 50}}, false); @@ -183,6 +277,10 @@ struct PCMQC { fRegistry.add("V0Leg/hChi2ITS", "chi2/number of ITS clusters", kTH1F, {{100, 0, 10}}, false); fRegistry.add("V0Leg/hITSClusterMap", "ITS cluster map", kTH1F, {{128, -0.5, 127.5}}, false); fRegistry.add("V0Leg/hMeanClusterSizeITS", "mean cluster size ITS; on ITS #times cos(#lambda)", kTH2F, {{1000, 0, 10}, {160, 0, 16}}, false); + if (pcmcuts.cfg_dEdx_postcalibration) { + fRegistry.add("V0Leg/hPvsConvPointvsTPCNsigmaElvsEta_Pos", "momentum of pos leg vs. conversion point of V0 vs. TPC n sigma pos vs. eta of pos leg; p (GeV/c); r_{xy} (cm); n #sigma_{e}^{TPC}; #eta", kTHnSparseF, {{200, 0, 20}, {100, 0, 100}, {500, -5, 5}, {200, -1, +1}}, false); + fRegistry.add("V0Leg/hPvsConvPointvsTPCNsigmaElvsEta_Ele", "momentum of neg leg vs. conversion point of V0 vs. TPC n sigma el vs. eta of neg leg; p (GeV/c); r_{xy} (cm); n #sigma_{e}^{TPC}; #eta", kTHnSparseF, {{200, 0, 20}, {100, 0, 100}, {500, -5, 5}, {200, -1, +1}}, false); + } // fRegistry.add("V0Leg/hXY", "X vs. Y;X (cm);Y (cm)", kTH2F, {{100, 0, 100}, {80, -20, 20}}, false); // fRegistry.add("V0Leg/hZX", "Z vs. X;Z (cm);X (cm)", kTH2F, {{200, -100, 100}, {100, 0, 100}}, false); // fRegistry.add("V0Leg/hZY", "Z vs. Y;Z (cm);Y (cm)", kTH2F, {{200, -100, 100}, {80, -20, 20}}, false); @@ -235,6 +333,31 @@ struct PCMQC { fV0PhotonCut.SetRequireITSTPC(pcmcuts.cfg_require_v0_with_itstpc); fV0PhotonCut.SetRequireITSonly(pcmcuts.cfg_require_v0_with_itsonly); fV0PhotonCut.SetRequireTPConly(pcmcuts.cfg_require_v0_with_tpconly); + + // for ML + fV0PhotonCut.SetApplyMlCuts(pcmcuts.cfg_apply_ml_cuts); + fV0PhotonCut.SetUse2DBinning(pcmcuts.cfg_use_2d_binning); + fV0PhotonCut.SetLoadMlModelsFromCCDB(pcmcuts.cfg_load_ml_models_from_ccdb); + fV0PhotonCut.SetNClassesMl(pcmcuts.cfg_nclasses_ml); + fV0PhotonCut.SetMlTimestampCCDB(pcmcuts.cfg_timestamp_ccdb); + fV0PhotonCut.SetCcdbUrl(ccdburl); + CentType mCentralityTypeMlEnum; + mCentralityTypeMlEnum = static_cast(cfgCentEstimator.value); + fV0PhotonCut.SetCentralityTypeMl(mCentralityTypeMlEnum); + fV0PhotonCut.SetCutDirMl(pcmcuts.cfg_cut_dir_ml); + fV0PhotonCut.SetMlModelPathsCCDB(pcmcuts.cfg_model_paths_ccdb); + fV0PhotonCut.SetMlOnnxFileNames(pcmcuts.cfg_onnx_file_names); + fV0PhotonCut.SetBinsPtMl(pcmcuts.cfg_bins_pt_ml); + fV0PhotonCut.SetBinsCentMl(pcmcuts.cfg_bins_cent_ml); + fV0PhotonCut.SetCutsMl(pcmcuts.cfg_cuts_ml_flat); + fV0PhotonCut.SetNamesInputFeatures(pcmcuts.cfg_input_feature_names); + fV0PhotonCut.SetLabelsBinsMl(pcmcuts.cfg_labels_bins_ml); + fV0PhotonCut.SetLabelsCutScoresMl(pcmcuts.cfg_labels_cut_scores_ml); + fV0PhotonCut.SetD_Bz(0.0f); // dummy value -> only for psi_pair calculation + + if (pcmcuts.cfg_apply_ml_cuts) { + fV0PhotonCut.initV0MlModels(ccdbApi); + } } template @@ -302,6 +425,28 @@ struct PCMQC { o2::math_utils::bringTo02Pi(phi_cp); float eta_cp = std::atanh(v0.vz() / std::sqrt(std::pow(v0.vx(), 2) + std::pow(v0.vy(), 2) + std::pow(v0.vz(), 2))); fRegistry.fill(HIST("V0/hsConvPoint"), v0.v0radius(), phi_cp, eta_cp); + + // BDT response histogram can be filled here when apply BDT is true + if (pcmcuts.cfg_apply_ml_cuts) { + const std::span& bdtValue = fV0PhotonCut.getBDTValue(); + float psipair = 999.f; + float phiv = 999.f; + if constexpr (requires { v0.psipair(); v0.phiv(); }) { + psipair = v0.psipair(); + phiv = v0.phiv(); + } + fRegistry.fill(HIST("V0/hPhiVPsi"), psipair, phiv); + if (pcmcuts.cfg_nclasses_ml == 2 && bdtValue.size() == 2) { + fRegistry.fill(HIST("V0/hBDTBackgroundScoreVsPt"), v0.pt(), bdtValue[0]); + fRegistry.fill(HIST("V0/hBDTSignalScoreVsPt"), v0.pt(), bdtValue[1]); + } else if (pcmcuts.cfg_nclasses_ml == 3 && bdtValue.size() == 3) { + fRegistry.fill(HIST("V0/hBDTBackgroundScoreVsPt"), v0.pt(), bdtValue[0]); + fRegistry.fill(HIST("V0/hBDTPrimaryPhotonScoreVsPt"), v0.pt(), bdtValue[1]); + fRegistry.fill(HIST("V0/hBDTSecondaryPhotonScoreVsPt"), v0.pt(), bdtValue[2]); + } else if (bdtValue.size() == 1) { + fRegistry.fill(HIST("V0/hBDTCutVsPt"), v0.pt(), bdtValue[0]); + } + } } template @@ -331,15 +476,17 @@ struct PCMQC { // fRegistry.fill(HIST("V0Leg/hZY"), leg.z(), leg.y()); } - Preslice perCollision = aod::v0photonkf::emeventId; + o2::framework::SliceCache v0cache; Filter collisionFilter_centrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); Filter collisionFilter_occupancy_track = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; Filter collisionFilter_occupancy_ft0c = eventcuts.cfgFT0COccupancyMin <= o2::aod::evsel::ft0cOccupancyInTimeRange && o2::aod::evsel::ft0cOccupancyInTimeRange < eventcuts.cfgFT0COccupancyMax; using FilteredMyCollisions = soa::Filtered; - void processQC(FilteredMyCollisions const& collisions, MyV0Photons const& v0photons, aod::V0Legs const&) + template + void process(FilteredMyCollisions const& collisions, TV0Photon const& v0photons, aod::V0Legs const&) { - for (auto& collision : collisions) { + for (const auto& collision : collisions) { + initCCDB(collision); const float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { continue; @@ -353,11 +500,12 @@ struct PCMQC { fRegistry.fill(HIST("Event/before/hCollisionCounter"), 10.0); // accepted fRegistry.fill(HIST("Event/after/hCollisionCounter"), 10.0); // accepted + fV0PhotonCut.SetCentrality(centralities[cfgCentEstimator]); int nv0 = 0; - auto v0photons_coll = v0photons.sliceBy(perCollision, collision.globalIndex()); - for (auto& v0 : v0photons_coll) { - auto pos = v0.posTrack_as(); - auto ele = v0.negTrack_as(); + auto v0photons_coll = v0photons.sliceByCached(aod::v0photonkf::emeventId, collision.globalIndex(), v0cache); + for (const auto& v0 : v0photons_coll) { + auto pos = v0.template posTrack_as(); + auto ele = v0.template negTrack_as(); if (!fV0PhotonCut.IsSelected(v0)) { continue; @@ -366,15 +514,29 @@ struct PCMQC { for (auto& leg : {pos, ele}) { fillV0LegInfo(leg); } + if (pcmcuts.cfg_dEdx_postcalibration) { + fRegistry.fill(HIST("V0Leg/hPvsConvPointvsTPCNsigmaElvsEta_Pos"), pos.p(), v0.v0radius(), pos.tpcNSigmaEl(), pos.eta()); + fRegistry.fill(HIST("V0Leg/hPvsConvPointvsTPCNsigmaElvsEta_Ele"), ele.p(), v0.v0radius(), ele.tpcNSigmaEl(), ele.eta()); + } nv0++; } // end of v0 loop fRegistry.fill(HIST("V0/hNgamma"), nv0); } // end of collision loop + } + void processQC(FilteredMyCollisions const& collisions, MyV0Photons const& v0photons, aod::V0Legs const& v0legs) + { + process(collisions, v0photons, v0legs); } // end of process + void processQCML(FilteredMyCollisions const& collisions, MyV0PhotonsML const& v0photonsML, aod::V0Legs const& v0legs) + { + process(collisions, v0photonsML, v0legs); + } // end of ML process + void processDummy(MyCollisions const&) {} PROCESS_SWITCH(PCMQC, processQC, "run PCM QC", true); + PROCESS_SWITCH(PCMQC, processQCML, "run PCM QC with ML", false); PROCESS_SWITCH(PCMQC, processDummy, "Dummy function", false); }; diff --git a/PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx b/PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx index f858ec60743..eb04bc86b88 100644 --- a/PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx +++ b/PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx @@ -27,6 +27,8 @@ #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" #include +#include +#include #include #include #include @@ -58,9 +60,12 @@ using MyCollision = MyCollisions::iterator; using MyMCCollisions = soa::Join; using MyMCCollision = MyMCCollisions::iterator; -using MyV0Photons = soa::Join; +using MyV0Photons = o2::soa::Join; using MyV0Photon = MyV0Photons::iterator; +using MyV0PhotonsML = soa::Join; +using MyV0PhotonML = MyV0PhotonsML::iterator; + using MyMCV0Legs = soa::Join; using MyMCV0Leg = MyMCV0Legs::iterator; @@ -69,6 +74,11 @@ struct PCMQCMC { Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; Configurable cfgCentMin{"cfgCentMin", 0, "min. centrality"}; Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; + Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; + Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + Configurable skipGRPOquery{"skipGRPOquery", true, "skip grpo query"}; + Configurable d_bz_input{"d_bz_input", -999, "bz field in kG, -999 is automatic"}; Configurable maxRgen{"maxRgen", 90.f, "maximum radius for generated particles"}; Configurable margin_z_mc{"margin_z_mc", 7.0, "margin for z cut in cm for MC"}; @@ -123,8 +133,27 @@ struct PCMQCMC { Configurable cfg_max_TPCNsigmaEl{"cfg_max_TPCNsigmaEl", +3.0, "max. TPC n sigma for electron"}; Configurable cfg_disable_itsonly_track{"cfg_disable_itsonly_track", false, "flag to disable ITSonly tracks"}; Configurable cfg_disable_tpconly_track{"cfg_disable_tpconly_track", false, "flag to disable TPConly tracks"}; + // for ML cuts + Configurable cfg_apply_ml_cuts{"cfg_apply_ml", false, "flag to apply ML cut"}; + Configurable cfg_use_2d_binning{"cfg_use_2d_binning", false, "flag to use 2D binning (pT, cent)"}; + Configurable cfg_load_ml_models_from_ccdb{"cfg_load_ml_models_from_ccdb", true, "flag to load ML models from CCDB"}; + Configurable cfg_timestamp_ccdb{"cfg_timestamp_ccdb", -1, "timestamp for CCDB"}; + Configurable cfg_nclasses_ml{"cfg_nclasses_ml", static_cast(o2::analysis::em_cuts_ml::NCutScores), "number of classes for ML"}; + Configurable> cfg_cut_dir_ml{"cfg_cut_dir_ml", std::vector{o2::analysis::em_cuts_ml::vecCutDir}, "cut direction for ML"}; + Configurable> cfg_input_feature_names{"cfg_input_feature_names", std::vector{"feature1", "feature2"}, "input feature names for ML models"}; + Configurable> cfg_model_paths_ccdb{"cfg_model_paths_ccdb", std::vector{"path_ccdb/BDT_PCM/"}, "CCDB paths for ML models"}; + Configurable> cfg_onnx_file_names{"cfg_onnx_file_names", std::vector{"ModelHandler_onnx_PCM.onnx"}, "ONNX file names for ML models"}; + Configurable> cfg_labels_bins_ml{"cfg_labels_bins_ml", std::vector{"bin 0", "bin 1"}, "Labels for bins"}; + Configurable> cfg_labels_cut_scores_ml{"cfg_labels_cut_scores_ml", std::vector{o2::analysis::em_cuts_ml::labelsCutScore}, "Labels for cut scores"}; + Configurable> cfg_bins_pt_ml{"cfg_bins_pt_ml", std::vector{0.0, +1e+10}, "pT bin limits for ML application"}; + Configurable> cfg_bins_cent_ml{"cfg_bins_cent_ml", std::vector{o2::analysis::em_cuts_ml::vecBinsCent}, "centrality bins for ML"}; + Configurable> cfg_cuts_ml_flat{"cfg_cuts_ml_flat", {0.5}, "Flattened ML cuts: [bin0_score0, bin0_score1, ..., binN_scoreM]"}; } pcmcuts; + o2::ccdb::CcdbApi ccdbApi; + o2::framework::Service ccdb; + int mRunNumber; + float d_bz; HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; static constexpr std::string_view event_types[2] = {"before/", "after/"}; static constexpr std::string_view mcphoton_types[5] = {"primary/", "fromWD/", "fromHS/", "fromPi0Dalitz/", "fromEtaDalitz/"}; @@ -134,6 +163,54 @@ struct PCMQCMC { DefineEMEventCut(); DefinePCMCut(); addhistograms(); + + mRunNumber = 0; + d_bz = 0; + + ccdb->setURL(ccdburl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + } + + template + void initCCDB(TCollision const& collision) + { + if (mRunNumber == collision.runNumber()) { + return; + } + + // In case override, don't proceed, please - no CCDB access required + if (d_bz_input > -990) { + d_bz = d_bz_input; + o2::parameters::GRPMagField grpmag; + if (std::fabs(d_bz) > 1e-5) { + grpmag.setL3Current(30000.f / (d_bz / 5.0f)); + } + mRunNumber = collision.runNumber(); + return; + } + + auto run3grp_timestamp = collision.timestamp(); + o2::parameters::GRPObject* grpo = 0x0; + o2::parameters::GRPMagField* grpmag = 0x0; + if (!skipGRPOquery) + grpo = ccdb->getForTimeStamp(grpPath, run3grp_timestamp); + if (grpo) { + // Fetch magnetic field from ccdb for current collision + d_bz = grpo->getNominalL3Field(); + LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; + } else { + grpmag = ccdb->getForTimeStamp(grpmagPath, run3grp_timestamp); + if (!grpmag) { + LOG(fatal) << "Got nullptr from CCDB for path " << grpmagPath << " of object GRPMagField and " << grpPath << " of object GRPObject for timestamp " << run3grp_timestamp; + } + // Fetch magnetic field from ccdb for current collision + d_bz = std::lround(5.f * grpmag->getL3Current() / 30000.f); + LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; + } + fV0PhotonCut.SetD_Bz(d_bz); + mRunNumber = collision.runNumber(); } void addhistograms() @@ -222,6 +299,21 @@ struct PCMQCMC { fRegistry.add("V0/primary/hXY_MC", "X vs. Y of true photon conversion point.;X (cm);Y (cm)", kTH2F, {{400, -100.0f, +100}, {400, -100, +100}}, true); fRegistry.add("V0/primary/hRZ_MC", "R vs. Z of true photon conversion point;Z (cm);R_{xy} (cm)", kTH2F, {{200, -100.0f, +100}, {200, 0, 100}}, true); fRegistry.add("V0/primary/hsConvPoint", "photon conversion point;r_{xy} (cm);#varphi (rad.);#eta;", kTHnSparseF, {{100, 0.0f, 100}, {90, 0, o2::constants::math::TwoPI}, {80, -2, +2}}, false); + if (pcmcuts.cfg_apply_ml_cuts) { + if (pcmcuts.cfg_nclasses_ml == 2) { + fRegistry.add("V0/primary/hBDTBackgroundScoreVsPt", "BDT background score vs pT; pT (GeV/c); BDT background score", {HistType::kTH2F, {{200, 0.0f, 20.0f}, {100, 0.0f, 1.0f}}}); + fRegistry.add("V0/primary/hBDTSignalScoreVsPt", "BDT signal score vs pT; pT (GeV/c); BDT signal score", {HistType::kTH2F, {{200, 0.0f, 20.0f}, {100, 0.0f, 1.0f}}}); + fRegistry.add("V0/primary/hPhiVPsi", "#varphi vs. #psi angle;#psi (rad.); #varphi (rad.)", kTH2F, {{200, -o2::constants::math::PI, o2::constants::math::PI}, {200, 0, o2::constants::math::TwoPI}}, false); + } else if (pcmcuts.cfg_nclasses_ml == 3) { + fRegistry.add("V0/primary/hBDTBackgroundScoreVsPt", "BDT background score vs pT; pT (GeV/c); BDT background score", {HistType::kTH2F, {{200, 0.0f, 20.0f}, {100, 0.0f, 1.0f}}}); + fRegistry.add("V0/primary/hBDTPrimaryPhotonScoreVsPt", "BDT primary photon score vs pT; pT (GeV/c); BDT primary photon score", {HistType::kTH2F, {{200, 0.0f, 20.0f}, {100, 0.0f, 1.0f}}}); + fRegistry.add("V0/primary/hBDTSecondaryPhotonScoreVsPt", "BDT secondary photon score vs pT; pT (GeV/c); BDT secondary photon score", {HistType::kTH2F, {{200, 0.0f, 20.0f}, {100, 0.0f, 1.0f}}}); + fRegistry.add("V0/primary/hPhiVPsi", "#varphi vs. #psi angle;#psi (rad.); #varphi (rad.)", kTH2F, {{200, -o2::constants::math::PI, o2::constants::math::PI}, {200, 0, o2::constants::math::TwoPI}}, false); + } else { + fRegistry.add("V0/primary/hBDTScoreVsPt", "BDT score vs pT; pT (GeV/c); BDT score", {HistType::kTH2F, {{200, 0.0f, 20.0f}, {100, 0.0f, 1.0f}}}); + fRegistry.add("V0/primary/hPhiVPsi", "#varphi vs. #psi angle;#psi (rad.); #varphi (rad.)", kTH2F, {{200, -o2::constants::math::PI, o2::constants::math::PI}, {200, 0, o2::constants::math::TwoPI}}, false); + } + } fRegistry.addClone("V0/primary/", "V0/fromWD/"); // from weak decay fRegistry.addClone("V0/primary/", "V0/fromHS/"); // from hadronic shower in detector materials fRegistry.addClone("V0/primary/", "V0/fromPi0Dalitz/"); // misidentified dielectron from pi0 dalitz decay @@ -314,6 +406,31 @@ struct PCMQCMC { fV0PhotonCut.SetRequireITSTPC(pcmcuts.cfg_require_v0_with_itstpc); fV0PhotonCut.SetRequireITSonly(pcmcuts.cfg_require_v0_with_itsonly); fV0PhotonCut.SetRequireTPConly(pcmcuts.cfg_require_v0_with_tpconly); + + // for ML + fV0PhotonCut.SetApplyMlCuts(pcmcuts.cfg_apply_ml_cuts); + fV0PhotonCut.SetUse2DBinning(pcmcuts.cfg_use_2d_binning); + fV0PhotonCut.SetLoadMlModelsFromCCDB(pcmcuts.cfg_load_ml_models_from_ccdb); + fV0PhotonCut.SetNClassesMl(pcmcuts.cfg_nclasses_ml); + fV0PhotonCut.SetMlTimestampCCDB(pcmcuts.cfg_timestamp_ccdb); + fV0PhotonCut.SetCcdbUrl(ccdburl); + CentType mCentralityTypeMlEnum; + mCentralityTypeMlEnum = static_cast(cfgCentEstimator.value); + fV0PhotonCut.SetCentralityTypeMl(mCentralityTypeMlEnum); + fV0PhotonCut.SetCutDirMl(pcmcuts.cfg_cut_dir_ml); + fV0PhotonCut.SetMlModelPathsCCDB(pcmcuts.cfg_model_paths_ccdb); + fV0PhotonCut.SetMlOnnxFileNames(pcmcuts.cfg_onnx_file_names); + fV0PhotonCut.SetBinsPtMl(pcmcuts.cfg_bins_pt_ml); + fV0PhotonCut.SetBinsCentMl(pcmcuts.cfg_bins_cent_ml); + fV0PhotonCut.SetCutsMl(pcmcuts.cfg_cuts_ml_flat); + fV0PhotonCut.SetNamesInputFeatures(pcmcuts.cfg_input_feature_names); + fV0PhotonCut.SetLabelsBinsMl(pcmcuts.cfg_labels_bins_ml); + fV0PhotonCut.SetLabelsCutScoresMl(pcmcuts.cfg_labels_cut_scores_ml); + fV0PhotonCut.SetD_Bz(0.0f); // dummy value -> only for phiv calculation + + if (pcmcuts.cfg_apply_ml_cuts) { + fV0PhotonCut.initV0MlModels(ccdbApi); + } } template @@ -394,6 +511,28 @@ struct PCMQCMC { o2::math_utils::bringTo02Pi(phi_cp); float eta_cp = std::atanh(v0.vz() / std::sqrt(std::pow(v0.vx(), 2) + std::pow(v0.vy(), 2) + std::pow(v0.vz(), 2))); fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hsConvPoint"), v0.v0radius(), phi_cp, eta_cp); + + // BDT response histogram can be filled here when apply BDT is true + if (pcmcuts.cfg_apply_ml_cuts) { + const std::span& bdtValue = fV0PhotonCut.getBDTValue(); + float psipair = 999.f; + float phiv = 999.f; + if constexpr (requires { v0.psipair(); v0.phiv(); }) { + psipair = v0.psipair(); + phiv = v0.phiv(); + } + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hPhiVPsi"), psipair, phiv); + if (pcmcuts.cfg_nclasses_ml == 2 && bdtValue.size() == 2) { + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hBDTBackgroundScoreVsPt"), v0.pt(), bdtValue[0]); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hBDTSignalScoreVsPt"), v0.pt(), bdtValue[1]); + } else if (pcmcuts.cfg_nclasses_ml == 3 && bdtValue.size() == 3) { + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hBDTBackgroundScoreVsPt"), v0.pt(), bdtValue[0]); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hBDTPrimaryPhotonScoreVsPt"), v0.pt(), bdtValue[1]); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hBDTSecondaryPhotonScoreVsPt"), v0.pt(), bdtValue[2]); + } else if (bdtValue.size() == 1) { + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hBDTCutVsPt"), v0.pt(), bdtValue[0]); + } + } } template @@ -429,16 +568,17 @@ struct PCMQCMC { fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hRxyGen_DeltaEta"), std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2)), leg.eta() - mcleg.eta()); fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hRxyGen_DeltaPhi"), std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2)), leg.phi() - mcleg.phi()); } - + o2::framework::SliceCache v0cache; Filter collisionFilter_centrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); Filter collisionFilter_occupancy_track = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; Filter collisionFilter_occupancy_ft0c = eventcuts.cfgFT0COccupancyMin <= o2::aod::evsel::ft0cOccupancyInTimeRange && o2::aod::evsel::ft0cOccupancyInTimeRange < eventcuts.cfgFT0COccupancyMax; using FilteredMyCollisions = soa::Filtered; - Preslice perCollision = aod::v0photonkf::emeventId; - void processQCMC(FilteredMyCollisions const& collisions, MyV0Photons const& v0photons, MyMCV0Legs const&, aod::EMMCParticles const& mcparticles, aod::EMMCEvents const&) + template + void processMC(FilteredMyCollisions const& collisions, TV0Photons const& v0photons, aod::EMMCParticles const& mcparticles, MyMCV0Legs const&, aod::EMMCEvents const&) { - for (auto& collision : collisions) { + for (const auto& collision : collisions) { + initCCDB(collision); const float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { continue; @@ -452,11 +592,12 @@ struct PCMQCMC { fRegistry.fill(HIST("Event/before/hCollisionCounter"), 10.0); // accepted fRegistry.fill(HIST("Event/after/hCollisionCounter"), 10.0); // accepted - auto V0Photons_coll = v0photons.sliceBy(perCollision, collision.globalIndex()); + fV0PhotonCut.SetCentrality(centralities[cfgCentEstimator]); // set centrality for BDT response + auto V0Photons_coll = v0photons.sliceByCached(aod::v0photonkf::emeventId, collision.globalIndex(), v0cache); int ng_primary = 0, ng_wd = 0, ng_hs = 0, nee_pi0 = 0, nee_eta = 0; - for (auto& v0 : V0Photons_coll) { - auto pos = v0.posTrack_as(); - auto ele = v0.negTrack_as(); + for (const auto& v0 : V0Photons_coll) { + auto pos = v0.template posTrack_as(); + auto ele = v0.template negTrack_as(); auto posmc = pos.template emmcparticle_as(); auto elemc = ele.template emmcparticle_as(); @@ -468,7 +609,7 @@ struct PCMQCMC { fRegistry.fill(HIST("V0/candidate/hPt"), v0.pt()); fRegistry.fill(HIST("V0/candidate/hEtaPhi"), v0.phi(), v0.eta()); - for (auto& leg : {pos, ele}) { + for (const auto& leg : {pos, ele}) { fRegistry.fill(HIST("V0Leg/candidate/hPt"), leg.pt()); fRegistry.fill(HIST("V0Leg/candidate/hEtaPhi"), leg.phi(), leg.eta()); } @@ -488,19 +629,19 @@ struct PCMQCMC { if (mcphoton.isPhysicalPrimary() || mcphoton.producedByGenerator()) { fillV0Info<0>(v0, mcphoton, elemc); - for (auto& leg : {pos, ele}) { + for (const auto& leg : {pos, ele}) { fillV0LegInfo<0>(leg); } ng_primary++; } else if (IsFromWD(mcphoton.template emmcevent_as(), mcphoton, mcparticles) > 0) { fillV0Info<1>(v0, mcphoton, elemc); - for (auto& leg : {pos, ele}) { + for (const auto& leg : {pos, ele}) { fillV0LegInfo<1>(leg); } ng_wd++; } else { fillV0Info<2>(v0, mcphoton, elemc); - for (auto& leg : {pos, ele}) { + for (const auto& leg : {pos, ele}) { fillV0LegInfo<2>(leg); } ng_hs++; @@ -513,7 +654,7 @@ struct PCMQCMC { } if (mcpi0.isPhysicalPrimary() || mcpi0.producedByGenerator()) { fillV0Info<3>(v0, mcpi0, elemc); - for (auto& leg : {pos, ele}) { + for (const auto& leg : {pos, ele}) { fillV0LegInfo<3>(leg); } nee_pi0++; @@ -525,7 +666,7 @@ struct PCMQCMC { } if (mceta.isPhysicalPrimary() || mceta.producedByGenerator()) { fillV0Info<4>(v0, mceta, elemc); - for (auto& leg : {pos, ele}) { + for (const auto& leg : {pos, ele}) { fillV0LegInfo<4>(leg); } nee_eta++; @@ -540,6 +681,16 @@ struct PCMQCMC { } // end of collision loop } // end of process + void processQCMC(FilteredMyCollisions const& collisions, MyV0Photons const& v0photons, aod::EMMCParticles const& mcparticles, MyMCV0Legs const& mcv0legs, aod::EMMCEvents const& mcevents) + { + processMC(collisions, v0photons, mcparticles, mcv0legs, mcevents); + } // end of QC process + + void processQCMCML(FilteredMyCollisions const& collisions, MyV0PhotonsML const& v0photonsML, aod::EMMCParticles const& mcparticles, MyMCV0Legs const& mcv0legs, aod::EMMCEvents const& mcevents) + { + processMC(collisions, v0photonsML, mcparticles, mcv0legs, mcevents); + } // end of QC process with ML cuts + template void fillBinnedData(TBinnedData const& binned_data, const float weight = 1.f) { @@ -570,7 +721,7 @@ struct PCMQCMC { // loop over mc stack and fill histograms for pure MC truth signals // all MC tracks which belong to the MC event corresponding to the current reconstructed event - for (auto& collision : collisions) { + for (const auto& collision : collisions) { const float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { continue; @@ -586,12 +737,12 @@ struct PCMQCMC { // LOGF(info, "mccollision.globalIndex() = %d", mccollision.globalIndex()); auto mctracks_coll = mcparticles.sliceBy(perMcCollision, mccollision.globalIndex()); - for (auto& mctrack : mctracks_coll) { + for (const auto& mctrack : mctracks_coll) { if (std::fabs(mctrack.y()) > pcmcuts.cfg_max_eta_v0) { continue; } - if (std::abs(mctrack.pdgCode()) == 22 && (mctrack.isPhysicalPrimary() || mctrack.producedByGenerator())) { + if (std::abs(mctrack.pdgCode()) == PDG_t::kGamma && (mctrack.isPhysicalPrimary() || mctrack.producedByGenerator())) { auto daughter = mcparticles.iteratorAt(mctrack.daughtersIds()[0]); // choose ele or pos. float rxy_gen_e = std::sqrt(std::pow(daughter.vx(), 2) + std::pow(daughter.vy(), 2)); float phi_cp = std::atan2(daughter.vy(), daughter.vx()); @@ -621,6 +772,7 @@ struct PCMQCMC { PROCESS_SWITCH(PCMQCMC, processQCMC, "run PCM QC in MC", false); PROCESS_SWITCH(PCMQCMC, processGen, "run generated information", false); + PROCESS_SWITCH(PCMQCMC, processQCMCML, "run PCM QC in MC with ML cuts", false); PROCESS_SWITCH(PCMQCMC, processDummy, "Dummy function", true); }; From cd4161fbcb6675f7b5894c3af57b2321594b3ce7 Mon Sep 17 00:00:00 2001 From: AlexianL <123153896+AlexianL@users.noreply.github.com> Date: Sun, 22 Feb 2026 10:42:50 +0100 Subject: [PATCH 016/347] [PWGLF,PWGMM] add mftReassociationValidation.cxx task (#15054) --- PWGMM/Mult/Tasks/CMakeLists.txt | 6 + .../Mult/Tasks/mftReassociationValidation.cxx | 1124 +++++++++++++++++ 2 files changed, 1130 insertions(+) create mode 100644 PWGMM/Mult/Tasks/mftReassociationValidation.cxx diff --git a/PWGMM/Mult/Tasks/CMakeLists.txt b/PWGMM/Mult/Tasks/CMakeLists.txt index aae28c5eef1..b9e85153285 100644 --- a/PWGMM/Mult/Tasks/CMakeLists.txt +++ b/PWGMM/Mult/Tasks/CMakeLists.txt @@ -39,6 +39,12 @@ o2physics_add_dpl_workflow(dndeta-mft-pbpb PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::AnalysisCCDB COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(mft-reassociation-validation + SOURCES mftReassociationValidation.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::AnalysisCCDB + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(flatenicity-fv0 SOURCES flatenicityFV0.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore diff --git a/PWGMM/Mult/Tasks/mftReassociationValidation.cxx b/PWGMM/Mult/Tasks/mftReassociationValidation.cxx new file mode 100644 index 00000000000..7964859f289 --- /dev/null +++ b/PWGMM/Mult/Tasks/mftReassociationValidation.cxx @@ -0,0 +1,1124 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file mftReassociationValidation.cxx +/// \brief validation task for MFT DCAxy and DCAxyz reassociation +/// \author Alexian Lejeune , Czech Technical University in Prague + +#include "PWGMM/Mult/DataModel/bestCollisionTable.h" + +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/RCTSelectionFlags.h" +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/CollisionAssociationTables.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace o2; +using namespace o2::aod::rctsel; +using namespace o2::aod::track; +using namespace o2::constants::math; +using namespace o2::framework; +using namespace o2::framework::expressions; + +enum Reassociation2dMftTracks { + AllAmbiguousTracksAfterTrackSelectionsFor2d = 0, + NotReassociated2dMftTracks, + Reassociated2dMftTracks, + NReassociation2dMftTracksSteps +}; + +enum Reassociation3dMftTracks { + AllAmbiguousTracksAfterTrackSelectionsFor3d = 0, + NotReassociated3dMftTracks, + Reassociated3dMftTracks, + NReassociation3dMftTracksSteps +}; + +enum MatchedToTrueCollisionStep { + AllTracks = 0, + IsNotMatchedToTrueCollision, + IsMatchedToTrueCollision, + NMatchedToTrueCollisionSteps +}; + +enum DataType { + Data, + Mc +}; + +enum SpecificEventSelectionStep { + AllEventsPrecise = 0, + HasMcCollision, + IsSel8, + IsNoSameBunchPileup, + IsGoodItsLayersAll, + IsGoodZvtxFT0vsPV, + IsNoCollInRofStandard, + IsNoCollInRofStrict, + IsNoCollInTimeRangeStandard, + IsNoCollInTimeRangeStrict, + IsNoHighMultCollInPrevRof, + IsRctFlagChecked, + NSpecificEventSelectionSteps +}; + +enum MonteCarloEventSelectionStep { + AllMonteCarloEvents = 0, + MonteCarloEventsAfterEventSelection, + HasMonteCarloCollision, + HasNotMonteCarloCollision, + NMonteCarloEventSelectionSteps +}; + +enum MonteCarloTrackSelectionStep { + AllMonteCarloTracks = 0, + MonteCarloTracksAfterTrackSelection, + HasMonteCarloParticle, + HasNotMonteCarloParticle, + NMonteCarloTrackSelectionSteps +}; + +enum MftTrackAmbiguityStep { + AllMftTracks = 0, + AfterTrackSelection, + NumberOfAmbiguousTracks, + NumberOfNonAmbiguousTracks, + NMftAmbiguitySteps +}; + +enum MftAmbiguousAndMatchedToTrueCollisionStep { + IsAmbiguous = 0, + IsAmbiguousAndMatchedToTrueCollision, + IsAmbiguousAndNotMatchedToTrueCollision, + NMftAmbiguousAndMatchedToTrueCollisionSteps +}; + +enum MftNonAmbiguousAndMatchedToTrueCollisionStep { + IsNonAmbiguous = 0, + IsNonAmbiguousAndMatchedToTrueCollision, + IsNonAmbiguousAndNotMatchedToTrueCollision, + NMftNonAmbiguousAndMatchedToTrueCollisionSteps +}; + +enum Mft2dReassociatedAndMatchedToTrueCollisionStep { + Is2dReassociated = 0, + Is2dReassociatedAndMatchedToTrueCollision, + Is2dReassociatedAndNotMatchedToTrueCollision, + NMft2dReassociatedAndMatchedToTrueCollisionSteps +}; + +enum Mft3dReassociatedAndMatchedToTrueCollisionStep { + Is3dReassociated = 0, + Is3dReassociatedAndMatchedToTrueCollision, + Is3dReassociatedAndNotMatchedToTrueCollision, + NMft3dReassociatedAndMatchedToTrueCollisionSteps +}; + +enum MftNot2dReassociatedAndMatchedToTrueCollisionStep { + IsNot2dReassociated = 0, + IsNot2dReassociatedAndMatchedToTrueCollision, + IsNot2dReassociatedAndNotMatchedToTrueCollision, + NMftNot2dReassociatedAndMatchedToTrueCollisionSteps +}; + +enum MftNot3dReassociatedAndMatchedToTrueCollisionStep { + IsNot3dReassociated = 0, + IsNot3dReassociatedAndMatchedToTrueCollision, + IsNot3dReassociatedAndNotMatchedToTrueCollision, + NMftNot3dReassociatedAndMatchedToTrueCollisionSteps +}; + +enum MftTrackSelectionStep { + NoSelection = 0, + Eta, + Cluster, + Pt, + NMftTrackSelectionSteps +}; + +enum MultiplicityEstimators { + MultNTracksPV = 0, + MultNumContrib, + MultFT0C, + MultFT0M +}; + +static constexpr std::string_view WhatDataType[] = {"Data/", "MC/"}; +static constexpr std::string_view WhatMultiplicityEstimator[] = {"multNTracksPV", "multNumContrib", "multFT0C", "multFT0M"}; +std::unordered_map recoVtxX; +std::unordered_map recoVtxY; +std::unordered_map recoVtxZ; +std::unordered_map recoMcCollisionId; + +struct MftReassociationValidation { + + struct : ConfigurableGroup { + std::string prefix = "ConfigCcdb_group"; + Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "Address of the CCDB to browse"}; + Configurable noLaterThan{"noLaterThan", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "Latest acceptable timestamp of creation for the object"}; + } configCcdb; + + // configurables for processing options + + struct : ConfigurableGroup { + std::string prefix = "ConfigTask_group"; + Configurable centralityBinsForMc{"centralityBinsForMc", false, "falsce = OFF, true = ON for data like multiplicity/centrality bins for MC steps"}; + } configTask; + + // configurables for collisions + struct : ConfigurableGroup { + std::string prefix = "ConfigCollision_group"; + Configurable isApplyGoodItsLayersAll{"isApplyGoodItsLayersAll", false, "Enable GoodITSLayersAll"}; + Configurable isApplyGoodZvtxFT0vsPV{"isApplyGoodZvtxFT0vsPV", false, "Enable GoodZvtxFT0vsPV cut"}; + Configurable isApplySameBunchPileup{"isApplySameBunchPileup", false, "Enable SameBunchPileup cut"}; + Configurable maxMultiplicity{"maxMultiplicity", 300, "maximum multiplicity selection for collision"}; + Configurable minMultiplicity{"minMultiplicity", 0, "minimum multiplicity selection for collision"}; + Configurable multiplicityEstimator{"multiplicityEstimator", 0, "0: multNTracksPV, 1: numContrib, 2: multFT0C, 3: multFT0M, 4: centFT0C, 5: centFT0CVariants1s, 6: centFT0M, 7: centFV0A, 8: centNTracksPV, 9: centNGlobal, 10: centMFT"}; + Configurable isApplyNoCollInTimeRangeStrict{"isApplyNoCollInTimeRangeStrict", false, ""}; + Configurable isApplyNoCollInTimeRangeStandard{"isApplyNoCollInTimeRangeStandard", false, ""}; + Configurable isApplyNoCollInRofStrict{"isApplyNoCollInRofStrict", false, ""}; + Configurable isApplyNoCollInRofStandard{"isApplyNoCollInRofStandard", false, ""}; + Configurable isApplyNoHighMultCollInPrevRof{"isApplyNoHighMultCollInPrevRof", false, ""}; + Configurable zVertexMax{"zVertexMax", 10.0f, "Accepted z-vertex range"}; + Configurable requireRCTFlagChecker{"requireRCTFlagChecker", false, "Check event quality in run condition table"}; + Configurable requireCorrelationAnalysisRCTFlagChecker{"requireCorrelationAnalysisRCTFlagChecker", false, "Check event quality in run condition table for correlation analysis"}; + Configurable setRCTFlagCheckerLabel{"setRCTFlagCheckerLabel", "CBT_muon_global", "Evt sel: RCT flag checker label"}; + Configurable requireRCTFlagCheckerLimitAcceptanceAsBad{"requireRCTFlagCheckerLimitAcceptanceAsBad", true, "Evt sel: RCT flag checker treat Limited Acceptance As Bad"}; + Configurable requireZDCCheck{"requireZDCCheck", false, "Evt sel: RCT flag checker ZDC check"}; + } configCollision; + + // configurables for MFT tracks + struct : ConfigurableGroup { + std::string prefix = "ConfigMft_group"; + Configurable cutBestCollisionId{"cutBestCollisionId", 0, "cut on the best collision Id used in a filter"}; + Configurable etaMftTrackMax{"etaMftTrackMax", -2.4f, "Maximum value for the eta of MFT tracks when used in cut function"}; + Configurable etaMftTrackMin{"etaMftTrackMin", -3.36f, "Minimum value for the eta of MFT tracks when used in cut function"}; + Configurable etaMftTrackMaxFilter{"etaMftTrackMaxFilter", -2.0f, "Maximum value for the eta of MFT tracks when used in filter"}; + Configurable etaMftTrackMinFilter{"etaMftTrackMinFilter", -3.9f, "Minimum value for the eta of MFT tracks when used in filter"}; + Configurable mftMaxDCAxy{"mftMaxDCAxy", 2.0f, "Cut on dcaXY for MFT tracks"}; + Configurable mftMaxDCAz{"mftMaxDCAz", 2.0f, "Cut on dcaZ for MFT tracks"}; + Configurable nClustersMftTrack{"nClustersMftTrack", 5, "Minimum number of clusters for the reconstruction of MFT tracks"}; + Configurable ptMftTrackMax{"ptMftTrackMax", 10.0f, "max value of MFT tracks pT when used in cut function"}; + Configurable ptMftTrackMin{"ptMftTrackMin", 0.f, "min value of MFT tracks pT when used in cut function"}; + Configurable useMftPtCut{"useMftPtCut", false, "if true, use the Mft pt function cut"}; + } configMft; + + TF1* fPtDepDCAxy = nullptr; + + SliceCache cache; + Service pdg; + Service ccdb; + o2::ccdb::CcdbApi ccdbApi; + RCTFlagsChecker rctChecker; + RCTFlagsChecker correlationAnalysisRctChecker{kFT0Bad, kITSBad, kTPCBadTracking, kMFTBad}; + std::array, MatchedToTrueCollisionStep::NMatchedToTrueCollisionSteps> hZVtxDiffAmbiguousTracks; + std::array, MatchedToTrueCollisionStep::NMatchedToTrueCollisionSteps> hZVtxDiffNonAmbiguousTracks; + std::array, MatchedToTrueCollisionStep::NMatchedToTrueCollisionSteps> hZVtxDiff2dReassociatedTracks; + std::array, MatchedToTrueCollisionStep::NMatchedToTrueCollisionSteps> hZVtxDiffNot2dReassociatedTracks; + std::array, MatchedToTrueCollisionStep::NMatchedToTrueCollisionSteps> hZVtxDiff3dReassociatedTracks; + std::array, MatchedToTrueCollisionStep::NMatchedToTrueCollisionSteps> hZVtxDiffNot3dReassociatedTracks; + + // ========================= + // using declarations : DATA + // ========================= + + using FilteredCollisionsWSelMult = soa::Filtered>; + using FilteredMftTracks = soa::Filtered; + using FilteredMftTracksWColls = soa::Filtered>; + + // ========================= + // using declarations : MONTE-CARLO + // ========================= + + using FilteredCollisionsWSelMultMcLabels = soa::Filtered>; + using FilteredMftTracksWCollsMcLabels = soa::Filtered>; + // using MftReasso3dTracksWCollsMcLabels = soa::Join; + // using MftReasso2dTracksWCollsMcLabels = soa::Join; + // using MftReasso2dTracksWCollsMcLabels = soa::Join; + // using MftReasso3dTracksWCollsMcLabels = soa::Join; + using FilteredMcParticles = soa::Filtered; + + // ========================= + // Filters & partitions : DATA + // ========================= + + // Collision filters + Filter collisionVtxZFilter = nabs(aod::collision::posZ) < configCollision.zVertexMax; + + Filter mftTrackEtaFilter = ((aod::fwdtrack::eta < configMft.etaMftTrackMaxFilter) && (aod::fwdtrack::eta > configMft.etaMftTrackMinFilter)); + + Filter mftTrackCollisionIdFilter = (aod::fwdtrack::bestCollisionId >= 0); + Filter mftTrackDcaXYFilter = (nabs(aod::fwdtrack::bestDCAXY) < configMft.mftMaxDCAxy); + // Filter mftTrackDcaZFilter = (nabs(aod::fwdtrack::bestDCAZ) < configMft.mftMaxDCAz); + + // ========================= + // Filters & partitions : MONTE-CARLO + // ========================= + + Filter primaries = (aod::mcparticle::flags & (uint8_t)o2::aod::mcparticle::enums::PhysicalPrimary) == (uint8_t)o2::aod::mcparticle::enums::PhysicalPrimary && (aod::mcparticle::eta < configMft.etaMftTrackMaxFilter) && (aod::mcparticle::eta > configMft.etaMftTrackMinFilter); + + Partition mcParticlesSample = (aod::mcparticle::eta < configMft.etaMftTrackMaxFilter) && (aod::mcparticle::eta > configMft.etaMftTrackMinFilter); + + // ========================= + // Preslice : DATA + // ========================= + + Preslice perColMftTracks = o2::aod::fwdtrack::collisionId; + + struct : ConfigurableGroup { + std::string prefix = "ConfigAxis_group"; + ConfigurableAxis axisEta{"axisEta", {48, -4, -2}, "eta axis for MFT histograms"}; + ConfigurableAxis axisDcaX{"axisDcaX", {800, -1., 1.}, "DCAx binning (cm)"}; + ConfigurableAxis axisDcaY{"axisDcaY", {800, -1., 1.}, "DCAy binning (cm)"}; + ConfigurableAxis axisDcaZ{"axisDcaZ", {800, -1., 1.}, "DCAz binning (cm)"}; + ConfigurableAxis axisMultiplicity{"axisMultiplicity", {VARIABLE_WIDTH, 0, 5, 10, 20, 30, 40, 50, 100.1}, "multiplicity axis for histograms"}; + ConfigurableAxis axisPhi{"axisPhi", {72, 0, TwoPI}, "phi axis for histograms"}; + ConfigurableAxis axisPt{"axisPt", {72, 0, 36}, "pt axis for histograms"}; + ConfigurableAxis axisVertex{"axisVertex", {20, -10, 10}, "vertex axis for histograms"}; + ConfigurableAxis axisVertexEfficiency{"axisVertexEfficiency", {1, -10, 10}, "vertex axis for efficiency histograms"}; + } configAxis; + + HistogramRegistry registry{"registry"}; + + template + void addMftHistograms() + { + registry.add(Form("%shAmbiguityOfMftTracks", WhatDataType[DataType].data()), "hAmbiguityOfMftTracks", {HistType::kTH1D, {{MftTrackAmbiguityStep::NMftAmbiguitySteps, -0.5, +MftTrackAmbiguityStep::NMftAmbiguitySteps - 0.5}}}); + std::string labelsAmbiguityOfMftTracks[MftTrackAmbiguityStep::NMftAmbiguitySteps]; + labelsAmbiguityOfMftTracks[MftTrackAmbiguityStep::AllMftTracks] = "all MFT tracks"; + labelsAmbiguityOfMftTracks[MftTrackAmbiguityStep::AfterTrackSelection] = "MFT tracks after selection"; + labelsAmbiguityOfMftTracks[MftTrackAmbiguityStep::NumberOfAmbiguousTracks] = "how much tracks are ambigous"; + labelsAmbiguityOfMftTracks[MftTrackAmbiguityStep::NumberOfNonAmbiguousTracks] = "how much tracks are non-ambiguous"; + registry.get(HIST(WhatDataType[DataType]) + HIST("hAmbiguityOfMftTracks"))->SetMinimum(0); + + for (int iBin = 0; iBin < MftTrackAmbiguityStep::NMftAmbiguitySteps; iBin++) { + registry.get(HIST(WhatDataType[DataType]) + HIST("hAmbiguityOfMftTracks"))->GetXaxis()->SetBinLabel(iBin + 1, labelsAmbiguityOfMftTracks[iBin].data()); + } + + registry.add(Form("%shMftTracksSelection", WhatDataType[DataType].data()), "hMftTracksSelection", {HistType::kTH1D, {{MftTrackSelectionStep::NMftTrackSelectionSteps, -0.5, +MftTrackSelectionStep::NMftTrackSelectionSteps - 0.5}}}); + std::string labelsMftTracksSelection[MftTrackSelectionStep::NMftTrackSelectionSteps]; + labelsMftTracksSelection[MftTrackSelectionStep::NoSelection] = "all MFT tracks"; + labelsMftTracksSelection[MftTrackSelectionStep::Eta] = "MFT tracks after eta selection"; + labelsMftTracksSelection[MftTrackSelectionStep::Cluster] = "MFT tracks after clusters selection"; + labelsMftTracksSelection[MftTrackSelectionStep::Pt] = "MFT tracks after pT selection"; + registry.get(HIST(WhatDataType[DataType]) + HIST("hMftTracksSelection"))->SetMinimum(0); + + for (int iBin = 0; iBin < MftTrackSelectionStep::NMftTrackSelectionSteps; iBin++) { + registry.get(HIST(WhatDataType[DataType]) + HIST("hMftTracksSelection"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMftTracksSelection[iBin].data()); + } + + registry.add(Form("%shReassociation2dMftTracks", WhatDataType[DataType].data()), "hReassociation2dMftTracks", {HistType::kTH1D, {{Reassociation2dMftTracks::NReassociation2dMftTracksSteps, -0.5, +Reassociation2dMftTracks::NReassociation2dMftTracksSteps - 0.5}}}); + std::string labelsReassociation2dMftTracks[Reassociation2dMftTracks::NReassociation2dMftTracksSteps]; + labelsReassociation2dMftTracks[Reassociation2dMftTracks::AllAmbiguousTracksAfterTrackSelectionsFor2d] = "Ambiguous MFT tracks after track selection"; + labelsReassociation2dMftTracks[Reassociation2dMftTracks::NotReassociated2dMftTracks] = "Not reassociated MFT tracks by DCAxy method"; + labelsReassociation2dMftTracks[Reassociation2dMftTracks::Reassociated2dMftTracks] = "Reassociated MFT tracks by DCAxy method"; + registry.get(HIST(WhatDataType[DataType]) + HIST("hReassociation2dMftTracks"))->SetMinimum(0); + + for (int iBin = 0; iBin < Reassociation2dMftTracks::NReassociation2dMftTracksSteps; iBin++) { + registry.get(HIST(WhatDataType[DataType]) + HIST("hReassociation2dMftTracks"))->GetXaxis()->SetBinLabel(iBin + 1, labelsReassociation2dMftTracks[iBin].data()); + } + + registry.add(Form("%shReassociation3dMftTracks", WhatDataType[DataType].data()), "hReassociation3dMftTracks", {HistType::kTH1D, {{Reassociation3dMftTracks::NReassociation3dMftTracksSteps, -0.5, +Reassociation3dMftTracks::NReassociation3dMftTracksSteps - 0.5}}}); + std::string labelsReassociation3dMftTracks[Reassociation3dMftTracks::NReassociation3dMftTracksSteps]; + labelsReassociation3dMftTracks[Reassociation3dMftTracks::AllAmbiguousTracksAfterTrackSelectionsFor3d] = "Ambiguous MFT tracks after track selection"; + labelsReassociation3dMftTracks[Reassociation3dMftTracks::NotReassociated3dMftTracks] = "Not reassociated MFT tracks by DCAxyz method"; + labelsReassociation3dMftTracks[Reassociation3dMftTracks::Reassociated3dMftTracks] = "Reassociated MFT tracks by DCAxyz method"; + registry.get(HIST(WhatDataType[DataType]) + HIST("hReassociation3dMftTracks"))->SetMinimum(0); + + for (int iBin = 0; iBin < Reassociation3dMftTracks::NReassociation3dMftTracksSteps; iBin++) { + registry.get(HIST(WhatDataType[DataType]) + HIST("hReassociation3dMftTracks"))->GetXaxis()->SetBinLabel(iBin + 1, labelsReassociation3dMftTracks[iBin].data()); + } + } + + void addMftMonteCarloHistograms() + { + // AmbiguousTracks ZVtxDiff dist. (contains matched to true and not matched to true collision) + hZVtxDiffAmbiguousTracks[MatchedToTrueCollisionStep::AllTracks] = registry.add("MC/hZVtxDiffAmbiguousTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + // AmbiguousTracks NOT matched to true collisions ZVtxDiff dist. + hZVtxDiffAmbiguousTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision] = registry.add("MC/hZVtxDiffAmbiguousTracksNotMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + // AmbiguousTracks matched to true collisions ZVtxDiff dist. + hZVtxDiffAmbiguousTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision] = registry.add("MC/hZVtxDiffAmbiguousTracksMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + + hZVtxDiffNonAmbiguousTracks[MatchedToTrueCollisionStep::AllTracks] = registry.add("MC/hZVtxDiffNonAmbiguousTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + hZVtxDiffNonAmbiguousTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision] = registry.add("MC/hZVtxDiffNonAmbiguousTracksNotMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + hZVtxDiffNonAmbiguousTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision] = registry.add("MC/hZVtxDiffNonAmbiguousTrackMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + + hZVtxDiff2dReassociatedTracks[MatchedToTrueCollisionStep::AllTracks] = registry.add("MC/hZVtxDiff2dReassociatedTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + hZVtxDiff2dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision] = registry.add("MC/hZVtxDiff2dReassociatedTracksNotMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + hZVtxDiff2dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision] = registry.add("MC/hZVtxDiff2dReassociatedTracksMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + + hZVtxDiffNot2dReassociatedTracks[MatchedToTrueCollisionStep::AllTracks] = registry.add("MC/hZVtxDiffNot2dReassociatedTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + hZVtxDiffNot2dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision] = registry.add("MC/hZVtxDiffNot2dReassociatedTracksNotMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + hZVtxDiffNot2dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision] = registry.add("MC/hZVtxDiffNot2dReassociatedTracksMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + + hZVtxDiff3dReassociatedTracks[MatchedToTrueCollisionStep::AllTracks] = registry.add("MC/hZVtxDiff3dReassociatedTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + hZVtxDiff3dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision] = registry.add("MC/hZVtxDiff3dReassociatedTracksNotMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + hZVtxDiff3dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision] = registry.add("MC/hZVtxDiff3dReassociatedTracksMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + + hZVtxDiffNot3dReassociatedTracks[MatchedToTrueCollisionStep::AllTracks] = registry.add("MC/hZVtxDiffNot3dReassociatedTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + hZVtxDiffNot3dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision] = registry.add("MC/hZVtxDiffNot3dReassociatedTracksNotMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + hZVtxDiffNot3dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision] = registry.add("MC/hZVtxDhZVtxDiffNot3dReassociatedTracksMatchedToTrueCollisioniffAmbiguousTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + + registry.add("MC/hIsAmbiguousTrackMatchedToTrueCollision", "hIsAmbiguousTrackMatchedToTrueCollision", {HistType::kTH1D, {{MftAmbiguousAndMatchedToTrueCollisionStep::NMftAmbiguousAndMatchedToTrueCollisionSteps, -0.5, +MftAmbiguousAndMatchedToTrueCollisionStep::NMftAmbiguousAndMatchedToTrueCollisionSteps - 0.5}}}); + std::string labelsMftAmbiguousAndMatchedToTrueCollisionStep[MftAmbiguousAndMatchedToTrueCollisionStep::NMftAmbiguousAndMatchedToTrueCollisionSteps]; + labelsMftAmbiguousAndMatchedToTrueCollisionStep[MftAmbiguousAndMatchedToTrueCollisionStep::IsAmbiguous] = "number of MFT ambiguous tracks"; + labelsMftAmbiguousAndMatchedToTrueCollisionStep[MftAmbiguousAndMatchedToTrueCollisionStep::IsAmbiguousAndMatchedToTrueCollision] = "number of MFT ambiguous tracks matched to true collision"; + labelsMftAmbiguousAndMatchedToTrueCollisionStep[MftAmbiguousAndMatchedToTrueCollisionStep::IsAmbiguousAndNotMatchedToTrueCollision] = "number of MFT ambiguous tracks NOT matched to true collision"; + registry.get(HIST("MC/hIsAmbiguousTrackMatchedToTrueCollision"))->SetMinimum(0); + + for (int iBin = 0; iBin < MftAmbiguousAndMatchedToTrueCollisionStep::NMftAmbiguousAndMatchedToTrueCollisionSteps; iBin++) { + registry.get(HIST("MC/hIsAmbiguousTrackMatchedToTrueCollision"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMftAmbiguousAndMatchedToTrueCollisionStep[iBin].data()); + } + + registry.add("MC/hIsNonAmbiguousTrackMatchedToTrueCollision", "hIsNonAmbiguousTrackMatchedToTrue", {HistType::kTH1D, {{MftNonAmbiguousAndMatchedToTrueCollisionStep::NMftNonAmbiguousAndMatchedToTrueCollisionSteps, -0.5, +MftNonAmbiguousAndMatchedToTrueCollisionStep::NMftNonAmbiguousAndMatchedToTrueCollisionSteps - 0.5}}}); + std::string labelsMftNonAmbiguousAndMatchedToTrueCollisionStep[MftNonAmbiguousAndMatchedToTrueCollisionStep::NMftNonAmbiguousAndMatchedToTrueCollisionSteps]; + labelsMftNonAmbiguousAndMatchedToTrueCollisionStep[MftNonAmbiguousAndMatchedToTrueCollisionStep::IsNonAmbiguous] = "number of MFT Non ambiguous tracks"; + labelsMftNonAmbiguousAndMatchedToTrueCollisionStep[MftNonAmbiguousAndMatchedToTrueCollisionStep::IsNonAmbiguousAndMatchedToTrueCollision] = "number of MFT Non ambiguous tracks matched to true collision"; + labelsMftNonAmbiguousAndMatchedToTrueCollisionStep[MftNonAmbiguousAndMatchedToTrueCollisionStep::IsNonAmbiguousAndNotMatchedToTrueCollision] = "number of MFT Non ambiguous tracks NOT matched to true collision"; + registry.get(HIST("MC/hIsNonAmbiguousTrackMatchedToTrueCollision"))->SetMinimum(0); + + for (int iBin = 0; iBin < MftNonAmbiguousAndMatchedToTrueCollisionStep::NMftNonAmbiguousAndMatchedToTrueCollisionSteps; iBin++) { + registry.get(HIST("MC/hIsNonAmbiguousTrackMatchedToTrueCollision"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMftNonAmbiguousAndMatchedToTrueCollisionStep[iBin].data()); + } + + registry.add("MC/Is2dReassociatedAndMatchedToTrueCollision", "Is2dReassociatedAndMatchedToTrueCollision", {HistType::kTH1D, {{Mft2dReassociatedAndMatchedToTrueCollisionStep::NMft2dReassociatedAndMatchedToTrueCollisionSteps, -0.5, +Mft2dReassociatedAndMatchedToTrueCollisionStep::NMft2dReassociatedAndMatchedToTrueCollisionSteps - 0.5}}}); + std::string labelsMft2dReassociatedAndMatchedToTrueCollisionStep[Mft2dReassociatedAndMatchedToTrueCollisionStep::NMft2dReassociatedAndMatchedToTrueCollisionSteps]; + labelsMft2dReassociatedAndMatchedToTrueCollisionStep[Mft2dReassociatedAndMatchedToTrueCollisionStep::Is2dReassociated] = "number of MFT 2d reassociated tracks"; + labelsMft2dReassociatedAndMatchedToTrueCollisionStep[Mft2dReassociatedAndMatchedToTrueCollisionStep::Is2dReassociatedAndMatchedToTrueCollision] = "number of MFT 2d reassociated tracks matched to true collision"; + labelsMft2dReassociatedAndMatchedToTrueCollisionStep[Mft2dReassociatedAndMatchedToTrueCollisionStep::Is2dReassociatedAndNotMatchedToTrueCollision] = "number of MFT 2d reassociated tracks NOT matched to true collision"; + registry.get(HIST("MC/Is2dReassociatedAndMatchedToTrueCollision"))->SetMinimum(0); + + for (int iBin = 0; iBin < Mft2dReassociatedAndMatchedToTrueCollisionStep::NMft2dReassociatedAndMatchedToTrueCollisionSteps; iBin++) { + registry.get(HIST("MC/Is2dReassociatedAndMatchedToTrueCollision"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMft2dReassociatedAndMatchedToTrueCollisionStep[iBin].data()); + } + + registry.add("MC/IsNot2dReassociatedAndMatchedToTrueCollision", "IsNot2dReassociatedAndMatchedToTrueCollision", {HistType::kTH1D, {{MftNot2dReassociatedAndMatchedToTrueCollisionStep::NMftNot2dReassociatedAndMatchedToTrueCollisionSteps, -0.5, +MftNot2dReassociatedAndMatchedToTrueCollisionStep::NMftNot2dReassociatedAndMatchedToTrueCollisionSteps - 0.5}}}); + std::string labelsMftNot2dReassociatedAndMatchedToTrueCollisionStep[MftNot2dReassociatedAndMatchedToTrueCollisionStep::NMftNot2dReassociatedAndMatchedToTrueCollisionSteps]; + labelsMftNot2dReassociatedAndMatchedToTrueCollisionStep[MftNot2dReassociatedAndMatchedToTrueCollisionStep::IsNot2dReassociated] = "number of MFT NOT 2d reassociated tracks"; + labelsMftNot2dReassociatedAndMatchedToTrueCollisionStep[MftNot2dReassociatedAndMatchedToTrueCollisionStep::IsNot2dReassociatedAndMatchedToTrueCollision] = "number of MFT NOT 2d reassociated tracks matched to true collision"; + labelsMftNot2dReassociatedAndMatchedToTrueCollisionStep[MftNot2dReassociatedAndMatchedToTrueCollisionStep::IsNot2dReassociatedAndNotMatchedToTrueCollision] = "number of MFT NOT 2d reassociated tracks NOT matched to true collision"; + registry.get(HIST("MC/IsNot2dReassociatedAndMatchedToTrueCollision"))->SetMinimum(0); + + for (int iBin = 0; iBin < MftNot2dReassociatedAndMatchedToTrueCollisionStep::NMftNot2dReassociatedAndMatchedToTrueCollisionSteps; iBin++) { + registry.get(HIST("MC/IsNot2dReassociatedAndMatchedToTrueCollision"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMftNot2dReassociatedAndMatchedToTrueCollisionStep[iBin].data()); + } + + registry.add("MC/Is3dReassociatedAndMatchedToTrueCollision", "Is3dReassociatedAndMatchedToTrueCollision", {HistType::kTH1D, {{Mft3dReassociatedAndMatchedToTrueCollisionStep::NMft3dReassociatedAndMatchedToTrueCollisionSteps, -0.5, +Mft3dReassociatedAndMatchedToTrueCollisionStep::NMft3dReassociatedAndMatchedToTrueCollisionSteps - 0.5}}}); + std::string labelsMft3dReassociatedAndMatchedToTrueCollisionStep[Mft3dReassociatedAndMatchedToTrueCollisionStep::NMft3dReassociatedAndMatchedToTrueCollisionSteps]; + labelsMft3dReassociatedAndMatchedToTrueCollisionStep[Mft3dReassociatedAndMatchedToTrueCollisionStep::Is3dReassociated] = "number of MFT 3d reassociated tracks"; + labelsMft3dReassociatedAndMatchedToTrueCollisionStep[Mft3dReassociatedAndMatchedToTrueCollisionStep::Is3dReassociatedAndMatchedToTrueCollision] = "number of MFT 3d reassociated tracks matched to true collision"; + labelsMft3dReassociatedAndMatchedToTrueCollisionStep[Mft3dReassociatedAndMatchedToTrueCollisionStep::Is3dReassociatedAndNotMatchedToTrueCollision] = "number of MFT 3d reassociated tracks NOT matched to true collision"; + registry.get(HIST("MC/Is3dReassociatedAndMatchedToTrueCollision"))->SetMinimum(0); + + for (int iBin = 0; iBin < Mft3dReassociatedAndMatchedToTrueCollisionStep::NMft3dReassociatedAndMatchedToTrueCollisionSteps; iBin++) { + registry.get(HIST("MC/Is3dReassociatedAndMatchedToTrueCollision"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMft3dReassociatedAndMatchedToTrueCollisionStep[iBin].data()); + } + + registry.add("MC/IsNot3dReassociatedAndMatchedToTrueCollision", "IsNot3dReassociatedAndMatchedToTrueCollision", {HistType::kTH1D, {{MftNot3dReassociatedAndMatchedToTrueCollisionStep::NMftNot3dReassociatedAndMatchedToTrueCollisionSteps, -0.5, +MftNot3dReassociatedAndMatchedToTrueCollisionStep::NMftNot3dReassociatedAndMatchedToTrueCollisionSteps - 0.5}}}); + std::string labelsMftNot3dReassociatedAndMatchedToTrueCollisionStep[MftNot3dReassociatedAndMatchedToTrueCollisionStep::NMftNot3dReassociatedAndMatchedToTrueCollisionSteps]; + labelsMftNot3dReassociatedAndMatchedToTrueCollisionStep[MftNot3dReassociatedAndMatchedToTrueCollisionStep::IsNot3dReassociated] = "number of MFT NOT 3d reassociated tracks"; + labelsMftNot3dReassociatedAndMatchedToTrueCollisionStep[MftNot3dReassociatedAndMatchedToTrueCollisionStep::IsNot3dReassociatedAndMatchedToTrueCollision] = "number of MFT NOT 3d reassociated tracks matched to true collision"; + labelsMftNot3dReassociatedAndMatchedToTrueCollisionStep[MftNot3dReassociatedAndMatchedToTrueCollisionStep::IsNot3dReassociatedAndNotMatchedToTrueCollision] = "number of MFT NOT 3d reassociated tracks NOT matched to true collision"; + registry.get(HIST("MC/IsNot3dReassociatedAndMatchedToTrueCollision"))->SetMinimum(0); + + for (int iBin = 0; iBin < MftNot3dReassociatedAndMatchedToTrueCollisionStep::NMftNot3dReassociatedAndMatchedToTrueCollisionSteps; iBin++) { + registry.get(HIST("MC/IsNot3dReassociatedAndMatchedToTrueCollision"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMftNot3dReassociatedAndMatchedToTrueCollisionStep[iBin].data()); + } + } + + // ========================= + // init() + // ========================= + void init(InitContext&) + { + ccdb->setURL(configCcdb.ccdbUrl); + ccdbApi.init("http://alice-ccdb.cern.ch"); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); + rctChecker.init(configCollision.setRCTFlagCheckerLabel, configCollision.requireZDCCheck, configCollision.requireRCTFlagCheckerLimitAcceptanceAsBad); + correlationAnalysisRctChecker.init({kFT0Bad, kITSBad, kTPCBadTracking, kMFTBad}, configCollision.requireZDCCheck, configCollision.requireRCTFlagCheckerLimitAcceptanceAsBad); + + // ========================= + // Event histograms + // ========================= + + registry.add("Data/hVtxZ", "v_{z} (cm)", {HistType::kTH1D, {configAxis.axisVertex}}); + // registry.add("Data/hNTracks", "", {HistType::kTH1F, {configAxis.axisMultiplicity}}); + registry.add(Form("Data/hMultiplicity_%s", WhatMultiplicityEstimator[configCollision.multiplicityEstimator].data()), "", {HistType::kTH1D, {configAxis.axisMultiplicity}}); + + registry.add("hPreciseEventCounter", "hPreciseEventCounter", {HistType::kTH1D, {{SpecificEventSelectionStep::NSpecificEventSelectionSteps, -0.5, +SpecificEventSelectionStep::NSpecificEventSelectionSteps - 0.5}}}); + std::string labels[SpecificEventSelectionStep::NSpecificEventSelectionSteps]; + labels[SpecificEventSelectionStep::AllEventsPrecise] = "all"; + labels[SpecificEventSelectionStep::HasMcCollision] = "has MC coll?"; + labels[SpecificEventSelectionStep::IsSel8] = "sel8"; + labels[SpecificEventSelectionStep::IsNoSameBunchPileup] = "IsNoSameBunchPileup"; + labels[SpecificEventSelectionStep::IsGoodItsLayersAll] = "IsGoodItsLayersAll"; + labels[SpecificEventSelectionStep::IsGoodZvtxFT0vsPV] = "IsGoodZvtxFT0vsPV"; + labels[SpecificEventSelectionStep::IsNoCollInRofStandard] = "IsNoCollInRofStandard"; + labels[SpecificEventSelectionStep::IsNoCollInRofStrict] = "IsNoCollInRofStrict"; + labels[SpecificEventSelectionStep::IsNoCollInTimeRangeStandard] = "IsNoCollInTimeRangeStandard"; + labels[SpecificEventSelectionStep::IsNoCollInTimeRangeStrict] = "IsNoCollInTimeRangeStrict"; + labels[SpecificEventSelectionStep::IsNoHighMultCollInPrevRof] = "IsNoHighMultCollInPrevRof"; + labels[SpecificEventSelectionStep::IsRctFlagChecked] = "IsRctFlagChecked"; + registry.get(HIST("hPreciseEventCounter"))->SetMinimum(0); + + for (int iBin = 0; iBin < SpecificEventSelectionStep::NSpecificEventSelectionSteps; iBin++) { + registry.get(HIST("hPreciseEventCounter"))->GetXaxis()->SetBinLabel(iBin + 1, labels[iBin].data()); + } + + registry.add("MC/hMonteCarloEventCounter", "hMonteCarloEventCounter", {HistType::kTH1D, {{MonteCarloEventSelectionStep::NMonteCarloEventSelectionSteps, -0.5, +MonteCarloEventSelectionStep::NMonteCarloEventSelectionSteps - 0.5}}}); + std::string labelsMonteCarloEvents[MonteCarloEventSelectionStep::NMonteCarloEventSelectionSteps]; + labelsMonteCarloEvents[MonteCarloEventSelectionStep::AllMonteCarloEvents] = "all collisions"; + labelsMonteCarloEvents[MonteCarloEventSelectionStep::MonteCarloEventsAfterEventSelection] = "collisions after event selection"; + labelsMonteCarloEvents[MonteCarloEventSelectionStep::HasMonteCarloCollision] = "has MC collision"; + labelsMonteCarloEvents[MonteCarloEventSelectionStep::HasNotMonteCarloCollision] = "has not MC collision"; + registry.get(HIST("MC/hMonteCarloEventCounter"))->SetMinimum(0); + + for (int iBin = 0; iBin < MonteCarloEventSelectionStep::NMonteCarloEventSelectionSteps; iBin++) { + registry.get(HIST("MC/hMonteCarloEventCounter"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMonteCarloEvents[iBin].data()); + } + + registry.add("MC/hMonteCarloTrackCounter", "hMonteCarloTrackCounter", {HistType::kTH1D, {{MonteCarloTrackSelectionStep::NMonteCarloTrackSelectionSteps, -0.5, +MonteCarloTrackSelectionStep::NMonteCarloTrackSelectionSteps - 0.5}}}); + std::string labelsMonteCarloTracks[MonteCarloTrackSelectionStep::NMonteCarloTrackSelectionSteps]; + labelsMonteCarloTracks[MonteCarloTrackSelectionStep::AllMonteCarloTracks] = "all tracks"; + labelsMonteCarloTracks[MonteCarloTrackSelectionStep::MonteCarloTracksAfterTrackSelection] = "tracks after track selection"; + labelsMonteCarloTracks[MonteCarloTrackSelectionStep::HasMonteCarloParticle] = "has MC particle"; + labelsMonteCarloTracks[MonteCarloTrackSelectionStep::HasNotMonteCarloParticle] = "has not MC particle"; + registry.get(HIST("MC/hMonteCarloTrackCounter"))->SetMinimum(0); + + for (int iBin = 0; iBin < MonteCarloTrackSelectionStep::NMonteCarloTrackSelectionSteps; iBin++) { + registry.get(HIST("MC/hMonteCarloTrackCounter"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMonteCarloTracks[iBin].data()); + } + + // ========================= + // Process functions initialization + // ========================= + + if (doprocessData) { + addMftHistograms(); + } + + if (doprocessMcReassociated2d) { + addMftHistograms(); + addMftMonteCarloHistograms(); + } + + if (doprocessMcReassociated3d) { + addMftHistograms(); + addMftMonteCarloHistograms(); + } + + } // End of init() function + + // ========================= + // Helper functions + // ========================= + + template + float getMultiplicityEstimator(TCollision collision, bool isSameEvent) + { + switch (configCollision.multiplicityEstimator) { + case MultiplicityEstimators::MultNTracksPV: + if (isSameEvent) { + registry.fill(HIST("Data/hMultiplicity_multNTracksPV"), collision.multNTracksPV()); + } + return collision.multNTracksPV(); + case MultiplicityEstimators::MultNumContrib: + if (isSameEvent) { + registry.fill(HIST("Data/hMultiplicity_multNumContrib"), collision.numContrib()); + } + return collision.numContrib(); + case MultiplicityEstimators::MultFT0C: + if (isSameEvent) { + registry.fill(HIST("Data/hMultiplicity_multFT0C"), collision.multFT0C()); + } + return collision.multFT0C(); + case MultiplicityEstimators::MultFT0M: + if (isSameEvent) { + registry.fill(HIST("Data/hMultiplicity_multFT0M"), collision.multFT0M()); + } + return collision.multFT0M(); + default: + return collision.multNTracksPV(); + } + } + + int getMagneticField(uint64_t timestamp) + { + // Get the magnetic field + static o2::parameters::GRPMagField* grpo = nullptr; + if (grpo == nullptr) { + grpo = ccdb->getForTimeStamp("/GLO/Config/GRPMagField", timestamp); + if (grpo == nullptr) { + LOGF(fatal, "GRP object not found for timestamp %llu", timestamp); + return 0; + } + LOGF(info, "Retrieved GRP for timestamp %llu with magnetic field of %d kG", timestamp, grpo->getNominalL3Field()); + } + return grpo->getNominalL3Field(); + } + + // ========================= + // Cuts with functions + // ========================= + + // FIXME: Some collisions are rejected here, what causes (part of) differences with the D0 task + template + bool isAcceptedCollision(TCollision const& collision, bool fillHistograms = false) + { + + if (!collision.sel8()) { + return false; + } + if (fillHistograms) { + registry.fill(HIST("hPreciseEventCounter"), SpecificEventSelectionStep::IsSel8); + } + if (configCollision.isApplySameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + return false; + } + if (fillHistograms) { + registry.fill(HIST("hPreciseEventCounter"), SpecificEventSelectionStep::IsNoSameBunchPileup); + } + if (configCollision.isApplyGoodItsLayersAll && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + return false; + } + if (fillHistograms) { + registry.fill(HIST("hPreciseEventCounter"), SpecificEventSelectionStep::IsGoodItsLayersAll); + } + if (configCollision.isApplyGoodZvtxFT0vsPV && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + return false; + } + if (fillHistograms) { + registry.fill(HIST("hPreciseEventCounter"), SpecificEventSelectionStep::IsGoodZvtxFT0vsPV); + } + if (configCollision.isApplyNoCollInRofStandard && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { + return false; + } + if (fillHistograms) { + registry.fill(HIST("hPreciseEventCounter"), SpecificEventSelectionStep::IsNoCollInRofStandard); + } + if (configCollision.isApplyNoCollInRofStrict && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStrict)) { + return false; + } + if (fillHistograms) { + registry.fill(HIST("hPreciseEventCounter"), SpecificEventSelectionStep::IsNoCollInRofStrict); + } + if (configCollision.isApplyNoCollInTimeRangeStandard && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + return false; + } + if (fillHistograms) { + registry.fill(HIST("hPreciseEventCounter"), SpecificEventSelectionStep::IsNoCollInTimeRangeStandard); + } + if (configCollision.isApplyNoCollInTimeRangeStrict && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStrict)) { + return false; + } + if (fillHistograms) { + registry.fill(HIST("hPreciseEventCounter"), SpecificEventSelectionStep::IsNoCollInTimeRangeStrict); + } + if (configCollision.isApplyNoHighMultCollInPrevRof && !collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { + return false; + } + if (fillHistograms) { + registry.fill(HIST("hPreciseEventCounter"), SpecificEventSelectionStep::IsNoHighMultCollInPrevRof); + } + if (configCollision.requireRCTFlagChecker && !rctChecker(collision)) { + return false; + } + if (configCollision.requireCorrelationAnalysisRCTFlagChecker && !correlationAnalysisRctChecker(collision)) { + return false; + } + if (fillHistograms) { + registry.fill(HIST("hPreciseEventCounter"), SpecificEventSelectionStep::IsRctFlagChecked); + } + + registry.fill(HIST("Data/hVtxZ"), collision.posZ()); + + return true; + } + + // TODO: Check how to put this into a Filter + // I tried to put it as a filter, but filters for normal TPC tracks also apply to MFT tracks I think + // and it seems that they are not compatible + template + bool isAcceptedMftTrack(TTrack const& mftTrack, bool fillHistograms) + { + // cut on the eta of MFT tracks + if (mftTrack.eta() > configMft.etaMftTrackMax || mftTrack.eta() < configMft.etaMftTrackMin) { + return false; + } + + if (fillHistograms) { + registry.fill(HIST("Data/hMftTracksSelection"), MftTrackSelectionStep::Eta); + } + + // cut on the number of clusters of the reconstructed MFT track + if (mftTrack.nClusters() < configMft.nClustersMftTrack) { + return false; + } + + if (fillHistograms) { + registry.fill(HIST("Data/hMftTracksSelection"), MftTrackSelectionStep::Cluster); + } + + // cut on the pT of MFT tracks (for test purposes) + if (configMft.useMftPtCut && (mftTrack.pt() > configMft.ptMftTrackMax || mftTrack.pt() < configMft.ptMftTrackMin)) { + return false; + } + + if (fillHistograms) { + registry.fill(HIST("Data/hMftTracksSelection"), MftTrackSelectionStep::Pt); + } + + return true; + } + + // Cut on ambiguous MFT tracks + template + bool isAmbiguousMftTrack(TTrack const& mftTrack, bool fillHistograms) + { + if (mftTrack.ambDegree() > 1) { + if (fillHistograms) { + registry.fill(HIST("Data/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::NumberOfAmbiguousTracks); + } + return true; + if (mftTrack.ambDegree() > 1) { + if (fillHistograms) { + registry.fill(HIST("Data/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::NumberOfAmbiguousTracks); + } + return true; + } + + if (fillHistograms) { + registry.fill(HIST("Data/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::NumberOfNonAmbiguousTracks); + } + return false; + } + + if (fillHistograms) { + registry.fill(HIST("Data/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::NumberOfNonAmbiguousTracks); + } + return false; + } + + //============================================================================================ + // + // PROCESS FUNCTIONS + // + //============================================================================================ + + void processData(FilteredCollisionsWSelMult::iterator const& collision, + FilteredMftTracks const& /*mftTracks*/, + soa::SmallGroups const& reassociated2dMftTracks, + aod::BCsWithTimestamps const&) + { + + if (!(isAcceptedCollision(collision, true))) { + return; + } + + // const auto multiplicity = getMultiplicityEstimator(collision, true); + + for (const auto& reassociated2dMftTrack : reassociated2dMftTracks) { + + registry.fill(HIST("Data/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::AllMftTracks); + auto templatedMftTrack = reassociated2dMftTrack.template mfttrack_as(); + + if (!isAcceptedMftTrack(templatedMftTrack, false)) { + continue; + } + + registry.fill(HIST("Data/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::AfterTrackSelection); + + if (isAmbiguousMftTrack(reassociated2dMftTrack, true)) { + registry.fill(HIST("Data/hReassociation2dMftTracks"), Reassociation2dMftTracks::NotReassociated2dMftTracks); + } + + } // end of loop over reassociated MFT tracks + + // TO-DO the same for reassociated3d (change the histograms) + } + PROCESS_SWITCH(MftReassociationValidation, processData, "Process MFT reassociation validation for DATA", false); + + void processCreateLookupTable(FilteredCollisionsWSelMultMcLabels const& collisions) + { + recoVtxX.reserve(collisions.size()); + recoVtxY.reserve(collisions.size()); + recoVtxZ.reserve(collisions.size()); + recoMcCollisionId.reserve(collisions.size()); + + for (auto const& col : collisions) { + recoVtxX.emplace(col.globalIndex(), col.posX()); + recoVtxY.emplace(col.globalIndex(), col.posY()); + recoVtxZ.emplace(col.globalIndex(), col.posZ()); + recoMcCollisionId.emplace(col.globalIndex(), col.mcCollisionId()); + } + } + PROCESS_SWITCH(MftReassociationValidation, processCreateLookupTable, "Process look uptable creation", false); + + void processMcReassociated2d(FilteredCollisionsWSelMultMcLabels::iterator const& collision, + FilteredMftTracksWCollsMcLabels const& /*mftTracks*/, + soa::SmallGroups> const& reassociated2dMftTracks, + aod::McCollisions const& /*mcCollisions*/, + aod::McParticles const& /*particles*/) + { + registry.fill(HIST("MC/hMonteCarloEventCounter"), MonteCarloEventSelectionStep::AllMonteCarloEvents); + registry.fill(HIST("hPreciseEventCounter"), SpecificEventSelectionStep::AllEventsPrecise); + + if (!collision.has_mcCollision()) { + registry.fill(HIST("MC/hMonteCarloEventCounter"), MonteCarloEventSelectionStep::HasNotMonteCarloCollision); + return; + } + + registry.fill(HIST("MC/hMonteCarloEventCounter"), MonteCarloEventSelectionStep::HasMonteCarloCollision); + registry.fill(HIST("hPreciseEventCounter"), SpecificEventSelectionStep::HasMcCollision); + + if (!isAcceptedCollision(collision, true)) { + return; + } + + registry.fill(HIST("MC/hMonteCarloEventCounter"), MonteCarloEventSelectionStep::MonteCarloEventsAfterEventSelection); + + for (auto const& reassociated2dMftTrack : reassociated2dMftTracks) { + + registry.fill(HIST("MC/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::AllMftTracks); + registry.fill(HIST("MC/hMonteCarloTrackCounter"), MonteCarloTrackSelectionStep::AllMonteCarloTracks); + + auto templatedTrack = reassociated2dMftTrack.template mfttrack_as(); + + if (!isAcceptedMftTrack(templatedTrack, false)) { + continue; + } + + registry.fill(HIST("MC/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::AfterTrackSelection); + registry.fill(HIST("MC/hMonteCarloTrackCounter"), MonteCarloTrackSelectionStep::MonteCarloTracksAfterTrackSelection); + + if (templatedTrack.has_mcParticle()) { + registry.fill(HIST("MC/hMonteCarloTrackCounter"), MonteCarloTrackSelectionStep::HasMonteCarloParticle); + + auto particle = templatedTrack.template mcParticle_as(); + float deltaX = -999.f; + float deltaY = -999.f; + float deltaZ = -999.f; + float reassociatedDeltaX = -999.f; + float reassociatedDeltaY = -999.f; + float reassociatedDeltaZ = -999.f; + auto collision = templatedTrack.collision_as(); + // auto mcCollision = particle.mcCollision_as(); + // deltaZ = collision.posZ() - mcCollision.posZ(); + auto xPosTrue = reassociated2dMftTrack.mcParticle().mcCollision().posX(); + auto yPosTrue = reassociated2dMftTrack.mcParticle().mcCollision().posY(); + auto zPosTrue = reassociated2dMftTrack.mcParticle().mcCollision().posZ(); + + const int bestRecoCol = reassociated2dMftTrack.bestCollisionId(); + // if (bestRecoCol < 0) { + // // no associated reco collision -> skip or count separately + // continue; + // } + + auto iteratorRecoVtxX = recoVtxX.find(bestRecoCol); + auto iteratorRecoVtxY = recoVtxY.find(bestRecoCol); + auto iteratorRecoVtxZ = recoVtxZ.find(bestRecoCol); + auto iteratorRecoMcCollisionId = recoMcCollisionId.find(bestRecoCol); + if (iteratorRecoVtxX == recoVtxX.end()) { + // bestRecoCol not found in reco collisions map -> skip or count separately + continue; + } + if (iteratorRecoVtxY == recoVtxY.end()) { + // bestRecoCol not found in reco collisions map -> skip or count separately + continue; + } + if (iteratorRecoVtxZ == recoVtxZ.end()) { + // bestRecoCol not found in reco collisions map -> skip or count separately + continue; + } + if (iteratorRecoMcCollisionId == recoMcCollisionId.end()) { + // bestRecoCol not found in reco collisions map -> skip or count separately + continue; + } + + const float xReco = iteratorRecoVtxX->second; + const float yReco = iteratorRecoVtxY->second; + const float zReco = iteratorRecoVtxZ->second; + const int mcCollisionIdReco = iteratorRecoMcCollisionId->second; + + reassociatedDeltaX = xReco - xPosTrue; + reassociatedDeltaY = yReco - yPosTrue; + reassociatedDeltaZ = zReco - zPosTrue; + + if (reassociated2dMftTrack.ambDegree() > 1) { // AMBIGUOUS TRACKS + registry.fill(HIST("MC/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::NumberOfAmbiguousTracks); + registry.fill(HIST("MC/hIsAmbiguousTrackMatchedToTrueCollision"), MftAmbiguousAndMatchedToTrueCollisionStep::IsAmbiguous); + registry.fill(HIST("MC/hReassociation2dMftTracks"), Reassociation2dMftTracks::AllAmbiguousTracksAfterTrackSelectionsFor2d); + hZVtxDiffAmbiguousTracks[MatchedToTrueCollisionStep::AllTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); + + if (collision.mcCollisionId() == particle.mcCollisionId()) { + registry.fill(HIST("MC/hIsAmbiguousTrackMatchedToTrueCollision"), MftAmbiguousAndMatchedToTrueCollisionStep::IsAmbiguousAndMatchedToTrueCollision); + hZVtxDiffAmbiguousTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); + } else { + registry.fill(HIST("MC/hIsAmbiguousTrackMatchedToTrueCollision"), MftAmbiguousAndMatchedToTrueCollisionStep::IsAmbiguousAndNotMatchedToTrueCollision); + hZVtxDiffAmbiguousTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); + } + + if (templatedTrack.collisionId() == reassociated2dMftTrack.bestCollisionId()) { // IS NOT 2D REASSOCIATED + + registry.fill(HIST("MC/hReassociation2dMftTracks"), Reassociation2dMftTracks::NotReassociated2dMftTracks); + registry.fill(HIST("MC/IsNot2dReassociatedAndMatchedToTrueCollision"), MftNot2dReassociatedAndMatchedToTrueCollisionStep::IsNot2dReassociated); + hZVtxDiffNot2dReassociatedTracks[MatchedToTrueCollisionStep::AllTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); + + if (mcCollisionIdReco == particle.mcCollisionId()) { + registry.fill(HIST("MC/IsNot2dReassociatedAndMatchedToTrueCollision"), MftNot2dReassociatedAndMatchedToTrueCollisionStep::IsNot2dReassociatedAndMatchedToTrueCollision); + hZVtxDiffNot2dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); + } else { + registry.fill(HIST("MC/IsNot2dReassociatedAndMatchedToTrueCollision"), MftNot2dReassociatedAndMatchedToTrueCollisionStep::IsNot2dReassociatedAndNotMatchedToTrueCollision); + hZVtxDiffNot2dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); + } + + } else { // IS 2D REASSOCIATED + + registry.fill(HIST("MC/hReassociation2dMftTracks"), Reassociation2dMftTracks::Reassociated2dMftTracks); + registry.fill(HIST("MC/Is2dReassociatedAndMatchedToTrueCollision"), Mft2dReassociatedAndMatchedToTrueCollisionStep::Is2dReassociated); + hZVtxDiff2dReassociatedTracks[MatchedToTrueCollisionStep::AllTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); + + // is collision.mcCollisionId() the reassociated collision vertex ? or the initial collision + if (mcCollisionIdReco == particle.mcCollisionId()) { + registry.fill(HIST("MC/Is2dReassociatedAndMatchedToTrueCollision"), Mft2dReassociatedAndMatchedToTrueCollisionStep::Is2dReassociatedAndMatchedToTrueCollision); + hZVtxDiff2dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); + } else { + registry.fill(HIST("MC/Is2dReassociatedAndMatchedToTrueCollision"), Mft2dReassociatedAndMatchedToTrueCollisionStep::Is2dReassociatedAndNotMatchedToTrueCollision); + hZVtxDiff2dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); + } + } + + } else { // NON AMBI TRACKS + + registry.fill(HIST("MC/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::NumberOfNonAmbiguousTracks); + registry.fill(HIST("MC/hIsNonAmbiguousTrackMatchedToTrueCollision"), MftNonAmbiguousAndMatchedToTrueCollisionStep::IsNonAmbiguous); + hZVtxDiffNonAmbiguousTracks[MatchedToTrueCollisionStep::AllTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); + + if (collision.mcCollisionId() == particle.mcCollisionId()) { + registry.fill(HIST("MC/hIsNonAmbiguousTrackMatchedToTrueCollision"), MftNonAmbiguousAndMatchedToTrueCollisionStep::IsNonAmbiguousAndMatchedToTrueCollision); + hZVtxDiffNonAmbiguousTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); + } else { + registry.fill(HIST("MC/hIsNonAmbiguousTrackMatchedToTrueCollision"), MftNonAmbiguousAndMatchedToTrueCollisionStep::IsNonAmbiguousAndNotMatchedToTrueCollision); + hZVtxDiffNonAmbiguousTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); + } + + } // end of if non ambi + } else { + registry.fill(HIST("MC/hMonteCarloTrackCounter"), MonteCarloTrackSelectionStep::HasNotMonteCarloParticle); + } + } // end of loop over reassociated2dMftTracks + } + PROCESS_SWITCH(MftReassociationValidation, processMcReassociated2d, "Process MFT reassociation2d validation for MONTE-CARLO", false); + + void processMcReassociated3d(FilteredCollisionsWSelMultMcLabels::iterator const& collision, + FilteredMftTracksWCollsMcLabels const& /*mftTracks*/, + soa::SmallGroups> const& reassociated3dMftTracks, + aod::McCollisions const& /*mcCollisions*/, + aod::McParticles const& /*particles*/) + { + registry.fill(HIST("MC/hMonteCarloEventCounter"), MonteCarloEventSelectionStep::AllMonteCarloEvents); + registry.fill(HIST("hPreciseEventCounter"), SpecificEventSelectionStep::AllEventsPrecise); + + if (!collision.has_mcCollision()) { + registry.fill(HIST("MC/hMonteCarloEventCounter"), MonteCarloEventSelectionStep::HasNotMonteCarloCollision); + return; + } + + registry.fill(HIST("MC/hMonteCarloEventCounter"), MonteCarloEventSelectionStep::HasMonteCarloCollision); + registry.fill(HIST("hPreciseEventCounter"), SpecificEventSelectionStep::HasMcCollision); + + if (!isAcceptedCollision(collision, true)) { + return; + } + + registry.fill(HIST("MC/hMonteCarloEventCounter"), MonteCarloEventSelectionStep::MonteCarloEventsAfterEventSelection); + + for (auto const& reassociated3dMftTrack : reassociated3dMftTracks) { + + registry.fill(HIST("MC/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::AllMftTracks); + registry.fill(HIST("MC/hMonteCarloTrackCounter"), MonteCarloTrackSelectionStep::AllMonteCarloTracks); + + auto templatedTrack = reassociated3dMftTrack.template mfttrack_as(); + + if (!isAcceptedMftTrack(templatedTrack, false)) { + continue; + } + + registry.fill(HIST("MC/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::AfterTrackSelection); + registry.fill(HIST("MC/hMonteCarloTrackCounter"), MonteCarloTrackSelectionStep::MonteCarloTracksAfterTrackSelection); + + if (templatedTrack.has_mcParticle()) { + registry.fill(HIST("MC/hMonteCarloTrackCounter"), MonteCarloTrackSelectionStep::HasMonteCarloParticle); + + auto particle = templatedTrack.template mcParticle_as(); + float deltaX = -999.f; + float deltaY = -999.f; + float deltaZ = -999.f; + float reassociatedDeltaX = -999.f; + float reassociatedDeltaY = -999.f; + float reassociatedDeltaZ = -999.f; + auto collision = templatedTrack.collision_as(); + // auto mcCollision = particle.mcCollision_as(); + // deltaZ = collision.posZ() - mcCollision.posZ(); + auto xPosTrue = reassociated3dMftTrack.mcParticle().mcCollision().posX(); + auto yPosTrue = reassociated3dMftTrack.mcParticle().mcCollision().posY(); + auto zPosTrue = reassociated3dMftTrack.mcParticle().mcCollision().posZ(); + + const int bestRecoCol = reassociated3dMftTrack.bestCollisionId(); + // if (bestRecoCol < 0) { + // // no associated reco collision -> skip or count separately + // continue; + // } + + auto iteratorRecoVtxX = recoVtxX.find(bestRecoCol); + auto iteratorRecoVtxY = recoVtxY.find(bestRecoCol); + auto iteratorRecoVtxZ = recoVtxZ.find(bestRecoCol); + auto iteratorRecoMcCollisionId = recoMcCollisionId.find(bestRecoCol); + if (iteratorRecoVtxX == recoVtxX.end()) { + // bestRecoCol not found in reco collisions map -> skip or count separately + continue; + } + if (iteratorRecoVtxY == recoVtxY.end()) { + // bestRecoCol not found in reco collisions map -> skip or count separately + continue; + } + if (iteratorRecoVtxZ == recoVtxZ.end()) { + // bestRecoCol not found in reco collisions map -> skip or count separately + continue; + } + if (iteratorRecoMcCollisionId == recoMcCollisionId.end()) { + // bestRecoCol not found in reco collisions map -> skip or count separately + continue; + } + + const float xReco = iteratorRecoVtxX->second; + const float yReco = iteratorRecoVtxY->second; + const float zReco = iteratorRecoVtxZ->second; + const int mcCollisionIdReco = iteratorRecoMcCollisionId->second; + + reassociatedDeltaX = xReco - xPosTrue; + reassociatedDeltaY = yReco - yPosTrue; + reassociatedDeltaZ = zReco - zPosTrue; + + if (reassociated3dMftTrack.ambDegree() > 1) { // AMBIGUOUS TRACKS + registry.fill(HIST("MC/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::NumberOfAmbiguousTracks); + registry.fill(HIST("MC/hIsAmbiguousTrackMatchedToTrueCollision"), MftAmbiguousAndMatchedToTrueCollisionStep::IsAmbiguous); + registry.fill(HIST("MC/hReassociation3dMftTracks"), Reassociation3dMftTracks::AllAmbiguousTracksAfterTrackSelectionsFor3d); + hZVtxDiffAmbiguousTracks[MatchedToTrueCollisionStep::AllTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); + + if (collision.mcCollisionId() == particle.mcCollisionId()) { + registry.fill(HIST("MC/hIsAmbiguousTrackMatchedToTrueCollision"), MftAmbiguousAndMatchedToTrueCollisionStep::IsAmbiguousAndMatchedToTrueCollision); + hZVtxDiffAmbiguousTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); + } else { + registry.fill(HIST("MC/hIsAmbiguousTrackMatchedToTrueCollision"), MftAmbiguousAndMatchedToTrueCollisionStep::IsAmbiguousAndNotMatchedToTrueCollision); + hZVtxDiffAmbiguousTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); + } + + if (templatedTrack.collisionId() == reassociated3dMftTrack.bestCollisionId()) { // IS NOT 3D REASSOCIATED + + registry.fill(HIST("MC/hReassociation3dMftTracks"), Reassociation3dMftTracks::NotReassociated3dMftTracks); + registry.fill(HIST("MC/IsNot3dReassociatedAndMatchedToTrueCollision"), MftNot3dReassociatedAndMatchedToTrueCollisionStep::IsNot3dReassociated); + hZVtxDiffNot3dReassociatedTracks[MatchedToTrueCollisionStep::AllTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); + + if (mcCollisionIdReco == particle.mcCollisionId()) { + registry.fill(HIST("MC/IsNot3dReassociatedAndMatchedToTrueCollision"), MftNot3dReassociatedAndMatchedToTrueCollisionStep::IsNot3dReassociatedAndMatchedToTrueCollision); + hZVtxDiffNot3dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); + } else { + registry.fill(HIST("MC/IsNot3dReassociatedAndMatchedToTrueCollision"), MftNot3dReassociatedAndMatchedToTrueCollisionStep::IsNot3dReassociatedAndNotMatchedToTrueCollision); + hZVtxDiffNot3dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); + } + + } else { // IS 3D REASSOCIATED + + registry.fill(HIST("MC/hReassociation3dMftTracks"), Reassociation3dMftTracks::Reassociated3dMftTracks); + registry.fill(HIST("MC/Is3dReassociatedAndMatchedToTrueCollision"), Mft3dReassociatedAndMatchedToTrueCollisionStep::Is3dReassociated); + hZVtxDiff3dReassociatedTracks[MatchedToTrueCollisionStep::AllTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); + + // is collision.mcCollisionId() the reassociated collision vertex ? or the initial collision + if (mcCollisionIdReco == particle.mcCollisionId()) { + registry.fill(HIST("MC/Is3dReassociatedAndMatchedToTrueCollision"), Mft3dReassociatedAndMatchedToTrueCollisionStep::Is3dReassociatedAndMatchedToTrueCollision); + hZVtxDiff3dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); + } else { + registry.fill(HIST("MC/Is3dReassociatedAndMatchedToTrueCollision"), Mft3dReassociatedAndMatchedToTrueCollisionStep::Is3dReassociatedAndNotMatchedToTrueCollision); + hZVtxDiff3dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); + } + } + + } else { // NON AMBI TRACKS + + registry.fill(HIST("MC/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::NumberOfNonAmbiguousTracks); + registry.fill(HIST("MC/hIsNonAmbiguousTrackMatchedToTrueCollision"), MftNonAmbiguousAndMatchedToTrueCollisionStep::IsNonAmbiguous); + hZVtxDiffNonAmbiguousTracks[MatchedToTrueCollisionStep::AllTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); + + if (collision.mcCollisionId() == particle.mcCollisionId()) { + registry.fill(HIST("MC/hIsNonAmbiguousTrackMatchedToTrueCollision"), MftNonAmbiguousAndMatchedToTrueCollisionStep::IsNonAmbiguousAndMatchedToTrueCollision); + hZVtxDiffNonAmbiguousTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); + } else { + registry.fill(HIST("MC/hIsNonAmbiguousTrackMatchedToTrueCollision"), MftNonAmbiguousAndMatchedToTrueCollisionStep::IsNonAmbiguousAndNotMatchedToTrueCollision); + hZVtxDiffNonAmbiguousTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); + } + + } // end of if non ambi + } else { + registry.fill(HIST("MC/hMonteCarloTrackCounter"), MonteCarloTrackSelectionStep::HasNotMonteCarloParticle); + } + } // end of loop over reassociated3dMftTracks + } + PROCESS_SWITCH(MftReassociationValidation, processMcReassociated3d, "Process MFT reassociation3d validation for MONTE-CARLO", false); + +}; // End of struct + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} From 9c17cfd6c8237e7cf4c670b3fec6e78f8865bf15 Mon Sep 17 00:00:00 2001 From: Francesco Mazzaschi <43742195+fmazzasc@users.noreply.github.com> Date: Sun, 22 Feb 2026 13:50:57 +0100 Subject: [PATCH 017/347] [PWGLF] Doubleomega: avoid cascade track sharing (#15096) --- .../Strangeness/doubleCascTreeCreator.cxx | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/PWGLF/TableProducer/Strangeness/doubleCascTreeCreator.cxx b/PWGLF/TableProducer/Strangeness/doubleCascTreeCreator.cxx index 164d95d1ac6..669a69016f0 100644 --- a/PWGLF/TableProducer/Strangeness/doubleCascTreeCreator.cxx +++ b/PWGLF/TableProducer/Strangeness/doubleCascTreeCreator.cxx @@ -248,7 +248,22 @@ struct doubleCascTreeCreator { histos.fill(HIST("QA/massXi2"), casc2.pt(), casc2.mXi()); histos.fill(HIST("QA/massOmega2"), casc2.pt(), casc2.mOmega()); - if (casc1.posTrackId() == casc2.posTrackId() || casc1.posTrackId() == casc2.negTrackId() || casc1.bachelorId() == casc2.bachelorId()) { + // check that the cascades do not share any track + std::vector trackIdsCasc1 = {casc1.posTrackId(), casc1.negTrackId(), casc1.bachelorId()}; + std::vector trackIdsCasc2 = {casc2.posTrackId(), casc2.negTrackId(), casc2.bachelorId()}; + bool shareTrack = false; + for (auto id1 : trackIdsCasc1) { + for (auto id2 : trackIdsCasc2) { + if (id1 == id2) { + shareTrack = true; + break; + } + } + if (shareTrack) { + break; + } + } + if (shareTrack) { continue; } From a71939a968dcdd8c5aded772162ab1f39eb46a75 Mon Sep 17 00:00:00 2001 From: Subhadeep Roy Date: Sun, 22 Feb 2026 19:22:33 +0530 Subject: [PATCH 018/347] [PWGCF] Refactor LambdaSpinPolarization processing logic (#15052) --- .../Tasks/lambdaSpinPolarization.cxx | 35 ++++++++++++++----- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/lambdaSpinPolarization.cxx b/PWGCF/TwoParticleCorrelations/Tasks/lambdaSpinPolarization.cxx index df89d74512b..e0eefb67fad 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/lambdaSpinPolarization.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/lambdaSpinPolarization.cxx @@ -1634,16 +1634,33 @@ struct LambdaSpinPolarization { float dphi = RecoDecay::constrainAngle(p1.phi() - p2.phi(), -PI); float dR = std::sqrt(drap * drap + dphi * dphi); - // Get Lambda-Proton four-momentum std::array l1 = {p1.px(), p1.py(), p1.pz(), MassLambda0}; std::array l2 = {p2.px(), p2.py(), p2.pz(), MassLambda0}; + + std::array llpair = { + l1[0] + l2[0], + l1[1] + l2[1], + l1[2] + l2[2], + l1[3] + l2[3]}; + std::array pr1 = {p1.prPx(), p1.prPy(), p1.prPz(), MassProton}; std::array pr2 = {p2.prPx(), p2.prPy(), p2.prPz(), MassProton}; - std::array v1, v2; - getBoostVector(l1, v1, cInvBoostFlag); - getBoostVector(l2, v2, cInvBoostFlag); - boost(pr1, v1); - boost(pr2, v2); + + std::array vPair; + getBoostVector(llpair, vPair, cInvBoostFlag); + + boost(l1, vPair); + boost(l2, vPair); + + boost(pr1, vPair); + boost(pr2, vPair); + + std::array v1_pair, v2_pair; + getBoostVector(l1, v1_pair, cInvBoostFlag); + getBoostVector(l2, v2_pair, cInvBoostFlag); + + boost(pr1, v1_pair); + boost(pr2, v2_pair); std::array pr1tv = {pr1[0], pr1[1], pr1[2]}; std::array pr2tv = {pr2[0], pr2[1], pr2[2]}; @@ -1676,7 +1693,7 @@ struct LambdaSpinPolarization { continue; } - // Kinematic matching with named constants + // Kinematic matching float deltaPt = std::abs(trk_1.pt() - trk_2.pt()); float deltaPhi = std::abs(RecoDecay::constrainAngle(trk_1.phi() - trk_2.phi(), -PI)); float deltaRap = std::abs(trk_1.rap() - trk_2.rap()); @@ -1718,7 +1735,7 @@ struct LambdaSpinPolarization { analyzePairs(antiLambdaTracks, antiLambdaTracks); } - PROCESS_SWITCH(LambdaSpinPolarization, processDataReco, "Process for Data and MCReco", false); + PROCESS_SWITCH(LambdaSpinPolarization, processDataReco, "Process for Data and MCReco", true); struct GetMultiplicity { float operator()(auto const& col) const @@ -1766,7 +1783,7 @@ struct LambdaSpinPolarization { } } - PROCESS_SWITCH(LambdaSpinPolarization, processDataRecoMixed, "Process for Data and MCReco for Mixed events", true); + PROCESS_SWITCH(LambdaSpinPolarization, processDataRecoMixed, "Process for Data and MCReco for Mixed events", false); void processDataRecoMixEvent(LambdaCollisions::iterator const& collision, LambdaTracks const& tracks) { From 88e5b0e0cb4c7ee2e3324604acdd9bb7882e09b0 Mon Sep 17 00:00:00 2001 From: Francesco Mazzaschi <43742195+fmazzasc@users.noreply.github.com> Date: Sun, 22 Feb 2026 15:02:50 +0100 Subject: [PATCH 019/347] [PWGLF] Add generated k* in sigmaproton task (#15095) Co-authored-by: Francesco Mazzaschi --- PWGLF/DataModel/LFSigmaProtonTables.h | 6 +- .../Strangeness/sigmaProtonCorr.cxx | 66 ++++++++++++++++--- 2 files changed, 63 insertions(+), 9 deletions(-) diff --git a/PWGLF/DataModel/LFSigmaProtonTables.h b/PWGLF/DataModel/LFSigmaProtonTables.h index cf512422c79..d9eafbedda5 100644 --- a/PWGLF/DataModel/LFSigmaProtonTables.h +++ b/PWGLF/DataModel/LFSigmaProtonTables.h @@ -44,6 +44,9 @@ DECLARE_SOA_COLUMN(NSigmaTOFPr, nSigmaTOFPr, float); //! Number of sigmas for th DECLARE_SOA_COLUMN(SigmaPDG, sigmaPDG, int); //! PDG code of the Sigma daughter DECLARE_SOA_COLUMN(DaughterPDG, daughterPDG, int); //! PDG code of the kink daughter DECLARE_SOA_COLUMN(PrPDG, prPDG, int); //! PDG code of the proton candidate +DECLARE_SOA_COLUMN(SigmaGenPt, sigmaGenPt, float); //! Generated pT of the Sigma candidate +DECLARE_SOA_COLUMN(PrGenPt, prGenPt, float); //! Generated pT of the proton candidate +DECLARE_SOA_COLUMN(GenKStar, genKStar, float); //! Generated k* of the Sigma-Proton pair } // namespace sigmaproton @@ -60,7 +63,8 @@ DECLARE_SOA_TABLE(SigmaProtonMCCands, "AOD", "SIGMAPROTONMCCANDS", kinkcand::PxDaug, kinkcand::PyDaug, kinkcand::PzDaug, sigmaproton::SigmaDecRad, sigmaproton::SigmaCosPA, sigmaproton::ChargePr, sigmaproton::PxPr, sigmaproton::PyPr, sigmaproton::PzPr, sigmaproton::NSigmaTPCPr, sigmaproton::NSigmaTOFPr, - sigmaproton::SigmaPDG, sigmaproton::DaughterPDG, sigmaproton::PrPDG); + sigmaproton::SigmaPDG, sigmaproton::DaughterPDG, sigmaproton::PrPDG, + sigmaproton::SigmaGenPt, sigmaproton::PrGenPt, sigmaproton::GenKStar); } // namespace o2::aod diff --git a/PWGLF/TableProducer/Strangeness/sigmaProtonCorr.cxx b/PWGLF/TableProducer/Strangeness/sigmaProtonCorr.cxx index 17741f3a8c1..26c4eee67d7 100644 --- a/PWGLF/TableProducer/Strangeness/sigmaProtonCorr.cxx +++ b/PWGLF/TableProducer/Strangeness/sigmaProtonCorr.cxx @@ -180,6 +180,26 @@ struct sigmaProtonCorrTask { return 0.5 * trackRelK.P(); } + float getKStar(float sigmaPx, float sigmaPy, float sigmaPz, float pxPr, float pyPr, float pzPr) + { + TLorentzVector part1; // Sigma + TLorentzVector part2; // Proton + part1.SetXYZM(sigmaPx, sigmaPy, sigmaPz, o2::constants::physics::MassSigmaMinus); + part2.SetXYZM(pxPr, pyPr, pzPr, o2::constants::physics::MassProton); + trackSum = part1 + part2; + const float beta = trackSum.Beta(); + const float betax = beta * std::cos(trackSum.Phi()) * std::sin(trackSum.Theta()); + const float betay = beta * std::sin(trackSum.Phi()) * std::sin(trackSum.Theta()); + const float betaz = beta * std::cos(trackSum.Theta()); + PartOneCMS.SetXYZM(part1.Px(), part1.Py(), part1.Pz(), part1.M()); + PartTwoCMS.SetXYZM(part2.Px(), part2.Py(), part2.Pz(), part2.M()); + const ROOT::Math::Boost boostPRF = ROOT::Math::Boost(-betax, -betay, -betaz); + PartOneCMS = boostPRF(PartOneCMS); + PartTwoCMS = boostPRF(PartTwoCMS); + trackRelK = PartOneCMS - PartTwoCMS; + return 0.5 * trackRelK.P(); + } + template bool selectPrTrack(const Ttrack& candidate) { @@ -410,9 +430,22 @@ struct sigmaProtonCorrTask { auto mcLabelSigma = tracks.rawIteratorAt(candidate.sigmaID); auto mcLabelSigmaDau = tracks.rawIteratorAt(candidate.kinkDauID); auto mcLabelPr = tracks.rawIteratorAt(candidate.prID); - auto pdgSigma = mcLabelSigma.has_mcParticle() ? mcLabelSigma.mcParticle_as().pdgCode() : -999; - auto pdgSigmaDau = mcLabelSigmaDau.has_mcParticle() ? mcLabelSigmaDau.mcParticle_as().pdgCode() : -999; - auto pdgPr = mcLabelPr.has_mcParticle() ? mcLabelPr.mcParticle_as().pdgCode() : -999; + + if (!mcLabelSigma.has_mcParticle() || !mcLabelSigmaDau.has_mcParticle() || !mcLabelPr.has_mcParticle()) { + continue; // Skip candidates where MC truth is not available + } + + auto mcPartSigma = mcLabelSigma.mcParticle_as(); + auto mcPartSigmaDau = mcLabelSigmaDau.mcParticle_as(); + auto mcPartPr = mcLabelPr.mcParticle_as(); + auto pdgSigma = mcPartSigma.pdgCode(); + auto pdgSigmaDau = mcLabelSigmaDau.has_mcParticle() ? mcPartSigmaDau.pdgCode() : -999; + auto pdgPr = mcLabelPr.has_mcParticle() ? mcPartPr.pdgCode() : -999; + + float sigmaPtGen = std::hypot(mcPartSigma.px(), mcPartSigma.py()); + float prPtGen = std::hypot(mcPartPr.px(), mcPartPr.py()); + float kStarGen = getKStar(mcPartSigma.px(), mcPartSigma.py(), mcPartSigma.pz(), mcPartPr.px(), mcPartPr.py(), mcPartPr.pz()); + outputDataTableMC(candidate.sigmaCharge, candidate.sigmaPx, candidate.sigmaPy, @@ -430,7 +463,10 @@ struct sigmaProtonCorrTask { candidate.nSigmaTOFPr, pdgSigma, pdgSigmaDau, - pdgPr); + pdgPr, + sigmaPtGen, + prPtGen, + kStarGen); } } } @@ -462,9 +498,20 @@ struct sigmaProtonCorrTask { auto mcLabelSigma = tracks.rawIteratorAt(candidate.sigmaID); auto mcLabelSigmaDau = tracks.rawIteratorAt(candidate.kinkDauID); auto mcLabelPr = tracks.rawIteratorAt(candidate.prID); - auto pdgSigma = mcLabelSigma.has_mcParticle() ? mcLabelSigma.mcParticle_as().pdgCode() : -999; - auto pdgSigmaDau = mcLabelSigmaDau.has_mcParticle() ? mcLabelSigmaDau.mcParticle_as().pdgCode() : -999; - auto pdgPr = mcLabelPr.has_mcParticle() ? mcLabelPr.mcParticle_as().pdgCode() : -999; + + if (!mcLabelSigma.has_mcParticle() || !mcLabelSigmaDau.has_mcParticle() || !mcLabelPr.has_mcParticle()) { + continue; // Skip candidates where MC truth is not available + } + + auto mcPartSigma = mcLabelSigma.mcParticle_as(); + auto mcPartSigmaDau = mcLabelSigmaDau.mcParticle_as(); + auto mcPartPr = mcLabelPr.mcParticle_as(); + auto pdgSigma = mcPartSigma.pdgCode(); + auto pdgSigmaDau = mcLabelSigmaDau.has_mcParticle() ? mcPartSigmaDau.pdgCode() : -999; + auto pdgPr = mcLabelPr.has_mcParticle() ? mcPartPr.pdgCode() : -999; + float sigmaPtGen = std::hypot(mcPartSigma.px(), mcPartSigma.py()); + float prPtGen = std::hypot(mcPartPr.px(), mcPartPr.py()); + float kStarGen = getKStar(mcPartSigma.px(), mcPartSigma.py(), mcPartSigma.pz(), mcPartPr.px(), mcPartPr.py(), mcPartPr.pz()); outputDataTableMC(candidate.sigmaCharge, candidate.sigmaPx, candidate.sigmaPy, @@ -482,7 +529,10 @@ struct sigmaProtonCorrTask { candidate.nSigmaTOFPr, pdgSigma, pdgSigmaDau, - pdgPr); + pdgPr, + sigmaPtGen, + prPtGen, + kStarGen); } } } From 69be7d0e851a23e35cbac52c55a7e38bd6fce570 Mon Sep 17 00:00:00 2001 From: Ionut Cristian Arsene Date: Sun, 22 Feb 2026 15:50:48 +0100 Subject: [PATCH 020/347] [PWGDQ] Modified the trimming options for the bimodal coefficiencts; Fill bimodality and other quantities in the VarManager; Add histograms in the library (#15098) Co-authored-by: Ionut Cristian Arsene Co-authored-by: ALICE Action Bot --- PWGDQ/Core/HistogramsLibrary.cxx | 147 ++++++++++++++++++++++++++ PWGDQ/Core/VarManager.cxx | 64 ++++++++++- PWGDQ/Core/VarManager.h | 53 +++++++--- PWGDQ/Tasks/tableReader_withAssoc.cxx | 4 +- 4 files changed, 251 insertions(+), 17 deletions(-) diff --git a/PWGDQ/Core/HistogramsLibrary.cxx b/PWGDQ/Core/HistogramsLibrary.cxx index aa2c387409d..d40e5dc9847 100644 --- a/PWGDQ/Core/HistogramsLibrary.cxx +++ b/PWGDQ/Core/HistogramsLibrary.cxx @@ -436,6 +436,153 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "energyCommonZNA_energyCommonZNC", "Common ZNA energy vs common ZNC energy", false, 1050, -10.0, 200.0, VarManager::kEnergyCommonZNA, 1050, -10.0, 200.0, VarManager::kEnergyCommonZNC); hm->AddHistogram(histClass, "energyCommonZNA_energyCommonZNC_lowRange", "Common ZNA energy vs common ZNC energy", false, 220, -2.0, 20.0, VarManager::kEnergyCommonZNA, 220, -2.0, 20.0, VarManager::kEnergyCommonZNC); } + if (subGroupStr.Contains("merging")) { + // 1D histograms + hm->AddHistogram(histClass, "BimodalCoeffUnbinned", "Bimodal coefficient unbinned", false, 1001, 0.0, 1.001, VarManager::kDCAzBimodalityCoefficient); + hm->AddHistogram(histClass, "BimodalCoeffBinned", "Bimodal coefficient binned", false, 1001, 0.0, 1.001, VarManager::kDCAzBimodalityCoefficientBinned); + hm->AddHistogram(histClass, "BimodalCoeffBinnedTrim1", "Bimodal coefficient binned, trim 1", false, 1001, 0.0, 1.001, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed1); + hm->AddHistogram(histClass, "BimodalCoeffBinnedTrim2", "Bimodal coefficient binned, trim 2", false, 1001, 0.0, 1.001, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed2); + hm->AddHistogram(histClass, "BimodalCoeffBinnedTrim3", "Bimodal coefficient binned, trim 3", false, 1001, 0.0, 1.001, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed3); + hm->AddHistogram(histClass, "DCAzMean", "DCAz per event mean", false, 3000, -15.0, 15.0, VarManager::kDCAzMean); + hm->AddHistogram(histClass, "DCAzMeanTrimmed1", "DCAz per event mean, trim 1", false, 3000, -15.0, 15.0, VarManager::kDCAzMeanBinnedTrimmed1); + hm->AddHistogram(histClass, "DCAzMeanTrimmed2", "DCAz per event mean, trim 2", false, 3000, -15.0, 15.0, VarManager::kDCAzMeanBinnedTrimmed2); + hm->AddHistogram(histClass, "DCAzMeanTrimmed3", "DCAz per event mean, trim 3", false, 3000, -15.0, 15.0, VarManager::kDCAzMeanBinnedTrimmed3); + hm->AddHistogram(histClass, "DCAzRMS", "DCAz per event RMS", false, 3000, 0.0, 15.0, VarManager::kDCAzRMS); + hm->AddHistogram(histClass, "DCAzRMSTrimmed1", "DCAz per event RMS, trim 1", false, 3000, 0.0, 15.0, VarManager::kDCAzRMSBinnedTrimmed1); + hm->AddHistogram(histClass, "DCAzRMSTrimmed2", "DCAz per event RMS, trim 2", false, 3000, 0.0, 15.0, VarManager::kDCAzRMSBinnedTrimmed2); + hm->AddHistogram(histClass, "DCAzRMSTrimmed3", "DCAz per event RMS, trim 3", false, 3000, 0.0, 15.0, VarManager::kDCAzRMSBinnedTrimmed3); + hm->AddHistogram(histClass, "DCAzSkewness", "DCAz per event skewness", false, 1000, 0.0, 100.0, VarManager::kDCAzSkewness); + hm->AddHistogram(histClass, "DCAzKurtosis", "DCAz per event kurtosis", false, 1001, 0.0, 1.001, VarManager::kDCAzKurtosis); + hm->AddHistogram(histClass, "NPeaks", "Number of peaks in DCAz distribution per event", false, 100, 0.0, 100.0, VarManager::kDCAzNPeaks); + hm->AddHistogram(histClass, "NPeaksTrimmed1", "Number of peaks in DCAz distribution per event, trim 1", false, 100, 0.0, 100.0, VarManager::kDCAzNPeaksTrimmed1); + hm->AddHistogram(histClass, "NPeaksTrimmed2", "Number of peaks in DCAz distribution per event, trim 2", false, 100, 0.0, 100.0, VarManager::kDCAzNPeaksTrimmed2); + hm->AddHistogram(histClass, "NPeaksTrimmed3", "Number of peaks in DCAz distribution per event, trim 3", false, 100, 0.0, 100.0, VarManager::kDCAzNPeaksTrimmed3); + hm->AddHistogram(histClass, "FracAbove100um", "Fraction of tracks with DCAz > 100 um", false, 1000, 0.0, 1.0, VarManager::kDCAzFracAbove100um); + hm->AddHistogram(histClass, "FracAbove200um", "Fraction of tracks with DCAz > 200 um", false, 1000, 0.0, 1.0, VarManager::kDCAzFracAbove200um); + hm->AddHistogram(histClass, "FracAbove500um", "Fraction of tracks with DCAz > 500 um", false, 1000, 0.0, 1.0, VarManager::kDCAzFracAbove500um); + hm->AddHistogram(histClass, "FracAbove1mm", "Fraction of tracks with DCAz > 1 mm", false, 1000, 0.0, 1.0, VarManager::kDCAzFracAbove1mm); + hm->AddHistogram(histClass, "FracAbove2mm", "Fraction of tracks with DCAz > 2 mm", false, 1000, 0.0, 1.0, VarManager::kDCAzFracAbove2mm); + hm->AddHistogram(histClass, "FracAbove5mm", "Fraction of tracks with DCAz > 5 mm", false, 1000, 0.0, 1.0, VarManager::kDCAzFracAbove5mm); + hm->AddHistogram(histClass, "FracAbove10mm", "Fraction of tracks with DCAz > 10 mm", false, 1000, 0.0, 1.0, VarManager::kDCAzFracAbove10mm); + // 2D histograms + // bimodality coefficients vs each other + hm->AddHistogram(histClass, "BimodalityUnbinned_BimodalityBinned", "Bimodality unbinned vs binned", false, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficient, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinned); + hm->AddHistogram(histClass, "BimodalityUnbinned_BimodalityBinnedTrim1", "Bimodality unbinned vs binned, trim 1", false, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficient, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed1); + hm->AddHistogram(histClass, "BimodalityUnbinned_BimodalityBinnedTrim2", "Bimodality unbinned vs binned, trim 2", false, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficient, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed2); + hm->AddHistogram(histClass, "BimodalityUnbinned_BimodalityBinnedTrim3", "Bimodality unbinned vs binned, trim 3", false, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficient, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed3); + hm->AddHistogram(histClass, "BimodalityBinned_BimodalityBinnedTrim1", "Bimodality binned vs binned, trim 1", false, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinned, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed1); + hm->AddHistogram(histClass, "BimodalityBinned_BimodalityBinnedTrim2", "Bimodality binned vs binned, trim 2", false, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinned, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed2); + hm->AddHistogram(histClass, "BimodalityBinned_BimodalityBinnedTrim3", "Bimodality binned vs binned, trim 3", false, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinned, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed3); + hm->AddHistogram(histClass, "BimodalityBinnedTrim1_BimodalityBinnedTrim2", "Bimodality binned, trim 1 vs binned, trim 2", false, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed1, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed2); + hm->AddHistogram(histClass, "BimodalityBinnedTrim1_BimodalityBinnedTrim3", "Bimodality binned, trim 1 vs binned, trim 3", false, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed1, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed3); + hm->AddHistogram(histClass, "BimodalityBinnedTrim2_BimodalityBinnedTrim3", "Bimodality binned, trim 2 vs binned, trim 3", false, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed2, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed3); + // bimodality coefficients vs DCAz mean and RMS + hm->AddHistogram(histClass, "BimodalityUnbinned_DCAzMean", "Bimodality unbinned vs DCAz mean", false, 400, -2.0, 2.0, VarManager::kDCAzMean, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficient); + hm->AddHistogram(histClass, "BimodalityBinned_DCAzMean", "Bimodality binned vs DCAz mean", false, 400, -2.0, 2.0, VarManager::kDCAzMean, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinned); + hm->AddHistogram(histClass, "BimodalityBinnedTrim1_DCAzMeanTrimmed1", "Bimodality binned, trim 1 vs DCAz mean", false, 400, -2.0, 2.0, VarManager::kDCAzMeanBinnedTrimmed1, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed1); + hm->AddHistogram(histClass, "BimodalityBinnedTrim2_DCAzMeanTrimmed2", "Bimodality binned, trim 2 vs DCAz mean", false, 400, -2.0, 2.0, VarManager::kDCAzMeanBinnedTrimmed2, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed2); + hm->AddHistogram(histClass, "BimodalityBinnedTrim3_DCAzMeanTrimmed3", "Bimodality binned, trim 3 vs DCAz mean", false, 400, -2.0, 2.0, VarManager::kDCAzMeanBinnedTrimmed3, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed3); + hm->AddHistogram(histClass, "BimodalityUnbinned_DCAzRMS", "Bimodality unbinned vs DCAz RMS", false, 400, 0.0, 2.0, VarManager::kDCAzRMS, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficient); + hm->AddHistogram(histClass, "BimodalityBinned_DCAzRMS", "Bimodality binned vs DCAz RMS", false, 400, 0.0, 2.0, VarManager::kDCAzRMS, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinned); + hm->AddHistogram(histClass, "BimodalityBinnedTrim1_DCAzRMSTrimmed1", "Bimodality binned, trim 1 vs DCAz RMS", false, 400, 0.0, 2.0, VarManager::kDCAzRMSBinnedTrimmed1, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed1); + hm->AddHistogram(histClass, "BimodalityBinnedTrim2_DCAzRMSTrimmed2", "Bimodality binned, trim 2 vs DCAz RMS", false, 400, 0.0, 2.0, VarManager::kDCAzRMSBinnedTrimmed2, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed2); + hm->AddHistogram(histClass, "BimodalityBinnedTrim3_DCAzRMSTrimmed3", "Bimodality binned, trim 3 vs DCAz RMS", false, 400, 0.0, 2.0, VarManager::kDCAzRMSBinnedTrimmed3, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed3); + // bimodality coefficients vs number of peaks + hm->AddHistogram(histClass, "BimodalityUnbinned_NPeaks", "Bimodality unbinned vs number of peaks", false, 50, 0.0, 50.0, VarManager::kDCAzNPeaks, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficient); + hm->AddHistogram(histClass, "BimodalityBinned_NPeaks", "Bimodality binned vs number of peaks", false, 50, 0.0, 50.0, VarManager::kDCAzNPeaks, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinned); + hm->AddHistogram(histClass, "BimodalityBinnedTrim1_NPeaks", "Bimodality binned, trim 1 vs number of peaks", false, 50, 0.0, 50.0, VarManager::kDCAzNPeaksTrimmed1, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed1); + hm->AddHistogram(histClass, "BimodalityBinnedTrim2_NPeaks", "Bimodality binned, trim 2 vs number of peaks", false, 50, 0.0, 50.0, VarManager::kDCAzNPeaksTrimmed2, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed2); + hm->AddHistogram(histClass, "BimodalityBinnedTrim3_NPeaks", "Bimodality binned, trim 3 vs number of peaks", false, 50, 0.0, 50.0, VarManager::kDCAzNPeaksTrimmed3, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed3); + // bimodality coefficients vs fraction of tracks above certain DCAz thresholds + hm->AddHistogram(histClass, "BimodalityUnbinned_FracAbove100um", "Bimodality unbinned vs fraction of tracks with DCAz > 100 um", false, 100, 0.0, 1.0, VarManager::kDCAzFracAbove100um, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficient); + hm->AddHistogram(histClass, "BimodalityBinned_FracAbove100um", "Bimodality binned vs fraction of tracks with DCAz > 100 um", false, 100, 0.0, 1.0, VarManager::kDCAzFracAbove100um, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinned); + hm->AddHistogram(histClass, "BimodalityBinnedTrim1_FracAbove100um", "Bimodality binned, trim 1 vs fraction of tracks with DCAz > 100 um", false, 100, 0.0, 1.0, VarManager::kDCAzFracAbove100um, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed1); + hm->AddHistogram(histClass, "BimodalityBinnedTrim2_FracAbove100um", "Bimodality binned, trim 2 vs fraction of tracks with DCAz > 100 um", false, 100, 0.0, 1.0, VarManager::kDCAzFracAbove100um, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed2); + hm->AddHistogram(histClass, "BimodalityBinnedTrim3_FracAbove100um", "Bimodality binned, trim 3 vs fraction of tracks with DCAz > 100 um", false, 100, 0.0, 1.0, VarManager::kDCAzFracAbove100um, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed3); + hm->AddHistogram(histClass, "BimodalityUnbinned_FracAbove500um", "Bimodality unbinned vs fraction of tracks with DCAz > 500 um", false, 100, 0.0, 1.0, VarManager::kDCAzFracAbove500um, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficient); + hm->AddHistogram(histClass, "BimodalityBinned_FracAbove500um", "Bimodality binned vs fraction of tracks with DCAz > 500 um", false, 100, 0.0, 1.0, VarManager::kDCAzFracAbove500um, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinned); + hm->AddHistogram(histClass, "BimodalityBinnedTrim1_FracAbove500um", "Bimodality binned, trim 1 vs fraction of tracks with DCAz > 500 um", false, 100, 0.0, 1.0, VarManager::kDCAzFracAbove500um, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed1); + hm->AddHistogram(histClass, "BimodalityBinnedTrim2_FracAbove500um", "Bimodality binned, trim 2 vs fraction of tracks with DCAz > 500 um", false, 100, 0.0, 1.0, VarManager::kDCAzFracAbove500um, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed2); + hm->AddHistogram(histClass, "BimodalityBinnedTrim3_FracAbove500um", "Bimodality binned, trim 3 vs fraction of tracks with DCAz > 500 um", false, 100, 0.0, 1.0, VarManager::kDCAzFracAbove500um, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed3); + hm->AddHistogram(histClass, "BimodalityUnbinned_FracAbove2mm", "Bimodality unbinned vs fraction of tracks with DCAz > 2 mm", false, 100, 0.0, 1.0, VarManager::kDCAzFracAbove2mm, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficient); + hm->AddHistogram(histClass, "BimodalityBinned_FracAbove2mm", "Bimodality binned vs fraction of tracks with DCAz > 2 mm", false, 100, 0.0, 1.0, VarManager::kDCAzFracAbove2mm, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinned); + hm->AddHistogram(histClass, "BimodalityBinnedTrim1_FracAbove2mm", "Bimodality binned, trim 1 vs fraction of tracks with DCAz > 2 mm", false, 100, 0.0, 1.0, VarManager::kDCAzFracAbove2mm, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed1); + hm->AddHistogram(histClass, "BimodalityBinnedTrim2_FracAbove2mm", "Bimodality binned, trim 2 vs fraction of tracks with DCAz > 2 mm", false, 100, 0.0, 1.0, VarManager::kDCAzFracAbove2mm, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed2); + hm->AddHistogram(histClass, "BimodalityBinnedTrim3_FracAbove2mm", "Bimodality binned, trim 3 vs fraction of tracks with DCAz > 2 mm", false, 100, 0.0, 1.0, VarManager::kDCAzFracAbove2mm, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed3); + hm->AddHistogram(histClass, "BimodalityUnbinned_FracAbove10mm", "Bimodality unbinned vs fraction of tracks with DCAz > 10 mm", false, 100, 0.0, 1.0, VarManager::kDCAzFracAbove10mm, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficient); + hm->AddHistogram(histClass, "BimodalityBinned_FracAbove10mm", "Bimodality binned vs fraction of tracks with DCAz > 10 mm", false, 100, 0.0, 1.0, VarManager::kDCAzFracAbove10mm, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinned); + hm->AddHistogram(histClass, "BimodalityBinnedTrim1_FracAbove10mm", "Bimodality binned, trim 1 vs fraction of tracks with DCAz > 10 mm", false, 100, 0.0, 1.0, VarManager::kDCAzFracAbove10mm, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed1); + hm->AddHistogram(histClass, "BimodalityBinnedTrim2_FracAbove10mm", "Bimodality binned, trim 2 vs fraction of tracks with DCAz > 10 mm", false, 100, 0.0, 1.0, VarManager::kDCAzFracAbove10mm, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed2); + hm->AddHistogram(histClass, "BimodalityBinnedTrim3_FracAbove10mm", "Bimodality binned, trim 3 vs fraction of tracks with DCAz > 10 mm", false, 100, 0.0, 1.0, VarManager::kDCAzFracAbove10mm, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed3); + + // All the event merging vs centrality FT0C + hm->AddHistogram(histClass, "BimodalityUnbinned_CentFT0C", "Bimodality unbinned vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficient); + hm->AddHistogram(histClass, "BimodalityBinned_CentFT0C", "Bimodality binned vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinned); + hm->AddHistogram(histClass, "BimodalityBinnedTrim1_CentFT0C", "Bimodality binned, trim 1 vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed1); + hm->AddHistogram(histClass, "BimodalityBinnedTrim2_CentFT0C", "Bimodality binned, trim 2 vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed2); + hm->AddHistogram(histClass, "BimodalityBinnedTrim3_CentFT0C", "Bimodality binned, trim 3 vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed3); + hm->AddHistogram(histClass, "DCAzMean_CentFT0C", "DCAz per event mean vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 400, -2.0, 2.0, VarManager::kDCAzMean); + hm->AddHistogram(histClass, "DCAzMeanTrimmed1_CentFT0C", "DCAz per event mean, trim 1 vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 400, -2.0, 2.0, VarManager::kDCAzMeanBinnedTrimmed1); + hm->AddHistogram(histClass, "DCAzMeanTrimmed2_CentFT0C", "DCAz per event mean, trim 2 vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 400, -2.0, 2.0, VarManager::kDCAzMeanBinnedTrimmed2); + hm->AddHistogram(histClass, "DCAzMeanTrimmed3_CentFT0C", "DCAz per event mean, trim 3 vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 400, -2.0, 2.0, VarManager::kDCAzMeanBinnedTrimmed3); + hm->AddHistogram(histClass, "DCAzRMS_CentFT0C", "DCAz per event RMS vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 400, 0.0, 2.0, VarManager::kDCAzRMS); + hm->AddHistogram(histClass, "DCAzRMSTrimmed1_CentFT0C", "DCAz per event RMS, trim 1 vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 400, 0.0, 2.0, VarManager::kDCAzRMSBinnedTrimmed1); + hm->AddHistogram(histClass, "DCAzRMSTrimmed2_CentFT0C", "DCAz per event RMS, trim 2 vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 400, 0.0, 2.0, VarManager::kDCAzRMSBinnedTrimmed2); + hm->AddHistogram(histClass, "DCAzRMSTrimmed3_CentFT0C", "DCAz per event RMS, trim 3 vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 400, 0.0, 2.0, VarManager::kDCAzRMSBinnedTrimmed3); + hm->AddHistogram(histClass, "DCAzSkewness_CentFT0C", "DCAz per event skewness vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 1000, 0.0, 100.0, VarManager::kDCAzSkewness); + hm->AddHistogram(histClass, "DCAzKurtosis_CentFT0C", "DCAz per event kurtosis vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 1001, 0.0, 1.001, VarManager::kDCAzKurtosis); + hm->AddHistogram(histClass, "NPeaks_CentFT0C", "Number of peaks in DCAz distribution per event vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 100, 0.0, 100.0, VarManager::kDCAzNPeaks); + hm->AddHistogram(histClass, "NPeaksTrimmed1_CentFT0C", "Number of peaks in DCAz distribution per event, trim 1 vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 100, 0.0, 100.0, VarManager::kDCAzNPeaksTrimmed1); + hm->AddHistogram(histClass, "NPeaksTrimmed2_CentFT0C", "Number of peaks in DCAz distribution per event, trim 2 vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 100, 0.0, 100.0, VarManager::kDCAzNPeaksTrimmed2); + hm->AddHistogram(histClass, "NPeaksTrimmed3_CentFT0C", "Number of peaks in DCAz distribution per event, trim 3 vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 100, 0.0, 100.0, VarManager::kDCAzNPeaksTrimmed3); + hm->AddHistogram(histClass, "FracAbove100um_CentFT0C", "Fraction of tracks with DCAz > 100 um vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 100, 0.0, 1.0, VarManager::kDCAzFracAbove100um); + hm->AddHistogram(histClass, "FracAbove200um_CentFT0C", "Fraction of tracks with DCAz > 200 um vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 100, 0.0, 1.0, VarManager::kDCAzFracAbove200um); + hm->AddHistogram(histClass, "FracAbove500um_CentFT0C", "Fraction of tracks with DCAz > 500 um vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 100, 0.0, 1.0, VarManager::kDCAzFracAbove500um); + hm->AddHistogram(histClass, "FracAbove1mm_CentFT0C", "Fraction of tracks with DCAz > 1 mm vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 100, 0.0, 1.0, VarManager::kDCAzFracAbove1mm); + hm->AddHistogram(histClass, "FracAbove2mm_CentFT0C", "Fraction of tracks with DCAz > 2 mm vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 100, 0.0, 1.0, VarManager::kDCAzFracAbove2mm); + hm->AddHistogram(histClass, "FracAbove5mm_CentFT0C", "Fraction of tracks with DCAz > 5 mm vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 100, 0.0, 1.0, VarManager::kDCAzFracAbove5mm); + hm->AddHistogram(histClass, "FracAbove10mm_CentFT0C", "Fraction of tracks with DCAz > 10 mm vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 100, 0.0, 1.0, VarManager::kDCAzFracAbove10mm); + // histograms vs number of tracks with ITS + hm->AddHistogram(histClass, "BimodalityUnbinned_NTracksITS", "Bimodality unbinned vs number of tracks with ITS", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasITS, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficient); + hm->AddHistogram(histClass, "BimodalityBinnedTrimmed1_NTracksITS", "Bimodality binned, trimmed 1, vs number of tracks with ITS", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasITS, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed1); + hm->AddHistogram(histClass, "BimodalityBinnedTrimmed2_NTracksITS", "Bimodality binned, trimmed 2, vs number of tracks with ITS", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasITS, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed2); + hm->AddHistogram(histClass, "DCAzMean_NTracksITS", "DCAz mean vs number of tracks with ITS", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasITS, 100, 0.0, 1.0, VarManager::kDCAzMean); + hm->AddHistogram(histClass, "DCAzRMS_NTracksITS", "DCAz RMS vs number of tracks with ITS", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasITS, 100, 0.0, 1.0, VarManager::kDCAzRMS); + hm->AddHistogram(histClass, "NPeaksTrimmed1_NTracksITS", "Number of peaks in DCAz distribution per event, trim 1, vs number of tracks with ITS", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasITS, 50, 0.0, 50.0, VarManager::kDCAzNPeaksTrimmed1); + hm->AddHistogram(histClass, "NPeaksTrimmed2_NTracksITS", "Number of peaks in DCAz distribution per event, trim 2, vs number of tracks with ITS", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasITS, 50, 0.0, 50.0, VarManager::kDCAzNPeaksTrimmed2); + hm->AddHistogram(histClass, "FracAbove500um_NTracksITS", "Fraction of tracks with DCAz > 500 um vs number of tracks with ITS", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasITS, 100, 0.0, 1.0, VarManager::kDCAzFracAbove500um); + hm->AddHistogram(histClass, "FracAbove5mm_NTracksITS", "Fraction of tracks with DCAz > 5 mm vs number of tracks with ITS", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasITS, 100, 0.0, 1.0, VarManager::kDCAzFracAbove5mm); + // histograms vs number of tracks with TPC + hm->AddHistogram(histClass, "BimodalityUnbinned_NTracksTPC", "Bimodality unbinned vs number of tracks with TPC", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTPC, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficient); + hm->AddHistogram(histClass, "BimodalityBinnedTrimmed1_NTracksTPC", "Bimodality binned, trimmed 1, vs number of tracks with TPC", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTPC, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed1); + hm->AddHistogram(histClass, "BimodalityBinnedTrimmed2_NTracksTPC", "Bimodality binned, trimmed 2, vs number of tracks with TPC", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTPC, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed2); + hm->AddHistogram(histClass, "DCAzMean_NTracksTPC", "DCAz mean vs number of tracks with TPC", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTPC, 100, 0.0, 1.0, VarManager::kDCAzMean); + hm->AddHistogram(histClass, "DCAzRMS_NTracksTPC", "DCAz RMS vs number of tracks with TPC", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTPC, 100, 0.0, 1.0, VarManager::kDCAzRMS); + hm->AddHistogram(histClass, "NPeaksTrimmed1_NTracksTPC", "Number of peaks in DCAz distribution per event, trim 1, vs number of tracks with TPC", false, 100, 0.0, 1000.0, 50, 0.0, 50.0, VarManager::kDCAzNPeaksTrimmed1); + hm->AddHistogram(histClass, "NPeaksTrimmed2_NTracksTPC", "Number of peaks in DCAz distribution per event, trim 2, vs number of tracks with TPC", false, 100, 0.0, 1000.0, 50, 0.0, 50.0, VarManager::kDCAzNPeaksTrimmed2); + hm->AddHistogram(histClass, "FracAbove500um_NTracksTPC", "Fraction of tracks with DCAz > 500 um vs number of tracks with TPC", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTPC, 100, 0.0, 1.0, VarManager::kDCAzFracAbove500um); + hm->AddHistogram(histClass, "FracAbove5mm_NTracksTPC", "Fraction of tracks with DCAz > 5 mm vs number of tracks with TPC", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTPC, 100, 0.0, 1.0, VarManager::kDCAzFracAbove5mm); + // histograms vs number of tracks with TOF + hm->AddHistogram(histClass, "BimodalityUnbinned_NTracksTOF", "Bimodality unbinned vs number of tracks with TOF", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTOF, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficient); + hm->AddHistogram(histClass, "BimodalityBinnedTrimmed1_NTracksTOF", "Bimodality binned, trimmed 1, vs number of tracks with TOF", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTOF, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed1); + hm->AddHistogram(histClass, "BimodalityBinnedTrimmed2_NTracksTOF", "Bimodality binned, trimmed 2, vs number of tracks with TOF", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTOF, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed2); + hm->AddHistogram(histClass, "DCAzMean_NTracksTOF", "DCAz mean vs number of tracks with TOF", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTOF, 100, 0.0, 1.0, VarManager::kDCAzMean); + hm->AddHistogram(histClass, "DCAzRMS_NTracksTOF", "DCAz RMS vs number of tracks with TOF", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTOF, 100, 0.0, 1.0, VarManager::kDCAzRMS); + hm->AddHistogram(histClass, "NPeaksTrimmed1_NTracksTOF", "Number of peaks in DCAz distribution per event, trim 1, vs number of tracks with TOF", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTOF, 50, 0.0, 50.0, VarManager::kDCAzNPeaksTrimmed1); + hm->AddHistogram(histClass, "NPeaksTrimmed2_NTracksTOF", "Number of peaks in DCAz distribution per event, trim 2, vs number of tracks with TOF", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTOF, 50, 0.0, 50.0, VarManager::kDCAzNPeaksTrimmed2); + hm->AddHistogram(histClass, "FracAbove500um_NTracksTOF", "Fraction of tracks with DCAz > 500 um vs number of tracks with TOF", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTOF, 100, 0.0, 1.0, VarManager::kDCAzFracAbove500um); + hm->AddHistogram(histClass, "FracAbove5mm_NTracksTOF", "Fraction of tracks with DCAz > 5 mm vs number of tracks with TOF", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTOF, 100, 0.0, 1.0, VarManager::kDCAzFracAbove5mm); + // histograms vs number of tracks with TRD + hm->AddHistogram(histClass, "BimodalityUnbinned_NTracksTRD", "Bimodality unbinned vs number of tracks with TRD", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTRD, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficient); + hm->AddHistogram(histClass, "BimodalityBinnedTrimmed1_NTracksTRD", "Bimodality binned, trimmed 1, vs number of tracks with TRD", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTRD, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed1); + hm->AddHistogram(histClass, "BimodalityBinnedTrimmed2_NTracksTRD", "Bimodality binned, trimmed 2, vs number of tracks with TRD", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTRD, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed2); + hm->AddHistogram(histClass, "DCAzMean_NTracksTRD", "DCAz mean vs number of tracks with TRD", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTRD, 100, 0.0, 1.0, VarManager::kDCAzMean); + hm->AddHistogram(histClass, "DCAzRMS_NTracksTRD", "DCAz RMS vs number of tracks with TRD", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTRD, 100, 0.0, 1.0, VarManager::kDCAzRMS); + hm->AddHistogram(histClass, "NPeaksTrimmed1_NTracksTRD", "Number of peaks in DCAz distribution per event, trim 1, vs number of tracks with TRD", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTRD, 50, 0.0, 50.0, VarManager::kDCAzNPeaksTrimmed1); + hm->AddHistogram(histClass, "NPeaksTrimmed2_NTracksTRD", "Number of peaks in DCAz distribution per event, trim 2, vs number of tracks with TRD", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTRD, 50, 0.0, 50.0, VarManager::kDCAzNPeaksTrimmed2); + hm->AddHistogram(histClass, "FracAbove500um_NTracksTRD", "Fraction of tracks with DCAz > 500 um vs number of tracks with TRD", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTRD, 100, 0.0, 1.0, VarManager::kDCAzFracAbove500um); + hm->AddHistogram(histClass, "FracAbove5mm_NTracksTRD", "Fraction of tracks with DCAz > 5 mm vs number of tracks with TRD", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTRD, 100, 0.0, 1.0, VarManager::kDCAzFracAbove5mm); + } } // end "event" if (!groupStr.CompareTo("two-collisions")) { diff --git a/PWGDQ/Core/VarManager.cxx b/PWGDQ/Core/VarManager.cxx index af3bdcdefea..b058531989f 100644 --- a/PWGDQ/Core/VarManager.cxx +++ b/PWGDQ/Core/VarManager.cxx @@ -423,8 +423,66 @@ std::tuple VarManager::BimodalityCoeffic // trim the distribution if requested, by requiring a minimum of "trim" counts in each bin if (trim > 0) { for (int i = 0; i < nBins; ++i) { + // if the count in the bin is less than the trim value, set it to zero if (counts[i] < trim) { - counts[i] = 0; + // set the count to zero only if this is an isolated bin, + // i.e. if this count belongs to a peak, we want to keep it even if it has counts below the trim limit, as long as the whole peak is not below the trim limit + // check the previous bins until we find an empty bin or we reach the beginning of the histogram + int localPeakCount = counts[i]; + for (int j = i - 1; j >= 0; --j) { + if (counts[j] == 0) { + break; + } + localPeakCount += counts[j]; + } + // check the next bins until we find an empty bin or we reach the end of the histogram + for (int j = i + 1; j < nBins; ++j) { + if (counts[j] == 0) { + break; + } + localPeakCount += counts[j]; + } + if (localPeakCount < trim) { + counts[i] = 0; + } + } + } + } + if (trim < 0) { + // if trim is negative, then we remove all counts belonging to local peaks with an integrated count below 1/abs(trim) + for (int i = 0; i < nBins; ++i) { + if (counts[i] == 0) { + continue; // skip empty bins + } + // check the previous bins until we find an empty bin or we reach the beginning of the histogram + int localPeakCount = counts[i]; + for (int j = i - 1; j >= 0; --j) { + if (counts[j] == 0) { + break; + } + localPeakCount += counts[j]; + } + // check the next bins until we find an empty bin or we reach the end of the histogram + for (int j = i + 1; j < nBins; ++j) { + if (counts[j] == 0) { + break; + } + localPeakCount += counts[j]; + } + if (localPeakCount < (1.0 / std::abs(trim)) * data.size()) { + // set all bins belonging to this local peak to zero + for (int j = i; j >= 0; --j) { + if (counts[j] == 0) { + break; + } + counts[j] = 0; + } + for (int j = i + 1; j < nBins; ++j) { + if (counts[j] == 0) { + break; + } + counts[j] = 0; + } } } } @@ -453,7 +511,7 @@ std::tuple VarManager::BimodalityCoeffic } if (totalCounts == 0) { - return std::make_tuple(-1.0, -1.0, -1.0, -1.0, -1.0, -1); + return std::make_tuple(-1.0, -1.0, -1.0, -1.0, -1.0, nPeaks); } mean /= totalCounts; @@ -477,7 +535,7 @@ std::tuple VarManager::BimodalityCoeffic m4 /= totalCounts; if (m2 == 0.0) { - return std::make_tuple(-1.0, -1.0, -1.0, -1.0, -1.0, -1); + return std::make_tuple(-1.0, -1.0, -1.0, -1.0, -1.0, nPeaks); } float stddev = std::sqrt(m2); diff --git a/PWGDQ/Core/VarManager.h b/PWGDQ/Core/VarManager.h index cd3d31d7f05..389050980e2 100644 --- a/PWGDQ/Core/VarManager.h +++ b/PWGDQ/Core/VarManager.h @@ -2364,6 +2364,36 @@ void VarManager::FillEvent(T const& event, float* values) values[kBGFDDCpf] = event.bgFDDCpf(); } + // check if the template T type includes the O2remerge table and if so, fill the corresponding variables + if constexpr (requires { event.dcazBimodalityCoefficient(); }) { + values[kDCAzBimodalityCoefficient] = event.dcazBimodalityCoefficient(); + values[kDCAzBimodalityCoefficientBinned] = event.dcazBimodalityCoefficientBinned(); + values[kDCAzBimodalityCoefficientBinnedTrimmed1] = event.dcazBimodalityCoefficientBinnedTrimmed1(); + values[kDCAzBimodalityCoefficientBinnedTrimmed2] = event.dcazBimodalityCoefficientBinnedTrimmed2(); + values[kDCAzBimodalityCoefficientBinnedTrimmed3] = event.dcazBimodalityCoefficientBinnedTrimmed3(); + values[kDCAzMean] = event.dcazMean(); + values[kDCAzMeanBinnedTrimmed1] = event.dcazMeanBinnedTrimmed1(); + values[kDCAzMeanBinnedTrimmed2] = event.dcazMeanBinnedTrimmed2(); + values[kDCAzMeanBinnedTrimmed3] = event.dcazMeanBinnedTrimmed3(); + values[kDCAzRMS] = event.dcazRMS(); + values[kDCAzRMSBinnedTrimmed1] = event.dcazRMSBinnedTrimmed1(); + values[kDCAzRMSBinnedTrimmed2] = event.dcazRMSBinnedTrimmed2(); + values[kDCAzRMSBinnedTrimmed3] = event.dcazRMSBinnedTrimmed3(); + values[kDCAzSkewness] = event.dcazSkewness(); + values[kDCAzKurtosis] = event.dcazKurtosis(); + values[kDCAzNPeaks] = event.dcazNPeaks(); + values[kDCAzNPeaksTrimmed1] = event.dcazNPeaksTrimmed1(); + values[kDCAzNPeaksTrimmed2] = event.dcazNPeaksTrimmed2(); + values[kDCAzNPeaksTrimmed3] = event.dcazNPeaksTrimmed3(); + values[kDCAzFracAbove100um] = event.dcazFracAbove100um(); + values[kDCAzFracAbove200um] = event.dcazFracAbove200um(); + values[kDCAzFracAbove500um] = event.dcazFracAbove500um(); + values[kDCAzFracAbove1mm] = event.dcazFracAbove1mm(); + values[kDCAzFracAbove2mm] = event.dcazFracAbove2mm(); + values[kDCAzFracAbove5mm] = event.dcazFracAbove5mm(); + values[kDCAzFracAbove10mm] = event.dcazFracAbove10mm(); + } + // FillEventDerived(values); } @@ -2414,51 +2444,50 @@ void VarManager::FillEventTracks(T const& tracks, float* values) auto [bimodalityCoefficientBin, meanBin, stddevBin, skewnessBin, kurtosisBin, nPeaksBin] = BimodalityCoefficientAndNPeaks(dcazValues, 0.005); if (stddevBin > -1.0) { values[kDCAzBimodalityCoefficientBinned] = bimodalityCoefficientBin; - values[kDCAzNPeaks] = nPeaksBin; } else { values[kDCAzBimodalityCoefficientBinned] = -9999.0; - values[kDCAzNPeaks] = -9999.0; } + values[kDCAzNPeaks] = nPeaksBin; cout << "Bimodality coefficient binned: " << bimodalityCoefficientBin << ", mean: " << mean << ", stddev: " << stddev << ", skewness: " << skewness << ", kurtosis: " << kurtosis << ", nPeaks: " << nPeaksBin << endl; - // compute the binned bimodality coefficient and related statistics with a bin width of 50um and trimming of 1, 2, 3 entries per bin - auto [bimodalityCoefficientBinTrimmed1, meanBinTrimmed1, stddevBinTrimmed1, skewnessBinTrimmed1, kurtosisBinTrimmed1, nPeaksBinTrimmed1] = BimodalityCoefficientAndNPeaks(dcazValues, 0.005, 2); + // compute the binned bimodality coefficient and related statistics with a bin width of 50um and different trimming versions + // more then 3 counts per bin + auto [bimodalityCoefficientBinTrimmed1, meanBinTrimmed1, stddevBinTrimmed1, skewnessBinTrimmed1, kurtosisBinTrimmed1, nPeaksBinTrimmed1] = BimodalityCoefficientAndNPeaks(dcazValues, 0.005, 4); if (stddevBinTrimmed1 > -1.0) { values[kDCAzBimodalityCoefficientBinnedTrimmed1] = bimodalityCoefficientBinTrimmed1; values[kDCAzMeanBinnedTrimmed1] = meanBinTrimmed1; values[kDCAzRMSBinnedTrimmed1] = stddevBinTrimmed1; - values[kDCAzNPeaksTrimmed1] = nPeaksBinTrimmed1; } else { values[kDCAzBimodalityCoefficientBinnedTrimmed1] = -9999.0; values[kDCAzMeanBinnedTrimmed1] = -9999.0; values[kDCAzRMSBinnedTrimmed1] = -9999.0; - values[kDCAzNPeaksTrimmed1] = -9999.0; } + values[kDCAzNPeaksTrimmed1] = nPeaksBinTrimmed1; cout << "Bimodality coefficient (trimmed 1): " << bimodalityCoefficientBinTrimmed1 << ", mean: " << meanBinTrimmed1 << ", stddev: " << stddevBinTrimmed1 << ", skewness: " << skewnessBinTrimmed1 << ", kurtosis: " << kurtosisBinTrimmed1 << ", nPeaks: " << nPeaksBinTrimmed1 << endl; - auto [bimodalityCoefficientBinTrimmed2, meanBinTrimmed2, stddevBinTrimmed2, skewnessBinTrimmed2, kurtosisBinTrimmed2, nPeaksBinTrimmed2] = BimodalityCoefficientAndNPeaks(dcazValues, 0.005, 3); + // more than 3% of the entries per peak + auto [bimodalityCoefficientBinTrimmed2, meanBinTrimmed2, stddevBinTrimmed2, skewnessBinTrimmed2, kurtosisBinTrimmed2, nPeaksBinTrimmed2] = BimodalityCoefficientAndNPeaks(dcazValues, 0.005, -100); if (stddevBinTrimmed2 > -1.0) { values[kDCAzBimodalityCoefficientBinnedTrimmed2] = bimodalityCoefficientBinTrimmed2; values[kDCAzMeanBinnedTrimmed2] = meanBinTrimmed2; values[kDCAzRMSBinnedTrimmed2] = stddevBinTrimmed2; - values[kDCAzNPeaksTrimmed2] = nPeaksBinTrimmed2; } else { values[kDCAzBimodalityCoefficientBinnedTrimmed2] = -9999.0; values[kDCAzMeanBinnedTrimmed2] = -9999.0; values[kDCAzRMSBinnedTrimmed2] = -9999.0; - values[kDCAzNPeaksTrimmed2] = -9999.0; } + values[kDCAzNPeaksTrimmed2] = nPeaksBinTrimmed2; cout << "Bimodality coefficient (trimmed 2): " << bimodalityCoefficientBinTrimmed2 << ", mean: " << meanBinTrimmed2 << ", stddev: " << stddevBinTrimmed2 << ", skewness: " << skewnessBinTrimmed2 << ", kurtosis: " << kurtosisBinTrimmed2 << ", nPeaks: " << nPeaksBinTrimmed2 << endl; - auto [bimodalityCoefficientBinTrimmed3, meanBinTrimmed3, stddevBinTrimmed3, skewnessBinTrimmed3, kurtosisBinTrimmed3, nPeaksBinTrimmed3] = BimodalityCoefficientAndNPeaks(dcazValues, 0.005, 4); + // more than 5% of the entries per peak + auto [bimodalityCoefficientBinTrimmed3, meanBinTrimmed3, stddevBinTrimmed3, skewnessBinTrimmed3, kurtosisBinTrimmed3, nPeaksBinTrimmed3] = BimodalityCoefficientAndNPeaks(dcazValues, 0.005, -20); if (stddevBinTrimmed3 > -1.0) { values[kDCAzBimodalityCoefficientBinnedTrimmed3] = bimodalityCoefficientBinTrimmed3; values[kDCAzMeanBinnedTrimmed3] = meanBinTrimmed3; values[kDCAzRMSBinnedTrimmed3] = stddevBinTrimmed3; - values[kDCAzNPeaksTrimmed3] = nPeaksBinTrimmed3; } else { values[kDCAzBimodalityCoefficientBinnedTrimmed3] = -9999.0; values[kDCAzMeanBinnedTrimmed3] = -9999.0; values[kDCAzRMSBinnedTrimmed3] = -9999.0; - values[kDCAzNPeaksTrimmed3] = -9999.0; } + values[kDCAzNPeaksTrimmed3] = nPeaksBinTrimmed3; cout << "Bimodality coefficient (trimmed 3): " << bimodalityCoefficientBinTrimmed3 << ", mean: " << meanBinTrimmed3 << ", stddev: " << stddevBinTrimmed3 << ", skewness: " << skewnessBinTrimmed3 << ", kurtosis: " << kurtosisBinTrimmed3 << ", nPeaks: " << nPeaksBinTrimmed3 << endl; // compute fraction of tracks with |DCAz| > 100um, 200um, 500um, 1mm, 2mm, 5mm, 10mm diff --git a/PWGDQ/Tasks/tableReader_withAssoc.cxx b/PWGDQ/Tasks/tableReader_withAssoc.cxx index 1cd2cbad0b5..2b112f3c15d 100644 --- a/PWGDQ/Tasks/tableReader_withAssoc.cxx +++ b/PWGDQ/Tasks/tableReader_withAssoc.cxx @@ -194,8 +194,8 @@ DECLARE_SOA_TABLE(JPsieeCandidates, "AOD", "DQPSEUDOPROPER", dqanalysisflags::Ma } // namespace o2::aod // Declarations of various short names -using MyEvents = soa::Join; -using MyEventsMultExtra = soa::Join; +using MyEvents = soa::Join; +using MyEventsMultExtra = soa::Join; using MyEventsMultExtraQVector = soa::Join; using MyEventsZdc = soa::Join; using MyEventsMultExtraZdc = soa::Join; From c0f8013ce6363af68408f3ad45c1a6cd0fe87b7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Jura=C4=8Dka?= <137087737+jjuracka@users.noreply.github.com> Date: Sun, 22 Feb 2026 19:19:26 +0100 Subject: [PATCH 021/347] [PWGUD] updates to upcRhoAnalysis.cxx (#15099) --- PWGUD/Tasks/upcRhoAnalysis.cxx | 76 +++++++++++++++++++--------------- 1 file changed, 43 insertions(+), 33 deletions(-) diff --git a/PWGUD/Tasks/upcRhoAnalysis.cxx b/PWGUD/Tasks/upcRhoAnalysis.cxx index 721070ff427..2b5d7405fca 100644 --- a/PWGUD/Tasks/upcRhoAnalysis.cxx +++ b/PWGUD/Tasks/upcRhoAnalysis.cxx @@ -175,33 +175,34 @@ struct UpcRhoAnalysis { const std::vector runNumbers = {544013, 544028, 544032, 544091, 544095, 544098, 544116, 544121, 544122, 544123, 544124, 544184, 544185, 544389, 544390, 544391, 544392, 544451, 544454, 544474, 544475, 544476, 544477, 544490, 544491, 544492, 544508, 544510, 544511, 544512, 544514, 544515, 544518, 544548, 544549, 544550, 544551, 544564, 544565, 544567, 544568, 544580, 544582, 544583, 544585, 544614, 544640, 544652, 544653, 544672, 544674, 544692, 544693, 544694, 544696, 544739, 544742, 544754, 544767, 544794, 544795, 544797, 544813, 544868, 544886, 544887, 544896, 544911, 544913, 544914, 544917, 544931, 544947, 544961, 544963, 544964, 544968, 544991, 544992, 545004, 545008, 545009, 545041, 545042, 545044, 545047, 545060, 545062, 545063, 545064, 545066, 545086, 545103, 545117, 545171, 545184, 545185, 545210, 545222, 545223, 545246, 545249, 545262, 545289, 545291, 545294, 545295, 545296, 545311, 545312, 545332, 545345, 545367}; AxisSpec runNumberAxis = {static_cast(runNumbers.size()), 0.5, static_cast(runNumbers.size()) + 0.5, "run number"}; - Configurable isPO{"isPO", false, "process proton-oxygen data"}; + Configurable isPO{"isPO", false, "processing p-O data?"}; - Configurable cutGapSide{"cutGapSide", true, "apply gap side cut"}; + Configurable cutGapSide{"cutGapSide", true, "apply gap side cut?"}; Configurable gapSide{"gapSide", 2, "required gap side"}; - Configurable useTrueGap{"useTrueGap", false, "use true gap"}; + Configurable useTrueGap{"useTrueGap", false, "use true gap?"}; Configurable cutTrueGapSideFV0{"cutTrueGapSideFV0", 180000, "FV0A threshold for SG selector"}; Configurable cutTrueGapSideFT0A{"cutTrueGapSideFT0A", 150., "FT0A threshold for SG selector"}; Configurable cutTrueGapSideFT0C{"cutTrueGapSideFT0C", 50., "FT0C threshold for SG selector"}; Configurable cutTrueGapSideZDC{"cutTrueGapSideZDC", 10000., "ZDC threshold for SG selector. 0 is <1n, 4.2 is <2n, 6.7 is <3n, 9.5 is <4n, 12.5 is <5n"}; - Configurable requireTof{"requireTof", false, "require TOF signal"}; - Configurable useRecoFlag{"useRecoFlag", false, "use reco flag for event selection"}; + Configurable requireTof{"requireTof", false, "require TOF signal?"}; + Configurable useRecoFlag{"useRecoFlag", false, "use UPC/STD reconstruction flag for event selection?"}; Configurable cutRecoFlag{"cutRecoFlag", 1, "0 = std mode, 1 = upc mode"}; - Configurable useRctFlag{"useRctFlag", false, "use RCT flags for event selection"}; + Configurable useRctFlag{"useRctFlag", false, "use RCT flags for event selection?"}; Configurable cutRctFlag{"cutRctFlag", 0, "0 = off, 1 = CBT, 2 = CBT+ZDC, 3 = CBThadron, 4 = CBThadron+ZDC"}; - Configurable selectRuns{"selectRuns", false, "select runs from the list"}; + Configurable selectRuns{"selectRuns", false, "select runs?"}; Configurable> selectedRuns{"selectedRuns", {544013, 544028, 544032, 544091, 544095, 544098, 544116, 544121, 544122, 544123, 544124, 544184, 544185, 544389, 544390, 544391, 544392, 544451, 544454, 544474, 544475, 544476, 544477, 544490, 544491, 544492, 544508, 544510, 544511, 544512, 544514, 544515, 544518, 544548, 544549, 544550, 544551, 544564, 544565, 544567, 544568, 544580, 544582, 544583, 544585, 544614, 544640, 544652, 544653, 544672, 544674, 544692, 544693, 544694, 544696, 544739, 544742, 544754, 544767, 544794, 544795, 544797, 544813, 544868, 544886, 544887, 544896, 544913, 544914, 544917, 544931, 544947, 544961, 544963, 544964, 544968, 544992, 545009, 545044, 545047, 545063, 545064, 545066, 545185, 545210, 545223, 545249, 545291, 545294, 545295, 545296, 545312}, "list of selected runs"}; Configurable collisionsPosZMaxCut{"collisionsPosZMaxCut", 10.0, "max Z position cut on collisions"}; - Configurable cutNumContribs{"cutNumContribs", true, "cut on number of contributors"}; + Configurable cutNumContribs{"cutNumContribs", true, "cut on number of contributors?"}; Configurable collisionsNumContribsMaxCut{"collisionsNumContribsMaxCut", 2, "max number of contributors cut on collisions"}; - Configurable znCommonEnergyCut{"znCommonEnergyCut", 0.0, "ZN common energy cut"}; - Configurable znTimeCut{"znTimeCut", 2.0, "ZN time cut"}; + Configurable znTimeCut{"znTimeCut", 2.0, "ZN time cut (ns)"}; + Configurable cutOccupancy{"cutOccupancy", true, "cut on collision occupancy?"}; + Configurable occupancyCut{"occupancyCut", 1000.0, "occupancy cut"}; Configurable tracksTpcNSigmaPiCut{"tracksTpcNSigmaPiCut", 3.0, "TPC nSigma pion cut"}; - Configurable rejectLowerProbPairs{"rejectLowerProbPairs", true, "reject track pairs with lower El or Ka PID radii"}; + Configurable rejectLowerProbPairs{"rejectLowerProbPairs", true, "reject track pairs with smaller El/Ka/Pr PID radii?"}; Configurable tracksDcaMaxCut{"tracksDcaMaxCut", 1.0, "max DCA cut on tracks"}; Configurable tracksMinItsNClsCut{"tracksMinItsNClsCut", 4, "min ITS clusters cut"}; Configurable tracksMaxItsChi2NClCut{"tracksMaxItsChi2NClCut", 3.0, "max ITS chi2/Ncls cut"}; @@ -226,7 +227,7 @@ struct UpcRhoAnalysis { ConfigurableAxis deltaPhiAxis{"deltaPhiAxis", {182, -o2::constants::math::PI, o2::constants::math::PI}, "#Delta#it{#phi} (rad)"}; ConfigurableAxis znCommonEnergyAxis{"znCommonEnergyAxis", {250, -5.0, 20.0}, "ZN common energy (TeV)"}; ConfigurableAxis znTimeAxis{"znTimeAxis", {200, -10.0, 10.0}, "ZN time (ns)"}; - ConfigurableAxis nSigmaAxis{"nSigmaAxis", {600, -30.0, 30.0}, "TPC #it{n#sigma}"}; + ConfigurableAxis nSigmaAxis{"nSigmaAxis", {400, -20.0, 20.0}, "TPC #it{n#sigma}"}; ConfigurableAxis resolutionAxis{"resolutionAxis", {2000, -1.0, 1.0}, "resolution"}; HistogramRegistry rQC{"rQC", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -251,35 +252,37 @@ struct UpcRhoAnalysis { rQC.add("QC/collisions/all/hTotalFV0AmplitudeA", ";FV0A amplitude;counts", kTH1D, {{300, 0.0, 300.0}}); rQC.add("QC/collisions/all/hTotalFDDAmplitudeA", ";FDDA amplitude;counts", kTH1D, {{160, 0.0, 160.0}}); rQC.add("QC/collisions/all/hTotalFDDAmplitudeC", ";FDDC amplitude;counts", kTH1D, {{50, 0.0, 50.0}}); - rQC.add("QC/collisions/all/hTimeFT0A", ";FT0A time (ns);counts", kTH1D, {{500, -10.0, 40.0}}); - rQC.add("QC/collisions/all/hTimeFT0C", ";FT0C time (ns);counts", kTH1D, {{500, -10.0, 40.0}}); - rQC.add("QC/collisions/all/hTimeFV0A", ";FV0A time (ns);counts", kTH1D, {{500, -10.0, 40.0}}); - rQC.add("QC/collisions/all/hTimeFDDA", ";FDDA time (ns);counts", kTH1D, {{500, -10.0, 40.0}}); - rQC.add("QC/collisions/all/hTimeFDDC", ";FDDC time (ns);counts", kTH1D, {{500, -10.0, 40.0}}); - rQC.add("QC/collisions/all/hOccupancyInTime", ";occupancy in time;counts", kTH1D, {{1100, -100.0, 1000.0}}); + rQC.add("QC/collisions/all/hTimeFT0A", ";FT0A time (ns);counts", kTH1D, {{400, -5.0, 35.0}}); + rQC.add("QC/collisions/all/hTimeFT0C", ";FT0C time (ns);counts", kTH1D, {{400, -5.0, 35.0}}); + rQC.add("QC/collisions/all/hTimeFV0A", ";FV0A time (ns);counts", kTH1D, {{400, -5.0, 35.0}}); + rQC.add("QC/collisions/all/hTimeFDDA", ";FDDA time (ns);counts", kTH1D, {{400, -5.0, 35.0}}); + rQC.add("QC/collisions/all/hTimeFDDC", ";FDDC time (ns);counts", kTH1D, {{400, -5.0, 35.0}}); + rQC.add("QC/collisions/all/hOccupancyInTime", ";occupancy in time;counts", kTH1D, {{1100, 0.0, 1100.0}}); // events with selected rho candidates rQC.addClone("QC/collisions/all/", "QC/collisions/trackSelections/"); rQC.addClone("QC/collisions/all/", "QC/collisions/systemSelections/"); - std::vector collisionSelectionCounterLabels = {"all collisions", "rapidity gap", "ITS-TPC vertex", "same bunch pile-up", "ITS ROF border", "TF border", "#it{z} position", "number of contributors", "RCT selections", "reco flag selection"}; + std::vector collisionSelectionCounterLabels = {"all collisions", "rapidity gap", "ITS-TPC vertex", "same bunch pile-up", "ITS ROF border", "TF border", "#it{z} position", "number of contributors", "RCT selections", "reco flag selection", "occupancy selection"}; rQC.add("QC/collisions/hSelectionCounter", ";;collisions passing selections", kTH1D, {{static_cast(collisionSelectionCounterLabels.size()), -0.5, static_cast(collisionSelectionCounterLabels.size()) - 0.5}}); rQC.add("QC/collisions/hSelectionCounterPerRun", ";;run number;collisions passing selections", kTH2D, {{static_cast(collisionSelectionCounterLabels.size()), -0.5, static_cast(collisionSelectionCounterLabels.size()) - 0.5}, runNumberAxis}); for (int i = 0; i < static_cast(collisionSelectionCounterLabels.size()); ++i) { rQC.get(HIST("QC/collisions/hSelectionCounter"))->GetXaxis()->SetBinLabel(i + 1, collisionSelectionCounterLabels[i].c_str()); rQC.get(HIST("QC/collisions/hSelectionCounterPerRun"))->GetXaxis()->SetBinLabel(i + 1, collisionSelectionCounterLabels[i].c_str()); } + for (int i = 0; i < static_cast(runNumbers.size()); ++i) + rQC.get(HIST("QC/collisions/hSelectionCounterPerRun"))->GetYaxis()->SetBinLabel(i + 1, std::to_string(runNumbers[i]).c_str()); // tracks rQC.add("QC/tracks/all/hTpcNSigmaPi", ";TPC #it{n#sigma}(#pi);counts", kTH1D, {nSigmaAxis}); rQC.add("QC/tracks/all/hTpcNSigmaEl", ";TPC #it{n#sigma}(e);counts", kTH1D, {nSigmaAxis}); rQC.add("QC/tracks/all/hTpcNSigmaKa", ";TPC #it{n#sigma}(K);counts", kTH1D, {nSigmaAxis}); rQC.add("QC/tracks/all/hTpcNSigmaPr", ";TPC #it{n#sigma}(p);counts", kTH1D, {nSigmaAxis}); rQC.add("QC/tracks/all/hDcaXYZ", ";track #it{DCA}_{z} (cm);track #it{DCA}_{xy} (cm);counts", kTH2D, {{1000, -5.0, 5.0}, {400, -2.0, 2.0}}); - rQC.add("QC/tracks/all/hItsNCls", ";ITS #it{N}_{cls};counts", kTH1D, {{11, -0.5, 10.5}}); - rQC.add("QC/tracks/all/hItsChi2NCl", ";ITS #it{#chi}^{2}/#it{N}_{cls};counts", kTH1D, {{200, 0.0, 20.0}}); - rQC.add("QC/tracks/all/hTpcChi2NCl", ";TPC #it{#chi}^{2}/#it{N}_{cls};counts", kTH1D, {{200, 0.0, 20.0}}); + rQC.add("QC/tracks/all/hItsNCls", ";ITS #it{N}_{cls};counts", kTH1D, {{9, -0.5, 8.5}}); + rQC.add("QC/tracks/all/hItsChi2NCl", ";ITS #it{#chi}^{2}/#it{N}_{cls};counts", kTH1D, {{150, 0.0, 15.0}}); + rQC.add("QC/tracks/all/hTpcChi2NCl", ";TPC #it{#chi}^{2}/#it{N}_{cls};counts", kTH1D, {{150, 0.0, 15.0}}); rQC.add("QC/tracks/all/hTpcNCls", ";found TPC #it{N}_{cls};counts", kTH1D, {{160, 0.0, 160.0}}); // tpcNClsFindable() - track.tpcNClsFindableMinusFound rQC.add("QC/tracks/all/hTpcNClsCrossedRows", ";TPC crossed rows;counts", kTH1D, {{160, 0.0, 160.0}}); - rQC.add("QC/tracks/all/hTpcNClsCrossedRowsOverNClsFindable", ";TPC crossed rows/findable #it{N}_{cls};counts", kTH1D, {{300, 0.5, 2.5}}); + rQC.add("QC/tracks/all/hTpcNClsCrossedRowsOverNClsFindable", ";TPC crossed rows/findable #it{N}_{cls};counts", kTH1D, {{160, 0.6, 2.2}}); rQC.add("QC/tracks/all/hPt", ";#it{p}_{T} (GeV/#it{c});counts", kTH1D, {ptAxis}); rQC.add("QC/tracks/all/hEta", ";#it{#eta};counts", kTH1D, {etaAxis}); rQC.add("QC/tracks/all/hPhi", ";#it{#phi} (rad);counts", kTH1D, {phiAxis}); @@ -400,14 +403,14 @@ struct UpcRhoAnalysis { rResolution.add("MC/resolution/collisions/hPosZ", ";vertex #it{z}_{reco} - vertex #it{z}_{true} (cm);counts", kTH1D, {resolutionAxis}); // track matching and resolutions rResolution.add("MC/resolution/tracks/hMatch", ";matched;counts", kTH1D, {{2, -0.5, 1.5}}); - rResolution.add("MC/resolution/tracks/hPt", ";#it{p}_{T, reco} - #it{p}_{T, true} (GeV/#it{c});counts", kTH1D, {resolutionAxis}); + rResolution.add("MC/resolution/tracks/hPt", ";1/#it{p}_{T, reco} - 1/#it{p}_{T, true} (1/(GeV/#it{c}));counts", kTH1D, {resolutionAxis}); rResolution.add("MC/resolution/tracks/hEta", ";#it{#eta}_{reco} - #it{#eta}_{true};counts", kTH1D, {resolutionAxis}); rResolution.add("MC/resolution/tracks/hPhi", ";#it{#phi}_{reco} - #it{#phi}_{true} (rad);counts", kTH1D, {resolutionAxis}); // dipion system resolutions (1D and 2D) rResolution.add("MC/resolution/system/1D/hM", ";#it{m}_{reco} - #it{m}_{true} (GeV/#it{c}^{2});counts", kTH1D, {resolutionAxis}); rResolution.add("MC/resolution/system/2D/hMVsM", ";#it{m}_{true} (GeV/#it{c}^{2});#it{m}_{reco} (GeV/#it{c}^{2});counts", kTH2D, {mAxis, mAxis}); - rResolution.add("MC/resolution/system/1D/hPt", ";#it{p}_{T, reco} - #it{p}_{T, true} (GeV/#it{c});counts", kTH1D, {resolutionAxis}); - rResolution.add("MC/resolution/system/2D/hPtVsPt", ";#it{p}_{T, true} (GeV/#it{c});#it{p}_{T, reco} (GeV/#it{c});counts", kTH2D, {ptAxis, ptAxis}); + rResolution.add("MC/resolution/system/1D/hPt", ";1/#it{p}_{T, reco} - 1/#it{p}_{T, true} (1/(GeV/#it{c}));counts", kTH1D, {resolutionAxis}); + rResolution.add("MC/resolution/system/2D/hPtVsPt", ";1/#it{p}_{T, true} (GeV/#it{c});#it{p}_{T, reco} (GeV/#it{c});counts", kTH2D, {ptAxis, ptAxis}); rResolution.add("MC/resolution/system/1D/hY", ";#it{y}_{reco} - #it{y}_{true};counts", kTH1D, {resolutionAxis}); rResolution.add("MC/resolution/system/2D/hYVsY", ";#it{y}_{true};#it{y}_{reco};counts", kTH2D, {yAxis, yAxis}); rResolution.add("MC/resolution/system/1D/hDeltaPhi", ";#Delta#it{#phi}_{reco} - #Delta#it{#phi}_{true} (rad);counts", kTH1D, {resolutionAxis}); @@ -451,6 +454,7 @@ struct UpcRhoAnalysis { rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hTpcNSigmaPi"), track.tpcNSigmaPi()); rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hTpcNSigmaEl"), track.tpcNSigmaEl()); rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hTpcNSigmaKa"), track.tpcNSigmaKa()); + rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hTpcNSigmaPr"), track.tpcNSigmaPr()); rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hDcaXYZ"), track.dcaZ(), track.dcaXY()); rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hItsNCls"), track.itsNCls()); rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hItsChi2NCl"), track.itsChi2NCl()); @@ -585,6 +589,13 @@ struct UpcRhoAnalysis { rQC.fill(HIST("QC/collisions/hSelectionCounterPerRun"), 9, runIndex); } + if (cutOccupancy) { + if (collision.occupancyInTime() > occupancyCut) + return false; + rQC.fill(HIST("QC/collisions/hSelectionCounter"), 10); + rQC.fill(HIST("QC/collisions/hSelectionCounterPerRun"), 10, runIndex); + } + // if all selections passed return true; } @@ -805,20 +816,19 @@ struct UpcRhoAnalysis { if (std::isinf(timeZNC)) timeZNC = -999; - if (energyCommonZNA <= znCommonEnergyCut && energyCommonZNC <= znCommonEnergyCut) { + if (std::abs(timeZNA) > znTimeCut && std::abs(timeZNC) > znTimeCut) { onon = true; neutronClass = 0; } - if (energyCommonZNA > znCommonEnergyCut && std::abs(timeZNA) <= znTimeCut && energyCommonZNC <= znCommonEnergyCut) { + if (std::abs(timeZNA) <= znTimeCut && std::abs(timeZNC) > znTimeCut) { xnon = true; neutronClass = 1; } - if (energyCommonZNA <= znCommonEnergyCut && energyCommonZNC > znCommonEnergyCut && std::abs(timeZNC) <= znTimeCut) { + if (std::abs(timeZNA) > znTimeCut && std::abs(timeZNC) <= znTimeCut) { onxn = true; neutronClass = 2; } - if (energyCommonZNA > znCommonEnergyCut && std::abs(timeZNA) <= znTimeCut && - energyCommonZNC > znCommonEnergyCut && std::abs(timeZNC) <= znTimeCut) { + if (std::abs(timeZNA) <= znTimeCut && std::abs(timeZNC) <= znTimeCut) { xnxn = true; neutronClass = 3; } @@ -1145,7 +1155,7 @@ struct UpcRhoAnalysis { auto mcParticle = track.udMcParticle(); if (std::abs(mcParticle.pdgCode()) != kPiPlus && !mcParticle.isPhysicalPrimary()) continue; - rResolution.fill(HIST("MC/resolution/tracks/hPt"), pt(track.px(), track.py()) - pt(mcParticle.px(), mcParticle.py())); + rResolution.fill(HIST("MC/resolution/tracks/hPt"), 1.0 / pt(track.px(), track.py()) - 1.0 / pt(mcParticle.px(), mcParticle.py())); rResolution.fill(HIST("MC/resolution/tracks/hEta"), eta(track.px(), track.py(), track.pz()) - eta(mcParticle.px(), mcParticle.py(), mcParticle.pz())); rResolution.fill(HIST("MC/resolution/tracks/hPhi"), phi(track.px(), track.py()) - phi(mcParticle.px(), mcParticle.py())); truePionLVs.push_back(ROOT::Math::PxPyPzMVector(mcParticle.px(), mcParticle.py(), mcParticle.pz(), o2::constants::physics::MassPionCharged)); @@ -1164,7 +1174,7 @@ struct UpcRhoAnalysis { rResolution.fill(HIST("MC/resolution/system/1D/hM"), recoSystem.M() - trueSystem.M()); rResolution.fill(HIST("MC/resolution/system/2D/hMVsM"), trueSystem.M(), recoSystem.M()); - rResolution.fill(HIST("MC/resolution/system/1D/hPt"), recoSystem.Pt() - trueSystem.Pt()); + rResolution.fill(HIST("MC/resolution/system/1D/hPt"), 1.0 / recoSystem.Pt() - 1.0 / trueSystem.Pt()); rResolution.fill(HIST("MC/resolution/system/2D/hPtVsPt"), trueSystem.Pt(), recoSystem.Pt()); rResolution.fill(HIST("MC/resolution/system/1D/hY"), recoSystem.Rapidity() - trueSystem.Rapidity()); rResolution.fill(HIST("MC/resolution/system/2D/hYVsY"), trueSystem.Rapidity(), recoSystem.Rapidity()); From ec249340be5953a0eef5aa2ca05af9306b784323 Mon Sep 17 00:00:00 2001 From: Subhadeep Mandal <147193283+5ub-Man@users.noreply.github.com> Date: Mon, 23 Feb 2026 00:10:15 +0530 Subject: [PATCH 022/347] [PWGLF] Added INEL > 0 in generated MC events (#15101) --- PWGLF/Tasks/Resonances/kstar892LightIon.cxx | 65 ++++++++++++++--- .../Tasks/Resonances/phianalysisrun3_PbPb.cxx | 70 ++++++++++++++----- 2 files changed, 107 insertions(+), 28 deletions(-) diff --git a/PWGLF/Tasks/Resonances/kstar892LightIon.cxx b/PWGLF/Tasks/Resonances/kstar892LightIon.cxx index 238ff319118..5f1b3d84925 100644 --- a/PWGLF/Tasks/Resonances/kstar892LightIon.cxx +++ b/PWGLF/Tasks/Resonances/kstar892LightIon.cxx @@ -82,7 +82,6 @@ struct Kstar892LightIon { struct : ConfigurableGroup { // Configurables for event selections Configurable cfgVrtxZCut{"cfgVrtxZCut", 10.0f, "Accepted z-vertex range (cm)"}; - Configurable isApplycutVzLoss{"isApplycutVzLoss", true, "Apply Vertex-z cut in processAllLossMC"}; Configurable isApplysel8{"isApplysel8", true, "Apply sel8 event selection"}; Configurable isApplyINELgt0{"isApplyINELgt0", true, "INEL>0 selection"}; Configurable isTriggerTVX{"isTriggerTVX", true, "TriggerTVX"}; @@ -99,7 +98,9 @@ struct Kstar892LightIon { Configurable isVertexTOFMatched{"isVertexTOFMatched", false, "Vertex TOF Matched"}; // check - Configurable isApplyEvSelFactors{"isApplyEvSelFactors", false, "Apply event selection cut in processCorrFactors"}; + Configurable isApplyMCGenInelgt0{"isApplyMCGenInelgt0", true, "Apply INEL>0 cut in MC Gen Collisions"}; + Configurable isApplyMCGenTVX{"isApplyMCGenTVX", true, "Apply TVX cut in MC Gen Collisions"}; + Configurable isApplyMCGenVz{"isApplyMCGenVz", true, "Apply Vz cut in MC Gen Collisions"}; // Configurables for track selections Configurable isPVContributor{"isPVContributor", true, "PV contributor track selection"}; // PV Contriuibutor @@ -817,7 +818,7 @@ struct Kstar892LightIon { using EventCandidates = soa::Join; // aod::CentNGlobals, aod::CentNTPVs, aod::CentMFTs using TrackCandidates = soa::Join; - using EventMCGenerated = soa::Join; // aod::CentNGlobals, aod::CentNTPVs, aod::CentMFTs + using EventMCGenerated = soa::Join; // aod::CentNGlobals, aod::CentNTPVs, aod::CentMFTs using EventCandidatesMC = soa::Join; using TrackCandidatesMC = soa::Join; @@ -1272,6 +1273,19 @@ struct Kstar892LightIon { void processGen(EventMCGenerated::iterator const& mcCollision, aod::McParticles const& mcParticles, const soa::SmallGroups& collisions) { + + if (selectionConfig.isApplyMCGenInelgt0 && !mcCollision.isInelGt0()) { + return; + } + + if (selectionConfig.isApplyMCGenTVX && !(mcCollision.multMCFT0C() > 0 && mcCollision.multMCFT0A() > 0)) { + return; + } + + if (selectionConfig.isApplyMCGenVz && std::abs(mcCollision.posZ()) >= selectionConfig.cfgVrtxZCut) { + return; + } + std::vector selectedEvents(collisions.size()); int nevts = 0; centrality = -1.0; @@ -1590,8 +1604,20 @@ struct Kstar892LightIon { } PROCESS_SWITCH(Kstar892LightIon, processRec, "Process Reconstructed", false); - void processEvtLossSigLossMC(aod::McCollisions::iterator const& mcCollision, aod::McParticles const& mcParticles, const soa::SmallGroups& recCollisions) + void processEvtLossSigLossMC(EventMCGenerated::iterator const& mcCollision, const soa::SmallGroups& recCollisions, aod::McParticles const& mcParticles) { + if (selectionConfig.isApplyMCGenInelgt0 && !mcCollision.isInelGt0()) { + return; + } + + if (selectionConfig.isApplyMCGenTVX && !(mcCollision.multMCFT0C() > 0 && mcCollision.multMCFT0A() > 0)) { + return; + } + + if (selectionConfig.isApplyMCGenVz && std::abs(mcCollision.posZ()) >= selectionConfig.cfgVrtxZCut) { + return; + } + auto impactPar = mcCollision.impactParameter(); hMC.fill(HIST("ImpactCorr/hImpactParameterGen"), impactPar); @@ -1639,11 +1665,21 @@ struct Kstar892LightIon { } PROCESS_SWITCH(Kstar892LightIon, processEvtLossSigLossMC, "Process Signal Loss, Event Loss using impact parameter", false); - using McCollisionMults = soa::Join; - using LabeledTracks = soa::Join; - - void processLossMCMultiplicity(McCollisionMults::iterator const& mcCollision, aod::McParticles const& mcParticles, soa::SmallGroups const& recCollisions) + void processLossMCMultiplicity(EventMCGenerated::iterator const& mcCollision, aod::McParticles const& mcParticles, soa::SmallGroups const& recCollisions) { + + if (selectionConfig.isApplyMCGenInelgt0 && !mcCollision.isInelGt0()) { + return; + } + + if (selectionConfig.isApplyMCGenTVX && !(mcCollision.multMCFT0C() > 0 && mcCollision.multMCFT0A() > 0)) { + return; + } + + if (selectionConfig.isApplyMCGenVz && std::abs(mcCollision.posZ()) >= selectionConfig.cfgVrtxZCut) { + return; + } + const int multMC = mcCollision.multMCNParticlesEta05(); hMC.fill(HIST("LossMult/hMultMC"), multMC); @@ -1697,10 +1733,19 @@ struct Kstar892LightIon { } PROCESS_SWITCH(Kstar892LightIon, processLossMCMultiplicity, "Signal + Event loss (using MC multiplicity)", false); - void processAllLossMC(McCollisionMults::iterator const& mcCollision, aod::McParticles const& mcParticles, const soa::SmallGroups& recCollisions) + void processAllLossMC(EventMCGenerated::iterator const& mcCollision, aod::McParticles const& mcParticles, const soa::SmallGroups& recCollisions) { - if (selectionConfig.isApplycutVzLoss && std::abs(mcCollision.posZ()) > selectionConfig.cfgVrtxZCut) + if (selectionConfig.isApplyMCGenInelgt0 && !mcCollision.isInelGt0()) { + return; + } + + if (selectionConfig.isApplyMCGenTVX && !(mcCollision.multMCFT0C() > 0 && mcCollision.multMCFT0A() > 0)) { return; + } + + if (selectionConfig.isApplyMCGenVz && std::abs(mcCollision.posZ()) >= selectionConfig.cfgVrtxZCut) { + return; + } // Event loss estimation auto impactPar = mcCollision.impactParameter(); diff --git a/PWGLF/Tasks/Resonances/phianalysisrun3_PbPb.cxx b/PWGLF/Tasks/Resonances/phianalysisrun3_PbPb.cxx index 3fce22fb5ac..78e07fbd4f4 100644 --- a/PWGLF/Tasks/Resonances/phianalysisrun3_PbPb.cxx +++ b/PWGLF/Tasks/Resonances/phianalysisrun3_PbPb.cxx @@ -96,6 +96,7 @@ struct phianalysisrun3_PbPb { Configurable additionalEvSel5{"additionalEvSel5", true, "Additional evsel5"}; Configurable additionalEvSel6{"additionalEvSel6", true, "Additional evsel6"}; Configurable cutvz{"cutvz", true, "Vz cut"}; + Configurable cutvzgen{"cutvzgen", true, "Vz cut"}; Configurable isINELgt0{"isINELgt0", true, "INEL>0 selection"}; } selectionConfig; Configurable cfgMultFT0{"cfgMultFT0", true, "cfgMultFT0"}; @@ -134,7 +135,8 @@ struct phianalysisrun3_PbPb { ConfigurableAxis binsMult{"binsMult", {500, 0.0f, +500.0f}, ""}; Configurable isApplyCentFT0C{"isApplyCentFT0C", true, "Centrality based on FT0C"}; Configurable isApplyCentFT0M{"isApplyCentFV0M", false, "Centrality based on FT0M"}; - + Configurable isApplyInelgt0{"isApplyInelgt0", false, "Enable INEL > 0 condition"}; + Configurable isApplyTVX{"isApplyTVX", false, "Enable TVX trigger sel"}; Configurable genacceptancecut{"genacceptancecut", true, "use acceptance cut for generated"}; // MC Configurable isMC{"isMC", false, "Run MC"}; @@ -1693,59 +1695,77 @@ struct phianalysisrun3_PbPb { } } PROCESS_SWITCH(phianalysisrun3_PbPb, processMixedEventMC, "Process Mixed event MC", true); - void processGen1(aod::McCollision const& mcCollision, aod::McParticles const& mcParticles, const soa::SmallGroups& collisions) + void processGen1(McCollisionMults::iterator const& mcCollision, aod::McParticles const& mcParticles, const soa::SmallGroups& collisions) { + // all events histos.fill(HIST("hMC1"), 0.5); - if (!selectionConfig.cutvz || std::abs(mcCollision.posZ()) < selectionConfig.cfgCutVertex) { + + // vertex QA (not selection) + if (!selectionConfig.cutvzgen || + std::abs(mcCollision.posZ()) < selectionConfig.cfgCutVertex) { histos.fill(HIST("hMC1"), 1.5); } + + // INEL>0 selection + if (isApplyInelgt0 && !mcCollision.isInelGt0()) + return; + + histos.fill(HIST("hMC1"), 2.5); + + // TVX selection + if (isApplyTVX && + !(mcCollision.multMCFT0C() > 0 && mcCollision.multMCFT0A() > 0)) + return; + + histos.fill(HIST("hMC1"), 3.5); std::vector selectedEvents(collisions.size()); int nevts = 0; auto multiplicity = -1.0; for (const auto& collision : collisions) { - histos.fill(HIST("hMC1"), 2.5); + histos.fill(HIST("hMC1"), 4.5); if (cfgDoSel8 && !collision.sel8()) { continue; } + histos.fill(HIST("hMC1"), 5.5); if (selectionConfig.cutvz && std::abs(collision.mcCollision().posZ()) > selectionConfig.cfgCutVertex) { continue; } - histos.fill(HIST("hMC1"), 3.5); + histos.fill(HIST("hMC1"), 6.5); if (selectionConfig.additionalEvSel1 && !collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) { continue; } - histos.fill(HIST("hMC1"), 4.5); + histos.fill(HIST("hMC1"), 7.5); if (selectionConfig.additionalEvSel2 && !collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) { continue; } - histos.fill(HIST("hMC1"), 5.5); + histos.fill(HIST("hMC1"), 8.5); if (selectionConfig.additionalEvSel3 && !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { continue; } - histos.fill(HIST("hMC1"), 6.5); + histos.fill(HIST("hMC1"), 9.5); if (selectionConfig.additionalEvSel4 && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { continue; } - histos.fill(HIST("hMC1"), 7.5); + histos.fill(HIST("hMC1"), 10.5); if (selectionConfig.additionalEvSel5 && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { continue; } - histos.fill(HIST("hMC1"), 8.5); + histos.fill(HIST("hMC1"), 11.5); if (selectionConfig.additionalEvSel6 && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { continue; } - histos.fill(HIST("hMC1"), 9.5); + histos.fill(HIST("hMC1"), 12.5); if (selectionConfig.isINELgt0 && !collision.isInelGt0()) { continue; } - histos.fill(HIST("hMC1"), 10.5); + histos.fill(HIST("hMC1"), 13.5); int occupancy = collision.trackOccupancyInTimeRange(); if (selectionConfig.fillOccupancy && (occupancy < cfgMinOccupancy || occupancy > cfgMaxOccupancy)) { continue; } - histos.fill(HIST("hMC1"), 11.5); + histos.fill(HIST("hMC1"), 14.5); const int kCentFT0C = 0; const int kCentFT0A = 1; const int kCentFT0M = 2; @@ -1765,11 +1785,11 @@ struct phianalysisrun3_PbPb { } selectedEvents.resize(nevts); const auto evtReconstructedAndSelected = std::find(selectedEvents.begin(), selectedEvents.end(), mcCollision.globalIndex()) != selectedEvents.end(); - histos.fill(HIST("hMC1"), 12.5); + histos.fill(HIST("hMC1"), 15.5); if (!evtReconstructedAndSelected) { // Check that the event is reconstructed and that the reconstructed events pass the selection return; } - histos.fill(HIST("hMC1"), 13.5); + histos.fill(HIST("hMC1"), 16.5); for (const auto& mcParticle : mcParticles) { if (mcParticle.y() < rapiditycut1 || mcParticle.y() > rapiditycut2) { @@ -1861,7 +1881,7 @@ struct phianalysisrun3_PbPb { multiplicity = collision.centFV0A(); } histos.fill(HIST("Centrec1"), multiplicity); - histos.fill(HIST("hMC1"), 14.5); + histos.fill(HIST("hMC1"), 17.5); auto oldindex = -999; for (const auto& track1 : tracks) { if (!selectionTrack(track1)) { @@ -1958,10 +1978,17 @@ struct phianalysisrun3_PbPb { void processEvtLossSigLossMC(McCollisionMults::iterator const& mcCollision, aod::McParticles const& mcParticles, const soa::SmallGroups& recCollisions) { - if (selectionConfig.cutvz && + if (selectionConfig.cutvzgen && std::abs(mcCollision.posZ()) > selectionConfig.cfgCutVertex) { return; } + if (isApplyInelgt0 && !mcCollision.isInelGt0()) { + return; + } + + if (isApplyTVX && !(mcCollision.multMCFT0C() > 0 && mcCollision.multMCFT0A() > 0)) { + return; + } // Event loss estimation auto impactPar = mcCollision.impactParameter(); histos.fill(HIST("QAevent/hImpactParameterGen"), impactPar); @@ -2026,10 +2053,17 @@ struct phianalysisrun3_PbPb { PROCESS_SWITCH(phianalysisrun3_PbPb, processEvtLossSigLossMC, "Process Signal Loss, Event Loss", false); void processEvtLossSigLossMC1(McCollisionMults::iterator const& mcCollision, soa::SmallGroups const& collisions, aod::McParticles const& GenParticles) { - if (selectionConfig.cutvz && + if (selectionConfig.cutvzgen && std::abs(mcCollision.posZ()) > selectionConfig.cfgCutVertex) { return; } + if (isApplyInelgt0 && !mcCollision.isInelGt0()) { + return; + } + + if (isApplyTVX && !(mcCollision.multMCFT0C() > 0 && mcCollision.multMCFT0A() > 0)) { + return; + } // All generated events histos.fill(HIST("MCEventHist"), 1); histos.fill(HIST("hImpactParameterGen1"), mcCollision.impactParameter()); From d54fbb7f3d77242cc259c1b91d5c851fa1613bdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?BiaoZhang=20=28=E5=BC=A0=E5=BD=AA=29?= <52267892+zhangbiao-phy@users.noreply.github.com> Date: Sun, 22 Feb 2026 20:27:05 +0100 Subject: [PATCH 023/347] =?UTF-8?q?[PWGHF]=20remove=20useless=20filter=20f?= =?UTF-8?q?or=20charm=20gen.level=20particle=20in=20charm=20femto=20pro?= =?UTF-8?q?=E2=80=A6=20(#15100)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../producerCharmHadronsTrackFemtoDream.cxx | 6 +++--- .../producerCharmHadronsV0FemtoDream.cxx | 12 +++++++----- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/PWGHF/HFC/TableProducer/producerCharmHadronsTrackFemtoDream.cxx b/PWGHF/HFC/TableProducer/producerCharmHadronsTrackFemtoDream.cxx index b5bcd1a492f..9884ff920e3 100644 --- a/PWGHF/HFC/TableProducer/producerCharmHadronsTrackFemtoDream.cxx +++ b/PWGHF/HFC/TableProducer/producerCharmHadronsTrackFemtoDream.cxx @@ -227,9 +227,9 @@ struct HfProducerCharmHadronsTrackFemtoDream { using FemtoHFMcTracks = soa::Join; using FemtoHFMcTrack = FemtoHFMcTracks::iterator; - using Generated3ProngMc = soa::Filtered>; - using Generated2ProngMc = soa::Filtered>; - using GeneratedDstarMc = soa::Filtered>; + using Generated3ProngMc = soa::Join; + using Generated2ProngMc = soa::Join; + using GeneratedDstarMc = soa::Join; Filter filterSelectCandidateD0 = (aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagHadron || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlagHadron); Filter filterSelectCandidateDstar = aod::hf_sel_candidate_dstar::isSelDstarToD0Pi == true; diff --git a/PWGHF/HFC/TableProducer/producerCharmHadronsV0FemtoDream.cxx b/PWGHF/HFC/TableProducer/producerCharmHadronsV0FemtoDream.cxx index ba70eef248a..ebc38e73682 100644 --- a/PWGHF/HFC/TableProducer/producerCharmHadronsV0FemtoDream.cxx +++ b/PWGHF/HFC/TableProducer/producerCharmHadronsV0FemtoDream.cxx @@ -250,7 +250,9 @@ struct HfProducerCharmHadronsV0FemtoDream { using FemtoFullMcgenCollisions = soa::Join; using FemtoFullMcgenCollision = FemtoFullMcgenCollisions::iterator; - using GeneratedMc = soa::Filtered>; + using Generated3ProngMc = soa::Join; + using Generated2ProngMc = soa::Join; + using GeneratedDstarMc = soa::Join; Filter filterSelectCandidateD0 = (aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagCharmHadron || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlagCharmHadron); Filter filterSelectCandidateDstar = aod::hf_sel_candidate_dstar::isSelDstarToD0Pi == true; @@ -1223,7 +1225,7 @@ struct HfProducerCharmHadronsV0FemtoDream { } PROCESS_SWITCH(HfProducerCharmHadronsV0FemtoDream, processMcD0ToPiKWithML, "Provide Mc for D0ToPiK with ml", false); - void processMcD0ToPiKGen(GeneratedMc const& particles) + void processMcD0ToPiKGen(Generated2ProngMc const& particles) { fillCharmHadMcGen(particles); } @@ -1282,7 +1284,7 @@ struct HfProducerCharmHadronsV0FemtoDream { } PROCESS_SWITCH(HfProducerCharmHadronsV0FemtoDream, processMcDstarToD0PiWithML, "Provide Mc for DstarToD0Pi with ml", false); - void processMcDstarToD0PiGen(GeneratedMc const& particles) + void processMcDstarToD0PiGen(GeneratedDstarMc const& particles) { fillCharmHadMcGen(particles); @@ -1343,7 +1345,7 @@ struct HfProducerCharmHadronsV0FemtoDream { } PROCESS_SWITCH(HfProducerCharmHadronsV0FemtoDream, processMcDplusToPiKPiWithML, "Provide Mc for DplusToPiKPi with ml", false); - void processMcDplusToPiKPiGen(GeneratedMc const& particles) + void processMcDplusToPiKPiGen(Generated3ProngMc const& particles) { fillCharmHadMcGen(particles); @@ -1404,7 +1406,7 @@ struct HfProducerCharmHadronsV0FemtoDream { } PROCESS_SWITCH(HfProducerCharmHadronsV0FemtoDream, processMcLcToPKPiWithML, "Provide Mc for lctopkpi with ml", false); - void processMcLcToPKPiGen(GeneratedMc const& particles) + void processMcLcToPKPiGen(Generated3ProngMc const& particles) { fillCharmHadMcGen(particles); From 3c7f54601b67bd1fdfedd9f7f91980dae8760f42 Mon Sep 17 00:00:00 2001 From: prottayCMT <61418725+prottayCMT@users.noreply.github.com> Date: Sun, 22 Feb 2026 22:12:28 +0100 Subject: [PATCH 024/347] [PWGLF] added few QA histograms to monitor calibration after shifts (#15103) Co-authored-by: Prottay Das --- PWGLF/Tasks/Strangeness/lambdapolsp.cxx | 96 +++++++++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/PWGLF/Tasks/Strangeness/lambdapolsp.cxx b/PWGLF/Tasks/Strangeness/lambdapolsp.cxx index a472872745e..50c891f43f2 100644 --- a/PWGLF/Tasks/Strangeness/lambdapolsp.cxx +++ b/PWGLF/Tasks/Strangeness/lambdapolsp.cxx @@ -190,6 +190,16 @@ struct lambdapolsp { ConfigurableAxis configbinAxis{"configbinAxis", {VARIABLE_WIDTH, -0.8, -0.4, -0.2, 0, 0.2, 0.4, 0.8}, "BA"}; */ // ConfigurableAxis configphiAxis{"configphiAxis", {VARIABLE_WIDTH, 0.0, 0.2, 0.4, 0.8, 1.0, 2.0, 2.5, 3.0, 4.0, 5.0, 5.5, 6.28}, "PhiAxis"}; + + struct : ConfigurableGroup { + Configurable isQA{"isQA", true, "Flag to fill QA"}; + ConfigurableAxis centfineAxis{"centfineAxis", {VARIABLE_WIDTH, 0.0, 10.0, 40.0, 80.0}, "Cent V0M"}; + ConfigurableAxis vxfineAxis{"vxfineAxis", {VARIABLE_WIDTH, 0.0, 10.0, 40.0, 80.0}, "vx fine axis"}; + ConfigurableAxis vyfineAxis{"vyfineAxis", {VARIABLE_WIDTH, 0.0, 10.0, 40.0, 80.0}, "vy fine axis"}; + ConfigurableAxis vzfineAxis{"vzfineAxis", {VARIABLE_WIDTH, 0.0, 10.0, 40.0, 80.0}, "vz fine axis"}; + ConfigurableAxis qxZDCAxis{"qxZDCAxis", {VARIABLE_WIDTH, 0.0, 10.0, 40.0, 80.0}, "qx axis"}; + ConfigurableAxis psiAxis{"psiAxis", {VARIABLE_WIDTH, 0.0, 10.0, 40.0, 80.0}, "psi axis"}; + } QAgrp; struct : ConfigurableGroup { Configurable requireRCTFlagChecker{"requireRCTFlagChecker", true, "Check event quality in run condition table"}; Configurable cfgEvtRCTFlagCheckerLabel{"cfgEvtRCTFlagCheckerLabel", "CBT_hadronPID", "Evt sel: RCT flag checker label"}; @@ -456,6 +466,32 @@ struct lambdapolsp { histos.add("hSparseRecLambda", "hSparseRecLambda", HistType::kTHnSparseF, runaxes2, true); histos.add("hSparseRecAntiLambda", "hSparseRecAntiLambda", HistType::kTHnSparseF, runaxes2, true); + if (QAgrp.isQA) { + histos.add("hCentQxZDCA", "hCentQxZDCA", kTH2F, {{QAgrp.centfineAxis}, {QAgrp.qxZDCAxis}}); + histos.add("hCentQyZDCA", "hCentQyZDCA", kTH2F, {{QAgrp.centfineAxis}, {QAgrp.qxZDCAxis}}); + histos.add("hCentQxZDCC", "hCentQxZDCC", kTH2F, {{QAgrp.centfineAxis}, {QAgrp.qxZDCAxis}}); + histos.add("hCentQyZDCC", "hCentQyZDCC", kTH2F, {{QAgrp.centfineAxis}, {QAgrp.qxZDCAxis}}); + + histos.add("hvxQxZDCA", "hvxQxZDCA", kTH2F, {{QAgrp.vxfineAxis}, {QAgrp.qxZDCAxis}}); + histos.add("hvxQyZDCA", "hvxQyZDCA", kTH2F, {{QAgrp.vxfineAxis}, {QAgrp.qxZDCAxis}}); + histos.add("hvxQxZDCC", "hvxQxZDCC", kTH2F, {{QAgrp.vxfineAxis}, {QAgrp.qxZDCAxis}}); + histos.add("hvxQyZDCC", "hvxQyZDCC", kTH2F, {{QAgrp.vxfineAxis}, {QAgrp.qxZDCAxis}}); + + histos.add("hvyQxZDCA", "hvyQxZDCA", kTH2F, {{QAgrp.vyfineAxis}, {QAgrp.qxZDCAxis}}); + histos.add("hvyQyZDCA", "hvyQyZDCA", kTH2F, {{QAgrp.vyfineAxis}, {QAgrp.qxZDCAxis}}); + histos.add("hvyQxZDCC", "hvyQxZDCC", kTH2F, {{QAgrp.vyfineAxis}, {QAgrp.qxZDCAxis}}); + histos.add("hvyQyZDCC", "hvyQyZDCC", kTH2F, {{QAgrp.vyfineAxis}, {QAgrp.qxZDCAxis}}); + + histos.add("hvzQxZDCA", "hvzQxZDCA", kTH2F, {{QAgrp.vzfineAxis}, {QAgrp.qxZDCAxis}}); + histos.add("hvzQyZDCA", "hvzQyZDCA", kTH2F, {{QAgrp.vzfineAxis}, {QAgrp.qxZDCAxis}}); + histos.add("hvzQxZDCC", "hvzQxZDCC", kTH2F, {{QAgrp.vzfineAxis}, {QAgrp.qxZDCAxis}}); + histos.add("hvzQyZDCC", "hvzQyZDCC", kTH2F, {{QAgrp.vzfineAxis}, {QAgrp.qxZDCAxis}}); + + histos.add("PsiZDCC", "PsiZDCC", kTH2F, {QAgrp.centfineAxis, QAgrp.psiAxis}); + histos.add("PsiZDCA", "PsiZDCA", kTH2F, {QAgrp.centfineAxis, QAgrp.psiAxis}); + histos.add("PsiZDC", "PsiZDC", kTH2F, {QAgrp.centfineAxis, QAgrp.psiAxis}); + } + ccdb->setURL(cfgCcdbParam.cfgURL); ccdbApi.init("http://alice-ccdb.cern.ch"); ccdb->setCaching(true); @@ -939,6 +975,10 @@ struct lambdapolsp { // currentRunNumber = collision.foundBC_as().runNumber(); auto bc = collision.foundBC_as(); + auto vz = collision.vz(); + auto vx = collision.vx(); + auto vy = collision.vy(); + auto qxZDCA = collision.qxZDCA(); auto qxZDCC = collision.qxZDCC(); auto qyZDCA = collision.qyZDCA(); @@ -963,6 +1003,32 @@ struct lambdapolsp { psiZDC = psiZDCC - psiZDCA; }*/ + if (QAgrp.isQA) { + histos.fill(HIST("hCentQxZDCA"), centrality, modqxZDCA); + histos.fill(HIST("hCentQyZDCA"), centrality, modqyZDCA); + histos.fill(HIST("hCentQxZDCC"), centrality, modqxZDCC); + histos.fill(HIST("hCentQyZDCC"), centrality, modqyZDCC); + + histos.fill(HIST("hvxQxZDCA"), vx, modqxZDCA); + histos.fill(HIST("hvxQyZDCA"), vx, modqyZDCA); + histos.fill(HIST("hvxQxZDCC"), vx, modqxZDCC); + histos.fill(HIST("hvxQyZDCC"), vx, modqyZDCC); + + histos.fill(HIST("hvyQxZDCA"), vy, modqxZDCA); + histos.fill(HIST("hvyQyZDCA"), vy, modqyZDCA); + histos.fill(HIST("hvyQxZDCC"), vy, modqxZDCC); + histos.fill(HIST("hvyQyZDCC"), vy, modqyZDCC); + + histos.fill(HIST("hvzQxZDCA"), vz, modqxZDCA); + histos.fill(HIST("hvzQyZDCA"), vz, modqyZDCA); + histos.fill(HIST("hvzQxZDCC"), vz, modqxZDCC); + histos.fill(HIST("hvzQyZDCC"), vz, modqyZDCC); + + histos.fill(HIST("PsiZDCA"), centrality, psiZDCA); + histos.fill(HIST("PsiZDCC"), centrality, psiZDCC); + histos.fill(HIST("PsiZDC"), centrality, psiZDC); + } + histos.fill(HIST("hCentrality"), centrality); if (!checkwithpub) { // histos.fill(HIST("hVtxZ"), collision.posZ()); @@ -1260,6 +1326,10 @@ struct lambdapolsp { else if (centestim == 3) centrality = collision.centFV0A(); + auto vz = collision.posZ(); + auto vx = collision.posX(); + auto vy = collision.posY(); + auto runnumber = collision.runNumber(); if (!collision.triggereventsp()) { // provided by StraZDCSP return; @@ -1319,6 +1389,32 @@ struct lambdapolsp { auto psiZDC = TMath::ATan2((modqyZDCC - modqyZDCA), (modqxZDCC - modqxZDCA)); // full event plane + if (QAgrp.isQA) { + histos.fill(HIST("hCentQxZDCA"), centrality, modqxZDCA); + histos.fill(HIST("hCentQyZDCA"), centrality, modqyZDCA); + histos.fill(HIST("hCentQxZDCC"), centrality, modqxZDCC); + histos.fill(HIST("hCentQyZDCC"), centrality, modqyZDCC); + + histos.fill(HIST("hvxQxZDCA"), vx, modqxZDCA); + histos.fill(HIST("hvxQyZDCA"), vx, modqyZDCA); + histos.fill(HIST("hvxQxZDCC"), vx, modqxZDCC); + histos.fill(HIST("hvxQyZDCC"), vx, modqyZDCC); + + histos.fill(HIST("hvyQxZDCA"), vy, modqxZDCA); + histos.fill(HIST("hvyQyZDCA"), vy, modqyZDCA); + histos.fill(HIST("hvyQxZDCC"), vy, modqxZDCC); + histos.fill(HIST("hvyQyZDCC"), vy, modqyZDCC); + + histos.fill(HIST("hvzQxZDCA"), vz, modqxZDCA); + histos.fill(HIST("hvzQyZDCA"), vz, modqyZDCA); + histos.fill(HIST("hvzQxZDCC"), vz, modqxZDCC); + histos.fill(HIST("hvzQyZDCC"), vz, modqyZDCC); + + histos.fill(HIST("PsiZDCA"), centrality, psiZDCA); + histos.fill(HIST("PsiZDCC"), centrality, psiZDCC); + histos.fill(HIST("PsiZDC"), centrality, psiZDC); + } + // fill histograms histos.fill(HIST("hCentrality"), centrality); if (!checkwithpub) { From 6ec23197cb8503a7a339d098b72e7f7127b233d5 Mon Sep 17 00:00:00 2001 From: Subhadeep Mandal <147193283+5ub-Man@users.noreply.github.com> Date: Mon, 23 Feb 2026 04:12:48 +0530 Subject: [PATCH 025/347] [PWGLF] Added has_foundFT0 event selection (#15106) --- PWGLF/Tasks/Resonances/kstar892LightIon.cxx | 22 +++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/PWGLF/Tasks/Resonances/kstar892LightIon.cxx b/PWGLF/Tasks/Resonances/kstar892LightIon.cxx index 5f1b3d84925..6badcceea3c 100644 --- a/PWGLF/Tasks/Resonances/kstar892LightIon.cxx +++ b/PWGLF/Tasks/Resonances/kstar892LightIon.cxx @@ -97,6 +97,8 @@ struct Kstar892LightIon { Configurable isVertexITSTPC{"isVertexITSTPC", false, "Vertex ITS TPC"}; Configurable isVertexTOFMatched{"isVertexTOFMatched", false, "Vertex TOF Matched"}; + Configurable isApplyhasFT0{"isApplyhasFT0", false, "Apply has_foundFT0 event selection"}; + // check Configurable isApplyMCGenInelgt0{"isApplyMCGenInelgt0", true, "Apply INEL>0 cut in MC Gen Collisions"}; Configurable isApplyMCGenTVX{"isApplyMCGenTVX", true, "Apply TVX cut in MC Gen Collisions"}; @@ -156,10 +158,10 @@ struct Kstar892LightIon { // Fixed variables float lowPtCutPID = 0.5; - Configurable selHasFT0{"selHasFT0", true, "Has FT0?"}; + Configurable selHasFT0MC{"selHasFT0MC", true, "Has FT0?"}; Configurable isZvtxPosSelMC{"isZvtxPosSelMC", true, "Zvtx position selection for MC events?"}; Configurable selTVXMC{"selTVXMC", true, "apply TVX selection in MC?"}; - Configurable selINELgt0{"selINELgt0", true, "Select INEL > 0?"}; + Configurable selINELgt0MC{"selINELgt0MC", true, "Select INEL > 0?"}; } selectionConfig; Configurable calcLikeSign{"calcLikeSign", true, "Calculate Like Sign"}; @@ -252,7 +254,9 @@ struct Kstar892LightIon { std::string("kIsGoodZvtxFT0vsPV") + check(selectionConfig.isGoodZvtxFT0vsPV.value), std::string("isVertexITSTPC") + check(selectionConfig.isVertexITSTPC.value), std::string("isVertexTOFMatched") + check(selectionConfig.isVertexTOFMatched.value), - std::string("INEL > 0") + check(selectionConfig.isApplyINELgt0.value)}; + std::string("INEL > 0") + check(selectionConfig.isApplyINELgt0.value), + std::string("hasFT0") + check(selectionConfig.isApplyhasFT0.value)}; + // assign labels for (size_t i = 0; i < eveCutLabels.size(); ++i) { hEventSelection.get(HIST("hEventCut"))->GetXaxis()->SetBinLabel(i + 1, eveCutLabels[i].c_str()); @@ -499,6 +503,12 @@ struct Kstar892LightIon { if (fillHist) hEventSelection.fill(HIST("hEventCut"), 14); + if (selectionConfig.isApplyhasFT0 && !collision.has_foundFT0()) { + return false; + } + if (fillHist) + hEventSelection.fill(HIST("hEventCut"), 15); + return true; } @@ -2124,7 +2134,7 @@ struct Kstar892LightIon { //--------------------------- // Only INEL > 0 generated events //--------------------------- - if (selectionConfig.selINELgt0) { + if (selectionConfig.selINELgt0MC) { if (!(nChMC > ZeroInt)) { return; } @@ -2157,7 +2167,7 @@ struct Kstar892LightIon { centrality = collision.centFT0M(); // default } - if (selectionConfig.selHasFT0 && !collision.has_foundFT0()) { + if (selectionConfig.selHasFT0MC && !collision.has_foundFT0()) { continue; } @@ -2194,7 +2204,7 @@ struct Kstar892LightIon { //--------------------------- // Reject collisions if has_foundFT0() returns false //--------------------------- - if (selectionConfig.selHasFT0 && !collision.has_foundFT0()) { + if (selectionConfig.selHasFT0MC && !collision.has_foundFT0()) { hMC.fill(HIST("MCCheck/CentVsFoundFT0"), centrality, 0.5); continue; } From 6f2e666e908f820e4407fabba97cfda873805f9f Mon Sep 17 00:00:00 2001 From: Gianni Shigeru Setoue Liveraro <81832939+gianniliveraro@users.noreply.github.com> Date: Sun, 22 Feb 2026 20:15:29 -0300 Subject: [PATCH 026/347] [PWGLF] safeguard when getting MC info of V0s (#15104) Co-authored-by: ALICE Action Bot --- PWGLF/TableProducer/Strangeness/sigma0builder.cxx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/PWGLF/TableProducer/Strangeness/sigma0builder.cxx b/PWGLF/TableProducer/Strangeness/sigma0builder.cxx index d6bb3f0b11c..cc6dcf403cf 100644 --- a/PWGLF/TableProducer/Strangeness/sigma0builder.cxx +++ b/PWGLF/TableProducer/Strangeness/sigma0builder.cxx @@ -1244,11 +1244,18 @@ struct sigma0builder { template void analyzeV0CollAssoc(TCollision const& collision, TV0Object const& fullv0s, std::vector selV0Indices, bool isPhotonAnalysis) { + if (!collision.has_straMCCollision()) + return; + auto v0MCCollision = collision.template straMCCollision_as>(); float IR = (fGetIR) ? rateFetcher.fetch(ccdb.service, collision.timestamp(), collision.runNumber(), irSource, fIRCrashOnNull) * 1.e-3 : -1; for (size_t i = 0; i < selV0Indices.size(); ++i) { auto v0 = fullv0s.rawIteratorAt(selV0Indices[i]); + + if (!v0.has_v0MCCore()) + continue; + auto v0MC = v0.template v0MCCore_as>(); float V0MCpT = RecoDecay::pt(array{v0MC.pxMC(), v0MC.pyMC()}); From ec79c2549d028bc5d8551a77f1fbdc51f9d8e5ce Mon Sep 17 00:00:00 2001 From: Gyula Bencedi Date: Mon, 23 Feb 2026 01:00:47 +0100 Subject: [PATCH 027/347] [PWGLF,PWGMM] Added extra checks for reassociation (#15105) --- PWGMM/Mult/Tasks/dndetaMFTPbPb.cxx | 623 ++++++++++++++++++++--------- 1 file changed, 424 insertions(+), 199 deletions(-) diff --git a/PWGMM/Mult/Tasks/dndetaMFTPbPb.cxx b/PWGMM/Mult/Tasks/dndetaMFTPbPb.cxx index e7c6b9c5b5d..4380a7471c6 100644 --- a/PWGMM/Mult/Tasks/dndetaMFTPbPb.cxx +++ b/PWGMM/Mult/Tasks/dndetaMFTPbPb.cxx @@ -20,6 +20,7 @@ #include "bestCollisionTable.h" #include "Common/CCDB/ctpRateFetcher.h" +#include "Common/Core/fwdtrackUtilities.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/CollisionAssociationTables.h" #include "Common/DataModel/EventSelection.h" @@ -72,10 +73,13 @@ using namespace o2::aod::rctsel; auto static constexpr CminCharge = 3.f; auto static constexpr CintZero = 0; -auto static constexpr CintTwo = 2; auto static constexpr Czero = 0.f; auto static constexpr Cninety = 90.f; auto static constexpr ConeHeighty = 180.f; +auto static constexpr CminAccFT0A = 3.5f; +auto static constexpr CmaxAccFT0A = 4.9f; +auto static constexpr CminAccFT0C = -3.3f; +auto static constexpr CmaxAccFT0C = -2.1f; enum TrkSel { trkSelAll, @@ -106,6 +110,11 @@ enum AmbTrkType { nAmbTrkType }; +std::unordered_map mapVtxXrec; +std::unordered_map mapVtxYrec; +std::unordered_map mapVtxZrec; +std::unordered_map mapMcCollIdPerRecColl; + struct DndetaMFTPbPb { SliceCache cache; @@ -141,6 +150,7 @@ struct DndetaMFTPbPb { Configurable cfgRemoveReassigned{"cfgRemoveReassigned", false, "Remove reassgined tracks"}; Configurable cfgUseTrackParExtra{"cfgUseTrackParExtra", false, "Use table with refitted track parameters"}; Configurable cfgUseInelgt0{"cfgUseInelgt0", false, "Use INEL > 0 condition"}; + Configurable cfgUseInelgt0wMFT{"cfgUseInelgt0wMFT", false, "Use INEL > 0 condition with MFT acceptance"}; Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; Configurable cfgDCAtype{"cfgDCAtype", 2, "DCA coordinate type [0: DCA-X, 1: DCA-Y, 2: DCA-XY]"}; } gConf; @@ -217,6 +227,9 @@ struct DndetaMFTPbPb { Service ccdb; Configurable ccdbNoLaterThan{"ccdbNoLaterThan", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object"}; Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable cfgApplyZShiftFromCCDB{"cfgApplyZShiftFromCCDB", false, "flag to apply z shift from CCDB"}; + Configurable cfgZShiftPath{"cfgZShiftPath", "Users/m/mcoquet/ZShift", "CCDB path for z shift to apply to forward tracks"}; + Configurable cfgManualZShift{"cfgManualZShift", 0.0f, "manual z-shift for propagation of global muon to PV"}; int mRunNumber{-1}; uint64_t mSOR{0}; @@ -228,6 +241,7 @@ struct DndetaMFTPbPb { float bZ = 0; // Magnetic field for MFT static constexpr double CcenterMFT[3] = {0, 0, -61.4}; // Field at center of MFT + float mZShift = 0; // z-vertex shift o2::parameters::GRPMagField* grpmag = nullptr; @@ -908,27 +922,24 @@ struct DndetaMFTPbPb { if (doprocessCollAssocMC) { // tracks not associated to any collision - hCollAssoc[0] = qaregistry.add("TrackToColl/hNonAssocTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis}); + hCollAssoc[0] = qaregistry.add("TrackToColl/hNonAssocTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); // tracks associasted to a collision - hCollAssoc[1] = qaregistry.add("TrackToColl/hAssocTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis}); + hCollAssoc[1] = qaregistry.add("TrackToColl/hAssocTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); // tracks associated to the correct collision considering only first reco collision (based on the MC collision index) - hCollAssoc[2] = qaregistry.add("TrackToColl/hGoodAssocTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis}); + hCollAssoc[2] = qaregistry.add("TrackToColl/hGoodAssocTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); // tracks associated to the correct collision considering all ambiguous reco collisions (based on the MC collision index) - hCollAssoc[3] = qaregistry.add("TrackToColl/hGoodAssocTracksAmb", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis}); + hCollAssoc[3] = qaregistry.add("TrackToColl/hGoodAssocTracksAmb", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); qaregistry.add("TrackToColl/histFracTracksFakeMcColl", "Fraction of tracks originating from fake collision; fraction; entries", {HistType::kTH1F, {{101, 0., 1.01}}}); qaregistry.add("TrackToColl/histFracGoodTracks", "Fraction of tracks originating from the correct collision; fraction; entries", {HistType::kTH1F, {{101, 0., 1.01}}}); qaregistry.add("TrackToColl/histAmbTrackNumColls", "Number of collisions associated to an ambiguous track; no. collisions; entries", {HistType::kTH1F, {{30, -0.5, 29.5}}}); + qaregistry.add("TrackToColl/histAmbTrackZvtxRMS", "RMS of #it{Z}^{reco} of collisions associated to a track; RMS(#it{Z}^{reco}) (cm); entries", {HistType::kTH1F, {{100, 0., 0.5}}}); } if (doprocessReAssocMC) { - // tracks not associated to any collision - hReAssoc[0] = qaregistry.add("ReAssoc/hNonAssocTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); - // tracks associasted to a collision - hReAssoc[1] = qaregistry.add("ReAssoc/hAssocTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); - // tracks associated to the correct collision considering only first reco collision (based on the MC collision index) - hReAssoc[2] = qaregistry.add("ReAssoc/hGoodAssocTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); - // tracks associated to the correct collision considering all ambiguous reco collisions (based on the MC collision index) - hReAssoc[3] = qaregistry.add("ReAssoc/hGoodAssocTracksAmb", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); + hReAssoc[0] = qaregistry.add("ReAssoc/hAssocBestTrue", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); + hReAssoc[1] = qaregistry.add("ReAssoc/hAssocBestWrong", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); + hReAssoc[2] = qaregistry.add("ReAssoc/hReAssocBestTrue", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); + hReAssoc[3] = qaregistry.add("ReAssoc/hReAssocBestWrong", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); } if (doprocessEfficiencyInclusive) { @@ -1073,12 +1084,11 @@ struct DndetaMFTPbPb { } } - if (doprocessReassocEfficiencyCentFT0C) { - auto hNevt = registry.add("Events/hNReEffColls", "Number of generated and reconstructed MC collisions", HistType::kTH1F, {{3, 0.5, 3.5}}); - hNevt->GetXaxis()->SetBinLabel(1, "Reconstructed collisions"); - hNevt->GetXaxis()->SetBinLabel(2, "Generated collisions"); + if (doprocessReassocEfficiency) { + registry.add("Events/hNReEffColls", "Number of times generated collisions are reconstructed; N; Counts", HistType::kTH1F, {{10, -0.5, 9.5}}); + registry.add("Events/hNchTVX", "; status;", HistType::kTH2F, {multAxis, {2, 0, 2}}); - registry.add("Events/Centrality/ReEffStatus", ";status;centrality", HistType::kTH2F, {{8, 0.5, 8.5}, centralityAxis}); + registry.add("Events/Centrality/ReEffStatus", ";status;centrality", HistType::kTH2F, {{9, 0.5, 9.5}, centralityAxis}); auto hstat = registry.get(HIST("Events/Centrality/ReEffStatus")); hstat->GetXaxis()->SetBinLabel(1, "All tracks"); hstat->GetXaxis()->SetBinLabel(2, "Ambiguous tracks"); @@ -1086,8 +1096,11 @@ struct DndetaMFTPbPb { hstat->GetXaxis()->SetBinLabel(4, "Extra tracks"); hstat->GetXaxis()->SetBinLabel(5, "Originally correctly reassgined"); hstat->GetXaxis()->SetBinLabel(6, "Correctly reassigned"); - hstat->GetXaxis()->SetBinLabel(7, "Not reassigned"); - hstat->GetXaxis()->SetBinLabel(8, "Correctly assigned true"); + hstat->GetXaxis()->SetBinLabel(7, "Not reassigned (reassigned)"); + hstat->GetXaxis()->SetBinLabel(8, "Not reassigned"); + hstat->GetXaxis()->SetBinLabel(9, "Correctly assigned true"); + + registry.add({"AmbTracks/hVtxzMCrec", " ; Z_{vtx} (cm)", {HistType::kTH1F, {zAxis}}}); registry.add({"AmbTracks/DCAXY", " ; DCA_{XY} (cm)", {HistType::kTH1F, {dcaxyAxis}}}); registry.add({"AmbTracks/DCAZ", " ; DCA_{Z} (cm)", {HistType::kTH1F, {dcazAxis}}}); @@ -1110,6 +1123,13 @@ struct DndetaMFTPbPb { registry.add({"AmbTracks/Centrality/THnDCAxyBestFalse", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm)", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis, centralityAxis}}}); registry.add({"AmbTracks/Centrality/THnDCAxyBestTrueOrigAssoc", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm)", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis, centralityAxis}}}); registry.add({"AmbTracks/Centrality/THnDCAxyBestTrueOrigReAssoc", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm)", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis, centralityAxis}}}); + + registry.add({"AmbTracks/BestGenDxyz", "; #Delta X (cm); #Delta Y (cm); #Delta Z (cm); DCA_{XY} (cm); DCA_{Z} (cm)", {HistType::kTHnSparseF, {deltaZAxis, deltaZAxis, deltaZAxis, dcaxyAxis, dcazAxis}}}); + registry.add({"AmbTracks/BestPrimDxyz", "; #Delta X (cm); #Delta Y (cm); #Delta Z (cm); DCA_{XY} (cm); DCA_{Z} (cm)", {HistType::kTHnSparseF, {deltaZAxis, deltaZAxis, deltaZAxis, dcaxyAxis, dcazAxis}}}); + registry.add({"AmbTracks/BestTrueDxyz", "; #Delta X (cm); #Delta Y (cm); #Delta Z (cm); DCA_{XY} (cm); DCA_{Z} (cm)", {HistType::kTHnSparseF, {deltaZAxis, deltaZAxis, deltaZAxis, dcaxyAxis, dcazAxis}}}); + registry.add({"AmbTracks/BestFalseDxyz", "; #Delta X (cm); #Delta Y (cm); #Delta Z (cm); DCA_{XY} (cm); DCA_{Z} (cm)", {HistType::kTHnSparseF, {deltaZAxis, deltaZAxis, deltaZAxis, dcaxyAxis, dcazAxis}}}); + registry.add({"AmbTracks/BestTrueOrigReAssocDxyz", "; #Delta X (cm); #Delta Y (cm); #Delta Z (cm); DCA_{XY} (cm); DCA_{Z} (cm)", {HistType::kTHnSparseF, {deltaZAxis, deltaZAxis, deltaZAxis, dcaxyAxis, dcazAxis}}}); + registry.add({"AmbTracks/BestTrueOrigAssocDxyz", "; #Delta X (cm); #Delta Y (cm); #Delta Z (cm); DCA_{XY} (cm); DCA_{Z} (cm)", {HistType::kTHnSparseF, {deltaZAxis, deltaZAxis, deltaZAxis, dcaxyAxis, dcazAxis}}}); } if (doprocessEventAndSignalLossCentFT0C) { @@ -1184,6 +1204,22 @@ struct DndetaMFTPbPb { using FiltParticles = soa::Filtered; + /// \brief RMS calculation + /// \param vec vector of values to compute RMS + template + T computeRMS(std::vector& vec) + { + T sum = std::accumulate(vec.begin(), vec.end(), 0.0); + T mean = sum / vec.size(); + + std::vector diff(vec.size()); + std::transform(vec.begin(), vec.end(), diff.begin(), [mean](T x) { return x - mean; }); + T sqSum = std::inner_product(diff.begin(), diff.end(), diff.begin(), 0.0); + T stdev = std::sqrt(sqSum / vec.size()); + + return stdev; + } + void initCCDB(ExtBCs::iterator const& bc) { if (mRunNumber == bc.runNumber()) { @@ -1200,6 +1236,20 @@ struct DndetaMFTPbPb { o2::field::MagneticField* field = static_cast(TGeoGlobalMagField::Instance()->GetField()); bZ = field->getBz(CcenterMFT); LOG(info) << "The field at the center of the MFT is bZ = " << bZ; + + if (cfgApplyZShiftFromCCDB) { + auto* zShift = ccdb->getForTimeStamp>(cfgZShiftPath, bc.timestamp()); + if (zShift != nullptr && !zShift->empty()) { + LOGF(info, "reading z shift %f from %s", (*zShift)[0], cfgZShiftPath.value); + mZShift = (*zShift)[0]; + } else { + LOGF(info, "z shift is not found in ccdb path %s. set to 0 cm", cfgZShiftPath.value); + mZShift = 0; + } + } else { + LOGF(info, "z shift is manually set to %f cm", cfgManualZShift.value); + mZShift = cfgManualZShift; + } } template @@ -1501,6 +1551,46 @@ struct DndetaMFTPbPb { return nCharged; } + template + bool isInelGt0wMft(P const& particles) + { + int nChrgMc = 0; + int nChrgFT0A = 0; + int nChrgFT0C = 0; + for (auto const& particle : particles) { + if (!isChrgParticle(particle.pdgCode())) { + continue; + } + if (!particle.isPhysicalPrimary()) { + continue; + } + // trigger TVX + if (particle.eta() > CminAccFT0A && particle.eta() < CmaxAccFT0A) { + nChrgFT0A++; + } + if (particle.eta() > CminAccFT0C && particle.eta() < CmaxAccFT0C) { + nChrgFT0C++; + } + // acceptance MFT + if (particle.eta() < trackCuts.minEta || particle.eta() > trackCuts.maxEta) { + continue; + } + nChrgMc++; + } + + if (nChrgFT0A == CintZero || nChrgFT0C == CintZero) { + registry.fill(HIST("Events/hNchTVX"), nChrgMc, 0.5); + return false; + } + registry.fill(HIST("Events/hNchTVX"), nChrgMc, 1.5); + + if (nChrgMc == CintZero) { + return false; + } + + return true; + } + template bool isParticleSelected(P const& particle) { @@ -2934,37 +3024,51 @@ struct DndetaMFTPbPb { qaregistry.fill(HIST("TrackToColl/histFracTracksFakeMcColl"), fracFake); } - for (auto const& track : tracks) { + for (const auto& track : tracks) { uint index = uint(track.collisionId() >= 0); if (track.has_mcParticle()) { // auto particle = track.mcParticle_as(); - auto particle = track.mcParticle(); - bool isAmbiguous = (track.compatibleCollIds().size() != 1); + const auto& particle = track.mcParticle(); + bool isAmbiguous = (track.compatibleCollIds().size() > 1); if (isAmbiguous) { qaregistry.fill(HIST("TrackToColl/histAmbTrackNumColls"), track.compatibleCollIds().size()); + + std::vector ambVtxZ{}; + for (const auto& collIdx : track.compatibleCollIds()) { + const auto& ambColl = collisions.rawIteratorAt(collIdx); + ambVtxZ.push_back(ambColl.posZ()); + } + if (!ambVtxZ.empty()) { + qaregistry.fill(HIST("TrackToColl/histAmbTrackZvtxRMS"), computeRMS(ambVtxZ)); + } } + float deltaX = -999.f; + float deltaY = -999.f; float deltaZ = -999.f; if (index) { - auto collision = track.collision_as(); - auto mcCollision = particle.mcCollision_as(); + const auto& collision = track.collision_as(); + const auto& mcCollision = particle.mcCollision_as(); + deltaX = collision.posX() - mcCollision.posX(); + deltaY = collision.posY() - mcCollision.posY(); deltaZ = collision.posZ() - mcCollision.posZ(); if (collision.has_mcCollision() && collision.mcCollisionId() == particle.mcCollisionId()) { - hCollAssoc[index + 1]->Fill(track.pt(), track.eta(), deltaZ); + hCollAssoc[index + 1]->Fill(track.pt(), track.eta(), deltaX, deltaY, deltaZ); } else { if (isAmbiguous) { for (const auto& collIdx : track.compatibleCollIds()) { - auto ambCollision = collisions.rawIteratorAt(collIdx); - if (ambCollision.has_mcCollision() && ambCollision.mcCollisionId() == particle.mcCollisionId()) { - hCollAssoc[index + 2]->Fill(track.pt(), track.eta(), deltaZ); + auto ambColl = collisions.rawIteratorAt(collIdx); + if (ambColl.has_mcCollision() && ambColl.mcCollisionId() == particle.mcCollisionId()) { + hCollAssoc[index + 2]->Fill(track.pt(), track.eta(), deltaX, deltaY, deltaZ); + // hCollAssoc[index + 2]->Fill(track.pt(), track.eta(), ambColl.posX() - mcCollision.posX(), ambColl.posY() - mcCollision.posY(), ambColl.posZ() - mcCollision.posZ()); break; } } } } + hCollAssoc[index]->Fill(track.pt(), track.eta(), deltaX, deltaY, deltaZ); } - hCollAssoc[index]->Fill(track.pt(), track.eta(), deltaZ); } else { - hCollAssoc[index]->Fill(track.pt(), track.eta(), -999.f); + hCollAssoc[index]->Fill(track.pt(), track.eta(), -999.f, -999.f, -999.f); } } } @@ -2979,50 +3083,136 @@ struct DndetaMFTPbPb { PROCESS_SWITCH(DndetaMFTPbPb, processCollAssocMC, "Process collision-association information, requires extra table from TrackToCollisionAssociation task (fillTableOfCollIdsPerTrack=true)", false); template - void processCheckReAssocMC(C const& /*collisions*/, + void processCheckReAssocMC(C const& collisions, soa::SmallGroups const& besttracks, FiltMcMftTracks const& /*tracks*/, FiltParticles const& /*particles*/, aod::McCollisions const& /*mccollisions*/ ) { - for (auto const& track : besttracks) { - uint index = uint(track.bestCollisionId() >= 0); // assigned - if (!isBestTrackSelected(track)) { - continue; + const auto& nRecoColls = collisions.size(); + // Generated evets with >= 1 reco collisions + if (nRecoColls > CintZero) { + + mapVtxXrec.clear(); + mapVtxYrec.clear(); + mapVtxZrec.clear(); + mapMcCollIdPerRecColl.clear(); + mapVtxXrec.reserve(collisions.size()); + mapVtxYrec.reserve(collisions.size()); + mapVtxZrec.reserve(collisions.size()); + mapMcCollIdPerRecColl.reserve(collisions.size()); + + auto maxNcontributors = -1; + auto bestCollIndex = -1; + for (auto const& collision : collisions) { + if (!isGoodEvent(collision)) { + continue; + } + if (!collision.has_mcCollision()) { + continue; + } + if (maxNcontributors < collision.numContrib()) { + maxNcontributors = collision.numContrib(); + bestCollIndex = collision.globalIndex(); + mapVtxXrec.emplace(collision.globalIndex(), collision.posX()); + mapVtxYrec.emplace(collision.globalIndex(), collision.posY()); + mapVtxZrec.emplace(collision.globalIndex(), collision.posZ()); + mapMcCollIdPerRecColl.emplace(collision.globalIndex(), collision.mcCollisionId()); + } else { + continue; + } } - auto itrack = track.mfttrack_as(); - if (gConf.cfgRemoveReassigned) { - if (itrack.collisionId() != track.bestCollisionId()) { + for (const auto& collision : collisions) { + if (!isGoodEvent(collision)) { + continue; + } + if (!collision.has_mcCollision()) { + continue; + } + // Select collisions with the largest number of contributors + if (bestCollIndex != collision.globalIndex()) { continue; } - } - if (!isTrackSelected(itrack)) { - continue; - } - if (itrack.has_mcParticle()) { - auto particle = itrack.mcParticle_as(); - float deltaX = -999.f; - float deltaY = -999.f; - float deltaZ = -999.f; - if (index) { - auto collision = itrack.collision_as(); - auto mcCollision = particle.mcCollision_as(); - deltaX = collision.posX() - mcCollision.posX(); - deltaY = collision.posY() - mcCollision.posY(); - deltaZ = collision.posZ() - mcCollision.posZ(); - if (collision.has_mcCollision() && collision.mcCollisionId() == particle.mcCollisionId()) { - hReAssoc[index + 1]->Fill(itrack.pt(), itrack.eta(), deltaX, deltaY, deltaZ); - } else { - hReAssoc[index + 2]->Fill(itrack.pt(), itrack.eta(), deltaX, deltaY, deltaZ); + auto perCollisionASample = besttracks.sliceBy(perColU, collision.globalIndex()); + for (auto const& atrack : perCollisionASample) { + if (!isBestTrackSelected(atrack)) { + continue; + } + auto itrack = atrack.template mfttrack_as(); + if (!isTrackSelected(itrack)) { + continue; + } + float phi = itrack.phi(); + o2::math_utils::bringTo02Pi(phi); + if (phi < Czero || TwoPI < phi) { + continue; + } + if (!itrack.has_collision()) { + continue; + } + if (gConf.cfgRemoveReassigned) { + if (itrack.collisionId() != atrack.bestCollisionId()) { + continue; + } + } + if (itrack.has_mcParticle()) { + auto particle = itrack.template mcParticle_as(); + auto collision = itrack.template collision_as(); + auto mcCollision = particle.template mcCollision_as(); + + if (eventCuts.useZVtxCutMC && (std::abs(mcCollision.posZ()) >= eventCuts.maxZvtx)) { + continue; + } + + float deltaX = -999.f; + float deltaY = -999.f; + float deltaZ = -999.f; + + if (mapVtxXrec.find(atrack.bestCollisionId()) == mapVtxXrec.end()) { + continue; + } + if (mapVtxYrec.find(atrack.bestCollisionId()) == mapVtxYrec.end()) { + continue; + } + if (mapVtxZrec.find(atrack.bestCollisionId()) == mapVtxZrec.end()) { + continue; + } + if (mapMcCollIdPerRecColl.find(atrack.bestCollisionId()) == mapMcCollIdPerRecColl.end()) { + continue; + } + const float vtxXbest = mapVtxXrec.find(atrack.bestCollisionId())->second; + const float vtxYbest = mapVtxYrec.find(atrack.bestCollisionId())->second; + const float vtxZbest = mapVtxZrec.find(atrack.bestCollisionId())->second; + // LOGP(info, "\t ---> \t .... \t vtxZrec: {} - collision.posZ(): {}", vtxZrec, collision.posZ()); + const float mcCollIdRec = mapMcCollIdPerRecColl.find(atrack.bestCollisionId())->second; + // LOGP(info, "\t ---> \t .... \t mcCollIdRec: {} - bestMCCol: {}", mcCollIdRec, bestMCCol); + deltaX = vtxXbest - mcCollision.posX(); + deltaY = vtxYbest - mcCollision.posY(); + deltaZ = vtxZbest - mcCollision.posZ(); + + if (itrack.collisionId() == atrack.bestCollisionId()) { // associated + if (collision.has_mcCollision() && mcCollIdRec == particle.mcCollisionId()) { + hReAssoc[0]->Fill(itrack.pt(), itrack.eta(), deltaX, deltaY, deltaZ); + } else { + hReAssoc[1]->Fill(itrack.pt(), itrack.eta(), deltaX, deltaY, deltaZ); + } + } else { + if (collision.has_mcCollision() && mcCollIdRec == particle.mcCollisionId()) { + hReAssoc[2]->Fill(itrack.pt(), itrack.eta(), deltaX, deltaY, deltaZ); + } else { + hReAssoc[3]->Fill(itrack.pt(), itrack.eta(), deltaX, deltaY, deltaZ); + } + } } } - hReAssoc[index]->Fill(itrack.pt(), itrack.eta(), deltaX, deltaY, deltaZ); - } else { - hReAssoc[index]->Fill(itrack.pt(), itrack.eta(), -999.f, -999.f, -999.f); } + mapVtxXrec.clear(); + mapVtxYrec.clear(); + mapVtxZrec.clear(); + mapMcCollIdPerRecColl.clear(); } } @@ -3266,8 +3456,8 @@ struct DndetaMFTPbPb { } else { if (isAmbiguous) { for (const auto& collIdx : track.compatibleCollIds()) { - auto ambCollision = collisions.rawIteratorAt(collIdx); - if (ambCollision.has_mcCollision() && ambCollision.mcCollisionId() == particle.mcCollisionId()) { + auto ambColl = collisions.rawIteratorAt(collIdx); + if (ambColl.has_mcCollision() && ambColl.mcCollisionId() == particle.mcCollisionId()) { if (!particle.isPhysicalPrimary()) { // Secondaries (weak decays and material) if constexpr (has_reco_cent) { registry.fill(HIST("Tracks/Centrality/THnGenSecAmb"), particle.pt(), particle.eta(), particle.mcCollision().posZ(), crec); @@ -3649,11 +3839,10 @@ struct DndetaMFTPbPb { Preslice compCollPerCol = o2::aod::fwdtrack::collisionId; /// @brief process function to check reassociation efficiency - template - void processReassocEfficiency(typename soa::Join const& collisions, + void processReassocEfficiency(CollsMCExtra::iterator const& mcCollision, + soa::SmallGroups const& collisions, MftTracksWCollsMC const& tracks, - MC const& mcCollisions, - aod::McParticles const& /*particles*/, + aod::McParticles const& particles, ExtBCs const& bcs) { if (bcs.size() == 0) { @@ -3662,158 +3851,203 @@ struct DndetaMFTPbPb { auto bc = bcs.begin(); initCCDB(bc); - registry.fill(HIST("Events/hNReEffColls"), 1.f, collisions.size()); - registry.fill(HIST("Events/hNReEffColls"), 2.f, mcCollisions.size()); - - for (const auto& collision : collisions) { - if (!isGoodEvent(collision)) { - continue; - } - float crec = getRecoCent(collision); - registry.fill(HIST("Events/Centrality/ReEffStatus"), 1, crec); - - if (!collision.has_mcCollision()) { - continue; - } + // At least one generated primary in MFT acceptance + TVX triggered collisions + if (gConf.cfgUseInelgt0wMFT && !isInelGt0wMft(particles)) { + return; + } + if (eventCuts.useZVtxCutMC && (std::abs(mcCollision.posZ()) >= eventCuts.maxZvtx)) { + return; + } - std::array dcaInfOrig; - std::array dcaInfo; - double bestDCA[2]; - auto trkPerColl = tracks.sliceBy(compCollPerCol, collision.globalIndex()); + const auto& nRecoColls = collisions.size(); + registry.fill(HIST("Events/hNReEffColls"), 1.f, nRecoColls); - for (auto const& track : trkPerColl) { - dcaInfOrig[0] = 999.f; // original DCAx from propagation - dcaInfOrig[1] = 999.f; // original DCAy from propagation - dcaInfOrig[2] = 999.f; // original DCAz from propagation - dcaInfo[0] = 999.f; // calcualted DCAxy - dcaInfo[1] = 999.f; // calculated DCAz - same as original - bestDCA[0] = 999.f; // minimal DCAxy - bestDCA[1] = 999.f; // minimal DCAz + // Generated evets with >= 1 reco collisions + if (nRecoColls > CintZero) { - if (!isTrackSelected(track)) { + auto maxNcontributors = -1; + auto bestCollIndex = -1; + auto crec = -1; + for (auto const& collision : collisions) { + if (!isGoodEvent(collision)) { continue; } - - auto bestCol = track.collisionId(); - uint index = uint(track.collisionId() >= 0); - auto ids = track.compatibleCollIds(); - bool isAmbiguous = (ids.size() > 1); - - if (!track.has_mcParticle()) { + if (maxNcontributors < collision.numContrib()) { + maxNcontributors = collision.numContrib(); + bestCollIndex = collision.globalIndex(); + crec = getRecoCent(collision); + } else { continue; } - auto particle = track.template mcParticle_as(); - if (!isChrgParticle(particle.pdgCode())) { + } + + registry.fill(HIST("AmbTracks/hVtxzMCrec"), mcCollision.posZ()); + + for (const auto& collision : collisions) { + if (!isGoodEvent(collision)) { continue; } - if (particle.eta() <= trackCuts.minEta || particle.eta() >= trackCuts.maxEta) { + // Select collisions with the largest number of contributors + if (bestCollIndex != collision.globalIndex()) { continue; } - if (gConf.cfgUseParticleSel && !isParticleSelected(particle)) { + + registry.fill(HIST("Events/Centrality/ReEffStatus"), 1, crec); + + if (!collision.has_mcCollision()) { continue; } - int bestMCCol = -1; - std::vector v1; // Temporary null vector for the computation of the covariance matrix - SMatrix55 tcovs(v1.begin(), v1.end()); - SMatrix5 tpars(track.x(), track.y(), track.phi(), track.tgl(), track.signed1Pt()); - o2::track::TrackParCovFwd trackPar{track.z(), tpars, tcovs, track.chi2()}; + std::array dcaInfOrig; + std::array dcaInfo; + double bestDCA[2]; + auto trkPerColl = tracks.sliceBy(compCollPerCol, collision.globalIndex()); + + for (auto const& track : trkPerColl) { + dcaInfOrig[0] = 999.f; // original DCAx from propagation + dcaInfOrig[1] = 999.f; // original DCAy from propagation + dcaInfOrig[2] = 999.f; // original DCAz from propagation + dcaInfo[0] = 999.f; // calcualted DCAxy + dcaInfo[1] = 999.f; // calculated DCAz - same as original + bestDCA[0] = 999.f; // minimal DCAxy + bestDCA[1] = 999.f; // minimal DCAz + + if (!isTrackSelected(track)) { + continue; + } - if (index) { - auto mcCollision = particle.template mcCollision_as(); - if (eventCuts.useZDiffCut) { - if (std::abs(collision.posZ() - mcCollision.posZ()) > eventCuts.maxZvtxDiff) { + auto bestCol = track.has_collision() ? track.collisionId() : -1; + uint index = uint(track.collisionId() >= 0); + bool isAmbiguous = (track.compatibleCollIds().size() > 1); + + if (!track.has_mcParticle()) { + continue; + } + auto particle = track.mcParticle_as(); + if (!isChrgParticle(particle.pdgCode())) { + continue; + } + if (particle.eta() <= trackCuts.minEta || particle.eta() >= trackCuts.maxEta) { + continue; + } + if (gConf.cfgUseParticleSel && !isParticleSelected(particle)) { + continue; + } + + if (gConf.cfgRemoveReassigned) { + if (track.compatibleCollIds().empty() || (track.compatibleCollIds().size() == 1 && bestCol == track.compatibleCollIds()[0])) { continue; } } - if (isAmbiguous) { - for (const auto& collIdx : track.compatibleCollIds()) { - auto ambCollision = collisions.rawIteratorAt(collIdx); - if (!ambCollision.has_mcCollision()) { + int bestMCCol = -1; + o2::track::TrackParCovFwd trackPar = o2::aod::fwdtrackutils::getTrackParCovFwdShift(track, mZShift); + + if (index) { + auto mcCollision = particle.mcCollision_as(); + if (eventCuts.useZDiffCut) { + if (std::abs(collision.posZ() - mcCollision.posZ()) > eventCuts.maxZvtxDiff) { continue; } + } - trackPar.propagateToDCAhelix(bZ, {ambCollision.posX(), ambCollision.posY(), ambCollision.posZ()}, dcaInfOrig); + if (isAmbiguous) { + for (const auto& collIdx : track.compatibleCollIds()) { + auto ambColl = collisions.rawIteratorAt(collIdx); + if (!ambColl.has_mcCollision()) { + continue; + } - if (gConf.cfgDCAtype == 0) { - dcaInfo[0] = dcaInfOrig[0]; - } else if (gConf.cfgDCAtype == 1) { - dcaInfo[0] = dcaInfOrig[1]; - } else if (gConf.cfgDCAtype == CintTwo) { - dcaInfo[0] = std::sqrt(dcaInfOrig[0] * dcaInfOrig[0] + dcaInfOrig[1] * dcaInfOrig[1]); - } - dcaInfo[1] = dcaInfOrig[2]; + trackPar.propagateToDCAhelix(bZ, {ambColl.posX(), ambColl.posY(), ambColl.posZ()}, dcaInfOrig); - // LOGP(info, "-> track {}: {}", track.globalIndex(), dcaInfo[0]); - registry.fill(HIST("AmbTracks/DCAXY"), dcaInfo[0]); - registry.fill(HIST("AmbTracks/DCAZ"), dcaInfo[1]); + if (gConf.cfgDCAtype == 0) { + dcaInfo[0] = dcaInfOrig[0]; + } else if (gConf.cfgDCAtype == 1) { + dcaInfo[0] = dcaInfOrig[1]; + } else if (gConf.cfgDCAtype == 2) { + dcaInfo[0] = std::sqrt(dcaInfOrig[0] * dcaInfOrig[0] + dcaInfOrig[1] * dcaInfOrig[1]); + } + dcaInfo[1] = dcaInfOrig[2]; - if ((std::abs(dcaInfo[0]) < std::abs(bestDCA[0])) && (std::abs(dcaInfo[1]) < std::abs(bestDCA[1]))) { - bestCol = ambCollision.globalIndex(); - bestMCCol = ambCollision.mcCollisionId(); - bestDCA[0] = dcaInfo[0]; - bestDCA[1] = dcaInfo[1]; - } - } + if ((std::abs(dcaInfo[0]) < std::abs(bestDCA[0])) && (std::abs(dcaInfo[1]) < std::abs(bestDCA[1]))) { + bestCol = ambColl.globalIndex(); + bestMCCol = ambColl.mcCollisionId(); + bestDCA[0] = dcaInfo[0]; + bestDCA[1] = dcaInfo[1]; + } - registry.fill(HIST("AmbTracks/DCAXYBest"), bestDCA[0]); - registry.fill(HIST("AmbTracks/DCAZBest"), bestDCA[1]); - registry.fill(HIST("AmbTracks/Centrality/THnDCAxyBestGen"), particle.pt(), particle.eta(), mcCollision.posZ(), bestDCA[0], bestDCA[1], crec); + // LOGP(info, "-> track {}: {}", track.globalIndex(), dcaInfo[0]); + registry.fill(HIST("AmbTracks/DCAXY"), dcaInfo[0]); + registry.fill(HIST("AmbTracks/DCAZ"), dcaInfo[1]); + } - if (particle.isPhysicalPrimary()) { - registry.fill(HIST("AmbTracks/DCAXYBestPrim"), bestDCA[0]); - registry.fill(HIST("AmbTracks/DCAZBestPrim"), bestDCA[1]); - registry.fill(HIST("AmbTracks/Centrality/THnDCAxyBestGenPrim"), particle.pt(), particle.eta(), mcCollision.posZ(), bestDCA[0], bestDCA[1], crec); - } + registry.fill(HIST("AmbTracks/DCAXYBest"), bestDCA[0]); + registry.fill(HIST("AmbTracks/DCAZBest"), bestDCA[1]); + registry.fill(HIST("AmbTracks/Centrality/THnDCAxyBestGen"), particle.pt(), particle.eta(), mcCollision.posZ(), bestDCA[0], bestDCA[1], crec); + registry.fill(HIST("AmbTracks/BestGenDxyz"), collision.posX() - mcCollision.posX(), collision.posY() - mcCollision.posY(), collision.posZ() - mcCollision.posZ(), bestDCA[0], bestDCA[1]); - auto mcCollID = particle.mcCollisionId(); - registry.fill(HIST("Events/Centrality/ReEffStatus"), 2, crec); - - if (!track.has_collision()) { - registry.fill(HIST("Events/Centrality/ReEffStatus"), 4, crec); - if (bestMCCol == mcCollID) // correctly assigned to bestCol - { - registry.fill(HIST("Events/Centrality/ReEffStatus"), 6, crec); - registry.fill(HIST("AmbTracks/DCAXYBestTrue"), bestDCA[0]); - registry.fill(HIST("AmbTracks/DCAZBestTrue"), bestDCA[1]); - registry.fill(HIST("AmbTracks/Centrality/THnDCAxyBestTrue"), particle.pt(), particle.eta(), mcCollision.posZ(), bestDCA[0], bestDCA[1], crec); - } else { - registry.fill(HIST("AmbTracks/DCAXYBestFalse"), bestDCA[0]); - registry.fill(HIST("AmbTracks/DCAZBestFalse"), bestDCA[1]); - registry.fill(HIST("AmbTracks/Centrality/THnDCAxyBestFalse"), particle.pt(), particle.eta(), mcCollision.posZ(), bestDCA[0], bestDCA[1], crec); - } - } else if (track.collisionId() != bestCol) { // reassgined - auto collOrig = track.template collision_as>(); - registry.fill(HIST("Events/Centrality/ReEffStatus"), 3, crec); - if (bestMCCol == mcCollID) // correctly reassigned - { - registry.fill(HIST("Events/Centrality/ReEffStatus"), 6, crec); - registry.fill(HIST("AmbTracks/DCAXYBestTrue"), bestDCA[0]); - registry.fill(HIST("AmbTracks/DCAZBestTrue"), bestDCA[1]); - registry.fill(HIST("AmbTracks/Centrality/THnDCAxyBestTrue"), particle.pt(), particle.eta(), mcCollision.posZ(), bestDCA[0], bestDCA[1], crec); - } else { // uncorrectly reassigned - registry.fill(HIST("AmbTracks/DCAXYBestFalse"), bestDCA[0]); - registry.fill(HIST("AmbTracks/DCAZBestFalse"), bestDCA[1]); - registry.fill(HIST("AmbTracks/Centrality/THnDCAxyBestFalse"), particle.pt(), particle.eta(), mcCollision.posZ(), bestDCA[0], bestDCA[1], crec); + if (particle.isPhysicalPrimary()) { + registry.fill(HIST("AmbTracks/DCAXYBestPrim"), bestDCA[0]); + registry.fill(HIST("AmbTracks/DCAZBestPrim"), bestDCA[1]); + registry.fill(HIST("AmbTracks/Centrality/THnDCAxyBestGenPrim"), particle.pt(), particle.eta(), mcCollision.posZ(), bestDCA[0], bestDCA[1], crec); + registry.fill(HIST("AmbTracks/BestPrimDxyz"), collision.posX() - mcCollision.posX(), collision.posY() - mcCollision.posY(), collision.posZ() - mcCollision.posZ(), bestDCA[0], bestDCA[1]); } - if (collOrig.mcCollisionId() == mcCollID) { // initially correctly assigned - registry.fill(HIST("Events/Centrality/ReEffStatus"), 5, crec); - registry.fill(HIST("AmbTracks/DCAXYBestTrueOrigReAssoc"), bestDCA[0]); - registry.fill(HIST("AmbTracks/DCAZBestTrueOrigReAssoc"), bestDCA[1]); - registry.fill(HIST("AmbTracks/Centrality/THnDCAxyBestTrueOrigReAssoc"), particle.pt(), particle.eta(), mcCollision.posZ(), bestDCA[0], bestDCA[1], crec); - } - } else { // the track has a collision and track.collisionId() == bestCol - if (track.collisionId() != bestCol) { - // LOGP(info, "-> track id {}: bestCollid {}", track.collisionId(), bestCol); - } - registry.fill(HIST("Events/Centrality/ReEffStatus"), 7, crec); - if (bestMCCol == mcCollID) // correctly assigned - { + + auto mcCollID = particle.mcCollisionId(); + registry.fill(HIST("Events/Centrality/ReEffStatus"), 2, crec); + + if (!track.has_collision()) { + registry.fill(HIST("Events/Centrality/ReEffStatus"), 4, crec); + if (bestMCCol == mcCollID) // correctly assigned to bestCol + { + registry.fill(HIST("Events/Centrality/ReEffStatus"), 6, crec); + registry.fill(HIST("AmbTracks/DCAXYBestTrue"), bestDCA[0]); + registry.fill(HIST("AmbTracks/DCAZBestTrue"), bestDCA[1]); + registry.fill(HIST("AmbTracks/Centrality/THnDCAxyBestTrue"), particle.pt(), particle.eta(), mcCollision.posZ(), bestDCA[0], bestDCA[1], crec); + registry.fill(HIST("AmbTracks/BestTrueDxyz"), collision.posX() - mcCollision.posX(), collision.posY() - mcCollision.posY(), collision.posZ() - mcCollision.posZ(), bestDCA[0], bestDCA[1]); + } else { + registry.fill(HIST("AmbTracks/DCAXYBestFalse"), bestDCA[0]); + registry.fill(HIST("AmbTracks/DCAZBestFalse"), bestDCA[1]); + registry.fill(HIST("AmbTracks/Centrality/THnDCAxyBestFalse"), particle.pt(), particle.eta(), mcCollision.posZ(), bestDCA[0], bestDCA[1], crec); + registry.fill(HIST("AmbTracks/BestFalseDxyz"), collision.posX() - mcCollision.posX(), collision.posY() - mcCollision.posY(), collision.posZ() - mcCollision.posZ(), bestDCA[0], bestDCA[1]); + } + } else if (track.collisionId() != bestCol) { // reassgined + auto collOrig = collisions.rawIteratorAt(track.collisionId()); + registry.fill(HIST("Events/Centrality/ReEffStatus"), 3, crec); + if (bestMCCol == mcCollID) // correctly reassigned + { + registry.fill(HIST("Events/Centrality/ReEffStatus"), 6, crec); + registry.fill(HIST("AmbTracks/DCAXYBestTrue"), bestDCA[0]); + registry.fill(HIST("AmbTracks/DCAZBestTrue"), bestDCA[1]); + registry.fill(HIST("AmbTracks/Centrality/THnDCAxyBestTrue"), particle.pt(), particle.eta(), mcCollision.posZ(), bestDCA[0], bestDCA[1], crec); + registry.fill(HIST("AmbTracks/BestTrueDxyz"), collision.posX() - mcCollision.posX(), collision.posY() - mcCollision.posY(), collision.posZ() - mcCollision.posZ(), bestDCA[0], bestDCA[1]); + } else { // uncorrectly reassigned + registry.fill(HIST("AmbTracks/DCAXYBestFalse"), bestDCA[0]); + registry.fill(HIST("AmbTracks/DCAZBestFalse"), bestDCA[1]); + registry.fill(HIST("AmbTracks/Centrality/THnDCAxyBestFalse"), particle.pt(), particle.eta(), mcCollision.posZ(), bestDCA[0], bestDCA[1], crec); + registry.fill(HIST("AmbTracks/BestFalseDxyz"), collision.posX() - mcCollision.posX(), collision.posY() - mcCollision.posY(), collision.posZ() - mcCollision.posZ(), bestDCA[0], bestDCA[1]); + } + if (collOrig.mcCollisionId() == mcCollID) { // initially correctly assigned + registry.fill(HIST("Events/Centrality/ReEffStatus"), 5, crec); + registry.fill(HIST("AmbTracks/DCAXYBestTrueOrigReAssoc"), bestDCA[0]); + registry.fill(HIST("AmbTracks/DCAZBestTrueOrigReAssoc"), bestDCA[1]); + registry.fill(HIST("AmbTracks/Centrality/THnDCAxyBestTrueOrigReAssoc"), particle.pt(), particle.eta(), mcCollision.posZ(), bestDCA[0], bestDCA[1], crec); + registry.fill(HIST("AmbTracks/BestTrueOrigReAssocDxyz"), collision.posX() - mcCollision.posX(), collision.posY() - mcCollision.posY(), collision.posZ() - mcCollision.posZ(), bestDCA[0], bestDCA[1]); + } + } else { // not reassigned - the track has a collision and track.collisionId() == bestCol + if (track.collisionId() != bestCol) { + registry.fill(HIST("Events/Centrality/ReEffStatus"), 7, crec); + // LOGP(info, "-> track id {}: bestCollid {}", track.collisionId(), bestCol); + } registry.fill(HIST("Events/Centrality/ReEffStatus"), 8, crec); - registry.fill(HIST("AmbTracks/DCAXYBestTrueOrigAssoc"), bestDCA[0]); - registry.fill(HIST("AmbTracks/DCAZBestTrueOrigAssoc"), bestDCA[1]); - registry.fill(HIST("AmbTracks/Centrality/THnDCAxyBestTrueOrigAssoc"), particle.pt(), particle.eta(), mcCollision.posZ(), bestDCA[0], bestDCA[1], crec); + if (bestMCCol == mcCollID) // correctly assigned + { + registry.fill(HIST("Events/Centrality/ReEffStatus"), 9, crec); + registry.fill(HIST("AmbTracks/DCAXYBestTrueOrigAssoc"), bestDCA[0]); + registry.fill(HIST("AmbTracks/DCAZBestTrueOrigAssoc"), bestDCA[1]); + registry.fill(HIST("AmbTracks/Centrality/THnDCAxyBestTrueOrigAssoc"), particle.pt(), particle.eta(), mcCollision.posZ(), bestDCA[0], bestDCA[1], crec); + registry.fill(HIST("AmbTracks/BestTrueOrigAssocDxyz"), collision.posX() - mcCollision.posX(), collision.posY() - mcCollision.posY(), collision.posZ() - mcCollision.posZ(), bestDCA[0], bestDCA[1]); + } } } } @@ -3822,16 +4056,7 @@ struct DndetaMFTPbPb { } } - void processReassocEfficiencyCentFT0C(soa::Join const& collisions, - MftTracksWCollsMC const& tracks, - aod::McCollisions const& mccollisions, - aod::McParticles const& particles, - ExtBCs const& bcs) - { - processReassocEfficiency(collisions, tracks, mccollisions, particles, bcs); - } - - PROCESS_SWITCH(DndetaMFTPbPb, processReassocEfficiencyCentFT0C, "Process collision-reassociation efficiency based on track propagation DCA 3D (in FT0C centrality bins)", false); + PROCESS_SWITCH(DndetaMFTPbPb, processReassocEfficiency, "Process collision-reassociation efficiency based on track propagation DCA 3D (in FT0C centrality bins)", false); /// @brief process function to calculate signal loss based on MC void processEventAndSignalLossCentFT0C(CollsMCExtra::iterator const& mcCollision, From 7433a1e73dc5932454503beee8260cf03a178027 Mon Sep 17 00:00:00 2001 From: Joachim Carlo Kristian Bjerg Hansen <50103987+joachimckh@users.noreply.github.com> Date: Mon, 23 Feb 2026 08:11:29 +0100 Subject: [PATCH 028/347] [PWGJE] Various bin changes (#15070) --- PWGJE/Tasks/jetSpectraEseTask.cxx | 43 +++++++++++++++++-------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/PWGJE/Tasks/jetSpectraEseTask.cxx b/PWGJE/Tasks/jetSpectraEseTask.cxx index 8e6417a7298..e9eff0f6cc1 100644 --- a/PWGJE/Tasks/jetSpectraEseTask.cxx +++ b/PWGJE/Tasks/jetSpectraEseTask.cxx @@ -65,9 +65,9 @@ struct JetSpectraEseTask { ConfigurableAxis binFit0{"binFit0", {100, 0, 50}, ""}; ConfigurableAxis binFit13{"binFit13", {100, 0, 1.4}, ""}; ConfigurableAxis binFit24{"binFit24", {100, 0, 10}, ""}; - ConfigurableAxis binTrackPt{"binTrackPt", {1000, 0, 100}, ""}; + ConfigurableAxis binTrackPt{"binTrackPt", {100, 0, 100}, ""}; ConfigurableAxis dbinEta{"dbinEta", {100, -1.6, 1.6}, ""}; - ConfigurableAxis dbinPhi{"dbinPhi", {120, -o2::constants::math::PIHalf, o2::constants::math::TwoPI - o2::constants::math::PIHalf}, ""}; + ConfigurableAxis dbinPhi{"dbinPhi", {120, -o2::constants::math::PIHalf, 3 * o2::constants::math::PI / 2}, ""}; Configurable jetPtMin{"jetPtMin", 5.0, "minimum jet pT cut"}; Configurable jetR{"jetR", 0.2, "jet resolution parameter"}; @@ -136,6 +136,9 @@ struct JetSpectraEseTask { AxisSpec fitAxis24 = {binFit24, "Fit24"}; AxisSpec trackPtAxis = {binTrackPt, "#it{p}_{T}"}; + ConfigurableAxis assocTrackPt{"assocTrackPt", {VARIABLE_WIDTH, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0}, "pT of associated track"}; + ConfigurableAxis rhoAxis{"rhoAxis", {50, 0, 200}, "#rho"}; + ConfigurableAxis vertexZAxis{"vertexZAxis", {50, -10.0, 10.0}, "z vertex"}; HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; @@ -212,15 +215,15 @@ struct JetSpectraEseTask { registry.add("hJetPt_bkgsub", "jet pT background sub;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {{jetPtAxis}}}); registry.add("hJetEta", "jet #eta;#eta_{jet};entries", {HistType::kTH1F, {{etaAxis}}}); registry.add("hJetPhi", "jet #phi;#phi_{jet};entries", {HistType::kTH1F, {{phiAxis}}}); - registry.add("eventQA/hRho", ";#rho;entries", {HistType::kTH2F, {{centAxis}, {100, 0, 200.}}}); - registry.add("eventQA/hRhoPhi", ";#rho;entries", {HistType::kTH2F, {{centAxis}, {100, 0, 200.}}}); - registry.add("hJetArea", ";area_{jet};entries", {HistType::kTH1F, {{80, 0, 10.}}}); - registry.add("hJetAreaRho", "", {HistType::kTH1F, {{100, 0, 500.}}}); + registry.add("eventQA/hRho", ";#rho;entries", {HistType::kTH2F, {{centAxis}, {rhoAxis}}}); + registry.add("eventQA/hRhoPhi", ";#rho;entries", {HistType::kTH2F, {{centAxis}, {rhoAxis}}}); + registry.add("hJetArea", ";area_{jet};entries", {HistType::kTH1F, {{50, 0, 5.}}}); + registry.add("hJetAreaRho", "", {HistType::kTH1F, {{50, 0, 10.}}}); registry.add("hCentJetPtdPhiq2", "", {HistType::kTHnSparseF, {{centAxis}, {jetPtAxis}, {dPhiAxis}, {eseAxis}}}); registry.add("hCentJetPtdPhiq2RhoPhi", "", {HistType::kTHnSparseF, {{centAxis}, {jetPtAxis}, {dPhiAxis}, {eseAxis}}}); - registry.add("eventQA/before/hVtxZ", ";z_{vtx} (cm);entries", {HistType::kTH1F, {{100, -10.0, 10.0}}}); - registry.add("eventQA/after/hVtxZ", ";z_{vtx} (cm);entries", {HistType::kTH1F, {{100, -10.0, 10.0}}}); + registry.add("eventQA/before/hVtxZ", ";z_{vtx} (cm);entries", {HistType::kTH1F, {{vertexZAxis}}}); + registry.add("eventQA/after/hVtxZ", ";z_{vtx} (cm);entries", {HistType::kTH1F, {{vertexZAxis}}}); registry.get(HIST("eventQA/hEventCounter"))->GetXaxis()->SetBinLabel(kFilteredInputEv, "Input filtered event"); registry.get(HIST("eventQA/hEventCounter"))->GetXaxis()->SetBinLabel(kEventSel, "Event selection"); @@ -240,9 +243,9 @@ struct JetSpectraEseTask { registry.add("eventQA/hfitPar3", "", {HistType::kTH2F, {{centAxis}, {fitAxis13}}}); registry.add("eventQA/hfitPar4", "", {HistType::kTH2F, {{centAxis}, {fitAxis24}}}); registry.add("eventQA/hPValueCentCDF", "p-value cDF vs centrality; centrality; p-value", {HistType::kTH2F, {{centAxis}, {40, 0, 1}}}); - registry.add("eventQA/hCentChi2Ndf", "Chi2 vs centrality; centrality; #tilde{#chi^{2}}", {HistType::kTH2F, {{centAxis}, {100, 0, 5}}}); - registry.add("eventQA/hCentPhi", "centrality vs #rho(#varphi); centrality; #rho(#varphi) ", {HistType::kTH2F, {{centAxis}, {210, -10.0, 200.0}}}); - registry.add("eventQA/hdPhiRhoPhi", "#varphi vs #rho(#varphi); #varphi - #Psi_{EP,2}; #rho(#varphi) ", {HistType::kTH2F, {{40, -o2::constants::math::PI, o2::constants::math::PI}, {210, -10.0, 200.0}}}); + registry.add("eventQA/hCentChi2Ndf", "Chi2 vs centrality; centrality; #tilde{#chi^{2}}", {HistType::kTH2F, {{centAxis}, {50, 0, 5}}}); + registry.add("eventQA/hCentPhi", "centrality vs #rho(#varphi); centrality; #rho(#varphi) ", {HistType::kTH2F, {{centAxis}, {rhoAxis}}}); + registry.add("eventQA/hdPhiRhoPhi", "#varphi vs #rho(#varphi); #varphi - #Psi_{EP,2}; #rho(#varphi) ", {HistType::kTH2F, {{40, -o2::constants::math::PI, o2::constants::math::PI}, {rhoAxis}}}); registry.add("jetQA/before/hLeadJetPt", ";Centrality;#it{p}_{T,lead jet} (GeV/#it{c});entries", {HistType::kTH2F, {{centAxis}, {jetPtAxis}}}); registry.add("jetQA/before/hLeadJetPhi", ";Centrality;#phi_{lead jet};entries", {HistType::kTH2F, {{centAxis}, {phiAxis}}}); @@ -255,7 +258,7 @@ struct JetSpectraEseTask { std::vector axes = { {centAxis}, {jetPtAxis}, - {trackPtAxis}, + {assocTrackPt}, {detaAxis}, {dphiAxis}, {dPhiAxis}, @@ -283,14 +286,14 @@ struct JetSpectraEseTask { registry.get(HIST("eventQA/hEventCounterMixed"))->GetXaxis()->SetBinLabel(kEse, "ESE available"); registry.get(HIST("eventQA/hEventCounterMixed"))->GetXaxis()->SetBinLabel(kRhoLocal, "rho(#phi) available"); registry.get(HIST("eventQA/hEventCounterMixed"))->GetXaxis()->SetBinLabel(kLeadJetCut, "leading jet pT cut"); - registry.add("eventQA/before/hVtxZMixed", ";z_{vtx} (cm);entries", {HistType::kTH1F, {{100, -10.0, 10.0}}}); - registry.add("eventQA/after/hVtxZMixed", ";z_{vtx} (cm);entries", {HistType::kTH1F, {{100, -10.0, 10.0}}}); - registry.add("eventQA/before/hVtxZMixed2", ";z_{vtx} (cm);entries", {HistType::kTH1F, {{100, -10.0, 10.0}}}); - registry.add("eventQA/after/hVtxZMixed2", ";z_{vtx} (cm);entries", {HistType::kTH1F, {{100, -10.0, 10.0}}}); + registry.add("eventQA/before/hVtxZMixed", ";z_{vtx} (cm);entries", {HistType::kTH1F, {{vertexZAxis}}}); + registry.add("eventQA/after/hVtxZMixed", ";z_{vtx} (cm);entries", {HistType::kTH1F, {{vertexZAxis}}}); + registry.add("eventQA/before/hVtxZMixed2", ";z_{vtx} (cm);entries", {HistType::kTH1F, {{vertexZAxis}}}); + registry.add("eventQA/after/hVtxZMixed2", ";z_{vtx} (cm);entries", {HistType::kTH1F, {{vertexZAxis}}}); registry.add("eventQA/hCentralityAnalyzedMixed", ";Centrality;entries", {HistType::kTH1F, {{centAxis}}}); registry.add("eventQA/hCentralityAnalyzedMixed2", ";Centrality;entries", {HistType::kTH1F, {{centAxis}}}); - registry.add("eventQA/hDeltaCentMixed", ";Centrality difference;entries", {HistType::kTH1F, {{100, -100, 100}}}); - registry.add("eventQA/hDeltaVtxZMixed", ";z_{vtx} difference (cm);entries", {HistType::kTH1F, {{100, -20.0, 20.0}}}); + registry.add("eventQA/hDeltaCentMixed", ";Centrality difference;entries", {HistType::kTH1F, {{50, -100, 100}}}); + registry.add("eventQA/hDeltaVtxZMixed", ";z_{vtx} difference (cm);entries", {HistType::kTH1F, {{50, -20.0, 20.0}}}); registry.add("trackQA/before/hTrackPtMixed", "", {HistType::kTH2F, {{centAxis}, {trackPtAxis}}}); registry.add("trackQA/before/hTrackEtaMixed", "", {HistType::kTH2F, {{centAxis}, {etaAxis}}}); @@ -301,12 +304,12 @@ struct JetSpectraEseTask { std::vector axes = { {centAxis}, {jetPtAxis}, - {trackPtAxis}, + {assocTrackPt}, {detaAxis}, {dphiAxis}, {dPhiAxis}, {eseAxis}}; - registry.add("thn_jethad_corr_mixed", "jet-had; centrality; #it{p}_{T,lead jet} - #rho_{local} * area_{jet} (GeV/#it{c}); #it{p}_{T,track} (GeV/#it{c}); #Delta#eta; #Delta#phi; #Delta#phi to EP; #it{q}_{2}", {HistType::kTHnSparseF, axes}); + registry.add("thn_jethad_corr_mixed", "jet-had; centrality; #it{p}_{T,jet} - #rho_{local} * area_{jet} (GeV/#it{c}); #it{p}_{T,track} (GeV/#it{c}); #Delta#eta; #Delta#phi; #Delta#phi to EP; #it{q}_{2}", {HistType::kTHnSparseF, axes}); registry.add("hNtrigMixed", "", {HistType::kTHnSparseF, {{centAxis}, {jetPtAxis}, {dPhiAxis}, {eseAxis}}}); } if (doprocessESEEPData) { From 21ee232811f4e6ac78cef35cdbffe67bed6c0949 Mon Sep 17 00:00:00 2001 From: Artem Kotliarov <71133985+KotliarovAr@users.noreply.github.com> Date: Mon, 23 Feb 2026 08:12:52 +0100 Subject: [PATCH 029/347] [PWGJE] Smearing of TT (#15107) --- PWGJE/Tasks/recoilJets.cxx | 514 +++++++++++++++++++++++++++---------- 1 file changed, 385 insertions(+), 129 deletions(-) diff --git a/PWGJE/Tasks/recoilJets.cxx b/PWGJE/Tasks/recoilJets.cxx index 29087baeac3..378c42875ed 100644 --- a/PWGJE/Tasks/recoilJets.cxx +++ b/PWGJE/Tasks/recoilJets.cxx @@ -57,13 +57,15 @@ using namespace o2::framework::expressions; using CollDataIt = soa::Filtered::iterator; using CollRhoDataIt = soa::Filtered>::iterator; using CollRhoOutlierDetIt = soa::Filtered>::iterator; +using CollOutlierDetIt = soa::Filtered>::iterator; +using CollDetIt = soa::Filtered::iterator; using CollRhoDetIt = soa::Filtered>::iterator; using CollPartIt = soa::Filtered::iterator; -using CollRhoPartTbl = soa::Filtered>; +using CollRhoPartTbl = soa::Join; using CollRhoPartIt = soa::Filtered>::iterator; using CollRhoOutlierPartIt = soa::Filtered>::iterator; -using CollRhoOutlierPartTbl = soa::Filtered>; +using CollRhoOutlierPartTbl = soa::Join; // --- Event multiplicity (+ ZDC etc.) using EvMultZDCDataIt = soa::Filtered>::iterator; @@ -72,6 +74,7 @@ using EvMultOutlierPartIt = soa::Filtered; +using TrackMCLbsTbl = soa::Filtered; using PartTbl = soa::Filtered; // --- Jets (with constituents) @@ -98,10 +101,11 @@ struct RecoilJets { triggerMasks{"triggerMasks", "", "Relevant trigger masks: fTrackLowPt,fTrackHighPt"}; Configurable vertexZCut{"vertexZCut", 10., "Accepted z-vertex range"}; - Configurable skipMBGapEvents{"skipMBGapEvents", false, - "Flag to choose to reject min. bias gap events; jet-level rejection " - "applied at the jet finder level, here rejection is applied for " - "collision and track process functions"}; + Configurable isMCJJProd{"isMCJJProd", false, "Flag to select MC production: MB (false) or JJ(true)"}, + skipMBGapEvents{"skipMBGapEvents", false, + "Flag to choose to reject min. bias gap events; jet-level rejection " + "applied at the jet finder level, here rejection is applied for " + "collision and track process functions"}; } ev; // ---------- RCT / flag-based selections ---------- @@ -226,6 +230,15 @@ struct RecoilJets { std::string axisName; // Empty for AxisSpec }; + struct FT0Metrics { + float multFT0A = 0.f; + float multFT0C = 0.f; + float multFT0M = 0.f; + float scaledFT0A = 0.f; + float scaledFT0C = 0.f; + float scaledFT0M = 0.f; + }; + void init(InitContext const&) { // Initialize histogram axes: configurable @@ -294,12 +307,12 @@ struct RecoilJets { // List of raw and MC det. distributions if (doprocessData || doprocessMCDetLevel || doprocessMCDetLevelWeighted) { - spectra.add("hEventSelectionCount", "Count # of events in the analysis", kTH1F, {{5, 0.0, 5.}}); - spectra.get(HIST("hEventSelectionCount"))->GetXaxis()->SetBinLabel(1, "Total # of events"); - spectra.get(HIST("hEventSelectionCount"))->GetXaxis()->SetBinLabel(2, Form("# of events after sel. %s", evSelToString.data())); - spectra.get(HIST("hEventSelectionCount"))->GetXaxis()->SetBinLabel(3, "# of events w. outlier"); - spectra.get(HIST("hEventSelectionCount"))->GetXaxis()->SetBinLabel(4, "# of events w/o assoc MC."); - spectra.get(HIST("hEventSelectionCount"))->GetXaxis()->SetBinLabel(5, "# of selected events"); + spectra.add("hEventSelectionCountReco", "Count # of events in the analysis", kTH1F, {{5, 0.0, 5.}}); + spectra.get(HIST("hEventSelectionCountReco"))->GetXaxis()->SetBinLabel(1, "Total # of events"); + spectra.get(HIST("hEventSelectionCountReco"))->GetXaxis()->SetBinLabel(2, Form("# of events after sel. %s", evSelToString.data())); + spectra.get(HIST("hEventSelectionCountReco"))->GetXaxis()->SetBinLabel(3, "# of events w. outlier"); + spectra.get(HIST("hEventSelectionCountReco"))->GetXaxis()->SetBinLabel(4, "# of events w/o assoc MC."); + spectra.get(HIST("hEventSelectionCountReco"))->GetXaxis()->SetBinLabel(5, "# of selected events"); spectra.add("hTrackSelectionCount", "Count # of tracks in the analysis", kTH1F, {{2, 0.0, 2.}}); spectra.get(HIST("hTrackSelectionCount"))->GetXaxis()->SetBinLabel(1, "Total # of tracks"); @@ -378,11 +391,11 @@ struct RecoilJets { Form("Events w. TT_{Sig}: scaled %s & #rho", eaAxis.label), kTH2F, {{eaAxis.axis, eaAxis.axisName}, rho}, hist.sumw2); - spectra.add(Form("hScaled%s_DPhi_JetPt_Corr_TTRef_RectrictedPhi", eaAxis.label), + spectra.add(Form("hScaled%s_DPhi_JetPt_Corr_TTRef_RestrictedPhi", eaAxis.label), Form("Events w. TT_{Ref} #in #varphi (%.2f, %.2f): scaled %s & #Delta#varphi & #it{p}_{T, jet}^{ch}", phiMin, phiMax, eaAxis.label), kTH3F, {{eaAxis.axis, eaAxis.axisName}, deltaPhiAngle, jetPTcorr}, hist.sumw2); - spectra.add(Form("hScaled%s_DPhi_JetPt_Corr_TTSig_RectrictedPhi", eaAxis.label), + spectra.add(Form("hScaled%s_DPhi_JetPt_Corr_TTSig_RestrictedPhi", eaAxis.label), Form("Events w. TT_{Sig} #in #varphi (%.2f, %.2f): scaled %s & #Delta#varphi & #it{p}_{T, jet}^{ch}", phiMin, phiMax, eaAxis.label), kTH3F, {{eaAxis.axis, eaAxis.axisName}, deltaPhiAngle, jetPTcorr}, hist.sumw2); } @@ -400,7 +413,6 @@ struct RecoilJets { // List of MC particle level distributions if (doprocessMCPartLevel || doprocessMCPartLevelWeighted) { - spectra.add("hEventSelectionCountPartLevel", "Count # of events in the part. level analysis", kTH1F, {{4, 0.0, 4.}}); spectra.get(HIST("hEventSelectionCountPartLevel"))->GetXaxis()->SetBinLabel(1, "Total # of events"); spectra.get(HIST("hEventSelectionCountPartLevel"))->GetXaxis()->SetBinLabel(2, Form("# of events after sel. %s", evSelToString.data())); @@ -481,11 +493,11 @@ struct RecoilJets { kTH2F, {{eaAxis.axis, eaAxis.axisName}, rho}, hist.sumw2); // Rectricted phi range for TT selection - spectra.add(Form("hScaled%s_DPhi_JetPt_Corr_TTRef_RectrictedPhi_Part", eaAxis.label), + spectra.add(Form("hScaled%s_DPhi_JetPt_Corr_TTRef_RestrictedPhi_Part", eaAxis.label), Form("Events w. TT_{Ref} #in #varphi (%.2f, %.2f): scaled %s & #Delta#varphi & #it{p}_{T, jet}^{ch}", phiMin, phiMax, eaAxis.label), kTH3F, {{eaAxis.axis, eaAxis.axisName}, deltaPhiAngle, jetPTcorr}, hist.sumw2); - spectra.add(Form("hScaled%s_DPhi_JetPt_Corr_TTSig_RectrictedPhi_Part", eaAxis.label), + spectra.add(Form("hScaled%s_DPhi_JetPt_Corr_TTSig_RestrictedPhi_Part", eaAxis.label), Form("Events w. TT_{Sig} #in #varphi (%.2f, %.2f): scaled %s & #Delta#varphi & #it{p}_{T, jet}^{ch}", phiMin, phiMax, eaAxis.label), kTH3F, {{eaAxis.axis, eaAxis.axisName}, deltaPhiAngle, jetPTcorr}, hist.sumw2); } @@ -638,7 +650,7 @@ struct RecoilJets { } // Multiplicity for raw data and detector level MC - if (doprocessEventActivityOO || doprocessEventActivityMCDetLevelWeightedOO) { + if (doprocessEventActivity || doprocessEventActivityMCDetLevelWeighted) { //==================================================================================== // FIT data @@ -716,13 +728,13 @@ struct RecoilJets { } } - if (doprocessEventActivityQA) { - spectra.add("hEventSelectionCount", "Count # of events in the analysis", kTH1F, {{5, 0.0, 5.}}); - spectra.get(HIST("hEventSelectionCount"))->GetXaxis()->SetBinLabel(1, "sel8"); - spectra.get(HIST("hEventSelectionCount"))->GetXaxis()->SetBinLabel(2, "IsGoodZvtxFT0vsPV"); - spectra.get(HIST("hEventSelectionCount"))->GetXaxis()->SetBinLabel(3, "NoSameBunchPileup"); - spectra.get(HIST("hEventSelectionCount"))->GetXaxis()->SetBinLabel(4, "NoCollInTimeRangeStandard"); - spectra.get(HIST("hEventSelectionCount"))->GetXaxis()->SetBinLabel(5, "All flags"); + if (doprocessEventActivitySelectionQA) { + spectra.add("hEventSelectionCountQA", "Count # of events in the analysis", kTH1F, {{5, 0.0, 5.}}); + spectra.get(HIST("hEventSelectionCountQA"))->GetXaxis()->SetBinLabel(1, "sel8"); + spectra.get(HIST("hEventSelectionCountQA"))->GetXaxis()->SetBinLabel(2, "IsGoodZvtxFT0vsPV"); + spectra.get(HIST("hEventSelectionCountQA"))->GetXaxis()->SetBinLabel(3, "NoSameBunchPileup"); + spectra.get(HIST("hEventSelectionCountQA"))->GetXaxis()->SetBinLabel(4, "NoCollInTimeRangeStandard"); + spectra.get(HIST("hEventSelectionCountQA"))->GetXaxis()->SetBinLabel(5, "All flags"); //==================================================================================== // ZNA vs. ZNC correlation @@ -777,13 +789,13 @@ struct RecoilJets { spectra.add("hScaledFT0APerRunPerSetOfFlags", "Scaled FT0A signal per run per set of ev. sel. flags", kTH3F, {{scaledFT0A}, {nRunsOO, 0., nRunsOO * 1.}, {nEvSelFlags, 0., nEvSelFlags * 1.}}, hist.sumw2); - setBinLablesYZaxes(spectra.get(HIST("hScaledFT0APerRunPerSetOfFlags")), runNumbersOO, evSelFlags); + setBinLabelsYZAxes(spectra.get(HIST("hScaledFT0APerRunPerSetOfFlags")), runNumbersOO, evSelFlags); for (const auto& eaAxis : arrAxisSpecScaledEA) { auto tmpHistPointer = spectra.add(Form("hScaled%sPerRunPerSetOfFlags", eaAxis.label), Form("Scaled %s signal per run per set of ev. sel. flags", eaAxis.label), kTH3F, {{eaAxis.axis}, {nRunsOO, 0., nRunsOO * 1.}, {nEvSelFlags, 0., nEvSelFlags * 1.}}, hist.sumw2); - setBinLablesYZaxes(tmpHistPointer, runNumbersOO, evSelFlags); + setBinLabelsYZAxes(tmpHistPointer, runNumbersOO, evSelFlags); } // Unscaled FT0 signal; check whether mean value is the same for all runs @@ -791,7 +803,7 @@ struct RecoilJets { auto tmpHistPointer = spectra.add(Form("h%sPerRunPerSetOfFlags", eaAxis.label), Form("%s signal per run per set of ev. sel. flags", eaAxis.label), kTH3F, {{eaAxis.axis}, {nRunsOO, 0., nRunsOO * 1.}, {nEvSelFlags, 0., nEvSelFlags * 1.}}, hist.sumw2); - setBinLablesYZaxes(tmpHistPointer, runNumbersOO, evSelFlags); + setBinLabelsYZAxes(tmpHistPointer, runNumbersOO, evSelFlags); } // Check whether each BC has FT0 signal @@ -800,17 +812,17 @@ struct RecoilJets { spectra.get(HIST("hIsFT0SignalComeFromCollPerRun"))->GetXaxis()->SetBinLabel(2, "BC has not FT0"); spectra.get(HIST("hIsFT0SignalComeFromCollPerRun"))->GetXaxis()->SetBinLabel(3, "Coll. w. BC"); spectra.get(HIST("hIsFT0SignalComeFromCollPerRun"))->GetXaxis()->SetBinLabel(4, "Coll. w/o BC"); - setBinLablesYZaxes(spectra.get(HIST("hIsFT0SignalComeFromCollPerRun")), runNumbersOO, {}); + setBinLabelsYZAxes(spectra.get(HIST("hIsFT0SignalComeFromCollPerRun")), runNumbersOO, {}); // FT0 signal for the case when there is no associated BC spectra.add("hScaledFT0AsignalWithoutBC", "", kTH2F, {{scaledFT0A}, {nRunsOO, 0., nRunsOO * 1.}}); - setBinLablesYZaxes(spectra.get(HIST("hScaledFT0AsignalWithoutBC")), runNumbersOO, {}); + setBinLabelsYZAxes(spectra.get(HIST("hScaledFT0AsignalWithoutBC")), runNumbersOO, {}); for (const auto& eaAxis : arrAxisSpecScaledEA) { auto tmpHistPointer = spectra.add(Form("hScaled%ssignalWithoutBC", eaAxis.label), "", kTH2F, {{eaAxis.axis}, {nRunsOO, 0., nRunsOO * 1.}}); - setBinLablesYZaxes(tmpHistPointer, runNumbersOO, {}); + setBinLabelsYZAxes(tmpHistPointer, runNumbersOO, {}); } } @@ -882,8 +894,56 @@ struct RecoilJets { kTH2F, {{eaAxis.axis}, {400, -40., 60., "#delta#it{p}_{T} (GeV/#it{c})"}}, hist.sumw2); } } - spectra.add("hResponseLoopDet", "", kTH2F, {{100, 0., 100., "det. level"}, {100, 0., 100., "part. level"}}); - spectra.add("hResponseLoopPart", "", kTH2F, {{100, 0., 100., "det. level"}, {100, 0., 100., "part. level"}}); + + if (doprocessTTSmearingPtPhi || doprocessTTSmearingPtPhiWeighted) { + AxisSpec relPtSmearTT{120, -5., 1., "(#it{p}_{T, part} - #it{p}_{T, det}) / #it{p}_{T, part}"}; + AxisSpec smearPhi{80, -0.2, 0.2, "#it{#varphi}_{part} - #it{#varphi}_{det}"}; + AxisSpec smearEta{80, -0.2, 0.2, "#it{#eta}_{part} - #it{#eta}_{det}"}; + + int nBinsPtTTSig = static_cast(tt.sigPtRange->at(1) - tt.sigPtRange->at(0)) * 5; + int nBinsPtTTRef = static_cast(tt.refPtRange->at(1) - tt.refPtRange->at(0)) * 5; + AxisSpec partPtTTSig{nBinsPtTTSig, tt.sigPtRange->at(0), tt.sigPtRange->at(1), "#it{p}_{T, part}^{TT_{Sig}}"}; + AxisSpec partPtTTRef{nBinsPtTTRef, tt.refPtRange->at(0), tt.refPtRange->at(1), "#it{p}_{T, part}^{TT_{Ref}}"}; + + //==================================================================================== + // Signal TT + for (const auto& eaAxis : arrAxisSpecScaledEA) { + spectra.add(Form("hScaleMult%s_PtSmearingTTSig", eaAxis.label), + Form("#it{p}_{T} smearing of TT_{Sig} vs %s", eaAxis.label), + kTH3F, {{eaAxis.axis}, {relPtSmearTT}, {partPtTTSig}}, hist.sumw2); + + spectra.add(Form("hScaleMult%s_PhiSmearingTTSig", eaAxis.label), + Form("#it{#varphi} smearing of TT_{Sig} vs %s", eaAxis.label), + kTH3F, {{eaAxis.axis}, {smearPhi}, {partPtTTSig}}, hist.sumw2); + + spectra.add(Form("hScaleMult%s_EtaSmearingTTSig", eaAxis.label), + Form("#it{#eta} smearing of TT_{Sig} vs %s", eaAxis.label), + kTH3F, {{eaAxis.axis}, {smearEta}, {partPtTTSig}}, hist.sumw2); + + auto tmpHistPointer = spectra.add(Form("hScaled%s_FractionOfPartTTSigSatisfCond", eaAxis.label), + "Check associat. part. level also satisf. TT_{Sig} conditions", + kTH3F, {{eaAxis.axis}, {2, 0.0, 2.0}, {2, 0.0, 2.0}}); + tmpHistPointer->GetYaxis()->SetBinLabel(1, "#in |#it{#eta}| < 0.9"); + tmpHistPointer->GetYaxis()->SetBinLabel(2, "#notin |#it{#eta}| < 0.9"); + tmpHistPointer->GetZaxis()->SetBinLabel(1, "#it{p}_{T} #in TT_{Sig}"); + tmpHistPointer->GetZaxis()->SetBinLabel(2, "#it{p}_{T} #notin TT_{Sig}"); + } + + // Reference TT + for (const auto& eaAxis : arrAxisSpecScaledEA) { + spectra.add(Form("hScaleMult%s_PtSmearingTTRef", eaAxis.label), + Form("#it{p}_{T} smearing of TT_{Ref} vs %s", eaAxis.label), + kTH3F, {{eaAxis.axis}, {relPtSmearTT}, {partPtTTRef}}, hist.sumw2); + + spectra.add(Form("hScaleMult%s_PhiSmearingTTRef", eaAxis.label), + Form("#it{#varphi} smearing of TT_{Ref} vs %s", eaAxis.label), + kTH3F, {{eaAxis.axis}, {smearPhi}, {partPtTTRef}}, hist.sumw2); + + spectra.add(Form("hScaleMult%s_EtaSmearingTTRef", eaAxis.label), + Form("#it{#eta} smearing of TT_{Ref} vs %s", eaAxis.label), + kTH3F, {{eaAxis.axis}, {smearEta}, {partPtTTRef}}, hist.sumw2); + } + } } //============================================================================= @@ -902,8 +962,9 @@ struct RecoilJets { double phiTT = 0.; int nTT = 0; float rho = collision.rho(); - float scaledFT0C = getScaledFT0(collision.multFT0C(), ft0c.mean); - float scaledFT0M = getScaledFT0M(getScaledFT0(collision.multFT0A(), ft0a.mean), scaledFT0C); + const auto ft0Metrics = getFT0Metrics(collision, ft0a.mean, ft0c.mean); + const auto scaledFT0C = ft0Metrics.scaledFT0C; + const auto scaledFT0M = ft0Metrics.scaledFT0M; auto dice = randGen->Rndm(); if (dice < tt.fracSig) @@ -1000,8 +1061,8 @@ struct RecoilJets { spectra.fill(HIST("hJetArea_JetPt_Rho_TTSig"), jetArea, jetPt, rho, weight); if (phiTT > phiMin && phiTT < phiMax) { - spectra.fill(HIST("hScaledFT0C_DPhi_JetPt_Corr_TTSig_RectrictedPhi"), scaledFT0C, dphi, jetPtCorr, weight); - spectra.fill(HIST("hScaledFT0M_DPhi_JetPt_Corr_TTSig_RectrictedPhi"), scaledFT0M, dphi, jetPtCorr, weight); + spectra.fill(HIST("hScaledFT0C_DPhi_JetPt_Corr_TTSig_RestrictedPhi"), scaledFT0C, dphi, jetPtCorr, weight); + spectra.fill(HIST("hScaledFT0M_DPhi_JetPt_Corr_TTSig_RestrictedPhi"), scaledFT0M, dphi, jetPtCorr, weight); } if (bRecoilJet) { @@ -1020,8 +1081,8 @@ struct RecoilJets { spectra.fill(HIST("hJetArea_JetPt_Rho_TTRef"), jetArea, jetPt, rho, weight); if (phiTT > phiMin && phiTT < phiMax) { - spectra.fill(HIST("hScaledFT0C_DPhi_JetPt_Corr_TTRef_RectrictedPhi"), scaledFT0C, dphi, jetPtCorr, weight); - spectra.fill(HIST("hScaledFT0M_DPhi_JetPt_Corr_TTRef_RectrictedPhi"), scaledFT0M, dphi, jetPtCorr, weight); + spectra.fill(HIST("hScaledFT0C_DPhi_JetPt_Corr_TTRef_RestrictedPhi"), scaledFT0C, dphi, jetPtCorr, weight); + spectra.fill(HIST("hScaledFT0M_DPhi_JetPt_Corr_TTRef_RestrictedPhi"), scaledFT0M, dphi, jetPtCorr, weight); } if (bRecoilJet) { @@ -1047,8 +1108,9 @@ struct RecoilJets { double phiTT = 0.; int nTT = 0; float rho = collision.rho(); - float scaledFT0C = getScaledFT0(collision.multFT0C(), ft0c.meanPartLevel); - float scaledFT0M = getScaledFT0M(getScaledFT0(collision.multFT0A(), ft0a.meanPartLevel), scaledFT0C); + const auto ft0Metrics = getFT0Metrics(collision, ft0a.meanPartLevel, ft0c.meanPartLevel); + const auto scaledFT0C = ft0Metrics.scaledFT0C; + const auto scaledFT0M = ft0Metrics.scaledFT0M; auto dice = randGen->Rndm(); if (dice < tt.fracSig) @@ -1138,8 +1200,8 @@ struct RecoilJets { spectra.fill(HIST("hJetArea_JetPt_Rho_TTSig_Part"), jetArea, jetPt, rho, weight); if (phiTT > phiMin && phiTT < phiMax) { - spectra.fill(HIST("hScaledFT0C_DPhi_JetPt_Corr_TTSig_RectrictedPhi_Part"), scaledFT0C, dphi, jetPtCorr, weight); - spectra.fill(HIST("hScaledFT0M_DPhi_JetPt_Corr_TTSig_RectrictedPhi_Part"), scaledFT0M, dphi, jetPtCorr, weight); + spectra.fill(HIST("hScaledFT0C_DPhi_JetPt_Corr_TTSig_RestrictedPhi_Part"), scaledFT0C, dphi, jetPtCorr, weight); + spectra.fill(HIST("hScaledFT0M_DPhi_JetPt_Corr_TTSig_RestrictedPhi_Part"), scaledFT0M, dphi, jetPtCorr, weight); } if (bRecoilJet) { @@ -1161,8 +1223,8 @@ struct RecoilJets { spectra.fill(HIST("hJetArea_JetPt_Rho_TTRef_Part"), jetArea, jetPt, rho, weight); if (phiTT > phiMin && phiTT < phiMax) { - spectra.fill(HIST("hScaledFT0C_DPhi_JetPt_Corr_TTRef_RectrictedPhi_Part"), scaledFT0C, dphi, jetPtCorr, weight); - spectra.fill(HIST("hScaledFT0M_DPhi_JetPt_Corr_TTRef_RectrictedPhi_Part"), scaledFT0M, dphi, jetPtCorr, weight); + spectra.fill(HIST("hScaledFT0C_DPhi_JetPt_Corr_TTRef_RestrictedPhi_Part"), scaledFT0C, dphi, jetPtCorr, weight); + spectra.fill(HIST("hScaledFT0M_DPhi_JetPt_Corr_TTRef_RestrictedPhi_Part"), scaledFT0M, dphi, jetPtCorr, weight); } if (bRecoilJet) { @@ -1431,15 +1493,16 @@ struct RecoilJets { // Event Activity analysis //============================================================================= template - void fillMultiplicityHistogramsOO(JCollision const& collision, - float weight = 1.) + void fillMultiplicityHistograms(JCollision const& collision, + float weight = 1.) { - float multFT0A = collision.multFT0A(); - float multFT0C = collision.multFT0C(); - float multFT0M = collision.multFT0M(); - float scaledFT0A = getScaledFT0(multFT0A, ft0a.mean); - float scaledFT0C = getScaledFT0(multFT0C, ft0c.mean); - float scaledFT0M = getScaledFT0M(scaledFT0A, scaledFT0C); + const auto ft0Metrics = getFT0Metrics(collision, ft0a.mean, ft0c.mean); + const auto multFT0A = ft0Metrics.multFT0A; + const auto multFT0C = ft0Metrics.multFT0C; + const auto multFT0M = ft0Metrics.multFT0M; + const auto scaledFT0A = ft0Metrics.scaledFT0A; + const auto scaledFT0C = ft0Metrics.scaledFT0C; + const auto scaledFT0M = ft0Metrics.scaledFT0M; float multZNA = collision.multZNA(); float multZNC = collision.multZNC(); @@ -1490,36 +1553,36 @@ struct RecoilJets { void fillMultiplicityHistogramsMCPartLevel(JCollisionMC const& collision, float weight = 1.) { - spectra.fill(HIST("hMultFT0APartLevel"), collision.multFT0A(), weight); - spectra.fill(HIST("hMultFT0CPartLevel"), collision.multFT0C(), weight); - spectra.fill(HIST("hMultFT0MPartLevel"), collision.multFT0A() + collision.multFT0C(), weight); - - auto scaledFT0A = getScaledFT0(collision.multFT0A(), ft0a.meanPartLevel); - auto scaledFT0C = getScaledFT0(collision.multFT0C(), ft0c.meanPartLevel); - spectra.fill(HIST("hScaleMultFT0APartLevel"), scaledFT0A, weight); - spectra.fill(HIST("hScaleMultFT0CPartLevel"), scaledFT0C, weight); - spectra.fill(HIST("hScaleMultFT0MPartLevel"), getScaledFT0M(scaledFT0A, scaledFT0C), weight); + const auto ft0Metrics = getFT0Metrics(collision, ft0a.meanPartLevel, ft0c.meanPartLevel); + spectra.fill(HIST("hMultFT0APartLevel"), ft0Metrics.multFT0A, weight); + spectra.fill(HIST("hMultFT0CPartLevel"), ft0Metrics.multFT0C, weight); + spectra.fill(HIST("hMultFT0MPartLevel"), ft0Metrics.multFT0M, weight); + + spectra.fill(HIST("hScaleMultFT0APartLevel"), ft0Metrics.scaledFT0A, weight); + spectra.fill(HIST("hScaleMultFT0CPartLevel"), ft0Metrics.scaledFT0C, weight); + spectra.fill(HIST("hScaleMultFT0MPartLevel"), ft0Metrics.scaledFT0M, weight); } //============================================================================= - // Event Activity QA analysis in OO collisions (raw and MC detector level (no weight; MB events)) + // Event Activity QA analysis in raw OO data //============================================================================= template - void fillMultiplicityQA(Collision const& collision, - BC const&, - ZDC const&, - float weight = 1.) + void fillEventActivitySelectionQAHistograms(Collision const& collision, + BC const&, + ZDC const&, + float weight = 1.) { int runNumber = collision.multRunNumber(); int fillNumber = getBinNumberOnYaxisForGivenRun(spectra.get(HIST("hScaledFT0CPerRunPerSetOfFlags")), runNumber) - 0.5; // Same for FT0M distrib. // FT0 Signal - float multFT0A = collision.multFT0A(); - float multFT0C = collision.multFT0C(); - float multFT0M = collision.multFT0M(); - float scaledFT0A = getScaledFT0(multFT0A, ft0a.mean); - float scaledFT0C = getScaledFT0(multFT0C, ft0c.mean); - float scaledFT0M = getScaledFT0M(scaledFT0A, scaledFT0C); + const auto ft0Metrics = getFT0Metrics(collision, ft0a.mean, ft0c.mean); + const auto multFT0A = ft0Metrics.multFT0A; + const auto multFT0C = ft0Metrics.multFT0C; + const auto multFT0M = ft0Metrics.multFT0M; + const auto scaledFT0A = ft0Metrics.scaledFT0A; + const auto scaledFT0C = ft0Metrics.scaledFT0C; + const auto scaledFT0M = ft0Metrics.scaledFT0M; // Event with flag Sel8 spectra.fill(HIST("hFT0APerRunPerSetOfFlags"), multFT0A, fillNumber, 0.5, weight); @@ -1530,7 +1593,7 @@ struct RecoilJets { spectra.fill(HIST("hScaledFT0CPerRunPerSetOfFlags"), scaledFT0C, fillNumber, 0.5, weight); spectra.fill(HIST("hScaledFT0MPerRunPerSetOfFlags"), scaledFT0M, fillNumber, 0.5, weight); - spectra.fill(HIST("hEventSelectionCount"), 0.5); + spectra.fill(HIST("hEventSelectionCountQA"), 0.5); bool isGoodZvtxFT0vsPV = collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV); if (isGoodZvtxFT0vsPV) { @@ -1542,7 +1605,7 @@ struct RecoilJets { spectra.fill(HIST("hScaledFT0CPerRunPerSetOfFlags"), scaledFT0C, fillNumber, 1.5, weight); spectra.fill(HIST("hScaledFT0MPerRunPerSetOfFlags"), scaledFT0M, fillNumber, 1.5, weight); - spectra.fill(HIST("hEventSelectionCount"), 1.5); + spectra.fill(HIST("hEventSelectionCountQA"), 1.5); } bool isNoSameBunchPileup = collision.selection_bit(aod::evsel::kNoSameBunchPileup); @@ -1555,7 +1618,7 @@ struct RecoilJets { spectra.fill(HIST("hScaledFT0CPerRunPerSetOfFlags"), scaledFT0C, fillNumber, 2.5, weight); spectra.fill(HIST("hScaledFT0MPerRunPerSetOfFlags"), scaledFT0M, fillNumber, 2.5, weight); - spectra.fill(HIST("hEventSelectionCount"), 2.5); + spectra.fill(HIST("hEventSelectionCountQA"), 2.5); } bool isNoCollInTimeRangeStandard = collision.selection_bit(aod::evsel::kNoCollInTimeRangeStandard); @@ -1569,13 +1632,13 @@ struct RecoilJets { spectra.fill(HIST("hScaledFT0CPerRunPerSetOfFlags"), scaledFT0C, fillNumber, 3.5, weight); spectra.fill(HIST("hScaledFT0MPerRunPerSetOfFlags"), scaledFT0M, fillNumber, 3.5, weight); - spectra.fill(HIST("hEventSelectionCount"), 3.5); + spectra.fill(HIST("hEventSelectionCountQA"), 3.5); } - if (!(isGoodZvtxFT0vsPV && isNoSameBunchPileup & isNoCollInTimeRangeStandard)) + if (!(isGoodZvtxFT0vsPV && isNoSameBunchPileup && isNoCollInTimeRangeStandard)) return; - spectra.fill(HIST("hEventSelectionCount"), 4.5); // All accepted events after 4 flags cut + spectra.fill(HIST("hEventSelectionCountQA"), 4.5); // All accepted events after 4 flags cut spectra.fill(HIST("hFT0APerRunPerSetOfFlags"), multFT0A, fillNumber, 4.5, weight); spectra.fill(HIST("hFT0CPerRunPerSetOfFlags"), multFT0C, fillNumber, 4.5, weight); @@ -1589,12 +1652,13 @@ struct RecoilJets { // Investigate other EA variables // Multiplicity equalized for the vertex position with FT0 detector - float multZeqFT0A = collision.multZeqFT0A(); - float multZeqFT0C = collision.multZeqFT0C(); - float multZeqFT0M = multZeqFT0A + multZeqFT0C; - float scaledZeqFT0A = getScaledFT0(multZeqFT0A, ft0a.meanZeq); - float scaledZeqFT0C = getScaledFT0(multZeqFT0C, ft0c.meanZeq); - float scaledZeqFT0M = getScaledFT0M(scaledZeqFT0A, scaledZeqFT0C); + const auto zeqFT0Metrics = makeFT0Metrics(collision.multZeqFT0A(), collision.multZeqFT0C(), ft0a.meanZeq, ft0c.meanZeq); + const auto multZeqFT0A = zeqFT0Metrics.multFT0A; + const auto multZeqFT0C = zeqFT0Metrics.multFT0C; + const auto multZeqFT0M = zeqFT0Metrics.multFT0M; + const auto scaledZeqFT0A = zeqFT0Metrics.scaledFT0A; + const auto scaledZeqFT0C = zeqFT0Metrics.scaledFT0C; + const auto scaledZeqFT0M = zeqFT0Metrics.scaledFT0M; spectra.fill(HIST("hMultZeqFT0A"), multZeqFT0A, weight); spectra.fill(HIST("hMultZeqFT0C"), multZeqFT0C, weight); @@ -1626,7 +1690,7 @@ struct RecoilJets { spectra.fill(HIST("hScaledFT0C_TracksPV"), scaledFT0C, multNContribs, weight); spectra.fill(HIST("hScaledFT0M_TracksPV"), scaledFT0M, multNContribs, weight); - if (foundBC.foundFT0Id() > 0) // -1 if does not + if (foundBC.foundFT0Id() != -1) // -1 if does not { spectra.fill(HIST("hIsFT0SignalComeFromCollPerRun"), 0.5, fillNumber, weight); } else { @@ -1636,7 +1700,7 @@ struct RecoilJets { spectra.fill(HIST("hScaledFT0MsignalWithoutBC"), scaledFT0M, fillNumber, weight); } - if (collision.foundBCId() > 0) + if (collision.foundBCId() != -1) // -1 if does not spectra.fill(HIST("hIsFT0SignalComeFromCollPerRun"), 2.5, fillNumber, weight); else spectra.fill(HIST("hIsFT0SignalComeFromCollPerRun"), 3.5, fillNumber, weight); @@ -1652,8 +1716,9 @@ struct RecoilJets { std::vector vPtOfLeadingTracks; std::vector vPhiOfAssociatedTracks; - float scaledFT0C = getScaledFT0(collision.multFT0C(), ft0c.mean); - float scaledFT0M = getScaledFT0M(getScaledFT0(collision.multFT0A(), ft0a.mean), scaledFT0C); + const auto ft0Metrics = getFT0Metrics(collision, ft0a.mean, ft0c.mean); + const auto scaledFT0C = ft0Metrics.scaledFT0C; + const auto scaledFT0M = ft0Metrics.scaledFT0M; // Search for leading tracks for (const auto& track : tracks) { @@ -1709,8 +1774,9 @@ struct RecoilJets { { //---------------------------------------------------------- float rho = collision.rho(); - float scaledFT0C = getScaledFT0(collision.multFT0C(), ft0c.mean); - float scaledFT0M = getScaledFT0M(getScaledFT0(collision.multFT0A(), ft0a.mean), scaledFT0C); + const auto ft0Metrics = getFT0Metrics(collision, ft0a.mean, ft0c.mean); + const auto scaledFT0C = ft0Metrics.scaledFT0C; + const auto scaledFT0M = ft0Metrics.scaledFT0M; //---------------------------------------------------------- // Study bkgd fluctuations in events with TTsig @@ -1900,8 +1966,9 @@ struct RecoilJets { { //---------------------------------------------------------- float rho = collision.rho(); - float scaledFT0C = getScaledFT0(collision.multFT0C(), ft0c.meanPartLevel); - float scaledFT0M = getScaledFT0M(getScaledFT0(collision.multFT0A(), ft0a.meanPartLevel), scaledFT0C); + const auto ft0Metrics = getFT0Metrics(collision, ft0a.meanPartLevel, ft0c.meanPartLevel); + const auto scaledFT0C = ft0Metrics.scaledFT0C; + const auto scaledFT0M = ft0Metrics.scaledFT0M; //---------------------------------------------------------- // Study bkgd fluctuations in events with TTsig @@ -2083,6 +2150,128 @@ struct RecoilJets { } } + //============================================================================= + // Pt and Phi smearing of TT + //============================================================================= + template + void fillTTSmearingPtPhi(JColl const& collision, + JTracks const& tracks, + JParticles const&, + float weight = 1.) + { + const auto ft0Metrics = getFT0Metrics(collision, ft0a.mean, ft0c.mean); + const auto scaledFT0C = ft0Metrics.scaledFT0C; + const auto scaledFT0M = ft0Metrics.scaledFT0M; + + bool bSigEv = false; + auto dice = randGen->Rndm(); + if (dice < tt.fracSig) + bSigEv = true; + + float ptTTMin = 0.0, ptTTMax = 0.0; + if (bSigEv) { + ptTTMin = tt.sigPtRange->at(0); + ptTTMax = tt.sigPtRange->at(1); + } else { + ptTTMin = tt.refPtRange->at(0); + ptTTMax = tt.refPtRange->at(1); + } + + //============================================================================= + // Search for TT + int nCand = 0; + int32_t index = 0; + int32_t chosenTTPos = -1; + + for (const auto& track : tracks) { + if (skipTrack(track)) { + ++index; + continue; + } + + // Search for TT candidate + float trackPt = track.pt(); + if (trackPt > ptTTMin && trackPt < ptTTMax) { + + ++nCand; + // Random selection of TT + if (randGen->Integer(nCand) == 0) { + chosenTTPos = index; + } + } + ++index; + } + + // Skip if no TT + if (chosenTTPos < 0) + return; + + bool bHasAssocMcPart = tracks.iteratorAt(chosenTTPos).has_mcParticle(); + if (!bHasAssocMcPart) + return; + + // No filter on Particles, it can be outside of |eta| acceptance + auto particle = tracks.iteratorAt(chosenTTPos).mcParticle(); + float particleEta = particle.eta(); + bool bPartWithinEta = std::fabs(particleEta) < trk.etaCut; + + if (bSigEv) { + float particlePt = particle.pt(); + bool bPartWithinPtOfTT = (particlePt > ptTTMin) && (particlePt < ptTTMax); + + if (bPartWithinEta && bPartWithinPtOfTT) { + spectra.fill(HIST("hScaledFT0C_FractionOfPartTTSigSatisfCond"), scaledFT0C, 0.5, 0.5); + spectra.fill(HIST("hScaledFT0M_FractionOfPartTTSigSatisfCond"), scaledFT0M, 0.5, 0.5); + } + + if (!bPartWithinEta && bPartWithinPtOfTT) { + spectra.fill(HIST("hScaledFT0C_FractionOfPartTTSigSatisfCond"), scaledFT0C, 1.5, 0.5); + spectra.fill(HIST("hScaledFT0C_FractionOfPartTTSigSatisfCond"), scaledFT0M, 1.5, 0.5); + } + + if (bPartWithinEta && !bPartWithinPtOfTT) { + spectra.fill(HIST("hScaledFT0C_FractionOfPartTTSigSatisfCond"), scaledFT0C, 0.5, 1.5); + spectra.fill(HIST("hScaledFT0M_FractionOfPartTTSigSatisfCond"), scaledFT0M, 0.5, 1.5); + } + + if (!bPartWithinEta && !bPartWithinPtOfTT) { + spectra.fill(HIST("hScaledFT0C_FractionOfPartTTSigSatisfCond"), scaledFT0C, 1.5, 1.5); + spectra.fill(HIST("hScaledFT0M_FractionOfPartTTSigSatisfCond"), scaledFT0M, 1.5, 1.5); + } + } + if (!bPartWithinEta) + return; + + //============================================================================= + // Fill histograms + float particlePt = particle.pt(); + float particlePhi = particle.phi(); + + float relPtSmearing = (particlePt - tracks.iteratorAt(chosenTTPos).pt()) / particlePt; + float phiSmearing = particlePhi - tracks.iteratorAt(chosenTTPos).phi(); + float etaSmearing = particleEta - tracks.iteratorAt(chosenTTPos).eta(); + + if (bSigEv) { + spectra.fill(HIST("hScaleMultFT0C_PtSmearingTTSig"), scaledFT0C, relPtSmearing, particlePt, weight); + spectra.fill(HIST("hScaleMultFT0M_PtSmearingTTSig"), scaledFT0M, relPtSmearing, particlePt, weight); + + spectra.fill(HIST("hScaleMultFT0C_PhiSmearingTTSig"), scaledFT0C, phiSmearing, particlePt, weight); + spectra.fill(HIST("hScaleMultFT0M_PhiSmearingTTSig"), scaledFT0M, phiSmearing, particlePt, weight); + + spectra.fill(HIST("hScaleMultFT0C_EtaSmearingTTSig"), scaledFT0C, etaSmearing, particlePt, weight); + spectra.fill(HIST("hScaleMultFT0M_EtaSmearingTTSig"), scaledFT0M, etaSmearing, particlePt, weight); + } else { + spectra.fill(HIST("hScaleMultFT0C_PtSmearingTTRef"), scaledFT0C, relPtSmearing, particlePt, weight); + spectra.fill(HIST("hScaleMultFT0M_PtSmearingTTRef"), scaledFT0M, relPtSmearing, particlePt, weight); + + spectra.fill(HIST("hScaleMultFT0C_PhiSmearingTTRef"), scaledFT0C, phiSmearing, particlePt, weight); + spectra.fill(HIST("hScaleMultFT0M_PhiSmearingTTRef"), scaledFT0M, phiSmearing, particlePt, weight); + + spectra.fill(HIST("hScaleMultFT0C_EtaSmearingTTRef"), scaledFT0C, etaSmearing, particlePt, weight); + spectra.fill(HIST("hScaleMultFT0M_EtaSmearingTTRef"), scaledFT0M, etaSmearing, particlePt, weight); + } + } + //----------------------------------------------------------------------------- // Block of Process Functions @@ -2093,12 +2282,12 @@ struct RecoilJets { TrackTbl const& tracksPerColl, JetsDataTbl const& jetsPerColl) { - spectra.fill(HIST("hEventSelectionCount"), 0.5); + spectra.fill(HIST("hEventSelectionCountReco"), 0.5); if (skipEvent(collision)) return; - spectra.fill(HIST("hEventSelectionCount"), 1.5); // number of events selected for analysis + spectra.fill(HIST("hEventSelectionCountReco"), 1.5); // number of events selected for analysis fillHistograms(collision, jetsPerColl, tracksPerColl); } @@ -2109,13 +2298,13 @@ struct RecoilJets { TrackTbl const& tracksPerColl, JetsDetTbl const& jetsPerColl) { - spectra.fill(HIST("hEventSelectionCount"), 0.5); + spectra.fill(HIST("hEventSelectionCountReco"), 0.5); if (skipEvent(collision)) return; - spectra.fill(HIST("hEventSelectionCount"), 1.5); + spectra.fill(HIST("hEventSelectionCountReco"), 1.5); - spectra.fill(HIST("hEventSelectionCount"), 4.5); // number of events selected for analysis + spectra.fill(HIST("hEventSelectionCountReco"), 4.5); // number of events selected for analysis fillHistograms(collision, jetsPerColl, tracksPerColl); } PROCESS_SWITCH(RecoilJets, processMCDetLevel, "process MC det. level data (no weight; MB events)", false); @@ -2126,23 +2315,23 @@ struct RecoilJets { TrackTbl const& tracksPerColl, JetsDetTbl const& jetsPerColl) { - spectra.fill(HIST("hEventSelectionCount"), 0.5); + spectra.fill(HIST("hEventSelectionCountReco"), 0.5); if (skipEvent(collision)) return; - spectra.fill(HIST("hEventSelectionCount"), 1.5); + spectra.fill(HIST("hEventSelectionCountReco"), 1.5); if (collision.isOutlier()) { - spectra.fill(HIST("hEventSelectionCount"), 2.5); + spectra.fill(HIST("hEventSelectionCountReco"), 2.5); return; } if (!collision.has_mcCollision()) { - spectra.fill(HIST("hEventSelectionCount"), 3.5); + spectra.fill(HIST("hEventSelectionCountReco"), 3.5); return; } - spectra.fill(HIST("hEventSelectionCount"), 4.5); // number of events selected for analysis + spectra.fill(HIST("hEventSelectionCountReco"), 4.5); // number of events selected for analysis auto weight = collision.mcCollision().weight(); fillHistograms(collision, jetsPerColl, tracksPerColl, weight); } @@ -2194,7 +2383,7 @@ struct RecoilJets { // Construction of response matrix //============================================================================= void processJetsGeoMatching(CollRhoDetIt const& collision, - CollRhoPartTbl const& mcCollisions, + CollRhoPartTbl const&, TrackTbl const& tracksPerColl, MatchedJetsDetToPartTbl const& mcDetJetsPerColl, MatchedJetsPartToDetTbl const& mcPartJets) @@ -2205,7 +2394,9 @@ struct RecoilJets { auto mcCollisionId = collision.mcCollisionId(); auto detLevelCollRho = collision.rho(); - auto partLevelCollRho = mcCollisions.iteratorAt(mcCollisionId).rho(); + + auto mcColl = collision.mcCollision_as(); + auto partLevelCollRho = mcColl.rho(); // Slice for mc part level jets associated to a given mcCollisionId auto mcPartJetsPerMcCollision = mcPartJets.sliceBy(partJetsPerMcCollision, mcCollisionId); // signature: (__column to slice___, __index__) @@ -2216,7 +2407,7 @@ struct RecoilJets { //___________________________ void processJetsGeoPtMatching(CollRhoDetIt const& collision, - CollRhoPartTbl const& mcCollisions, + CollRhoPartTbl const&, TrackTbl const& tracksPerColl, MatchedJetsDetToPartTbl const& mcDetJetsPerColl, MatchedJetsPartToDetTbl const& mcPartJets) @@ -2227,7 +2418,9 @@ struct RecoilJets { auto mcCollisionId = collision.mcCollisionId(); auto detLevelCollRho = collision.rho(); - auto partLevelCollRho = mcCollisions.iteratorAt(mcCollisionId).rho(); + + auto mcColl = collision.mcCollision_as(); + auto partLevelCollRho = mcColl.rho(); // Slice for mc part level jets associated to a given mcCollisionId auto mcPartJetsPerMcCollision = mcPartJets.sliceBy(partJetsPerMcCollision, mcCollisionId); // signature: (__column to slice___, __index__) @@ -2238,7 +2431,7 @@ struct RecoilJets { //_________________________________ void processJetsGeoMatchingWeighted(CollRhoOutlierDetIt const& collision, - CollRhoOutlierPartTbl const& mcCollisions, + CollRhoOutlierPartTbl const&, TrackTbl const& tracksPerColl, MatchedJetsDetToPartTbl const& mcDetJetsPerColl, MatchedJetsPartToDetTbl const& mcPartJets) @@ -2249,8 +2442,10 @@ struct RecoilJets { auto mcCollisionId = collision.mcCollisionId(); auto detLevelCollRho = collision.rho(); - auto partLevelCollRho = mcCollisions.iteratorAt(mcCollisionId).rho(); - auto weight = mcCollisions.iteratorAt(mcCollisionId).weight(); + + auto mcColl = collision.mcCollision_as(); + auto partLevelCollRho = mcColl.rho(); + auto weight = mcColl.weight(); // Slice for mc part level jets associated to a given mcCollisionId auto mcPartJetsPerMcCollision = mcPartJets.sliceBy(partJetsPerMcCollision, mcCollisionId); // signature: (__column to slice___, __index__) @@ -2261,7 +2456,7 @@ struct RecoilJets { //___________________________________ void processJetsGeoPtMatchingWeighted(CollRhoOutlierDetIt const& collision, - CollRhoOutlierPartTbl const& mcCollisions, + CollRhoOutlierPartTbl const&, TrackTbl const& tracksPerColl, MatchedJetsDetToPartTbl const& mcDetJetsPerColl, MatchedJetsPartToDetTbl const& mcPartJets) @@ -2272,8 +2467,10 @@ struct RecoilJets { auto mcCollisionId = collision.mcCollisionId(); auto detLevelCollRho = collision.rho(); - auto partLevelCollRho = mcCollisions.iteratorAt(mcCollisionId).rho(); - auto weight = mcCollisions.iteratorAt(mcCollisionId).weight(); + + auto mcColl = collision.mcCollision_as(); + auto partLevelCollRho = mcColl.rho(); + auto weight = mcColl.weight(); // Slice for mc part level jets associated to a given mcCollisionId auto mcPartJetsPerMcCollision = mcPartJets.sliceBy(partJetsPerMcCollision, mcCollisionId); // signature: (__column to slice___, __index__) @@ -2283,28 +2480,28 @@ struct RecoilJets { PROCESS_SWITCH(RecoilJets, processJetsGeoPtMatchingWeighted, "process matching of MC jets using Geo+Pt criteria (weighted JJ)", false); //============================================================================= - // Event Activity analysis in OO collisions (raw and MC detector level (no weight; MB events)) + // Event Activity analysis in OO and pp collisions (raw and MC detector level (no weight; MB events)) //============================================================================= - void processEventActivityOO(EvMultZDCDataIt const& collision) + void processEventActivity(EvMultZDCDataIt const& collision) { if (skipEvent(collision)) return; - fillMultiplicityHistogramsOO(collision); + fillMultiplicityHistograms(collision); } - PROCESS_SWITCH(RecoilJets, processEventActivityOO, "process event activity in OO collisions and MC det. level (no weight; MB events)", false); + PROCESS_SWITCH(RecoilJets, processEventActivity, "process event activity in raw data and MC det. level (no weight; MB events)", false); - //___________________________________________ - void processEventActivityMCDetLevelWeightedOO(EvMultOutlierZDCDetIt const& collision, - aod::JetMcCollisions const&) + //_________________________________________ + void processEventActivityMCDetLevelWeighted(EvMultOutlierZDCDetIt const& collision, + aod::JetMcCollisions const&) { if (skipEvent(collision) || collision.isOutlier() || !collision.has_mcCollision()) return; auto weight = collision.mcCollision().weight(); - fillMultiplicityHistogramsOO(collision, weight); + fillMultiplicityHistograms(collision, weight); } - PROCESS_SWITCH(RecoilJets, processEventActivityMCDetLevelWeightedOO, "process event activity in MC det. level OO collisions (weighted JJ)", false); + PROCESS_SWITCH(RecoilJets, processEventActivityMCDetLevelWeighted, "process event activity in MC det. level events (weighted JJ)", false); //============================================================================= // Event Activity analysis in OO and pp collisions at Particle level @@ -2330,19 +2527,19 @@ struct RecoilJets { PROCESS_SWITCH(RecoilJets, processEventActivityMCPartLevelWeighted, "process event activity in MC part. level events (weighted JJ)", false); //============================================================================= - // Event Activity QA analysis in OO collisions (raw and MC detector level (no weight; MB events)) + // Event Activity QA analysis in raw OO //============================================================================= - void processEventActivityQA(CollEvSelExtendedIt const& collision, - BCsRun3Tbl const& BCs, - aod::Zdcs const& ZDCs) + void processEventActivitySelectionQA(CollEvSelExtendedIt const& collision, + BCsRun3Tbl const& BCs, + aod::Zdcs const& ZDCs) { // Base flag for event selection if (!collision.sel8()) return; - fillMultiplicityQA(collision, BCs, ZDCs); + fillEventActivitySelectionQAHistograms(collision, BCs, ZDCs); } - PROCESS_SWITCH(RecoilJets, processEventActivityQA, "process function for EA QA purposes in raw and MC det. level (no weight; MB events) data", false); + PROCESS_SWITCH(RecoilJets, processEventActivitySelectionQA, "process function for EA QA purposes in raw OO collisions", false); //============================================================================= // Di-hadron azimuthal correlation in raw and MC det. level (no weight; MB events) data @@ -2421,6 +2618,39 @@ struct RecoilJets { } PROCESS_SWITCH(RecoilJets, processBkgdFluctuationsMCPartLevelWeighted, "process MC part. level (weighted JJ) data to estimate bkgd fluctuations", false); + //============================================================================= + // Pt and Phi smearing of TT + //============================================================================= + void processTTSmearingPtPhi(CollDetIt const& collision, + aod::JetMcCollisions const&, + TrackMCLbsTbl const& tracksPerColl, + aod::JetParticles const& particles) + { + + // Skip detector level collisions + if (skipEvent(collision) || !collision.has_mcCollision()) + return; + + fillTTSmearingPtPhi(collision, tracksPerColl, particles); + } + PROCESS_SWITCH(RecoilJets, processTTSmearingPtPhi, "process MC data (no weight; MB events) to estimate pT and phi smearing of TT", false); + + //_________________________________ + void processTTSmearingPtPhiWeighted(CollOutlierDetIt const& collision, + aod::JetMcCollisions const&, + TrackMCLbsTbl const& tracksPerColl, + aod::JetParticles const& particles) + { + + // Skip detector level collisions + if (skipEvent(collision) || collision.isOutlier() || !collision.has_mcCollision()) + return; + + auto weight = collision.mcCollision().weight(); + fillTTSmearingPtPhi(collision, tracksPerColl, particles, weight); + } + PROCESS_SWITCH(RecoilJets, processTTSmearingPtPhiWeighted, "process MC data (weighted JJ) to estimate pT and phi smearing of TT", false); + //------------------------------------------------------------------------------ // Auxiliary functions template @@ -2466,8 +2696,34 @@ struct RecoilJets { return vPhiOfTT[iTrig]; } + FT0Metrics makeFT0Metrics(float multFT0A, + float multFT0C, + float meanFT0A, + float meanFT0C) + { + FT0Metrics values; + values.multFT0A = multFT0A; + values.multFT0C = multFT0C; + values.multFT0M = multFT0A + multFT0C; + values.scaledFT0A = getScaledFT0(values.multFT0A, meanFT0A); + values.scaledFT0C = getScaledFT0(values.multFT0C, meanFT0C); + values.scaledFT0M = getScaledFT0M(values.scaledFT0A, values.scaledFT0C); + return values; + } + + template + FT0Metrics getFT0Metrics(const Collision& collision, + float meanFT0A, + float meanFT0C) + { + return makeFT0Metrics(collision.multFT0A(), collision.multFT0C(), meanFT0A, meanFT0C); + } + float getScaledFT0(const float& multFT0, const float& meanFT0) { + if (meanFT0 == 0.f) { + LOGF(fatal, "FT0 mean is 0. This would cause division by zero. Use a non-zero mean (or keep -1 when scaling is not required)."); + } return multFT0 / meanFT0; } @@ -2540,7 +2796,7 @@ struct RecoilJets { } template - void setBinLablesYZaxes(const std::shared_ptr& histPointer, + void setBinLabelsYZAxes(const std::shared_ptr& histPointer, const std::vector& yAxis, const std::vector& zAxis) { From 746981b94e7e3d2c822f7aba063fc3c68461061a Mon Sep 17 00:00:00 2001 From: sangwoo <141385263+sangwoo184@users.noreply.github.com> Date: Mon, 23 Feb 2026 16:22:09 +0900 Subject: [PATCH 030/347] [PWGLF] Fix QAhistogram dimension (#15110) --- PWGLF/Tasks/Resonances/f0980pbpbanalysis.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PWGLF/Tasks/Resonances/f0980pbpbanalysis.cxx b/PWGLF/Tasks/Resonances/f0980pbpbanalysis.cxx index 4844c3c0374..5c2884459a0 100644 --- a/PWGLF/Tasks/Resonances/f0980pbpbanalysis.cxx +++ b/PWGLF/Tasks/Resonances/f0980pbpbanalysis.cxx @@ -328,8 +328,8 @@ struct F0980pbpbanalysis { histos.fill(HIST("TrackQA/TPCChi2_BC"), centrality, obj.tpcChi2NCl()); histos.fill(HIST("TrackQA/ITSChi2_BC"), centrality, obj.itsChi2NCl()); } else { - histos.fill(HIST("TrackQA/DCArToPv_AC"), centrality, obj.dcaXY()); - histos.fill(HIST("TrackQA/DCAzToPv_AC"), centrality, obj.dcaZ()); + histos.fill(HIST("TrackQA/DCArToPv_AC"), obj.pt(), centrality, obj.dcaXY()); + histos.fill(HIST("TrackQA/DCAzToPv_AC"), obj.pt(), centrality, obj.dcaZ()); histos.fill(HIST("TrackQA/IsPrim_AC"), centrality, obj.isPrimaryTrack()); histos.fill(HIST("TrackQA/IsGood_AC"), centrality, obj.isGlobalTrackWoDCA()); histos.fill(HIST("TrackQA/IsPrimCont_AC"), centrality, obj.isPVContributor()); From 1406d6b72c3ca41c5cddca72e7d4e934d3c4d048 Mon Sep 17 00:00:00 2001 From: JimunLee Date: Mon, 23 Feb 2026 16:22:22 +0900 Subject: [PATCH 031/347] [PWGLF] Fixed the nEvents of processMCJets of KstarInOO.cxx (#15111) Co-authored-by: jimun_lee --- PWGLF/Tasks/Resonances/kstarInOO.cxx | 29 +++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/PWGLF/Tasks/Resonances/kstarInOO.cxx b/PWGLF/Tasks/Resonances/kstarInOO.cxx index a5aa4753276..d295aa655eb 100644 --- a/PWGLF/Tasks/Resonances/kstarInOO.cxx +++ b/PWGLF/Tasks/Resonances/kstarInOO.cxx @@ -222,7 +222,11 @@ struct kstarInOO { histos.add("QA_track_pT_AC", "QA_track_pT_AC", kTH1F, {{13, 0.0, 13.0}}); } if (cfgJetQAHistos) { - histos.add("nTriggerQA", "nTriggerQA", kTH1F, {{7, 0.0, 7.0}}); + histos.add("nTriggerQA", "nTriggerQA", kTH1F, {{8, 0.0, 8.0}}); + histos.add("nTriggerQA_GoodEv", "nTriggerQA_GoodEv", kTH1F, {{8, 0.0, 8.0}}); + histos.add("nTriggerQA_GoodTrig", "nTriggerQA_GoodTrig", kTH1F, {{8, 0.0, 8.0}}); + histos.add("nTriggerQA_GoodEvTrig", "nTriggerQA_GoodEvTrig", kTH1F, {{8, 0.0, 8.0}}); + histos.add("JetpT", "Jet pT (GeV/c)", kTH1F, {{4000, 0., 200.}}); histos.add("JetEta", "Jet Eta", kTH1F, {{100, -1.0, 1.0}}); histos.add("JetPhi", "Jet Phi", kTH1F, {{80, -1.0, 7.0}}); @@ -1149,12 +1153,10 @@ struct kstarInOO { if (!jetderiveddatautilities::selectTrigger(collision, RealTriggerMaskBits)) return; - - histos.fill(HIST("nEvents"), 1.5); // Before passing the condition - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { return; } + histos.fill(HIST("nEvents"), 1.5); // Before passing the condition bool INELgt0 = false; for (auto& jetTrack : jetTracks) { @@ -1571,13 +1573,22 @@ struct kstarInOO { // check K* PID if (goodEv) { histos.fill(HIST("hGen_pT_GoodEv"), particle.pt()); - } + + } // goodEv + if (goodTrig) { histos.fill(HIST("hGen_pT_GoodTrig"), particle.pt()); - } + + } // goodTrig + if (goodEv && goodTrig) { histos.fill(HIST("hGen_pT_GoodEvTrig"), particle.pt()); - } + + if (cfgJetQAHistos) { + histos.fill(HIST("nTriggerQA"), 7.5); + } + + } // goodEvTrig } // cfgJetMCHistos } // mcParticles } // recocolls (=reconstructed collisions) @@ -1585,8 +1596,8 @@ struct kstarInOO { //================= //|| Efficiency //================= - if (fabs(collision.posZ()) > cfgEventVtxCut) - return; + // if (fabs(collision.posZ()) > cfgEventVtxCut) + // return; for (auto& recocoll : recocolls) { // poorly reconstructed auto goodEv = jetderiveddatautilities::selectCollision(recocoll, eventSelectionBits); From 400dfe3726845baca9a15a8e41cfb97825185956 Mon Sep 17 00:00:00 2001 From: Giorgio Alberto Lucia <87222843+GiorgioAlbertoLucia@users.noreply.github.com> Date: Mon, 23 Feb 2026 09:27:45 +0100 Subject: [PATCH 032/347] [PWGLF] added extended table and fixed downscaling (#15055) --- PWGLF/DataModel/LFSlimNucleiTables.h | 8 +++ PWGLF/TableProducer/QC/nucleiQC.cxx | 94 +++++++++++++++++++++++----- PWGLF/Utils/nucleiUtils.h | 3 + 3 files changed, 91 insertions(+), 14 deletions(-) diff --git a/PWGLF/DataModel/LFSlimNucleiTables.h b/PWGLF/DataModel/LFSlimNucleiTables.h index e266bed5001..b35355873f7 100644 --- a/PWGLF/DataModel/LFSlimNucleiTables.h +++ b/PWGLF/DataModel/LFSlimNucleiTables.h @@ -56,6 +56,9 @@ DECLARE_SOA_COLUMN(MotherDecRad, motherDecRad, float); DECLARE_SOA_COLUMN(AbsoDecL, absoDecL, float); DECLARE_SOA_COLUMN(McProcess, mcProcess, uint64_t); +DECLARE_SOA_COLUMN(NsigmaTpc, nsigmaTpc, uint8_t); +DECLARE_SOA_COLUMN(NsigmaTof, nsigmaTof, uint8_t); + } // namespace NucleiTableNS namespace NucleiPairTableNS @@ -203,6 +206,11 @@ DECLARE_SOA_TABLE(NucleiTableRed, "AOD", "NUCLEITABLERED", NucleiTableNS::PDGcode, NucleiTableNS::MotherPDGcode); +// Extended table with central PID information +DECLARE_SOA_TABLE(NucleiTableExt, "AOD", "NUCLEITABLEEXT", + NucleiTableNS::NsigmaTpc, + NucleiTableNS::NsigmaTof); + } // namespace o2::aod #endif // PWGLF_DATAMODEL_LFSLIMNUCLEITABLES_H_ diff --git a/PWGLF/TableProducer/QC/nucleiQC.cxx b/PWGLF/TableProducer/QC/nucleiQC.cxx index 04dc6750c8c..a6597d45137 100644 --- a/PWGLF/TableProducer/QC/nucleiQC.cxx +++ b/PWGLF/TableProducer/QC/nucleiQC.cxx @@ -64,11 +64,32 @@ using namespace o2; using namespace o2::framework; +namespace +{ + +enum trackQuality { + kNoCuts = 0, + kEtaCut = 1, + kPtpcCut = 2, + kNclsItsCut = 3, + kNclsTpcCut = 4, + kNCrossedRowsCut = 5, + kTpcChi2Cut = 6, + kItsChi2Cut = 7, + kNtrackQuality = 8 +}; + +std::array trackQualityLabels{"All", "#eta cut", "#it{p}_{TPC}^{min} cut", "#it{N}_{cls}^{ITS} cut", "#it{N}_{cls}^{TPC} cut", "Crossed rows cut", "#chi^{2}_{TPC} cut", "#chi^{2}_{ITS} cut"}; + +} // namespace + struct nucleiQC { using TrackCandidates = soa::Join; using TrackCandidatesMC = soa::Join; using Collision = soa::Join::iterator; + using Collisions = soa::Join; + Preslice mTracksPerCollision = aod::track::collisionId; Preslice mMcParticlesPerCollision = o2::aod::mcparticle::mcCollisionId; Configurable cfgFillTable{"cfgFillTable", true, "Fill output tree"}; @@ -77,6 +98,9 @@ struct nucleiQC { Configurable> cfgSpeciesToProcess{"cfgSpeciesToProcess", {nuclei::speciesToProcessDefault[0], nuclei::Species::kNspecies, 1, nuclei::names, {"processNucleus"}}, "Nuclei to process"}; Configurable> cfgEventSelections{"cfgEventSelections", {nuclei::EvSelDefault[0], 8, 1, nuclei::eventSelectionLabels, nuclei::eventSelectionTitle}, "Event selections"}; Configurable cfgCentralityEstimator{"cfgCentralityEstimator", 0, "Centrality estimator (FV0A: 0, FT0M: 1, FT0A: 2, FT0C: 3)"}; + Configurable cfgPerformPidSelectionInIts{"cfgPerformPidSelectionInIts", false, "Perform PID selections in ITS"}; + Configurable cfgPerformPidSelectionInTpc{"cfgPerformPidSelectionInTpc", false, "Perform PID selections in TPC"}; + Configurable cfgPerformPidSelectionInTof{"cfgPerformPidSelectionInTof", false, "Perform PID selections in TOF"}; Configurable> cfgBetheBlochParams{"cfgBetheBlochParams", {nuclei::betheBlochDefault[0], nuclei::Species::kNspecies, 6, nuclei::names, nuclei::betheBlochParNames}, "TPC Bethe-Bloch parameterisation for light nuclei"}; Configurable> cfgUseCentralTpcCalibration{"cfgUseCentralTpcCalibration", {nuclei::useCentralTpcCalibrationDefault[0], nuclei::Species::kNspecies, 1, nuclei::names, {"UseCentralTpcCalibration"}}, "Use central TPC calibration"}; Configurable> cfgDownscalingFactor{"cfgDownscalingFactor", {nuclei::DownscalingDefault[0], nuclei::Species::kNspecies, 1, nuclei::names, {"DownscalingFactor"}}, "Save to the AO2D with a downscaling factor"}; @@ -95,6 +119,9 @@ struct nucleiQC { Configurable cfgCutTpcMom{"cfgCutTpcMom", 0.2f, "Minimum TPC momentum for tracks"}; Configurable cfgCutNclusITS{"cfgCutNclusITS", 5, "Minimum number of ITS clusters"}; Configurable cfgCutNclusTPC{"cfgCutNclusTPC", 70, "Minimum number of TPC clusters"}; + Configurable cfgCutNclusCrossedRowsTPC{"cfgCutNclusCrossedRowsTPC", 70, "Minimum number of TPC clusters crossed rows"}; + Configurable cfgCutChi2PerClusterTPC{"cfgCutChi2PerClusterTPC", 4.f, "Maximum chi2 per TPC cluster"}; + Configurable cfgCutChi2PerClusterITS{"cfgCutChi2PerClusterITS", 36.f, "Maximum chi2 per ITS cluster"}; Configurable> cfgNsigmaTPC{"cfgNsigmaTPC", {nuclei::nSigmaTPCdefault[0], nuclei::Species::kNspecies, 2, nuclei::names, nuclei::nSigmaConfigName}, "TPC nsigma selection for light nuclei"}; Configurable> cfgNsigmaTOF{"cfgNsigmaTOF", {nuclei::nSigmaTOFdefault[0], nuclei::Species::kNspecies, 2, nuclei::names, nuclei::nSigmaConfigName}, "TPC nsigma selection for light nuclei"}; @@ -123,6 +150,7 @@ struct nucleiQC { std::vector mSpeciesToProcess; Produces mNucleiTableRed; + Produces mNucleiTableExt; std::vector mNucleiCandidates; std::vector mFilledMcParticleIds; @@ -166,6 +194,10 @@ struct nucleiQC { } nuclei::createHistogramRegistryNucleus(mHistograms); + mHistograms.add(fmt::format("{}/hTrackQuality", nuclei::cNames[kSpeciesRt]).c_str(), (fmt::format("{} track quality;", nuclei::cNames[kSpeciesRt]) + std::string("#it{p}_{T} / #it{Z} (GeV/#it{c}); Selection step; Counts")).c_str(), o2::framework::HistType::kTH2D, {{400, -10.0f, 10.0f}, {trackQuality::kNtrackQuality, -0.5f, static_cast(trackQuality::kNtrackQuality) - 0.5f}}); + for (size_t iSel = 0; iSel < trackQuality::kNtrackQuality; iSel++) { + mHistograms.get(HIST(nuclei::cNames[kSpeciesRt]) + HIST("/hTrackQuality"))->GetYaxis()->SetBinLabel(iSel + 1, trackQualityLabels[iSel].c_str()); + } if (cfgUseCentralTpcCalibration->get(static_cast(kSpeciesRt), static_cast(0)) == 0) { mPidManagers[kSpeciesRt] = nuclei::PidManager(kSpeciesRt, tpcBetheBlochParams); @@ -217,19 +249,39 @@ struct nucleiQC { LOGF(info, "Retrieved GRP for timestamp %ull (%i) with magnetic field of %1.2f kZG", timestamp, mRunNumber, mBz); } - template + template bool trackSelection(const Ttrack& track) { - if (std::abs(track.eta()) > cfgCutEta || - track.tpcInnerParam() < cfgCutTpcMom || - track.itsNCls() < cfgCutNclusITS || - track.tpcNClsFound() < cfgCutNclusTPC || - track.tpcNClsCrossedRows() < 70 || - track.tpcNClsCrossedRows() < 0.8 * track.tpcNClsFindable() || - track.tpcChi2NCl() > 4.f || - track.itsChi2NCl() > 36.f) { + mHistograms.fill(HIST(nuclei::cNames[iSpecies]) + HIST("/hTrackQuality"), track.sign() * track.pt(), trackQuality::kNoCuts); + + if (std::abs(track.eta()) > cfgCutEta) return false; - } + mHistograms.fill(HIST(nuclei::cNames[iSpecies]) + HIST("/hTrackQuality"), track.sign() * track.pt(), trackQuality::kEtaCut); + + if (track.tpcInnerParam() < cfgCutTpcMom) + return false; + mHistograms.fill(HIST(nuclei::cNames[iSpecies]) + HIST("/hTrackQuality"), track.sign() * track.pt(), trackQuality::kPtpcCut); + + if (track.itsNCls() < cfgCutNclusITS) + return false; + mHistograms.fill(HIST(nuclei::cNames[iSpecies]) + HIST("/hTrackQuality"), track.sign() * track.pt(), trackQuality::kNclsItsCut); + + if (track.tpcNClsFound() < cfgCutNclusTPC) + return false; + mHistograms.fill(HIST(nuclei::cNames[iSpecies]) + HIST("/hTrackQuality"), track.sign() * track.pt(), trackQuality::kNclsTpcCut); + + if (track.tpcNClsCrossedRows() < cfgCutNclusCrossedRowsTPC) + return false; + mHistograms.fill(HIST(nuclei::cNames[iSpecies]) + HIST("/hTrackQuality"), track.sign() * track.pt(), trackQuality::kNCrossedRowsCut); + + if (track.tpcChi2NCl() > cfgCutChi2PerClusterTPC) + return false; + mHistograms.fill(HIST(nuclei::cNames[iSpecies]) + HIST("/hTrackQuality"), track.sign() * track.pt(), trackQuality::kTpcChi2Cut); + + if (track.itsChi2NCl() > cfgCutChi2PerClusterITS) + return false; + mHistograms.fill(HIST(nuclei::cNames[iSpecies]) + HIST("/hTrackQuality"), track.sign() * track.pt(), trackQuality::kItsChi2Cut); + return true; } @@ -243,7 +295,7 @@ struct nucleiQC { float centrality = nuclei::getCentrality(collision, cfgCentralityEstimator); float nsigmaTPC = mPidManagers[kIndex].getNSigmaTPC(track); mHistograms.fill(HIST(nuclei::cNames[kIndex]) + HIST("/h3NsigmaTPC_preselectionVsCentrality"), track.pt() * track.sign(), nsigmaTPC, centrality); - if (std::abs(nsigmaTPC) > cfgNsigmaTPC->get(kIndex, 1)) + if (std::abs(nsigmaTPC) > cfgNsigmaTPC->get(kIndex, 1) && cfgPerformPidSelectionInTpc) return false; mHistograms.fill(HIST(nuclei::cNames[kIndex]) + HIST("/h3NsigmaTPCVsCentrality"), track.pt() * track.sign(), nsigmaTPC, centrality); @@ -254,7 +306,7 @@ struct nucleiQC { float nsigmaTOF = mPidManagers[kIndex].getNSigmaTOF(track); mHistograms.fill(HIST(nuclei::cNames[kIndex]) + HIST("/h3NsigmaTOF_preselectionVsCentrality"), track.sign() * track.pt(), nsigmaTOF, centrality); - if (std::abs(nsigmaTOF) > cfgNsigmaTOF->get(kIndex, 1) && track.hasTOF()) + if (std::abs(nsigmaTOF) > cfgNsigmaTOF->get(kIndex, 1) && track.hasTOF() && cfgPerformPidSelectionInTof) return false; mHistograms.fill(HIST(nuclei::cNames[kIndex]) + HIST("/h3NsigmaTOFVsCentrality"), track.sign() * track.pt(), nsigmaTOF, centrality); @@ -390,7 +442,9 @@ struct nucleiQC { .yGenerated = 0.f, .phiGenerated = 0.f, .centrality = nuclei::getCentrality(collision, cfgCentralityEstimator, mHistFailCentrality), - .mcProcess = TMCProcess::kPNoProcess}; + .mcProcess = TMCProcess::kPNoProcess, + .nsigmaTpc = mPidManagers[iSpecies].getNSigmaTPC(track), + .nsigmaTof = mPidManagers[iSpecies].getNSigmaTOF(track)}; fillNucleusFlagsPdgs(iSpecies, collision, track, candidate); @@ -456,6 +510,7 @@ struct nucleiQC { void processMc(const Collision& collision, const TrackCandidatesMC& tracks, const aod::BCsWithTimestamps&, const aod::McParticles& mcParticles) { + gRandom->SetSeed(67); mNucleiCandidates.clear(); mFilledMcParticleIds.clear(); @@ -480,6 +535,9 @@ struct nucleiQC { mTrackTuner.getDcaGraphs(); } + auto tracksThisCollision = tracks.sliceBy(mTracksPerCollision, collision.globalIndex()); + tracksThisCollision.bindExternalIndices(&tracks); + for (const auto& track : tracks) { static_for<0, nuclei::kNspecies - 1>([&](auto iSpecies) { @@ -510,7 +568,7 @@ struct nucleiQC { return; mHistograms.fill(HIST(nuclei::cNames[kSpeciesCt]) + HIST("/hTrackSelections"), nuclei::trackSelection::kNoCuts); - if (!trackSelection(track)) + if (!trackSelection(track)) return; mHistograms.fill(HIST(nuclei::cNames[kSpeciesCt]) + HIST("/hTrackSelections"), nuclei::trackSelection::kTrackCuts); @@ -547,6 +605,11 @@ struct nucleiQC { if (std::find(mSpeciesToProcess.begin(), mSpeciesToProcess.end(), iSpecies) == mSpeciesToProcess.end()) continue; + if (cfgDownscalingFactor->get(iSpecies) < 1.) { + if ((gRandom->Uniform()) > cfgDownscalingFactor->get(iSpecies)) + return; + } + nuclei::SlimCandidate candidate; candidate.centrality = nuclei::getCentrality(collision, cfgCentralityEstimator, mHistFailCentrality); fillNucleusFlagsPdgsMc(particle, candidate); @@ -576,6 +639,9 @@ struct nucleiQC { candidate.mcProcess, candidate.pdgCode, candidate.motherPdgCode); + mNucleiTableExt( + candidate.nsigmaTpc, + candidate.nsigmaTof); } } PROCESS_SWITCH(nucleiQC, processMc, "Mc analysis", false); diff --git a/PWGLF/Utils/nucleiUtils.h b/PWGLF/Utils/nucleiUtils.h index 193daaeeaca..e322db1b024 100644 --- a/PWGLF/Utils/nucleiUtils.h +++ b/PWGLF/Utils/nucleiUtils.h @@ -27,6 +27,7 @@ #include "TMCProcess.h" #include +#include #include #include @@ -102,6 +103,8 @@ struct SlimCandidate { float phiGenerated = -999.f; float centrality = -1.f; uint64_t mcProcess = TMCProcess::kPNoProcess; + float nsigmaTpc = -999.f; + float nsigmaTof = -999.f; }; enum Species { From dab549bb4867936a43de0af03fe11a12ae78939e Mon Sep 17 00:00:00 2001 From: alicja-pp <101565842+alicja-pp@users.noreply.github.com> Date: Mon, 23 Feb 2026 09:59:47 +0100 Subject: [PATCH 033/347] [PWGCF] FemtoUniverse V0 task: Refactor separate mass cut for lambdas and antilambdas (#15046) --- .../femtoUniversePairTaskTrackV0Extended.cxx | 115 ++++-------------- 1 file changed, 25 insertions(+), 90 deletions(-) diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx index 9cfe12d2fe6..bcc85d0acc2 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx @@ -117,7 +117,7 @@ struct FemtoUniversePairTaskTrackV0Extended { Configurable confHPtChildPion{"confHPtChildPion", 10.0f, "Higher limit for pt of children pions"}; Configurable confLPtChildPion{"confLPtChildPion", 0.f, "Lower limit for pt of children pions"}; Configurable confV0DuplCosPA{"confV0DuplCosPA", false, "Use cosPA instead of inv. mass as a deciding factor in rejecting a V0 in V0V0 pairs"}; - Configurable confAddInvMassCheck{"confAddInvMassCheck", false, "Apply additional cut separate for mLambda and mAntiLambda"}; + Configurable confSeparateInvMassCheck{"confSeparateInvMassCheck", false, "Apply additional cut separate for mLambda and mAntiLambda"}; } ConfV0Selection; /// Partition for particle 2 using extended table @@ -210,10 +210,17 @@ struct FemtoUniversePairTaskTrackV0Extended { } } - bool invMLambda(float invMassLambda, float invMassAntiLambda) + bool invMLambda(float invMassLambda, float invMassAntiLambda, int V0Type) { - if ((invMassLambda < ConfV0Selection.confV0InvMassLowLimit || invMassLambda > ConfV0Selection.confV0InvMassUpLimit) && (invMassAntiLambda < ConfV0Selection.confV0InvMassLowLimit || invMassAntiLambda > ConfV0Selection.confV0InvMassUpLimit)) { - return false; + if (ConfV0Selection.confSeparateInvMassCheck) { + const float pMass = V0Type ? invMassAntiLambda : invMassLambda; + if (pMass < ConfV0Selection.confV0InvMassLowLimit || pMass > ConfV0Selection.confV0InvMassUpLimit) { + return false; + } + } else { + if ((invMassLambda < ConfV0Selection.confV0InvMassLowLimit || invMassLambda > ConfV0Selection.confV0InvMassUpLimit) && (invMassAntiLambda < ConfV0Selection.confV0InvMassLowLimit || invMassAntiLambda > ConfV0Selection.confV0InvMassUpLimit)) { + return false; + } } return true; } @@ -417,7 +424,7 @@ struct FemtoUniversePairTaskTrackV0Extended { /// Histogramming same event for (const auto& part : groupPartsTwo) { - if (!invMLambda(part.mLambda(), part.mAntiLambda())) + if (!invMLambda(part.mLambda(), part.mAntiLambda(), ConfV0Selection.confV0Type1)) continue; const auto& posChild = parts.iteratorAt(part.globalIndex() - 2 - parts.begin().globalIndex()); const auto& negChild = parts.iteratorAt(part.globalIndex() - 1 - parts.begin().globalIndex()); @@ -426,13 +433,6 @@ struct FemtoUniversePairTaskTrackV0Extended { continue; } - if (ConfV0Selection.confAddInvMassCheck) { - const float pMass = ConfV0Selection.confV0Type1 ? part.mAntiLambda() : part.mLambda(); - if (pMass < ConfV0Selection.confV0InvMassLowLimit || pMass > ConfV0Selection.confV0InvMassUpLimit) { - continue; - } - } - /// Daughters that do not pass this condition are not selected if constexpr (std::experimental::is_detected::value) { if (!isParticleTPC(posChild, V0ChildTable[ConfV0Selection.confV0Type1][0]) || !isParticleTPC(negChild, V0ChildTable[ConfV0Selection.confV0Type1][1])) @@ -492,7 +492,7 @@ struct FemtoUniversePairTaskTrackV0Extended { /// Now build the combinations for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { // Lambda invariant mass cut - if (!invMLambda(p2.mLambda(), p2.mAntiLambda())) + if (!invMLambda(p2.mLambda(), p2.mAntiLambda(), ConfV0Selection.confV0Type1)) continue; /// PID using stored binned nsigma if constexpr (std::experimental::is_detected::value) { @@ -534,13 +534,6 @@ struct FemtoUniversePairTaskTrackV0Extended { } } - if (ConfV0Selection.confAddInvMassCheck) { - const float pMass = ConfV0Selection.confV0Type1 ? p2.mAntiLambda() : p2.mLambda(); - if (pMass < ConfV0Selection.confV0InvMassLowLimit || pMass > ConfV0Selection.confV0InvMassUpLimit) { - continue; - } - } - if (ConfCPR.confIsCPR.value) { if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla, femto_universe_container::EventType::same)) { continue; @@ -571,7 +564,7 @@ struct FemtoUniversePairTaskTrackV0Extended { /// Histogramming same event for first V0 particle for (const auto& part : groupPartsTwo) { - if (!invMLambda(part.mLambda(), part.mAntiLambda())) + if (!invMLambda(part.mLambda(), part.mAntiLambda(), ConfV0Selection.confV0Type1)) continue; const auto& posChild = parts.iteratorAt(part.globalIndex() - 2 - parts.begin().globalIndex()); const auto& negChild = parts.iteratorAt(part.globalIndex() - 1 - parts.begin().globalIndex()); @@ -586,12 +579,6 @@ struct FemtoUniversePairTaskTrackV0Extended { if (!isParticleTOF(posChild, V0ChildTable[ConfV0Selection.confV0Type1][0]) || !isParticleTOF(negChild, V0ChildTable[ConfV0Selection.confV0Type1][1])) continue; - if (ConfV0Selection.confAddInvMassCheck) { - const float pMass = ConfV0Selection.confV0Type1 ? part.mAntiLambda() : part.mLambda(); - if (pMass < ConfV0Selection.confV0InvMassLowLimit || pMass > ConfV0Selection.confV0InvMassUpLimit) { - continue; - } - } trackHistoV0Type1.fillQABase(part, HIST("V0Type1")); posChildV0Type1.fillQABase(posChild, HIST("posChildV0Type1")); negChildV0Type1.fillQABase(negChild, HIST("negChildV0Type1")); @@ -618,7 +605,7 @@ struct FemtoUniversePairTaskTrackV0Extended { /// Histogramming same event for second V0 particle for (const auto& part : groupPartsTwo) { - if (!invMLambda(part.mLambda(), part.mAntiLambda())) + if (!invMLambda(part.mLambda(), part.mAntiLambda(), ConfV0Selection.confV0Type2)) continue; const auto& posChild = parts.iteratorAt(part.globalIndex() - 2 - parts.begin().globalIndex()); const auto& negChild = parts.iteratorAt(part.globalIndex() - 1 - parts.begin().globalIndex()); @@ -633,12 +620,6 @@ struct FemtoUniversePairTaskTrackV0Extended { if (!isParticleTOF(posChild, V0ChildTable[ConfV0Selection.confV0Type2][0]) || !isParticleTOF(negChild, V0ChildTable[ConfV0Selection.confV0Type2][1])) continue; - if (ConfV0Selection.confAddInvMassCheck) { - const float pMass = ConfV0Selection.confV0Type2 ? part.mAntiLambda() : part.mLambda(); - if (pMass < ConfV0Selection.confV0InvMassLowLimit || pMass > ConfV0Selection.confV0InvMassUpLimit) { - continue; - } - } trackHistoV0Type2.fillQABase(part, HIST("V0Type2")); posChildV0Type2.fillQABase(posChild, HIST("posChildV0Type2")); negChildV0Type2.fillQABase(negChild, HIST("negChildV0Type2")); @@ -665,20 +646,12 @@ struct FemtoUniversePairTaskTrackV0Extended { auto pairDuplicateCheckFunc = [&](auto& p1, auto& p2) -> void { // V0 inv mass cut for p1 - if (!invMLambda(p1.mLambda(), p1.mAntiLambda())) + if (!invMLambda(p1.mLambda(), p1.mAntiLambda(), ConfV0Selection.confV0Type1)) return; // V0 inv mass cut for p2 - if (!invMLambda(p2.mLambda(), p2.mAntiLambda())) + if (!invMLambda(p2.mLambda(), p2.mAntiLambda(), ConfV0Selection.confV0Type2)) return; - if (ConfV0Selection.confAddInvMassCheck) { - const float p1Mass = ConfV0Selection.confV0Type1 ? p1.mAntiLambda() : p1.mLambda(); - const float p2Mass = ConfV0Selection.confV0Type2 ? p2.mAntiLambda() : p2.mLambda(); - if (p1Mass < ConfV0Selection.confV0InvMassLowLimit || p1Mass > ConfV0Selection.confV0InvMassUpLimit || p2Mass < ConfV0Selection.confV0InvMassLowLimit || p2Mass > ConfV0Selection.confV0InvMassUpLimit) { - return; - } - } - // track cleaning & checking for duplicate pairs if (!pairCleanerV0.isCleanPair(p1, p2, parts)) { // mark for rejection the cascade that shares a daughter with another cascade and has an invariant mass further from default value @@ -702,10 +675,10 @@ struct FemtoUniversePairTaskTrackV0Extended { if (v0Duplicates.contains(p1.globalIndex()) || v0Duplicates.contains(p2.globalIndex())) return false; // Lambda invariant mass cut for p1 - if (!invMLambda(p1.mLambda(), p1.mAntiLambda())) + if (!invMLambda(p1.mLambda(), p1.mAntiLambda(), ConfV0Selection.confV0Type1)) return false; // Lambda invariant mass cut for p2 - if (!invMLambda(p2.mLambda(), p2.mAntiLambda())) + if (!invMLambda(p2.mLambda(), p2.mAntiLambda(), ConfV0Selection.confV0Type2)) return false; const auto& posChild1 = parts.iteratorAt(p1.globalIndex() - 2 - parts.begin().globalIndex()); @@ -756,14 +729,6 @@ struct FemtoUniversePairTaskTrackV0Extended { } } - if (ConfV0Selection.confAddInvMassCheck) { - const float p1Mass = ConfV0Selection.confV0Type1 ? p1.mAntiLambda() : p1.mLambda(); - const float p2Mass = ConfV0Selection.confV0Type2 ? p2.mAntiLambda() : p2.mLambda(); - if (p1Mass < ConfV0Selection.confV0InvMassLowLimit || p1Mass > ConfV0Selection.confV0InvMassUpLimit || p2Mass < ConfV0Selection.confV0InvMassLowLimit || p2Mass > ConfV0Selection.confV0InvMassUpLimit) { - return false; - } - } - if (ConfCPR.confIsCPR.value) { if (ConfCPR.confRectV0V0CPR && pairCloseRejectionV0.isClosePair(p1, p2, parts, magFieldTesla, femto_universe_container::EventType::same)) { return false; @@ -984,7 +949,7 @@ struct FemtoUniversePairTaskTrackV0Extended { for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { // Lambda invariant mass cut - if (!invMLambda(p2.mLambda(), p2.mAntiLambda())) + if (!invMLambda(p2.mLambda(), p2.mAntiLambda(), ConfV0Selection.confV0Type1)) continue; /// PID using stored binned nsigma if constexpr (std::experimental::is_detected::value) { @@ -1019,13 +984,6 @@ struct FemtoUniversePairTaskTrackV0Extended { } } - if (ConfV0Selection.confAddInvMassCheck) { - const float pMass = ConfV0Selection.confV0Type1 ? p2.mAntiLambda() : p2.mLambda(); - if (pMass < ConfV0Selection.confV0InvMassLowLimit || pMass > ConfV0Selection.confV0InvMassUpLimit) { - continue; - } - } - // track cleaning if (!pairCleaner.isCleanPair(p1, p2, parts)) { continue; @@ -1084,11 +1042,11 @@ struct FemtoUniversePairTaskTrackV0Extended { for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { // Lambda invariant mass cut for p1 - if (!invMLambda(p1.mLambda(), p1.mAntiLambda())) { + if (!invMLambda(p1.mLambda(), p1.mAntiLambda(), ConfV0Selection.confV0Type1)) { continue; } // Lambda invariant mass cut for p2 - if (!invMLambda(p2.mLambda(), p2.mAntiLambda())) { + if (!invMLambda(p2.mLambda(), p2.mAntiLambda(), ConfV0Selection.confV0Type2)) { continue; } @@ -1141,14 +1099,6 @@ struct FemtoUniversePairTaskTrackV0Extended { } } - if (ConfV0Selection.confAddInvMassCheck) { - const float p1Mass = ConfV0Selection.confV0Type1 ? p1.mAntiLambda() : p1.mLambda(); - const float p2Mass = ConfV0Selection.confV0Type2 ? p2.mAntiLambda() : p2.mLambda(); - if (p1Mass < ConfV0Selection.confV0InvMassLowLimit || p1Mass > ConfV0Selection.confV0InvMassUpLimit || p2Mass < ConfV0Selection.confV0InvMassLowLimit || p2Mass > ConfV0Selection.confV0InvMassUpLimit) { - continue; - } - } - // track cleaning if (!pairCleanerV0.isCleanPair(p1, p2, parts)) { continue; @@ -1375,7 +1325,7 @@ struct FemtoUniversePairTaskTrackV0Extended { for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { // Lambda invariant mass cut - if (!invMLambda(p2.mLambda(), p2.mAntiLambda())) + if (!invMLambda(p2.mLambda(), p2.mAntiLambda(), ConfV0Selection.confV0Type1)) continue; /// PID using stored binned nsigma if (!isParticleCombined(p1, ConfTrkSelection.confTrackChoicePartOne)) @@ -1393,13 +1343,6 @@ struct FemtoUniversePairTaskTrackV0Extended { if (!isParticleTOF(posChild, V0ChildTable[ConfV0Selection.confV0Type1][0]) || !isParticleTOF(negChild, V0ChildTable[ConfV0Selection.confV0Type1][1])) continue; - if (ConfV0Selection.confAddInvMassCheck) { - const float pMass = ConfV0Selection.confV0Type1 ? p2.mAntiLambda() : p2.mLambda(); - if (pMass < ConfV0Selection.confV0InvMassLowLimit || pMass > ConfV0Selection.confV0InvMassUpLimit) { - continue; - } - } - // track cleaning if (!pairCleaner.isCleanPair(p1, p2, parts)) { continue; @@ -1452,11 +1395,11 @@ struct FemtoUniversePairTaskTrackV0Extended { for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { // Lambda invariant mass cut for p1 - if (!invMLambda(p1.mLambda(), p1.mAntiLambda())) { + if (!invMLambda(p1.mLambda(), p1.mAntiLambda(), ConfV0Selection.confV0Type1)) { continue; } // Lambda invariant mass cut for p2 - if (!invMLambda(p2.mLambda(), p2.mAntiLambda())) { + if (!invMLambda(p2.mLambda(), p2.mAntiLambda(), ConfV0Selection.confV0Type2)) { continue; } @@ -1484,14 +1427,6 @@ struct FemtoUniversePairTaskTrackV0Extended { if (!isParticleTOF(negChild2, V0ChildTable[ConfV0Selection.confV0Type1][0]) || !isParticleTOF(negChild2, V0ChildTable[ConfV0Selection.confV0Type1][1])) continue; - if (ConfV0Selection.confAddInvMassCheck) { - const float p1Mass = ConfV0Selection.confV0Type1 ? p1.mAntiLambda() : p1.mLambda(); - const float p2Mass = ConfV0Selection.confV0Type2 ? p2.mAntiLambda() : p2.mLambda(); - if (p1Mass < ConfV0Selection.confV0InvMassLowLimit || p1Mass > ConfV0Selection.confV0InvMassUpLimit || p2Mass < ConfV0Selection.confV0InvMassLowLimit || p2Mass > ConfV0Selection.confV0InvMassUpLimit) { - continue; - } - } - // track cleaning if (!pairCleanerV0.isCleanPair(p1, p2, parts)) { continue; From 5b868a95cbaeb11a0c464c310c35bfe8ae22555a Mon Sep 17 00:00:00 2001 From: Lucia Anna Tarasovicova Date: Mon, 23 Feb 2026 10:09:31 +0100 Subject: [PATCH 034/347] [ALICE3] Update of the alice3TrackingTranslator.cxx (#15071) Co-authored-by: Lucia Anna Tarasovicova Co-authored-by: ALICE Action Bot --- ALICE3/Core/ALICE3CoreLinkDef.h | 2 + ALICE3/DataModel/tracksAlice3.h | 15 + ALICE3/TableProducer/CMakeLists.txt | 4 +- .../alice3TrackingTranslator.cxx | 300 ++++++++++++------ 4 files changed, 220 insertions(+), 101 deletions(-) diff --git a/ALICE3/Core/ALICE3CoreLinkDef.h b/ALICE3/Core/ALICE3CoreLinkDef.h index 05d2a78fc00..076c21f8a79 100644 --- a/ALICE3/Core/ALICE3CoreLinkDef.h +++ b/ALICE3/Core/ALICE3CoreLinkDef.h @@ -14,3 +14,5 @@ #pragma link off all functions; #pragma link C++ class o2::pid::tof::TOFResoALICE3 + ; +#pragma link C++ class std::vector < std::vector < unsigned int>> + ; +#pragma link C++ class std::vector < std::vector < std::uint32_t>> + ; diff --git a/ALICE3/DataModel/tracksAlice3.h b/ALICE3/DataModel/tracksAlice3.h index 280c5ccb110..6e03e5e68ba 100644 --- a/ALICE3/DataModel/tracksAlice3.h +++ b/ALICE3/DataModel/tracksAlice3.h @@ -21,6 +21,7 @@ // O2 includes #include "Framework/AnalysisDataModel.h" +#include namespace o2::aod { @@ -29,16 +30,30 @@ namespace track_alice3 DECLARE_SOA_COLUMN(IsReconstructed, isReconstructed, bool); //! is reconstructed or not DECLARE_SOA_COLUMN(NSiliconHits, nSiliconHits, int); //! number of silicon hits DECLARE_SOA_COLUMN(NTPCHits, nTPCHits, int); //! number of tpc hits +DECLARE_SOA_COLUMN(PdgCode, pdgCode, int); //! PDG code of the linked truth MC particle } // namespace track_alice3 DECLARE_SOA_TABLE(TracksAlice3, "AOD", "TRACKSALICE3", track_alice3::IsReconstructed); using TrackAlice3 = TracksAlice3::iterator; +DECLARE_SOA_TABLE(TracksAlice3Pdg, "AOD", "TRACKSALICE3PDG", + track_alice3::PdgCode); +using TrackAlice3Pdg = TracksAlice3Pdg::iterator; + DECLARE_SOA_TABLE(TracksExtraA3, "AOD", "TracksExtraA3", track_alice3::NSiliconHits, track_alice3::NTPCHits); using TrackExtraA3 = TracksExtraA3::iterator; +namespace mcparticle_alice3 +{ +DECLARE_SOA_COLUMN(NHits, nHits, int); //! number of silicon hits +DECLARE_SOA_COLUMN(Charge, charge, float); //! particle charge +} // namespace mcparticle_alice3 +DECLARE_SOA_TABLE(MCParticlesExtraA3, "AOD", "MCParticlesExtraA3", + mcparticle_alice3::NHits, + mcparticle_alice3::Charge); +using MCParticleExtraA3 = MCParticlesExtraA3::iterator; } // namespace o2::aod #endif // ALICE3_DATAMODEL_TRACKSALICE3_H_ diff --git a/ALICE3/TableProducer/CMakeLists.txt b/ALICE3/TableProducer/CMakeLists.txt index 280a15f59ce..233088b6d5e 100644 --- a/ALICE3/TableProducer/CMakeLists.txt +++ b/ALICE3/TableProducer/CMakeLists.txt @@ -58,7 +58,7 @@ o2physics_add_dpl_workflow(alice3-hf-tree-creator-3prong o2physics_add_dpl_workflow(alice3-tracking-translator SOURCES alice3TrackingTranslator.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::ALICE3Core COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(alice3-dq-table-maker @@ -68,5 +68,5 @@ o2physics_add_dpl_workflow(alice3-dq-table-maker o2physics_add_dpl_workflow(alice3strangenessfinder SOURCES alice3strangenessFinder.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::ALICE3Core COMPONENT_NAME Analysis) diff --git a/ALICE3/TableProducer/alice3TrackingTranslator.cxx b/ALICE3/TableProducer/alice3TrackingTranslator.cxx index 5fc4728de98..706d5cba462 100644 --- a/ALICE3/TableProducer/alice3TrackingTranslator.cxx +++ b/ALICE3/TableProducer/alice3TrackingTranslator.cxx @@ -42,11 +42,6 @@ #include #include -#ifdef __CLING__ -#pragma link C++ class std::vector < std::vector < unsigned int>> + ; -#pragma link C++ class std::vector < std::vector < std::uint32_t>> + ; -#endif - TString inputPath; struct Alice3TrackingTranslator { @@ -61,7 +56,9 @@ struct Alice3TrackingTranslator { o2::framework::Produces tableTracksDCACov; o2::framework::Produces tableCollisionsAlice3; o2::framework::Produces tableTracksAlice3; + o2::framework::Produces tableTracksAlice3Pdg; o2::framework::Produces tableTracksExtraA3; + o2::framework::Produces tableMCParticlesExtraA3; o2::framework::Produces tableStoredTracksExtra; o2::framework::Produces tableTrackSelection; @@ -71,13 +68,12 @@ struct Alice3TrackingTranslator { o2::framework::Produces tableOTFLUTConfigId; o2::framework::Configurable maxCollisions{"maxCollisions", -1000, "Maximum number of collisions translated"}; + o2::framework::Configurable addDaughterInfo{"addDaughterInfo", false, "Add daughter particle information to the MC truth output tables"}; void init(o2::framework::InitContext&) { // Initialization if needed LOG(info) << "Alice3TrackingTranslator init called"; - // Load dictionary for nested vector - gInterpreter->GenerateDictionary("vector>", "vector"); } #define SETADDRESS(branchname, branchvar) \ @@ -123,6 +119,12 @@ struct Alice3TrackingTranslator { SETADDRESS("pz", m_pz); SETADDRESS("m", m_m); SETADDRESS("p", m_p); + SETADDRESS("q", m_q); + SETADDRESS("number_of_hits", m_number_of_hits); + SETADDRESS("particle_id", m_particleId); + if (mTree->GetBranchStatus("mother_particle_id")) { + SETADDRESS("mother_particle_id", m_motherId); + } } std::vector* m_particle_type = nullptr; std::vector* m_vx = nullptr; @@ -134,6 +136,10 @@ struct Alice3TrackingTranslator { std::vector* m_pz = nullptr; std::vector* m_m = nullptr; std::vector* m_p = nullptr; + std::vector* m_number_of_hits = nullptr; + std::vector* m_particleId = nullptr; + std::vector* m_q = nullptr; + std::vector* m_motherId = nullptr; }; struct TrackStruct : public FileStruct { @@ -155,8 +161,8 @@ struct Alice3TrackingTranslator { SETADDRESS("eQOP_fit", m_eQOP_fit); SETADDRESS("eT_fit", m_eT_fit); SETADDRESS("nMajorityHits", m_nMajorityHits); - // SETADDRESS("majorityParticleId", m_majorityParticleId); - mTree->SetBranchAddress("majorityParticleId", &m_majorityParticleId); + SETADDRESS("majorityParticleId", m_majorityParticleId); + // mTree->SetBranchAddress("majorityParticleId", &m_majorityParticleId); SETADDRESS("t_charge", m_t_charge); SETADDRESS("t_vx", m_t_vx); SETADDRESS("t_vy", m_t_vy); @@ -187,20 +193,20 @@ struct Alice3TrackingTranslator { std::vector* m_eT_fit = nullptr; // time // The majority truth particle info - std::vector* m_nMajorityHits = nullptr; /// The number of hits from majority particle - std::vector>* m_majorityParticleId = nullptr; /// The particle Id of the majority particle - std::vector* m_t_charge = nullptr; /// Charge of majority particle - std::vector* m_t_time = nullptr; /// Time of majority particle - std::vector* m_t_vx = nullptr; /// Vertex x positions of majority particle - std::vector* m_t_vy = nullptr; /// Vertex y positions of majority particle - std::vector* m_t_vz = nullptr; /// Vertex z positions of majority particle - std::vector* m_t_px = nullptr; /// Initial momenta m_px of majority particle - std::vector* m_t_py = nullptr; /// Initial momenta m_py of majority particle - std::vector* m_t_pz = nullptr; /// Initial momenta m_pz of majority particle - std::vector* m_t_theta = nullptr; /// Initial momenta theta of majority particle - std::vector* m_t_phi = nullptr; /// Initial momenta phi of majority particle - std::vector* m_t_pT = nullptr; /// Initial momenta pT of majority particle - std::vector* m_t_eta = nullptr; /// Initial momenta eta of majority particle + std::vector* m_nMajorityHits = nullptr; /// The number of hits from majority particle + std::vector* m_majorityParticleId = nullptr; /// The particle Id of the majority particle + std::vector* m_t_charge = nullptr; /// Charge of majority particle + std::vector* m_t_time = nullptr; /// Time of majority particle + std::vector* m_t_vx = nullptr; /// Vertex x positions of majority particle + std::vector* m_t_vy = nullptr; /// Vertex y positions of majority particle + std::vector* m_t_vz = nullptr; /// Vertex z positions of majority particle + std::vector* m_t_px = nullptr; /// Initial momenta m_px of majority particle + std::vector* m_t_py = nullptr; /// Initial momenta m_py of majority particle + std::vector* m_t_pz = nullptr; /// Initial momenta m_pz of majority particle + std::vector* m_t_theta = nullptr; /// Initial momenta theta of majority particle + std::vector* m_t_phi = nullptr; /// Initial momenta phi of majority particle + std::vector* m_t_pT = nullptr; /// Initial momenta pT of majority particle + std::vector* m_t_eta = nullptr; /// Initial momenta eta of majority particle std::vector* m_majorityParticlePDG = nullptr; // IA }; @@ -213,6 +219,28 @@ struct Alice3TrackingTranslator { } std::vector* barcode = nullptr; }; + void addMCParticle(int collIndex, ParticleStruct& fileParticles, int iParticle, uint8_t flags, int firstMother, int firstDaughter, int numberOfHits) + { + int mothers[2] = {firstMother, -1}; + int daughters[2] = {firstDaughter, -1}; + tableStoredMcParticles(collIndex, // mcCollisionId + fileParticles.m_particle_type->at(iParticle), // pdgCode + 0, // statusCode + flags, // flags + mothers, // mothersIds + daughters, // daughtersIdSlice + 1.0f, // weight + fileParticles.m_px->at(iParticle), // m_px + fileParticles.m_py->at(iParticle), // m_py + fileParticles.m_pz->at(iParticle), // m_pz + std::hypot(fileParticles.m_p->at(iParticle), fileParticles.m_m->at(iParticle)), // e + fileParticles.m_vx->at(iParticle), // m_vx + fileParticles.m_vy->at(iParticle), // m_vy + fileParticles.m_vz->at(iParticle), // m_vz + fileParticles.m_vt->at(iParticle)); // m_vt + tableMCParticlesExtraA3(numberOfHits, // number_of_hits + fileParticles.m_q->at(iParticle)); // charge + }; void process(o2::aod::BCs const&) { @@ -248,23 +276,34 @@ struct Alice3TrackingTranslator { LOG(info) << "Processing file: " << justFilename.Data(); files[justFilename.Data()] = filename; } - + LOG(info) << "All files loaded successfully"; // Now open the files to translate and read the trees - ParticleStruct fileParticles(files["particles_simulation.root"], "particles"); + ParticleStruct fileParticles(files["particles.root"], "particles"); + LOG(info) << "Particles loaded successfully"; + ParticleStruct fileParticlesSim(files["particles_simulation.root"], "particles"); + LOG(info) << "Particles Sim loaded successfully"; + std::string daughterFileName = addDaughterInfo ? "particles_decay.root" : "particles_simulation.root"; + ParticleStruct fileDaughterParticles(files[daughterFileName], "particles"); + LOG(info) << "Daughter particles loaded successfully from file " << daughterFileName; // FileStruct fileVertices(files["performance_vertexing.root"], "vertexing"); TrackStruct fileTracksummary(files["tracksummary_ambi.root"], "tracksummary"); // HitsStruct fileHits(files["hits.root"], "hits"); + LOG(info) << "Tracks loaded successfully"; const Long64_t kEvents = fileParticles.getEntries(); + int indexOfLastParticleAfterEvent = -1; for (Long64_t iEvent = 0; iEvent < kEvents; ++iEvent) { if (iEvent > 0 && maxCollisions.value > 0 && (iEvent % maxCollisions) == 0) { - LOG(info) << "Processing event " << iEvent << "/" << kEvents; + LOG(info) << "Stopping at event " << iEvent << "/" << kEvents; break; } fileParticles.setEventEntry(iEvent); // fileVertices.setEventEntry(iEvent); fileTracksummary.setEventEntry(iEvent); // fileHits.setEventEntry(iEvent); + if (addDaughterInfo) + fileDaughterParticles.setEventEntry(iEvent); + fileParticlesSim.setEventEntry(iEvent); LOG(info) << "Processing event " << iEvent << "/" << kEvents; @@ -275,6 +314,12 @@ struct Alice3TrackingTranslator { float collisionZ = 0.0f; tableOTFLUTConfigId(0); // dummy for the moment + + // Determine the collision ID for the new entry. + // If the table is empty, lastIndex() returns -1, so we start at 0. + // If it has entries, lastIndex() returns the index of the last element, so we use lastIndex() + 1. + int collisionId = tableCollisions.lastIndex() + 1; + tableCollisions(0, // bcId collisionX, // posX collisionY, // posY @@ -296,10 +341,6 @@ struct Alice3TrackingTranslator { tableCollisionsAlice3(0.f); // multDensity - // Fill MC particles - int mothers[2] = {-1, -1}; - int daughters[2] = {-1, -1}; - struct addedParticle { float px; float py; @@ -308,51 +349,92 @@ struct Alice3TrackingTranslator { float vy; float vz; }; - std::map> addedParticles; // Convert tracks from ACTS to ALICE format const size_t nParticlesGen = fileParticles.m_vx->size(); - const size_t nParticles = fileTracksummary.m_t_vx->size(); + const size_t nParticlesSim = fileParticlesSim.m_vx->size(); + const size_t nDaughterParticles = fileDaughterParticles.m_vx->size(); const size_t nTracks = fileTracksummary.m_eLOC0_fit->size(); + std::vector idMCparticles; + for (size_t iTrack = 0; iTrack < nTracks; ++iTrack) { - LOG(info) << "Processing track " << iTrack << "/" << nTracks << " (nParticles=" << nParticles << ") nParticlesGen=" << nParticlesGen; + LOG(info) << "Processing track " << iTrack << "/" << nTracks << " (nParticlesSim=" << nParticlesSim << ") nParticlesGen=" << nParticlesGen; const size_t iParticle = iTrack; + if (iParticle == 0) { - tableMcCollisions(0, // mccollision::BCId, - 0, // mccollision::GeneratorsID, - fileTracksummary.m_t_vx->at(iParticle), // mccollision::PosX, - fileTracksummary.m_t_vy->at(iParticle), // mccollision::PosY, - fileTracksummary.m_t_vz->at(iParticle), // mccollision::PosZ - fileTracksummary.m_t_time->at(iParticle), // mccollision::T - 1.0f, // mccollision::Weight - 0.0f, // mccollision::ImpactParameter, - 0.f); // mccollision::EventPlaneAngle, + tableMcCollisions(0, // mccollision::BCId, + 0, // mccollision::GeneratorsID, + fileParticles.m_vx->at(iParticle), // mccollision::PosX, + fileParticles.m_vy->at(iParticle), // mccollision::PosY, + fileParticles.m_vz->at(iParticle), // mccollision::PosZ + fileParticles.m_vt->at(iParticle), // mccollision::T + 1.0f, // mccollision::Weight + 0.0f, // mccollision::ImpactParameter, + 0.f); // mccollision::EventPlaneAngle, } uint8_t flags = 0; - flags |= o2::aod::mcparticle::enums::PhysicalPrimary; - - addedParticles[fileTracksummary.m_majorityParticlePDG->at(iParticle)].push_back({fileTracksummary.m_t_px->at(iParticle), - fileTracksummary.m_t_py->at(iParticle), - fileTracksummary.m_t_pz->at(iParticle), - fileTracksummary.m_t_vx->at(iParticle), - fileTracksummary.m_t_vy->at(iParticle), - fileTracksummary.m_t_vz->at(iParticle)}); - - tableStoredMcParticles(tableMcCollisions.lastIndex(), // mcCollisionId - fileTracksummary.m_majorityParticlePDG->at(iParticle), // pdgCode - 0, // statusCode - flags, // flags - mothers, // mothersIds - daughters, // daughtersIdSlice - 1.0f, // weight - fileTracksummary.m_t_px->at(iParticle), // m_px - fileTracksummary.m_t_py->at(iParticle), // m_py - fileTracksummary.m_t_pz->at(iParticle), // m_pz - 0, // e - fileTracksummary.m_t_vx->at(iParticle), // m_vx - fileTracksummary.m_t_vy->at(iParticle), // m_vy - fileTracksummary.m_t_vz->at(iParticle), // m_vz - fileTracksummary.m_t_time->at(iParticle)); // m_vt + ULong64_t idMCTrueParticle = fileTracksummary.m_majorityParticleId->at(iParticle); + int32_t mcParticleId = -1; + int pdgCode = -1; + + for (size_t iMC = 0; iMC < nParticlesGen; ++iMC) { + if (fileParticles.m_particleId->at(iMC) == idMCTrueParticle) { + if (count(idMCparticles.begin(), idMCparticles.end(), fileParticles.m_particleId->at(iMC)) > 0) { + continue; + } + idMCparticles.push_back(fileParticles.m_particleId->at(iMC)); + flags |= o2::aod::mcparticle::enums::PhysicalPrimary; + int nHits = 0; + for (size_t iPartSim = 0; iPartSim < nParticlesSim; ++iPartSim) { + if (fileParticlesSim.m_particleId->at(iPartSim) == fileParticles.m_particleId->at(iMC)) { + nHits = fileParticlesSim.m_number_of_hits->at(iPartSim); + break; + } + } + addMCParticle(tableMcCollisions.lastIndex(), fileParticles, iMC, flags, -1, -1, nHits); + mcParticleId = tableStoredMcParticles.lastIndex(); + pdgCode = fileParticles.m_particle_type->at(iMC); + break; + } + } + if (addDaughterInfo) { + for (size_t iMC = 0; iMC < nDaughterParticles; ++iMC) { + if (fileDaughterParticles.m_particleId->at(iMC) == idMCTrueParticle) { + if (count(idMCparticles.begin(), idMCparticles.end(), fileDaughterParticles.m_particleId->at(iMC)) > 0) { + break; + } + + int nHits = 0; + for (size_t iPartSim = 0; iPartSim < nParticlesSim; ++iPartSim) { + if (fileParticlesSim.m_particleId->at(iPartSim) == fileDaughterParticles.m_particleId->at(iMC)) { + nHits = fileParticlesSim.m_number_of_hits->at(iPartSim); + break; + } + } + for (size_t iMother = 0; iMother < nParticlesGen; ++iMother) { + if (fileDaughterParticles.m_motherId->at(iMC) == fileParticles.m_particleId->at(iMother)) { + if (count(idMCparticles.begin(), idMCparticles.end(), fileParticles.m_particleId->at(iMother)) > 0) { + break; + } + idMCparticles.push_back(fileParticles.m_particleId->at(iMother)); + uint8_t flagsMother = o2::aod::mcparticle::enums::PhysicalPrimary; + addMCParticle(tableMcCollisions.lastIndex(), fileParticles, iMother, flagsMother, -1, tableStoredMcParticles.lastIndex() + 2, 0); + break; + } + } + int motherId = -1; + if (count(idMCparticles.begin(), idMCparticles.end(), fileDaughterParticles.m_motherId->at(iMC)) > 0) { + auto it = find(idMCparticles.begin(), idMCparticles.end(), fileDaughterParticles.m_motherId->at(iMC)); + motherId = it - idMCparticles.begin() + indexOfLastParticleAfterEvent + 1; + } + idMCparticles.push_back(fileDaughterParticles.m_particleId->at(iMC)); + addMCParticle(tableMcCollisions.lastIndex(), fileDaughterParticles, iMC, flags, motherId, -1, nHits); + mcParticleId = tableStoredMcParticles.lastIndex(); + pdgCode = fileDaughterParticles.m_particle_type->at(iMC); + break; + } + } + } // Extract ACTS track parameters const float phi = fileTracksummary.m_ePHI_fit->at(iTrack); const float theta = fileTracksummary.m_eTHETA_fit->at(iTrack); @@ -409,7 +491,7 @@ struct Alice3TrackingTranslator { o2::track::TrackParCov trackParCov(x, alpha, trackParams, trackCov, charge); // Fill StoredTracks table (basic track parameters) - tableStoredTracks(tableCollisions.lastIndex(), // collisionId + tableStoredTracks(collisionId, // collisionId o2::aod::track::TrackTypeEnum::Track, // trackType trackParCov.getX(), // x trackParCov.getAlpha(), // alpha @@ -460,8 +542,6 @@ struct Alice3TrackingTranslator { // Fill MC track labels // Get particle linkage from hits using the majority hit index - int32_t mcParticleId = -1; // Default to invalid particle ID - mcParticleId = tableStoredMcParticles.lastIndex(); // Temporary: link all tracks to the last added MC particle // if (fileTracksummary.nMajorityHits && iTrack < fileTracksummary.nMajorityHits->size()) { // unsigned int hitIndex = fileTracksummary.nMajorityHits->at(iTrack); // if (fileHits.barcode && hitIndex < fileHits.barcode->size()) { @@ -489,7 +569,8 @@ struct Alice3TrackingTranslator { 0.0f); // sigmaDcaZ2 // Fill ALICE3 specific tables - tableTracksAlice3(true); // isReconstructed + tableTracksAlice3(true); // isReconstructed + tableTracksAlice3Pdg(pdgCode); // PdgCode to the linked MC truth particle tableTracksExtraA3(m_nMeasurements, // nSiliconHits (using m_nMeasurements as proxy) 0); // nTPCHits @@ -546,43 +627,64 @@ struct Alice3TrackingTranslator { } for (size_t iParticle = 0; iParticle < nParticlesGen; ++iParticle) { - + if (iParticle == 0 && nTracks == 0) { + tableMcCollisions(0, // mccollision::BCId, + 0, // mccollision::GeneratorsID, + fileParticles.m_vx->at(iParticle), // mccollision::PosX, + fileParticles.m_vy->at(iParticle), // mccollision::PosY, + fileParticles.m_vz->at(iParticle), // mccollision::PosZ + fileParticles.m_vt->at(iParticle), // mccollision::T + 1.0f, // mccollision::Weight + 0.0f, // mccollision::ImpactParameter, + 0.f); // mccollision::EventPlaneAngle, + } + if (idMCparticles.end() != std::find(idMCparticles.begin(), idMCparticles.end(), fileParticles.m_particleId->at(iParticle))) { + // Already added via track + continue; + } uint8_t flags = 0; flags |= o2::aod::mcparticle::enums::PhysicalPrimary; - bool alreadyAdded = false; - for (const auto& ap : addedParticles[fileParticles.m_particle_type->at(iParticle)]) { - if (std::abs(ap.px - fileParticles.m_px->at(iParticle)) <= 1.e-5 && - std::abs(ap.py - fileParticles.m_py->at(iParticle)) <= 1.e-5 && - std::abs(ap.pz - fileParticles.m_pz->at(iParticle)) <= 1.e-5 && - std::abs(ap.vx - fileParticles.m_vx->at(iParticle)) <= 1.e-5 && - std::abs(ap.vy - fileParticles.m_vy->at(iParticle)) <= 1.e-5 && - std::abs(ap.vz - fileParticles.m_vz->at(iParticle)) <= 1.e-5) { - alreadyAdded = true; + + int nHits = 0; + for (size_t iPartSim = 0; iPartSim < nParticlesSim; ++iPartSim) { + if (fileParticlesSim.m_particleId->at(iPartSim) == fileParticles.m_particleId->at(iParticle)) { + nHits = fileParticlesSim.m_number_of_hits->at(iPartSim); break; } } - if (alreadyAdded) { - continue; + addMCParticle(tableMcCollisions.lastIndex(), fileParticles, iParticle, flags, -1, -1, nHits); + idMCparticles.push_back(fileParticles.m_particleId->at(iParticle)); + } + if (addDaughterInfo) { + for (size_t iParticle = 0; iParticle < nDaughterParticles; ++iParticle) { + if (idMCparticles.end() != std::find(idMCparticles.begin(), idMCparticles.end(), fileDaughterParticles.m_particleId->at(iParticle))) { + // Already added via track + continue; + } + uint8_t flags = 0; + int nHits = 0; + for (size_t iPartSim = 0; iPartSim < nParticlesSim; ++iPartSim) { + if (fileParticlesSim.m_particleId->at(iPartSim) == fileDaughterParticles.m_particleId->at(iParticle)) { + nHits = fileParticlesSim.m_number_of_hits->at(iPartSim); + break; + } + } + int motherId = -1; + for (size_t iMother = 0; iMother < nParticlesGen; ++iMother) { + if (fileDaughterParticles.m_motherId->at(iParticle) == fileParticles.m_particleId->at(iMother)) { + if (count(idMCparticles.begin(), idMCparticles.end(), fileDaughterParticles.m_motherId->at(iParticle)) > 0) { + auto it = find(idMCparticles.begin(), idMCparticles.end(), fileDaughterParticles.m_motherId->at(iParticle)); + motherId = it - idMCparticles.begin() + indexOfLastParticleAfterEvent + 1; + } + } + } + addMCParticle(tableMcCollisions.lastIndex(), fileDaughterParticles, iParticle, flags, motherId, -1, nHits); } - - tableStoredMcParticles(tableMcCollisions.lastIndex(), // mcCollisionId - fileParticles.m_particle_type->at(iParticle), // pdgCode - 0, // statusCode - flags, // flags - mothers, // mothersIds - daughters, // daughtersIdSlice - 1.0f, // weight - fileParticles.m_px->at(iParticle), // m_px - fileParticles.m_py->at(iParticle), // m_py - fileParticles.m_pz->at(iParticle), // m_pz - std::hypot(fileParticles.m_p->at(iParticle), fileParticles.m_m->at(iParticle)), // e - fileParticles.m_vx->at(iParticle), // m_vx - fileParticles.m_vy->at(iParticle), // m_vy - fileParticles.m_vz->at(iParticle), // m_vz - fileParticles.m_vt->at(iParticle)); // m_vt } - LOG(info) << "Event " << iEvent << ": has " << nTracks << " tracks and " << nParticles << " particles."; + LOG(info) << "Event " << iEvent << ": has " << nTracks << " tracks, " << nParticlesGen << " particles " << nDaughterParticles << " daughter particles, " << nParticlesSim << " propagated particles."; + LOG(info) << "Total numbers of stored MC particles: " << tableStoredMcParticles.lastIndex() + 1; + indexOfLastParticleAfterEvent = tableStoredMcParticles.lastIndex(); } } }; From 7a0792059363a48720f5f31728cd8a2de584969b Mon Sep 17 00:00:00 2001 From: Md Samsul Islam <56156956+mislam17@users.noreply.github.com> Date: Mon, 23 Feb 2026 15:50:21 +0530 Subject: [PATCH 035/347] [PWGHF] Task to identify various sources of single muons and the Axe calculation (#15112) --- PWGHF/HFL/Tasks/taskSingleMuonMultMc.cxx | 535 +++++++++++++++++++++++ 1 file changed, 535 insertions(+) create mode 100644 PWGHF/HFL/Tasks/taskSingleMuonMultMc.cxx diff --git a/PWGHF/HFL/Tasks/taskSingleMuonMultMc.cxx b/PWGHF/HFL/Tasks/taskSingleMuonMultMc.cxx new file mode 100644 index 00000000000..1f67d77b14d --- /dev/null +++ b/PWGHF/HFL/Tasks/taskSingleMuonMultMc.cxx @@ -0,0 +1,535 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +// +/// \file taskSingleMuonMultMc.cxx +/// \brief Task used to identify various sources of single muons and to calculated Axe in Monte Carlo simulation. +/// \author Md Samsul Islam , IITB + +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "CommonConstants/PhysicsConstants.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/TrackFwd.h" +#include + +#include + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::aod::fwdtrack; + +auto static constexpr MinCharge = 3.f; + +namespace +{ +enum ParticleType { + IsIdentified = 0, // this particle is identified + IsMuon, // this is a muon + IsSecondary, // this is a secondary particle + HasTauParent, // this particle has a tau parent + HasWParent, // this particle has a W parent + HasZParent, // this particle has a Z parent + HasLightParent, // this particle has a light flavor parent + HasQuarkoniumParent, // this particle has a quarkonium parent + HasCharmParent, // this particle has a charm parent + HasBeautyParent // this particle has a beauty parent +}; +} // namespace + +struct HfTaskSingleMuonMultMc { + SliceCache cache; + Preslice perCol = aod::track::collisionId; + Preslice perMcCol = aod::mcparticle::mcCollisionId; + o2::framework::Service pdg; + + Configurable mcMaskSelection{"mcMaskSelection", 0, "McMask for correct match, valid values are 0 and 128"}; + Configurable pdgQuark{"pdgQuark", 10, "pdg Max for Quarks"}; + Configurable pdgRemMin{"pdgRemMin", 100, " Min. pdg Remnant for calculating Hadron pdg"}; + Configurable pdgRemMax{"pdgRemMax", 10000, "Max. pdg Remnant for calculating Hadron pdg"}; + Configurable flvMin{"flvMin", 4, "Min flavor of constituent quark"}; + Configurable flvMax{"flvMax", 6, "Max flavor of constituent quark"}; + Configurable flvLeading{"flvLeading", 10, "Base to extract leading flavor of constituent quark"}; + + Configurable charge{"charge", -1, "Muon track charge, validated values are 0, 1 and -1, 0 represents both 1 and -1"}; + Configurable zVtxMax{"zVtxMax", 10., "maxium z of primary vertex [cm]"}; + Configurable ptTrackMin{"ptTrackMin", 0.15, "minimum pt of tracks"}; + Configurable etaTrackMax{"etaTrackMax", 0.8, "maximum pseudorapidity of tracks"}; + Configurable etaMin{"etaMin", -3.6, "minimum pseudorapidity"}; + Configurable etaMax{"etaMax", -2.5, "maximum pseudorapidity"}; + Configurable pDcaMin{"pDcaMin", 324., "p*DCA value for small RAbsorb"}; + Configurable pDcaMax{"pDcaMax", 594., "p*DCA value for large RAbsorb"}; + Configurable rAbsorbMin{"rAbsorbMin", 17.6, "R at absorber end minimum value"}; + Configurable rAbsorbMax{"rAbsorbMax", 89.5, "R at absorber end maximum value"}; + Configurable rAbsorbMid{"rAbsorbMid", 26.5, "R at absorber end split point for different p*DCA selections"}; + + using MyCollisions = soa::Join; + using McMuons = soa::Join; + using MyTracks = soa::Filtered>; + using McGenCollisions = soa::Join; + using McRecCollisions = soa::SmallGroups>; + + // Filter Global Track for Multiplicty + Filter trackFilter = ((nabs(aod::track::eta) < etaTrackMax) && (aod::track::pt > ptTrackMin)); + + HistogramRegistry registry{ + "registry", + {}, + OutputObjHandlingPolicy::AnalysisObject, + true, + true}; + + void init(InitContext&) + { + const TString muonSources[]{ + "Identified", + "Muon", + "SecondaryMu", + "LightDecayMu", + "TauDecayMu", + "WBosonDecayMu", + "ZBosonDecayMu", + "QuarkoniumDecayMu", + "BeautyMu", + "BeautyDecayMu", + "NonpromptCharmMu", + "PromptCharmMu", + "OtherMu", + "Hadron", + "Unidentified"}; + + AxisSpec axisColNumber{1, 0.5, 1.5, "Selected collisions"}; + AxisSpec axisMcMask{1001, -500.5, 500.5, "Mc Mask Selection"}; + AxisSpec axisMcLabel{1001, -500.5, 500.5, "McLabel"}; + AxisSpec axisNCh{500, 0.5, 500.5, "#it{N}_{ch}"}; + AxisSpec axisNtrk{500, 0.5, 500.5, "#it{N}_{trk}"}; + AxisSpec axisPt{5000, 0., 500., "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec axisEta{1000, -5., 5., "#it{#eta}"}; + AxisSpec axisRAbsorb{1000, 0., 100., "#it{R}_{Absorb} (cm)"}; + AxisSpec axisDCA{500, 0., 5., "#it{DCA}_{xy} (cm)"}; + AxisSpec axisChi2{1000, 0., 1000., "MCH-MFT matching #chi^{2}"}; + AxisSpec axisPDca{100000, 0, 100000, "#it{p} #times DCA (GeV/#it{c} * cm)"}; + AxisSpec axisDeltaPt{10000, -50, 50, "#Delta #it{p}_{T} (GeV/#it{c})"}; + AxisSpec axisTrackType{8, -1.5, 6.5, "TrackType"}; + AxisSpec axisZ{1000, -50, 50, "V_{z} axis"}; + AxisSpec axisCharge{21, -10.5, 10.5, "charge"}; + AxisSpec axisPDG{201, -100.5, 100.5, "PDG"}; + AxisSpec axisMuonMask{15, -0.5, 14.5, "MuonMask"}; + + HistogramConfigSpec hNEventGen{HistType::kTH1F, {axisColNumber}}; + HistogramConfigSpec hNEventRec{HistType::kTH1F, {axisColNumber}}; + HistogramConfigSpec hParticleGen{HistType::kTHnSparseF, {axisPt, axisEta}}; + HistogramConfigSpec hParticleRec{HistType::kTHnSparseF, {axisPt, axisEta}}; + HistogramConfigSpec hTrackResponse{HistType::kTH2F, {axisNCh, axisNtrk}}; + + HistogramConfigSpec hMcMask{HistType::kTH1F, {axisMcMask}}; + HistogramConfigSpec hMuMcLabel{HistType::kTH1F, {axisMcLabel}}; + HistogramConfigSpec hMuTrackType{HistType::kTH1F, {axisTrackType}}; + HistogramConfigSpec hNEventGenMu{HistType::kTH1F, {axisColNumber}}; + HistogramConfigSpec hNEventRecMu{HistType::kTH1F, {axisColNumber}}; + HistogramConfigSpec hGenMuVar{HistType::kTHnSparseF, {axisPDG, axisPt, axisEta}}; + HistogramConfigSpec hRecMuVar{HistType::kTHnSparseF, {axisPDG, axisPt, axisEta}}; + HistogramConfigSpec hMuAfterAccCuts{HistType::kTHnSparseF, {axisPDG, axisPt, axisEta, axisRAbsorb, axisDCA, axisPDca, axisChi2, axisTrackType}}; + + registry.add("hNEventRec", "", hNEventRec); + registry.add("hNEventGen", "", hNEventGen); + registry.add("hParticleGen", "Generated particles ", hParticleGen); + registry.add("hParticleRec", "Reconstructed particles", hParticleRec); + registry.add("hTrackResponse", "Generation-Recontsruction Response", hTrackResponse); + + registry.add("hMcMask", "Muon mcMask", hMcMask); + registry.add("hMuMcLabel", "Muon mcLabel", hMuMcLabel); + registry.add("hMuTrackType", "PDG code", hMuTrackType); + registry.add("hNEventGenMu", "Muon Generated", hNEventGenMu); + registry.add("hNEventRecMu", "Muon Reconstruced", hNEventRecMu); + registry.add("hGenMuVar", "Muon Generated Variables", hGenMuVar); + registry.add("hRecMuVar", "Muon Reconstructed Variables", hRecMuVar); + registry.add("hMuAfterAccCuts", "Muon Reconstructed Variables", hMuAfterAccCuts); + + for (const auto& src : muonSources) { + registry.add(Form("h2%s", src.Data()), "", {HistType::kTH2F, {axisPt, axisEta}}); + } + } + + // get the bitmask for muon sources identification + uint16_t getMask(const McMuons::iterator& muon) + { + uint16_t mask(0); + if (!muon.has_mcParticle()) { + return mask; + } + SETBIT(mask, IsIdentified); + + auto mcPart(muon.mcParticle()); + if (std::abs(mcPart.pdgCode()) != kMuonMinus) { + return mask; + } + SETBIT(mask, IsMuon); + + while (mcPart.has_mothers()) { + mcPart = *(mcPart.mothers_first_as()); + const int pdgAbs = std::abs(mcPart.pdgCode()); + + // Stop at quark + if (pdgAbs < pdgQuark) { + break; + } + + // Produced in transport code + if (!mcPart.producedByGenerator()) { + SETBIT(mask, IsSecondary); + continue; + } + + // Tau parent + if (pdgAbs == kTauMinus) { + SETBIT(mask, HasTauParent); + continue; + } + + // W boson + if (pdgAbs == kWPlus) { + SETBIT(mask, HasWParent); + continue; + } + + // Z boson + if (pdgAbs == kZ0) { + SETBIT(mask, HasZParent); + continue; + } + + const int pdgRem(pdgAbs % 100000); + + if (pdgRem == kProton) { + continue; + } // Beam particle + + if ((pdgRem < pdgRemMin) || (pdgRem >= pdgRemMax)) { + continue; + } + // compute the leding flavor of constituent quark + int flv(pdgRem); + while (flv >= flvLeading) { + flv /= flvLeading; + } + + if (flv > flvMax) { + // no more than 6 flavors + continue; + } + if (flv < flvMin) { + // light flavor + SETBIT(mask, HasLightParent); + continue; + } + + auto pdgData(pdg->GetParticle(mcPart.pdgCode())); + if (pdgData && (pdgData->AntiParticle() == nullptr)) { + SETBIT(mask, HasQuarkoniumParent); + continue; + } else if (flv == flvMin) { + SETBIT(mask, HasCharmParent); + continue; + } else { + SETBIT(mask, HasBeautyParent); + continue; + } + } + + return mask; + } + + // particle has an associated MC particle + bool isIdentified(const uint16_t& mask) + { + return (TESTBIT(mask, IsIdentified)); + } + // this particle is muon + bool isMuon(const uint16_t& mask) + { + return (TESTBIT(mask, IsIdentified) && TESTBIT(mask, IsMuon)); + } + + // this muon comes from transport + bool isSecondaryMu(const uint16_t& mask) + { + return (isMuon(mask) && TESTBIT(mask, IsSecondary)); + } + + // this muon comes from light flavor quark decay + bool isLightDecayMu(const uint16_t& mask) + { + return (isMuon(mask) && TESTBIT(mask, HasLightParent) && (!TESTBIT(mask, IsSecondary))); + } + + // this muon comes from tau decays + bool isTauDecayMu(const uint16_t& mask) + { + return (isMuon(mask) && TESTBIT(mask, HasTauParent) && (!TESTBIT(mask, HasWParent)) && (!TESTBIT(mask, HasZParent)) && (!TESTBIT(mask, HasBeautyParent)) && (!TESTBIT(mask, HasCharmParent))); + } + + // this muon comes from W+- decay + bool isWBosonDecayMu(const uint16_t& mask) + { + return (isMuon(mask) && TESTBIT(mask, HasWParent) && (!TESTBIT(mask, HasZParent)) && (!TESTBIT(mask, HasTauParent)) && (!TESTBIT(mask, HasLightParent)) && (!TESTBIT(mask, IsSecondary))); + } + + // this muon comes from Z decay + bool isZBosonDecayMu(const uint16_t& mask) + { + return (isMuon(mask) && TESTBIT(mask, HasZParent) && (!TESTBIT(mask, HasWParent)) && (!TESTBIT(mask, HasTauParent)) && (!TESTBIT(mask, HasLightParent)) && (!TESTBIT(mask, IsSecondary))); + } + + // this muon comes from quarkonium decay + bool isQuarkoniumDecayMu(const uint16_t& mask) + { + return (isMuon(mask) && TESTBIT(mask, HasQuarkoniumParent) && (!TESTBIT(mask, HasBeautyParent)) && (!TESTBIT(mask, HasCharmParent)) && (!TESTBIT(mask, HasLightParent))); + } + + // this muon comes from beauty decay and does not have light flavor parent + bool isBeautyMu(const uint16_t& mask) + { + return (isMuon(mask) && TESTBIT(mask, HasBeautyParent) && (!TESTBIT(mask, HasQuarkoniumParent)) && (!TESTBIT(mask, HasLightParent)) && (!TESTBIT(mask, IsSecondary))); + } + + // this muon comes directly from beauty decay + bool isBeautyDecayMu(const uint16_t& mask) + { + return (isBeautyMu(mask) && (!TESTBIT(mask, HasCharmParent) && (!TESTBIT(mask, HasQuarkoniumParent))) && (!TESTBIT(mask, HasLightParent)) && (!TESTBIT(mask, IsSecondary))); + } + + // this muon comes from non-prompt charm decay and does not have light flavor parent + bool isNonpromptCharmMu(const uint16_t& mask) + { + return (isBeautyMu(mask) && TESTBIT(mask, HasCharmParent) && (!TESTBIT(mask, HasQuarkoniumParent)) && (!TESTBIT(mask, HasLightParent)) && (!TESTBIT(mask, IsSecondary))); + } + + // this muon comes from prompt charm decay and does not have light flavor parent + bool isPromptCharmMu(const uint16_t& mask) + { + return (isMuon(mask) && TESTBIT(mask, HasCharmParent) && (!TESTBIT(mask, HasBeautyParent)) && (!TESTBIT(mask, HasQuarkoniumParent)) && (!TESTBIT(mask, HasLightParent)) && (!TESTBIT(mask, IsSecondary))); + } + + // this muon comes from other sources which have not classified above. + bool isOtherMu(const uint16_t& mask) + { + return (isMuon(mask) && (!isSecondaryMu(mask)) && (!isLightDecayMu(mask)) && (!isTauDecayMu(mask)) && (!isWBosonDecayMu(mask)) && (!isZBosonDecayMu(mask)) && (!isQuarkoniumDecayMu(mask)) && (!isBeautyMu(mask)) && (!isPromptCharmMu(mask))); + } + + // this is a hadron + bool isHadron(const uint16_t& mask) + { + return (TESTBIT(mask, IsIdentified) && (!TESTBIT(mask, IsMuon))); + } + + // this particle is unidentified + bool isUnidentified(const uint16_t& mask) + { + return ((!TESTBIT(mask, IsIdentified))); + } + + // fill the histograms of each particle types + void fillHistograms(const McMuons::iterator& muon) + { + const auto mask(getMask(muon)); + const auto pt(muon.pt()), eta(muon.eta()); + + if (isIdentified(mask)) { + registry.fill(HIST("h2Identified"), pt, eta); + } + if (isMuon(mask)) { + registry.fill(HIST("h2Muon"), pt, eta); + } + if (isSecondaryMu(mask)) { + registry.fill(HIST("h2SecondaryMu"), pt, eta); + } + if (isLightDecayMu(mask)) { + registry.fill(HIST("h2LightDecayMu"), pt, eta); + } + if (isTauDecayMu(mask)) { + registry.fill(HIST("h2TauDecayMu"), pt, eta); + } + if (isWBosonDecayMu(mask)) { + registry.fill(HIST("h2WBosonDecayMu"), pt, eta); + } + if (isZBosonDecayMu(mask)) { + registry.fill(HIST("h2ZBosonDecayMu"), pt, eta); + } + if (isQuarkoniumDecayMu(mask)) { + registry.fill(HIST("h2QuarkoniumDecayMu"), pt, eta); + } + if (isBeautyMu(mask)) { + registry.fill(HIST("h2BeautyMu"), pt, eta); + } + if (isBeautyDecayMu(mask)) { + registry.fill(HIST("h2BeautyDecayMu"), pt, eta); + } + if (isNonpromptCharmMu(mask)) { + registry.fill(HIST("h2NonpromptCharmMu"), pt, eta); + } + if (isPromptCharmMu(mask)) { + registry.fill(HIST("h2PromptCharmMu"), pt, eta); + } + if (isOtherMu(mask)) { + registry.fill(HIST("h2OtherMu"), pt, eta); + } + if (isHadron(mask)) { + registry.fill(HIST("h2Hadron"), pt, eta); + } + if (isUnidentified(mask)) { + registry.fill(HIST("h2Unidentified"), pt, eta); + } + } + + void process(McGenCollisions::iterator const& mccollision, McMuons const& muons, aod::McParticles const&, McRecCollisions const& collisions) + { + + // event selections + if (std::abs(mccollision.posZ()) > zVtxMax) { + return; + } + + registry.fill(HIST("hNEventGenMu"), 1); + + for (const auto& muon : muons) { + if (!(muon.has_mcParticle())) { + continue; + } + auto mcPart(muon.mcParticle()); + auto pdgGen(mcPart.pdgCode()); + auto etaGen(mcPart.eta()); + + if (!(std::abs(pdgGen) == kMuonMinus)) { + continue; + } + if ((etaGen >= etaMax) || (etaGen < etaMin)) { + continue; + } + registry.fill(HIST("hGenMuVar"), pdgGen, mcPart.pt(), etaGen); + } + + for (const auto& collision : collisions) { + if (std::abs(collision.posZ()) > zVtxMax) { + continue; + } + registry.fill(HIST("hNEventRecMu"), 1); + + for (const auto& muon : muons) { + // muon selections + registry.fill(HIST("hMcMask"), muon.mcMask()); + + if (muon.mcMask() != mcMaskSelection) { + continue; + } + + if (!(muon.has_mcParticle())) { + continue; + } + const auto pt(muon.pt()), eta(muon.eta()), rAbsorb(muon.rAtAbsorberEnd()), pDca(muon.pDca()), chi2(muon.chi2MatchMCHMFT()); + const auto dcaXY{RecoDecay::sqrtSumOfSquares(muon.fwdDcaX(), muon.fwdDcaY())}; + const auto muTrackType{muon.trackType()}; + const auto mcLabel(muon.mcParticleId()); + + if (mcLabel < 0) { + continue; + } + + registry.fill(HIST("hMuMcLabel"), mcLabel); + registry.fill(HIST("hMuTrackType"), muTrackType); + + auto mcparticle(muon.mcParticle()); + const auto pdg(mcparticle.pdgCode()); + + if ((eta >= etaMax) || (eta < etaMin)) { + continue; + } + if ((rAbsorb >= rAbsorbMax) || (rAbsorb < rAbsorbMin)) { + continue; + } + if (pDca >= pDcaMax) { + continue; + } + registry.fill(HIST("hRecMuVar"), pdg, pt, eta); + registry.fill(HIST("hMuAfterAccCuts"), pdg, pt, eta, rAbsorb, dcaXY, pDca, chi2, muTrackType); + + fillHistograms(muon); + } + } + } + + void processResTrack(McGenCollisions::iterator const& mccollision, McRecCollisions const& collisions, aod::McParticles const& particles, MyTracks const& tracks) + { + // event selections + if (std::abs(mccollision.posZ()) > zVtxMax) { + return; + } + registry.fill(HIST("hNEventGen"), 1.); + auto nP = 0; + for (const auto& particle : particles) { + if (!particle.isPhysicalPrimary()) { + continue; + } + if (!particle.producedByGenerator()) { + continue; + } + + auto charge = 0.; + auto* p = pdg->GetParticle(particle.pdgCode()); + if (p != nullptr) { + charge = p->Charge(); + } + + if (std::abs(charge) < MinCharge) { + continue; + } + if (particle.pt() < ptTrackMin || std::abs(particle.eta()) >= etaTrackMax) { + continue; + } + + registry.fill(HIST("hParticleGen"), particle.pt(), particle.eta()); + nP++; + } + for (const auto& collision : collisions) { + if (std::abs(collision.posZ()) > zVtxMax) { + continue; + } + registry.fill(HIST("hNEventRec"), 1.); + auto nTrk = 0; + auto tracksample = tracks.sliceBy(perCol, collision.globalIndex()); + for (const auto& track : tracksample) { + if (!track.isGlobalTrack()) + continue; + registry.fill(HIST("hParticleRec"), track.pt(), track.eta()); + ++nTrk; + } + if (nTrk < 1) + continue; + registry.fill(HIST("hTrackResponse"), nP, nTrk); + } + } + PROCESS_SWITCH(HfTaskSingleMuonMultMc, processResTrack, "Process Track Reconstruction/Generation", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc), + }; +} From 790d3e8082196cdb112b1f60fe8591e827acf9e0 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Mon, 23 Feb 2026 11:52:42 +0100 Subject: [PATCH 036/347] [PWGEM/Dilepton] reduce data size in Event,Mult,Cent,Qvector (#15108) Co-authored-by: ALICE Action Bot --- PWGEM/Dilepton/Core/Dilepton.h | 44 +- PWGEM/Dilepton/Core/DileptonMC.h | 42 +- PWGEM/Dilepton/Core/DileptonProducer.h | 4 +- PWGEM/Dilepton/Core/EMEventCut.h | 32 +- PWGEM/Dilepton/Core/SingleTrackQC.h | 42 +- PWGEM/Dilepton/Core/SingleTrackQCMC.h | 42 +- PWGEM/Dilepton/DataModel/dileptonTables.h | 231 +++- PWGEM/Dilepton/TableProducer/CMakeLists.txt | 10 + .../TableProducer/Converters/CMakeLists.txt | 35 + .../Converters/bcConverter1.cxx} | 27 +- .../Converters/eventCentConverter1.cxx | 47 + .../Converters/eventConverter5.cxx | 113 ++ .../Converters/eventMultConverter1.cxx | 46 + .../Converters/eventNormConverter2.cxx | 59 ++ .../Converters/qvec2Converter0.cxx | 50 + .../Converters/qvec3Converter0.cxx | 50 + .../TableProducer/associateMCinfoDilepton.cxx | 168 +-- .../TableProducer/createEMEventDilepton.cxx | 119 ++- .../TableProducer/qVector2DummyOTF.cxx | 46 + .../TableProducer/qVector3DummyOTF.cxx | 46 + PWGEM/Dilepton/Tasks/checkMCPairTemplate.cxx | 42 +- PWGEM/Dilepton/Tasks/eventQC.cxx | 2 +- PWGEM/Dilepton/Utils/EventHistograms.h | 63 +- PWGEM/PhotonMeson/Core/DiphotonHadronMPC.h | 992 ------------------ PWGEM/PhotonMeson/Core/EMCPhotonCut.h | 6 +- PWGEM/PhotonMeson/Core/EMPhotonEventCut.cxx | 102 ++ PWGEM/PhotonMeson/Core/EMPhotonEventCut.h | 163 ++- PWGEM/PhotonMeson/Core/PhotonHBT.h | 4 +- PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h | 34 +- PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h | 38 +- PWGEM/PhotonMeson/Core/TaggingPi0.h | 42 +- PWGEM/PhotonMeson/Core/TaggingPi0MC.h | 42 +- PWGEM/PhotonMeson/Core/V0PhotonCut.h | 6 +- PWGEM/PhotonMeson/DataModel/gammaTables.h | 35 +- .../PhotonMeson/TableProducer/CMakeLists.txt | 2 + .../TableProducer/Converters/CMakeLists.txt | 27 + .../Converters/emcIdConverter1.cxx} | 26 +- .../Converters/phosIdConverter1.cxx | 38 + .../Converters/v0photonIdConverter1.cxx | 38 + .../TableProducer/createEMEventPhoton.cxx | 22 +- .../TableProducer/nonLinProducer.cxx | 10 +- .../TableProducer/skimmerDalitzEE.cxx | 12 +- PWGEM/PhotonMeson/Tasks/CMakeLists.txt | 11 - PWGEM/PhotonMeson/Tasks/MaterialBudget.cxx | 10 +- PWGEM/PhotonMeson/Tasks/MaterialBudgetMC.cxx | 4 +- .../Tasks/Pi0EtaToGammaGammaMCPCMDalitzEE.cxx | 2 +- .../Tasks/Pi0EtaToGammaGammaPCMDalitzEE.cxx | 2 +- PWGEM/PhotonMeson/Tasks/SinglePhoton.cxx | 4 +- PWGEM/PhotonMeson/Tasks/SinglePhotonMC.cxx | 4 +- PWGEM/PhotonMeson/Tasks/TagAndProbe.cxx | 7 +- PWGEM/PhotonMeson/Tasks/calibTaskEmc.cxx | 10 +- PWGEM/PhotonMeson/Tasks/compconvbuilder.cxx | 6 +- PWGEM/PhotonMeson/Tasks/dalitzEEQC.cxx | 10 +- PWGEM/PhotonMeson/Tasks/dalitzEEQCMC.cxx | 10 +- PWGEM/PhotonMeson/Tasks/emcalQC.cxx | 4 +- PWGEM/PhotonMeson/Tasks/gammaConversions.cxx | 2 +- PWGEM/PhotonMeson/Tasks/pcmQC.cxx | 2 +- PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx | 2 +- PWGEM/PhotonMeson/Tasks/phosQC.cxx | 2 +- PWGEM/PhotonMeson/Tasks/photonResoTask.cxx | 6 +- PWGEM/PhotonMeson/Tasks/prefilterPhoton.cxx | 16 +- PWGEM/PhotonMeson/Tasks/taskFlowReso.cxx | 2 +- PWGEM/PhotonMeson/Tasks/taskPi0FlowEMC.cxx | 10 +- 63 files changed, 1612 insertions(+), 1513 deletions(-) rename PWGEM/{PhotonMeson/Tasks/diphotonHadronMPCPCMDalitzEE.cxx => Dilepton/TableProducer/Converters/bcConverter1.cxx} (61%) create mode 100644 PWGEM/Dilepton/TableProducer/Converters/eventCentConverter1.cxx create mode 100644 PWGEM/Dilepton/TableProducer/Converters/eventConverter5.cxx create mode 100644 PWGEM/Dilepton/TableProducer/Converters/eventMultConverter1.cxx create mode 100644 PWGEM/Dilepton/TableProducer/Converters/eventNormConverter2.cxx create mode 100644 PWGEM/Dilepton/TableProducer/Converters/qvec2Converter0.cxx create mode 100644 PWGEM/Dilepton/TableProducer/Converters/qvec3Converter0.cxx create mode 100644 PWGEM/Dilepton/TableProducer/qVector2DummyOTF.cxx create mode 100644 PWGEM/Dilepton/TableProducer/qVector3DummyOTF.cxx delete mode 100644 PWGEM/PhotonMeson/Core/DiphotonHadronMPC.h create mode 100644 PWGEM/PhotonMeson/TableProducer/Converters/CMakeLists.txt rename PWGEM/PhotonMeson/{Tasks/diphotonHadronMPCPCMPCM.cxx => TableProducer/Converters/emcIdConverter1.cxx} (63%) create mode 100644 PWGEM/PhotonMeson/TableProducer/Converters/phosIdConverter1.cxx create mode 100644 PWGEM/PhotonMeson/TableProducer/Converters/v0photonIdConverter1.cxx diff --git a/PWGEM/Dilepton/Core/Dilepton.h b/PWGEM/Dilepton/Core/Dilepton.h index c6c01e23b2f..f0b0aa28156 100644 --- a/PWGEM/Dilepton/Core/Dilepton.h +++ b/PWGEM/Dilepton/Core/Dilepton.h @@ -70,7 +70,7 @@ using namespace o2::aod::pwgem::dilepton::utils; using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; using namespace o2::aod::pwgem::dilepton::utils::pairutil; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; using MyElectrons = soa::Join; @@ -1604,28 +1604,28 @@ struct Dilepton { fRegistry.fill(HIST("Event/norm/hZvtx"), collision.posZ()); fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 1.0); - if (collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + if (collision.selection_bit(o2::aod::emevsel::kIsTriggerTVX)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 2.0); } - if (collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + if (collision.selection_bit(o2::aod::emevsel::kNoTimeFrameBorder)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 3.0); } - if (collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + if (collision.selection_bit(o2::aod::emevsel::kNoITSROFrameBorder)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 4.0); } - if (collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + if (collision.selection_bit(o2::aod::emevsel::kNoSameBunchPileup)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 5.0); } - if (collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + if (collision.selection_bit(o2::aod::emevsel::kIsGoodZvtxFT0vsPV)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 6.0); } - if (collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + if (collision.selection_bit(o2::aod::emevsel::kIsVertexITSTPC)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 7.0); } - if (collision.selection_bit(o2::aod::evsel::kIsVertexTRDmatched)) { + if (collision.selection_bit(o2::aod::emevsel::kIsVertexTRDmatched)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 8.0); } - if (collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) { + if (collision.selection_bit(o2::aod::emevsel::kIsVertexTOFmatched)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 9.0); } if (collision.sel8()) { @@ -1634,28 +1634,28 @@ struct Dilepton { if (std::fabs(collision.posZ()) < 10.0) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 11.0); } - if (collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + if (collision.selection_bit(o2::aod::emevsel::kNoCollInTimeRangeStandard)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 12.0); } - if (collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStrict)) { + if (collision.selection_bit(o2::aod::emevsel::kNoCollInTimeRangeStrict)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 13.0); } - if (collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { + if (collision.selection_bit(o2::aod::emevsel::kNoCollInRofStandard)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 14.0); } - if (collision.selection_bit(o2::aod::evsel::kNoCollInRofStrict)) { + if (collision.selection_bit(o2::aod::emevsel::kNoCollInRofStrict)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 15.0); } - if (collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { + if (collision.selection_bit(o2::aod::emevsel::kNoHighMultCollInPrevRof)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 16.0); } - if (collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer3)) { + if (collision.selection_bit(o2::aod::emevsel::kIsGoodITSLayer3)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 17.0); } - if (collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer0123)) { + if (collision.selection_bit(o2::aod::emevsel::kIsGoodITSLayer0123)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 18.0); } - if (collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + if (collision.selection_bit(o2::aod::emevsel::kIsGoodITSLayersAll)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 19.0); } if (!fEMEventCut.IsSelected(collision)) { @@ -1672,22 +1672,22 @@ struct Dilepton { void processBC(aod::EMBCs const& bcs) { for (const auto& bc : bcs) { - if (bc.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + if (bc.selection_bit(o2::aod::emevsel::kIsTriggerTVX)) { fRegistry.fill(HIST("BC/hTVXCounter"), 0.f); - if (bc.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + if (bc.selection_bit(o2::aod::emevsel::kNoTimeFrameBorder)) { fRegistry.fill(HIST("BC/hTVXCounter"), 1.f); } - if (bc.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + if (bc.selection_bit(o2::aod::emevsel::kNoITSROFrameBorder)) { fRegistry.fill(HIST("BC/hTVXCounter"), 2.f); } if (rctChecker(bc)) { fRegistry.fill(HIST("BC/hTVXCounter"), 3.f); } - if (bc.selection_bit(o2::aod::evsel::kNoTimeFrameBorder) && bc.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + if (bc.selection_bit(o2::aod::emevsel::kNoTimeFrameBorder) && bc.selection_bit(o2::aod::emevsel::kNoITSROFrameBorder)) { fRegistry.fill(HIST("BC/hTVXCounter"), 4.f); } - if (bc.selection_bit(o2::aod::evsel::kNoTimeFrameBorder) && bc.selection_bit(o2::aod::evsel::kNoITSROFrameBorder) && rctChecker(bc)) { + if (bc.selection_bit(o2::aod::emevsel::kNoTimeFrameBorder) && bc.selection_bit(o2::aod::emevsel::kNoITSROFrameBorder) && rctChecker(bc)) { fRegistry.fill(HIST("BC/hTVXCounter"), 5.f); } } diff --git a/PWGEM/Dilepton/Core/DileptonMC.h b/PWGEM/Dilepton/Core/DileptonMC.h index bcf9292ed02..e323fee60a9 100644 --- a/PWGEM/Dilepton/Core/DileptonMC.h +++ b/PWGEM/Dilepton/Core/DileptonMC.h @@ -2640,28 +2640,28 @@ struct DileptonMC { { for (const auto& collision : collisions) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 1.0); - if (collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + if (collision.selection_bit(o2::aod::emevsel::kIsTriggerTVX)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 2.0); } - if (collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + if (collision.selection_bit(o2::aod::emevsel::kNoTimeFrameBorder)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 3.0); } - if (collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + if (collision.selection_bit(o2::aod::emevsel::kNoITSROFrameBorder)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 4.0); } - if (collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + if (collision.selection_bit(o2::aod::emevsel::kNoSameBunchPileup)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 5.0); } - if (collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + if (collision.selection_bit(o2::aod::emevsel::kIsGoodZvtxFT0vsPV)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 6.0); } - if (collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + if (collision.selection_bit(o2::aod::emevsel::kIsVertexITSTPC)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 7.0); } - if (collision.selection_bit(o2::aod::evsel::kIsVertexTRDmatched)) { + if (collision.selection_bit(o2::aod::emevsel::kIsVertexTRDmatched)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 8.0); } - if (collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) { + if (collision.selection_bit(o2::aod::emevsel::kIsVertexTOFmatched)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 9.0); } if (collision.sel8()) { @@ -2670,28 +2670,28 @@ struct DileptonMC { if (std::fabs(collision.posZ()) < 10.0) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 11.0); } - if (collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + if (collision.selection_bit(o2::aod::emevsel::kNoCollInTimeRangeStandard)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 12.0); } - if (collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStrict)) { + if (collision.selection_bit(o2::aod::emevsel::kNoCollInTimeRangeStrict)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 13.0); } - if (collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { + if (collision.selection_bit(o2::aod::emevsel::kNoCollInRofStandard)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 14.0); } - if (collision.selection_bit(o2::aod::evsel::kNoCollInRofStrict)) { + if (collision.selection_bit(o2::aod::emevsel::kNoCollInRofStrict)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 15.0); } - if (collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { + if (collision.selection_bit(o2::aod::emevsel::kNoHighMultCollInPrevRof)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 16.0); } - if (collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer3)) { + if (collision.selection_bit(o2::aod::emevsel::kIsGoodITSLayer3)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 17.0); } - if (collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer0123)) { + if (collision.selection_bit(o2::aod::emevsel::kIsGoodITSLayer0123)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 18.0); } - if (collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + if (collision.selection_bit(o2::aod::emevsel::kIsGoodITSLayersAll)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 19.0); } if (!fEMEventCut.IsSelected(collision)) { @@ -2708,22 +2708,22 @@ struct DileptonMC { void processBC(aod::EMBCs const& bcs) { for (const auto& bc : bcs) { - if (bc.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + if (bc.selection_bit(o2::aod::emevsel::kIsTriggerTVX)) { fRegistry.fill(HIST("BC/hTVXCounter"), 0.f); - if (bc.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + if (bc.selection_bit(o2::aod::emevsel::kNoTimeFrameBorder)) { fRegistry.fill(HIST("BC/hTVXCounter"), 1.f); } - if (bc.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + if (bc.selection_bit(o2::aod::emevsel::kNoITSROFrameBorder)) { fRegistry.fill(HIST("BC/hTVXCounter"), 2.f); } if (rctChecker(bc)) { fRegistry.fill(HIST("BC/hTVXCounter"), 3.f); } - if (bc.selection_bit(o2::aod::evsel::kNoTimeFrameBorder) && bc.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + if (bc.selection_bit(o2::aod::emevsel::kNoTimeFrameBorder) && bc.selection_bit(o2::aod::emevsel::kNoITSROFrameBorder)) { fRegistry.fill(HIST("BC/hTVXCounter"), 4.f); } - if (bc.selection_bit(o2::aod::evsel::kNoTimeFrameBorder) && bc.selection_bit(o2::aod::evsel::kNoITSROFrameBorder) && rctChecker(bc)) { + if (bc.selection_bit(o2::aod::emevsel::kNoTimeFrameBorder) && bc.selection_bit(o2::aod::emevsel::kNoITSROFrameBorder) && rctChecker(bc)) { fRegistry.fill(HIST("BC/hTVXCounter"), 5.f); } } diff --git a/PWGEM/Dilepton/Core/DileptonProducer.h b/PWGEM/Dilepton/Core/DileptonProducer.h index 764914fe806..26b06061cb4 100644 --- a/PWGEM/Dilepton/Core/DileptonProducer.h +++ b/PWGEM/Dilepton/Core/DileptonProducer.h @@ -69,7 +69,7 @@ using namespace o2::aod::pwgem::dilepton::utils; using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; using namespace o2::aod::pwgem::dilepton::utils::pairutil; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; using MyElectrons = soa::Join; @@ -774,7 +774,7 @@ struct DileptonProducer { continue; } - normTable(collision.selection_raw(), collision.rct_raw(), collision.posZint16(), collision.centFT0Cuint16()); + normTable(collision.selection_raw(), collision.rct_raw(), collision.posZint8(), collision.centFT0Muint8(), collision.centFT0Cuint8(), collision.centNTPVuint8() /*, collision.centNGlobaluint8()*/); } // end of collision loop } diff --git a/PWGEM/Dilepton/Core/EMEventCut.h b/PWGEM/Dilepton/Core/EMEventCut.h index 8dc1b7ef961..3cc785e80a8 100644 --- a/PWGEM/Dilepton/Core/EMEventCut.h +++ b/PWGEM/Dilepton/Core/EMEventCut.h @@ -16,6 +16,8 @@ #ifndef PWGEM_DILEPTON_CORE_EMEVENTCUT_H_ #define PWGEM_DILEPTON_CORE_EMEVENTCUT_H_ +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" + #include "Common/CCDB/EventSelectionParams.h" #include "Common/CCDB/TriggerAliases.h" @@ -116,52 +118,52 @@ class EMEventCut : public TNamed return collision.sel8(); case EMEventCuts::kFT0AND: - return collision.selection_bit(o2::aod::evsel::kIsTriggerTVX); + return collision.selection_bit(o2::aod::emevsel::kIsTriggerTVX); case EMEventCuts::kZvtx: return mMinZvtx < collision.posZ() && collision.posZ() < mMaxZvtx; case EMEventCuts::kNoTFB: - return collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder); + return collision.selection_bit(o2::aod::emevsel::kNoTimeFrameBorder); case EMEventCuts::kNoITSROFB: - return collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder); + return collision.selection_bit(o2::aod::emevsel::kNoITSROFrameBorder); case EMEventCuts::kNoSameBunchPileup: - return collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup); + return collision.selection_bit(o2::aod::emevsel::kNoSameBunchPileup); case EMEventCuts::kIsVertexITSTPC: - return collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC); + return collision.selection_bit(o2::aod::emevsel::kIsVertexITSTPC); case EMEventCuts::kIsVertexTOFmatched: - return collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched); + return collision.selection_bit(o2::aod::emevsel::kIsVertexTOFmatched); case EMEventCuts::kIsGoodZvtxFT0vsPV: - return collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV); + return collision.selection_bit(o2::aod::emevsel::kIsGoodZvtxFT0vsPV); case EMEventCuts::kNoCollInTimeRangeStandard: - return collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard); + return collision.selection_bit(o2::aod::emevsel::kNoCollInTimeRangeStandard); case EMEventCuts::kNoCollInTimeRangeStrict: - return collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStrict); + return collision.selection_bit(o2::aod::emevsel::kNoCollInTimeRangeStrict); case EMEventCuts::kNoCollInITSROFStandard: - return collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard); + return collision.selection_bit(o2::aod::emevsel::kNoCollInRofStandard); case EMEventCuts::kNoCollInITSROFStrict: - return collision.selection_bit(o2::aod::evsel::kNoCollInRofStrict); + return collision.selection_bit(o2::aod::emevsel::kNoCollInRofStrict); case EMEventCuts::kNoHighMultCollInPrevRof: - return collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof); + return collision.selection_bit(o2::aod::emevsel::kNoHighMultCollInPrevRof); case EMEventCuts::kIsGoodITSLayer3: - return collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer3); + return collision.selection_bit(o2::aod::emevsel::kIsGoodITSLayer3); case EMEventCuts::kIsGoodITSLayer0123: - return collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer0123); + return collision.selection_bit(o2::aod::emevsel::kIsGoodITSLayer0123); case EMEventCuts::kIsGoodITSLayersAll: - return collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll); + return collision.selection_bit(o2::aod::emevsel::kIsGoodITSLayersAll); default: return true; diff --git a/PWGEM/Dilepton/Core/SingleTrackQC.h b/PWGEM/Dilepton/Core/SingleTrackQC.h index 403c3316ebf..ea22e1b3d0e 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQC.h @@ -922,28 +922,28 @@ struct SingleTrackQC { { for (const auto& collision : collisions) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 1.0); - if (collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + if (collision.selection_bit(o2::aod::emevsel::kIsTriggerTVX)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 2.0); } - if (collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + if (collision.selection_bit(o2::aod::emevsel::kNoTimeFrameBorder)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 3.0); } - if (collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + if (collision.selection_bit(o2::aod::emevsel::kNoITSROFrameBorder)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 4.0); } - if (collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + if (collision.selection_bit(o2::aod::emevsel::kNoSameBunchPileup)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 5.0); } - if (collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + if (collision.selection_bit(o2::aod::emevsel::kIsGoodZvtxFT0vsPV)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 6.0); } - if (collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + if (collision.selection_bit(o2::aod::emevsel::kIsVertexITSTPC)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 7.0); } - if (collision.selection_bit(o2::aod::evsel::kIsVertexTRDmatched)) { + if (collision.selection_bit(o2::aod::emevsel::kIsVertexTRDmatched)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 8.0); } - if (collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) { + if (collision.selection_bit(o2::aod::emevsel::kIsVertexTOFmatched)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 9.0); } if (collision.sel8()) { @@ -952,28 +952,28 @@ struct SingleTrackQC { if (std::fabs(collision.posZ()) < 10.0) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 11.0); } - if (collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + if (collision.selection_bit(o2::aod::emevsel::kNoCollInTimeRangeStandard)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 12.0); } - if (collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStrict)) { + if (collision.selection_bit(o2::aod::emevsel::kNoCollInTimeRangeStrict)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 13.0); } - if (collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { + if (collision.selection_bit(o2::aod::emevsel::kNoCollInRofStandard)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 14.0); } - if (collision.selection_bit(o2::aod::evsel::kNoCollInRofStrict)) { + if (collision.selection_bit(o2::aod::emevsel::kNoCollInRofStrict)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 15.0); } - if (collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { + if (collision.selection_bit(o2::aod::emevsel::kNoHighMultCollInPrevRof)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 16.0); } - if (collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer3)) { + if (collision.selection_bit(o2::aod::emevsel::kIsGoodITSLayer3)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 17.0); } - if (collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer0123)) { + if (collision.selection_bit(o2::aod::emevsel::kIsGoodITSLayer0123)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 18.0); } - if (collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + if (collision.selection_bit(o2::aod::emevsel::kIsGoodITSLayersAll)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 19.0); } if (!fEMEventCut.IsSelected(collision)) { @@ -990,22 +990,22 @@ struct SingleTrackQC { void processBC(aod::EMBCs const& bcs) { for (const auto& bc : bcs) { - if (bc.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + if (bc.selection_bit(o2::aod::emevsel::kIsTriggerTVX)) { fRegistry.fill(HIST("BC/hTVXCounter"), 0.f); - if (bc.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + if (bc.selection_bit(o2::aod::emevsel::kNoTimeFrameBorder)) { fRegistry.fill(HIST("BC/hTVXCounter"), 1.f); } - if (bc.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + if (bc.selection_bit(o2::aod::emevsel::kNoITSROFrameBorder)) { fRegistry.fill(HIST("BC/hTVXCounter"), 2.f); } if (rctChecker(bc)) { fRegistry.fill(HIST("BC/hTVXCounter"), 3.f); } - if (bc.selection_bit(o2::aod::evsel::kNoTimeFrameBorder) && bc.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + if (bc.selection_bit(o2::aod::emevsel::kNoTimeFrameBorder) && bc.selection_bit(o2::aod::emevsel::kNoITSROFrameBorder)) { fRegistry.fill(HIST("BC/hTVXCounter"), 4.f); } - if (bc.selection_bit(o2::aod::evsel::kNoTimeFrameBorder) && bc.selection_bit(o2::aod::evsel::kNoITSROFrameBorder) && rctChecker(bc)) { + if (bc.selection_bit(o2::aod::emevsel::kNoTimeFrameBorder) && bc.selection_bit(o2::aod::emevsel::kNoITSROFrameBorder) && rctChecker(bc)) { fRegistry.fill(HIST("BC/hTVXCounter"), 5.f); } } diff --git a/PWGEM/Dilepton/Core/SingleTrackQCMC.h b/PWGEM/Dilepton/Core/SingleTrackQCMC.h index f60a66b1c81..888102d0090 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQCMC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQCMC.h @@ -1183,28 +1183,28 @@ struct SingleTrackQCMC { { for (const auto& collision : collisions) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 1.0); - if (collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + if (collision.selection_bit(o2::aod::emevsel::kIsTriggerTVX)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 2.0); } - if (collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + if (collision.selection_bit(o2::aod::emevsel::kNoTimeFrameBorder)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 3.0); } - if (collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + if (collision.selection_bit(o2::aod::emevsel::kNoITSROFrameBorder)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 4.0); } - if (collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + if (collision.selection_bit(o2::aod::emevsel::kNoSameBunchPileup)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 5.0); } - if (collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + if (collision.selection_bit(o2::aod::emevsel::kIsGoodZvtxFT0vsPV)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 6.0); } - if (collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + if (collision.selection_bit(o2::aod::emevsel::kIsVertexITSTPC)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 7.0); } - if (collision.selection_bit(o2::aod::evsel::kIsVertexTRDmatched)) { + if (collision.selection_bit(o2::aod::emevsel::kIsVertexTRDmatched)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 8.0); } - if (collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) { + if (collision.selection_bit(o2::aod::emevsel::kIsVertexTOFmatched)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 9.0); } if (collision.sel8()) { @@ -1213,28 +1213,28 @@ struct SingleTrackQCMC { if (std::fabs(collision.posZ()) < 10.0) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 11.0); } - if (collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + if (collision.selection_bit(o2::aod::emevsel::kNoCollInTimeRangeStandard)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 12.0); } - if (collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStrict)) { + if (collision.selection_bit(o2::aod::emevsel::kNoCollInTimeRangeStrict)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 13.0); } - if (collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { + if (collision.selection_bit(o2::aod::emevsel::kNoCollInRofStandard)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 14.0); } - if (collision.selection_bit(o2::aod::evsel::kNoCollInRofStrict)) { + if (collision.selection_bit(o2::aod::emevsel::kNoCollInRofStrict)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 15.0); } - if (collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { + if (collision.selection_bit(o2::aod::emevsel::kNoHighMultCollInPrevRof)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 16.0); } - if (collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer3)) { + if (collision.selection_bit(o2::aod::emevsel::kIsGoodITSLayer3)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 17.0); } - if (collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer0123)) { + if (collision.selection_bit(o2::aod::emevsel::kIsGoodITSLayer0123)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 18.0); } - if (collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + if (collision.selection_bit(o2::aod::emevsel::kIsGoodITSLayersAll)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 19.0); } if (!fEMEventCut.IsSelected(collision)) { @@ -1251,22 +1251,22 @@ struct SingleTrackQCMC { void processBC(aod::EMBCs const& bcs) { for (const auto& bc : bcs) { - if (bc.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + if (bc.selection_bit(o2::aod::emevsel::kIsTriggerTVX)) { fRegistry.fill(HIST("BC/hTVXCounter"), 0.f); - if (bc.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + if (bc.selection_bit(o2::aod::emevsel::kNoTimeFrameBorder)) { fRegistry.fill(HIST("BC/hTVXCounter"), 1.f); } - if (bc.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + if (bc.selection_bit(o2::aod::emevsel::kNoITSROFrameBorder)) { fRegistry.fill(HIST("BC/hTVXCounter"), 2.f); } if (rctChecker(bc)) { fRegistry.fill(HIST("BC/hTVXCounter"), 3.f); } - if (bc.selection_bit(o2::aod::evsel::kNoTimeFrameBorder) && bc.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + if (bc.selection_bit(o2::aod::emevsel::kNoTimeFrameBorder) && bc.selection_bit(o2::aod::emevsel::kNoITSROFrameBorder)) { fRegistry.fill(HIST("BC/hTVXCounter"), 4.f); } - if (bc.selection_bit(o2::aod::evsel::kNoTimeFrameBorder) && bc.selection_bit(o2::aod::evsel::kNoITSROFrameBorder) && rctChecker(bc)) { + if (bc.selection_bit(o2::aod::emevsel::kNoTimeFrameBorder) && bc.selection_bit(o2::aod::emevsel::kNoITSROFrameBorder) && rctChecker(bc)) { fRegistry.fill(HIST("BC/hTVXCounter"), 5.f); } } diff --git a/PWGEM/Dilepton/DataModel/dileptonTables.h b/PWGEM/Dilepton/DataModel/dileptonTables.h index 249af041973..e26f3ef9ab4 100644 --- a/PWGEM/Dilepton/DataModel/dileptonTables.h +++ b/PWGEM/Dilepton/DataModel/dileptonTables.h @@ -66,9 +66,93 @@ const std::unordered_map aliasLabels = { }; } // namespace pwgem::dilepton::swt -DECLARE_SOA_TABLE(EMBCs, "AOD", "EMBC", //! bc information for normalization - o2::soa::Index<>, evsel::Selection, evsel::Rct); -using EMBC = EMBCs::iterator; +namespace emevsel +{ +// Event selection criteria. See O2Physics/Common/CCDB/EventSelectionParams.h +enum EventSelectionFlags { + kIsTriggerTVX = 0, // FT0 vertex (acceptable FT0C-FT0A time difference) at trigger level + kNoITSROFrameBorder, // bunch crossing is far from ITS RO Frame border + kNoTimeFrameBorder, // bunch crossing is far from Time Frame borders + kNoSameBunchPileup, // reject collisions in case of pileup with another collision in the same foundBC + kIsGoodZvtxFT0vsPV, // small difference between z-vertex from PV and from FT0 + kIsVertexITSTPC, // at least one ITS-TPC track (reject vertices built from ITS-only tracks) + kIsVertexTOFmatched, // at least one of vertex contributors is matched to TOF + kIsVertexTRDmatched, // at least one of vertex contributors is matched to TRD + kNoCollInTimeRangeNarrow, // no other collisions in specified time range (narrower than Strict) + kNoCollInTimeRangeStrict, // no other collisions in specified time range + kNoCollInTimeRangeStandard, // no other collisions in specified time range with per-collision multiplicity above threshold + kNoCollInRofStrict, // no other collisions in this Readout Frame + kNoCollInRofStandard, // no other collisions in this Readout Frame with per-collision multiplicity above threshold + kNoHighMultCollInPrevRof, // veto an event if FT0C amplitude in previous ITS ROF is above threshold + kIsGoodITSLayer3, // number of inactive chips on ITS layer 3 is below maximum allowed value + kIsGoodITSLayer0123, // numbers of inactive chips on ITS layers 0-3 are below maximum allowed values + kIsGoodITSLayersAll, // numbers of inactive chips on all ITS layers are below maximum allowed values + kNsel // counter +}; + +DECLARE_SOA_BITMAP_COLUMN(Selection, selection, 32); //! Bitmask of selection flags +DECLARE_SOA_DYNAMIC_COLUMN(Sel8, sel8, [](uint32_t selection_bit) -> bool { return (selection_bit & BIT(o2::aod::emevsel::kIsTriggerTVX)) && (selection_bit & BIT(o2::aod::emevsel::kNoTimeFrameBorder)) && (selection_bit & BIT(o2::aod::emevsel::kNoITSROFrameBorder)); }); + +template +uint32_t reduceSelectionBit(TBC const& bc) +{ + // input should be aod::BcSels or aod::EvSels. + uint32_t bitMap = 0; + if (bc.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + SETBIT(bitMap, o2::aod::emevsel::kIsTriggerTVX); + } + if (bc.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + SETBIT(bitMap, o2::aod::emevsel::kNoTimeFrameBorder); + } + if (bc.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + SETBIT(bitMap, o2::aod::emevsel::kNoITSROFrameBorder); + } + if (bc.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + SETBIT(bitMap, o2::aod::emevsel::kNoSameBunchPileup); + } + if (bc.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + SETBIT(bitMap, o2::aod::emevsel::kIsGoodZvtxFT0vsPV); + } + if (bc.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + SETBIT(bitMap, o2::aod::emevsel::kIsVertexITSTPC); + } + if (bc.selection_bit(o2::aod::evsel::kIsVertexTRDmatched)) { + SETBIT(bitMap, o2::aod::emevsel::kIsVertexTRDmatched); + } + if (bc.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) { + SETBIT(bitMap, o2::aod::emevsel::kIsVertexTOFmatched); + } + if (bc.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + SETBIT(bitMap, o2::aod::emevsel::kNoCollInTimeRangeStandard); + } + if (bc.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStrict)) { + SETBIT(bitMap, o2::aod::emevsel::kNoCollInTimeRangeStrict); + } + if (bc.selection_bit(o2::aod::evsel::kNoCollInTimeRangeNarrow)) { + SETBIT(bitMap, o2::aod::emevsel::kNoCollInTimeRangeNarrow); + } + if (bc.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { + SETBIT(bitMap, o2::aod::emevsel::kNoCollInRofStandard); + } + if (bc.selection_bit(o2::aod::evsel::kNoCollInRofStrict)) { + SETBIT(bitMap, o2::aod::emevsel::kNoCollInRofStrict); + } + if (bc.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { + SETBIT(bitMap, o2::aod::emevsel::kNoHighMultCollInPrevRof); + } + if (bc.selection_bit(o2::aod::evsel::kIsGoodITSLayer3)) { + SETBIT(bitMap, o2::aod::emevsel::kIsGoodITSLayer3); + } + if (bc.selection_bit(o2::aod::evsel::kIsGoodITSLayer0123)) { + SETBIT(bitMap, o2::aod::emevsel::kIsGoodITSLayer0123); + } + if (bc.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + SETBIT(bitMap, o2::aod::emevsel::kIsGoodITSLayersAll); + } + return bitMap; +} + +} // namespace emevsel namespace emevent { @@ -129,12 +213,21 @@ DECLARE_SOA_COLUMN(Q4yBTot, q4ybtot, float); //! DECLARE_SOA_COLUMN(SpherocityPtWeighted, spherocity_ptweighted, float); //! transverse spherocity DECLARE_SOA_COLUMN(SpherocityPtUnWeighted, spherocity_ptunweighted, float); //! transverse spherocity DECLARE_SOA_COLUMN(NtrackSpherocity, ntspherocity, int); -DECLARE_SOA_COLUMN(IsSelected, isSelected, bool); //! MB event selection info -DECLARE_SOA_COLUMN(IsEoI, isEoI, bool); //! lepton or photon exists in MB event (not for CEFP) -DECLARE_SOA_COLUMN(PosX, posX, float); //! only for treeCreatetorML.cxx -DECLARE_SOA_COLUMN(PosY, posY, float); //! only for treeCreatetorML.cxx -DECLARE_SOA_COLUMN(PosZint16, posZint16, int16_t); //! this is only to reduce data size -DECLARE_SOA_COLUMN(CentFT0Cuint16, centFT0Cuint16, uint16_t); //! this is only to reduce data size +DECLARE_SOA_COLUMN(IsSelected, isSelected, bool); //! MB event selection info +DECLARE_SOA_COLUMN(IsEoI, isEoI, bool); //! lepton or photon exists in MB event (not for CEFP) +DECLARE_SOA_COLUMN(PosX, posX, float); //! only for treeCreatetorML.cxx +DECLARE_SOA_COLUMN(PosY, posY, float); //! only for treeCreatetorML.cxx +DECLARE_SOA_COLUMN(PosZint16, posZint16, int16_t); //! this is only to reduce data size +DECLARE_SOA_COLUMN(CentFT0Cuint16, centFT0Cuint16, uint16_t); //! this is only to reduce data size +DECLARE_SOA_COLUMN(PosZint8, posZint8, int8_t); //! this is only to reduce data size +DECLARE_SOA_COLUMN(CentFT0Cuint8, centFT0Cuint8, uint8_t); //! this is only to reduce data size +DECLARE_SOA_COLUMN(CentNTPVuint8, centNTPVuint8, uint8_t); //! this is only to reduce data size +DECLARE_SOA_COLUMN(CentNGlobaluint8, centNGlobaluint8, uint8_t); //! this is only to reduce data size +DECLARE_SOA_COLUMN(CentFT0Muint8, centFT0Muint8, uint8_t); //! this is only to reduce data size +DECLARE_SOA_COLUMN(CentFT0Auint8, centFT0Auint8, uint8_t); //! this is only to reduce data size +// DECLARE_SOA_COLUMN(CentFT0Cuint8, centFT0Cuint8, uint8_t); //! this is only to reduce data size +// DECLARE_SOA_COLUMN(CentNTPVuint8, centNTPVuint8, uint8_t); //! this is only to reduce data size +// DECLARE_SOA_COLUMN(CentNGlobaluint8, centNGlobaluint8, uint8_t); //! this is only to reduce data size DECLARE_SOA_DYNAMIC_COLUMN(PosZ, posZ, [](int16_t posZint16) -> float { return (posZint16 < 0 ? std::nextafter(posZint16 * 0.01f, -std::numeric_limits::infinity()) : std::nextafter(posZint16 * 0.01f, std::numeric_limits::infinity())); }); //! poZ is multiplied by 100 in createEMEventDileton.cxx DECLARE_SOA_DYNAMIC_COLUMN(CentFT0C, centFT0C, [](uint16_t centuint16) -> float { return std::nextafter(centuint16 * 0.002f, std::numeric_limits::infinity()); }); //! centrality is multiplied by 500 in createEMEventDilepton.cxx @@ -162,6 +255,47 @@ DECLARE_SOA_DYNAMIC_COLUMN(EP4BNeg, ep4bneg, [](float q4x, float q4y) -> float { DECLARE_SOA_DYNAMIC_COLUMN(EP4BTot, ep4btot, [](float q4x, float q4y) -> float { return std::atan2(q4y, q4x) / 4.0; }); } // namespace emevent +namespace emeventnorm +{ +DECLARE_SOA_DYNAMIC_COLUMN(PosZ, posZ, [](int8_t posZint8) -> float { return (posZint8 < 0 ? std::nextafter(posZint8 * 0.5f, -std::numeric_limits::infinity()) : std::nextafter(posZint8 * 0.5f, std::numeric_limits::infinity())); }); //! posZ is multiplied by 2 in createEMEventDileton.cxx +DECLARE_SOA_DYNAMIC_COLUMN(CentFT0M, centFT0M, [](uint8_t centuint8) -> float { return centuint8 < 100 ? std::nextafter(centuint8 * 0.01f, std::numeric_limits::infinity()) : std::nextafter(centuint8 - 110.f, std::numeric_limits::infinity()); }); //! centrality is multiplied by 100 in createEMEventDilepton.cxx +DECLARE_SOA_DYNAMIC_COLUMN(CentFT0A, centFT0A, [](uint8_t centuint8) -> float { return centuint8 < 100 ? std::nextafter(centuint8 * 0.01f, std::numeric_limits::infinity()) : std::nextafter(centuint8 - 110.f, std::numeric_limits::infinity()); }); //! centrality is multiplied by 100 in createEMEventDilepton.cxx +DECLARE_SOA_DYNAMIC_COLUMN(CentFT0C, centFT0C, [](uint8_t centuint8) -> float { return centuint8 < 100 ? std::nextafter(centuint8 * 0.01f, std::numeric_limits::infinity()) : std::nextafter(centuint8 - 110.f, std::numeric_limits::infinity()); }); //! centrality is multiplied by 100 in createEMEventDilepton.cxx +DECLARE_SOA_DYNAMIC_COLUMN(CentNTPV, centNTPV, [](uint8_t centuint8) -> float { return centuint8 < 100 ? std::nextafter(centuint8 * 0.01f, std::numeric_limits::infinity()) : std::nextafter(centuint8 - 110.f, std::numeric_limits::infinity()); }); //! centrality is multiplied by 100 in createEMEventDilepton.cxx +DECLARE_SOA_DYNAMIC_COLUMN(CentNGlobal, centNGlobal, [](uint8_t centuint8) -> float { return centuint8 < 100 ? std::nextafter(centuint8 * 0.01f, std::numeric_limits::infinity()) : std::nextafter(centuint8 - 110.f, std::numeric_limits::infinity()); }); //! centrality is multiplied by 100 in createEMEventDilepton.cxx +} // namespace emeventnorm + +// namespace emcent +// { +// DECLARE_SOA_COLUMN(CentFT0Muint8, centFT0Muint8, uint8_t); //! this is only to reduce data size +// DECLARE_SOA_COLUMN(CentFT0Auint8, centFT0Auint8, uint8_t); //! this is only to reduce data size +// DECLARE_SOA_COLUMN(CentFT0Cuint8, centFT0Cuint8, uint8_t); //! this is only to reduce data size +// DECLARE_SOA_COLUMN(CentNTPVuint8, centNTPVuint8, uint8_t); //! this is only to reduce data size +// DECLARE_SOA_COLUMN(CentNGlobaluint8, centNGlobaluint8, uint8_t); //! this is only to reduce data size +// +// DECLARE_SOA_EXPRESSION_COLUMN(CentFT0A, centFT0A, float, 1.f * centFT0Auint8); // this must be inverse of calculation in createEMEventDilepton.cxx +// DECLARE_SOA_EXPRESSION_COLUMN(CentFT0M, centFT0M, float, 1.f * centFT0Muint8); // this must be inverse of calculation in createEMEventDilepton.cxx +// DECLARE_SOA_EXPRESSION_COLUMN(CentFT0C, centFT0C, float, 1.f * centFT0Cuint8); // this must be inverse of calculation in createEMEventDilepton.cxx +// DECLARE_SOA_EXPRESSION_COLUMN(CentNTPV, centNTPV, float, 1.f * centNTPVuint8); // this must be inverse of calculation in createEMEventDilepton.cxx +// DECLARE_SOA_EXPRESSION_COLUMN(CentNGlobal, centNGlobal, float, 1.f * centNGlobaluint8); // this must be inverse of calculation in createEMEventDilepton.cxx +// +// // DECLARE_SOA_EXPRESSION_COLUMN(CentFT0A, centFT0A, float, (centFT0Auint8 < 100) ? std::nextafter((1.f * centFT0Auint8) / 100.f, std::numeric_limits::infinity()) : std::nextafter((1.f * centFT0Auint8) - 110.f, std::numeric_limits::infinity())); // this must be inverse of calculation in createEMEventDilepton.cxx +// // DECLARE_SOA_EXPRESSION_COLUMN(CentFT0M, centFT0M, float, (centFT0Muint8 < 100) ? std::nextafter((1.f * centFT0Muint8) / 100.f, std::numeric_limits::infinity()) : std::nextafter((1.f * centFT0Muint8) - 110.f, std::numeric_limits::infinity())); // this must be inverse of calculation in createEMEventDilepton.cxx +// // DECLARE_SOA_EXPRESSION_COLUMN(CentFT0C, centFT0C, float, (centFT0Cuint8 < 100) ? std::nextafter((1.f * centFT0Cuint8) / 100.f, std::numeric_limits::infinity()) : std::nextafter((1.f * centFT0Cuint8) - 110.f, std::numeric_limits::infinity())); // this must be inverse of calculation in createEMEventDilepton.cxx +// // DECLARE_SOA_EXPRESSION_COLUMN(CentNTPV, centNTPV, float, (centNTPVuint8 < 100) ? std::nextafter((1.f * centNTPVuint8) / 100.f, std::numeric_limits::infinity()) : std::nextafter((1.f * centNTPVuint8) - 110.f, std::numeric_limits::infinity())); // this must be inverse of calculation in createEMEventDilepton.cxx +// // DECLARE_SOA_EXPRESSION_COLUMN(CentNGlobal, centNGlobal, float, (centNGlobaluint8 < 100) ? std::nextafter((1.f * centNGlobaluint8) / 100.f, std::numeric_limits::infinity()) : std::nextafter((1.f * centNGlobaluint8) - 110.f, std::numeric_limits::infinity())); // this must be inverse of calculation in createEMEventDilepton.cxx +// +// } // namespace emcent + +DECLARE_SOA_TABLE(EMBCs_000, "AOD", "EMBC", //! bc information for normalization + o2::soa::Index<>, evsel::Selection, evsel::Rct); + +DECLARE_SOA_TABLE_VERSIONED(EMBCs_001, "AOD", "EMBC", 1, //! bc information for normalization + o2::soa::Index<>, emevsel::Selection, evsel::Rct); + +using EMBCs = EMBCs_001; +using EMBC = EMBCs::iterator; + DECLARE_SOA_TABLE_VERSIONED(EMEvents_001, "AOD", "EMEVENT", 1, //! Main event information table o2::soa::Index<>, emevent::CollisionId, bc::RunNumber, bc::GlobalBC, evsel::Alias, evsel::Selection, timestamp::Timestamp, collision::PosX, collision::PosY, collision::PosZ, @@ -182,7 +316,12 @@ DECLARE_SOA_TABLE_VERSIONED(EMEvents_004, "AOD", "EMEVENT", 4, //! Main event collision::PosZ, collision::NumContrib, evsel::NumTracksInTimeRange, evsel::SumAmpFT0CInTimeRange, emevent::Sel8); -using EMEvents = EMEvents_004; +DECLARE_SOA_TABLE_VERSIONED(EMEvents_005, "AOD", "EMEVENT", 5, //! Main event information table + o2::soa::Index<>, emevent::CollisionId, bc::RunNumber, bc::GlobalBC, emevsel::Selection, evsel::Rct, timestamp::Timestamp, + collision::PosZ, + collision::NumContrib, evsel::NumTracksInTimeRange, evsel::SumAmpFT0CInTimeRange, emevsel::Sel8); + +using EMEvents = EMEvents_005; using EMEvent = EMEvents::iterator; DECLARE_SOA_TABLE_VERSIONED(EMEventsAlias_000, "AOD", "EMEVENTALIAS", 0, evsel::Alias) //! joinable to EMEvents @@ -199,15 +338,38 @@ using EMEventCov = EMEventsCov::iterator; DECLARE_SOA_TABLE(EMEventsBz, "AOD", "EMEVENTBZ", emevent::Bz); // joinable to EMEvents using EMEventBz = EMEventsBz::iterator; -DECLARE_SOA_TABLE(EMEventsMult, "AOD", "EMEVENTMULT", //! event multiplicity table, joinable to EMEvents +DECLARE_SOA_TABLE(EMEventsMult_000, "AOD", "EMEVENTMULT", //! event multiplicity table, joinable to EMEvents mult::MultFT0A, mult::MultFT0C, mult::MultNTracksPV, mult::MultNTracksPVeta1, mult::MultNTracksPVetaHalf, mult::IsInelGt0, mult::IsInelGt1, mult::MultFT0M); + +DECLARE_SOA_TABLE_VERSIONED(EMEventsMult_001, "AOD", "EMEVENTMULT", 1, //! event multiplicity table, joinable to EMEvents + mult::MultFT0A, mult::MultFT0C, mult::MultNTracksPV, /*mult::MultNTracksGlobal,*/ + mult::MultFT0M); + +using EMEventsMult = EMEventsMult_001; using EMEventMult = EMEventsMult::iterator; -DECLARE_SOA_TABLE(EMEventsCent, "AOD", "EMEVENTCENT", //! event centrality table, joinable to EMEvents +DECLARE_SOA_TABLE(EMEventsCent_000, "AOD", "EMEVENTCENT", //! event centrality table, joinable to EMEvents cent::CentFT0M, cent::CentFT0A, cent::CentFT0C); + +DECLARE_SOA_TABLE_VERSIONED(EMEventsCent_001, "AOD", "EMEVENTCENT", 1, //! event centrality table stored in AO2D + cent::CentFT0M, cent::CentFT0A, cent::CentFT0C, cent::CentNTPV /*, cent::CentNGlobal*/); + +using EMEventsCent = EMEventsCent_001; using EMEventCent = EMEventsCent::iterator; +// DECLARE_SOA_TABLE_VERSIONED(EMEventsCentBase_001, "AOD", "EMEVENTCENT", 1, //! event centrality table stored in AO2D +// emcent::CentFT0Muint8, emcent::CentFT0Auint8, emcent::CentFT0Cuint8, emcent::CentNTPVuint8, emcent::CentNGlobaluint8); +// +// using EMEventsCentBase = EMEventsCentBase_001; +// using EMEventCentBase = EMEventsCentBase::iterator; +// +// // Extended table with expression columns that can be used for Filter. +// DECLARE_SOA_EXTENDED_TABLE_USER(EMEventsCent, EMEventsCentBase, "EMCENTEXT", +// emcent::CentFT0M, emcent::CentFT0A, emcent::CentFT0C, emcent::CentNTPV, emcent::CentNGlobal); +// +// using EMEventCent = EMEventsCent::iterator; + DECLARE_SOA_TABLE_VERSIONED(EMEventsQvec_000, "AOD", "EMEVENTQVEC", 0, //! event q vector table, joinable to EMEvents emevent::Q2xFT0M, emevent::Q2yFT0M, emevent::Q2xFT0A, emevent::Q2yFT0A, emevent::Q2xFT0C, emevent::Q2yFT0C, emevent::Q2xBPos, emevent::Q2yBPos, emevent::Q2xBNeg, emevent::Q2yBNeg, emevent::Q2xBTot, emevent::Q2yBTot, @@ -255,6 +417,38 @@ DECLARE_SOA_TABLE_VERSIONED(EMEventsQvec_001, "AOD", "EMEVENTQVEC", 1, //! Mai using EMEventsQvec = EMEventsQvec_001; using EMEventQvec = EMEventsQvec::iterator; +DECLARE_SOA_TABLE_VERSIONED(EMEventsQvec2_000, "AOD", "EMEVENTQVEC2", 0, //! Main event information table + emevent::Q2xFT0M, emevent::Q2yFT0M, emevent::Q2xFT0A, emevent::Q2yFT0A, emevent::Q2xFT0C, emevent::Q2yFT0C, + emevent::Q2xFV0A, emevent::Q2yFV0A, + emevent::Q2xBPos, emevent::Q2yBPos, emevent::Q2xBNeg, emevent::Q2yBNeg, emevent::Q2xBTot, emevent::Q2yBTot, + // Dynamic columns + emevent::EP2FT0M, + emevent::EP2FT0A, + emevent::EP2FT0C, + emevent::EP2FV0A, + emevent::EP2BPos, + emevent::EP2BNeg, + emevent::EP2BTot); + +using EMEventsQvec2 = EMEventsQvec2_000; +using EMEventQvec2 = EMEventsQvec2::iterator; + +DECLARE_SOA_TABLE_VERSIONED(EMEventsQvec3_000, "AOD", "EMEVENTQVEC3", 0, //! Main event information table + emevent::Q3xFT0M, emevent::Q3yFT0M, emevent::Q3xFT0A, emevent::Q3yFT0A, emevent::Q3xFT0C, emevent::Q3yFT0C, + emevent::Q3xFV0A, emevent::Q3yFV0A, + emevent::Q3xBPos, emevent::Q3yBPos, emevent::Q3xBNeg, emevent::Q3yBNeg, emevent::Q3xBTot, emevent::Q3yBTot, + // Dynamic columns + emevent::EP3FT0M, + emevent::EP3FT0A, + emevent::EP3FT0C, + emevent::EP3FV0A, + emevent::EP3BPos, + emevent::EP3BNeg, + emevent::EP3BTot); + +using EMEventsQvec3 = EMEventsQvec3_000; +using EMEventQvec3 = EMEventsQvec3::iterator; + DECLARE_SOA_TABLE(EMSWTriggerBits, "AOD", "EMSWTBIT", emevent::SWTAlias, o2::soa::Marker<1>); //! joinable to EMEvents using EMSWTriggerBit = EMSWTriggerBits::iterator; @@ -301,7 +495,12 @@ DECLARE_SOA_TABLE_VERSIONED(EMEventNormInfos_000, "AOD", "EMEVENTNORMINFO", 0, / DECLARE_SOA_TABLE_VERSIONED(EMEventNormInfos_001, "AOD", "EMEVENTNORMINFO", 1, //! event information for normalization o2::soa::Index<>, evsel::Selection, evsel::Rct, emevent::PosZint16, emevent::CentFT0Cuint16, emevent::Sel8, emevent::PosZ, emevent::CentFT0C, o2::soa::Marker<1>); -using EMEventNormInfos = EMEventNormInfos_001; + +DECLARE_SOA_TABLE_VERSIONED(EMEventNormInfos_002, "AOD", "EMEVENTNORMINFO", 2, //! event information for normalization + emevsel::Selection, evsel::Rct, emevent::PosZint8, emevent::CentFT0Muint8, emevent::CentFT0Cuint8, emevent::CentNTPVuint8, /*emevent::CentNGlobaluint8,*/ + emevsel::Sel8, emeventnorm::PosZ, emeventnorm::CentFT0M, emeventnorm::CentFT0C, emeventnorm::CentNTPV, /*emeventnorm::CentNTPV,*/ o2::soa::Marker<1>); + +using EMEventNormInfos = EMEventNormInfos_002; using EMEventNormInfo = EMEventNormInfos::iterator; namespace emmcevent @@ -960,9 +1159,9 @@ DECLARE_SOA_TABLE_VERSIONED(EMThinEvents_000, "AOD", "EMTHINEVENT", 0, //! Thin using EMThinEvents = EMThinEvents_000; using EMThinEvent = EMThinEvents::iterator; -DECLARE_SOA_TABLE_VERSIONED(EMThinEventNormInfos_000, "AOD", "EMTHINEVENTNORM", 0, //! event information for normalization - o2::soa::Index<>, evsel::Selection, evsel::Rct, emevent::PosZint16, emevent::CentFT0Cuint16, - emevent::Sel8, emevent::PosZ, emevent::CentFT0C, o2::soa::Marker<2>); +DECLARE_SOA_TABLE_VERSIONED(EMThinEventNormInfos_000, "AOD", "EMTHINEVENTNORM", 0, //! event information for normalization + o2::soa::Index<>, emevsel::Selection, evsel::Rct, emevent::PosZint8, emevent::CentFT0Muint8, emevent::CentFT0Cuint8, emevent::CentNTPVuint8, /*emevent::CentNGlobaluint8,*/ + emevsel::Sel8, emeventnorm::PosZ, emeventnorm::CentFT0M, emeventnorm::CentFT0C, emeventnorm::CentNTPV, /*emeventnorm::CentNGlobal,*/ o2::soa::Marker<2>); using EMThinEventNormInfos = EMThinEventNormInfos_000; using EMThinEventNormInfo = EMThinEventNormInfos::iterator; diff --git a/PWGEM/Dilepton/TableProducer/CMakeLists.txt b/PWGEM/Dilepton/TableProducer/CMakeLists.txt index 66715bbefa3..109248797d6 100644 --- a/PWGEM/Dilepton/TableProducer/CMakeLists.txt +++ b/PWGEM/Dilepton/TableProducer/CMakeLists.txt @@ -91,3 +91,13 @@ o2physics_add_dpl_workflow(qvector-dummy-otf PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(qvector2-dummy-otf + SOURCES qVector2DummyOTF.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(qvector3-dummy-otf + SOURCES qVector3DummyOTF.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + diff --git a/PWGEM/Dilepton/TableProducer/Converters/CMakeLists.txt b/PWGEM/Dilepton/TableProducer/Converters/CMakeLists.txt index eea03e885e6..9d130209e72 100644 --- a/PWGEM/Dilepton/TableProducer/Converters/CMakeLists.txt +++ b/PWGEM/Dilepton/TableProducer/Converters/CMakeLists.txt @@ -25,6 +25,11 @@ o2physics_add_dpl_workflow(event-converter4 PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(event-converter5 + SOURCES eventConverter5.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(electron-converter2 SOURCES electronConverter2.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore @@ -70,3 +75,33 @@ o2physics_add_dpl_workflow(event-norm-converter1 PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(event-norm-converter2 + SOURCES eventNormConverter2.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(event-mult-converter1 + SOURCES eventMultConverter1.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(event-cent-converter1 + SOURCES eventCentConverter1.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(qvec2-converter0 + SOURCES qvec2Converter0.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(qvec3-converter0 + SOURCES qvec3Converter0.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(bc-converter1 + SOURCES bcConverter1.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + diff --git a/PWGEM/PhotonMeson/Tasks/diphotonHadronMPCPCMDalitzEE.cxx b/PWGEM/Dilepton/TableProducer/Converters/bcConverter1.cxx similarity index 61% rename from PWGEM/PhotonMeson/Tasks/diphotonHadronMPCPCMDalitzEE.cxx rename to PWGEM/Dilepton/TableProducer/Converters/bcConverter1.cxx index a3a7b548894..43c3cf43e24 100644 --- a/PWGEM/PhotonMeson/Tasks/diphotonHadronMPCPCMDalitzEE.cxx +++ b/PWGEM/Dilepton/TableProducer/Converters/bcConverter1.cxx @@ -11,26 +11,33 @@ // // ======================== // -// This code loops over photons and makes pairs for neutral mesons analyses. +// This code runs loop over ULS ee pars for virtual photon QC. // Please write to: daiki.sekihata@cern.ch -#include "PWGEM/PhotonMeson/Core/DiphotonHadronMPC.h" -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGEM/PhotonMeson/Utils/PairUtilities.h" - -#include "Common/Core/RecoDecay.h" +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" #include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" using namespace o2; using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +struct bcConverter1 { + Produces bc_001; + + void process(aod::EMBCs_000 const& bcs) + { + for (const auto& bc : bcs) { + bc_001(o2::aod::emevsel::reduceSelectionBit(bc), bc.rct_raw()); + } // end of bc loop + } +}; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - return WorkflowSpec{ - adaptAnalysisTask>(cfgc, TaskName{"diphoton-hadron-mpc-pcmdalitzee"}), - }; + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"bc-converter1"})}; } diff --git a/PWGEM/Dilepton/TableProducer/Converters/eventCentConverter1.cxx b/PWGEM/Dilepton/TableProducer/Converters/eventCentConverter1.cxx new file mode 100644 index 00000000000..559c871dd1a --- /dev/null +++ b/PWGEM/Dilepton/TableProducer/Converters/eventCentConverter1.cxx @@ -0,0 +1,47 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +// +// ======================== +// +// This code runs loop over ULS ee pars for virtual photon QC. +// Please write to: daiki.sekihata@cern.ch + +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" + +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +struct eventCentConverter1 { + Produces cent_001; + + void process(aod::EMEventsCent_000 const& collisions) + { + for (const auto& collision : collisions) { + cent_001( + collision.centFT0M(), + collision.centFT0A(), + collision.centFT0C(), + 105.f); + } // end of collision loop + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"event-cent-converter1"})}; +} diff --git a/PWGEM/Dilepton/TableProducer/Converters/eventConverter5.cxx b/PWGEM/Dilepton/TableProducer/Converters/eventConverter5.cxx new file mode 100644 index 00000000000..59227518b1a --- /dev/null +++ b/PWGEM/Dilepton/TableProducer/Converters/eventConverter5.cxx @@ -0,0 +1,113 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +// +// ======================== +// +// This code runs loop over ULS ee pars for virtual photon QC. +// Please write to: daiki.sekihata@cern.ch + +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" + +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +struct eventConverter5 { + Produces event_005; + + // template + // uint32_t reduceSelectionBit(TBC const& bc) + // { + // //input should be aod::BcSels or aod::EvSels. + // uint32_t bitMap = 0; + // if (bc.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + // SETBIT(bitMap, o2::aod::emevsel::kIsTriggerTVX); + // } + // if (bc.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + // SETBIT(bitMap, o2::aod::emevsel::kNoTimeFrameBorder); + // } + // if (bc.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + // SETBIT(bitMap, o2::aod::emevsel::kNoITSROFrameBorder); + // } + // if (bc.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + // SETBIT(bitMap, o2::aod::emevsel::kNoSameBunchPileup); + // } + // if (bc.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + // SETBIT(bitMap, o2::aod::emevsel::kIsGoodZvtxFT0vsPV); + // } + // if (bc.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + // SETBIT(bitMap, o2::aod::emevsel::kIsVertexITSTPC); + // } + // if (bc.selection_bit(o2::aod::evsel::kIsVertexTRDmatched)) { + // SETBIT(bitMap, o2::aod::emevsel::kIsVertexTRDmatched); + // } + // if (bc.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) { + // SETBIT(bitMap, o2::aod::emevsel::kIsVertexTOFmatched); + // } + // if (bc.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + // SETBIT(bitMap, o2::aod::emevsel::kNoCollInTimeRangeStandard); + // } + // if (bc.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStrict)) { + // SETBIT(bitMap, o2::aod::emevsel::kNoCollInTimeRangeStandard); + // } + // if (bc.selection_bit(o2::aod::evsel::kNoCollInTimeRangeNarrow)) { + // SETBIT(bitMap, o2::aod::emevsel::kNoCollInTimeRangeNarrow); + // } + // if (bc.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { + // SETBIT(bitMap, o2::aod::emevsel::kNoCollInRofStandard); + // } + // if (bc.selection_bit(o2::aod::evsel::kNoCollInRofStrict)) { + // SETBIT(bitMap, o2::aod::emevsel::kNoCollInRofStrict); + // } + // if (bc.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { + // SETBIT(bitMap, o2::aod::emevsel::kNoHighMultCollInPrevRof); + // } + // if (bc.selection_bit(o2::aod::evsel::kIsGoodITSLayer3)) { + // SETBIT(bitMap, o2::aod::emevsel::kIsGoodITSLayer3); + // } + // if (bc.selection_bit(o2::aod::evsel::kIsGoodITSLayer0123)) { + // SETBIT(bitMap, o2::aod::emevsel::kIsGoodITSLayer0123); + // } + // if (bc.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + // SETBIT(bitMap, o2::aod::emevsel::kIsGoodITSLayersAll); + // } + // return bitMap; + // } + + void process004to005(aod::EMEvents_004 const& collisions) + { + for (const auto& collision : collisions) { + event_005( + collision.globalIndex(), + collision.runNumber(), + collision.globalBC(), + o2::aod::emevsel::reduceSelectionBit(collision), + collision.rct_raw(), + collision.timestamp(), + collision.posZ(), + collision.numContrib(), + collision.trackOccupancyInTimeRange(), + collision.ft0cOccupancyInTimeRange()); + } // end of collision loop + } + PROCESS_SWITCH(eventConverter5, process004to005, "convert from 004 into 005", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"event-converter5"})}; +} diff --git a/PWGEM/Dilepton/TableProducer/Converters/eventMultConverter1.cxx b/PWGEM/Dilepton/TableProducer/Converters/eventMultConverter1.cxx new file mode 100644 index 00000000000..0682d607675 --- /dev/null +++ b/PWGEM/Dilepton/TableProducer/Converters/eventMultConverter1.cxx @@ -0,0 +1,46 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +// +// ======================== +// +// This code runs loop over ULS ee pars for virtual photon QC. +// Please write to: daiki.sekihata@cern.ch + +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" + +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +struct eventMultConverter1 { + Produces mult_001; + + void process(aod::EMEventsMult_000 const& collisions) + { + for (const auto& collision : collisions) { + mult_001( + collision.multFT0A(), + collision.multFT0C(), + collision.multNTracksPV()); + } // end of mult row loop + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"event-mult-converter1"})}; +} diff --git a/PWGEM/Dilepton/TableProducer/Converters/eventNormConverter2.cxx b/PWGEM/Dilepton/TableProducer/Converters/eventNormConverter2.cxx new file mode 100644 index 00000000000..c782ef2cd4f --- /dev/null +++ b/PWGEM/Dilepton/TableProducer/Converters/eventNormConverter2.cxx @@ -0,0 +1,59 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +// +// ======================== +// +// This code runs loop over ULS ee pars for virtual photon QC. +// Please write to: daiki.sekihata@cern.ch + +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" + +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +struct eventNormConverter2 { + Produces event_002; + + void process(aod::EMEventNormInfos_001 const& collisions) + { + for (const auto& collision : collisions) { + + int8_t posZint8 = static_cast(collision.posZ() * 2.f); + if (posZint8 == 0) { + if (collision.posZ() < 0.f) { + posZint8 = -1; + } else { + posZint8 = +1; + } + } + + event_002( + o2::aod::emevsel::reduceSelectionBit(collision), + collision.rct_raw(), + posZint8, + 105 + 110, + collision.centFT0C() < 1.f ? static_cast(collision.centFT0C() * 100.f) : static_cast(collision.centFT0C() + 110.f), + 105 + 110); + } // end of collision loop + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"event-norm-converter2"})}; +} diff --git a/PWGEM/Dilepton/TableProducer/Converters/qvec2Converter0.cxx b/PWGEM/Dilepton/TableProducer/Converters/qvec2Converter0.cxx new file mode 100644 index 00000000000..21342c4468b --- /dev/null +++ b/PWGEM/Dilepton/TableProducer/Converters/qvec2Converter0.cxx @@ -0,0 +1,50 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +// +// ======================== +// +// This code converts q vector table into qvec2 table. +// Please write to: daiki.sekihata@cern.ch + +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" + +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +struct qvec2Converter0 { + Produces qvec2_000; + + void process(aod::EMEventsQvec_001 const& collisions) + { + for (const auto& collision : collisions) { + qvec2_000( + collision.q2xft0m(), collision.q2yft0m(), + collision.q2xft0a(), collision.q2yft0a(), + collision.q2xft0c(), collision.q2yft0c(), + collision.q2xfv0a(), collision.q2yfv0a(), + collision.q2xbpos(), collision.q2ybpos(), + collision.q2xbneg(), collision.q2ybneg(), + collision.q2xbtot(), collision.q2ybtot()); + } // end of collision loop + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"qvec2-converter0"})}; +} diff --git a/PWGEM/Dilepton/TableProducer/Converters/qvec3Converter0.cxx b/PWGEM/Dilepton/TableProducer/Converters/qvec3Converter0.cxx new file mode 100644 index 00000000000..cc35b94bec3 --- /dev/null +++ b/PWGEM/Dilepton/TableProducer/Converters/qvec3Converter0.cxx @@ -0,0 +1,50 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +// +// ======================== +// +// This code converts q vector table into qvec3 table. +// Please write to: daiki.sekihata@cern.ch + +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" + +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +struct qvec3Converter0 { + Produces qvec3_000; + + void process(aod::EMEventsQvec_001 const& collisions) + { + for (const auto& collision : collisions) { + qvec3_000( + collision.q3xft0m(), collision.q3yft0m(), + collision.q3xft0a(), collision.q3yft0a(), + collision.q3xft0c(), collision.q3yft0c(), + collision.q3xfv0a(), collision.q3yfv0a(), + collision.q3xbpos(), collision.q3ybpos(), + collision.q3xbneg(), collision.q3ybneg(), + collision.q3xbtot(), collision.q3ybtot()); + } // end of collision loop + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"qvec3-converter0"})}; +} diff --git a/PWGEM/Dilepton/TableProducer/associateMCinfoDilepton.cxx b/PWGEM/Dilepton/TableProducer/associateMCinfoDilepton.cxx index 1b4044f4bf3..e60f9b54365 100644 --- a/PWGEM/Dilepton/TableProducer/associateMCinfoDilepton.cxx +++ b/PWGEM/Dilepton/TableProducer/associateMCinfoDilepton.cxx @@ -15,7 +15,7 @@ // Please write to: daiki.sekihata@cern.ch #include "PWGEM/Dilepton/DataModel/dileptonTables.h" -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +// #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "Common/Core/TableHelper.h" @@ -39,7 +39,7 @@ struct AssociateMCInfoDilepton { enum SubSystem { kElectron = 0x1, kFwdMuon = 0x2, - kPCM = 0x4, + // kPCM = 0x4, }; using MyCollisionsMC = soa::Join; @@ -51,7 +51,7 @@ struct AssociateMCInfoDilepton { Produces mceventlabels; Produces emmcparticles; Produces emmcgenvms; - Produces v0legmclabels; + // Produces v0legmclabels; Produces emprimaryelectronmclabels; Produces emprimarymuonmclabels; Produces emmftmclabels; @@ -130,7 +130,7 @@ struct AssociateMCInfoDilepton { SliceCache cache; Preslice perMcCollision = aod::mcparticle::mcCollisionId; - Preslice perCollision_pcm = aod::v0photonkf::collisionId; + // Preslice perCollision_pcm = aod::v0photonkf::collisionId; Preslice perCollision_el = aod::emprimaryelectron::collisionId; Preslice perCollision_mu = aod::emprimarymuon::collisionId; @@ -140,7 +140,7 @@ struct AssociateMCInfoDilepton { Partition mcvectormesons = o2::aod::mcparticle::pdgCode == 223 || o2::aod::mcparticle::pdgCode == 333; template - void skimmingMC(MyCollisionsMC const& collisions, aod::BCs const&, aod::McCollisions const& mcCollisions, aod::McParticles const& mcTracks, TTracks const& o2tracks, TFwdTracks const& o2fwdtracks, TMFTTracks const&, TPCMs const& v0photons, TPCMLegs const&, TEMPrimaryElectrons const& emprimaryelectrons, TEMPrimaryMuons const& emprimarymuons) + void skimmingMC(MyCollisionsMC const& collisions, aod::BCs const&, aod::McCollisions const& mcCollisions, aod::McParticles const& mcTracks, TTracks const& o2tracks, TFwdTracks const& o2fwdtracks, TMFTTracks const&, TPCMs const&, TPCMLegs const&, TEMPrimaryElectrons const& emprimaryelectrons, TEMPrimaryMuons const& emprimarymuons) { // temporary variables used for the indexing of the skimmed MC stack std::map fNewLabels; @@ -359,68 +359,68 @@ struct AssociateMCInfoDilepton { } // end of mc collision loop - if constexpr (static_cast(system & kPCM)) { - for (const auto& v0 : v0photons) { - auto collision_from_v0 = collisions.iteratorAt(v0.collisionId()); - if (!collision_from_v0.has_mcCollision()) { - continue; - } - - auto ele = v0.template negTrack_as(); - auto pos = v0.template posTrack_as(); - - auto o2track_ele = o2tracks.iteratorAt(ele.trackId()); - auto o2track_pos = o2tracks.iteratorAt(pos.trackId()); - - if (!o2track_ele.has_mcParticle() || !o2track_pos.has_mcParticle()) { - continue; // If no MC particle is found, skip the v0 - } - - for (const auto& leg : {pos, ele}) { // be carefull of order {pos, ele}! - auto o2track = o2tracks.iteratorAt(leg.trackId()); - auto mctrack = o2track.template mcParticle_as(); - // LOGF(info, "mctrack.globalIndex() = %d, mctrack.index() = %d", mctrack.globalIndex(), mctrack.index()); // these are exactly the same. - - // if the MC truth particle corresponding to this reconstructed track which is not already written, add it to the skimmed MC stack - if (!(fNewLabels.find(mctrack.globalIndex()) != fNewLabels.end())) { - fNewLabels[mctrack.globalIndex()] = fCounters[0]; - fNewLabelsReversed[fCounters[0]] = mctrack.globalIndex(); - // fMCFlags[mctrack.globalIndex()] = mcflags; - fEventIdx[mctrack.globalIndex()] = fEventLabels.find(mctrack.mcCollisionId())->second; - fCounters[0]++; - } - v0legmclabels(fNewLabels.find(mctrack.index())->second, o2track.mcMask()); - - // Next, store mother-chain of this reconstructed track. - int motherid = -999; // first mother index - if (mctrack.has_mothers()) { - motherid = mctrack.mothersIds()[0]; // first mother index - } - while (motherid > -1) { - if (motherid < mcTracks.size()) { // protect against bad mother indices. why is this needed? - auto mp = mcTracks.iteratorAt(motherid); - - // if the MC truth particle corresponding to this reconstructed track which is not already written, add it to the skimmed MC stack - if (!(fNewLabels.find(mp.globalIndex()) != fNewLabels.end())) { - fNewLabels[mp.globalIndex()] = fCounters[0]; - fNewLabelsReversed[fCounters[0]] = mp.globalIndex(); - // fMCFlags[mp.globalIndex()] = mcflags; - fEventIdx[mp.globalIndex()] = fEventLabels.find(mp.mcCollisionId())->second; - fCounters[0]++; - } - - if (mp.has_mothers()) { - motherid = mp.mothersIds()[0]; // first mother index - } else { - motherid = -999; - } - } else { - motherid = -999; - } - } // end of mother chain loop - } // end of leg loop - } // end of v0 loop - } + // if constexpr (static_cast(system & kPCM)) { + // for (const auto& v0 : v0photons) { + // auto collision_from_v0 = collisions.iteratorAt(v0.collisionId()); + // if (!collision_from_v0.has_mcCollision()) { + // continue; + // } + + // auto ele = v0.template negTrack_as(); + // auto pos = v0.template posTrack_as(); + + // auto o2track_ele = o2tracks.iteratorAt(ele.trackId()); + // auto o2track_pos = o2tracks.iteratorAt(pos.trackId()); + + // if (!o2track_ele.has_mcParticle() || !o2track_pos.has_mcParticle()) { + // continue; // If no MC particle is found, skip the v0 + // } + + // for (const auto& leg : {pos, ele}) { // be carefull of order {pos, ele}! + // auto o2track = o2tracks.iteratorAt(leg.trackId()); + // auto mctrack = o2track.template mcParticle_as(); + // // LOGF(info, "mctrack.globalIndex() = %d, mctrack.index() = %d", mctrack.globalIndex(), mctrack.index()); // these are exactly the same. + + // // if the MC truth particle corresponding to this reconstructed track which is not already written, add it to the skimmed MC stack + // if (!(fNewLabels.find(mctrack.globalIndex()) != fNewLabels.end())) { + // fNewLabels[mctrack.globalIndex()] = fCounters[0]; + // fNewLabelsReversed[fCounters[0]] = mctrack.globalIndex(); + // // fMCFlags[mctrack.globalIndex()] = mcflags; + // fEventIdx[mctrack.globalIndex()] = fEventLabels.find(mctrack.mcCollisionId())->second; + // fCounters[0]++; + // } + // v0legmclabels(fNewLabels.find(mctrack.index())->second, o2track.mcMask()); + + // // Next, store mother-chain of this reconstructed track. + // int motherid = -999; // first mother index + // if (mctrack.has_mothers()) { + // motherid = mctrack.mothersIds()[0]; // first mother index + // } + // while (motherid > -1) { + // if (motherid < mcTracks.size()) { // protect against bad mother indices. why is this needed? + // auto mp = mcTracks.iteratorAt(motherid); + + // // if the MC truth particle corresponding to this reconstructed track which is not already written, add it to the skimmed MC stack + // if (!(fNewLabels.find(mp.globalIndex()) != fNewLabels.end())) { + // fNewLabels[mp.globalIndex()] = fCounters[0]; + // fNewLabelsReversed[fCounters[0]] = mp.globalIndex(); + // // fMCFlags[mp.globalIndex()] = mcflags; + // fEventIdx[mp.globalIndex()] = fEventLabels.find(mp.mcCollisionId())->second; + // fCounters[0]++; + // } + + // if (mp.has_mothers()) { + // motherid = mp.mothersIds()[0]; // first mother index + // } else { + // motherid = -999; + // } + // } else { + // motherid = -999; + // } + // } // end of mother chain loop + // } // end of leg loop + // } // end of v0 loop + // } if constexpr (static_cast(system & kElectron)) { // auto emprimaryelectrons_coll = emprimaryelectrons.sliceBy(perCollision_el, collision.globalIndex()); @@ -683,22 +683,22 @@ struct AssociateMCInfoDilepton { skimmingMC(collisions, bcs, mccollisions, mcTracks, o2tracks, o2fwdtracks, o2mfttracks, nullptr, nullptr, emprimaryelectrons, emprimarymuons); } - void processMC_Electron_FwdMuon_PCM(MyCollisionsMC const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, TracksMC const& o2tracks, FwdTracksMC const& o2fwdtracks, MFTTracksMC const& o2mfttracks, aod::V0PhotonsKF const& v0photons, aod::V0Legs const& v0legs, aod::EMPrimaryElectrons const& emprimaryelectrons, aod::EMPrimaryMuons const& emprimarymuons) - { - const uint8_t sysflag = kPCM | kElectron | kFwdMuon; - skimmingMC(collisions, bcs, mccollisions, mcTracks, o2tracks, o2fwdtracks, o2mfttracks, v0photons, v0legs, emprimaryelectrons, emprimarymuons); - } + // void processMC_Electron_FwdMuon_PCM(MyCollisionsMC const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, TracksMC const& o2tracks, FwdTracksMC const& o2fwdtracks, MFTTracksMC const& o2mfttracks, aod::V0PhotonsKF const& v0photons, aod::V0Legs const& v0legs, aod::EMPrimaryElectrons const& emprimaryelectrons, aod::EMPrimaryMuons const& emprimarymuons) + // { + // const uint8_t sysflag = kPCM | kElectron | kFwdMuon; + // skimmingMC(collisions, bcs, mccollisions, mcTracks, o2tracks, o2fwdtracks, o2mfttracks, v0photons, v0legs, emprimaryelectrons, emprimarymuons); + // } - void processMC_Electron_PCM(MyCollisionsMC const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, TracksMC const& o2tracks, aod::V0PhotonsKF const& v0photons, aod::V0Legs const& v0legs, aod::EMPrimaryElectrons const& emprimaryelectrons) - { - const uint8_t sysflag = kPCM | kElectron; - skimmingMC(collisions, bcs, mccollisions, mcTracks, o2tracks, nullptr, nullptr, v0photons, v0legs, emprimaryelectrons, nullptr); - } + // void processMC_Electron_PCM(MyCollisionsMC const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, TracksMC const& o2tracks, aod::V0PhotonsKF const& v0photons, aod::V0Legs const& v0legs, aod::EMPrimaryElectrons const& emprimaryelectrons) + // { + // const uint8_t sysflag = kPCM | kElectron; + // skimmingMC(collisions, bcs, mccollisions, mcTracks, o2tracks, nullptr, nullptr, v0photons, v0legs, emprimaryelectrons, nullptr); + // } - void processMC_PCM(MyCollisionsMC const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, TracksMC const& o2tracks, aod::V0PhotonsKF const& v0photons, aod::V0Legs const& v0legs) - { - skimmingMC(collisions, bcs, mccollisions, mcTracks, o2tracks, nullptr, nullptr, v0photons, v0legs, nullptr, nullptr); - } + // void processMC_PCM(MyCollisionsMC const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, TracksMC const& o2tracks, aod::V0PhotonsKF const& v0photons, aod::V0Legs const& v0legs) + // { + // skimmingMC(collisions, bcs, mccollisions, mcTracks, o2tracks, nullptr, nullptr, v0photons, v0legs, nullptr, nullptr); + // } void processGenDummy(MyCollisionsMC const&) { @@ -718,9 +718,9 @@ struct AssociateMCInfoDilepton { PROCESS_SWITCH(AssociateMCInfoDilepton, processMC_Electron, "create em mc event table for Electron", false); PROCESS_SWITCH(AssociateMCInfoDilepton, processMC_FwdMuon, "create em mc event table for Forward Muon", false); PROCESS_SWITCH(AssociateMCInfoDilepton, processMC_Electron_FwdMuon, "create em mc event table for Electron, FwdMuon", false); - PROCESS_SWITCH(AssociateMCInfoDilepton, processMC_Electron_FwdMuon_PCM, "create em mc event table for PCM, Electron, FwdMuon", false); - PROCESS_SWITCH(AssociateMCInfoDilepton, processMC_Electron_PCM, "create em mc event table for PCM, Electron", false); - PROCESS_SWITCH(AssociateMCInfoDilepton, processMC_PCM, "create em mc event table for PCM", false); + // PROCESS_SWITCH(AssociateMCInfoDilepton, processMC_Electron_FwdMuon_PCM, "create em mc event table for PCM, Electron, FwdMuon", false); + // PROCESS_SWITCH(AssociateMCInfoDilepton, processMC_Electron_PCM, "create em mc event table for PCM, Electron", false); + // PROCESS_SWITCH(AssociateMCInfoDilepton, processMC_PCM, "create em mc event table for PCM", false); PROCESS_SWITCH(AssociateMCInfoDilepton, processGenDummy, "produce dummy data", false); PROCESS_SWITCH(AssociateMCInfoDilepton, processDummy, "processDummy", true); }; diff --git a/PWGEM/Dilepton/TableProducer/createEMEventDilepton.cxx b/PWGEM/Dilepton/TableProducer/createEMEventDilepton.cxx index 608fd8afaf9..a4ab164a4b2 100644 --- a/PWGEM/Dilepton/TableProducer/createEMEventDilepton.cxx +++ b/PWGEM/Dilepton/TableProducer/createEMEventDilepton.cxx @@ -46,28 +46,32 @@ using namespace o2::framework::expressions; using namespace o2::soa; using MyBCs = soa::Join; +// using MyMults = soa::Join; +using MyCents = soa::Join; // centrality table has dependency on multiplicity table. using MyQvectors = soa::Join; using MyCollisions = soa::Join; -using MyCollisions_Cent = soa::Join; // centrality table has dependency on multiplicity table. -using MyCollisions_Cent_Qvec = soa::Join; +using MyCollisions_Cent = soa::Join; +using MyCollisions_Cent_Qvec = soa::Join; using MyCollisionsWithSWT = soa::Join; -using MyCollisionsWithSWT_Cent = soa::Join; // centrality table has dependency on multiplicity table. -using MyCollisionsWithSWT_Cent_Qvec = soa::Join; +using MyCollisionsWithSWT_Cent = soa::Join; +using MyCollisionsWithSWT_Cent_Qvec = soa::Join; using MyCollisionsMC = soa::Join; -using MyCollisionsMC_Cent = soa::Join; // centrality table has dependency on multiplicity table. -using MyCollisionsMC_Cent_Qvec = soa::Join; +using MyCollisionsMC_Cent = soa::Join; +using MyCollisionsMC_Cent_Qvec = soa::Join; struct CreateEMEventDilepton { - Produces embc; + Produces embc; Produces event; Produces eventXY; // Produces eventcov; Produces event_mult; Produces event_cent; - Produces event_qvec; + // Produces event_qvec; + Produces event_qvec2; + Produces event_qvec3; Produces event_norm_info; enum class EMEventType : int { @@ -79,7 +83,7 @@ struct CreateEMEventDilepton { // // CCDB options // Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; - HistogramRegistry registry{"registry"}; + HistogramRegistry registry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; void init(o2::framework::InitContext&) { // ccdb->setURL(ccdburl); @@ -87,9 +91,15 @@ struct CreateEMEventDilepton { // ccdb->setLocalObjectValidityChecking(); // ccdb->setFatalWhenNull(false); - auto hEventCounter = registry.add("hEventCounter", "hEventCounter", kTH1I, {{7, 0.5f, 7.5f}}); + auto hEventCounter = registry.add("hEventCounter", "hEventCounter", kTH1D, {{7, 0.5f, 7.5f}}); hEventCounter->GetXaxis()->SetBinLabel(1, "all"); hEventCounter->GetXaxis()->SetBinLabel(2, "sel8"); + + registry.add("hCentFT0M", "hCentFT0M;centrality FT0M (%);Number of collisions", kTH1F, {{110, 0, 110}}, false); + registry.add("hCentFT0A", "hCentFT0A;centrality FT0A (%);Number of collisions", kTH1F, {{110, 0, 110}}, false); + registry.add("hCentFT0C", "hCentFT0C;centrality FT0C (%);Number of collisions", kTH1F, {{110, 0, 110}}, false); + registry.add("hCentNTPV", "hCentNTPV;centrality NTPV (%);Number of collisions", kTH1F, {{110, 0, 110}}, false); + registry.add("hCentNGlobal", "hCentNGlobal;centrality NGlobal (%);Number of collisions", kTH1F, {{110, 0, 110}}, false); } ~CreateEMEventDilepton() {} @@ -102,7 +112,8 @@ struct CreateEMEventDilepton { { for (const auto& bc : bcs) { if (bc.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { - embc(bc.selection_raw(), bc.rct_raw()); // TVX is fired. + embc(o2::aod::emevsel::reduceSelectionBit(bc), bc.rct_raw()); // TVX is fired. + // embc(bc.selection_raw(), bc.rct_raw()); // TVX is fired. } } // end of bc loop @@ -118,20 +129,24 @@ struct CreateEMEventDilepton { auto bc = collision.template bc_as(); // use this for Zorro if (collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { - int16_t posZint16 = static_cast(collision.posZ() * 100.f); - if (posZint16 == 0) { + int8_t posZint8 = static_cast(collision.posZ() * 2.f); + if (posZint8 == 0) { if (collision.posZ() < 0.f) { - posZint16 = -1; + posZint8 = -1; } else { - posZint16 = +1; + posZint8 = +1; } } if constexpr (eventtype == EMEventType::kEvent) { - event_norm_info(collision.selection_raw(), collision.rct_raw(), posZint16, static_cast(105.f * 500.f)); + event_norm_info(o2::aod::emevsel::reduceSelectionBit(collision), collision.rct_raw(), posZint8, static_cast(105.f + 110.f), static_cast(105.f + 110.f), static_cast(105.f + 110.f) /*, static_cast(105.f + 110.f)*/); } else if constexpr (eventtype == EMEventType::kEvent_Cent || eventtype == EMEventType::kEvent_Cent_Qvec) { - event_norm_info(collision.selection_raw(), collision.rct_raw(), posZint16, static_cast(collision.centFT0C() * 500.f)); + uint8_t centFT0Muint8 = collision.centFT0M() < 1.f ? static_cast(collision.centFT0M() * 100.f) : static_cast(collision.centFT0M() + 110.f); + uint8_t centFT0Cuint8 = collision.centFT0C() < 1.f ? static_cast(collision.centFT0C() * 100.f) : static_cast(collision.centFT0C() + 110.f); + uint8_t centNTPVuint8 = collision.centNTPV() < 1.f ? static_cast(collision.centNTPV() * 100.f) : static_cast(collision.centNTPV() + 110.f); + // uint8_t centNGlobaluint8 = collision.centNGlobal() < 1.f ? static_cast(collision.centNGlobal() * 100.f) : static_cast(collision.centNGlobal() + 110.f); + event_norm_info(o2::aod::emevsel::reduceSelectionBit(collision), collision.rct_raw(), posZint8, centFT0Muint8, centFT0Cuint8, centNTPVuint8 /*, centNGlobaluint8*/); } else { - event_norm_info(collision.selection_raw(), collision.rct_raw(), posZint16, static_cast(105.f * 500.f)); + event_norm_info(o2::aod::emevsel::reduceSelectionBit(collision), collision.rct_raw(), posZint8, static_cast(105.f + 110.f), static_cast(105.f + 110.f), static_cast(105.f + 110.f) /*, static_cast(105.f + 110.f)*/); } } @@ -147,14 +162,11 @@ struct CreateEMEventDilepton { if (collision.swtaliastmp_raw() == 0) { continue; } - // else { - // emswtbit(collision.swtaliastmp_raw()); - // } } registry.fill(HIST("hEventCounter"), 2); - event(collision.globalIndex(), bc.runNumber(), bc.globalBC(), collision.selection_raw(), collision.rct_raw(), bc.timestamp(), + event(collision.globalIndex(), bc.runNumber(), bc.globalBC(), o2::aod::emevsel::reduceSelectionBit(collision), collision.rct_raw(), bc.timestamp(), collision.posZ(), collision.numContrib(), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange()); @@ -162,20 +174,36 @@ struct CreateEMEventDilepton { // eventcov(collision.covXX(), collision.covXY(), collision.covXZ(), collision.covYY(), collision.covYZ(), collision.covZZ(), collision.chi2()); - event_mult(collision.multFT0A(), collision.multFT0C(), collision.multNTracksPV(), collision.multNTracksPVeta1(), collision.multNTracksPVetaHalf()); + event_mult(collision.multFT0A(), collision.multFT0C(), collision.multNTracksPV() /*, collision.multNTracksGlobal()*/); if constexpr (eventtype == EMEventType::kEvent) { - event_cent(105.f, 105.f, 105.f); - event_qvec( - 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, - 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f); + event_cent(105.f, 105.f, 105.f, 105.f); + event_qvec2(999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f); + event_qvec3(999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f); + // event_qvec( + // 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, + // 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f); } else if constexpr (eventtype == EMEventType::kEvent_Cent) { - event_cent(collision.centFT0M(), collision.centFT0A(), collision.centFT0C()); - event_qvec( - 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, - 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f); + registry.fill(HIST("hCentFT0M"), collision.centFT0M()); + registry.fill(HIST("hCentFT0A"), collision.centFT0A()); + registry.fill(HIST("hCentFT0C"), collision.centFT0C()); + registry.fill(HIST("hCentNTPV"), collision.centNTPV()); + registry.fill(HIST("hCentNGlobal"), collision.centFT0M()); + + event_cent(collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV() /*, collision.centNGlobal()*/); + event_qvec2(999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f); + event_qvec3(999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f); + // event_qvec( + // 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, + // 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f); } else if constexpr (eventtype == EMEventType::kEvent_Cent_Qvec) { - event_cent(collision.centFT0M(), collision.centFT0A(), collision.centFT0C()); + registry.fill(HIST("hCentFT0M"), collision.centFT0M()); + registry.fill(HIST("hCentFT0A"), collision.centFT0A()); + registry.fill(HIST("hCentFT0C"), collision.centFT0C()); + registry.fill(HIST("hCentNTPV"), collision.centNTPV()); + registry.fill(HIST("hCentNGlobal"), collision.centFT0M()); + + event_cent(collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV() /*, collision.centNGlobal()*/); float q2xft0m = 999.f, q2yft0m = 999.f, q2xft0a = 999.f, q2yft0a = 999.f, q2xft0c = 999.f, q2yft0c = 999.f, q2xfv0a = 999.f, q2yfv0a = 999.f, q2xbpos = 999.f, q2ybpos = 999.f, q2xbneg = 999.f, q2ybneg = 999.f, q2xbtot = 999.f, q2ybtot = 999.f; float q3xft0m = 999.f, q3yft0m = 999.f, q3xft0a = 999.f, q3yft0a = 999.f, q3xft0c = 999.f, q3yft0c = 999.f, q3xfv0a = 999.f, q3yfv0a = 999.f, q3xbpos = 999.f, q3ybpos = 999.f, q3xbneg = 999.f, q3ybneg = 999.f, q3xbtot = 999.f, q3ybtot = 999.f; @@ -188,14 +216,16 @@ struct CreateEMEventDilepton { q2xft0m = collision.qvecFT0MReVec()[0], q2xft0a = collision.qvecFT0AReVec()[0], q2xft0c = collision.qvecFT0CReVec()[0], q2xfv0a = collision.qvecFV0AReVec()[0], q2xbpos = collision.qvecBPosReVec()[0], q2xbneg = collision.qvecBNegReVec()[0], q2xbtot = collision.qvecBTotReVec()[0]; q2yft0m = collision.qvecFT0MImVec()[0], q2yft0a = collision.qvecFT0AImVec()[0], q2yft0c = collision.qvecFT0CImVec()[0], q2yfv0a = collision.qvecFV0AImVec()[0], q2ybpos = collision.qvecBPosImVec()[0], q2ybneg = collision.qvecBNegImVec()[0], q2ybtot = collision.qvecBTotImVec()[0]; } - event_qvec( - q2xft0m, q2yft0m, q2xft0a, q2yft0a, q2xft0c, q2yft0c, q2xfv0a, q2yfv0a, q2xbpos, q2ybpos, q2xbneg, q2ybneg, q2xbtot, q2ybtot, - q3xft0m, q3yft0m, q3xft0a, q3yft0a, q3xft0c, q3yft0c, q3xfv0a, q3yfv0a, q3xbpos, q3ybpos, q3xbneg, q3ybneg, q3xbtot, q3ybtot); + // event_qvec(q2xft0m, q2yft0m, q2xft0a, q2yft0a, q2xft0c, q2yft0c, q2xfv0a, q2yfv0a, q2xbpos, q2ybpos, q2xbneg, q2ybneg, q2xbtot, q2ybtot, + // q3xft0m, q3yft0m, q3xft0a, q3yft0a, q3xft0c, q3yft0c, q3xfv0a, q3yfv0a, q3xbpos, q3ybpos, q3xbneg, q3ybneg, q3xbtot, q3ybtot); + event_qvec2(q2xft0m, q2yft0m, q2xft0a, q2yft0a, q2xft0c, q2yft0c, q2xfv0a, q2yfv0a, q2xbpos, q2ybpos, q2xbneg, q2ybneg, q2xbtot, q2ybtot); + event_qvec3(q3xft0m, q3yft0m, q3xft0a, q3yft0a, q3xft0c, q3yft0c, q3xfv0a, q3yfv0a, q3xbpos, q3ybpos, q3xbneg, q3ybneg, q3xbtot, q3ybtot); } else { - event_cent(105.f, 105.f, 105.f); - event_qvec( - 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, - 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f); + event_cent(105.f, 105.f, 105.f, 105.f); + // event_qvec( 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, + // 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f); + event_qvec2(999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f); + event_qvec3(999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f); } } // end of collision loop } // end of skimEvent @@ -293,10 +323,10 @@ struct AssociateDileptonToEMEvent { // This struct is for both data and MC. // Note that reconstructed collisions without mc collisions are already rejected in CreateEMEventDilepton in MC. - void processPCM(aod::EMEvents const& collisions, aod::V0PhotonsKF const& photons) - { - fillEventId(collisions, photons, v0kfeventid, perCollision_pcm); - } + // void processPCM(aod::EMEvents const& collisions, aod::V0PhotonsKF const& photons) + // { + // fillEventId(collisions, photons, v0kfeventid, perCollision_pcm); + // } void processElectron(aod::EMEvents const& collisions, aod::EMPrimaryElectrons const& tracks) { @@ -309,14 +339,13 @@ struct AssociateDileptonToEMEvent { } void processChargedTrack(aod::EMEvents const& collisions, aod::EMPrimaryTracks const& tracks) - // void processChargedTrack(aod::EMEvents const& collisions, aod::EMPrimaryTrackEMEventIdsTMP const& tracks) { fillEventId(collisions, tracks, prmtrackeventid, perCollision_track); } void processDummy(aod::EMEvents const&) {} - PROCESS_SWITCH(AssociateDileptonToEMEvent, processPCM, "process indexing for PCM", false); + // PROCESS_SWITCH(AssociateDileptonToEMEvent, processPCM, "process indexing for PCM", false); PROCESS_SWITCH(AssociateDileptonToEMEvent, processElectron, "process indexing for electrons", false); PROCESS_SWITCH(AssociateDileptonToEMEvent, processFwdMuon, "process indexing for forward muons", false); PROCESS_SWITCH(AssociateDileptonToEMEvent, processChargedTrack, "process indexing for charged tracks", false); diff --git a/PWGEM/Dilepton/TableProducer/qVector2DummyOTF.cxx b/PWGEM/Dilepton/TableProducer/qVector2DummyOTF.cxx new file mode 100644 index 00000000000..260c6233e79 --- /dev/null +++ b/PWGEM/Dilepton/TableProducer/qVector2DummyOTF.cxx @@ -0,0 +1,46 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +// +// ======================== +// +// This code produces on-the-fly dummy qvector table. +// Please write to: daiki.sekihata@cern.ch + +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" + +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +using namespace o2; +using namespace o2::aod; +using namespace o2::soa; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct qVector2DummyOTF { + Produces event_qvec2; + + void init(InitContext&) {} + ~qVector2DummyOTF() {} + + void process(aod::EMEvents const& collisions) + { + for (int i = 0; i < collisions.size(); i++) { + event_qvec2(999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f); + } // end of collision loop + } // end of process +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"qvector2-dummy-otf"})}; +} diff --git a/PWGEM/Dilepton/TableProducer/qVector3DummyOTF.cxx b/PWGEM/Dilepton/TableProducer/qVector3DummyOTF.cxx new file mode 100644 index 00000000000..864c4605462 --- /dev/null +++ b/PWGEM/Dilepton/TableProducer/qVector3DummyOTF.cxx @@ -0,0 +1,46 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +// +// ======================== +// +// This code produces on-the-fly dummy qvector table. +// Please write to: daiki.sekihata@cern.ch + +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" + +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +using namespace o2; +using namespace o2::aod; +using namespace o2::soa; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct qVector3DummyOTF { + Produces event_qvec3; + + void init(InitContext&) {} + ~qVector3DummyOTF() {} + + void process(aod::EMEvents const& collisions) + { + for (int i = 0; i < collisions.size(); i++) { + event_qvec3(999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f); + } // end of collision loop + } // end of process +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"qvector3-dummy-otf"})}; +} diff --git a/PWGEM/Dilepton/Tasks/checkMCPairTemplate.cxx b/PWGEM/Dilepton/Tasks/checkMCPairTemplate.cxx index cda9e5da1b9..2c7ebf754c4 100644 --- a/PWGEM/Dilepton/Tasks/checkMCPairTemplate.cxx +++ b/PWGEM/Dilepton/Tasks/checkMCPairTemplate.cxx @@ -3234,28 +3234,28 @@ struct checkMCPairTemplate { { for (const auto& collision : collisions) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 1.0); - if (collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + if (collision.selection_bit(o2::aod::emevsel::kIsTriggerTVX)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 2.0); } - if (collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + if (collision.selection_bit(o2::aod::emevsel::kNoTimeFrameBorder)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 3.0); } - if (collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + if (collision.selection_bit(o2::aod::emevsel::kNoITSROFrameBorder)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 4.0); } - if (collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + if (collision.selection_bit(o2::aod::emevsel::kNoSameBunchPileup)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 5.0); } - if (collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + if (collision.selection_bit(o2::aod::emevsel::kIsGoodZvtxFT0vsPV)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 6.0); } - if (collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + if (collision.selection_bit(o2::aod::emevsel::kIsVertexITSTPC)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 7.0); } - if (collision.selection_bit(o2::aod::evsel::kIsVertexTRDmatched)) { + if (collision.selection_bit(o2::aod::emevsel::kIsVertexTRDmatched)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 8.0); } - if (collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) { + if (collision.selection_bit(o2::aod::emevsel::kIsVertexTOFmatched)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 9.0); } if (collision.sel8()) { @@ -3264,28 +3264,28 @@ struct checkMCPairTemplate { if (std::fabs(collision.posZ()) < 10.0) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 11.0); } - if (collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + if (collision.selection_bit(o2::aod::emevsel::kNoCollInTimeRangeStandard)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 12.0); } - if (collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStrict)) { + if (collision.selection_bit(o2::aod::emevsel::kNoCollInTimeRangeStrict)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 13.0); } - if (collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { + if (collision.selection_bit(o2::aod::emevsel::kNoCollInRofStandard)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 14.0); } - if (collision.selection_bit(o2::aod::evsel::kNoCollInRofStrict)) { + if (collision.selection_bit(o2::aod::emevsel::kNoCollInRofStrict)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 15.0); } - if (collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { + if (collision.selection_bit(o2::aod::emevsel::kNoHighMultCollInPrevRof)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 16.0); } - if (collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer3)) { + if (collision.selection_bit(o2::aod::emevsel::kIsGoodITSLayer3)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 17.0); } - if (collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer0123)) { + if (collision.selection_bit(o2::aod::emevsel::kIsGoodITSLayer0123)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 18.0); } - if (collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + if (collision.selection_bit(o2::aod::emevsel::kIsGoodITSLayersAll)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 19.0); } if (!fEMEventCut.IsSelected(collision)) { @@ -3302,22 +3302,22 @@ struct checkMCPairTemplate { void processBC(aod::EMBCs const& bcs) { for (const auto& bc : bcs) { - if (bc.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + if (bc.selection_bit(o2::aod::emevsel::kIsTriggerTVX)) { fRegistry.fill(HIST("BC/hTVXCounter"), 0.f); - if (bc.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + if (bc.selection_bit(o2::aod::emevsel::kNoTimeFrameBorder)) { fRegistry.fill(HIST("BC/hTVXCounter"), 1.f); } - if (bc.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + if (bc.selection_bit(o2::aod::emevsel::kNoITSROFrameBorder)) { fRegistry.fill(HIST("BC/hTVXCounter"), 2.f); } if (rctChecker(bc)) { fRegistry.fill(HIST("BC/hTVXCounter"), 3.f); } - if (bc.selection_bit(o2::aod::evsel::kNoTimeFrameBorder) && bc.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + if (bc.selection_bit(o2::aod::emevsel::kNoTimeFrameBorder) && bc.selection_bit(o2::aod::emevsel::kNoITSROFrameBorder)) { fRegistry.fill(HIST("BC/hTVXCounter"), 4.f); } - if (bc.selection_bit(o2::aod::evsel::kNoTimeFrameBorder) && bc.selection_bit(o2::aod::evsel::kNoITSROFrameBorder) && rctChecker(bc)) { + if (bc.selection_bit(o2::aod::emevsel::kNoTimeFrameBorder) && bc.selection_bit(o2::aod::emevsel::kNoITSROFrameBorder) && rctChecker(bc)) { fRegistry.fill(HIST("BC/hTVXCounter"), 5.f); } } diff --git a/PWGEM/Dilepton/Tasks/eventQC.cxx b/PWGEM/Dilepton/Tasks/eventQC.cxx index c6fe4e3689c..0b1f4b3e0ef 100644 --- a/PWGEM/Dilepton/Tasks/eventQC.cxx +++ b/PWGEM/Dilepton/Tasks/eventQC.cxx @@ -14,7 +14,7 @@ // This code is for event QC for PWG-EM. // Please write to: daiki.sekihata@cern.ch -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +// #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "Common/Core/RecoDecay.h" #include "Common/Core/Zorro.h" diff --git a/PWGEM/Dilepton/Utils/EventHistograms.h b/PWGEM/Dilepton/Utils/EventHistograms.h index 3f123920339..74dd96bdb84 100644 --- a/PWGEM/Dilepton/Utils/EventHistograms.h +++ b/PWGEM/Dilepton/Utils/EventHistograms.h @@ -51,34 +51,13 @@ void addEventHistograms(HistogramRegistry* fRegistry) hCollisionCounter->GetXaxis()->SetBinLabel(20, "Calibrated Q vector"); hCollisionCounter->GetXaxis()->SetBinLabel(21, "accepted"); - const AxisSpec axis_cent_ft0m{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, - 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110}, - "centrality FT0M (%)"}; - - const AxisSpec axis_cent_ft0a{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, - 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110}, - "centrality FT0A (%)"}; - - const AxisSpec axis_cent_ft0c{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, - 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110}, - "centrality FT0C (%)"}; - fRegistry->add("Event/before/hZvtx", "vertex z; Z_{vtx} (cm)", kTH1D, {{100, -50, +50}}, false); fRegistry->add("Event/before/hMultNTracksPV", "hMultNTracksPV; N_{track} to PV", kTH1D, {{6001, -0.5, 6000.5}}, false); - fRegistry->add("Event/before/hMultNTracksPVeta1", "hMultNTracksPVeta1; N_{track} to PV", kTH1D, {{6001, -0.5, 6000.5}}, false); fRegistry->add("Event/before/hMultFT0", "hMultFT0;mult. FT0A;mult. FT0C", kTH2D, {{200, 0, 200000}, {60, 0, 60000}}, false); - fRegistry->add("Event/before/hCentFT0A", "hCentFT0A;centrality FT0A (%)", kTH1D, {{axis_cent_ft0a}}, false); - fRegistry->add("Event/before/hCentFT0C", "hCentFT0C;centrality FT0C (%)", kTH1D, {{axis_cent_ft0c}}, false); - fRegistry->add("Event/before/hCentFT0M", "hCentFT0M;centrality FT0M (%)", kTH1D, {{axis_cent_ft0m}}, false); + fRegistry->add("Event/before/hCentFT0A", "hCentFT0A;centrality FT0A (%)", kTH1D, {{110, 0, 110}}, false); + fRegistry->add("Event/before/hCentFT0C", "hCentFT0C;centrality FT0C (%)", kTH1D, {{110, 0, 110}}, false); + fRegistry->add("Event/before/hCentFT0M", "hCentFT0M;centrality FT0M (%)", kTH1D, {{110, 0, 110}}, false); + fRegistry->add("Event/before/hCentNTPV", "hCentNTPV;centrality NTPV (%)", kTH1D, {{110, 0, 110}}, false); fRegistry->add("Event/before/hCentFT0CvsMultNTracksPV", "hCentFT0CvsMultNTracksPV;centrality FT0C (%);N_{track} to PV", kTH2D, {{110, 0, 110}, {600, 0, 6000}}, false); fRegistry->add("Event/before/hMultFT0CvsMultNTracksPV", "hMultFT0CvsMultNTracksPV;mult. FT0C;N_{track} to PV", kTH2D, {{60, 0, 60000}, {600, 0, 6000}}, false); fRegistry->add("Event/before/hMultFT0CvsOccupancy", "hMultFT0CvsOccupancy;mult. FT0C;N_{track} in time range", kTH2D, {{60, 0, 60000}, {200, 0, 20000}}, false); @@ -170,28 +149,28 @@ void fillEventInfo(HistogramRegistry* fRegistry, TCollision const& collision, co { static constexpr std::string_view event_types[2] = {"before/", "after/"}; fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 1.0); - if (collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + if (collision.selection_bit(o2::aod::emevsel::kIsTriggerTVX)) { fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 2.0); } - if (collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + if (collision.selection_bit(o2::aod::emevsel::kNoTimeFrameBorder)) { fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 3.0); } - if (collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + if (collision.selection_bit(o2::aod::emevsel::kNoITSROFrameBorder)) { fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 4.0); } - if (collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + if (collision.selection_bit(o2::aod::emevsel::kNoSameBunchPileup)) { fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 5.0); } - if (collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + if (collision.selection_bit(o2::aod::emevsel::kIsGoodZvtxFT0vsPV)) { fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 6.0); } - if (collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + if (collision.selection_bit(o2::aod::emevsel::kIsVertexITSTPC)) { fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 7.0); } - if (collision.selection_bit(o2::aod::evsel::kIsVertexTRDmatched)) { + if (collision.selection_bit(o2::aod::emevsel::kIsVertexTRDmatched)) { fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 8.0); } - if (collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) { + if (collision.selection_bit(o2::aod::emevsel::kIsVertexTOFmatched)) { fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 9.0); } if (collision.sel8()) { @@ -200,38 +179,38 @@ void fillEventInfo(HistogramRegistry* fRegistry, TCollision const& collision, co if (abs(collision.posZ()) < 10.0) { fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 11.0); } - if (collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + if (collision.selection_bit(o2::aod::emevsel::kNoCollInTimeRangeStandard)) { fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 12.0); } - if (collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStrict)) { + if (collision.selection_bit(o2::aod::emevsel::kNoCollInTimeRangeStrict)) { fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 13.0); } - if (collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { + if (collision.selection_bit(o2::aod::emevsel::kNoCollInRofStandard)) { fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 14.0); } - if (collision.selection_bit(o2::aod::evsel::kNoCollInRofStrict)) { + if (collision.selection_bit(o2::aod::emevsel::kNoCollInRofStrict)) { fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 15.0); } - if (collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { + if (collision.selection_bit(o2::aod::emevsel::kNoHighMultCollInPrevRof)) { fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 16.0); } - if (collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer3)) { + if (collision.selection_bit(o2::aod::emevsel::kIsGoodITSLayer3)) { fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 17.0); } - if (collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer0123)) { + if (collision.selection_bit(o2::aod::emevsel::kIsGoodITSLayer0123)) { fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 18.0); } - if (collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + if (collision.selection_bit(o2::aod::emevsel::kIsGoodITSLayersAll)) { fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 19.0); } fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hZvtx"), collision.posZ()); fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hMultNTracksPV"), collision.multNTracksPV()); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hMultNTracksPVeta1"), collision.multNTracksPVeta1()); fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hMultFT0"), collision.multFT0A(), collision.multFT0C()); fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCentFT0A"), collision.centFT0A()); fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCentFT0C"), collision.centFT0C()); fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCentFT0M"), collision.centFT0M()); + fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCentNTPV"), collision.centNTPV()); fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCentFT0CvsMultNTracksPV"), collision.centFT0C(), collision.multNTracksPV()); fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hMultFT0CvsMultNTracksPV"), collision.multFT0C(), collision.multNTracksPV()); fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hMultFT0CvsOccupancy"), collision.multFT0C(), collision.trackOccupancyInTimeRange()); diff --git a/PWGEM/PhotonMeson/Core/DiphotonHadronMPC.h b/PWGEM/PhotonMeson/Core/DiphotonHadronMPC.h deleted file mode 100644 index 54381491765..00000000000 --- a/PWGEM/PhotonMeson/Core/DiphotonHadronMPC.h +++ /dev/null @@ -1,992 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -/// \file DiphotonHadronMPC.h -/// \brief This code is to analyze diphoton-hadron correlation. Keep in mind that cumulant method does not require event mixing. -/// \author D. Sekihata, daiki.sekihata@cern.ch - -#ifndef PWGEM_PHOTONMESON_CORE_DIPHOTONHADRONMPC_H_ -#define PWGEM_PHOTONMESON_CORE_DIPHOTONHADRONMPC_H_ - -#include "PWGEM/Dilepton/Core/EMTrackCut.h" -#include "PWGEM/Dilepton/Utils/EMTrack.h" -#include "PWGEM/Dilepton/Utils/EventMixingHandler.h" -#include "PWGEM/PhotonMeson/Core/DalitzEECut.h" -#include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" -#include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGEM/PhotonMeson/Utils/EventHistograms.h" -#include "PWGEM/PhotonMeson/Utils/PairUtilities.h" - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include // IWYU pragma: keep -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace o2; -using namespace o2::aod; -using namespace o2::framework; -using namespace o2::framework::expressions; -using namespace o2::soa; -using namespace o2::aod::pwgem::photonmeson::photonpair; -using namespace o2::aod::pwgem::photon; -using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; -using namespace o2::aod::pwgem::dilepton::utils; - -using MyCollisions = soa::Join; -using MyCollision = MyCollisions::iterator; - -using MyCollisionsWithSWT = soa::Join; -using MyCollisionWithSWT = MyCollisionsWithSWT::iterator; - -using MyV0Photons = soa::Filtered>; -using MyV0Photon = MyV0Photons::iterator; - -using MyPrimaryElectrons = soa::Filtered>; -using MyPrimaryElectron = MyPrimaryElectrons::iterator; - -template -struct DiphotonHadronMPC { - - Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; - Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; - Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; - Configurable skipGRPOquery{"skipGRPOquery", true, "skip grpo query"}; - Configurable d_bz_input{"d_bz_input", -999, "bz field in kG, -999 is automatic"}; - Configurable cfg_swt_name{"cfg_swt_name", "fHighTrackMult", "desired software trigger name"}; // 1 trigger name per 1 task. fHighTrackMult, fHighFt0Mult - - Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; - Configurable cfgOccupancyEstimator{"cfgOccupancyEstimator", 0, "FT0C:0, Track:1"}; - Configurable cfgCentMin{"cfgCentMin", -1, "min. centrality"}; - Configurable cfgCentMax{"cfgCentMax", 999, "max. centrality"}; - Configurable maxY{"maxY", 0.8, "maximum rapidity for diphoton"}; - Configurable cfgDoMix{"cfgDoMix", true, "flag for event mixing"}; - Configurable ndepth_photon{"ndepth_photon", 100, "depth for event mixing between photon-photon"}; - Configurable ndepth_hadron{"ndepth_hadron", 2, "depth for event mixing between hadron-hadron"}; - Configurable ndiff_bc_mix{"ndiff_bc_mix", 594, "difference in global BC required in mixed events"}; - ConfigurableAxis ConfVtxBins{"ConfVtxBins", {VARIABLE_WIDTH, -10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}, "Mixing bins - z-vertex"}; - ConfigurableAxis ConfCentBins{"ConfCentBins", {VARIABLE_WIDTH, 0.0f, 0.1, 1, 5.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f, 100.f, 999.f}, "Mixing bins - centrality"}; - ConfigurableAxis ConfOccupancyBins{"ConfOccupancyBins", {VARIABLE_WIDTH, -1, 1e+10}, "Mixing bins - occupancy"}; - - ConfigurableAxis ConfMggBins{"ConfMggBins", {200, 0.0, 0.8}, "mgg bins for output histograms"}; - ConfigurableAxis ConfPtggBins{"ConfPtggBins", {VARIABLE_WIDTH, 0.0, 0.1, 0.2, 0.3, 0.4, 0.50, 1.00, 1.50, 2.00, 2.50, 3.00, 3.50, 4.00, 4.50, 5.00, 6.00, 7.00, 8.00, 9.00, 10.00}, "pTgg bins for output histograms"}; - - ConfigurableAxis ConfPtHadronBins{"ConfPtHadronBins", {VARIABLE_WIDTH, 0.00, 0.15, 0.2, 0.3, 0.4, 0.50, 1.00, 2.00, 3.00, 4.00, 5.00}, "pT,h bins for output histograms"}; - ConfigurableAxis ConfDEtaBins{"ConfDEtaBins", {120, -6, 6}, "deta bins for output histograms"}; - Configurable cfgNbinsDPhi{"cfgNbinsDPhi", 36, "nbins in dphi for output histograms"}; - // Configurable cfgNbinsCosNDPhi{"cfgNbinsCosNDPhi", 100, "nbins in cos(n(dphi)) for output histograms"}; - // Configurable cfgNmod{"cfgNmod", 2, "n-th harmonics"}; - - EMPhotonEventCut fEMEventCut; - struct : ConfigurableGroup { - std::string prefix = "eventcut_group"; - Configurable cfgZvtxMin{"cfgZvtxMin", -10.f, "min. Zvtx"}; - Configurable cfgZvtxMax{"cfgZvtxMax", +10.f, "max. Zvtx"}; - Configurable cfgRequireSel8{"cfgRequireSel8", true, "require sel8 in event cut"}; - Configurable cfgRequireFT0AND{"cfgRequireFT0AND", true, "require FT0AND in event cut"}; - Configurable cfgRequireNoTFB{"cfgRequireNoTFB", false, "require No time frame border in event cut"}; - Configurable cfgRequireNoITSROFB{"cfgRequireNoITSROFB", false, "require no ITS readout frame border in event cut"}; - Configurable cfgRequireNoSameBunchPileup{"cfgRequireNoSameBunchPileup", false, "require no same bunch pileup in event cut"}; - Configurable cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; - Configurable cfgTrackOccupancyMin{"cfgTrackOccupancyMin", -2, "min. occupancy"}; - Configurable cfgTrackOccupancyMax{"cfgTrackOccupancyMax", 1000000000, "max. occupancy"}; - Configurable cfgFT0COccupancyMin{"cfgFT0COccupancyMin", -2, "min. FT0C occupancy"}; - Configurable cfgFT0COccupancyMax{"cfgFT0COccupancyMax", 1000000000, "max. FT0C occupancy"}; - // for RCT - Configurable cfgRequireGoodRCT{"cfgRequireGoodRCT", false, "require good detector flag in run condtion table"}; - Configurable cfgRCTLabel{"cfgRCTLabel", "CBT_hadronPID", "select 1 [CBT, CBT_hadronPID] see O2Physics/Common/CCDB/RCTSelectionFlags.h"}; - Configurable cfgCheckZDC{"cfgCheckZDC", false, "set ZDC flag for PbPb"}; - Configurable cfgTreatLimitedAcceptanceAsBad{"cfgTreatLimitedAcceptanceAsBad", false, "reject all events where the detectors relevant for the specified Runlist are flagged as LimitedAcceptance"}; - } eventcuts; - - V0PhotonCut fV0PhotonCut; - struct : ConfigurableGroup { - std::string prefix = "pcmcut_group"; - Configurable cfg_require_v0_with_itstpc{"cfg_require_v0_with_itstpc", false, "flag to select V0s with ITS-TPC matched tracks"}; - Configurable cfg_require_v0_with_itsonly{"cfg_require_v0_with_itsonly", false, "flag to select V0s with ITSonly tracks"}; - Configurable cfg_require_v0_with_tpconly{"cfg_require_v0_with_tpconly", false, "flag to select V0s with TPConly tracks"}; - Configurable cfg_min_pt_v0{"cfg_min_pt_v0", 0.1, "min pT for v0 photons at PV"}; - Configurable cfg_max_pt_v0{"cfg_max_pt_v0", 1e+10, "max pT for v0 photons at PV"}; - Configurable cfg_min_eta_v0{"cfg_min_eta_v0", -0.8, "min eta for v0 photons at PV"}; - Configurable cfg_max_eta_v0{"cfg_max_eta_v0", 0.8, "max eta for v0 photons at PV"}; - Configurable cfg_min_v0radius{"cfg_min_v0radius", 4.0, "min v0 radius"}; - Configurable cfg_max_v0radius{"cfg_max_v0radius", 90.0, "max v0 radius"}; - Configurable cfg_max_alpha_ap{"cfg_max_alpha_ap", 0.95, "max alpha for AP cut"}; - Configurable cfg_max_qt_ap{"cfg_max_qt_ap", 0.01, "max qT for AP cut"}; - Configurable cfg_min_cospa{"cfg_min_cospa", 0.997, "min V0 CosPA"}; - Configurable cfg_max_pca{"cfg_max_pca", 3.0, "max distance btween 2 legs"}; - Configurable cfg_max_chi2kf{"cfg_max_chi2kf", 1e+10, "max chi2/ndf with KF"}; - Configurable cfg_reject_v0_on_itsib{"cfg_reject_v0_on_itsib", true, "flag to reject V0s on ITSib"}; - Configurable cfg_apply_cuts_from_prefilter_derived{"cfg_apply_cuts_from_prefilter_derived", false, "flag to apply prefilter to V0"}; - - Configurable cfg_min_ncluster_tpc{"cfg_min_ncluster_tpc", 0, "min ncluster tpc"}; - Configurable cfg_min_ncrossedrows{"cfg_min_ncrossedrows", 40, "min ncrossed rows"}; - Configurable cfg_max_frac_shared_clusters_tpc{"cfg_max_frac_shared_clusters_tpc", 999.f, "max fraction of shared clusters in TPC"}; - Configurable cfg_max_chi2tpc{"cfg_max_chi2tpc", 4.0, "max chi2/NclsTPC"}; - Configurable cfg_max_chi2its{"cfg_max_chi2its", 36.0, "max chi2/NclsITS"}; - Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -3.0, "min. TPC n sigma for electron"}; - Configurable cfg_max_TPCNsigmaEl{"cfg_max_TPCNsigmaEl", +3.0, "max. TPC n sigma for electron"}; - Configurable cfg_disable_itsonly_track{"cfg_disable_itsonly_track", false, "flag to disable ITSonly tracks"}; - Configurable cfg_disable_tpconly_track{"cfg_disable_tpconly_track", false, "flag to disable TPConly tracks"}; - } pcmcuts; - - DalitzEECut fDileptonCut; - struct : ConfigurableGroup { - std::string prefix = "dileptoncut_group"; - Configurable cfg_min_mass{"cfg_min_mass", 0.0, "min mass"}; - Configurable cfg_max_mass{"cfg_max_mass", 0.04, "max mass"}; - Configurable cfg_apply_phiv{"cfg_apply_phiv", true, "flag to apply phiv cut"}; - Configurable cfg_require_itsib_any{"cfg_require_itsib_any", false, "flag to require ITS ib any hits"}; - Configurable cfg_require_itsib_1st{"cfg_require_itsib_1st", true, "flag to require ITS ib 1st hit"}; - Configurable cfg_phiv_slope{"cfg_phiv_slope", 0.0185, "slope for m vs. phiv"}; - Configurable cfg_phiv_intercept{"cfg_phiv_intercept", -0.0280, "intercept for m vs. phiv"}; - - Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.1, "min pT for single track"}; - Configurable cfg_max_eta_track{"cfg_max_eta_track", 2.0, "max eta for single track"}; - Configurable cfg_min_ncluster_tpc{"cfg_min_ncluster_tpc", 0, "min ncluster tpc"}; - Configurable cfg_min_ncluster_its{"cfg_min_ncluster_its", 5, "min ncluster its"}; - Configurable cfg_min_ncrossedrows{"cfg_min_ncrossedrows", 70, "min ncrossed rows"}; - Configurable cfg_max_chi2tpc{"cfg_max_chi2tpc", 4.0, "max chi2/NclsTPC"}; - Configurable cfg_max_chi2its{"cfg_max_chi2its", 36.0, "max chi2/NclsITS"}; - Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 0.1, "max dca XY for single track in cm"}; - Configurable cfg_max_dcaz{"cfg_max_dcaz", 0.1, "max dca Z for single track in cm"}; - Configurable cfg_max_dca3dsigma_track{"cfg_max_dca3dsigma_track", 1e+10, "max DCA 3D in sigma"}; - Configurable cfg_max_frac_shared_clusters_tpc{"cfg_max_frac_shared_clusters_tpc", 0.7, "max fraction of shared clusters in TPC"}; - Configurable cfg_apply_cuts_from_prefilter_derived{"cfg_apply_cuts_from_prefilter_derived", false, "flag to apply prefilter to electron"}; - - Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DalitzEECut::PIDSchemes::kTOFif), "pid scheme [kTOFif : 0, kTPConly : 1]"}; - Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -2.0, "min. TPC n sigma for electron inclusion"}; - Configurable cfg_max_TPCNsigmaEl{"cfg_max_TPCNsigmaEl", +3.0, "max. TPC n sigma for electron inclusion"}; - Configurable cfg_min_TPCNsigmaPi{"cfg_min_TPCNsigmaPi", -0.0, "min. TPC n sigma for pion exclusion"}; - Configurable cfg_max_TPCNsigmaPi{"cfg_max_TPCNsigmaPi", +0.0, "max. TPC n sigma for pion exclusion"}; - Configurable cfg_min_TOFNsigmaEl{"cfg_min_TOFNsigmaEl", -3.0, "min. TOF n sigma for electron inclusion"}; - Configurable cfg_max_TOFNsigmaEl{"cfg_max_TOFNsigmaEl", +3.0, "max. TOF n sigma for electron inclusion"}; - } dileptoncuts; - - EMTrackCut fEMTrackCut; - struct : ConfigurableGroup { - std::string prefix = "trackcut_group"; - Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.2, "min pT for ref. track"}; - Configurable cfg_max_pt_track{"cfg_max_pt_track", 3.0, "max pT for ref. track"}; - Configurable cfg_min_eta_track{"cfg_min_eta_track", -0.8, "min eta for ref. track"}; - Configurable cfg_max_eta_track{"cfg_max_eta_track", +0.8, "max eta for ref. track"}; - // Configurable cfg_min_phi_track{"cfg_min_phi_track", 0.0, "min phi for ref. track"}; - // Configurable cfg_max_phi_track{"cfg_max_phi_track", 6.3, "max phi for ref. track"}; - // Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 0.5, "max dca XY for single track in cm"}; - // Configurable cfg_max_dcaz{"cfg_max_dcaz", 0.5, "max dca Z for single track in cm"}; - Configurable cfg_track_bits{"cfg_track_bits", 645, "required track bits"}; // default:645, loose:0, tight:778 - } trackcuts; - - o2::aod::rctsel::RCTFlagsChecker rctChecker; - HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; - static constexpr std::string_view event_types[2] = {"before/", "after/"}; - static constexpr std::string_view event_pair_types[2] = {"same/", "mix/"}; - - std::vector zvtx_bin_edges; - std::vector cent_bin_edges; - std::vector occ_bin_edges; - - o2::ccdb::CcdbApi ccdbApi; - Service ccdb; - int mRunNumber; - float d_bz; - - void init(InitContext&) - { - zvtx_bin_edges = std::vector(ConfVtxBins.value.begin(), ConfVtxBins.value.end()); - zvtx_bin_edges.erase(zvtx_bin_edges.begin()); - - cent_bin_edges = std::vector(ConfCentBins.value.begin(), ConfCentBins.value.end()); - cent_bin_edges.erase(cent_bin_edges.begin()); - - LOGF(info, "cfgOccupancyEstimator = %d", cfgOccupancyEstimator.value); - occ_bin_edges = std::vector(ConfOccupancyBins.value.begin(), ConfOccupancyBins.value.end()); - occ_bin_edges.erase(occ_bin_edges.begin()); - - emh1 = new MyEMH(ndepth_photon); - emh2 = new MyEMH(ndepth_photon); - emh_diphoton = new MyEMH_track(ndepth_photon); - emh_ref = new MyEMH_track(ndepth_hadron); - - o2::aod::pwgem::photonmeson::utils::eventhistogram::addEventHistograms(&fRegistry); - addHistograms(); - - DefineEMEventCut(); - DefineEMTrackCut(); - DefinePCMCut(); - DefineDileptonCut(); - - fRegistry.add("Diphoton/mix/hDiffBC", "diff. global BC in mixed event;|BC_{current} - BC_{mixed}|", kTH1D, {{10001, -0.5, 10000.5}}, true); - if (doprocessTriggerAnalysis) { - fRegistry.add("Event/hNInspectedTVX", "N inspected TVX;run number;N_{TVX}", kTProfile, {{80000, 520000.5, 600000.5}}, true); - } - - mRunNumber = 0; - d_bz = 0; - - ccdb->setURL(ccdburl); - ccdb->setCaching(true); - ccdb->setLocalObjectValidityChecking(); - ccdb->setFatalWhenNull(false); - rctChecker.init(eventcuts.cfgRCTLabel.value, eventcuts.cfgCheckZDC.value, eventcuts.cfgTreatLimitedAcceptanceAsBad.value); - } - - template - void initCCDB(TCollision const& collision) - { - if (mRunNumber == collision.runNumber()) { - return; - } - - // In case override, don't proceed, please - no CCDB access required - if (d_bz_input > -990) { - d_bz = d_bz_input; - o2::parameters::GRPMagField grpmag; - if (std::fabs(d_bz) > 1e-5) { - grpmag.setL3Current(30000.f / (d_bz / 5.0f)); - } - mRunNumber = collision.runNumber(); - return; - } - - auto run3grp_timestamp = collision.timestamp(); - o2::parameters::GRPObject* grpo = 0x0; - o2::parameters::GRPMagField* grpmag = 0x0; - if (!skipGRPOquery) { - grpo = ccdb->getForTimeStamp(grpPath, run3grp_timestamp); - } - if (grpo) { - // Fetch magnetic field from ccdb for current collision - d_bz = grpo->getNominalL3Field(); - LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; - } else { - grpmag = ccdb->getForTimeStamp(grpmagPath, run3grp_timestamp); - if (!grpmag) { - LOG(fatal) << "Got nullptr from CCDB for path " << grpmagPath << " of object GRPMagField and " << grpPath << " of object GRPObject for timestamp " << run3grp_timestamp; - } - // Fetch magnetic field from ccdb for current collision - d_bz = std::lround(5.f * grpmag->getL3Current() / 30000.f); - LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; - } - mRunNumber = collision.runNumber(); - - if constexpr (isTriggerAnalysis) { - LOGF(info, "Trigger analysis is enabled. Desired trigger name = %s", cfg_swt_name.value); - // LOGF(info, "total inspected TVX events = %d in run number %d", collision.nInspectedTVX(), collision.runNumber()); - // fRegistry.fill(HIST("Event/hNInspectedTVX"), collision.runNumber(), collision.nInspectedTVX()); - } - } - - ~DiphotonHadronMPC() - { - delete emh1; - emh1 = 0x0; - delete emh2; - emh2 = 0x0; - delete emh_diphoton; - emh_diphoton = 0x0; - delete emh_ref; - emh_ref = 0x0; - - used_photonIds_per_col.clear(); - used_photonIds_per_col.shrink_to_fit(); - used_dileptonIds_per_col.clear(); - used_dileptonIds_per_col.shrink_to_fit(); - used_diphotonIds_per_col.clear(); - used_diphotonIds_per_col.shrink_to_fit(); - - map_mixed_eventId_to_globalBC.clear(); - } - - void addHistograms() - { - std::string mass_axis_title = "m_{#gamma#gamma} (GeV/c^{2})"; - std::string pair_pt_axis_title = "p_{T,#gamma#gamma} (GeV/c)"; - std::string deta_axis_title = "#Delta#eta = #eta_{#gamma#gamma} - #eta_{h}"; - std::string dphi_axis_title = "#Delta#varphi = #varphi_{#gamma#gamma} - #varphi_{h} (rad.)"; - // std::string cosndphi_axis_title = std::format("cos({0:d}(#varphi_{{#gamma#gamma}} - #varphi_{{h}}))", cfgNmod.value); - - if constexpr (pairtype == PairType::kPCMDalitzEE) { - mass_axis_title = "m_{ee#gamma} (GeV/c^{2})"; - pair_pt_axis_title = "p_{T,ee#gamma} (GeV/c)"; - deta_axis_title = "#Delta#eta = #eta_{ee#gamma} - #eta_{h}"; - dphi_axis_title = "#Delta#varphi = #varphi_{ee#gamma} - #varphi_{h} (rad.)"; - // cosndphi_axis_title = std::format("cos({0:d}(#varphi_{{ee#gamma}} - #varphi_{{h}}))", cfgNmod.value); - } - - // diphoton info - const AxisSpec axis_mass{ConfMggBins, mass_axis_title}; - const AxisSpec axis_pt{ConfPtggBins, pair_pt_axis_title}; - - // diphoton-hadron info - const AxisSpec axis_deta{ConfDEtaBins, deta_axis_title}; - const AxisSpec axis_dphi{cfgNbinsDPhi, -o2::constants::math::PIHalf, +3 * o2::constants::math::PIHalf, dphi_axis_title}; - - const AxisSpec axis_pt_hadron{ConfPtHadronBins, "p_{T,h} (GeV/c)"}; - const AxisSpec axis_eta_hadron{40, -2, +2, "#eta_{h}"}; - const AxisSpec axis_phi_hadron{36, 0, o2::constants::math::TwoPI, "#varphi_{h} (rad.)"}; - - fRegistry.add("Hadron/hs", "hadron", kTHnSparseD, {axis_pt_hadron, axis_eta_hadron, axis_phi_hadron}, false); - fRegistry.add("Hadron/hTrackBit", "track bit", kTH1D, {{65536, -0.5, 65535.5}}, false); - - fRegistry.add("Diphoton/same/hs", "diphoton", kTHnSparseD, {axis_mass, axis_pt}, true); - fRegistry.addClone("Diphoton/same/", "Diphoton/mix/"); - - fRegistry.add("DiphotonHadron/same/hs", "diphoton-hadron 2PC", kTHnSparseD, {axis_mass, axis_pt, axis_deta, axis_dphi}, true); - fRegistry.addClone("DiphotonHadron/same/", "DiphotonHadron/mix/"); - - // hadron-hadron - const AxisSpec axis_deta_hh{60, -3, +3, "#Delta#eta = #eta_{h}^{ref1} - #eta_{h}^{ref2}"}; - const AxisSpec axis_dphi_hh{90, -o2::constants::math::PIHalf, +3 * o2::constants::math::PIHalf, "#Delta#varphi = #varphi_{h}^{ref1} - #varphi_{h}^{ref2} (rad.)"}; - // const AxisSpec axis_cosndphi_hh{cfgNbinsCosNDPhi, -1, +1, std::format("cos({0:d}(#varphi_{{h}}^{{ref1}} - #varphi_{{h}}^{{ref2}}))", cfgNmod.value)}; - fRegistry.add("HadronHadron/same/hDEtaDPhi", "hadron-hadron 2PC", kTH2D, {axis_dphi_hh, axis_deta_hh}, true); - fRegistry.addClone("HadronHadron/same/", "HadronHadron/mix/"); - } - - void DefineEMEventCut() - { - fEMEventCut = EMPhotonEventCut("fEMEventCut", "fEMEventCut"); - fEMEventCut.SetRequireSel8(eventcuts.cfgRequireSel8); - fEMEventCut.SetRequireFT0AND(eventcuts.cfgRequireFT0AND); - fEMEventCut.SetZvtxRange(eventcuts.cfgZvtxMin, +eventcuts.cfgZvtxMax); - fEMEventCut.SetRequireNoTFB(eventcuts.cfgRequireNoTFB); - fEMEventCut.SetRequireNoITSROFB(eventcuts.cfgRequireNoITSROFB); - fEMEventCut.SetRequireNoSameBunchPileup(eventcuts.cfgRequireNoSameBunchPileup); - fEMEventCut.SetRequireGoodZvtxFT0vsPV(eventcuts.cfgRequireGoodZvtxFT0vsPV); - } - - void DefinePCMCut() - { - fV0PhotonCut = V0PhotonCut("fV0PhotonCut", "fV0PhotonCut"); - - // for v0 - fV0PhotonCut.SetV0PtRange(pcmcuts.cfg_min_pt_v0, pcmcuts.cfg_max_pt_v0); - fV0PhotonCut.SetV0EtaRange(pcmcuts.cfg_min_eta_v0, pcmcuts.cfg_max_eta_v0); - fV0PhotonCut.SetMinCosPA(pcmcuts.cfg_min_cospa); - fV0PhotonCut.SetMaxPCA(pcmcuts.cfg_max_pca); - fV0PhotonCut.SetMaxChi2KF(pcmcuts.cfg_max_chi2kf); - fV0PhotonCut.SetRxyRange(pcmcuts.cfg_min_v0radius, pcmcuts.cfg_max_v0radius); - fV0PhotonCut.SetAPRange(pcmcuts.cfg_max_alpha_ap, pcmcuts.cfg_max_qt_ap); - fV0PhotonCut.RejectITSib(pcmcuts.cfg_reject_v0_on_itsib); - - // for track - fV0PhotonCut.SetMinNClustersTPC(pcmcuts.cfg_min_ncluster_tpc); - fV0PhotonCut.SetMinNCrossedRowsTPC(pcmcuts.cfg_min_ncrossedrows); - fV0PhotonCut.SetMinNCrossedRowsOverFindableClustersTPC(0.8); - fV0PhotonCut.SetMaxFracSharedClustersTPC(pcmcuts.cfg_max_frac_shared_clusters_tpc); - fV0PhotonCut.SetChi2PerClusterTPC(0.0, pcmcuts.cfg_max_chi2tpc); - fV0PhotonCut.SetTPCNsigmaElRange(pcmcuts.cfg_min_TPCNsigmaEl, pcmcuts.cfg_max_TPCNsigmaEl); - fV0PhotonCut.SetChi2PerClusterITS(-1e+10, pcmcuts.cfg_max_chi2its); - fV0PhotonCut.SetNClustersITS(0, 7); - fV0PhotonCut.SetMeanClusterSizeITSob(0.0, 16.0); - fV0PhotonCut.SetDisableITSonly(pcmcuts.cfg_disable_itsonly_track); - fV0PhotonCut.SetDisableTPConly(pcmcuts.cfg_disable_tpconly_track); - fV0PhotonCut.SetRequireITSTPC(pcmcuts.cfg_require_v0_with_itstpc); - fV0PhotonCut.SetRequireITSonly(pcmcuts.cfg_require_v0_with_itsonly); - fV0PhotonCut.SetRequireTPConly(pcmcuts.cfg_require_v0_with_tpconly); - } - - void DefineDileptonCut() - { - fDileptonCut = DalitzEECut("fDileptonCut", "fDileptonCut"); - - // for pair - fDileptonCut.SetMeeRange(dileptoncuts.cfg_min_mass, dileptoncuts.cfg_max_mass); - fDileptonCut.SetMaxPhivPairMeeDep([&](float mll) { return (mll - dileptoncuts.cfg_phiv_intercept) / dileptoncuts.cfg_phiv_slope; }); - fDileptonCut.ApplyPhiV(dileptoncuts.cfg_apply_phiv); - fDileptonCut.RequireITSibAny(dileptoncuts.cfg_require_itsib_any); - fDileptonCut.RequireITSib1st(dileptoncuts.cfg_require_itsib_1st); - - // for track - fDileptonCut.SetTrackPtRange(dileptoncuts.cfg_min_pt_track, 1e+10f); - fDileptonCut.SetTrackEtaRange(-dileptoncuts.cfg_max_eta_track, +dileptoncuts.cfg_max_eta_track); - fDileptonCut.SetMinNClustersTPC(dileptoncuts.cfg_min_ncluster_tpc); - fDileptonCut.SetMinNCrossedRowsTPC(dileptoncuts.cfg_min_ncrossedrows); - fDileptonCut.SetMinNCrossedRowsOverFindableClustersTPC(0.8); - fDileptonCut.SetMaxFracSharedClustersTPC(dileptoncuts.cfg_max_frac_shared_clusters_tpc); - fDileptonCut.SetChi2PerClusterTPC(0.0, dileptoncuts.cfg_max_chi2tpc); - fDileptonCut.SetChi2PerClusterITS(0.0, dileptoncuts.cfg_max_chi2its); - fDileptonCut.SetNClustersITS(dileptoncuts.cfg_min_ncluster_its, 7); - fDileptonCut.SetMaxDcaXY(dileptoncuts.cfg_max_dcaxy); - fDileptonCut.SetMaxDcaZ(dileptoncuts.cfg_max_dcaz); - fDileptonCut.SetTrackDca3DRange(0.f, dileptoncuts.cfg_max_dca3dsigma_track); // in sigma - fDileptonCut.IncludeITSsa(false, 0.15); - - // for eID - fDileptonCut.SetPIDScheme(dileptoncuts.cfg_pid_scheme); - fDileptonCut.SetTPCNsigmaElRange(dileptoncuts.cfg_min_TPCNsigmaEl, dileptoncuts.cfg_max_TPCNsigmaEl); - fDileptonCut.SetTPCNsigmaPiRange(dileptoncuts.cfg_min_TPCNsigmaPi, dileptoncuts.cfg_max_TPCNsigmaPi); - fDileptonCut.SetTOFNsigmaElRange(dileptoncuts.cfg_min_TOFNsigmaEl, dileptoncuts.cfg_max_TOFNsigmaEl); - } - - void DefineEMTrackCut() - { - fEMTrackCut = EMTrackCut("fEMTrackCut", "fEMTrackCut"); - fEMTrackCut.SetTrackPtRange(trackcuts.cfg_min_pt_track, trackcuts.cfg_max_pt_track); - fEMTrackCut.SetTrackEtaRange(trackcuts.cfg_min_eta_track, trackcuts.cfg_max_eta_track); - // fEMTrackCut.SetTrackPhiRange(trackcuts.cfg_min_phi_track, trackcuts.cfg_max_phi_track); - // fEMTrackCut.SetTrackMaxDcaXY(trackcuts.cfg_max_dcaxy); - // fEMTrackCut.SetTrackMaxDcaZ(trackcuts.cfg_max_dcaz); - fEMTrackCut.SetTrackBit(trackcuts.cfg_track_bits); - } - - SliceCache cache; - Preslice perCollision_pcm = aod::v0photonkf::emeventId; - - Preslice perCollision_electron = aod::emprimaryelectron::emeventId; - Partition positrons = o2::aod::emprimaryelectron::sign > int8_t(0) && static_cast(dileptoncuts.cfg_min_pt_track) < o2::aod::track::pt&& nabs(o2::aod::track::eta) < static_cast(dileptoncuts.cfg_max_eta_track) && static_cast(dileptoncuts.cfg_min_TPCNsigmaEl) < o2::aod::pidtpc::tpcNSigmaEl&& o2::aod::pidtpc::tpcNSigmaEl < static_cast(dileptoncuts.cfg_max_TPCNsigmaEl); - Partition electrons = o2::aod::emprimaryelectron::sign < int8_t(0) && static_cast(dileptoncuts.cfg_min_pt_track) < o2::aod::track::pt && nabs(o2::aod::track::eta) < static_cast(dileptoncuts.cfg_max_eta_track) && static_cast(dileptoncuts.cfg_min_TPCNsigmaEl) < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < static_cast(dileptoncuts.cfg_max_TPCNsigmaEl); - - using RefTracks = soa::Join; - using RefTrack = RefTracks::iterator; - Preslice perCollision_track = aod::emprimarytrack::emeventId; - Filter refTrackFilter = trackcuts.cfg_min_pt_track < 1 / nabs(o2::aod::emprimarytrack::signed1Pt) && 1 / nabs(o2::aod::emprimarytrack::signed1Pt) < trackcuts.cfg_max_pt_track && trackcuts.cfg_min_eta_track < o2::aod::emprimarytrack::eta && o2::aod::emprimarytrack::eta < trackcuts.cfg_max_eta_track; - using FilteredRefTracks = soa::Filtered; - using FilteredRefTrack = FilteredRefTracks::iterator; - - using MyEMH = o2::aod::pwgem::dilepton::utils::EventMixingHandler, std::pair, EMTrack>; - MyEMH* emh1 = nullptr; - MyEMH* emh2 = nullptr; - using MyEMH_track = o2::aod::pwgem::dilepton::utils::EventMixingHandler, std::pair, EMTrack>; // for charged track - MyEMH_track* emh_diphoton = nullptr; - MyEMH_track* emh_ref = nullptr; - - std::vector used_photonIds_per_col; // - std::vector> used_dileptonIds_per_col; // - std::vector> used_diphotonIds_per_col; // - std::map, uint64_t> map_mixed_eventId_to_globalBC; - - template - void run2PC(TCollisions const& collisions, - TPhotons1 const& photons1, TPhotons2 const& photons2, TSubInfos1 const&, TSubInfos2 const&, TPreslice1 const& perCollision1, TPreslice2 const& perCollision2, TCut1 const& cut1, TCut2 const& cut2, - TRefTracks const& refTracks) - { - for (const auto& collision : collisions) { - initCCDB(collision); - int ndiphoton = 0; - - const float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; - if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { - continue; - } - - if constexpr (isTriggerAnalysis) { - if (!collision.swtalias_bit(o2::aod::pwgem::dilepton::swt::aliasLabels.at(cfg_swt_name.value))) { - continue; - } - } - - o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<0>(&fRegistry, collision, 1.f); - if (!fEMEventCut.IsSelected(collision)) { - continue; - } - if (eventcuts.cfgRequireGoodRCT && !rctChecker.checkTable(collision)) { - continue; - } - o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<1>(&fRegistry, collision, 1.f); - fRegistry.fill(HIST("Event/before/hCollisionCounter"), 12.0, 1.f); // accepted - fRegistry.fill(HIST("Event/after/hCollisionCounter"), 12.0, 1.f); // accepted - - int zbin = lower_bound(zvtx_bin_edges.begin(), zvtx_bin_edges.end(), collision.posZ()) - zvtx_bin_edges.begin() - 1; - if (zbin < 0) { - zbin = 0; - } else if (static_cast(zvtx_bin_edges.size()) - 2 < zbin) { - zbin = static_cast(zvtx_bin_edges.size()) - 2; - } - - float centrality = centralities[cfgCentEstimator]; - int centbin = lower_bound(cent_bin_edges.begin(), cent_bin_edges.end(), centrality) - cent_bin_edges.begin() - 1; - if (centbin < 0) { - centbin = 0; - } else if (static_cast(cent_bin_edges.size()) - 2 < centbin) { - centbin = static_cast(cent_bin_edges.size()) - 2; - } - - int epbin = 0; - - int occbin = -1; - if (cfgOccupancyEstimator == 0) { - occbin = lower_bound(occ_bin_edges.begin(), occ_bin_edges.end(), collision.ft0cOccupancyInTimeRange()) - occ_bin_edges.begin() - 1; - } else if (cfgOccupancyEstimator == 1) { - occbin = lower_bound(occ_bin_edges.begin(), occ_bin_edges.end(), collision.trackOccupancyInTimeRange()) - occ_bin_edges.begin() - 1; - } else { - occbin = lower_bound(occ_bin_edges.begin(), occ_bin_edges.end(), collision.ft0cOccupancyInTimeRange()) - occ_bin_edges.begin() - 1; - } - - if (occbin < 0) { - occbin = 0; - } else if (static_cast(occ_bin_edges.size()) - 2 < occbin) { - occbin = static_cast(occ_bin_edges.size()) - 2; - } - - // LOGF(info, "collision.globalIndex() = %d, collision.posZ() = %f, centrality = %f, ep2 = %f, collision.trackOccupancyInTimeRange() = %d, zbin = %d, centbin = %d, epbin = %d, occbin = %d", collision.globalIndex(), collision.posZ(), centrality, ep2, collision.trackOccupancyInTimeRange(), zbin, centbin, epbin, occbin); - - auto refTracks_per_collision = refTracks.sliceBy(perCollision_track, collision.globalIndex()); - - std::tuple key_bin = std::make_tuple(zbin, centbin, epbin, occbin); - std::pair key_df_collision = std::make_pair(ndf, collision.globalIndex()); - - if constexpr (pairtype == PairType::kPCMPCM) { // same kinds pairing - auto photons1_per_collision = photons1.sliceBy(perCollision1, collision.globalIndex()); - auto photons2_per_collision = photons2.sliceBy(perCollision2, collision.globalIndex()); - - for (const auto& [g1, g2] : combinations(CombinationsStrictlyUpperIndexPolicy(photons1_per_collision, photons2_per_collision))) { - if (!cut1.template IsSelected(g1) || !cut2.template IsSelected(g2)) { - continue; - } - - ROOT::Math::PtEtaPhiMVector v1(g1.pt(), g1.eta(), g1.phi(), 0.); - ROOT::Math::PtEtaPhiMVector v2(g2.pt(), g2.eta(), g2.phi(), 0.); - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - if (std::fabs(v12.Rapidity()) > maxY) { - continue; - } - fRegistry.fill(HIST("Diphoton/same/hs"), v12.M(), v12.Pt()); - auto pos1 = g1.template posTrack_as(); - auto ele1 = g1.template negTrack_as(); - auto pos2 = g2.template posTrack_as(); - auto ele2 = g2.template negTrack_as(); - - int npair = 0; // the number of diphoton-h pairs - for (const auto& track : refTracks_per_collision) { - if (pos1.trackId() == track.trackId() || ele1.trackId() == track.trackId()) { - continue; - } - if (pos2.trackId() == track.trackId() || ele2.trackId() == track.trackId()) { - continue; - } - - if (fEMTrackCut.IsSelected(track)) { - ROOT::Math::PtEtaPhiMVector v3(track.pt(), track.eta(), track.phi(), 0.139); - float deta = v12.Eta() - v3.Eta(); - float dphi = v12.Phi() - v3.Phi(); - // o2::math_utils::bringTo02Pi(dphi); - dphi = RecoDecay::constrainAngle(dphi, -o2::constants::math::PIHalf, 1U); - fRegistry.fill(HIST("DiphotonHadron/same/hs"), v12.M(), v12.Pt(), deta, dphi); - npair++; - } - } // end of ref track loop - - if (npair > 0) { - std::tuple tuple_tmp_diphoton = std::make_tuple(g1.globalIndex(), g2.globalIndex(), -1); - if (std::find(used_diphotonIds_per_col.begin(), used_diphotonIds_per_col.end(), tuple_tmp_diphoton) == used_diphotonIds_per_col.end()) { - emh_diphoton->AddTrackToEventPool(key_df_collision, EMTrack(v12.Pt(), v12.Eta(), v12.Phi(), v12.M())); - used_diphotonIds_per_col.emplace_back(tuple_tmp_diphoton); - } - } - - if (std::find(used_photonIds_per_col.begin(), used_photonIds_per_col.end(), g1.globalIndex()) == used_photonIds_per_col.end()) { - emh1->AddTrackToEventPool(key_df_collision, EMTrack(g1.pt(), g1.eta(), g1.phi(), 0)); - used_photonIds_per_col.emplace_back(g1.globalIndex()); - } - if (std::find(used_photonIds_per_col.begin(), used_photonIds_per_col.end(), g2.globalIndex()) == used_photonIds_per_col.end()) { - emh1->AddTrackToEventPool(key_df_collision, EMTrack(g2.pt(), g2.eta(), g2.phi(), 0)); - used_photonIds_per_col.emplace_back(g2.globalIndex()); - } - ndiphoton++; - } // end of pairing loop - } else if constexpr (pairtype == PairType::kPCMDalitzEE) { - auto photons1_per_collision = photons1.sliceBy(perCollision1, collision.globalIndex()); - auto positrons_per_collision = positrons->sliceByCached(o2::aod::emprimaryelectron::emeventId, collision.globalIndex(), cache); - auto electrons_per_collision = electrons->sliceByCached(o2::aod::emprimaryelectron::emeventId, collision.globalIndex(), cache); - - for (const auto& g1 : photons1_per_collision) { - if (!cut1.template IsSelected(g1)) { - continue; - } - auto pos1 = g1.template posTrack_as(); - auto ele1 = g1.template negTrack_as(); - ROOT::Math::PtEtaPhiMVector v_gamma(g1.pt(), g1.eta(), g1.phi(), 0.); - - for (const auto& [pos2, ele2] : combinations(CombinationsFullIndexPolicy(positrons_per_collision, electrons_per_collision))) { - - if (pos2.trackId() == ele2.trackId()) { // this is protection against pairing identical 2 tracks. - continue; - } - if (pos1.trackId() == pos2.trackId() || ele1.trackId() == ele2.trackId()) { - continue; - } - - if (!cut2.template IsSelectedTrack(pos2, collision) || !cut2.template IsSelectedTrack(ele2, collision)) { - continue; - } - - if (!cut2.IsSelectedPair(pos2, ele2, d_bz)) { - continue; - } - - ROOT::Math::PtEtaPhiMVector v_pos(pos2.pt(), pos2.eta(), pos2.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v_ele(ele2.pt(), ele2.eta(), ele2.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v_ee = v_pos + v_ele; - ROOT::Math::PtEtaPhiMVector veeg = v_gamma + v_pos + v_ele; - if (std::fabs(veeg.Rapidity()) > maxY) { - continue; - } - fRegistry.fill(HIST("Diphoton/same/hs"), veeg.M(), veeg.Pt()); - - int npair = 0; // the number of diphoton-h pairs - for (const auto& track : refTracks_per_collision) { - if (pos1.trackId() == track.trackId() || ele1.trackId() == track.trackId()) { - continue; - } - if (pos2.trackId() == track.trackId() || ele2.trackId() == track.trackId()) { - continue; - } - - ROOT::Math::PtEtaPhiMVector v3(track.pt(), track.eta(), track.phi(), 0.139); - float deta = veeg.Eta() - v3.Eta(); - float dphi = veeg.Phi() - v3.Phi(); - // o2::math_utils::bringTo02Pi(dphi); - dphi = RecoDecay::constrainAngle(dphi, -o2::constants::math::PIHalf, 1U); - fRegistry.fill(HIST("DiphotonHadron/same/hs"), veeg.M(), veeg.Pt(), deta, dphi); - npair++; - - } // end of ref track loop - - if (npair > 0) { - std::tuple tuple_tmp_diphoton = std::make_tuple(g1.globalIndex(), pos2.trackId(), ele2.trackId()); - if (std::find(used_diphotonIds_per_col.begin(), used_diphotonIds_per_col.end(), tuple_tmp_diphoton) == used_diphotonIds_per_col.end()) { - emh_diphoton->AddTrackToEventPool(key_df_collision, EMTrack(veeg.Pt(), veeg.Eta(), veeg.Phi(), veeg.M())); - used_diphotonIds_per_col.emplace_back(tuple_tmp_diphoton); - } - } - - std::pair tuple_tmp_id2 = std::make_pair(pos2.trackId(), ele2.trackId()); - if (std::find(used_photonIds_per_col.begin(), used_photonIds_per_col.end(), g1.globalIndex()) == used_photonIds_per_col.end()) { - emh1->AddTrackToEventPool(key_df_collision, EMTrack(g1.pt(), g1.eta(), g1.phi(), 0)); - used_photonIds_per_col.emplace_back(g1.globalIndex()); - } - if (std::find(used_dileptonIds_per_col.begin(), used_dileptonIds_per_col.end(), tuple_tmp_id2) == used_dileptonIds_per_col.end()) { - emh2->AddTrackToEventPool(key_df_collision, EMTrack(v_ee.Pt(), v_ee.Eta(), v_ee.Phi(), v_ee.M())); - used_dileptonIds_per_col.emplace_back(tuple_tmp_id2); - } - ndiphoton++; - } // end of dielectron loop - } // end of g1 loop - } // end of pairing in same event - - used_photonIds_per_col.clear(); - used_photonIds_per_col.shrink_to_fit(); - used_dileptonIds_per_col.clear(); - used_dileptonIds_per_col.shrink_to_fit(); - used_diphotonIds_per_col.clear(); - used_diphotonIds_per_col.shrink_to_fit(); - - if (ndiphoton > 0) { - emh_ref->ReserveNTracksPerCollision(key_df_collision, refTracks_per_collision.size()); - for (const auto& track : refTracks_per_collision) { - if (fEMTrackCut.IsSelected(track)) { - fRegistry.fill(HIST("Hadron/hs"), track.pt(), track.eta(), track.phi()); - fRegistry.fill(HIST("Hadron/hTrackBit"), track.trackBit()); - emh_ref->AddTrackToEventPool(key_df_collision, EMTrack(track.pt(), track.eta(), track.phi(), 0.139)); - } - } - - for (const auto& [ref1, ref2] : combinations(CombinationsStrictlyUpperIndexPolicy(refTracks_per_collision, refTracks_per_collision))) { - if (fEMTrackCut.IsSelected(ref1) && fEMTrackCut.IsSelected(ref2)) { - float deta = ref1.eta() - ref2.eta(); - float dphi = ref1.phi() - ref2.phi(); - // o2::math_utils::bringTo02Pi(dphi); - dphi = RecoDecay::constrainAngle(dphi, -o2::constants::math::PIHalf, 1U); - fRegistry.fill(HIST("HadronHadron/same/hDEtaDPhi"), dphi, deta); - } - } - } - - // event mixing - if (!cfgDoMix || !(ndiphoton > 0)) { - continue; - } - - // make a vector of selected photons in this collision. - auto selected_photons1_in_this_event = emh1->GetTracksPerCollision(key_df_collision); - auto selected_photons2_in_this_event = emh2->GetTracksPerCollision(key_df_collision); - auto selected_refTracks_in_this_event = emh_ref->GetTracksPerCollision(key_df_collision); - auto selected_diphotons_in_this_event = emh_diphoton->GetTracksPerCollision(key_df_collision); - - auto collisionIds1_in_mixing_pool = emh1->GetCollisionIdsFromEventPool(key_bin); - auto collisionIds2_in_mixing_pool = emh2->GetCollisionIdsFromEventPool(key_bin); - auto collisionIdsRef_in_mixing_pool = emh_ref->GetCollisionIdsFromEventPool(key_bin); - auto collisionIdsDiphoton_in_mixing_pool = emh_diphoton->GetCollisionIdsFromEventPool(key_bin); - - if constexpr (pairtype == PairType::kPCMPCM) { // same kinds pairing - for (const auto& mix_dfId_collisionId : collisionIds1_in_mixing_pool) { - int mix_dfId = mix_dfId_collisionId.first; - int64_t mix_collisionId = mix_dfId_collisionId.second; - - if (collision.globalIndex() == mix_collisionId && ndf == mix_dfId) { // this never happens. only protection. - continue; - } - - auto globalBC_mix = map_mixed_eventId_to_globalBC[mix_dfId_collisionId]; - uint64_t diffBC = std::max(collision.globalBC(), globalBC_mix) - std::min(collision.globalBC(), globalBC_mix); - fRegistry.fill(HIST("Diphoton/mix/hDiffBC"), diffBC); - if (diffBC < ndiff_bc_mix) { - continue; - } - - auto photons1_from_event_pool = emh1->GetTracksPerCollision(mix_dfId_collisionId); - // LOGF(info, "Do event mixing: current event (%d, %d), ngamma = %d | event pool (%d, %d), ngamma = %d", ndf, collision.globalIndex(), selected_photons1_in_this_event.size(), mix_dfId, mix_collisionId, photons1_from_event_pool.size()); - - for (const auto& g1 : selected_photons1_in_this_event) { - for (const auto& g2 : photons1_from_event_pool) { - ROOT::Math::PtEtaPhiMVector v1(g1.pt(), g1.eta(), g1.phi(), 0.); - ROOT::Math::PtEtaPhiMVector v2(g2.pt(), g2.eta(), g2.phi(), 0.); - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - if (std::fabs(v12.Rapidity()) > maxY) { - continue; - } - fRegistry.fill(HIST("Diphoton/mix/hs"), v12.M(), v12.Pt(), 1.f); - } - } - } // end of loop over mixed event pool between photon-photon - - for (const auto& mix_dfId_collisionId : collisionIdsRef_in_mixing_pool) { - int mix_dfId = mix_dfId_collisionId.first; - int64_t mix_collisionId = mix_dfId_collisionId.second; - - if (collision.globalIndex() == mix_collisionId && ndf == mix_dfId) { // this never happens. only protection. - continue; - } - - auto globalBC_mix = map_mixed_eventId_to_globalBC[mix_dfId_collisionId]; - uint64_t diffBC = std::max(collision.globalBC(), globalBC_mix) - std::min(collision.globalBC(), globalBC_mix); - if (diffBC < ndiff_bc_mix) { - continue; - } - - auto refTracks_from_event_pool = emh_ref->GetTracksPerCollision(mix_dfId_collisionId); - for (const auto& trg : selected_diphotons_in_this_event) { - for (const auto& ref : refTracks_from_event_pool) { - float deta = trg.eta() - ref.eta(); - float dphi = trg.phi() - ref.phi(); - // o2::math_utils::bringTo02Pi(dphi); - dphi = RecoDecay::constrainAngle(dphi, -o2::constants::math::PIHalf, 1U); - fRegistry.fill(HIST("DiphotonHadron/mix/hs"), trg.mass(), trg.pt(), deta, dphi); - } - } - } // end of loop over mixed event pool between diphoton-hadron - - } else { // [photon1 from event1, photon2 from event2] and [photon1 from event2, photon2 from event1] - for (const auto& mix_dfId_collisionId : collisionIds2_in_mixing_pool) { - int mix_dfId = mix_dfId_collisionId.first; - int64_t mix_collisionId = mix_dfId_collisionId.second; - - if (collision.globalIndex() == mix_collisionId && ndf == mix_dfId) { // this never happens. only protection. - continue; - } - - auto globalBC_mix = map_mixed_eventId_to_globalBC[mix_dfId_collisionId]; - uint64_t diffBC = std::max(collision.globalBC(), globalBC_mix) - std::min(collision.globalBC(), globalBC_mix); - fRegistry.fill(HIST("Diphoton/mix/hDiffBC"), diffBC); - if (diffBC < ndiff_bc_mix) { - continue; - } - - auto photons2_from_event_pool = emh2->GetTracksPerCollision(mix_dfId_collisionId); - // LOGF(info, "Do event mixing: current event (%d, %d), ngamma = %d | event pool (%d, %d), nll = %d", ndf, collision.globalIndex(), selected_photons1_in_this_event.size(), mix_dfId, mix_collisionId, photons2_from_event_pool.size()); - - for (const auto& g1 : selected_photons1_in_this_event) { - for (const auto& g2 : photons2_from_event_pool) { - ROOT::Math::PtEtaPhiMVector v1(g1.pt(), g1.eta(), g1.phi(), 0.); - ROOT::Math::PtEtaPhiMVector v2(g2.pt(), g2.eta(), g2.phi(), 0.); - if constexpr (pairtype == PairType::kPCMDalitzEE) { //[photon from event1, dilepton from event2] and [photon from event2, dilepton from event1] - v2.SetM(g2.mass()); - } - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - if (std::fabs(v12.Rapidity()) > maxY) { - continue; - } - fRegistry.fill(HIST("Diphoton/mix/hs"), v12.M(), v12.Pt(), 1.f); - } - } - } // end of loop over mixed event pool between photon-photon - - for (const auto& mix_dfId_collisionId : collisionIds1_in_mixing_pool) { - int mix_dfId = mix_dfId_collisionId.first; - int64_t mix_collisionId = mix_dfId_collisionId.second; - - if (collision.globalIndex() == mix_collisionId && ndf == mix_dfId) { // this never happens. only protection. - continue; - } - - auto globalBC_mix = map_mixed_eventId_to_globalBC[mix_dfId_collisionId]; - uint64_t diffBC = std::max(collision.globalBC(), globalBC_mix) - std::min(collision.globalBC(), globalBC_mix); - fRegistry.fill(HIST("Diphoton/mix/hDiffBC"), diffBC); - if (diffBC < ndiff_bc_mix) { - continue; - } - - auto photons1_from_event_pool = emh1->GetTracksPerCollision(mix_dfId_collisionId); - // LOGF(info, "Do event mixing: current event (%d, %d), nll = %d | event pool (%d, %d), ngamma = %d", ndf, collision.globalIndex(), selected_photons2_in_this_event.size(), mix_dfId, mix_collisionId, photons1_from_event_pool.size()); - - for (const auto& g1 : selected_photons2_in_this_event) { - for (const auto& g2 : photons1_from_event_pool) { - ROOT::Math::PtEtaPhiMVector v1(g1.pt(), g1.eta(), g1.phi(), 0.); - ROOT::Math::PtEtaPhiMVector v2(g2.pt(), g2.eta(), g2.phi(), 0.); - if constexpr (pairtype == PairType::kPCMDalitzEE) { //[photon from event1, dilepton from event2] and [photon from event2, dilepton from event1] - v1.SetM(g1.mass()); - } - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - if (std::fabs(v12.Rapidity()) > maxY) { - continue; - } - fRegistry.fill(HIST("Diphoton/mix/hs"), v12.M(), v12.Pt(), 1.f); - } - } - } // end of loop over mixed event pool between photon-photon - - for (const auto& mix_dfId_collisionId : collisionIdsRef_in_mixing_pool) { - int mix_dfId = mix_dfId_collisionId.first; - int64_t mix_collisionId = mix_dfId_collisionId.second; - - if (collision.globalIndex() == mix_collisionId && ndf == mix_dfId) { // this never happens. only protection. - continue; - } - - auto globalBC_mix = map_mixed_eventId_to_globalBC[mix_dfId_collisionId]; - uint64_t diffBC = std::max(collision.globalBC(), globalBC_mix) - std::min(collision.globalBC(), globalBC_mix); - if (diffBC < ndiff_bc_mix) { - continue; - } - - auto refTracks_from_event_pool = emh_ref->GetTracksPerCollision(mix_dfId_collisionId); - for (const auto& trg : selected_diphotons_in_this_event) { - for (const auto& ref : refTracks_from_event_pool) { - float deta = trg.eta() - ref.eta(); - float dphi = trg.phi() - ref.phi(); - // o2::math_utils::bringTo02Pi(dphi); - dphi = RecoDecay::constrainAngle(dphi, -o2::constants::math::PIHalf, 1U); - fRegistry.fill(HIST("DiphotonHadron/mix/hs"), trg.mass(), trg.pt(), deta, dphi); - } - } - } // end of loop over mixed event pool between diphoton-hadron - } - - // hadron-hadron mixed event - for (const auto& mix_dfId_collisionId : collisionIdsRef_in_mixing_pool) { - int mix_dfId = mix_dfId_collisionId.first; - int64_t mix_collisionId = mix_dfId_collisionId.second; - - if (collision.globalIndex() == mix_collisionId && ndf == mix_dfId) { // this never happens. only protection. - continue; - } - - auto globalBC_mix = map_mixed_eventId_to_globalBC[mix_dfId_collisionId]; - uint64_t diffBC = std::max(collision.globalBC(), globalBC_mix) - std::min(collision.globalBC(), globalBC_mix); - if (diffBC < ndiff_bc_mix) { - continue; - } - - auto refTracks_from_event_pool = emh_ref->GetTracksPerCollision(mix_dfId_collisionId); - for (const auto& ref1 : selected_refTracks_in_this_event) { - for (const auto& ref2 : refTracks_from_event_pool) { - float deta = ref1.eta() - ref2.eta(); - float dphi = ref1.phi() - ref2.phi(); - // o2::math_utils::bringTo02Pi(dphi); - dphi = RecoDecay::constrainAngle(dphi, -o2::constants::math::PIHalf, 1U); - fRegistry.fill(HIST("HadronHadron/mix/hDEtaDPhi"), dphi, deta); - } - } - } // end of loop over mixed event pool between hadron-hadron - - if (ndiphoton > 0) { - emh1->AddCollisionIdAtLast(key_bin, key_df_collision); - emh2->AddCollisionIdAtLast(key_bin, key_df_collision); - emh_diphoton->AddCollisionIdAtLast(key_bin, key_df_collision); - emh_ref->AddCollisionIdAtLast(key_bin, key_df_collision); - map_mixed_eventId_to_globalBC[key_df_collision] = collision.globalBC(); - } - - } // end of collision loop - } - - Filter collisionFilter_occupancy_track = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; - Filter collisionFilter_occupancy_ft0c = eventcuts.cfgFT0COccupancyMin <= o2::aod::evsel::ft0cOccupancyInTimeRange && o2::aod::evsel::ft0cOccupancyInTimeRange < eventcuts.cfgFT0COccupancyMax; - Filter collisionFilter_centrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); - using FilteredMyCollisions = soa::Filtered; - - Filter prefilter_pcm = ifnode(pcmcuts.cfg_apply_cuts_from_prefilter_derived.node(), o2::aod::v0photonkf::pfbderived == static_cast(0), true); - Filter prefilter_primaryelectron = ifnode(dileptoncuts.cfg_apply_cuts_from_prefilter_derived.node(), o2::aod::emprimaryelectron::pfbderived == static_cast(0), true); - - int ndf = 0; - void processAnalysis(FilteredMyCollisions const& collisions, FilteredRefTracks const& refTracks, Types const&... args) - { - // LOGF(info, "ndf = %d", ndf); - if constexpr (pairtype == PairType::kPCMPCM) { - auto v0photons = std::get<0>(std::tie(args...)); - auto v0legs = std::get<1>(std::tie(args...)); - run2PC(collisions, v0photons, v0photons, v0legs, v0legs, perCollision_pcm, perCollision_pcm, fV0PhotonCut, fV0PhotonCut, refTracks); - } else if constexpr (pairtype == PairType::kPCMDalitzEE) { - auto v0photons = std::get<0>(std::tie(args...)); - auto v0legs = std::get<1>(std::tie(args...)); - auto emprimaryelectrons = std::get<2>(std::tie(args...)); - // LOGF(info, "electrons.size() = %d, positrons.size() = %d", electrons.size(), positrons.size()); - run2PC(collisions, v0photons, emprimaryelectrons, v0legs, emprimaryelectrons, perCollision_pcm, perCollision_electron, fV0PhotonCut, fDileptonCut, refTracks); - } - ndf++; - } - PROCESS_SWITCH(DiphotonHadronMPC, processAnalysis, "process pair analysis", true); - - // using FilteredMyCollisionsWithSWT = soa::Filtered; - void processTriggerAnalysis(MyCollisionsWithSWT const& collisions, FilteredRefTracks const& refTracks, Types const&... args) - { - // LOGF(info, "ndf = %d", ndf); - if constexpr (pairtype == PairType::kPCMPCM) { - auto v0photons = std::get<0>(std::tie(args...)); - auto v0legs = std::get<1>(std::tie(args...)); - run2PC(collisions, v0photons, v0photons, v0legs, v0legs, perCollision_pcm, perCollision_pcm, fV0PhotonCut, fV0PhotonCut, refTracks); - } else if constexpr (pairtype == PairType::kPCMDalitzEE) { - auto v0photons = std::get<0>(std::tie(args...)); - auto v0legs = std::get<1>(std::tie(args...)); - auto emprimaryelectrons = std::get<2>(std::tie(args...)); - // LOGF(info, "electrons.size() = %d, positrons.size() = %d", electrons.size(), positrons.size()); - run2PC(collisions, v0photons, emprimaryelectrons, v0legs, emprimaryelectrons, perCollision_pcm, perCollision_electron, fV0PhotonCut, fDileptonCut, refTracks); - } - ndf++; - } - PROCESS_SWITCH(DiphotonHadronMPC, processTriggerAnalysis, "process pair analysis with software trigger", false); - - void processDummy(MyCollisions const&) {} - PROCESS_SWITCH(DiphotonHadronMPC, processDummy, "Dummy function", false); -}; -#endif // PWGEM_PHOTONMESON_CORE_DIPHOTONHADRONMPC_H_ diff --git a/PWGEM/PhotonMeson/Core/EMCPhotonCut.h b/PWGEM/PhotonMeson/Core/EMCPhotonCut.h index 95ca402c913..57ed3fb4a2b 100644 --- a/PWGEM/PhotonMeson/Core/EMCPhotonCut.h +++ b/PWGEM/PhotonMeson/Core/EMCPhotonCut.h @@ -295,9 +295,9 @@ class EMCPhotonCut : public TNamed const bool doQA = mDoQA && fRegistry != nullptr; nTotClusterPerColl = 0; - currentCollID = clusters.iteratorAt(0).emeventId(); + currentCollID = clusters.iteratorAt(0).emphotoneventId(); for (const auto& cluster : clusters) { - const auto collID = cluster.emeventId(); + const auto collID = cluster.emphotoneventId(); if (doQA) { fillBeforeClusterHistogram(cluster, fRegistry); } @@ -376,7 +376,7 @@ class EMCPhotonCut : public TNamed } return false; } - if (currentCollID == cluster.emeventId()) { + if (currentCollID == cluster.emphotoneventId()) { ++nAccClusterPerColl; } else { if (doQA) { diff --git a/PWGEM/PhotonMeson/Core/EMPhotonEventCut.cxx b/PWGEM/PhotonMeson/Core/EMPhotonEventCut.cxx index 285bf50eba4..253020c7d69 100644 --- a/PWGEM/PhotonMeson/Core/EMPhotonEventCut.cxx +++ b/PWGEM/PhotonMeson/Core/EMPhotonEventCut.cxx @@ -18,6 +18,108 @@ ClassImp(EMPhotonEventCut); +void EMPhotonEventCut::SetRequireSel8(bool flag) +{ + mRequireSel8 = flag; + LOG(info) << "EM Event Cut, require sel8: " << mRequireSel8; +} + +void EMPhotonEventCut::SetRequireFT0AND(bool flag) +{ + mRequireFT0AND = flag; + LOG(info) << "EM Event Cut, require FT0AND: " << mRequireFT0AND; +} + +void EMPhotonEventCut::SetZvtxRange(float min, float max) +{ + mMinZvtx = min; + mMaxZvtx = max; + LOG(info) << "EM Event Cut, set z vtx range: " << mMinZvtx << " - " << mMaxZvtx; +} + +void EMPhotonEventCut::SetRequireNoTFB(bool flag) +{ + mRequireNoTFB = flag; + LOG(info) << "EM Event Cut, require No TF border: " << mRequireNoTFB; +} + +void EMPhotonEventCut::SetRequireNoITSROFB(bool flag) +{ + mRequireNoITSROFB = flag; + LOG(info) << "EM Event Cut, require No ITS ROF border: " << mRequireNoITSROFB; +} + +void EMPhotonEventCut::SetRequireNoSameBunchPileup(bool flag) +{ + mRequireNoSameBunchPileup = flag; + LOG(info) << "EM Event Cut, require No same bunch pileup: " << mRequireNoSameBunchPileup; +} + +void EMPhotonEventCut::SetRequireVertexITSTPC(bool flag) +{ + mRequireVertexITSTPC = flag; + LOG(info) << "EM Event Cut, require vertex reconstructed by ITS-TPC matched track: " << mRequireVertexITSTPC; +} + +void EMPhotonEventCut::SetRequireVertexTOFmatched(bool flag) +{ + mRequireVertexTOFmatched = flag; + LOG(info) << "EM Event Cut, require vertex reconstructed by ITS-TPC-TOF matched track: " << mRequireVertexTOFmatched; +} + +void EMPhotonEventCut::SetRequireGoodZvtxFT0vsPV(bool flag) +{ + mRequireGoodZvtxFT0vsPV = flag; + LOG(info) << "EM Event Cut, require good Zvtx between FT0 vs. PV: " << mRequireGoodZvtxFT0vsPV; +} + +void EMPhotonEventCut::SetRequireNoCollInTimeRangeStandard(bool flag) +{ + mRequireNoCollInTimeRangeStandard = flag; + LOG(info) << "EM Event Cut, require No collision in time range standard: " << mRequireNoCollInTimeRangeStandard; +} + +void EMPhotonEventCut::SetRequireNoCollInTimeRangeStrict(bool flag) +{ + mRequireNoCollInTimeRangeStrict = flag; + LOG(info) << "EM Event Cut, require No collision in time range strict: " << mRequireNoCollInTimeRangeStrict; +} +void EMPhotonEventCut::SetRequireNoCollInITSROFStandard(bool flag) +{ + mRequireNoCollInITSROFStandard = flag; + LOG(info) << "EM Event Cut, require No collision in ITS TOF standard: " << mRequireNoCollInITSROFStandard; +} + +void EMPhotonEventCut::SetRequireNoCollInITSROFStrict(bool flag) +{ + mRequireNoCollInITSROFStrict = flag; + LOG(info) << "EM Event Cut, require No collision in ITS ROF strict: " << mRequireNoCollInITSROFStrict; +} + +void EMPhotonEventCut::SetRequireNoHighMultCollInPrevRof(bool flag) +{ + mRequireNoHighMultCollInPrevRof = flag; + LOG(info) << "EM Event Cut, require No HM collision in previous ITS ROF: " << mRequireNoHighMultCollInPrevRof; +} + +void EMPhotonEventCut::SetRequireGoodITSLayer3(bool flag) +{ + mRequireGoodITSLayer3 = flag; + LOG(info) << "EM Event Cut, require GoodITSLayer3: " << mRequireGoodITSLayer3; +} + +void EMPhotonEventCut::SetRequireGoodITSLayer0123(bool flag) +{ + mRequireGoodITSLayer0123 = flag; + LOG(info) << "EM Event Cut, require GoodITSLayer0123: " << mRequireGoodITSLayer0123; +} + +void EMPhotonEventCut::SetRequireGoodITSLayersAll(bool flag) +{ + mRequireGoodITSLayersAll = flag; + LOG(info) << "EM Event Cut, require GoodITSLayersAll: " << mRequireGoodITSLayersAll; +} + void EMPhotonEventCut::SetRequireEMCReadoutInMB(bool flag) { mRequireEMCReadoutInMB = flag; diff --git a/PWGEM/PhotonMeson/Core/EMPhotonEventCut.h b/PWGEM/PhotonMeson/Core/EMPhotonEventCut.h index 3b134ce882e..1121a6fd922 100644 --- a/PWGEM/PhotonMeson/Core/EMPhotonEventCut.h +++ b/PWGEM/PhotonMeson/Core/EMPhotonEventCut.h @@ -16,18 +16,38 @@ #ifndef PWGEM_PHOTONMESON_CORE_EMPHOTONEVENTCUT_H_ #define PWGEM_PHOTONMESON_CORE_EMPHOTONEVENTCUT_H_ -#include "PWGEM/Dilepton/Core/EMEventCut.h" +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/TriggerAliases.h" + +#include "TNamed.h" using namespace std; -class EMPhotonEventCut : public EMEventCut +class EMPhotonEventCut : public TNamed { public: EMPhotonEventCut() = default; - EMPhotonEventCut(const char* name, const char* title) : EMEventCut(name, title) {} + EMPhotonEventCut(const char* name, const char* title) : TNamed(name, title) {} enum class EMPhotonEventCuts : int { - kEMCReadoutInMB = 0, + kSel8 = 0, + kFT0AND, + kZvtx, + kNoTFB, + kNoITSROFB, + kNoSameBunchPileup, + kIsVertexITSTPC, + kIsVertexTOFmatched, + kIsGoodZvtxFT0vsPV, + kNoCollInTimeRangeStandard, + kNoCollInTimeRangeStrict, + kNoCollInITSROFStandard, + kNoCollInITSROFStrict, + kNoHighMultCollInPrevRof, + kIsGoodITSLayer3, + kIsGoodITSLayer0123, + kIsGoodITSLayersAll, + kEMCReadoutInMB, kEMCHardwareTriggered, kNCuts }; @@ -35,7 +55,55 @@ class EMPhotonEventCut : public EMEventCut template bool IsSelected(T const& collision) const { - if (!EMEventCut::IsSelected(collision)) { + if (mRequireSel8 && !IsSelected(collision, EMPhotonEventCuts::kSel8)) { + return false; + } + if (mRequireFT0AND && !IsSelected(collision, EMPhotonEventCuts::kFT0AND)) { + return false; + } + if (!IsSelected(collision, EMPhotonEventCuts::kZvtx)) { + return false; + } + if (mRequireNoTFB && !IsSelected(collision, EMPhotonEventCuts::kNoTFB)) { + return false; + } + if (mRequireNoITSROFB && !IsSelected(collision, EMPhotonEventCuts::kNoITSROFB)) { + return false; + } + if (mRequireNoSameBunchPileup && !IsSelected(collision, EMPhotonEventCuts::kNoSameBunchPileup)) { + return false; + } + if (mRequireVertexITSTPC && !IsSelected(collision, EMPhotonEventCuts::kIsVertexITSTPC)) { + return false; + } + if (mRequireVertexTOFmatched && !IsSelected(collision, EMPhotonEventCuts::kIsVertexTOFmatched)) { + return false; + } + if (mRequireGoodZvtxFT0vsPV && !IsSelected(collision, EMPhotonEventCuts::kIsGoodZvtxFT0vsPV)) { + return false; + } + if (mRequireNoCollInTimeRangeStandard && !IsSelected(collision, EMPhotonEventCuts::kNoCollInTimeRangeStandard)) { + return false; + } + if (mRequireNoCollInTimeRangeStrict && !IsSelected(collision, EMPhotonEventCuts::kNoCollInTimeRangeStrict)) { + return false; + } + if (mRequireNoCollInITSROFStandard && !IsSelected(collision, EMPhotonEventCuts::kNoCollInITSROFStandard)) { + return false; + } + if (mRequireNoCollInITSROFStrict && !IsSelected(collision, EMPhotonEventCuts::kNoCollInITSROFStrict)) { + return false; + } + if (mRequireNoHighMultCollInPrevRof && !IsSelected(collision, EMPhotonEventCuts::kNoHighMultCollInPrevRof)) { + return false; + } + if (mRequireGoodITSLayer3 && !IsSelected(collision, EMPhotonEventCuts::kIsGoodITSLayer3)) { + return false; + } + if (mRequireGoodITSLayer0123 && !IsSelected(collision, EMPhotonEventCuts::kIsGoodITSLayer0123)) { + return false; + } + if (mRequireGoodITSLayersAll && !IsSelected(collision, EMPhotonEventCuts::kIsGoodITSLayersAll)) { return false; } if (mRequireEMCReadoutInMB && !IsSelected(collision, EMPhotonEventCuts::kEMCReadoutInMB)) { @@ -51,6 +119,57 @@ class EMPhotonEventCut : public EMEventCut bool IsSelected(T const& collision, const EMPhotonEventCuts& cut) const { switch (cut) { + case EMPhotonEventCuts::kSel8: + return collision.sel8(); + + case EMPhotonEventCuts::kFT0AND: + return collision.selection_bit(o2::aod::evsel::kIsTriggerTVX); + + case EMPhotonEventCuts::kZvtx: + return mMinZvtx < collision.posZ() && collision.posZ() < mMaxZvtx; + + case EMPhotonEventCuts::kNoTFB: + return collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder); + + case EMPhotonEventCuts::kNoITSROFB: + return collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder); + + case EMPhotonEventCuts::kNoSameBunchPileup: + return collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup); + + case EMPhotonEventCuts::kIsVertexITSTPC: + return collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC); + + case EMPhotonEventCuts::kIsVertexTOFmatched: + return collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched); + + case EMPhotonEventCuts::kIsGoodZvtxFT0vsPV: + return collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV); + + case EMPhotonEventCuts::kNoCollInTimeRangeStandard: + return collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard); + + case EMPhotonEventCuts::kNoCollInTimeRangeStrict: + return collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStrict); + + case EMPhotonEventCuts::kNoCollInITSROFStandard: + return collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard); + + case EMPhotonEventCuts::kNoCollInITSROFStrict: + return collision.selection_bit(o2::aod::evsel::kNoCollInRofStrict); + + case EMPhotonEventCuts::kNoHighMultCollInPrevRof: + return collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof); + + case EMPhotonEventCuts::kIsGoodITSLayer3: + return collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer3); + + case EMPhotonEventCuts::kIsGoodITSLayer0123: + return collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer0123); + + case EMPhotonEventCuts::kIsGoodITSLayersAll: + return collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll); + case EMPhotonEventCuts::kEMCReadoutInMB: return (collision.alias_bit(kTVXinEMC)); @@ -63,10 +182,44 @@ class EMPhotonEventCut : public EMEventCut } // Setters + void SetRequireSel8(bool flag); + void SetRequireFT0AND(bool flag); + void SetZvtxRange(float min, float max); + void SetRequireNoTFB(bool flag); + void SetRequireNoITSROFB(bool flag); + void SetRequireNoSameBunchPileup(bool flag); + void SetRequireVertexITSTPC(bool flag); + void SetRequireVertexTOFmatched(bool flag); + void SetRequireGoodZvtxFT0vsPV(bool flag); + void SetRequireNoCollInTimeRangeStandard(bool flag); + void SetRequireNoCollInTimeRangeStrict(bool flag); + void SetRequireNoCollInITSROFStandard(bool flag); + void SetRequireNoCollInITSROFStrict(bool flag); + void SetRequireNoHighMultCollInPrevRof(bool flag); + void SetRequireGoodITSLayer3(bool flag); + void SetRequireGoodITSLayer0123(bool flag); + void SetRequireGoodITSLayersAll(bool flag); void SetRequireEMCReadoutInMB(bool flag); void SetRequireEMCHardwareTriggered(bool flag); private: + bool mRequireSel8{false}; + bool mRequireFT0AND{true}; + float mMinZvtx{-10.f}, mMaxZvtx{+10.f}; + bool mRequireNoTFB{false}; + bool mRequireNoITSROFB{false}; + bool mRequireNoSameBunchPileup{false}; + bool mRequireVertexITSTPC{false}; + bool mRequireVertexTOFmatched{false}; + bool mRequireGoodZvtxFT0vsPV{false}; + bool mRequireNoCollInTimeRangeStandard{false}; + bool mRequireNoCollInTimeRangeStrict{false}; + bool mRequireNoCollInITSROFStandard{false}; + bool mRequireNoCollInITSROFStrict{false}; + bool mRequireNoHighMultCollInPrevRof{false}; + bool mRequireGoodITSLayer3{false}; + bool mRequireGoodITSLayer0123{false}; + bool mRequireGoodITSLayersAll{false}; bool mRequireEMCReadoutInMB{false}; bool mRequireEMCHardwareTriggered{false}; diff --git a/PWGEM/PhotonMeson/Core/PhotonHBT.h b/PWGEM/PhotonMeson/Core/PhotonHBT.h index 08738ce8e07..060768cdfde 100644 --- a/PWGEM/PhotonMeson/Core/PhotonHBT.h +++ b/PWGEM/PhotonMeson/Core/PhotonHBT.h @@ -71,7 +71,7 @@ using namespace o2::soa; using namespace o2::aod::pwgem::dilepton::utils; using namespace o2::aod::pwgem::photon::core::photonhbt; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; using MyV0Photons = soa::Join; @@ -668,7 +668,7 @@ struct PhotonHBT { std::map, uint64_t> map_mixed_eventId_to_globalBC; SliceCache cache; - Preslice perCollision_pcm = aod::v0photonkf::emeventId; + Preslice perCollision_pcm = aod::v0photonkf::emphotoneventId; Filter collisionFilter_centrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); Filter collisionFilter_occupancy_track = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; diff --git a/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h b/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h index 83e934bbdd0..965d88ddcc0 100644 --- a/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h +++ b/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h @@ -226,16 +226,16 @@ struct Pi0EtaToGammaGamma { //--------------------------------------------------------------------------- // Preslices and partitions o2::framework::SliceCache cache; - o2::framework::PresliceOptional>> perCollision_pcm = o2::aod::v0photonkf::emeventId; - o2::framework::PresliceOptional> perCollision_emc = o2::aod::emccluster::emeventId; - o2::framework::PresliceOptional> perCollision_phos = o2::aod::phoscluster::emeventId; - o2::framework::PresliceOptional>> perCollision_electron = o2::aod::emprimaryelectron::emeventId; + o2::framework::PresliceOptional>> perCollision_pcm = o2::aod::v0photonkf::emphotoneventId; + o2::framework::PresliceOptional> perCollision_emc = o2::aod::emccluster::emphotoneventId; + o2::framework::PresliceOptional> perCollision_phos = o2::aod::phoscluster::emphotoneventId; + o2::framework::PresliceOptional>> perCollision_electron = o2::aod::emprimaryelectronda::emphotoneventId; o2::framework::PresliceOptional perEMCClusterMT = o2::aod::trackmatching::emEmcClusterId; o2::framework::PresliceOptional perEMCClusterMS = o2::aod::trackmatching::emEmcClusterId; - o2::framework::Partition>> positrons = o2::aod::emprimaryelectron::sign > int8_t(0) && dileptoncuts.cfg_min_pt_track < o2::aod::track::pt&& nabs(o2::aod::track::eta) < dileptoncuts.cfg_max_eta_track; - o2::framework::Partition>> electrons = o2::aod::emprimaryelectron::sign < int8_t(0) && dileptoncuts.cfg_min_pt_track < o2::aod::track::pt && nabs(o2::aod::track::eta) < dileptoncuts.cfg_max_eta_track; + o2::framework::Partition>> positrons = o2::aod::emprimaryelectron::sign > int8_t(0) && dileptoncuts.cfg_min_pt_track < o2::aod::track::pt&& nabs(o2::aod::track::eta) < dileptoncuts.cfg_max_eta_track; + o2::framework::Partition>> electrons = o2::aod::emprimaryelectron::sign < int8_t(0) && dileptoncuts.cfg_min_pt_track < o2::aod::track::pt && nabs(o2::aod::track::eta) < dileptoncuts.cfg_max_eta_track; o2::aod::pwgem::dilepton::utils::EventMixingHandler, std::pair, o2::aod::pwgem::dilepton::utils::EMTrack>* emh1 = nullptr; o2::aod::pwgem::dilepton::utils::EventMixingHandler, std::pair, o2::aod::pwgem::dilepton::utils::EMTrack>* emh2 = nullptr; @@ -262,7 +262,7 @@ struct Pi0EtaToGammaGamma { static auto& perCollision() { - static auto slice{o2::aod::v0photonkf::emeventId}; + static auto slice{o2::aod::v0photonkf::emphotoneventId}; return slice; } @@ -283,7 +283,7 @@ struct Pi0EtaToGammaGamma { static auto& perCollision() { - static auto slice{o2::aod::emccluster::emeventId}; + static auto slice{o2::aod::emccluster::emphotoneventId}; return slice; } @@ -317,7 +317,7 @@ struct Pi0EtaToGammaGamma { static auto& perCollision() { - static auto slice{o2::aod::phoscluster::emeventId}; + static auto slice{o2::aod::phoscluster::emphotoneventId}; return slice; } @@ -338,7 +338,7 @@ struct Pi0EtaToGammaGamma { static auto& perCollision() { - static auto slice{o2::aod::emprimaryelectron::emeventId}; + static auto slice{o2::aod::emprimaryelectronda::emphotoneventId}; return slice; } @@ -709,7 +709,7 @@ struct Pi0EtaToGammaGamma { } float weight = 1.f; - if constexpr (std::is_same_v, o2::soa::Filtered, o2::aod::EMEventsWeight>>>) { + if constexpr (std::is_same_v, o2::soa::Filtered, o2::aod::EMEventsWeight>>>) { weight = collision.weight(); } @@ -776,8 +776,8 @@ struct Pi0EtaToGammaGamma { if constexpr (pairtype == o2::aod::pwgem::photonmeson::photonpair::PairType::kPCMDalitzEE) { auto photons1_per_collision = photons1.sliceByCached(TDetectorTag1::perCollision(), collision.globalIndex(), cache); - auto positrons_per_collision = positrons->sliceByCached(o2::aod::emprimaryelectron::emeventId, collision.globalIndex(), cache); - auto electrons_per_collision = electrons->sliceByCached(o2::aod::emprimaryelectron::emeventId, collision.globalIndex(), cache); + auto positrons_per_collision = positrons->sliceByCached(o2::aod::emprimaryelectronda::emphotoneventId, collision.globalIndex(), cache); + auto electrons_per_collision = electrons->sliceByCached(o2::aod::emprimaryelectronda::emphotoneventId, collision.globalIndex(), cache); for (const auto& g1 : photons1_per_collision) { if constexpr (std::is_same_v) { @@ -1024,13 +1024,13 @@ struct Pi0EtaToGammaGamma { o2::framework::expressions::Filter collisionFilter_occupancy_track = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; o2::framework::expressions::Filter collisionFilter_occupancy_ft0c = eventcuts.cfgFT0COccupancyMin <= o2::aod::evsel::ft0cOccupancyInTimeRange && o2::aod::evsel::ft0cOccupancyInTimeRange < eventcuts.cfgFT0COccupancyMax; o2::framework::expressions::Filter collisionFilter_centrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); - // using FilteredMyCollisions = o2::soa::Filtered>; + // using FilteredMyCollisions = o2::soa::Filtered>; o2::framework::expressions::Filter prefilter_pcm = ifnode(pcmcuts.cfg_apply_cuts_from_prefilter_derived.node(), o2::aod::v0photonkf::pfbderived == static_cast(0), true); o2::framework::expressions::Filter prefilter_primaryelectron = ifnode(dileptoncuts.cfg_apply_cuts_from_prefilter_derived.node(), o2::aod::emprimaryelectron::pfbderived == static_cast(0), true); int ndf = 0; - void processAnalysis(o2::soa::Filtered> const& collisions, Types const&... args) + void processAnalysis(o2::soa::Filtered> const& collisions, Types const&... args) { // LOGF(info, "ndf = %d", ndf); if constexpr (pairtype == o2::aod::pwgem::photonmeson::photonpair::PairType::kPCMPCM) { @@ -1066,8 +1066,8 @@ struct Pi0EtaToGammaGamma { } PROCESS_SWITCH(Pi0EtaToGammaGamma, processAnalysis, "process pair analysis", true); - // using FilteredMyCollisionsWithJJMC = o2::soa::Filtered, o2::aod::EMEventsWeight>>; - void processAnalysisJJMC(o2::soa::Filtered, o2::aod::EMEventsWeight>> const& collisions, Types const&... args) + // using FilteredMyCollisionsWithJJMC = o2::soa::Filtered, o2::aod::EMEventsWeight>>; + void processAnalysisJJMC(o2::soa::Filtered, o2::aod::EMEventsWeight>> const& collisions, Types const&... args) { // LOGF(info, "ndf = %d", ndf); if constexpr (pairtype == o2::aod::pwgem::photonmeson::photonpair::PairType::kPCMPCM) { diff --git a/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h b/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h index 729f76ce5de..a67295b4227 100644 --- a/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h +++ b/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h @@ -423,16 +423,16 @@ struct Pi0EtaToGammaGammaMC { } o2::framework::SliceCache cache; - o2::framework::PresliceOptional>> perCollision_pcm = o2::aod::v0photonkf::emeventId; - o2::framework::PresliceOptional> perCollision_emc = o2::aod::emccluster::emeventId; - o2::framework::PresliceOptional> perCollision_phos = o2::aod::phoscluster::emeventId; - o2::framework::PresliceOptional>> perCollision_electron = o2::aod::emprimaryelectron::emeventId; + o2::framework::PresliceOptional>> perCollision_pcm = o2::aod::v0photonkf::emphotoneventId; + o2::framework::PresliceOptional> perCollision_emc = o2::aod::emccluster::emphotoneventId; + o2::framework::PresliceOptional> perCollision_phos = o2::aod::phoscluster::emphotoneventId; + o2::framework::PresliceOptional>> perCollision_electron = o2::aod::emprimaryelectronda::emphotoneventId; o2::framework::PresliceOptional perEMCClusterMT = o2::aod::trackmatching::emEmcClusterId; o2::framework::PresliceOptional perEMCClusterMS = o2::aod::trackmatching::emEmcClusterId; - o2::framework::Partition>> positrons = o2::aod::emprimaryelectron::sign > int8_t(0) && dileptoncuts.cfg_min_pt_track < o2::aod::track::pt&& nabs(o2::aod::track::eta) < dileptoncuts.cfg_max_eta_track; - o2::framework::Partition>> electrons = o2::aod::emprimaryelectron::sign < int8_t(0) && dileptoncuts.cfg_min_pt_track < o2::aod::track::pt && nabs(o2::aod::track::eta) < dileptoncuts.cfg_max_eta_track; + o2::framework::Partition>> positrons = o2::aod::emprimaryelectron::sign > int8_t(0) && dileptoncuts.cfg_min_pt_track < o2::aod::track::pt&& nabs(o2::aod::track::eta) < dileptoncuts.cfg_max_eta_track; + o2::framework::Partition>> electrons = o2::aod::emprimaryelectron::sign < int8_t(0) && dileptoncuts.cfg_min_pt_track < o2::aod::track::pt && nabs(o2::aod::track::eta) < dileptoncuts.cfg_max_eta_track; //--------------------------------------------------------------------------- // In the following are tags defined which help to select the correct preslice and cuts @@ -440,7 +440,7 @@ struct Pi0EtaToGammaGammaMC { static auto& perCollision() { - static auto slice{o2::aod::v0photonkf::emeventId}; + static auto slice{o2::aod::v0photonkf::emphotoneventId}; return slice; } @@ -461,7 +461,7 @@ struct Pi0EtaToGammaGammaMC { static auto& perCollision() { - static auto slice{o2::aod::emccluster::emeventId}; + static auto slice{o2::aod::emccluster::emphotoneventId}; return slice; } @@ -495,7 +495,7 @@ struct Pi0EtaToGammaGammaMC { static auto& perCollision() { - static auto slice{o2::aod::phoscluster::emeventId}; + static auto slice{o2::aod::phoscluster::emphotoneventId}; return slice; } @@ -515,7 +515,7 @@ struct Pi0EtaToGammaGammaMC { struct DalitzEETag { static auto& perCollision() { - static auto slice{o2::aod::emprimaryelectron::emeventId}; + static auto slice{o2::aod::emprimaryelectronda::emphotoneventId}; return slice; } @@ -566,7 +566,7 @@ struct Pi0EtaToGammaGammaMC { } float weight = 1.f; - if constexpr (std::is_same_v, o2::soa::Filtered, o2::aod::EMEventsWeight>>>) { + if constexpr (std::is_same_v, o2::soa::Filtered, o2::aod::EMEventsWeight>>>) { weight = collision.weight(); } @@ -703,8 +703,8 @@ struct Pi0EtaToGammaGammaMC { } else if constexpr (pairtype == o2::aod::pwgem::photonmeson::photonpair::PairType::kPCMDalitzEE) { auto photons1_per_collision = photons1.sliceByCached(TDetectorTag1::perCollision(), collision.globalIndex(), cache); - auto positrons_per_collision = positrons->sliceByCached(o2::aod::emprimaryelectron::emeventId, collision.globalIndex(), cache); - auto electrons_per_collision = electrons->sliceByCached(o2::aod::emprimaryelectron::emeventId, collision.globalIndex(), cache); + auto positrons_per_collision = positrons->sliceByCached(o2::aod::emprimaryelectronda::emphotoneventId, collision.globalIndex(), cache); + auto electrons_per_collision = electrons->sliceByCached(o2::aod::emprimaryelectronda::emphotoneventId, collision.globalIndex(), cache); for (const auto& g1 : photons1_per_collision) { if constexpr (std::is_same_v) { @@ -851,7 +851,7 @@ struct Pi0EtaToGammaGammaMC { } o2::framework::PresliceUnsorted perMcCollision = o2::aod::emmcparticle::emmceventId; - o2::framework::PresliceUnsorted> rec_perMcCollision = o2::aod::emmceventlabel::emmceventId; + o2::framework::PresliceUnsorted> rec_perMcCollision = o2::aod::emmceventlabel::emmceventId; template void runGenInfo(TCollisions const& collisions, TMCCollisions const& mccollisions, TMCParticles const& /*mcparticles*/) @@ -871,7 +871,7 @@ struct Pi0EtaToGammaGammaMC { } float weight = 1.f; - if constexpr (std::is_same_v, o2::soa::Filtered, o2::aod::EMEventsWeight>>>) { + if constexpr (std::is_same_v, o2::soa::Filtered, o2::aod::EMEventsWeight>>>) { weight = collision.weight(); } @@ -899,12 +899,12 @@ struct Pi0EtaToGammaGammaMC { o2::framework::expressions::Filter collisionFilter_occupancy_track = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; o2::framework::expressions::Filter collisionFilter_occupancy_ft0c = eventcuts.cfgFT0COccupancyMin <= o2::aod::evsel::ft0cOccupancyInTimeRange && o2::aod::evsel::ft0cOccupancyInTimeRange < eventcuts.cfgFT0COccupancyMax; o2::framework::expressions::Filter collisionFilter_centrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); - // using FilteredMyCollisions = o2::soa::Filtered>; + // using FilteredMyCollisions = o2::soa::Filtered>; o2::framework::expressions::Filter prefilter_pcm = ifnode(pcmcuts.cfg_apply_cuts_from_prefilter_derived.node(), o2::aod::v0photonkf::pfbderived == static_cast(0), true); o2::framework::expressions::Filter prefilter_primaryelectron = ifnode(dileptoncuts.cfg_apply_cuts_from_prefilter_derived.node(), o2::aod::emprimaryelectron::pfbderived == static_cast(0), true); - void processAnalysis(o2::soa::Filtered> const& collisions, o2::soa::Join const& mccollisions, o2::aod::EMMCParticles const& mcparticles, Types const&... args) + void processAnalysis(o2::soa::Filtered> const& collisions, o2::soa::Join const& mccollisions, o2::aod::EMMCParticles const& mcparticles, Types const&... args) { if constexpr (pairtype == o2::aod::pwgem::photonmeson::photonpair::PairType::kPCMPCM) { auto&& [v0photons, v0legs] = std::forward_as_tuple(args...); @@ -939,8 +939,8 @@ struct Pi0EtaToGammaGammaMC { } PROCESS_SWITCH(Pi0EtaToGammaGammaMC, processAnalysis, "process pair analysis", true); - // using FilteredMyCollisionsWithJJMC = o2::soa::Filtered, aod::EMEventsWeight>>; - void processAnalysisJJMC(o2::soa::Filtered, o2::aod::EMEventsWeight>> const& collisions, o2::soa::Join const& mccollisions, o2::aod::EMMCParticles const& mcparticles, Types const&... args) + // using FilteredMyCollisionsWithJJMC = o2::soa::Filtered, aod::EMEventsWeight>>; + void processAnalysisJJMC(o2::soa::Filtered, o2::aod::EMEventsWeight>> const& collisions, o2::soa::Join const& mccollisions, o2::aod::EMMCParticles const& mcparticles, Types const&... args) { if constexpr (pairtype == o2::aod::pwgem::photonmeson::photonpair::PairType::kPCMPCM) { auto&& [v0photons, v0legs] = std::forward_as_tuple(args...); diff --git a/PWGEM/PhotonMeson/Core/TaggingPi0.h b/PWGEM/PhotonMeson/Core/TaggingPi0.h index 681b9d9938d..4dd43e290bf 100644 --- a/PWGEM/PhotonMeson/Core/TaggingPi0.h +++ b/PWGEM/PhotonMeson/Core/TaggingPi0.h @@ -21,7 +21,7 @@ #include "PWGEM/PhotonMeson/Core/DalitzEECut.h" #include "PWGEM/PhotonMeson/Core/EMCPhotonCut.h" #include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" -#include "PWGEM/PhotonMeson/Core/PHOSPhotonCut.h" +// #include "PWGEM/PhotonMeson/Core/PHOSPhotonCut.h" #include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/EventHistograms.h" @@ -73,7 +73,7 @@ using namespace o2::aod::pwgem::photon; using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; using namespace o2::aod::pwgem::dilepton::utils; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; using MyCollisionsWithJJMC = soa::Join; @@ -82,14 +82,14 @@ using MyCollisionWithJJMC = MyCollisionsWithJJMC::iterator; using MyV0Photons = soa::Join; using MyV0Photon = MyV0Photons::iterator; -using MyPrimaryElectrons = soa::Join; +using MyPrimaryElectrons = soa::Join; using MyPrimaryElectron = MyPrimaryElectrons::iterator; using MyEMCClusters = soa::Join; using MyEMCCluster = MyEMCClusters::iterator; -using MyPHOSClusters = soa::Join; -using MyPHOSCluster = MyPHOSClusters::iterator; +// using MyPHOSClusters = soa::Join; +// using MyPHOSCluster = MyPHOSClusters::iterator; template struct TaggingPi0 { @@ -213,11 +213,11 @@ struct TaggingPi0 { Configurable cfgDistanceToEdge{"cfgDistanceToEdge", 1, "Distance to edge in cells required for rotated cluster to be accepted"}; } emccuts; - PHOSPhotonCut fPHOSCut; - struct : ConfigurableGroup { - std::string prefix = "phoscut_group"; - Configurable cfg_min_Ecluster{"cfg_min_Ecluster", 0.3, "Minimum cluster energy for PHOS in GeV"}; - } phoscuts; + // PHOSPhotonCut fPHOSCut; + // struct : ConfigurableGroup { + // std::string prefix = "phoscut_group"; + // Configurable cfg_min_Ecluster{"cfg_min_Ecluster", 0.3, "Minimum cluster energy for PHOS in GeV"}; + // } phoscuts; HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; static constexpr std::string_view event_types[2] = {"before/", "after/"}; @@ -258,7 +258,7 @@ struct TaggingPi0 { DefinePCMCut(); DefineDileptonCut(); DefineEMCCut(); - DefinePHOSCut(); + // DefinePHOSCut(); mRunNumber = 0; d_bz = 0; @@ -436,17 +436,17 @@ struct TaggingPi0 { fEMCCut.SetUseExoticCut(emccuts.EMC_UseExoticCut); } - void DefinePHOSCut() - { - fPHOSCut.SetEnergyRange(phoscuts.cfg_min_Ecluster, 1e+10); - } + // void DefinePHOSCut() + // { + // fPHOSCut.SetEnergyRange(phoscuts.cfg_min_Ecluster, 1e+10); + // } SliceCache cache; - Preslice perCollision_pcm = aod::v0photonkf::emeventId; - Preslice perCollision_emc = aod::emccluster::emeventId; - Preslice perCollision_phos = aod::phoscluster::emeventId; + Preslice perCollision_pcm = aod::v0photonkf::emphotoneventId; + Preslice perCollision_emc = aod::emccluster::emphotoneventId; + // Preslice perCollision_phos = aod::phoscluster::emphotoneventId; - Preslice perCollision_electron = aod::emprimaryelectron::emeventId; + Preslice perCollision_electron = aod::emprimaryelectronda::emphotoneventId; Partition positrons = o2::aod::emprimaryelectron::sign > int8_t(0) && static_cast(dileptoncuts.cfg_min_pt_track) < o2::aod::track::pt&& nabs(o2::aod::track::eta) < static_cast(dileptoncuts.cfg_max_eta_track) && static_cast(dileptoncuts.cfg_min_TPCNsigmaEl) < o2::aod::pidtpc::tpcNSigmaEl&& o2::aod::pidtpc::tpcNSigmaEl < static_cast(dileptoncuts.cfg_max_TPCNsigmaEl); Partition electrons = o2::aod::emprimaryelectron::sign < int8_t(0) && static_cast(dileptoncuts.cfg_min_pt_track) < o2::aod::track::pt && nabs(o2::aod::track::eta) < static_cast(dileptoncuts.cfg_max_eta_track) && static_cast(dileptoncuts.cfg_min_TPCNsigmaEl) < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < static_cast(dileptoncuts.cfg_max_TPCNsigmaEl); @@ -535,8 +535,8 @@ struct TaggingPi0 { if constexpr (pairtype == PairType::kPCMDalitzEE) { auto photons1_per_collision = photons1.sliceBy(perCollision1, collision.globalIndex()); // PCM - auto positrons_per_collision = positrons->sliceByCached(o2::aod::emprimaryelectron::emeventId, collision.globalIndex(), cache); // positrons - auto electrons_per_collision = electrons->sliceByCached(o2::aod::emprimaryelectron::emeventId, collision.globalIndex(), cache); // electrons + auto positrons_per_collision = positrons->sliceByCached(o2::aod::emprimaryelectronda::emphotoneventId, collision.globalIndex(), cache); // positrons + auto electrons_per_collision = electrons->sliceByCached(o2::aod::emprimaryelectronda::emphotoneventId, collision.globalIndex(), cache); // electrons for (const auto& g1 : photons1_per_collision) { if (!cut1.template IsSelected(g1)) { diff --git a/PWGEM/PhotonMeson/Core/TaggingPi0MC.h b/PWGEM/PhotonMeson/Core/TaggingPi0MC.h index fb9ba22d87f..38d7a8e70d3 100644 --- a/PWGEM/PhotonMeson/Core/TaggingPi0MC.h +++ b/PWGEM/PhotonMeson/Core/TaggingPi0MC.h @@ -21,7 +21,7 @@ #include "PWGEM/PhotonMeson/Core/DalitzEECut.h" #include "PWGEM/PhotonMeson/Core/EMCPhotonCut.h" #include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" -#include "PWGEM/PhotonMeson/Core/PHOSPhotonCut.h" +// #include "PWGEM/PhotonMeson/Core/PHOSPhotonCut.h" #include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/EventHistograms.h" @@ -70,7 +70,7 @@ using namespace o2::aod::pwgem::photonmeson::photonpair; using namespace o2::aod::pwgem::photonmeson::utils::mcutil; using namespace o2::aod::pwgem::dilepton::utils::mcutil; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; using MyCollisionsWithJJMC = soa::Join; @@ -85,13 +85,13 @@ using MyV0Photon = MyV0Photons::iterator; using MyEMCClusters = soa::Join; using MyEMCCluster = MyEMCClusters::iterator; -using MyPHOSClusters = soa::Join; -using MyPHOSCluster = MyEMCClusters::iterator; +// using MyPHOSClusters = soa::Join; +// using MyPHOSCluster = MyEMCClusters::iterator; using MyMCV0Legs = soa::Join; using MyMCV0Leg = MyMCV0Legs::iterator; -using MyMCElectrons = soa::Join; +using MyMCElectrons = soa::Join; using MyMCElectron = MyMCElectrons::iterator; template @@ -210,11 +210,11 @@ struct TaggingPi0MC { Configurable EMC_UseExoticCut{"EMC_UseExoticCut", true, "FLag to use the EMCal exotic cluster cut"}; } emccuts; - PHOSPhotonCut fPHOSCut; - struct : ConfigurableGroup { - std::string prefix = "phoscut_group"; - Configurable cfg_min_Ecluster{"cfg_min_Ecluster", 0.3, "Minimum cluster energy for PHOS in GeV"}; - } phoscuts; + // PHOSPhotonCut fPHOSCut; + // struct : ConfigurableGroup { + // std::string prefix = "phoscut_group"; + // Configurable cfg_min_Ecluster{"cfg_min_Ecluster", 0.3, "Minimum cluster energy for PHOS in GeV"}; + // } phoscuts; HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; static constexpr std::string_view event_types[2] = {"before/", "after/"}; @@ -235,7 +235,7 @@ struct TaggingPi0MC { DefinePCMCut(); DefineDileptonCut(); DefineEMCCut(); - DefinePHOSCut(); + // DefinePHOSCut(); mRunNumber = 0; d_bz = 0; @@ -412,17 +412,17 @@ struct TaggingPi0MC { fEMCCut.SetUseExoticCut(emccuts.EMC_UseExoticCut); } - void DefinePHOSCut() - { - fPHOSCut.SetEnergyRange(phoscuts.cfg_min_Ecluster, 1e+10); - } + // void DefinePHOSCut() + // { + // fPHOSCut.SetEnergyRange(phoscuts.cfg_min_Ecluster, 1e+10); + // } SliceCache cache; - Preslice perCollision_pcm = aod::v0photonkf::emeventId; - Preslice perCollision_emc = aod::emccluster::emeventId; - Preslice perCollision_phos = aod::phoscluster::emeventId; + Preslice perCollision_pcm = aod::v0photonkf::emphotoneventId; + Preslice perCollision_emc = aod::emccluster::emphotoneventId; + // Preslice perCollision_phos = aod::phoscluster::emphotoneventId; - Preslice perCollision_electron = aod::emprimaryelectron::emeventId; + Preslice perCollision_electron = aod::emprimaryelectronda::emphotoneventId; Partition positrons = o2::aod::emprimaryelectron::sign > int8_t(0) && static_cast(dileptoncuts.cfg_min_pt_track) < o2::aod::track::pt&& nabs(o2::aod::track::eta) < static_cast(dileptoncuts.cfg_max_eta_track) && static_cast(dileptoncuts.cfg_min_TPCNsigmaEl) < o2::aod::pidtpc::tpcNSigmaEl&& o2::aod::pidtpc::tpcNSigmaEl < static_cast(dileptoncuts.cfg_max_TPCNsigmaEl); Partition electrons = o2::aod::emprimaryelectron::sign < int8_t(0) && static_cast(dileptoncuts.cfg_min_pt_track) < o2::aod::track::pt && nabs(o2::aod::track::eta) < static_cast(dileptoncuts.cfg_max_eta_track) && static_cast(dileptoncuts.cfg_min_TPCNsigmaEl) < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < static_cast(dileptoncuts.cfg_max_TPCNsigmaEl); @@ -461,8 +461,8 @@ struct TaggingPi0MC { if constexpr (pairtype == PairType::kPCMDalitzEE) { auto photons1_per_collision = photons1.sliceBy(perCollision1, collision.globalIndex()); - auto positrons_per_collision = positrons->sliceByCached(o2::aod::emprimaryelectron::emeventId, collision.globalIndex(), cache); - auto electrons_per_collision = electrons->sliceByCached(o2::aod::emprimaryelectron::emeventId, collision.globalIndex(), cache); + auto positrons_per_collision = positrons->sliceByCached(o2::aod::emprimaryelectronda::emphotoneventId, collision.globalIndex(), cache); + auto electrons_per_collision = electrons->sliceByCached(o2::aod::emprimaryelectronda::emphotoneventId, collision.globalIndex(), cache); for (const auto& g1 : photons1_per_collision) { if (!cut1.template IsSelected(g1)) { diff --git a/PWGEM/PhotonMeson/Core/V0PhotonCut.h b/PWGEM/PhotonMeson/Core/V0PhotonCut.h index 7f5ecaecb64..1be295b3235 100644 --- a/PWGEM/PhotonMeson/Core/V0PhotonCut.h +++ b/PWGEM/PhotonMeson/Core/V0PhotonCut.h @@ -367,10 +367,10 @@ class V0PhotonCut : public TNamed const bool doQA = mDoQA && fRegistry != nullptr; uint nTotV0PerColl = 0; - currentCollID = v0s.iteratorAt(0).emeventId(); + currentCollID = v0s.iteratorAt(0).emphotoneventId(); for (const auto& v0 : v0s) { - const auto collID = v0.emeventId(); + const auto collID = v0.emphotoneventId(); if (!IsSelected(v0, fRegistry)) { flags.set(iV0); } @@ -604,7 +604,7 @@ class V0PhotonCut : public TNamed } if (doQA) { fillAfterPhotonHistogram(v0, pos, ele, fRegistry); - if (v0.emeventId() != currentCollID) { + if (v0.emphotoneventId() != currentCollID) { fRegistry->fill(HIST("QA/V0Photon/after/hNgamma"), nAccV0PerColl); nAccV0PerColl = 0; } diff --git a/PWGEM/PhotonMeson/DataModel/gammaTables.h b/PWGEM/PhotonMeson/DataModel/gammaTables.h index f840f771db1..9b680aed2c9 100644 --- a/PWGEM/PhotonMeson/DataModel/gammaTables.h +++ b/PWGEM/PhotonMeson/DataModel/gammaTables.h @@ -36,6 +36,9 @@ namespace o2::aod { +using EMPhotonEvents = EMEvents_004; +using EMPhotonEvent = EMPhotonEvents::iterator; + namespace emmcbinnedgen { DECLARE_SOA_COLUMN(GeneratedGamma, generatedGamma, std::vector); //! gamma binned generated data @@ -263,6 +266,7 @@ using EMEventWeight = EMEventsWeight::iterator; namespace v0photonkf { DECLARE_SOA_INDEX_COLUMN(EMEvent, emevent); //! +DECLARE_SOA_INDEX_COLUMN(EMPhotonEvent, emphotonevent); //! DECLARE_SOA_COLUMN(CollisionId, collisionId, int); //! DECLARE_SOA_COLUMN(V0Id, v0Id, int); //! DECLARE_SOA_INDEX_COLUMN_FULL(PosTrack, posTrack, int, V0Legs, "_Pos"); //! @@ -341,8 +345,9 @@ using V0PhotonsKF = V0PhotonsKF_001; // iterators using V0PhotonKF = V0PhotonsKF::iterator; -DECLARE_SOA_TABLE(V0KFEMEventIds, "AOD", "V0KFEMEVENTID", v0photonkf::EMEventId); // To be joined with V0PhotonsKF table at analysis level. -// iterators +DECLARE_SOA_TABLE(V0KFEMEventIds_000, "AOD", "V0KFEMEVENTID", v0photonkf::EMEventId); // To be joined with V0PhotonsKF table at analysis level. +DECLARE_SOA_TABLE_VERSIONED(V0KFEMEventIds_001, "AOD", "V0KFEMEVENTID", 1, v0photonkf::EMPhotonEventId); // To be joined with V0PhotonsKF table at analysis level. +using V0KFEMEventIds = V0KFEMEventIds_001; using V0KFEMEventId = V0KFEMEventIds::iterator; DECLARE_SOA_TABLE(V0PhotonsKFCov, "AOD", "V0PHOTONKFCOV", //! To be joined with V0PhotonsKF table at analysis level. @@ -416,9 +421,20 @@ using EMPrimaryElectronsFromDalitz = EMPrimaryElectronsFromDalitz_001; // iterators using EMPrimaryElectronFromDalitz = EMPrimaryElectronsFromDalitz::iterator; +namespace emprimaryelectronda +{ +DECLARE_SOA_INDEX_COLUMN(EMEvent, emevent); //! +DECLARE_SOA_INDEX_COLUMN(EMPhotonEvent, emphotonevent); //! +} // namespace emprimaryelectronda + +DECLARE_SOA_TABLE_VERSIONED(EMPrimaryElectronDaEMEventIds_001, "AOD", "PRMELDAEVENTID", 1, emprimaryelectronda::EMPhotonEventId); // To be joined with EMPrimaryElectronsFromDalitz table at analysis level. +using EMPrimaryElectronDaEMEventIds = EMPrimaryElectronDaEMEventIds_001; +using EMPrimaryElectronDaEMEventId = EMPrimaryElectronDaEMEventIds::iterator; + namespace v0photonsphivpsi { DECLARE_SOA_INDEX_COLUMN(EMEvent, emevent); //! +DECLARE_SOA_INDEX_COLUMN(EMPhotonEvent, emphotonevent); //! DECLARE_SOA_COLUMN(PhiV, phiv, float); //! DECLARE_SOA_COLUMN(PsiPair, psipair, float); } // namespace v0photonsphivpsi @@ -430,6 +446,7 @@ using V0PhotonsPhiVPsi = V0PhotonsPhiVPsi; namespace dalitzee { DECLARE_SOA_INDEX_COLUMN(EMEvent, emevent); //! +DECLARE_SOA_INDEX_COLUMN(EMPhotonEvent, emphotonevent); //! DECLARE_SOA_INDEX_COLUMN_FULL(PosTrack, posTrack, int, EMPrimaryElectrons, "_Pos"); //! DECLARE_SOA_INDEX_COLUMN_FULL(NegTrack, negTrack, int, EMPrimaryElectrons, "_Neg"); //! DECLARE_SOA_COLUMN(CollisionId, collisionId, int); //! @@ -458,6 +475,7 @@ using DalitzEEEMEventId = DalitzEEEMEventIds::iterator; namespace pwgem::photon::swtinfo { DECLARE_SOA_INDEX_COLUMN(EMEvent, emevent); //! +DECLARE_SOA_INDEX_COLUMN(EMPhotonEvent, emphotonevent); //! DECLARE_SOA_COLUMN(CollisionId, collisionId, int); //! DECLARE_SOA_INDEX_COLUMN_FULL(TriggerV0PhotonHighPt, triggerV0PhotonHighPt, int, V0PhotonsKF, "_TriggerV0PhotonHighPt"); //! high pT PCM trigger is fired by this v0 photon DECLARE_SOA_INDEX_COLUMN_FULL(TriggerV0PhotonPair, triggerV0PhotonPair, int, V0PhotonsKF, "_TriggerV0PhotonPair"); //! PCM+EE trigger is fired by this v0 photon and dielectron @@ -557,6 +575,7 @@ DECLARE_SOA_TABLE(McGammasTrue, "AOD", "MCGATRUE", namespace skimmedcluster { DECLARE_SOA_INDEX_COLUMN(EMEvent, emevent); //! +DECLARE_SOA_INDEX_COLUMN(EMPhotonEvent, emphotonevent); //! DECLARE_SOA_COLUMN(CollisionId, collisionId, int); //! DECLARE_SOA_COLUMN(ID, id, int); //! cluster ID identifying cluster in event DECLARE_SOA_COLUMN(E, e, float); //! cluster energy (GeV) @@ -573,6 +592,7 @@ DECLARE_SOA_COLUMN(NLM, nlm, int); //! numbe namespace emccluster { DECLARE_SOA_INDEX_COLUMN(EMEvent, emevent); //! +DECLARE_SOA_INDEX_COLUMN(EMPhotonEvent, emphotonevent); //! DECLARE_SOA_COLUMN(CoreEnergy, coreEnergy, float); //! cluster core energy (GeV) DECLARE_SOA_COLUMN(Time, time, float); //! cluster time (ns) DECLARE_SOA_COLUMN(IsExotic, isExotic, bool); //! flag to mark cluster as exotic @@ -629,13 +649,15 @@ DECLARE_SOA_TABLE(EmEmcMTracks, "AOD", "EMEMCMTRACK", //! DECLARE_SOA_TABLE(EmEmcMSTracks, "AOD", "EMEMCMSTRACK", //! trackmatching::EmEmcClusterId, emctm::DeltaPhi, emctm::DeltaEta, emctm::TrackP, emctm::TrackPt); -DECLARE_SOA_TABLE(EMCEMEventIds, "AOD", "EMCEMEVENTID", emccluster::EMEventId); // To be joined with SkimEMCClusters table at analysis level. -// iterators +DECLARE_SOA_TABLE(EMCEMEventIds_000, "AOD", "EMCEMEVENTID", emccluster::EMEventId); // To be joined with SkimEMCClusters table at analysis level. +DECLARE_SOA_TABLE_VERSIONED(EMCEMEventIds_001, "AOD", "EMCEMEVENTID", 1, emccluster::EMPhotonEventId); // To be joined with SkimEMCClusters table at analysis level. +using EMCEMEventIds = EMCEMEventIds_001; using EMCEMEventId = EMCEMEventIds::iterator; namespace phoscluster { DECLARE_SOA_INDEX_COLUMN(EMEvent, emevent); //! +DECLARE_SOA_INDEX_COLUMN(EMPhotonEvent, emphotonevent); //! DECLARE_SOA_INDEX_COLUMN_FULL(MatchedTrack, matchedTrack, int, Tracks, "_Matched"); //! matched track index DECLARE_SOA_COLUMN(X, x, float); //! cluster hit position in ALICE global coordinate DECLARE_SOA_COLUMN(Y, y, float); //! cluster hit position in ALICE global coordinate @@ -670,8 +692,9 @@ DECLARE_SOA_TABLE(PHOSClusters, "AOD", "PHOSCLUSTERS", //! phoscluster::Phi); using PHOSCluster = PHOSClusters::iterator; -DECLARE_SOA_TABLE(PHOSEMEventIds, "AOD", "PHOSEMEVENTID", phoscluster::EMEventId); // To be joined with PHOSClusters table at analysis level. -// iterators +DECLARE_SOA_TABLE(PHOSEMEventIds_000, "AOD", "PHOSEMEVENTID", phoscluster::EMEventId); // To be joined with PHOSClusters table at analysis level. +DECLARE_SOA_TABLE_VERSIONED(PHOSEMEventIds_001, "AOD", "PHOSEMEVENTID", 1, phoscluster::EMPhotonEventId); // To be joined with PHOSClusters table at analysis level. +using PHOSEMEventIds = PHOSEMEventIds_001; using PHOSEMEventId = PHOSEMEventIds::iterator; namespace caloextra diff --git a/PWGEM/PhotonMeson/TableProducer/CMakeLists.txt b/PWGEM/PhotonMeson/TableProducer/CMakeLists.txt index 1e9c99c1cd5..20db3ba057e 100644 --- a/PWGEM/PhotonMeson/TableProducer/CMakeLists.txt +++ b/PWGEM/PhotonMeson/TableProducer/CMakeLists.txt @@ -9,6 +9,8 @@ # granted to it by virtue of its status as an Intergovernmental Organization # or submit itself to any jurisdiction. +add_subdirectory(Converters) + o2physics_add_dpl_workflow(skimmer-gamma-conversion SOURCES skimmerGammaConversion.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DCAFitter O2Physics::AnalysisCore KFParticle::KFParticle diff --git a/PWGEM/PhotonMeson/TableProducer/Converters/CMakeLists.txt b/PWGEM/PhotonMeson/TableProducer/Converters/CMakeLists.txt new file mode 100644 index 00000000000..8ee98eb4d36 --- /dev/null +++ b/PWGEM/PhotonMeson/TableProducer/Converters/CMakeLists.txt @@ -0,0 +1,27 @@ +# Copyright 2019-2020 CERN and copyright holders of ALICE O2. +# See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +# All rights not expressly granted are reserved. +# +# This software is distributed under the terms of the GNU General Public +# License v3 (GPL Version 3), copied verbatim in the file "COPYING". +# +# In applying this license CERN does not waive the privileges and immunities +# granted to it by virtue of its status as an Intergovernmental Organization +# or submit itself to any jurisdiction. + + +o2physics_add_dpl_workflow(v0photonid-converter1 + SOURCES v0photonIdConverter1.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(emcid-converter1 + SOURCES emcIdConverter1.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(phosid-converter1 + SOURCES phosIdConverter1.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + diff --git a/PWGEM/PhotonMeson/Tasks/diphotonHadronMPCPCMPCM.cxx b/PWGEM/PhotonMeson/TableProducer/Converters/emcIdConverter1.cxx similarity index 63% rename from PWGEM/PhotonMeson/Tasks/diphotonHadronMPCPCMPCM.cxx rename to PWGEM/PhotonMeson/TableProducer/Converters/emcIdConverter1.cxx index 6f0dfff7c2f..bdfa1aac27c 100644 --- a/PWGEM/PhotonMeson/Tasks/diphotonHadronMPCPCMPCM.cxx +++ b/PWGEM/PhotonMeson/TableProducer/Converters/emcIdConverter1.cxx @@ -8,27 +8,31 @@ // In applying this license CERN does not waive the privileges and immunities // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -// -// ======================== -// -// This code loops over photons and makes pairs for neutral mesons analyses. -// Please write to: daiki.sekihata@cern.ch -#include "PWGEM/PhotonMeson/Core/DiphotonHadronMPC.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGEM/PhotonMeson/Utils/PairUtilities.h" #include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" using namespace o2; using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +struct emcIdConverter1 { + Produces id_001; + + void process(aod::EMCEMEventIds_000 const& ids) + { + for (const auto& id : ids) { + id_001(id.emeventId()); + } // end of id loop + } +}; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - return WorkflowSpec{ - adaptAnalysisTask>(cfgc, TaskName{"diphoton-hadron-mpc-pcmpcm"}), - }; + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"emcid-converter1"})}; } diff --git a/PWGEM/PhotonMeson/TableProducer/Converters/phosIdConverter1.cxx b/PWGEM/PhotonMeson/TableProducer/Converters/phosIdConverter1.cxx new file mode 100644 index 00000000000..102907e9547 --- /dev/null +++ b/PWGEM/PhotonMeson/TableProducer/Converters/phosIdConverter1.cxx @@ -0,0 +1,38 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" + +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +struct phosIdConverter1 { + Produces id_001; + + void process(aod::PHOSEMEventIds_000 const& ids) + { + for (const auto& id : ids) { + id_001(id.emeventId()); + } // end of id loop + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"phosid-converter1"})}; +} diff --git a/PWGEM/PhotonMeson/TableProducer/Converters/v0photonIdConverter1.cxx b/PWGEM/PhotonMeson/TableProducer/Converters/v0photonIdConverter1.cxx new file mode 100644 index 00000000000..25230a2512e --- /dev/null +++ b/PWGEM/PhotonMeson/TableProducer/Converters/v0photonIdConverter1.cxx @@ -0,0 +1,38 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" + +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +struct v0photonIdConverter1 { + Produces id_001; + + void process(aod::V0KFEMEventIds_000 const& ids) + { + for (const auto& id : ids) { + id_001(id.emeventId()); + } // end of id loop + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"v0photonid-converter1"})}; +} diff --git a/PWGEM/PhotonMeson/TableProducer/createEMEventPhoton.cxx b/PWGEM/PhotonMeson/TableProducer/createEMEventPhoton.cxx index fe6726d4d98..2c87cc3431d 100644 --- a/PWGEM/PhotonMeson/TableProducer/createEMEventPhoton.cxx +++ b/PWGEM/PhotonMeson/TableProducer/createEMEventPhoton.cxx @@ -66,14 +66,14 @@ using MyCollisionsMCCentQvec = soa::Join; struct CreateEMEventPhoton { // Produces embc; - Produces event; + Produces event; Produces eventalias; // Produces eventCov; - Produces eventMult; - Produces eventCent; - Produces eventQvec; + Produces eventMult; + Produces eventCent; + Produces eventQvec; Produces emswtbit; - Produces event_norm_info; + Produces event_norm_info; Produces eventWeights; enum class EMEventType : int { @@ -359,7 +359,7 @@ struct CreateEMEventPhoton { }; struct AssociatePhotonToEMEvent { Produces v0kfeventid; - Produces prmeleventid; + Produces prmeleventid; Produces phoseventid; Produces emceventid; Produces prmtrackeventid; @@ -407,10 +407,10 @@ struct AssociatePhotonToEMEvent { fillEventId(collisions, photons, emceventid, perCollisionEMC); } - void processChargedTrack(aod::EMEvents const& collisions, aod::EMPrimaryTracks const& tracks) - { - fillEventId(collisions, tracks, prmtrackeventid, perCollision_track); - } + // void processChargedTrack(aod::EMEvents const& collisions, aod::EMPrimaryTracks const& tracks) + // { + // fillEventId(collisions, tracks, prmtrackeventid, perCollision_track); + // } void processDummy(aod::EMEvents const&) {} @@ -418,7 +418,7 @@ struct AssociatePhotonToEMEvent { PROCESS_SWITCH(AssociatePhotonToEMEvent, processElectronFromDalitz, "process dalitzee-event indexing", false); PROCESS_SWITCH(AssociatePhotonToEMEvent, processPHOS, "process phos-event indexing", false); PROCESS_SWITCH(AssociatePhotonToEMEvent, processEMC, "process emc-event indexing", false); - PROCESS_SWITCH(AssociatePhotonToEMEvent, processChargedTrack, "process indexing for charged tracks", false); + // PROCESS_SWITCH(AssociatePhotonToEMEvent, processChargedTrack, "process indexing for charged tracks", false); PROCESS_SWITCH(AssociatePhotonToEMEvent, processDummy, "process dummy", true); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGEM/PhotonMeson/TableProducer/nonLinProducer.cxx b/PWGEM/PhotonMeson/TableProducer/nonLinProducer.cxx index 6c8132fb0b6..9d3847ffb8a 100644 --- a/PWGEM/PhotonMeson/TableProducer/nonLinProducer.cxx +++ b/PWGEM/PhotonMeson/TableProducer/nonLinProducer.cxx @@ -59,7 +59,7 @@ struct NonLinProducer { using EMCalPhotons = soa::Join; using PcmPhotons = soa::Join; - using Colls = soa::Join; + using Colls = soa::Join; EMNonLin emNonLinEMC; EMNonLin emNonLinPCM; @@ -118,8 +118,8 @@ struct NonLinProducer { float nonLinFactor = 1.f; // check that we are at the correct collision - if (cluster.emeventId() != collIndex) { - collIndex = cluster.emeventId(); + if (cluster.emphotoneventId() != collIndex) { + collIndex = cluster.emphotoneventId(); collision.setCursor(collIndex); cent = getCentrality(collision); } @@ -155,8 +155,8 @@ struct NonLinProducer { float nonLinFactor = 1.f; // check that we are at the correct collision - if (v0.emeventId() != collIndex) { - collIndex = v0.emeventId(); + if (v0.emphotoneventId() != collIndex) { + collIndex = v0.emphotoneventId(); collision.setCursor(collIndex); cent = getCentrality(collision); } diff --git a/PWGEM/PhotonMeson/TableProducer/skimmerDalitzEE.cxx b/PWGEM/PhotonMeson/TableProducer/skimmerDalitzEE.cxx index c27bd6e64ab..c33a1e2020e 100644 --- a/PWGEM/PhotonMeson/TableProducer/skimmerDalitzEE.cxx +++ b/PWGEM/PhotonMeson/TableProducer/skimmerDalitzEE.cxx @@ -37,10 +37,10 @@ using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::constants::physics; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; -using MyTracks = soa::Join; +using MyTracks = soa::Join; using MyTrack = MyTracks::iterator; using MyTracksCEFP = soa::Join; @@ -54,7 +54,7 @@ struct skimmerDalitzEE { }; SliceCache cache; - Preslice perCol = o2::aod::emprimaryelectron::emeventId; + Preslice perCol = o2::aod::emprimaryelectronda::emphotoneventId; SliceCache cache_cefp; PresliceUnsorted perCol_cefp = o2::aod::emprimaryelectron::collisionId; @@ -337,8 +337,8 @@ struct skimmerDalitzEE { continue; } - auto posTracks_per_coll = posTracks->sliceByCached(o2::aod::emprimaryelectron::emeventId, collision.globalIndex(), cache); - auto negTracks_per_coll = negTracks->sliceByCached(o2::aod::emprimaryelectron::emeventId, collision.globalIndex(), cache); + auto posTracks_per_coll = posTracks->sliceByCached(o2::aod::emprimaryelectronda::emphotoneventId, collision.globalIndex(), cache); + auto negTracks_per_coll = negTracks->sliceByCached(o2::aod::emprimaryelectronda::emphotoneventId, collision.globalIndex(), cache); fRegistry.fill(HIST("hNpos"), collision.centFT0C(), posTracks_per_coll.size()); fRegistry.fill(HIST("hNele"), collision.centFT0C(), negTracks_per_coll.size()); // LOGF(info, "collision.centFT0C() = %f, posTracks_per_coll.size() = %d, negTracks_per_coll.size() = %d", collision.centFT0C() , posTracks_per_coll.size(), negTracks_per_coll.size()); @@ -375,7 +375,7 @@ struct skimmerDalitzEE { } PROCESS_SWITCH(skimmerDalitzEE, processCEFP, "Process dalitz ee for CEFP", false); // for central event filter processing - void processOnlyNee(soa::Join const& collisions) + void processOnlyNee(soa::Join const& collisions) { for (auto& collision : collisions) { float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; diff --git a/PWGEM/PhotonMeson/Tasks/CMakeLists.txt b/PWGEM/PhotonMeson/Tasks/CMakeLists.txt index ba160a3080f..e0ce318628f 100644 --- a/PWGEM/PhotonMeson/Tasks/CMakeLists.txt +++ b/PWGEM/PhotonMeson/Tasks/CMakeLists.txt @@ -181,22 +181,11 @@ o2physics_add_dpl_workflow(tagging-pi0-mc-pcmdalitzee PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(diphoton-hadron-mpc-pcmpcm - SOURCES diphotonHadronMPCPCMPCM.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore - COMPONENT_NAME Analysis) - - o2physics_add_dpl_workflow(compconvbuilder SOURCES compconvbuilder.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(diphoton-hadron-mpc-pcmdalitzee - SOURCES diphotonHadronMPCPCMDalitzEE.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore - COMPONENT_NAME Analysis) - o2physics_add_dpl_workflow(calib-task-emc SOURCES calibTaskEmc.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::EMCALBase O2::EMCALCalib O2Physics::PWGEMPhotonMesonCore diff --git a/PWGEM/PhotonMeson/Tasks/MaterialBudget.cxx b/PWGEM/PhotonMeson/Tasks/MaterialBudget.cxx index 298f05a1198..a023826777b 100644 --- a/PWGEM/PhotonMeson/Tasks/MaterialBudget.cxx +++ b/PWGEM/PhotonMeson/Tasks/MaterialBudget.cxx @@ -70,10 +70,10 @@ using namespace o2::aod::pwgem::dilepton::utils::mcutil; using namespace o2::aod::pwgem::dilepton::utils; using o2::constants::math::TwoPI; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; -using MyCollisionsMC = soa::Join; +using MyCollisionsMC = soa::Join; using MyCollisionMC = MyCollisionsMC::iterator; using MyMCCollisions = soa::Join; @@ -82,7 +82,7 @@ using MyMCCollision = MyMCCollisions::iterator; using MyV0Photons = soa::Join; using MyV0Photon = MyV0Photons::iterator; -using MyPrimaryElectrons = soa::Filtered>; +using MyPrimaryElectrons = soa::Filtered>; using MyPrimaryElectron = MyPrimaryElectrons::iterator; using MyMCV0Legs = soa::Join; @@ -831,8 +831,8 @@ struct MaterialBudget { } SliceCache cache; - Preslice perCollision = aod::v0photonkf::emeventId; - Preslice perCollisionElectron = aod::emprimaryelectron::emeventId; + Preslice perCollision = aod::v0photonkf::emphotoneventId; + Preslice perCollisionElectron = aod::emprimaryelectronda::emphotoneventId; Partition positrons = o2::aod::emprimaryelectron::sign > int8_t(0) && dileptoncuts.cfgMinPtTrack < o2::aod::track::pt&& nabs(o2::aod::track::eta) < dileptoncuts.cfgMaxEtaTrack; Partition electrons = o2::aod::emprimaryelectron::sign < int8_t(0) && dileptoncuts.cfgMinPtTrack < o2::aod::track::pt && nabs(o2::aod::track::eta) < dileptoncuts.cfgMaxEtaTrack; diff --git a/PWGEM/PhotonMeson/Tasks/MaterialBudgetMC.cxx b/PWGEM/PhotonMeson/Tasks/MaterialBudgetMC.cxx index a2cea8bd2b3..7956146ae89 100644 --- a/PWGEM/PhotonMeson/Tasks/MaterialBudgetMC.cxx +++ b/PWGEM/PhotonMeson/Tasks/MaterialBudgetMC.cxx @@ -57,7 +57,7 @@ using namespace o2::aod::pwgem::photonmeson::utils::mcutil; using namespace o2::aod::pwgem::dilepton::utils::mcutil; using namespace o2::aod::pwgem::photon; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; using MyV0Photons = soa::Join; @@ -227,7 +227,7 @@ struct MaterialBudgetMC { LOGF(info, "Number of Pair cuts = %d", fPairCuts.size()); } - Preslice perCollision_pcm = aod::v0photonkf::emeventId; + Preslice perCollision_pcm = aod::v0photonkf::emphotoneventId; template bool IsSelectedPair(TG1 const& g1, TG2 const& g2, TCut1 const& tagcut, TCut2 const& probecut) diff --git a/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaMCPCMDalitzEE.cxx b/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaMCPCMDalitzEE.cxx index e36da8a2556..573b8d0224e 100644 --- a/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaMCPCMDalitzEE.cxx +++ b/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaMCPCMDalitzEE.cxx @@ -28,7 +28,7 @@ using namespace o2::aod::pwgem::photonmeson::photonpair; using MyV0Photons = soa::Filtered>; using MyMCV0Legs = soa::Join; -using MyMCElectrons = soa::Filtered>; +using MyMCElectrons = soa::Filtered>; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { diff --git a/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaPCMDalitzEE.cxx b/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaPCMDalitzEE.cxx index 27d1c1cca7d..aa9afe80489 100644 --- a/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaPCMDalitzEE.cxx +++ b/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaPCMDalitzEE.cxx @@ -29,7 +29,7 @@ using namespace o2::framework; using namespace o2::aod::pwgem::photonmeson::photonpair; using MyV0Photons = Filtered>; -using MyPrimaryElectrons = Filtered>; +using MyPrimaryElectrons = Filtered>; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { diff --git a/PWGEM/PhotonMeson/Tasks/SinglePhoton.cxx b/PWGEM/PhotonMeson/Tasks/SinglePhoton.cxx index 5d5972e3685..1c536cf5751 100644 --- a/PWGEM/PhotonMeson/Tasks/SinglePhoton.cxx +++ b/PWGEM/PhotonMeson/Tasks/SinglePhoton.cxx @@ -53,7 +53,7 @@ using namespace o2::framework::expressions; using namespace o2::soa; using namespace o2::aod::pwgem::photon; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; using MyV0Photons = soa::Join; @@ -241,7 +241,7 @@ struct SinglePhoton { LOGF(info, "Number of EMCal cuts = %d", fEMCCuts.size()); } - Preslice perCollision = aod::v0photonkf::emeventId; + Preslice perCollision = aod::v0photonkf::emphotoneventId; // Preslice perCollision_phos = aod::skimmedcluster::collisionId; // Preslice perCollision_emc = aod::skimmedcluster::collisionId; diff --git a/PWGEM/PhotonMeson/Tasks/SinglePhotonMC.cxx b/PWGEM/PhotonMeson/Tasks/SinglePhotonMC.cxx index b9aeedf9ffa..f583890fd53 100644 --- a/PWGEM/PhotonMeson/Tasks/SinglePhotonMC.cxx +++ b/PWGEM/PhotonMeson/Tasks/SinglePhotonMC.cxx @@ -52,7 +52,7 @@ using namespace o2::aod::pwgem::photonmeson::utils::mcutil; using namespace o2::aod::pwgem::dilepton::utils::mcutil; using namespace o2::aod::pwgem::photon; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; using MyV0Photons = soa::Join; @@ -242,7 +242,7 @@ struct SinglePhotonMC { // LOGF(info, "Number of EMCal cuts = %d", fEMCCuts.size()); // } - Preslice perCollision = aod::v0photonkf::emeventId; + Preslice perCollision = aod::v0photonkf::emphotoneventId; // Preslice perCollision_phos = aod::skimmedcluster::collisionId; // Preslice perCollision_emc = aod::skimmedcluster::collisionId; diff --git a/PWGEM/PhotonMeson/Tasks/TagAndProbe.cxx b/PWGEM/PhotonMeson/Tasks/TagAndProbe.cxx index a2d09adcc0f..91b46605947 100644 --- a/PWGEM/PhotonMeson/Tasks/TagAndProbe.cxx +++ b/PWGEM/PhotonMeson/Tasks/TagAndProbe.cxx @@ -65,15 +65,12 @@ using namespace o2::soa; using namespace o2::aod::pwgem::photonmeson::photonpair; using namespace o2::aod::pwgem::photon; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; using MyV0Photons = soa::Join; using MyV0Photon = MyV0Photons::iterator; -using MyDalitzEEs = soa::Join; -using MyDalitzEE = MyDalitzEEs::iterator; - struct TagAndProbe { Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; Configurable cfgCentMin{"cfgCentMin", 0, "min. centrality"}; @@ -248,7 +245,7 @@ struct TagAndProbe { LOGF(info, "Number of Pair cuts = %d", fPairCuts.size()); } - Preslice perCollision = aod::v0photonkf::emeventId; + Preslice perCollision = aod::v0photonkf::emphotoneventId; Preslice perCollision_phos = aod::skimmedcluster::collisionId; Preslice perCollision_emc = aod::skimmedcluster::collisionId; diff --git a/PWGEM/PhotonMeson/Tasks/calibTaskEmc.cxx b/PWGEM/PhotonMeson/Tasks/calibTaskEmc.cxx index 9520c3216e6..66d140bf308 100644 --- a/PWGEM/PhotonMeson/Tasks/calibTaskEmc.cxx +++ b/PWGEM/PhotonMeson/Tasks/calibTaskEmc.cxx @@ -228,12 +228,12 @@ struct CalibTaskEmc { Filter collisionFilter = (nabs(aod::collision::posZ) <= eventcuts.cfgZvtxMax) && (aod::evsel::ft0cOccupancyInTimeRange <= eventcuts.cfgFT0COccupancyMax) && (aod::evsel::ft0cOccupancyInTimeRange >= eventcuts.cfgFT0COccupancyMin); using EMCalPhotons = soa::Join; using PCMPhotons = soa::Join; - using FilteredCollsWithQvecs = soa::Filtered>; - using CollsWithQvecs = soa::Join; - using Colls = soa::Join; + using FilteredCollsWithQvecs = soa::Filtered>; + using CollsWithQvecs = soa::Join; + using Colls = soa::Join; - PresliceOptional perCollisionEMC = o2::aod::emccluster::emeventId; - PresliceOptional perCollisionPCM = aod::v0photonkf::emeventId; + PresliceOptional perCollisionEMC = o2::aod::emccluster::emphotoneventId; + PresliceOptional perCollisionPCM = aod::v0photonkf::emphotoneventId; PresliceOptional perEMCClusterMT = o2::aod::mintm::minClusterId; PresliceOptional perEMCClusterMS = o2::aod::mintm::minClusterId; diff --git a/PWGEM/PhotonMeson/Tasks/compconvbuilder.cxx b/PWGEM/PhotonMeson/Tasks/compconvbuilder.cxx index 3a080016299..be0e088e60d 100644 --- a/PWGEM/PhotonMeson/Tasks/compconvbuilder.cxx +++ b/PWGEM/PhotonMeson/Tasks/compconvbuilder.cxx @@ -57,7 +57,7 @@ using MyV0Photons = soa::Join; using MyMCV0Legs = soa::Join; using MyMCV0Leg = MyMCV0Legs::iterator; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; using MyMCCollisions = soa::Join; @@ -128,7 +128,7 @@ struct Compconvbuilder { } // Link V0-photons to their collision - Preslice perV0PhotonCollision = aod::v0photonkf::emeventId; + Preslice perV0PhotonCollision = aod::v0photonkf::emphotoneventId; void init(InitContext const& /*ctx*/) { @@ -656,7 +656,7 @@ struct Compconvbuilder { } } - Preslice perCollision = aod::v0photonkf::emeventId; + Preslice perCollision = aod::v0photonkf::emphotoneventId; void processEMV0sMC(MyV0Photons const& v0s, aod::EMMCParticles const& mcparticles, MyMCV0Legs const&, MyCollisions const& collisions) { diff --git a/PWGEM/PhotonMeson/Tasks/dalitzEEQC.cxx b/PWGEM/PhotonMeson/Tasks/dalitzEEQC.cxx index a0c6deb047d..4717c1d307b 100644 --- a/PWGEM/PhotonMeson/Tasks/dalitzEEQC.cxx +++ b/PWGEM/PhotonMeson/Tasks/dalitzEEQC.cxx @@ -43,10 +43,10 @@ using namespace o2::framework::expressions; using namespace o2::soa; using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; -using MyTracks = soa::Join; +using MyTracks = soa::Join; using MyTrack = MyTracks::iterator; struct DalitzEEQC { @@ -332,7 +332,7 @@ struct DalitzEEQC { using FilteredMyCollisions = soa::Filtered; SliceCache cache; - Preslice perCollision_track = aod::emprimaryelectron::emeventId; + Preslice perCollision_track = aod::emprimaryelectronda::emphotoneventId; Filter trackFilter = dileptoncuts.cfg_min_pt_track < o2::aod::track::pt && nabs(o2::aod::track::eta) < dileptoncuts.cfg_max_eta_track && o2::aod::track::tpcChi2NCl < dileptoncuts.cfg_max_chi2tpc && o2::aod::track::itsChi2NCl < dileptoncuts.cfg_max_chi2its && nabs(o2::aod::track::dcaXY) < dileptoncuts.cfg_max_dcaxy && nabs(o2::aod::track::dcaZ) < dileptoncuts.cfg_max_dcaz; Filter pidFilter = dileptoncuts.cfg_min_TPCNsigmaEl < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < dileptoncuts.cfg_max_TPCNsigmaEl && (o2::aod::pidtpc::tpcNSigmaPi < dileptoncuts.cfg_min_TPCNsigmaPi || dileptoncuts.cfg_max_TPCNsigmaPi < o2::aod::pidtpc::tpcNSigmaPi); using FilteredMyTracks = soa::Filtered; @@ -360,8 +360,8 @@ struct DalitzEEQC { fRegistry.fill(HIST("Event/before/hCollisionCounter"), 12.0); // accepted fRegistry.fill(HIST("Event/after/hCollisionCounter"), 12.0); // accepted - auto posTracks_per_coll = posTracks->sliceByCached(o2::aod::emprimaryelectron::emeventId, collision.globalIndex(), cache); - auto negTracks_per_coll = negTracks->sliceByCached(o2::aod::emprimaryelectron::emeventId, collision.globalIndex(), cache); + auto posTracks_per_coll = posTracks->sliceByCached(o2::aod::emprimaryelectronda::emphotoneventId, collision.globalIndex(), cache); + auto negTracks_per_coll = negTracks->sliceByCached(o2::aod::emprimaryelectronda::emphotoneventId, collision.globalIndex(), cache); // LOGF(info, "centrality = %f , posTracks_per_coll.size() = %d, negTracks_per_coll.size() = %d", centralities[cfgCentEstimator], posTracks_per_coll.size(), negTracks_per_coll.size()); for (auto& [pos, ele] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS diff --git a/PWGEM/PhotonMeson/Tasks/dalitzEEQCMC.cxx b/PWGEM/PhotonMeson/Tasks/dalitzEEQCMC.cxx index 6b6ca3f6649..f5e202985be 100644 --- a/PWGEM/PhotonMeson/Tasks/dalitzEEQCMC.cxx +++ b/PWGEM/PhotonMeson/Tasks/dalitzEEQCMC.cxx @@ -46,10 +46,10 @@ using namespace o2::soa; using namespace o2::aod::pwgem::photonmeson::utils::mcutil; using namespace o2::aod::pwgem::dilepton::utils::mcutil; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; -using MyMCTracks = soa::Join; +using MyMCTracks = soa::Join; using MyMCTrack = MyMCTracks::iterator; struct DalitzEEQCMC { @@ -487,7 +487,7 @@ struct DalitzEEQCMC { std::vector used_trackIds; SliceCache cache; - Preslice perCollision_track = aod::emprimaryelectron::emeventId; + Preslice perCollision_track = aod::emprimaryelectronda::emphotoneventId; Filter trackFilter = dileptoncuts.cfg_min_pt_track < o2::aod::track::pt && nabs(o2::aod::track::eta) < dileptoncuts.cfg_max_eta_track && o2::aod::track::tpcChi2NCl < dileptoncuts.cfg_max_chi2tpc && o2::aod::track::itsChi2NCl < dileptoncuts.cfg_max_chi2its && nabs(o2::aod::track::dcaXY) < dileptoncuts.cfg_max_dcaxy && nabs(o2::aod::track::dcaZ) < dileptoncuts.cfg_max_dcaz; Filter pidFilter = dileptoncuts.cfg_min_TPCNsigmaEl < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < dileptoncuts.cfg_max_TPCNsigmaEl && (o2::aod::pidtpc::tpcNSigmaPi < dileptoncuts.cfg_min_TPCNsigmaPi || dileptoncuts.cfg_max_TPCNsigmaPi < o2::aod::pidtpc::tpcNSigmaPi); using FilteredMyMCTracks = soa::Filtered; @@ -520,8 +520,8 @@ struct DalitzEEQCMC { fRegistry.fill(HIST("Event/before/hCollisionCounter"), 12.0); // accepted fRegistry.fill(HIST("Event/after/hCollisionCounter"), 12.0); // accepted - auto posTracks_per_coll = posTracks->sliceByCached(o2::aod::emprimaryelectron::emeventId, collision.globalIndex(), cache); - auto negTracks_per_coll = negTracks->sliceByCached(o2::aod::emprimaryelectron::emeventId, collision.globalIndex(), cache); + auto posTracks_per_coll = posTracks->sliceByCached(o2::aod::emprimaryelectronda::emphotoneventId, collision.globalIndex(), cache); + auto negTracks_per_coll = negTracks->sliceByCached(o2::aod::emprimaryelectronda::emphotoneventId, collision.globalIndex(), cache); // LOGF(info, "centrality = %f , posTracks_per_coll.size() = %d, negTracks_per_coll.size() = %d", centralities[cfgCentEstimator], posTracks_per_coll.size(), negTracks_per_coll.size()); for (auto& [pos, ele] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS diff --git a/PWGEM/PhotonMeson/Tasks/emcalQC.cxx b/PWGEM/PhotonMeson/Tasks/emcalQC.cxx index 7c3fce2bd65..651828b8194 100644 --- a/PWGEM/PhotonMeson/Tasks/emcalQC.cxx +++ b/PWGEM/PhotonMeson/Tasks/emcalQC.cxx @@ -47,7 +47,7 @@ using namespace o2::framework::expressions; using namespace o2::soa; using namespace o2::aod::pwgem::photon; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; using EMCalPhotons = soa::Join; @@ -137,7 +137,7 @@ struct EmcalQC { PresliceOptional perEMCClusterMT = o2::aod::mintm::minClusterId; PresliceOptional perEMCClusterMS = o2::aod::mintm::minClusterId; - PresliceOptional perCollisionEMC = o2::aod::emccluster::emeventId; + PresliceOptional perCollisionEMC = o2::aod::emccluster::emphotoneventId; void init(InitContext&) { diff --git a/PWGEM/PhotonMeson/Tasks/gammaConversions.cxx b/PWGEM/PhotonMeson/Tasks/gammaConversions.cxx index b9268ab3907..c1a9eeed496 100644 --- a/PWGEM/PhotonMeson/Tasks/gammaConversions.cxx +++ b/PWGEM/PhotonMeson/Tasks/gammaConversions.cxx @@ -619,7 +619,7 @@ struct GammaConversions { } } - Preslice perCollision = aod::v0photonkf::emeventId; + Preslice perCollision = aod::v0photonkf::emphotoneventId; void processRec(aod::EMEvents::iterator const& theCollision, V0DatasAdditional const& theV0s, aod::V0Legs const&) diff --git a/PWGEM/PhotonMeson/Tasks/pcmQC.cxx b/PWGEM/PhotonMeson/Tasks/pcmQC.cxx index c741b283be3..4bb4e38f583 100644 --- a/PWGEM/PhotonMeson/Tasks/pcmQC.cxx +++ b/PWGEM/PhotonMeson/Tasks/pcmQC.cxx @@ -48,7 +48,7 @@ using namespace o2::framework::expressions; using namespace o2::soa; using namespace o2::aod::pwgem::photon; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; using MyV0Photons = soa::Join; diff --git a/PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx b/PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx index eb04bc86b88..0e3f56909ca 100644 --- a/PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx +++ b/PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx @@ -54,7 +54,7 @@ using namespace o2::aod::pwgem::photonmeson::utils::mcutil; using namespace o2::aod::pwgem::dilepton::utils::mcutil; using namespace o2::aod::pwgem::photon; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; using MyMCCollisions = soa::Join; diff --git a/PWGEM/PhotonMeson/Tasks/phosQC.cxx b/PWGEM/PhotonMeson/Tasks/phosQC.cxx index 4f5ef2ec075..8504be6ae8a 100644 --- a/PWGEM/PhotonMeson/Tasks/phosQC.cxx +++ b/PWGEM/PhotonMeson/Tasks/phosQC.cxx @@ -44,7 +44,7 @@ using namespace o2::framework::expressions; using namespace o2::soa; using namespace o2::aod::pwgem::photon; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; struct phosQC { diff --git a/PWGEM/PhotonMeson/Tasks/photonResoTask.cxx b/PWGEM/PhotonMeson/Tasks/photonResoTask.cxx index 238f5b77715..fe6ec07c476 100644 --- a/PWGEM/PhotonMeson/Tasks/photonResoTask.cxx +++ b/PWGEM/PhotonMeson/Tasks/photonResoTask.cxx @@ -202,13 +202,13 @@ struct PhotonResoTask { using PcmMcLegs = soa::Join; - using Colls = soa::Join; + using Colls = soa::Join; using McColls = o2::soa::Join; using McParticles = EMMCParticles; - PresliceOptional perCollisionEMC = o2::aod::emccluster::emeventId; - PresliceOptional perCollisionPCM = aod::v0photonkf::emeventId; + PresliceOptional perCollisionEMC = o2::aod::emccluster::emphotoneventId; + PresliceOptional perCollisionPCM = aod::v0photonkf::emphotoneventId; PresliceOptional perEMCClusterMT = o2::aod::mintm::minClusterId; PresliceOptional perEMCClusterMS = o2::aod::mintm::minClusterId; diff --git a/PWGEM/PhotonMeson/Tasks/prefilterPhoton.cxx b/PWGEM/PhotonMeson/Tasks/prefilterPhoton.cxx index cfaa5371cac..b7141518624 100644 --- a/PWGEM/PhotonMeson/Tasks/prefilterPhoton.cxx +++ b/PWGEM/PhotonMeson/Tasks/prefilterPhoton.cxx @@ -59,13 +59,13 @@ using namespace o2::framework::expressions; using namespace o2::soa; using namespace o2::aod::pwgem::photonmeson::photonpair; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; using MyV0Photons = soa::Join; using MyV0Photon = MyV0Photons::iterator; -using MyPrimaryElectrons = soa::Join; +using MyPrimaryElectrons = soa::Join; using MyPrimaryElectron = MyPrimaryElectrons::iterator; struct prefilterPhoton { @@ -389,8 +389,8 @@ struct prefilterPhoton { } auto photons1_per_collision = photons1.sliceBy(perCollision1, collision.globalIndex()); - auto positrons_per_collision = posTracks->sliceByCached(o2::aod::emprimaryelectron::emeventId, collision.globalIndex(), cache); - auto electrons_per_collision = negTracks->sliceByCached(o2::aod::emprimaryelectron::emeventId, collision.globalIndex(), cache); + auto positrons_per_collision = posTracks->sliceByCached(o2::aod::emprimaryelectronda::emphotoneventId, collision.globalIndex(), cache); + auto electrons_per_collision = negTracks->sliceByCached(o2::aod::emprimaryelectronda::emphotoneventId, collision.globalIndex(), cache); if (!fEMEventCut.IsSelected(collision) || !is_cent_ok) { for (const auto& photon1 : photons1_per_collision) { @@ -537,8 +537,8 @@ struct prefilterPhoton { } auto photons1_per_collision = photons1.sliceBy(perCollision1, collision.globalIndex()); - auto positrons_per_collision = posTracks->sliceByCached(o2::aod::emprimaryelectron::emeventId, collision.globalIndex(), cache); - auto electrons_per_collision = negTracks->sliceByCached(o2::aod::emprimaryelectron::emeventId, collision.globalIndex(), cache); + auto positrons_per_collision = posTracks->sliceByCached(o2::aod::emprimaryelectronda::emphotoneventId, collision.globalIndex(), cache); + auto electrons_per_collision = negTracks->sliceByCached(o2::aod::emprimaryelectronda::emphotoneventId, collision.globalIndex(), cache); for (const auto& [g1, g2] : combinations(CombinationsStrictlyUpperIndexPolicy(photons1_per_collision, photons1_per_collision))) { if (!cut1.template IsSelected(g1) || !cut1.template IsSelected(g2)) { @@ -600,8 +600,8 @@ struct prefilterPhoton { std::unordered_map map_pfb_ele; // map ele.globalIndex -> prefilter bit SliceCache cache; - Preslice perCollision_v0 = aod::v0photonkf::emeventId; - Preslice perCollision_electron = aod::emprimaryelectron::emeventId; + Preslice perCollision_v0 = aod::v0photonkf::emphotoneventId; + Preslice perCollision_electron = aod::emprimaryelectronda::emphotoneventId; Filter collisionFilter_centrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); Filter collisionFilter_occupancy_track = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; diff --git a/PWGEM/PhotonMeson/Tasks/taskFlowReso.cxx b/PWGEM/PhotonMeson/Tasks/taskFlowReso.cxx index 10731a2de42..936e5ea335b 100644 --- a/PWGEM/PhotonMeson/Tasks/taskFlowReso.cxx +++ b/PWGEM/PhotonMeson/Tasks/taskFlowReso.cxx @@ -118,7 +118,7 @@ struct TaskFlowReso { SliceCache cache; EventPlaneHelper epHelper; - using CollsWithQvecs = soa::Join; + using CollsWithQvecs = soa::Join; using CollWithQvec = CollsWithQvecs::iterator; static constexpr std::size_t NQVecEntries = 6; diff --git a/PWGEM/PhotonMeson/Tasks/taskPi0FlowEMC.cxx b/PWGEM/PhotonMeson/Tasks/taskPi0FlowEMC.cxx index 6126cd516b2..69c0dae38a8 100644 --- a/PWGEM/PhotonMeson/Tasks/taskPi0FlowEMC.cxx +++ b/PWGEM/PhotonMeson/Tasks/taskPi0FlowEMC.cxx @@ -257,14 +257,14 @@ struct TaskPi0FlowEMC { // using FilteredEMCalPhotons = soa::Filtered>; using EMCalPhotons = soa::Join; using PCMPhotons = soa::Join; - using FilteredCollsWithQvecs = soa::Filtered>; - using CollsWithQvecs = soa::Join; - using Colls = soa::Join; + using FilteredCollsWithQvecs = soa::Filtered>; + using CollsWithQvecs = soa::Join; + using Colls = soa::Join; static constexpr std::size_t NQVecEntries = 6; - PresliceOptional perCollisionEMC = o2::aod::emccluster::emeventId; - PresliceOptional perCollisionPCM = aod::v0photonkf::emeventId; + PresliceOptional perCollisionEMC = o2::aod::emccluster::emphotoneventId; + PresliceOptional perCollisionPCM = aod::v0photonkf::emphotoneventId; PresliceOptional perEMCClusterMT = o2::aod::mintm::minClusterId; PresliceOptional perEMCClusterMS = o2::aod::mintm::minClusterId; From 9141dd24e85fccb810d68dbfb0da573e03137f7d Mon Sep 17 00:00:00 2001 From: YazhenLin Date: Mon, 23 Feb 2026 19:42:13 +0800 Subject: [PATCH 037/347] [PWGDQ] Change some code for the energy correlator study (#15114) --- PWGDQ/Tasks/dqEfficiency_withAssoc_direct.cxx | 28 ++++++++++++++----- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/PWGDQ/Tasks/dqEfficiency_withAssoc_direct.cxx b/PWGDQ/Tasks/dqEfficiency_withAssoc_direct.cxx index 3a9c27cb956..eefc7e1852a 100644 --- a/PWGDQ/Tasks/dqEfficiency_withAssoc_direct.cxx +++ b/PWGDQ/Tasks/dqEfficiency_withAssoc_direct.cxx @@ -3152,13 +3152,21 @@ struct AnalysisDileptonTrack { // for the energy correlators for (auto& t2 : groupedMCTracks) { auto t2_raw = groupedMCTracks.rawIteratorAt(t2.globalIndex()); - if (TMath::Abs(t2_raw.pdgCode()) == 443 || TMath::Abs(t2_raw.pdgCode()) == 11 || TMath::Abs(t2_raw.pdgCode()) == 22) + if (!t2_raw.isPhysicalPrimary()) { continue; + } + + if (t2_raw.has_mothers()) { + auto mother_raw = t2_raw.template mothers_first_as(); + if (mother_raw.globalIndex() == t1_raw.globalIndex()) { + continue; + } + } + if (t2_raw.pt() < fConfigMCOptions.fConfigMCGenHadronPtMin.value || std::abs(t2_raw.eta()) > fConfigMCOptions.fConfigMCGenHadronEtaAbs.value) { continue; } - if (t2_raw.getGenStatusCode() <= 0) - continue; + std::vector fTransRange = fConfigOptions.fConfigTransRange; VarManager::FillEnergyCorrelatorsMC(t1_raw, t2_raw, VarManager::fgValues, fTransRange[0], fTransRange[1]); for (auto& sig : fGenMCSignals) { @@ -3229,15 +3237,21 @@ struct AnalysisDileptonTrack { // for the energy correlators for (auto& t2 : groupedMCTracks2) { auto t2_raw = groupedMCTracks2.rawIteratorAt(t2.globalIndex()); - if (TMath::Abs(t2_raw.pdgCode()) == 443 || TMath::Abs(t2_raw.pdgCode()) == 11 || TMath::Abs(t2_raw.pdgCode()) == 22) { + if (!t2_raw.isPhysicalPrimary()) { continue; } - if (t2_raw.pt() < fConfigMCOptions.fConfigMCGenHadronPtMin.value || std::abs(t2_raw.eta()) > fConfigMCOptions.fConfigMCGenHadronEtaAbs.value) { - continue; + + if (t2_raw.has_mothers()) { + auto mother_raw = t2_raw.template mothers_first_as(); + if (mother_raw.globalIndex() == t1_raw.globalIndex()) { + continue; + } } - if (t2_raw.getGenStatusCode() <= 0) { + + if (t2_raw.pt() < fConfigMCOptions.fConfigMCGenHadronPtMin.value || std::abs(t2_raw.eta()) > fConfigMCOptions.fConfigMCGenHadronEtaAbs.value) { continue; } + for (auto& sig : fGenMCSignals) { if (sig->CheckSignal(true, t1_raw)) { VarManager::FillEnergyCorrelatorsMC(t1_raw, t2_raw, VarManager::fgValues); From 147884a22f791da1c289831ba7c96a29b23401ec Mon Sep 17 00:00:00 2001 From: Sushanta Tripathy Date: Mon, 23 Feb 2026 13:23:00 +0100 Subject: [PATCH 038/347] [PWGCF] Task for balance function and correlations for nuclei (#15067) Co-authored-by: Sushanta Tripathy Co-authored-by: ALICE Action Bot --- .../Tasks/CMakeLists.txt | 5 + .../Tasks/nucleibalance.cxx | 2697 +++++++++++++++++ 2 files changed, 2702 insertions(+) create mode 100644 PWGCF/TwoParticleCorrelations/Tasks/nucleibalance.cxx diff --git a/PWGCF/TwoParticleCorrelations/Tasks/CMakeLists.txt b/PWGCF/TwoParticleCorrelations/Tasks/CMakeLists.txt index b5e6fa72c8c..7584e824e6a 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/CMakeLists.txt +++ b/PWGCF/TwoParticleCorrelations/Tasks/CMakeLists.txt @@ -92,3 +92,8 @@ o2physics_add_dpl_workflow(eta-dihadron SOURCES etaDihadron.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGCFCore O2Physics::AnalysisCCDB O2Physics::GFWCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(nuclei-balance + SOURCES nucleibalance.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGCFCore + COMPONENT_NAME Analysis) \ No newline at end of file diff --git a/PWGCF/TwoParticleCorrelations/Tasks/nucleibalance.cxx b/PWGCF/TwoParticleCorrelations/Tasks/nucleibalance.cxx new file mode 100644 index 00000000000..6eb1425355d --- /dev/null +++ b/PWGCF/TwoParticleCorrelations/Tasks/nucleibalance.cxx @@ -0,0 +1,2697 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file nucleibalance.cxx +/// \brief task for the balance function and correlations for nuclei for O2 analysis. First part is inspired from PWGCF/Tasks/correlations.cxx +/// \author Sushanta Tripathy + +#include "PWGCF/Core/CorrelationContainer.h" +#include "PWGCF/Core/PairCuts.h" +#include "PWGCF/DataModel/CorrelationsDerived.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "CCDB/BasicCCDBManager.h" +#include "CommonConstants/MathConstants.h" +#include "CommonConstants/PhysicsConstants.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/StepTHn.h" +#include "Framework/runDataProcessing.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace constants::math; + +#define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable NAME{#NAME, DEFAULT, HELP}; + +static constexpr float PairCutOff = -1.f; +static constexpr float CfgPairCutDefaults[1][5] = {{PairCutOff, PairCutOff, PairCutOff, PairCutOff, PairCutOff}}; + +struct Nucleibalance { + SliceCache cache; + + // Configuration + O2_DEFINE_CONFIGURABLE(cfgCutVertex, float, 7.0f, "Accepted z-vertex range") + O2_DEFINE_CONFIGURABLE(cfgCutPt, float, 0.5f, "Minimal pT for tracks") + O2_DEFINE_CONFIGURABLE(cfgCutEta, float, 0.8f, "Eta range for tracks") + O2_DEFINE_CONFIGURABLE(cfgCutMCPt, float, 0.5f, "Minimal pT for MC particles (AO2D-MC mode)") + O2_DEFINE_CONFIGURABLE(cfgCutMCEta, float, 0.8f, "Eta range for MC particles (AO2D-MC mode)") + O2_DEFINE_CONFIGURABLE(cfgUseFT0M, int, 1, "Use FT0M centrality (0-100) as multiplicity axis (1=ON, 0=use Ntracks/multiplicity())") + // Track-quality options (AO2D mode). Default selection corresponds to global tracks. + O2_DEFINE_CONFIGURABLE(cfgTPCNClsMin, int, 70, "Minimum number of TPC clusters (tpcNClsFound) in AO2D mode") + O2_DEFINE_CONFIGURABLE(cfgDcaXYMax, float, 0.1f, "Max |DCA_{xy}| to PV (cm) in AO2D mode") + O2_DEFINE_CONFIGURABLE(cfgDcaZMax, float, 0.2f, "Max |DCA_{z}| to PV (cm) in AO2D mode") + O2_DEFINE_CONFIGURABLE(chi2pertpccluster, float, 2.5f, "Maximum Chi2/cluster for the TPC track segment in AO2D mode") + O2_DEFINE_CONFIGURABLE(chi2peritscluster, float, 36.f, "Maximum Chi2/cluster for the ITS track segment in AO2D mode") + O2_DEFINE_CONFIGURABLE(itsnclusters, int, 5, "Minimum number of ITS clusters in AO2D mode") + + O2_DEFINE_CONFIGURABLE(cfgPtOrder, int, 1, "Only consider pairs for which pT,1 < pT,2 (0 = OFF, 1 = ON)"); + O2_DEFINE_CONFIGURABLE(cfgTriggerCharge, int, 0, "Select on charge of trigger particle: 0 = all; 1 = positive; -1 = negative"); + O2_DEFINE_CONFIGURABLE(cfgAssociatedCharge, int, 0, "Select on charge of associated particle: 0 = all charged; 1 = positive; -1 = negative"); + O2_DEFINE_CONFIGURABLE(cfgPairCharge, int, 0, "Select on charge of particle pair: 0 = all; 1 = like sign; -1 = unlike sign"); + + O2_DEFINE_CONFIGURABLE(cfgTwoTrackCut, float, -1, "Two track cut: -1 = off; >0 otherwise distance value (suggested: 0.02)"); + O2_DEFINE_CONFIGURABLE(cfgTwoTrackCutMinRadius, float, 0.8f, "Two track cut: radius in m from which two track cuts are applied"); + O2_DEFINE_CONFIGURABLE(cfgLocalEfficiency, int, 0, "0 = OFF and 1 = ON for local efficiency"); + O2_DEFINE_CONFIGURABLE(cfgCentBinsForMC, int, 0, "0 = OFF and 1 = ON for data like multiplicity/centrality bins for MC steps"); + O2_DEFINE_CONFIGURABLE(cfgTrackBitMask, uint16_t, 1, "BitMask for track selection systematics; refer to the enum TrackSelectionCuts in filtering task (default=1 selects global tracks)"); + O2_DEFINE_CONFIGURABLE(cfgMultCorrelationsMask, uint16_t, 0, "Selection bitmask for the multiplicity correlations. This should match the filter selection cfgEstimatorBitMask.") + O2_DEFINE_CONFIGURABLE(cfgMultCutFormula, std::string, "", "Multiplicity correlations cut formula. A result greater than zero results in accepted event. Parameters: [cFT0C] FT0C centrality, [mFV0A] V0A multiplicity, [mGlob] global track multiplicity, [mPV] PV track multiplicity") + + // PID and species selection for AO2D-based correlations (pi, K, p, d) + O2_DEFINE_CONFIGURABLE(cfgUseTPCOnlyPID, int, 1, "Use only TPC PID (1 = TPC only, 0 = require both TPC and TOF when available)"); + O2_DEFINE_CONFIGURABLE(cfgNsigmaTPCPi, float, 3.0f, "|n#sigma^{TPC}_{#pi}| cut"); + O2_DEFINE_CONFIGURABLE(cfgNsigmaTPCKa, float, 3.0f, "|n#sigma^{TPC}_{K}| cut"); + O2_DEFINE_CONFIGURABLE(cfgNsigmaTPCPr, float, 3.0f, "|n#sigma^{TPC}_{p}| cut"); + O2_DEFINE_CONFIGURABLE(cfgNsigmaTPCDe, float, 3.0f, "|n#sigma^{TPC}_{d}| cut"); + O2_DEFINE_CONFIGURABLE(cfgNsigmaTOFPi, float, 3.0f, "|n#sigma^{TOF}_{#pi}| cut"); + O2_DEFINE_CONFIGURABLE(cfgNsigmaTOFKa, float, 3.0f, "|n#sigma^{TOF}_{K}| cut"); + O2_DEFINE_CONFIGURABLE(cfgNsigmaTOFPr, float, 3.0f, "|n#sigma^{TOF}_{p}| cut"); + O2_DEFINE_CONFIGURABLE(cfgNsigmaTOFDe, float, 3.0f, "|n#sigma^{TOF}_{d}| cut"); + + // Species choice for trigger/associated in the BF: + // 0 = pion, 1 = kaon, 2 = proton, 3 = deuteron, -1 = all charged tracks + O2_DEFINE_CONFIGURABLE(cfgTriggerSpecies, int, 3, "Trigger species for BF: 0 = #pi, 1 = K, 2 = p, 3 = d, -1 = all charged tracks"); + O2_DEFINE_CONFIGURABLE(cfgAssociatedSpecies, int, 2, "Associated species for BF: 0 = #pi, 1 = K, 2 = p, 3 = d, -1 = all charged tracks"); + + // Suggested values: Photon: 0.004; K0 and Lambda: 0.005 + Configurable> cfgPairCut{"cfgPairCut", {CfgPairCutDefaults[0], 5, {"Photon", "K0", "Lambda", "Phi", "Rho"}}, "Pair cuts on various particles"}; + + O2_DEFINE_CONFIGURABLE(cfgEfficiencyTrigger, std::string, "", "CCDB path to efficiency object for trigger particles") + O2_DEFINE_CONFIGURABLE(cfgEfficiencyAssociated, std::string, "", "CCDB path to efficiency object for associated particles") + + O2_DEFINE_CONFIGURABLE(cfgNoMixedEvents, int, 5, "Number of mixed events per event") + + O2_DEFINE_CONFIGURABLE(cfgVerbosity, int, 1, "Verbosity level (0 = major, 1 = per collision)") + + O2_DEFINE_CONFIGURABLE(cfgMcTriggerPDGs, std::vector, {}, "MC PDG codes to use exclusively as trigger particles and exclude from associated particles. Empty = no selection.") + + ConfigurableAxis axisVertex{"axisVertex", {7, -7, 7}, "vertex axis for histograms"}; + ConfigurableAxis axisDeltaPhi{"axisDeltaPhi", {72, -PIHalf, PIHalf * 3}, "delta phi axis for histograms"}; + ConfigurableAxis axisDeltaEta{"axisDeltaEta", {40, -2, 2}, "delta eta axis for histograms"}; + ConfigurableAxis axisPtTrigger{"axisPtTrigger", {VARIABLE_WIDTH, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0, 10.0}, "pt trigger axis for histograms"}; + ConfigurableAxis axisPtAssoc{"axisPtAssoc", {VARIABLE_WIDTH, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0}, "pt associated axis for histograms"}; + ConfigurableAxis axisMultiplicity{"axisMultiplicity", {VARIABLE_WIDTH, 0, 5, 10, 20, 30, 40, 50, 100.1}, "multiplicity / centrality axis for histograms"}; + + ConfigurableAxis axisVertexEfficiency{"axisVertexEfficiency", {10, -10, 10}, "vertex axis for efficiency histograms"}; + ConfigurableAxis axisEtaEfficiency{"axisEtaEfficiency", {20, -1.0, 1.0}, "eta axis for efficiency histograms"}; + ConfigurableAxis axisPtEfficiency{"axisPtEfficiency", {VARIABLE_WIDTH, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.25, 1.5, 1.75, 2.0, 2.25, 2.5, 2.75, 3.0, 3.25, 3.5, 3.75, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0}, "pt axis for efficiency histograms"}; + + Configurable cfgTrigger{"cfgTrigger", 4, "Event trigger selection: 0=none, 1=sel8, 2=sel8+(kNoSameBunchPileup+kIsGoodZvtxFT0vsPV+kIsGoodITSLayersAll), 3=sel8+occupancy+(kNoCollInTimeRangeStandard)+(kNoSameBunchPileup+kIsGoodZvtxFT0vsPV+kIsGoodITSLayersAll), 4=sel8+(kNoSameBunchPileup+kIsGoodZvtxFT0vsPV)"}; + Configurable cfgMinOcc{"cfgMinOcc", 0, "minimum occupancy selection (for cfgTrigger==3)"}; + Configurable cfgMaxOcc{"cfgMaxOcc", 3000, "maximum occupancy selection (for cfgTrigger==3)"}; + + // Named trigger codes to avoid magic numbers in keepCollisionAO2D + // ---- Ion/nucleus PDG encoding helpers (10LZZZAAAI) ---- + // Note: these are *format* constants (not particle PDG species codes) + static constexpr int IonCodeThreshold = 1000000000; // 10^9 + static constexpr int IonZDivisor = 10000; + static constexpr int IonZModulo = 1000; + static constexpr int PdgElectron = static_cast(PDG_t::kElectron); + static constexpr int PdgMuon = static_cast(PDG_t::kMuonMinus); + static constexpr int PdgPion = static_cast(PDG_t::kPiPlus); + static constexpr int PdgKaon = static_cast(PDG_t::kKPlus); + static constexpr int PdgProton = static_cast(PDG_t::kProton); + static constexpr int TriggerNone = 0; + static constexpr int TriggerSel8 = 1; + static constexpr int TriggerSel8Quality = 2; + static constexpr int TriggerSel8OccQuality = 3; + static constexpr int TriggerSel8NoSbpZvtx = 4; + template + bool keepCollisionAO2D(TCollision const& collision) const + { + if (cfgTrigger.value == TriggerNone) { + return true; + } else if (cfgTrigger.value == TriggerSel8) { + return collision.sel8(); + } else if (cfgTrigger.value == TriggerSel8Quality) { + return collision.sel8() && + collision.selection_bit(aod::evsel::kNoSameBunchPileup) && + collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) && + collision.selection_bit(aod::evsel::kIsGoodITSLayersAll); + } else if (cfgTrigger.value == TriggerSel8OccQuality) { + const int occupancy = collision.trackOccupancyInTimeRange(); + if (occupancy < cfgMinOcc.value || occupancy >= cfgMaxOcc.value) { + return false; + } + return collision.sel8() && + collision.selection_bit(aod::evsel::kNoSameBunchPileup) && + collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) && + collision.selection_bit(aod::evsel::kNoCollInTimeRangeStandard) && + collision.selection_bit(aod::evsel::kIsGoodITSLayersAll); + } else if (cfgTrigger.value == TriggerSel8NoSbpZvtx) { + return collision.sel8() && + collision.selection_bit(aod::evsel::kNoSameBunchPileup) && + collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV); + } + + LOGF(warn, "Invalid cfgTrigger=%d. Accepting all collisions.", cfgTrigger.value); + return true; + } + + template + float eventMultiplicityFT0MOrFallback(TCollision const& collision, float fallback) const + { + if (cfgUseFT0M.value == 0) { + return fallback; + } + + // Prefer FT0M centrality if present in this collision table + if constexpr (requires { collision.centFT0M(); }) { + const float v = collision.centFT0M(); + if (v >= 0.f) { + return v; // expected 0..100 + } + } + + // Some tables may expose a validity bit + if constexpr (requires { collision.centFT0MValid(); }) { + if (collision.centFT0MValid()) { + if constexpr (requires { collision.centFT0M(); }) { + return collision.centFT0M(); + } + } + } + + return fallback; + } + + static int chargeFromPdg(int pdg) + { + const int apdg = std::abs(pdg); + + // Ions/nuclei: PDG code format 10LZZZAAAI -> Z is encoded in digits [7..5] + if (apdg >= IonCodeThreshold) { + const int z = (apdg / IonZDivisor) % IonZModulo; + return (pdg >= 0) ? z : -z; + } + + // Common charged hadrons/leptons (extend if needed) + switch (apdg) { + case PdgElectron: // e + case PdgMuon: // mu + case PdgPion: // pi + case PdgKaon: // K + case PdgProton: // p + return (pdg >= 0) ? 1 : -1; + default: + return 0; + } + } + + // This filter is applied to AOD and derived data (column names are identical) + Filter collisionZVtxFilter = nabs(aod::collision::posZ) < cfgCutVertex; + // This filter is only applied to AOD + Filter collisionVertexTypeFilter = (aod::collision::flags & static_cast(aod::collision::CollisionFlagsRun2::Run2VertexerTracks)) == static_cast(aod::collision::CollisionFlagsRun2::Run2VertexerTracks); + + // Track filters + Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && (aod::track::pt > cfgCutPt) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)); + Filter cfTrackFilter = (nabs(aod::cftrack::eta) < cfgCutEta) && (aod::cftrack::pt > cfgCutPt) && ((aod::track::trackType & (uint8_t)cfgTrackBitMask) == (uint8_t)cfgTrackBitMask); + + // MC filters + Filter cfMCCollisionFilter = nabs(aod::mccollision::posZ) < cfgCutVertex; + Filter cfMCParticleFilter = (nabs(aod::cfmcparticle::eta) < cfgCutEta) && (aod::cfmcparticle::pt > cfgCutPt); // && (aod::cfmcparticle::sign != 0); //check the sign manually, some specials may be neutral + + // Output definitions + OutputObj same{"sameEvent"}; + OutputObj mixed{"mixedEvent"}; + + // persistent caches + std::vector efficiencyAssociatedCache; + + std::unique_ptr multCutFormula; + std::array multCutFormulaParamIndex; + + struct Config { + bool mPairCuts = false; + THn* mEfficiencyTrigger = nullptr; + THn* mEfficiencyAssociated = nullptr; + bool efficiencyLoaded = false; + } cfg; + + HistogramRegistry registry{"registry"}; + PairCuts mPairCuts; + + Service ccdb; + + // AO2D-based tracks with PID for pi / K / p / d + using TracksPID = soa::Join; + using TracksPIDFiltered = soa::Filtered; + + using TracksPIDMC = soa::Join; + + using CollisionsAO2DMC = soa::Join; + + // group MC particles by MC collision + Preslice mcParticlesPerCollision = aod::mcparticle::mcCollisionId; + + // Helper: access a row of a soa::Join by row index (operator[] is not available for joins) + template + static auto trackAt(TTracks const& tracks, uint32_t idx) + { + if constexpr (requires { tracks.iteratorAt(idx); }) { + return tracks.iteratorAt(idx); + } else { + return tracks.rawIteratorAt(idx); + } + } + + // Helper: AO2D track-quality selection (default: global tracks) + template + bool passTrackQualityAO2D(const TTrack& trk) const + { + // Default: require global tracks when the column exists + if constexpr (requires { trk.isGlobalTrack(); }) { + if (!trk.isGlobalTrack()) { + return false; + } + } else if constexpr (requires { trk.isGlobalTrackSDD(); }) { + // fallback (older tables) + if (!trk.isGlobalTrackSDD()) { + return false; + } + } + + if constexpr (requires { trk.itsNCls(); }) { + if (itsnclusters.value > 0 && trk.itsNCls() < itsnclusters.value) { + return false; + } + } + + if constexpr (requires { trk.tpcNClsFound(); }) { + if (cfgTPCNClsMin.value > 0 && trk.tpcNClsFound() < cfgTPCNClsMin.value) { + return false; + } + } + + if constexpr (requires { trk.tpcChi2NCl(); }) { + if (chi2pertpccluster.value > 0.f && trk.tpcChi2NCl() > chi2pertpccluster.value) { + return false; + } + } + + if constexpr (requires { trk.itsChi2NCl(); }) { + if (chi2peritscluster.value > 0.f && trk.itsChi2NCl() > chi2peritscluster.value) { + return false; + } + } + + if constexpr (requires { trk.dcaXY(); }) { + if (cfgDcaXYMax.value > 0.f && std::abs(trk.dcaXY()) > cfgDcaXYMax.value) { + return false; + } + } + + if constexpr (requires { trk.dcaZ(); }) { + if (cfgDcaZMax.value > 0.f && std::abs(trk.dcaZ()) > cfgDcaZMax.value) { + return false; + } + } + + return true; + } + + struct SimpleTrack { + float eta; + float phi; + float pt; + int charge; + }; + + struct MixEventEntry { + float multiplicity; + float zvtx; + std::vector triggerTracks; + std::vector associatedTracks; + }; + + // Very simple mixing buffer: keep last cfgNoMixedEvents events + std::deque mMixEvents; + std::deque mMixEventsMC; + + // Preslice to group AO2D tracks by collision + + using DerivedCollisions = soa::Filtered; + using DerivedTracks = soa::Filtered; + using DerivedTracksWithRefs = soa::Filtered>; + + void init(o2::framework::InitContext&) + { + // --- HISTOGRAMS --- + registry.add("yields", "multiplicity/centrality vs pT vs eta", {HistType::kTH3F, {{100, 0, 100, "/multiplicity/centrality"}, {40, 0, 20, "p_{T}"}, {100, -2, 2, "#eta"}}}); + registry.add("etaphi", "multiplicity/centrality vs eta vs phi", {HistType::kTH3F, {{100, 0, 100, "multiplicity/centrality"}, {100, -2, 2, "#eta"}, {200, 0, o2::constants::math::TwoPI, "#varphi"}}}); + + if (doprocessSameDerivedMultSet) { + if (cfgMultCorrelationsMask == 0) + LOGF(fatal, "cfgMultCorrelationsMask can not be 0 when MultSet process functions are in use."); + std::vector multAxes; + if (cfgMultCorrelationsMask & aod::cfmultset::CentFT0C) + multAxes.emplace_back(100, 0, 100, "FT0C centrality"); + if (cfgMultCorrelationsMask & aod::cfmultset::MultFV0A) + multAxes.emplace_back(1000, 0, 100000, "V0A multiplicity"); + if (cfgMultCorrelationsMask & aod::cfmultset::MultNTracksPV) + multAxes.emplace_back(100, 0, 1000, "Nch PV"); + if (cfgMultCorrelationsMask & aod::cfmultset::MultNTracksGlobal) + multAxes.emplace_back(100, 0, 1000, "Nch Global"); + registry.add("multCorrelations", "Multiplicity correlations", {HistType::kTHnSparseF, multAxes}); + } + registry.add("multiplicity", "event multiplicity", {HistType::kTH1F, {{1000, 0, 100, "/multiplicity/centrality"}}}); + registry.add("yvspt", "y vs pT", {HistType::kTH2F, {{100, -1, 1, "y"}, {100, 0, 20, "p_{T}"}}}); // y vs pT for all tracks (control histogram) + + const int maxMixBin = AxisSpec(axisMultiplicity).getNbins() * AxisSpec(axisVertex).getNbins(); + // The bin numbers for the control histograms (eventcount_*) come from getBin(...) and are the following: #mult_bin * #number_of_z_bins + #zbin + registry.add("eventcount_same", "bin", {HistType::kTH1F, {{maxMixBin + 2, -2.5, -0.5 + maxMixBin, "bin"}}}); + registry.add("eventcount_mixed", "bin", {HistType::kTH1F, {{maxMixBin + 2, -2.5, -0.5 + maxMixBin, "bin"}}}); + registry.add("trackcount_same", "bin", {HistType::kTH2F, {{maxMixBin + 2, -2.5, -0.5 + maxMixBin, "bin"}, {10, -0.5, 9.5}}}); + registry.add("trackcount_mixed", "bin", {HistType::kTH3F, {{maxMixBin + 2, -2.5, -0.5 + maxMixBin, "bin"}, {10, -0.5, 9.5}, {10, -0.5, 9.5}}}); + + mPairCuts.SetHistogramRegistry(®istry); + + if (cfgPairCut->get("Photon") > 0 || cfgPairCut->get("K0") > 0 || cfgPairCut->get("Lambda") > 0 || cfgPairCut->get("Phi") > 0 || cfgPairCut->get("Rho") > 0) { + mPairCuts.SetPairCut(PairCuts::Photon, cfgPairCut->get("Photon")); + mPairCuts.SetPairCut(PairCuts::K0, cfgPairCut->get("K0")); + mPairCuts.SetPairCut(PairCuts::Lambda, cfgPairCut->get("Lambda")); + mPairCuts.SetPairCut(PairCuts::Phi, cfgPairCut->get("Phi")); + mPairCuts.SetPairCut(PairCuts::Rho, cfgPairCut->get("Rho")); + cfg.mPairCuts = true; + } + + if (cfgTwoTrackCut > 0) { + mPairCuts.SetTwoTrackCuts(cfgTwoTrackCut, cfgTwoTrackCutMinRadius); + } + + // --- OBJECT INIT --- + + if (!cfgMultCutFormula.value.empty()) { + multCutFormula = std::make_unique("multCutFormula", cfgMultCutFormula.value.c_str()); + std::fill_n(multCutFormulaParamIndex.begin(), std::size(multCutFormulaParamIndex), ~0u); + std::array pars = {"cFT0C", "mFV0A", "mPV", "mGlob"}; // must correspond the order of MultiplicityEstimators + for (uint i = 0, n = multCutFormula->GetNpar(); i < n; ++i) { + auto m = std::find(pars.begin(), pars.end(), multCutFormula->GetParName(i)); + if (m == pars.end()) { + + LOGF(warning, "Unknown parameter in cfgMultCutFormula: %s", multCutFormula->GetParName(i)); + continue; + } + if ((cfgMultCorrelationsMask.value & (1u << i)) == 0) { + LOGF(warning, "The centrality/multiplicity estimator %s is not available to be used in cfgMultCutFormula. Ensure cfgMultCorrelationsMask is correct and matches the CFMultSets in derived data."); + } else { + multCutFormulaParamIndex[std::distance(pars.begin(), m)] = i; + LOGF(info, "Multiplicity cut parameter %s in use.", m->c_str()); + } + } + } + + std::vector corrAxis = {{axisDeltaEta, "#Delta#eta"}, + {axisPtAssoc, "p_{T} (GeV/c)"}, + {axisPtTrigger, "p_{T} (GeV/c)"}, + {axisMultiplicity, "multiplicity / centrality"}, + {axisDeltaPhi, "#Delta#varphi (rad)"}, + {axisVertex, "z-vtx (cm)"}}; + std::vector effAxis = {{axisEtaEfficiency, "#eta"}, + {axisPtEfficiency, "p_{T} (GeV/c)"}, + {axisVertexEfficiency, "z-vtx (cm)"}}; + std::vector userAxis; + std::vector userMixingAxis; + + same.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, userAxis)); + mixed.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, userMixingAxis)); + + same->setTrackEtaCut(cfgCutEta); + mixed->setTrackEtaCut(cfgCutEta); + + if (!cfgEfficiencyAssociated.value.empty()) + efficiencyAssociatedCache.reserve(512); + + // o2-ccdb-upload -p Users/jgrosseo/correlations/LHC15o -f /tmp/correction_2011_global.root -k correction + + ccdb->setURL("http://alice-ccdb.cern.ch"); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + + auto now = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + ccdb->setCreatedNotAfter(now); // TODO must become global parameter from the train creation time + } + + int getMagneticField(uint64_t timestamp) + { + // TODO done only once (and not per run). Will be replaced by CCDBConfigurable + static o2::parameters::GRPObject* grpo = nullptr; + // static o2::parameters::GRPMagField* grpo = nullptr; + if (grpo == nullptr) { + grpo = ccdb->getForTimeStamp("GLO/GRP/GRP", timestamp); + // grpo = ccdb->getForTimeStamp("GLO/Config/GRPMagField", timestamp); + if (grpo == nullptr) { + LOGF(fatal, "GRP object not found for timestamp %llu", timestamp); + return 0; + } + LOGF(info, "Retrieved GRP for timestamp %llu with magnetic field of %d kG", timestamp, grpo->getNominalL3Field()); + } + return grpo->getNominalL3Field(); + } + + template + using HasMultSet = decltype(std::declval().multiplicities()); + + template + void fillQA(const TCollision& /*collision*/, float multiplicity, const TTracks& tracks) + { + registry.fill(HIST("multiplicity"), multiplicity); + for (const auto& track1 : tracks) { + registry.fill(HIST("yields"), multiplicity, track1.pt(), track1.eta()); + registry.fill(HIST("etaphi"), multiplicity, track1.eta(), track1.phi()); + } + } + + template + using HasInvMass = decltype(std::declval().invMass()); + template + using HasPDGCode = decltype(std::declval().pdgCode()); + + template + void fillQA(const TCollision& collision, float multiplicity, const TTracks1& tracks1, const TTracks2& tracks2) + { + for (const auto& track1 : tracks1) { + registry.fill(HIST("yieldsTrigger"), multiplicity, track1.pt(), track1.eta()); + registry.fill(HIST("etaphiTrigger"), multiplicity, track1.eta(), track1.phi()); + } + fillQA(collision, multiplicity, tracks2); + } + + template + bool checkObject(TTrack& track) + { + if constexpr (step <= CorrelationContainer::kCFStepAnaTopology) { + return track.isPhysicalPrimary(); + } else if constexpr (step == CorrelationContainer::kCFStepTrackedOnlyPrim) { + return track.isPhysicalPrimary() && (track.flags() & aod::cfmcparticle::kReconstructed); + } else if constexpr (step == CorrelationContainer::kCFStepTracked) { + return (track.flags() & aod::cfmcparticle::kReconstructed); + } + + return true; + } + + template + void fillCorrelations(TTarget target, TTracks1& tracks1, TTracks2& tracks2, float multiplicity, float posZ, int magField, float eventWeight) + { + // Helper lambda for pair charge selection + auto passPairCharge = [this](auto const& t1, auto const& t2) { + if (cfgPairCharge.value == 0) { + return true; + } + + int q1 = 0; + int q2 = 0; + + if constexpr (requires { t1.sign(); }) { + q1 = t1.sign(); + } else if constexpr (requires { t1.charge(); }) { + q1 = t1.charge(); + } else if constexpr (requires { t1.pdgCode(); }) { + q1 = chargeFromPdg(t1.pdgCode()); + } + + if constexpr (requires { t2.sign(); }) { + q2 = t2.sign(); + } else if constexpr (requires { t2.charge(); }) { + q2 = t2.charge(); + } else if constexpr (requires { t2.pdgCode(); }) { + q2 = chargeFromPdg(t2.pdgCode()); + } + + if (q1 == 0 || q2 == 0) { + // If we cannot determine both charges, reject the pair for pair-charge selections + return false; + } + + const int pairSign = q1 * q2; + if (cfgPairCharge.value == 1) { // like-sign pairs only + return pairSign > 0; + } + if (cfgPairCharge.value == -1) { // unlike-sign pairs only + return pairSign < 0; + } + + return true; + }; + + // Cache efficiency for particles (too many FindBin lookups) + if constexpr (step == CorrelationContainer::kCFStepCorrected) { + if (cfg.mEfficiencyAssociated) { + efficiencyAssociatedCache.clear(); + efficiencyAssociatedCache.reserve(tracks2.size()); + for (const auto& track : tracks2) { + efficiencyAssociatedCache.push_back(getEfficiencyCorrection(cfg.mEfficiencyAssociated, track.eta(), track.pt(), multiplicity, posZ)); + } + } + } + + for (const auto& track1 : tracks1) { + // LOGF(info, "Track %f | %f | %f %d %d", track1.eta(), track1.phi(), track1.pt(), track1.isGlobalTrack(), track1.isGlobalTrackSDD()); + + if constexpr (step <= CorrelationContainer::kCFStepTracked) { + if (!checkObject(track1)) { + continue; + } + } + + float triggerWeight = eventWeight; + if constexpr (step == CorrelationContainer::kCFStepCorrected) { + if (cfg.mEfficiencyTrigger) { + triggerWeight *= getEfficiencyCorrection(cfg.mEfficiencyTrigger, track1.eta(), track1.pt(), multiplicity, posZ); + } + } + + target->getTriggerHist()->Fill(step, track1.pt(), multiplicity, posZ, triggerWeight); + + for (const auto& track2 : tracks2) { + if constexpr (std::is_same::value) { + if (track1.globalIndex() == track2.globalIndex()) { + // LOGF(info, "Track identical: %f | %f | %f || %f | %f | %f", track1.eta(), track1.phi(), track1.pt(), track2.eta(), track2.phi(), track2.pt()); + continue; + } + } + if constexpr (step <= CorrelationContainer::kCFStepTracked) { + if (!checkObject(track2)) { + continue; + } + } + + // Pair charge selection + if (!passPairCharge(track1, track2)) { + continue; + } + + if (cfgPtOrder != 0 && track2.pt() >= track1.pt()) { + continue; + } + + if constexpr (std::is_same::value) { + if constexpr (step >= CorrelationContainer::kCFStepReconstructed) { + if (cfg.mPairCuts && mPairCuts.conversionCuts(track1, track2)) { + continue; + } + if (cfgTwoTrackCut > 0 && mPairCuts.twoTrackCut(track1, track2, magField)) { + continue; + } + } + } + + float associatedWeight = triggerWeight; + if constexpr (step == CorrelationContainer::kCFStepCorrected) { + if (cfg.mEfficiencyAssociated) { + associatedWeight *= efficiencyAssociatedCache[track2.filteredIndex()]; + } + } + + float deltaPhi = RecoDecay::constrainAngle(track1.phi() - track2.phi(), -o2::constants::math::PIHalf); + target->getPairHist()->Fill(step, track1.eta() - track2.eta(), track2.pt(), track1.pt(), multiplicity, deltaPhi, posZ, associatedWeight); + } + } + } + + void loadEfficiency(uint64_t timestamp) + { + if (cfg.efficiencyLoaded) { + return; + } + if (cfgEfficiencyTrigger.value.empty() == false) { + if (cfgLocalEfficiency > 0) { + TFile* fEfficiencyTrigger = TFile::Open(cfgEfficiencyTrigger.value.c_str(), "READ"); + cfg.mEfficiencyTrigger = reinterpret_cast(fEfficiencyTrigger->Get("ccdb_object")); + } else { + cfg.mEfficiencyTrigger = ccdb->getForTimeStamp>(cfgEfficiencyTrigger, timestamp); + } + if (cfg.mEfficiencyTrigger == nullptr) { + LOGF(fatal, "Could not load efficiency histogram for trigger particles from %s", cfgEfficiencyTrigger.value.c_str()); + } + LOGF(info, "Loaded efficiency histogram for trigger particles from %s (%p)", cfgEfficiencyTrigger.value.c_str(), (void*)cfg.mEfficiencyTrigger); + } + if (cfgEfficiencyAssociated.value.empty() == false) { + if (cfgLocalEfficiency > 0) { + TFile* fEfficiencyAssociated = TFile::Open(cfgEfficiencyAssociated.value.c_str(), "READ"); + cfg.mEfficiencyAssociated = reinterpret_cast(fEfficiencyAssociated->Get("ccdb_object")); + } else { + cfg.mEfficiencyAssociated = ccdb->getForTimeStamp>(cfgEfficiencyAssociated, timestamp); + } + if (cfg.mEfficiencyAssociated == nullptr) { + LOGF(fatal, "Could not load efficiency histogram for associated particles from %s", cfgEfficiencyAssociated.value.c_str()); + } + LOGF(info, "Loaded efficiency histogram for associated particles from %s (%p)", cfgEfficiencyAssociated.value.c_str(), (void*)cfg.mEfficiencyAssociated); + } + cfg.efficiencyLoaded = true; + } + + double getEfficiencyCorrection(THn* eff, float eta, float pt, float multiplicity, float posZ) + { + int effVars[4]; + effVars[0] = eff->GetAxis(0)->FindBin(eta); + effVars[1] = eff->GetAxis(1)->FindBin(pt); + effVars[2] = eff->GetAxis(2)->FindBin(multiplicity); + effVars[3] = eff->GetAxis(3)->FindBin(posZ); + return eff->GetBinContent(effVars); + } + + template + bool passPIDForSpecies(const TTrack& trk, int species) + { + // -1 means "all charged tracks" + if (species < 0) { + return trk.sign() != 0; + } + + const bool useTPCOnly = (cfgUseTPCOnlyPID.value != 0); + + switch (species) { + case 0: { // pion + if (cfgNsigmaTPCPi.value > 0.f && std::abs(trk.tpcNSigmaPi()) > cfgNsigmaTPCPi.value) { + return false; + } + if (!useTPCOnly && cfgNsigmaTOFPi.value > 0.f && std::abs(trk.tofNSigmaPi()) > cfgNsigmaTOFPi.value) { + return false; + } + return trk.sign() != 0; + } + case 1: { // kaon + if (cfgNsigmaTPCKa.value > 0.f && std::abs(trk.tpcNSigmaKa()) > cfgNsigmaTPCKa.value) { + return false; + } + if (!useTPCOnly && cfgNsigmaTOFKa.value > 0.f && std::abs(trk.tofNSigmaKa()) > cfgNsigmaTOFKa.value) { + return false; + } + return trk.sign() != 0; + } + case 2: { // proton + if (cfgNsigmaTPCPr.value > 0.f && std::abs(trk.tpcNSigmaPr()) > cfgNsigmaTPCPr.value) { + return false; + } + if (!useTPCOnly && cfgNsigmaTOFPr.value > 0.f && std::abs(trk.tofNSigmaPr()) > cfgNsigmaTOFPr.value) { + return false; + } + return trk.sign() != 0; + } + case 3: { // deuteron + if (cfgNsigmaTPCDe.value > 0.f && std::abs(trk.tpcNSigmaDe()) > cfgNsigmaTPCDe.value) { + return false; + } + if (!useTPCOnly && cfgNsigmaTOFDe.value > 0.f && std::abs(trk.tofNSigmaDe()) > cfgNsigmaTOFDe.value) { + return false; + } + return trk.sign() != 0; + } + default: + return false; + } + } + + // Simple correlation filler writing directly into CorrelationContainer + void fillCorrelationsSimple(OutputObj& target, + CorrelationContainer::CFStep step, + const std::vector& triggers, + const std::vector& associates, + float multiplicity, + float posZ, + float eventWeight) + { + auto* trigHist = target->getTriggerHist(); + auto* pairHist = target->getPairHist(); + + for (auto const& t : triggers) { + trigHist->Fill(step, t.pt, multiplicity, posZ, eventWeight); + + for (auto const& a : associates) { + if (cfgPtOrder != 0 && a.pt >= t.pt) { + continue; + } + // Pair charge selection + if (cfgPairCharge.value != 0) { + const int pairSign = t.charge * a.charge; + if (cfgPairCharge.value == 1 && pairSign <= 0) { + continue; // keep only like-sign pairs + } + if (cfgPairCharge.value == -1 && pairSign >= 0) { + continue; // keep only unlike-sign pairs + } + } + float deltaPhi = RecoDecay::constrainAngle(t.phi - a.phi, -o2::constants::math::PIHalf); + float deltaEta = t.eta - a.eta; + pairHist->Fill(step, + deltaEta, + a.pt, + t.pt, + multiplicity, + deltaPhi, + posZ, + eventWeight); + } + } + } + template + void processSameDerivedPIDT(CollType const& collision, TCFTracks const& tracks, TracksPID const& tracksAll) + { + if (cfgVerbosity > 0) { + LOGF(info, "processSameDerivedPIDT: Tracks for collision: %d | Vertex: %.1f | Multiplicity/Centrality: %.1f", tracks.size(), collision.posZ(), collision.multiplicity()); + } + + loadEfficiency(collision.timestamp()); + + const auto multiplicity = eventMultiplicityFT0MOrFallback(collision, collision.multiplicity()); + + using BinningTypeDerived = ColumnBinningPolicy; + BinningTypeDerived configurableBinningDerived{{axisVertex, axisMultiplicity}, true}; + int bin = configurableBinningDerived.getBin({collision.posZ(), multiplicity}); + registry.fill(HIST("eventcount_same"), bin); + registry.fill(HIST("trackcount_same"), bin, tracks.size()); + + // Kinematic QA + fillQA(collision, multiplicity, tracks); + + // PID-selected trigger/associate lists via CFTrackRefs -> AO2D TracksPID + std::vector triggerTracks; + std::vector associatedTracks; + triggerTracks.reserve(tracks.size()); + associatedTracks.reserve(tracks.size()); + + for (auto const& cftrk : tracks) { + const auto trk = trackAt(tracksAll, cftrk.trackId()); + if (trk.sign() == 0) { + continue; + } + + if (passPIDForSpecies(trk, cfgTriggerSpecies.value)) { + if (cfgTriggerCharge.value == 0 || trk.sign() == cfgTriggerCharge.value) { + triggerTracks.push_back(SimpleTrack{cftrk.eta(), cftrk.phi(), cftrk.pt(), trk.sign()}); + } + } + + if (passPIDForSpecies(trk, cfgAssociatedSpecies.value)) { + if (cfgAssociatedCharge.value == 0 || trk.sign() == cfgAssociatedCharge.value) { + associatedTracks.push_back(SimpleTrack{cftrk.eta(), cftrk.phi(), cftrk.pt(), trk.sign()}); + } + } + } + + if (triggerTracks.empty() || associatedTracks.empty()) { + return; + } + + same->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); + fillCorrelationsSimple(same, + CorrelationContainer::kCFStepReconstructed, + triggerTracks, + associatedTracks, + multiplicity, + collision.posZ(), + 1.0f); + + if (cfg.mEfficiencyAssociated || cfg.mEfficiencyTrigger) { + same->fillEvent(multiplicity, CorrelationContainer::kCFStepCorrected); + fillCorrelationsSimple(same, + CorrelationContainer::kCFStepCorrected, + triggerTracks, + associatedTracks, + multiplicity, + collision.posZ(), + 1.0f); + } + } + + void processSameDerivedPID(DerivedCollisions::iterator const& collision, + DerivedTracksWithRefs const& tracks, + TracksPID const& tracksAll) + { + processSameDerivedPIDT(collision, tracks, tracksAll); + } + PROCESS_SWITCH(Nucleibalance, processSameDerivedPID, "Process same event on derived data with PID via CFTrackRefs", false); + + void processSameDerivedMultSetPID(soa::Filtered>::iterator const& collision, + DerivedTracksWithRefs const& tracks, + TracksPID const& tracksAll) + { + processSameDerivedPIDT(collision, tracks, tracksAll); + } + PROCESS_SWITCH(Nucleibalance, processSameDerivedMultSetPID, "Process same event on derived data with multiplicity sets and PID via CFTrackRefs", false); + // AO2D-based processing: same + mixed events with PID-selected pi, p, d + void processAO2D(soa::Join::iterator const& collision, + TracksPID const& tracksAll) + { + // Event selection on vertex + if (std::abs(collision.posZ()) > cfgCutVertex) { + return; + } + + // Event selection (cfgTrigger) -- AO2D only + if (!keepCollisionAO2D(collision)) { + return; + } + + const auto thisCollIndex = collision.globalIndex(); + + // Per-event containers + std::vector eventTracks; // all selected tracks for multiplicity / QA + std::vector triggerTracks; // PID + charge selected triggers + std::vector associatedTracks; // PID + charge selected associates + + // Loop over all tracks and select those belonging to this collision + for (auto const& trk : tracksAll) { + if (trk.collisionId() != thisCollIndex) { + continue; + } + + // Kinematic cuts + if (std::abs(trk.eta()) > cfgCutEta || trk.pt() < cfgCutPt) { + continue; + } + + // Track-quality cuts (default: global tracks) + if (!passTrackQualityAO2D(trk)) { + continue; + } + + // Save for multiplicity / QA (keep charge even if neutral) + eventTracks.push_back(SimpleTrack{trk.eta(), trk.phi(), trk.pt(), static_cast(trk.sign())}); + + if (trk.sign() == 0) { + continue; + } + + // Trigger selection: PID + charge + if (passPIDForSpecies(trk, cfgTriggerSpecies.value)) { + if (cfgTriggerCharge.value == 0 || trk.sign() == cfgTriggerCharge.value) { + triggerTracks.push_back(SimpleTrack{trk.eta(), trk.phi(), trk.pt(), trk.sign()}); + } + } + + // Associated selection: PID + charge + if (passPIDForSpecies(trk, cfgAssociatedSpecies.value)) { + if (cfgAssociatedCharge.value == 0 || trk.sign() == cfgAssociatedCharge.value) { + associatedTracks.push_back(SimpleTrack{trk.eta(), trk.phi(), trk.pt(), trk.sign()}); + } + } + } + + if (triggerTracks.empty() || associatedTracks.empty()) { + return; + } + + const float multiplicity = + eventMultiplicityFT0MOrFallback(collision, static_cast(eventTracks.size())); + + // QA on tracks for this event (AO2D-based) + registry.fill(HIST("multiplicity"), multiplicity); + for (const auto& t : eventTracks) { + registry.fill(HIST("yields"), multiplicity, t.pt, t.eta); + registry.fill(HIST("etaphi"), multiplicity, t.eta, t.phi); + } + + // -------------------------- + // SAME-EVENT CORRELATIONS + // -------------------------- + same->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); + fillCorrelationsSimple(same, + CorrelationContainer::kCFStepReconstructed, + triggerTracks, + associatedTracks, + multiplicity, + collision.posZ(), + 1.0f); + + // Optional efficiency-corrected step (if you configure efficiencies) + if (cfg.mEfficiencyAssociated || cfg.mEfficiencyTrigger) { + if (!cfg.efficiencyLoaded) { + // For AO2D only, the timestamp is not crucial if you use local efficiency files + loadEfficiency(0); + } + same->fillEvent(multiplicity, CorrelationContainer::kCFStepCorrected); + fillCorrelationsSimple(same, + CorrelationContainer::kCFStepCorrected, + triggerTracks, + associatedTracks, + multiplicity, + collision.posZ(), + 1.0f); + } + + // -------------------------- + // MIXED-EVENT CORRELATIONS + // -------------------------- + for (auto const& prev : mMixEvents) { + if (prev.triggerTracks.empty() || prev.associatedTracks.empty()) { + continue; + } + + mixed->fillEvent(prev.multiplicity, CorrelationContainer::kCFStepReconstructed); + fillCorrelationsSimple(mixed, + CorrelationContainer::kCFStepReconstructed, + triggerTracks, + prev.associatedTracks, + prev.multiplicity, + prev.zvtx, + 1.0f); + + if (cfg.mEfficiencyAssociated || cfg.mEfficiencyTrigger) { + mixed->fillEvent(prev.multiplicity, CorrelationContainer::kCFStepCorrected); + fillCorrelationsSimple(mixed, + CorrelationContainer::kCFStepCorrected, + triggerTracks, + prev.associatedTracks, + prev.multiplicity, + prev.zvtx, + 1.0f); + } + } + + // -------------------------- + // UPDATE MIXING BUFFER + // -------------------------- + MixEventEntry entry; + entry.multiplicity = multiplicity; + entry.zvtx = collision.posZ(); + entry.triggerTracks = std::move(triggerTracks); + entry.associatedTracks = std::move(associatedTracks); + + mMixEvents.push_front(std::move(entry)); + if (mMixEvents.size() > static_cast(cfgNoMixedEvents.value)) { + mMixEvents.pop_back(); + } + } + + PROCESS_SWITCH(Nucleibalance, processAO2D, + "Process AO2D: same- and mixed-event correlations with PID", true); + + // AO2D-MC processing: reconstructed correlations + MC efficiency (truth vs reco) + void processAO2DMC(CollisionsAO2DMC::iterator const& collision, + TracksPIDMC const& tracksAll, + aod::McCollisions const& /*mcCollisions*/, + aod::McParticles const& mcParticles) + { + if (std::abs(collision.posZ()) > cfgCutVertex) { + return; + } + if (!keepCollisionAO2D(collision)) { + return; + } + + // Resolve MC collision index + int mcCollIdx = -1; + if constexpr (requires { collision.has_mcCollision(); }) { + if (!collision.has_mcCollision()) { + return; + } + } + if constexpr (requires { collision.mcCollisionId(); }) { + mcCollIdx = collision.mcCollisionId(); + } else if constexpr (requires { collision.mcCollision().globalIndex(); }) { + mcCollIdx = collision.mcCollision().globalIndex(); + } + if (mcCollIdx < 0) { + return; + } + + const auto thisCollIndex = collision.globalIndex(); + + std::vector eventTracks; + std::vector triggerTracks; + std::vector associatedTracks; + + for (auto const& trk : tracksAll) { + if (trk.collisionId() != thisCollIndex) { + continue; + } + if (std::abs(trk.eta()) > cfgCutEta || trk.pt() < cfgCutPt) { + continue; + } + if (!passTrackQualityAO2D(trk)) { + continue; + } + + eventTracks.push_back(SimpleTrack{trk.eta(), trk.phi(), trk.pt(), static_cast(trk.sign())}); + + if (trk.sign() == 0) { + continue; + } + + if (passPIDForSpecies(trk, cfgTriggerSpecies.value) && + (cfgTriggerCharge.value == 0 || trk.sign() == cfgTriggerCharge.value)) { + triggerTracks.push_back(SimpleTrack{trk.eta(), trk.phi(), trk.pt(), trk.sign()}); + } + + if (passPIDForSpecies(trk, cfgAssociatedSpecies.value) && + (cfgAssociatedCharge.value == 0 || trk.sign() == cfgAssociatedCharge.value)) { + associatedTracks.push_back(SimpleTrack{trk.eta(), trk.phi(), trk.pt(), trk.sign()}); + } + } + + if (triggerTracks.empty() || associatedTracks.empty()) { + return; + } + + const float multiplicity = + eventMultiplicityFT0MOrFallback(collision, static_cast(eventTracks.size())); + + // ---- MC efficiency filling (AO2D-MC) ---- + auto groupedMcParticles = mcParticles.sliceBy(mcParticlesPerCollision, mcCollIdx); + + for (auto const& mcPart : groupedMcParticles) { + if (std::abs(mcPart.eta()) > cfgCutMCEta || mcPart.pt() < cfgCutMCPt) { + continue; + } + if (mcPart.isPhysicalPrimary() && chargeFromPdg(mcPart.pdgCode()) != 0) { + same->getTrackHistEfficiency()->Fill(CorrelationContainer::MC, + mcPart.eta(), mcPart.pt(), + getSpecies(mcPart.pdgCode()), + multiplicity, collision.posZ()); + } + } + + for (auto const& trk : tracksAll) { + if (trk.collisionId() != thisCollIndex) { + continue; + } + if (std::abs(trk.eta()) > cfgCutEta || trk.pt() < cfgCutPt) { + continue; + } + if (!passTrackQualityAO2D(trk)) { + continue; + } + + if constexpr (requires { trk.has_mcParticle(); trk.mcParticle(); }) { + if (trk.has_mcParticle()) { + const auto mcPart = trk.mcParticle(); + if (mcPart.isPhysicalPrimary()) { + same->getTrackHistEfficiency()->Fill(CorrelationContainer::RecoPrimaries, + mcPart.eta(), mcPart.pt(), + getSpecies(mcPart.pdgCode()), + multiplicity, collision.posZ()); + } + same->getTrackHistEfficiency()->Fill(CorrelationContainer::RecoAll, + mcPart.eta(), mcPart.pt(), + getSpecies(mcPart.pdgCode()), + multiplicity, collision.posZ()); + } else { + same->getTrackHistEfficiency()->Fill(CorrelationContainer::Fake, + trk.eta(), trk.pt(), + 0, multiplicity, collision.posZ()); + } + } + } + + // ---- QA ---- + registry.fill(HIST("multiplicity"), multiplicity); + for (const auto& t : eventTracks) { + registry.fill(HIST("yields"), multiplicity, t.pt, t.eta); + registry.fill(HIST("etaphi"), multiplicity, t.eta, t.phi); + } + + // ---- Same-event ---- + same->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); + fillCorrelationsSimple(same, CorrelationContainer::kCFStepReconstructed, + triggerTracks, associatedTracks, + multiplicity, collision.posZ(), 1.0f); + + if (cfg.mEfficiencyAssociated || cfg.mEfficiencyTrigger) { + if (!cfg.efficiencyLoaded) { + loadEfficiency(0); + } + same->fillEvent(multiplicity, CorrelationContainer::kCFStepCorrected); + fillCorrelationsSimple(same, CorrelationContainer::kCFStepCorrected, + triggerTracks, associatedTracks, + multiplicity, collision.posZ(), 1.0f); + } + + // ---- Mixed-event ---- + for (auto const& prev : mMixEventsMC) { + if (prev.triggerTracks.empty() || prev.associatedTracks.empty()) { + continue; + } + + mixed->fillEvent(prev.multiplicity, CorrelationContainer::kCFStepReconstructed); + fillCorrelationsSimple(mixed, CorrelationContainer::kCFStepReconstructed, + triggerTracks, prev.associatedTracks, + prev.multiplicity, prev.zvtx, 1.0f); + + if (cfg.mEfficiencyAssociated || cfg.mEfficiencyTrigger) { + mixed->fillEvent(prev.multiplicity, CorrelationContainer::kCFStepCorrected); + fillCorrelationsSimple(mixed, CorrelationContainer::kCFStepCorrected, + triggerTracks, prev.associatedTracks, + prev.multiplicity, prev.zvtx, 1.0f); + } + } + + MixEventEntry entry; + entry.multiplicity = multiplicity; + entry.zvtx = collision.posZ(); + entry.triggerTracks = std::move(triggerTracks); + entry.associatedTracks = std::move(associatedTracks); + + mMixEventsMC.push_front(std::move(entry)); + if (mMixEventsMC.size() > static_cast(cfgNoMixedEvents.value)) { + mMixEventsMC.pop_back(); + } + } + + PROCESS_SWITCH(Nucleibalance, processAO2DMC, + "Process AO2D-MC: reconstructed correlations + MC efficiency via labels", false); + + template + void processSameDerivedT(CollType const& collision, TTracks1 const& tracks1, TTracks2 const& tracks2) + { + using BinningTypeDerived = ColumnBinningPolicy; + BinningTypeDerived configurableBinningDerived{{axisVertex, axisMultiplicity}, true}; // true is for 'ignore overflows' (true by default). Underflows and overflows will have bin -1. + if (cfgVerbosity > 0) { + LOGF(info, "processSameDerivedT: Tracks for collision: %d/%d | Vertex: %.1f | Multiplicity/Centrality: %.1f", tracks1.size(), tracks2.size(), collision.posZ(), collision.multiplicity()); + } + loadEfficiency(collision.timestamp()); + + const auto multiplicity = eventMultiplicityFT0MOrFallback(collision, collision.multiplicity()); + int field = 0; + if (cfgTwoTrackCut > 0) { + field = getMagneticField(collision.timestamp()); + } + + int bin = configurableBinningDerived.getBin({collision.posZ(), multiplicity}); + registry.fill(HIST("eventcount_same"), bin); + registry.fill(HIST("trackcount_same"), bin, tracks1.size()); + + fillQA(collision, multiplicity, tracks1); + + same->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); + fillCorrelations(same, tracks1, tracks2, multiplicity, collision.posZ(), field, 1.0f); + + if (cfg.mEfficiencyAssociated || cfg.mEfficiencyTrigger) { + same->fillEvent(multiplicity, CorrelationContainer::kCFStepCorrected); + fillCorrelations(same, tracks1, tracks2, multiplicity, collision.posZ(), field, 1.0f); + } + } + + void processSameDerived(DerivedCollisions::iterator const& collision, soa::Filtered const& tracks) + { + processSameDerivedT(collision, tracks, tracks); + } + PROCESS_SWITCH(Nucleibalance, processSameDerived, "Process same event on derived data", false); + + void processSameDerivedMultSet(soa::Filtered>::iterator const& collision, soa::Filtered const& tracks) + { + processSameDerivedT(collision, tracks, tracks); + } + PROCESS_SWITCH(Nucleibalance, processSameDerivedMultSet, "Process same event on derived data with multiplicity sets", false); + + template + void processMixedDerivedT(CollType const& collisions, TrackTypes&&... tracks) + { + auto getMultiplicity = + [this](auto& col) { + (void)this; // fix compile error on unused 'this' capture + return eventMultiplicityFT0MOrFallback(col, col.multiplicity()); + }; + + using BinningTypeDerived = FlexibleBinningPolicy, aod::collision::PosZ, decltype(getMultiplicity)>; + BinningTypeDerived configurableBinningDerived{{getMultiplicity}, {axisVertex, axisMultiplicity}, true}; // true is for 'ignore overflows' (true by default). Underflows and overflows will have bin -1. + // Strictly upper categorised collisions, for cfgNoMixedEvents combinations per bin, skipping those in entry -1 + auto tracksTuple = std::make_tuple(std::forward(tracks)...); + using TA = std::tuple_element<0, decltype(tracksTuple)>::type; + using TB = std::tuple_element - 1, decltype(tracksTuple)>::type; + Pair pairs{configurableBinningDerived, cfgNoMixedEvents, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip + + for (auto it = pairs.begin(); it != pairs.end(); it++) { + auto& [collision1, tracks1, collision2, tracks2] = *it; + float multiplicity = getMultiplicity(collision1); + int bin = configurableBinningDerived.getBin(std::tuple(collision1.posZ(), multiplicity)); + float eventWeight = 1.0f / it.currentWindowNeighbours(); + int field = 0; + if (cfgTwoTrackCut > 0) { + field = getMagneticField(collision1.timestamp()); + } + + if (cfgVerbosity > 0) { + LOGF(info, "processMixedDerived: Mixed collisions bin: %d pair: [%d, %d] %d (%.3f, %.3f), %d (%.3f, %.3f)", bin, it.isNewWindow(), it.currentWindowNeighbours(), collision1.globalIndex(), collision1.posZ(), collision1.multiplicity(), collision2.globalIndex(), collision2.posZ(), collision2.multiplicity()); + } + + if (it.isNewWindow()) { + loadEfficiency(collision1.timestamp()); + mixed->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); + } + + // LOGF(info, "Tracks: %d and %d entries", tracks1.size(), tracks2.size()); + + registry.fill(HIST("eventcount_mixed"), bin); + registry.fill(HIST("trackcount_mixed"), bin, tracks1.size(), tracks2.size()); + fillCorrelations(mixed, tracks1, tracks2, multiplicity, collision1.posZ(), field, eventWeight); + + if (cfg.mEfficiencyAssociated || cfg.mEfficiencyTrigger) { + if (it.isNewWindow()) { + mixed->fillEvent(multiplicity, CorrelationContainer::kCFStepCorrected); + } + fillCorrelations(mixed, tracks1, tracks2, multiplicity, collision1.posZ(), field, eventWeight); + } + } + } + + void processMixedDerived(DerivedCollisions const& collisions, DerivedTracks const& tracks) + { + processMixedDerivedT(collisions, tracks); + } + PROCESS_SWITCH(Nucleibalance, processMixedDerived, "Process mixed events on derived data", false); + + void processMixedDerivedMultSet(soa::Filtered> const& collisions, DerivedTracks const& tracks) + { + processMixedDerivedT(collisions, tracks); + } + PROCESS_SWITCH(Nucleibalance, processMixedDerivedMultSet, "Process mixed events on derived data with multiplicity sets", false); + + // Mixed-event processing on derived data with PID via CFTrackRefs -> AO2D TracksPID + template + void processMixedDerivedPIDT(CollType const& collisions, TracksPID const& tracksAll, TrackTypes&&... tracks) + { + auto getMultiplicity = + [this](auto& col) { + (void)this; + return eventMultiplicityFT0MOrFallback(col, col.multiplicity()); + }; + + using BinningTypeDerived = FlexibleBinningPolicy, aod::collision::PosZ, decltype(getMultiplicity)>; + BinningTypeDerived configurableBinningDerived{{getMultiplicity}, {axisVertex, axisMultiplicity}, true}; + + auto tracksTuple = std::make_tuple(std::forward(tracks)...); + using TA = std::tuple_element<0, decltype(tracksTuple)>::type; + using TB = std::tuple_element - 1, decltype(tracksTuple)>::type; + Pair pairs{configurableBinningDerived, cfgNoMixedEvents, -1, collisions, tracksTuple, &cache}; + + for (auto it = pairs.begin(); it != pairs.end(); ++it) { + auto& [collision1, tracks1, collision2, tracks2] = *it; + + const float multiplicity = getMultiplicity(collision1); + const int bin = configurableBinningDerived.getBin(std::tuple(collision1.posZ(), multiplicity)); + const float eventWeight = 1.0f / it.currentWindowNeighbours(); + + if (cfgVerbosity > 0) { + LOGF(info, "processMixedDerivedPID: Mixed collisions bin: %d pair: [%d, %d] %d (%.3f, %.3f), %d (%.3f, %.3f)", + bin, it.isNewWindow(), it.currentWindowNeighbours(), + collision1.globalIndex(), collision1.posZ(), collision1.multiplicity(), + collision2.globalIndex(), collision2.posZ(), collision2.multiplicity()); + } + + if (it.isNewWindow()) { + loadEfficiency(collision1.timestamp()); + mixed->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); + } + + registry.fill(HIST("eventcount_mixed"), bin); + registry.fill(HIST("trackcount_mixed"), bin, tracks1.size(), tracks2.size()); + + std::vector triggerTracks; + std::vector associatedTracks; + triggerTracks.reserve(tracks1.size()); + associatedTracks.reserve(tracks2.size()); + + // Triggers from collision1 + for (auto const& cftrk : tracks1) { + const auto trk = trackAt(tracksAll, cftrk.trackId()); + if (trk.sign() == 0) { + continue; + } + if (passPIDForSpecies(trk, cfgTriggerSpecies.value)) { + if (cfgTriggerCharge.value == 0 || trk.sign() == cfgTriggerCharge.value) { + triggerTracks.push_back(SimpleTrack{cftrk.eta(), cftrk.phi(), cftrk.pt(), trk.sign()}); + } + } + } + + // Associates from collision2 + for (auto const& cftrk : tracks2) { + const auto trk = trackAt(tracksAll, cftrk.trackId()); + if (trk.sign() == 0) { + continue; + } + if (passPIDForSpecies(trk, cfgAssociatedSpecies.value)) { + if (cfgAssociatedCharge.value == 0 || trk.sign() == cfgAssociatedCharge.value) { + associatedTracks.push_back(SimpleTrack{cftrk.eta(), cftrk.phi(), cftrk.pt(), trk.sign()}); + } + } + } + + if (!triggerTracks.empty() && !associatedTracks.empty()) { + fillCorrelationsSimple(mixed, + CorrelationContainer::kCFStepReconstructed, + triggerTracks, + associatedTracks, + multiplicity, + collision1.posZ(), + eventWeight); + } + + if (cfg.mEfficiencyAssociated || cfg.mEfficiencyTrigger) { + if (it.isNewWindow()) { + mixed->fillEvent(multiplicity, CorrelationContainer::kCFStepCorrected); + } + if (!triggerTracks.empty() && !associatedTracks.empty()) { + fillCorrelationsSimple(mixed, + CorrelationContainer::kCFStepCorrected, + triggerTracks, + associatedTracks, + multiplicity, + collision1.posZ(), + eventWeight); + } + } + } + } + + void processMixedDerivedPID(DerivedCollisions const& collisions, + DerivedTracksWithRefs const& tracks, + TracksPID const& tracksAll) + { + processMixedDerivedPIDT(collisions, tracksAll, tracks); + } + PROCESS_SWITCH(Nucleibalance, processMixedDerivedPID, "Process mixed events on derived data with PID via CFTrackRefs", false); + + void processMixedDerivedMultSetPID(soa::Filtered> const& collisions, + DerivedTracksWithRefs const& tracks, + TracksPID const& tracksAll) + { + processMixedDerivedPIDT(collisions, tracksAll, tracks); + } + PROCESS_SWITCH(Nucleibalance, processMixedDerivedMultSetPID, "Process mixed events on derived data with multiplicity sets and PID via CFTrackRefs", false); + + int getSpecies(int pdgCode) + { + switch (pdgCode) { + case PdgPion: // pion + case -PdgPion: + return 0; + case PdgKaon: // Kaon + case -PdgKaon: + return 1; + case PdgProton: // proton + case -PdgProton: + return 2; + } + if (std::find(cfgMcTriggerPDGs->begin(), cfgMcTriggerPDGs->end(), pdgCode) != cfgMcTriggerPDGs->end()) + return 4; + else + return 3; + } + + // NOTE SmallGroups includes soa::Filtered always + Preslice perCollision = aod::cftrack::cfCollisionId; + void processMCEfficiency(soa::Filtered::iterator const& mcCollision, aod::CFMcParticles const& mcParticles, soa::SmallGroups const& collisions, aod::CFTracksWithLabel const& tracks) + { + if (cfgVerbosity > 0) { + LOGF(info, "MC collision at vtx-z = %f with %d mc particles and %d reconstructed collisions", mcCollision.posZ(), mcParticles.size(), collisions.size()); + } + + auto multiplicity = mcCollision.multiplicity(); + if (cfgCentBinsForMC > 0) { + if (collisions.size() == 0) { + return; + } + for (const auto& collision : collisions) { + multiplicity = collision.multiplicity(); + } + } + // Primaries + for (const auto& mcParticle : mcParticles) { + if (mcParticle.isPhysicalPrimary() && mcParticle.sign() != 0) { + same->getTrackHistEfficiency()->Fill(CorrelationContainer::MC, mcParticle.eta(), mcParticle.pt(), getSpecies(mcParticle.pdgCode()), multiplicity, mcCollision.posZ()); + } + } + for (const auto& collision : collisions) { + auto groupedTracks = tracks.sliceBy(perCollision, collision.globalIndex()); + if (cfgVerbosity > 0) { + LOGF(info, " Reconstructed collision at vtx-z = %f", collision.posZ()); + LOGF(info, " which has %d tracks", groupedTracks.size()); + } + + for (const auto& track : groupedTracks) { + if (track.has_cfMCParticle()) { + const auto& mcParticle = track.cfMCParticle(); + if (mcParticle.isPhysicalPrimary()) { + same->getTrackHistEfficiency()->Fill(CorrelationContainer::RecoPrimaries, mcParticle.eta(), mcParticle.pt(), getSpecies(mcParticle.pdgCode()), multiplicity, mcCollision.posZ()); + } + same->getTrackHistEfficiency()->Fill(CorrelationContainer::RecoAll, mcParticle.eta(), mcParticle.pt(), getSpecies(mcParticle.pdgCode()), multiplicity, mcCollision.posZ()); + // LOGF(info, "Filled track %d", track.globalIndex()); + } else { + // fake track + same->getTrackHistEfficiency()->Fill(CorrelationContainer::Fake, track.eta(), track.pt(), 0, multiplicity, mcCollision.posZ()); + } + } + } + } + PROCESS_SWITCH(Nucleibalance, processMCEfficiency, "MC: Extract efficiencies", false); + + template + void processMCSameDerivedT(soa::Filtered::iterator const& mcCollision, Particles1 const& mcParticles1, Particles2 const& mcParticles2, soa::SmallGroups const& collisions) + { + if (cfgVerbosity > 0) { + LOGF(info, "processMCSameDerivedT. MC collision: %d, particles1: %d, particles2: %d, collisions: %d", mcCollision.globalIndex(), mcParticles1.size(), mcParticles2.size(), collisions.size()); + } + + auto multiplicity = mcCollision.multiplicity(); + if (cfgCentBinsForMC > 0) { + if (collisions.size() == 0) { + return; + } + for (const auto& collision : collisions) { + multiplicity = collision.multiplicity(); + } + } + + same->fillEvent(multiplicity, CorrelationContainer::kCFStepAll); + fillCorrelations(same, mcParticles1, mcParticles2, multiplicity, mcCollision.posZ(), 0, 1.0f); + + if (collisions.size() == 0) { + return; + } + + same->fillEvent(multiplicity, CorrelationContainer::kCFStepVertex); + fillCorrelations(same, mcParticles1, mcParticles2, multiplicity, mcCollision.posZ(), 0, 1.0f); + + same->fillEvent(multiplicity, CorrelationContainer::kCFStepTrackedOnlyPrim); + fillCorrelations(same, mcParticles1, mcParticles2, multiplicity, mcCollision.posZ(), 0, 1.0f); + + same->fillEvent(multiplicity, CorrelationContainer::kCFStepTracked); + fillCorrelations(same, mcParticles1, mcParticles2, multiplicity, mcCollision.posZ(), 0, 1.0f); + + // NOTE kCFStepReconstructed and kCFStepCorrected are filled in processSameDerived + // This also means that if a MC collision had several reconstructed vertices (collisions), all of them are filled + } + + // NOTE SmallGroups includes soa::Filtered always + void processMCSameDerived(soa::Filtered::iterator const& mcCollision, soa::Filtered const& mcParticles, soa::SmallGroups const& collisions) // TODO. For mixed no need to check the daughters since the events are different + { + processMCSameDerivedT(mcCollision, mcParticles, mcParticles, collisions); + } + PROCESS_SWITCH(Nucleibalance, processMCSameDerived, "Process MC same event on derived data", false); + + PresliceUnsorted collisionPerMCCollision = aod::cfcollision::cfMcCollisionId; + template + void processMCMixedDerivedT(soa::Filtered const& mcCollisions, soa::Filtered const& collisions, ParticleTypes&&... particles) + { + bool useMCMultiplicity = (cfgCentBinsForMC == 0); + auto getMultiplicity = + [&collisions, &useMCMultiplicity, this](auto& col) { + if (useMCMultiplicity) + return col.multiplicity(); + auto groupedCollisions = collisions.sliceBy(collisionPerMCCollision, col.globalIndex()); + if (groupedCollisions.size() == 0) + return -1.0f; + return groupedCollisions.begin().multiplicity(); + }; + + using BinningTypeMCDerived = FlexibleBinningPolicy, aod::mccollision::PosZ, decltype(getMultiplicity)>; + BinningTypeMCDerived configurableBinning{{getMultiplicity}, {axisVertex, axisMultiplicity}, true}; + + // Strictly upper categorised collisions, for cfgNoMixedEvents combinations per bin, skipping those in entry -1 + auto tuple = std::make_tuple(std::forward(particles)...); + using TA = std::tuple_element<0, decltype(tuple)>::type; + using TB = std::tuple_element - 1, decltype(tuple)>::type; + Pair, TA, TB, BinningTypeMCDerived> pairs{configurableBinning, cfgNoMixedEvents, -1, mcCollisions, tuple, &cache}; // -1 is the number of the bin to skip + + for (auto it = pairs.begin(); it != pairs.end(); it++) { + auto& [collision1, tracks1, collision2, tracks2] = *it; + float eventWeight = 1.0f / it.currentWindowNeighbours(); + + float multiplicity = getMultiplicity(collision1); + if (cfgVerbosity > 0) { + int bin = configurableBinning.getBin(std::tuple(collision1.posZ(), multiplicity)); + LOGF(info, "processMCMixedDerived: Mixed collisions bin: %d pair: [%d, %d] %d (%.3f, %.3f), %d (%.3f, %.3f)", bin, it.isNewWindow(), it.currentWindowNeighbours(), collision1.globalIndex(), collision1.posZ(), getMultiplicity(collision1), collision2.globalIndex(), collision2.posZ(), getMultiplicity(collision2)); + } + + // STEP 0 + if (it.isNewWindow()) { + mixed->fillEvent(multiplicity, CorrelationContainer::kCFStepAll); + } + fillCorrelations(mixed, tracks1, tracks2, multiplicity, collision1.posZ(), 0, eventWeight); + // check if collision1 has at least one reconstructed collision + auto groupedCollisions = collisions.sliceBy(collisionPerMCCollision, collision1.globalIndex()); + if (cfgVerbosity > 0) { + LOGF(info, "Found %d related collisions", groupedCollisions.size()); + } + if (groupedCollisions.size() == 0) { + continue; + } + + // STEP 2, 4, 5 + if (it.isNewWindow()) { + mixed->fillEvent(multiplicity, CorrelationContainer::kCFStepVertex); + mixed->fillEvent(multiplicity, CorrelationContainer::kCFStepTrackedOnlyPrim); + mixed->fillEvent(multiplicity, CorrelationContainer::kCFStepTracked); + } + fillCorrelations(mixed, tracks1, tracks2, multiplicity, collision1.posZ(), 0, eventWeight); + fillCorrelations(mixed, tracks1, tracks2, multiplicity, collision1.posZ(), 0, eventWeight); + fillCorrelations(mixed, tracks1, tracks2, multiplicity, collision1.posZ(), 0, eventWeight); + + // NOTE kCFStepReconstructed and kCFStepCorrected are filled in processMixedDerived + // This also means that if a MC collision had several reconstructed vertices (collisions), all of them are filled + } + } + + void processMCMixedDerived(soa::Filtered const& mcCollisions, soa::Filtered const& mcParticles, soa::Filtered const& collisions) + { + processMCMixedDerivedT(mcCollisions, collisions, mcParticles); + } + PROCESS_SWITCH(Nucleibalance, processMCMixedDerived, "Process MC mixed events on derived data", false); +}; + +// Lambda* proxy analysis task based on deuteron proxy +struct Lambdastarproxy { + // ---- Ion/nucleus PDG encoding helpers (10LZZZAAAI) ---- + // Note: these are *format* constants (not particle PDG species codes) + static constexpr int IonCodeThreshold = 1000000000; // 10^9 + static constexpr int IonZDivisor = 10000; + static constexpr int IonZModulo = 1000; + // ---- Common PDG codes (use named values; avoid explicit literals) ---- + static constexpr int PdgElectron = static_cast(PDG_t::kElectron); + static constexpr int PdgMuon = static_cast(PDG_t::kMuonMinus); + static constexpr int PdgPion = static_cast(PDG_t::kPiPlus); + static constexpr int PdgKaon = static_cast(PDG_t::kKPlus); + static constexpr int PdgProton = static_cast(PDG_t::kProton); + // ---- Named defaults to avoid magic numbers (o2-linter) ---- + static constexpr float CutVertexDefault = 10.f; + static constexpr float CutPtMinDefault = 0.5f; + static constexpr float CutEtaMaxDefault = 0.8f; + + static constexpr float CutMCPtMinDefault = 0.1f; + static constexpr float CutMCEtaMaxDefault = 0.8f; + static constexpr int FillMCTruthDefault = 1; + + static constexpr float NsigmaTPCDefault = 3.f; + static constexpr float NsigmaTOFDefault = 3.f; + + static constexpr bool RequireGlobalTrackDefault = true; + static constexpr int TPCNClsMinDefault = 70; + static constexpr float DcaXYMaxDefault = 0.1f; + static constexpr float DcaZMaxDefault = 0.2f; + static constexpr float Chi2PerTPCClusterDefault = 2.5f; + static constexpr float Chi2PerITSClusterDefault = 36.f; + static constexpr int ITSNClustersDefault = 5; + + static constexpr int TriggerDefault = 4; + // Named trigger codes + static constexpr int TriggerNone = 0; + static constexpr int TriggerSel8 = 1; + static constexpr int TriggerSel8Quality = 2; + static constexpr int TriggerSel8OccQuality = 3; + static constexpr int TriggerSel8NoSbpZvtx = 4; + static constexpr int MinOccDefault = 0; + static constexpr int MaxOccDefault = 3000; + + static constexpr int NoMixedEventsDefault = 5; + static constexpr float MixZvtxMaxDefault = 2.0f; + static constexpr float MixMultMaxDefault = 50.0f; + + static constexpr float ProxyMomentumScale = 0.5f; + static constexpr float TofBetaMin = 0.01f; + static constexpr float TofBetaMax = 1.2f; + static constexpr double Half = 0.5; + // Basic configuration for event and track selection + Configurable lstarCutVertex{"lstarCutVertex", float{CutVertexDefault}, "Accepted z-vertex range (cm)"}; + Configurable lstarCutPtMin{"lstarCutPtMin", float{CutPtMinDefault}, "Minimal pT for tracks (GeV/c)"}; + Configurable lstarCutEtaMax{"lstarCutEtaMax", float{CutEtaMaxDefault}, "Max |eta| for tracks"}; + + // MC truth + Configurable lstarCutMCPtMin{"lstarCutMCPtMin", float{CutMCPtMinDefault}, "Minimal pT for MC particles (GeV/c)"}; + Configurable lstarCutMCEtaMax{"lstarCutMCEtaMax", float{CutMCEtaMaxDefault}, "Max |eta| for MC particles"}; + Configurable lstarFillMCTruth{"lstarFillMCTruth", int{FillMCTruthDefault}, "Fill MC truth and reco-matching QA (AO2D-MC mode)"}; + + // PID cuts + Configurable lstarCutNsigmaTPCPi{"lstarCutNsigmaTPCPi", float{NsigmaTPCDefault}, "|nSigma^{TPC}_{#pi}| cut"}; + Configurable lstarCutNsigmaTOFPi{"lstarCutNsigmaTOFPi", float{NsigmaTOFDefault}, "|nSigma^{TOF}_{#pi}| cut"}; + Configurable lstarCutNsigmaTPCPr{"lstarCutNsigmaTPCPr", float{NsigmaTPCDefault}, "|nSigma^{TPC}_{p}| cut"}; + Configurable lstarCutNsigmaTOFPr{"lstarCutNsigmaTOFPr", float{NsigmaTOFDefault}, "|nSigma^{TOF}_{p}| cut"}; + Configurable lstarCutNsigmaTPCKaon{"lstarCutNsigmaTPCKaon", float{NsigmaTPCDefault}, "|nSigma^{TPC}_{K}| cut"}; + Configurable lstarCutNsigmaTOFKaon{"lstarCutNsigmaTOFKaon", float{NsigmaTOFDefault}, "|nSigma^{TOF}_{K}| cut"}; + Configurable lstarCutNsigmaTPCDe{"lstarCutNsigmaTPCDe", float{NsigmaTPCDefault}, "|nSigma^{TPC}_{d}| cut"}; + Configurable lstarCutNsigmaTOFDe{"lstarCutNsigmaTOFDe", float{NsigmaTOFDefault}, "|nSigma^{TOF}_{d}| cut"}; + + // Track quality + Configurable lstarRequireGlobalTrack{"lstarRequireGlobalTrack", bool{RequireGlobalTrackDefault}, "Require global tracks (default)"}; + Configurable lstarTPCNClsMin{"lstarTPCNClsMin", int{TPCNClsMinDefault}, "Minimum number of TPC clusters (tpcNClsFound)"}; + Configurable lstarDcaXYMax{"lstarDcaXYMax", float{DcaXYMaxDefault}, "Max |DCA_{xy}| to PV (cm)"}; + Configurable lstarDcaZMax{"lstarDcaZMax", float{DcaZMaxDefault}, "Max |DCA_{z}| to PV (cm)"}; + Configurable lstarChi2PerTPCCluster{"lstarChi2PerTPCCluster", float{Chi2PerTPCClusterDefault}, "Maximum Chi2/cluster for the TPC track segment"}; + Configurable lstarChi2PerITSCluster{"lstarChi2PerITSCluster", float{Chi2PerITSClusterDefault}, "Maximum Chi2/cluster for the ITS track segment"}; + Configurable lstarITSNClusters{"lstarITSNClusters", int{ITSNClustersDefault}, "Minimum number of ITS clusters"}; + + // Trigger + occupancy + Configurable lstarCfgTrigger{"lstarCfgTrigger", int{TriggerDefault}, "Event trigger selection: 0=none, 1=sel8, 2=sel8+(kNoSameBunchPileup+kIsGoodZvtxFT0vsPV+kIsGoodITSLayersAll), 3=sel8+occupancy+(kNoCollInTimeRangeStandard)+(kNoSameBunchPileup+kIsGoodZvtxFT0vsPV+kIsGoodITSLayersAll), 4=sel8+(kNoSameBunchPileup+kIsGoodZvtxFT0vsPV)"}; + Configurable lstarMinOcc{"lstarMinOcc", int{MinOccDefault}, "minimum occupancy selection (for cfgTrigger==3)"}; + Configurable lstarMaxOcc{"lstarMaxOcc", int{MaxOccDefault}, "maximum occupancy selection (for cfgTrigger==3)"}; + Configurable lstarUseFT0M{"lstarUseFT0M", 1, "Use FT0M centrality (0-100) as multiplicity axis (1=ON, 0=use Ntracks)"}; + + // --- Mixed-event configuration for pK / proxy invariant-mass background (AO2D only) --- + Configurable lstarNoMixedEvents{"lstarNoMixedEvents", int{NoMixedEventsDefault}, "Number of previous events kept for mixed-event background"}; + Configurable lstarMixZvtxMax{"lstarMixZvtxMax", float{MixZvtxMaxDefault}, "Max |Δzvtx| (cm) for event mixing"}; + Configurable lstarMixMultMax{"lstarMixMultMax", float{MixMultMaxDefault}, "Max |Δmult| for event mixing"}; + Configurable lstarEnablePidQA{"lstarEnablePidQA", 0, "Enable PID QA histograms (dE/dx, TOF #beta, proxy invariant-mass QA, etc.): 1 = ON, 0 = OFF"}; + Configurable lstarEnableSparse{"lstarEnableSparse", 0, "Enable THnSparse invariant-mass histograms (#Lambda^{*} pK and proxy); 1 = ON, 0 = OFF"}; + + struct KaonCand { + float px, py, pz; + int charge; + int tid; + }; + struct ProxyCand { + float px, py, pz; + int charge; + int tid; + }; + + // Helpers for invariant-mass kinematics + static float phiFromPxPy(float px, float py) + { + return std::atan2(py, px); + } + + static float rapidityFromEPz(double e, double pz) + { + const double num = e + pz; + const double den = e - pz; + if (num <= 0.0 || den <= 0.0) { + return 0.f; + } + return static_cast(Half * std::log(num / den)); + } + + // Mixed-event pool entry for pK / proxy background (AO2D only) + struct LStarMixEventEntry { + float mult = 0.f; + float zvtx = 0.f; + std::vector kaons; + std::vector proxies; + }; + + // Keep last N events for event-mixing + std::deque mLStarMixEvents; + + template + bool keepCollisionAO2D(TCollision const& collision) const + { + if (lstarCfgTrigger.value == TriggerNone) { + return true; + } else if (lstarCfgTrigger.value == TriggerSel8) { + return collision.sel8(); + } else if (lstarCfgTrigger.value == TriggerSel8Quality) { + return collision.sel8() && + collision.selection_bit(aod::evsel::kNoSameBunchPileup) && + collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) && + collision.selection_bit(aod::evsel::kIsGoodITSLayersAll); + } else if (lstarCfgTrigger.value == TriggerSel8OccQuality) { + const int occupancy = collision.trackOccupancyInTimeRange(); + if (occupancy < lstarMinOcc.value || occupancy >= lstarMaxOcc.value) { + return false; + } + return collision.sel8() && + collision.selection_bit(aod::evsel::kNoSameBunchPileup) && + collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) && + collision.selection_bit(aod::evsel::kNoCollInTimeRangeStandard) && + collision.selection_bit(aod::evsel::kIsGoodITSLayersAll); + } else if (lstarCfgTrigger.value == TriggerSel8NoSbpZvtx) { + return collision.sel8() && + collision.selection_bit(aod::evsel::kNoSameBunchPileup) && + collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV); + } + + LOGF(warn, "Invalid lstarCfgTrigger=%d. Accepting all collisions.", lstarCfgTrigger.value); + return true; + } + + template + float eventMultiplicityFT0MOrFallback(TCollision const& collision, float fallback) const + { + if (lstarUseFT0M.value == 0) { + return fallback; + } + + if constexpr (requires { collision.centFT0M(); }) { + const float v = collision.centFT0M(); + if (v >= 0.f) { + return v; + } + } + + if constexpr (requires { collision.centFT0MValid(); }) { + if (collision.centFT0MValid()) { + if constexpr (requires { collision.centFT0M(); }) { + return collision.centFT0M(); + } + } + } + + return fallback; + } + + static int chargeFromPdg(int pdg) + { + const int apdg = std::abs(pdg); + + // Ions/nuclei: PDG code format 10LZZZAAAI -> Z is encoded in digits [7..5] + if (apdg >= IonCodeThreshold) { + const int z = (apdg / IonZDivisor) % IonZModulo; + return (pdg >= 0) ? z : -z; + } + + switch (apdg) { + case PdgElectron: // e + case PdgMuon: // mu + case PdgPion: // pi + case PdgKaon: // K + case PdgProton: // p + return (pdg >= 0) ? 1 : -1; + default: + return 0; + } + } + + // Histogram registry for this task + HistogramRegistry histos{"lstarRegistry"}; + + // Filters + Filter collisionZVtxFilter = nabs(aod::collision::posZ) < lstarCutVertex; + Filter trackFilter = (nabs(aod::track::eta) < lstarCutEtaMax) && (aod::track::pt > lstarCutPtMin); + + // Tracks with PID information from TPC and TOF services for all relevant species + // NOTE: aod::TracksExtra is needed for TPC dE/dx (tpcSignal) + using TracksWithPID = soa::Join; + template + bool passTrackQuality(const TTrack& trk) const + { + if (lstarRequireGlobalTrack.value) { + if constexpr (requires { trk.isGlobalTrack(); }) { + if (!trk.isGlobalTrack()) { + return false; + } + } else if constexpr (requires { trk.isGlobalTrackSDD(); }) { + if (!trk.isGlobalTrackSDD()) { + return false; + } + } + } + + if constexpr (requires { trk.itsNCls(); }) { + if (lstarITSNClusters.value > 0 && trk.itsNCls() < lstarITSNClusters.value) { + return false; + } + } + + if constexpr (requires { trk.tpcNClsFound(); }) { + if (lstarTPCNClsMin.value > 0 && trk.tpcNClsFound() < lstarTPCNClsMin.value) { + return false; + } + } + + if constexpr (requires { trk.tpcChi2NCl(); }) { + if (lstarChi2PerTPCCluster.value > 0.f && trk.tpcChi2NCl() > lstarChi2PerTPCCluster.value) { + return false; + } + } + + if constexpr (requires { trk.itsChi2NCl(); }) { + if (lstarChi2PerITSCluster.value > 0.f && trk.itsChi2NCl() > lstarChi2PerITSCluster.value) { + return false; + } + } + + if constexpr (requires { trk.dcaXY(); }) { + if (lstarDcaXYMax.value > 0.f && std::abs(trk.dcaXY()) > lstarDcaXYMax.value) { + return false; + } + } + + if constexpr (requires { trk.dcaZ(); }) { + if (lstarDcaZMax.value > 0.f && std::abs(trk.dcaZ()) > lstarDcaZMax.value) { + return false; + } + } + + return true; + } + using CollisionsWithEvSel = soa::Join; + using FilteredCollisions = soa::Filtered; + using FilteredTracks = soa::Filtered; + + // AO2D-MC variants (for truth QA and reco->MC matching) + using CollisionsWithEvSelMC = soa::Join; + using FilteredCollisionsMC = soa::Filtered; + + using TracksWithPIDMC = soa::Join; + using FilteredTracksMC = soa::Filtered; + + Preslice mcParticlesPerCollision = aod::mcparticle::mcCollisionId; + + void init(o2::framework::InitContext&) + { + AxisSpec massAxis{200, 1.4, 1.9, "M_{pK} (GeV/c^{2})"}; + AxisSpec ptAxis{100, 0., 10., "p_{T} (GeV/c)"}; + AxisSpec nsAxis{100, -10., 10., "n#sigma"}; + AxisSpec pAxis{100, 0., 10., "p (GeV/c)"}; + AxisSpec etaAxis{80, -2., 2., "#eta"}; + AxisSpec phiAxis{64, 0., o2::constants::math::TwoPI, "#varphi"}; + AxisSpec centAxis{100, 0., 100., "multiplicity/centrality"}; + + AxisSpec pdgAxis{10001, -5000.5, 5000.5, "PDG code"}; + + AxisSpec dEdxAxis{400, 0., 200., "TPC dE/dx (arb. units)"}; + AxisSpec betaAxis{160, 0., 1.6, "#beta_{TOF}"}; + + // Invariant-mass spectra + histos.add("hInvMassPKUnlike", + "pK invariant mass (unlike-sign);M_{pK} (GeV/c^{2});Counts", + HistType::kTH1F, {massAxis}); + histos.add("hInvMassPKLike", + "pK invariant mass (like-sign);M_{pK} (GeV/c^{2});Counts", + HistType::kTH1F, {massAxis}); + + // Invariant-mass vs pair pT (use p_{T} of pK system) + histos.add("hInvMassPKUnlikeVsPt", + "pK invariant mass vs p_{T} (unlike-sign);M_{pK} (GeV/c^{2});p_{T}^{pK} (GeV/c);Counts", + HistType::kTH2F, {massAxis, ptAxis}); + histos.add("hInvMassPKLikeVsPt", + "pK invariant mass vs p_{T} (like-sign);M_{pK} (GeV/c^{2});p_{T}^{pK} (GeV/c);Counts", + HistType::kTH2F, {massAxis, ptAxis}); + + // THnSparse for invariant-mass analysis (mass, pT, y, phi) + if (lstarEnableSparse.value != 0) { + histos.add("hLambdaStarPKUnlikeSparse", + "#Lambda^{*}(1520) pK unlike-sign candidates;M_{pK} (GeV/c^{2});p_{T}^{pK} (GeV/c);y_{pK};#varphi_{pK}", + HistType::kTHnSparseF, + {AxisSpec{400, 1.3, 1.9, "M_{pK} (GeV/c^{2})"}, + AxisSpec{100, 0., 10., "p_{T}^{pK} (GeV/c)"}, + AxisSpec{60, -1.5, 1.5, "y_{pK}"}, + AxisSpec{64, -3.2, 3.2, "#varphi_{pK}"}, centAxis}); + + histos.add("hLambdaStarPKLikeSparse", + "#Lambda^{*}(1520) pK like-sign candidates;M_{pK} (GeV/c^{2});p_{T}^{pK} (GeV/c);y_{pK};#varphi_{pK}", + HistType::kTHnSparseF, + {AxisSpec{400, 1.3, 1.9, "M_{pK} (GeV/c^{2})"}, + AxisSpec{100, 0., 10., "p_{T}^{pK} (GeV/c)"}, + AxisSpec{60, -1.5, 1.5, "y_{pK}"}, + AxisSpec{64, -3.2, 3.2, "#varphi_{pK}"}, centAxis}); + + histos.add("hLambdaStarPKMixedSparse", + "#Lambda^{*}(1520) pK mixed-event candidates;M_{pK} (GeV/c^{2});p_{T}^{pK} (GeV/c);y_{pK};#varphi_{pK}", + HistType::kTHnSparseF, + {AxisSpec{400, 1.3, 1.9, "M_{pK} (GeV/c^{2})"}, + AxisSpec{100, 0., 10., "p_{T}^{pK} (GeV/c)"}, + AxisSpec{60, -1.5, 1.5, "y_{pK}"}, + AxisSpec{64, -3.2, 3.2, "#varphi_{pK}"}, centAxis}); + + // THnSparse for deuteron-proxy invariant-mass analysis (mass, pT, y, phi) + histos.add("hLambdaStarProxySparse", + "#Lambda^{*}(1520) deuteron-proxy candidates;M_{p_{proxy}K} (GeV/c^{2});p_{T}^{p_{proxy}K} (GeV/c);y_{p_{proxy}K};#varphi_{p_{proxy}K}", + HistType::kTHnSparseF, + {AxisSpec{400, 1.3, 1.9, "M_{p_{proxy}K} (GeV/c^{2})"}, + AxisSpec{100, 0., 10., "p_{T}^{p_{proxy}K} (GeV/c)"}, + AxisSpec{60, -1.5, 1.5, "y_{p_{proxy}K}"}, + AxisSpec{64, -3.2, 3.2, "#varphi_{p_{proxy}K}"}, centAxis}); + + histos.add("hLambdaStarProxyMixedSparse", + "#Lambda^{*}(1520) deuteron-proxy mixed-event candidates;M_{p_{proxy}K} (GeV/c^{2});p_{T}^{p_{proxy}K} (GeV/c);y_{p_{proxy}K};#varphi_{p_{proxy}K}", + HistType::kTHnSparseF, + {AxisSpec{400, 1.3, 1.9, "M_{p_{proxy}K} (GeV/c^{2})"}, + AxisSpec{100, 0., 10., "p_{T}^{p_{proxy}K} (GeV/c)"}, + AxisSpec{60, -1.5, 1.5, "y_{p_{proxy}K}"}, + AxisSpec{64, -3.2, 3.2, "#varphi_{p_{proxy}K}"}, centAxis}); + } + + // Deuteron-proxy invariant mass (p_{proxy} from d/2 combined with K) + histos.add("hDeuteronProxyMass", + "#Lambda^{*} proxy invariant mass from (d/2 + K);M_{pK} (GeV/c^{2});Counts", + HistType::kTH1F, {massAxis}); + + // TPC dE/dx vs total momentum + histos.add("hTPCdEdxVsP", + "TPC dE/dx vs p;p (GeV/c);dE/dx (arb. units);Counts", + HistType::kTH2F, {pAxis, dEdxAxis}); + + // TOF #beta vs total momentum + histos.add("hTOFBetaVsP", + "TOF #beta vs p;p (GeV/c);#beta_{TOF};Counts", + HistType::kTH2F, {pAxis, betaAxis}); + + // --- Per-species PID QA (tagged) --- + histos.add("hTPCdEdxVsP_Pi", + "TPC dE/dx vs p (tagged #pi);p (GeV/c);dE/dx (arb. units);Counts", + HistType::kTH2F, {pAxis, dEdxAxis}); + histos.add("hTPCdEdxVsP_K", + "TPC dE/dx vs p (tagged K);p (GeV/c);dE/dx (arb. units);Counts", + HistType::kTH2F, {pAxis, dEdxAxis}); + histos.add("hTPCdEdxVsP_P", + "TPC dE/dx vs p (tagged p);p (GeV/c);dE/dx (arb. units);Counts", + HistType::kTH2F, {pAxis, dEdxAxis}); + histos.add("hTPCdEdxVsP_D", + "TPC dE/dx vs p (tagged d);p (GeV/c);dE/dx (arb. units);Counts", + HistType::kTH2F, {pAxis, dEdxAxis}); + + histos.add("hTOFBetaVsP_Pi", + "TOF #beta vs p (tagged #pi);p (GeV/c);#beta_{TOF};Counts", + HistType::kTH2F, {pAxis, betaAxis}); + histos.add("hTOFBetaVsP_K", + "TOF #beta vs p (tagged K);p (GeV/c);#beta_{TOF};Counts", + HistType::kTH2F, {pAxis, betaAxis}); + histos.add("hTOFBetaVsP_P", + "TOF #beta vs p (tagged p);p (GeV/c);#beta_{TOF};Counts", + HistType::kTH2F, {pAxis, betaAxis}); + histos.add("hTOFBetaVsP_D", + "TOF #beta vs p (tagged d);p (GeV/c);#beta_{TOF};Counts", + HistType::kTH2F, {pAxis, betaAxis}); + + // --- MC QA (AO2D-MC mode) --- + histos.add("hMcPrimariesPtEta", + "MC charged physical primaries; p_{T} (GeV/c); #eta; Counts", + HistType::kTH2F, {ptAxis, etaAxis}); + + histos.add("hRecoMatchedPdg", + "Reco tracks matched to MC (PDG); PDG code; Counts", + HistType::kTH1F, {pdgAxis}); + + histos.add("hRecoFakePtEta", + "Reco tracks without MC label (fakes / unmatched); p_{T} (GeV/c); #eta; Counts", + HistType::kTH2F, {ptAxis, etaAxis}); + + // Deuteron-proxy kinematics and PID QA + histos.add("hDeuteronProxyPt", + "Deuteron proxy p_{T};p_{T} (GeV/c);Counts", + HistType::kTH1F, {ptAxis}); + histos.add("hDeuteronProxyEta", + "Deuteron proxy #eta;#eta;Counts", + HistType::kTH1F, {etaAxis}); + histos.add("hDeuteronProxyPhi", + "Deuteron proxy #varphi;#varphi;Counts", + HistType::kTH1F, {phiAxis}); + + histos.add("hNsigmaTPCDeuteron", + "TPC n#sigma_{d};n#sigma^{TPC}_{d};Counts", + HistType::kTH1F, {nsAxis}); + histos.add("hNsigmaTOFDeuteron", + "TOF n#sigma_{d};n#sigma^{TOF}_{d};Counts", + HistType::kTH1F, {nsAxis}); + + histos.add("hNsigmaTPCDeuteronVsP", + "TPC n#sigma_{d} vs p; p (GeV/c); n#sigma^{TPC}_{d};Counts", + HistType::kTH2F, {pAxis, nsAxis}); + histos.add("hNsigmaTOFDeuteronVsP", + "TOF n#sigma_{d} vs p; p (GeV/c); n#sigma^{TOF}_{d};Counts", + HistType::kTH2F, {pAxis, nsAxis}); + + // Kaon kinematics and PID QA + histos.add("hKaonPt", + "Kaon p_{T};p_{T} (GeV/c);Counts", + HistType::kTH1F, {ptAxis}); + histos.add("hKaonEta", + "Kaon #eta;#eta;Counts", + HistType::kTH1F, {etaAxis}); + histos.add("hKaonPhi", + "Kaon #varphi;#varphi;Counts", + HistType::kTH1F, {phiAxis}); + + histos.add("hNsigmaTPCKaon", + "TPC n#sigma_{K};n#sigma^{TPC}_{K};Counts", + HistType::kTH1F, {nsAxis}); + histos.add("hNsigmaTOFKaon", + "TOF n#sigma_{K};n#sigma^{TOF}_{K};Counts", + HistType::kTH1F, {nsAxis}); + + histos.add("hNsigmaTPCKaonVsP", + "TPC n#sigma_{K} vs p; p (GeV/c); n#sigma^{TPC}_{K};Counts", + HistType::kTH2F, {pAxis, nsAxis}); + histos.add("hNsigmaTOFKaonVsP", + "TOF n#sigma_{K} vs p; p (GeV/c); n#sigma^{TOF}_{K};Counts", + HistType::kTH2F, {pAxis, nsAxis}); + } + + // AO2D-MC QA: truth primaries + reco-to-MC matching sanity plots + void processMCQA(FilteredCollisionsMC::iterator const& collision, + FilteredTracksMC const& tracks, + aod::McParticles const& mcParticles) + { + if (lstarFillMCTruth.value == 0) { + return; + } + + // Same basic event selection as AO2D reco + if (!keepCollisionAO2D(collision)) { + return; + } + if (std::abs(collision.posZ()) > lstarCutVertex.value) { + return; + } + + // Require a linked MC collision + if constexpr (requires { collision.has_mcCollision(); }) { + if (!collision.has_mcCollision()) { + return; + } + } + + int mcCollIdx = -1; + if constexpr (requires { collision.mcCollisionId(); }) { + mcCollIdx = collision.mcCollisionId(); + } else if constexpr (requires { collision.mcCollision().globalIndex(); }) { + mcCollIdx = collision.mcCollision().globalIndex(); + } + if (mcCollIdx < 0) { + return; + } + + // --- Truth QA: charged physical primaries --- + auto truth = mcParticles.sliceBy(mcParticlesPerCollision, mcCollIdx); + for (auto const& mcPart : truth) { + if (!mcPart.isPhysicalPrimary()) { + continue; + } + if (mcPart.pt() < lstarCutMCPtMin.value || std::abs(mcPart.eta()) > lstarCutMCEtaMax.value) { + continue; + } + if (chargeFromPdg(mcPart.pdgCode()) == 0) { + continue; + } + histos.fill(HIST("hMcPrimariesPtEta"), mcPart.pt(), mcPart.eta()); + } + + // --- Reco->MC matching QA --- + const auto collIdx = collision.globalIndex(); + for (auto const& trk : tracks) { + if (trk.collisionId() != collIdx) { + continue; + } + if (!passTrackQuality(trk)) { + continue; + } + + if constexpr (requires { trk.has_mcParticle(); trk.mcParticle(); }) { + if (trk.has_mcParticle()) { + const auto mcPart = trk.mcParticle(); + histos.fill(HIST("hRecoMatchedPdg"), mcPart.pdgCode()); + } else { + histos.fill(HIST("hRecoFakePtEta"), trk.pt(), trk.eta()); + } + } + } + } + + PROCESS_SWITCH(Lambdastarproxy, processMCQA, + "AO2D-MC: fill truth and reco-matching QA histograms", false); + + // Helper: fill TPC dE/dx vs total momentum if TPC signal is available + template + void fillTPCdEdxVsPIfAvailable(const TTrack& trk) + { + if (lstarEnablePidQA.value == 0) { + return; + } + // aod::TracksExtra provides tpcSignal(); keep the constexpr-guard for robustness + if constexpr (requires { trk.tpcSignal(); }) { + const float p = trk.p(); + histos.fill(HIST("hTPCdEdxVsP"), p, trk.tpcSignal()); + } + } + + // Helper: fill TOF beta vs total momentum if beta is available (and looks valid) + template + void fillTOFBetaVsPIfAvailable(const TTrack& trk) + { + if (lstarEnablePidQA.value == 0) { + return; + } + if constexpr (requires { trk.beta(); }) { + bool hasTof = true; + if constexpr (requires { trk.hasTOF(); }) { + hasTof = trk.hasTOF(); + } + const float beta = trk.beta(); + // Guard against default/invalid values for tracks without TOF match + if (hasTof && beta > TofBetaMin && beta < TofBetaMax) { + histos.fill(HIST("hTOFBetaVsP"), trk.p(), beta); + } + } + } + + // --- Per-species PID QA helpers --- + template + static bool hasTOFMatch(const TTrack& trk) + { + if constexpr (requires { trk.hasTOF(); }) { + return trk.hasTOF(); + } + return true; // fallback: if column not present, assume available + } + + // Return: 0=#pi, 1=K, 2=p, 3=d, -1=unclassified + template + int classifyPidSpecies(const TTrack& trk) + { + const bool hasTof = hasTOFMatch(trk); + + auto score = [hasTof](float nsTPC, float nsTOF) { + return std::abs(nsTPC) + (hasTof ? std::abs(nsTOF) : 0.f); + }; + + float bestScore = 1e9f; + int best = -1; + + // pion + { + const float nsTPC = trk.tpcNSigmaPi(); + const float nsTOF = trk.tofNSigmaPi(); + const bool pass = (std::abs(nsTPC) < lstarCutNsigmaTPCPi.value) && (!hasTof || (std::abs(nsTOF) < lstarCutNsigmaTOFPi.value)); + if (pass) { + const float sc = score(nsTPC, nsTOF); + if (sc < bestScore) { + bestScore = sc; + best = 0; + } + } + } + + // kaon + { + const float nsTPC = trk.tpcNSigmaKa(); + const float nsTOF = trk.tofNSigmaKa(); + const bool pass = (std::abs(nsTPC) < lstarCutNsigmaTPCKaon.value) && (!hasTof || (std::abs(nsTOF) < lstarCutNsigmaTOFKaon.value)); + if (pass) { + const float sc = score(nsTPC, nsTOF); + if (sc < bestScore) { + bestScore = sc; + best = 1; + } + } + } + + // proton + { + const float nsTPC = trk.tpcNSigmaPr(); + const float nsTOF = trk.tofNSigmaPr(); + const bool pass = (std::abs(nsTPC) < lstarCutNsigmaTPCPr.value) && (!hasTof || (std::abs(nsTOF) < lstarCutNsigmaTOFPr.value)); + if (pass) { + const float sc = score(nsTPC, nsTOF); + if (sc < bestScore) { + bestScore = sc; + best = 2; + } + } + } + + // deuteron + { + const float nsTPC = trk.tpcNSigmaDe(); + const float nsTOF = trk.tofNSigmaDe(); + const bool pass = (std::abs(nsTPC) < lstarCutNsigmaTPCDe.value) && (!hasTof || (std::abs(nsTOF) < lstarCutNsigmaTOFDe.value)); + if (pass) { + const float sc = score(nsTPC, nsTOF); + if (sc < bestScore) { + bestScore = sc; + best = 3; + } + } + } + + return best; + } + + // Helper to compute invariant mass from two 3-momenta and masses + static double invariantMass(float px1, float py1, float pz1, double m1, + float px2, float py2, float pz2, double m2) + { + const double e1 = std::sqrt(m1 * m1 + px1 * px1 + py1 * py1 + pz1 * pz1); + const double e2 = std::sqrt(m2 * m2 + px2 * px2 + py2 * py2 + pz2 * pz2); + const double ex = px1 + px2; + const double ey = py1 + py2; + const double ez = pz1 + pz2; + const double eTot = e1 + e2; + const double p2Tot = ex * ex + ey * ey + ez * ez; + const double m2Tot = eTot * eTot - p2Tot; + return m2Tot > 0. ? std::sqrt(m2Tot) : 0.; + } + + void process(FilteredCollisions::iterator const& collision, FilteredTracks const& tracks) + { + // Event selection (cfgTrigger) -- AO2D only + if (!keepCollisionAO2D(collision)) { + return; + } + // physics masses (GeV/c^2) + constexpr double MassProton = o2::constants::physics::MassProton; + constexpr double MassKaonCharged = o2::constants::physics::MassKaonCharged; + + // --- Inclusive PID QA: keep #pi/K/p/d bands in TPC dE/dx and TOF beta plots --- + if (lstarEnablePidQA.value != 0) { + for (auto const& trk : tracks) { + if (trk.pt() < lstarCutPtMin.value || std::abs(trk.eta()) > lstarCutEtaMax.value) { + continue; + } + if (!passTrackQuality(trk)) { + continue; + } + if (trk.sign() == 0) { + continue; + } + // Inclusive PID QA + fillTPCdEdxVsPIfAvailable(trk); + fillTOFBetaVsPIfAvailable(trk); + + // Per-species PID-QA (tagged) histograms + const int sp = classifyPidSpecies(trk); + switch (sp) { + case 0: { // pion + if constexpr (requires { trk.tpcSignal(); }) { + histos.fill(HIST("hTPCdEdxVsP_Pi"), trk.p(), trk.tpcSignal()); + } + if constexpr (requires { trk.beta(); }) { + const bool hasTof = hasTOFMatch(trk); + const float beta = trk.beta(); + if (hasTof && beta > TofBetaMin && beta < TofBetaMax) { + histos.fill(HIST("hTOFBetaVsP_Pi"), trk.p(), beta); + } + } + break; + } + + case 1: { // kaon + if constexpr (requires { trk.tpcSignal(); }) { + histos.fill(HIST("hTPCdEdxVsP_K"), trk.p(), trk.tpcSignal()); + } + if constexpr (requires { trk.beta(); }) { + const bool hasTof = hasTOFMatch(trk); + const float beta = trk.beta(); + if (hasTof && beta > TofBetaMin && beta < TofBetaMax) { + histos.fill(HIST("hTOFBetaVsP_K"), trk.p(), beta); + } + } + break; + } + + case 2: { // proton + if constexpr (requires { trk.tpcSignal(); }) { + histos.fill(HIST("hTPCdEdxVsP_P"), trk.p(), trk.tpcSignal()); + } + if constexpr (requires { trk.beta(); }) { + const bool hasTof = hasTOFMatch(trk); + const float beta = trk.beta(); + if (hasTof && beta > TofBetaMin && beta < TofBetaMax) { + histos.fill(HIST("hTOFBetaVsP_P"), trk.p(), beta); + } + } + break; + } + + case 3: { // deuteron + if constexpr (requires { trk.tpcSignal(); }) { + histos.fill(HIST("hTPCdEdxVsP_D"), trk.p(), trk.tpcSignal()); + } + if constexpr (requires { trk.beta(); }) { + const bool hasTof = hasTOFMatch(trk); + const float beta = trk.beta(); + if (hasTof && beta > TofBetaMin && beta < TofBetaMax) { + histos.fill(HIST("hTOFBetaVsP_D"), trk.p(), beta); + } + } + break; + } + + default: + break; + } + } + } + + std::vector kaonCands; + std::vector proxyCands; + kaonCands.reserve(128); + proxyCands.reserve(32); + + float eventMultFallback = 0.f; // fallback mixing variable: number of selected charged tracks (after quality cuts) + + // Inclusive PID QA loop: count all selected charged tracks for fallback multiplicity + for (auto const& trk : tracks) { + if (trk.pt() < lstarCutPtMin.value || std::abs(trk.eta()) > lstarCutEtaMax.value) { + continue; + } + if (!passTrackQuality(trk)) { + continue; + } + if (trk.sign() == 0) { + continue; + } + eventMultFallback += 1.f; + if (lstarEnablePidQA.value == 0) { + continue; + } + // Inclusive PID QA + fillTPCdEdxVsPIfAvailable(trk); + fillTOFBetaVsPIfAvailable(trk); + + // Per-species PID-QA (tagged) histograms + const int sp = classifyPidSpecies(trk); + switch (sp) { + case 0: { // pion + if constexpr (requires { trk.tpcSignal(); }) { + histos.fill(HIST("hTPCdEdxVsP_Pi"), trk.p(), trk.tpcSignal()); + } + if constexpr (requires { trk.beta(); }) { + const bool hasTof = hasTOFMatch(trk); + const float beta = trk.beta(); + if (hasTof && beta > TofBetaMin && beta < TofBetaMax) { + histos.fill(HIST("hTOFBetaVsP_Pi"), trk.p(), beta); + } + } + break; + } + case 1: { // kaon + if constexpr (requires { trk.tpcSignal(); }) { + histos.fill(HIST("hTPCdEdxVsP_K"), trk.p(), trk.tpcSignal()); + } + if constexpr (requires { trk.beta(); }) { + const bool hasTof = hasTOFMatch(trk); + const float beta = trk.beta(); + if (hasTof && beta > TofBetaMin && beta < TofBetaMax) { + histos.fill(HIST("hTOFBetaVsP_K"), trk.p(), beta); + } + } + break; + } + case 2: { // proton + if constexpr (requires { trk.tpcSignal(); }) { + histos.fill(HIST("hTPCdEdxVsP_P"), trk.p(), trk.tpcSignal()); + } + if constexpr (requires { trk.beta(); }) { + const bool hasTof = hasTOFMatch(trk); + const float beta = trk.beta(); + if (hasTof && beta > TofBetaMin && beta < TofBetaMax) { + histos.fill(HIST("hTOFBetaVsP_P"), trk.p(), beta); + } + } + break; + } + case 3: { // deuteron + if constexpr (requires { trk.tpcSignal(); }) { + histos.fill(HIST("hTPCdEdxVsP_D"), trk.p(), trk.tpcSignal()); + } + if constexpr (requires { trk.beta(); }) { + const bool hasTof = hasTOFMatch(trk); + const float beta = trk.beta(); + if (hasTof && beta > TofBetaMin && beta < TofBetaMax) { + histos.fill(HIST("hTOFBetaVsP_D"), trk.p(), beta); + } + } + break; + } + default: + break; + } + } + + // Compute event multiplicity (FT0M or fallback) + const float eventMult = eventMultiplicityFT0MOrFallback(collision, eventMultFallback); + + // Deuteron candidates -> proton-proxy candidates + for (auto const& trkD : tracks) { + if (trkD.pt() < lstarCutPtMin.value || std::abs(trkD.eta()) > lstarCutEtaMax.value) { + continue; + } + if (!passTrackQuality(trkD)) { + continue; + } + if (trkD.sign() == 0) { + continue; + } + + // PID for deuteron candidates + const float nsTPCDe = trkD.tpcNSigmaDe(); + const float nsTOFDe = trkD.tofNSigmaDe(); + const bool isDeuteron = (std::abs(nsTPCDe) < lstarCutNsigmaTPCDe.value) && (std::abs(nsTOFDe) < lstarCutNsigmaTOFDe.value); + if (!isDeuteron) { + continue; + } + + // Deuteron kinematics + const float ptD = trkD.pt(); + const float etaD = trkD.eta(); + const float phiD = trkD.phi(); + const double pD = static_cast(ptD) * std::cosh(static_cast(etaD)); + + // QA histos for deuteron PID and kinematics + if (lstarEnablePidQA.value != 0) { + histos.fill(HIST("hDeuteronProxyPt"), ptD); + histos.fill(HIST("hDeuteronProxyEta"), etaD); + histos.fill(HIST("hDeuteronProxyPhi"), phiD); + histos.fill(HIST("hNsigmaTPCDeuteron"), nsTPCDe); + histos.fill(HIST("hNsigmaTOFDeuteron"), nsTOFDe); + histos.fill(HIST("hNsigmaTPCDeuteronVsP"), pD, nsTPCDe); + histos.fill(HIST("hNsigmaTOFDeuteronVsP"), pD, nsTOFDe); + } + + // build proton-proxy momentum from deuteron: p_p ≈ p_d / 2 + const float pxProxy = ProxyMomentumScale * ptD * std::cos(phiD); + const float pyProxy = ProxyMomentumScale * ptD * std::sin(phiD); + const float pzProxy = ProxyMomentumScale * ptD * std::sinh(etaD); + + proxyCands.push_back(ProxyCand{pxProxy, pyProxy, pzProxy, static_cast(trkD.sign()), static_cast(trkD.globalIndex())}); + } + + // Kaon candidates + for (auto const& trkK : tracks) { + if (trkK.pt() < lstarCutPtMin.value || std::abs(trkK.eta()) > lstarCutEtaMax.value) { + continue; + } + if (!passTrackQuality(trkK)) { + continue; + } + if (trkK.sign() == 0) { + continue; + } + + // PID for kaon candidates + const float nsTPCK = trkK.tpcNSigmaKa(); + const float nsTOFK = trkK.tofNSigmaKa(); + const bool isKaon = (std::abs(nsTPCK) < lstarCutNsigmaTPCKaon.value) && (std::abs(nsTOFK) < lstarCutNsigmaTOFKaon.value); + if (!isKaon) { + continue; + } + + // Kaon kinematics + const float ptK = trkK.pt(); + const float etaK = trkK.eta(); + const float phiK = trkK.phi(); + const double pK = static_cast(ptK) * std::cosh(static_cast(etaK)); + + // Kaon QA + if (lstarEnablePidQA.value != 0) { + histos.fill(HIST("hKaonPt"), ptK); + histos.fill(HIST("hKaonEta"), etaK); + histos.fill(HIST("hKaonPhi"), phiK); + histos.fill(HIST("hNsigmaTPCKaon"), nsTPCK); + histos.fill(HIST("hNsigmaTOFKaon"), nsTOFK); + histos.fill(HIST("hNsigmaTPCKaonVsP"), pK, nsTPCK); + histos.fill(HIST("hNsigmaTOFKaonVsP"), pK, nsTOFK); + } + + const float pxK = ptK * std::cos(phiK); + const float pyK = ptK * std::sin(phiK); + const float pzK = ptK * std::sinh(etaK); + + kaonCands.push_back(KaonCand{pxK, pyK, pzK, static_cast(trkK.sign()), static_cast(trkK.globalIndex())}); + } + + if (proxyCands.empty() || kaonCands.empty()) { + // still update mixing buffer so that later events can mix with this one + LStarMixEventEntry entry; + entry.mult = eventMult; + entry.zvtx = collision.posZ(); + entry.kaons = std::move(kaonCands); + entry.proxies = std::move(proxyCands); + mLStarMixEvents.push_front(std::move(entry)); + if (mLStarMixEvents.size() > static_cast(lstarNoMixedEvents.value)) { + mLStarMixEvents.pop_back(); + } + return; + } + + // --- SAME-EVENT: proxy (d/2) + K --- + for (auto const& pr : proxyCands) { + for (auto const& k : kaonCands) { + if (pr.tid == k.tid) + continue; // sanity check: should never match, but just in case of bug in candidate-building logic + const double mass = invariantMass(pr.px, pr.py, pr.pz, MassProton, k.px, k.py, k.pz, MassKaonCharged); + + const float pxTot = pr.px + k.px; + const float pyTot = pr.py + k.py; + const float pzTot = pr.pz + k.pz; + const float ptPair = std::sqrt(pxTot * pxTot + pyTot * pyTot); + const float phiPair = phiFromPxPy(pxTot, pyTot); + + const double eTot = std::sqrt(mass * mass + static_cast(pxTot) * pxTot + static_cast(pyTot) * pyTot + static_cast(pzTot) * pzTot); + const float yPair = rapidityFromEPz(eTot, pzTot); + + // Inclusive invariant-mass spectrum for the #Lambda^{*} proxy + histos.fill(HIST("hDeuteronProxyMass"), mass); + if (lstarEnableSparse.value != 0) { + histos.fill(HIST("hLambdaStarProxySparse"), mass, ptPair, yPair, phiPair, eventMult); + } + + const bool unlikeSign = (pr.charge * k.charge) < 0; + if (unlikeSign) { + histos.fill(HIST("hInvMassPKUnlike"), mass); + histos.fill(HIST("hInvMassPKUnlikeVsPt"), mass, ptPair); + if (lstarEnableSparse.value != 0) { + histos.fill(HIST("hLambdaStarPKUnlikeSparse"), mass, ptPair, yPair, phiPair, eventMult); + } + } else { + histos.fill(HIST("hInvMassPKLike"), mass); + histos.fill(HIST("hInvMassPKLikeVsPt"), mass, ptPair); + if (lstarEnableSparse.value != 0) { + histos.fill(HIST("hLambdaStarPKLikeSparse"), mass, ptPair, yPair, phiPair, eventMult); + } + } + } + } + + // --- MIXED-EVENT: current proxies + previous-event kaons --- + for (auto const& prev : mLStarMixEvents) { + if (std::abs(prev.zvtx - collision.posZ()) > lstarMixZvtxMax.value) + continue; + if (std::abs(prev.mult - eventMult) > lstarMixMultMax.value) + continue; + if (prev.kaons.empty()) { + continue; + } + + for (auto const& pr : proxyCands) { + for (auto const& k : prev.kaons) { + // convention: mix for unlike-sign only (resonance background) + if ((pr.charge * k.charge) >= 0) { + continue; + } + if (pr.tid == k.tid) + continue; // sanity check: should never match, but just in case of bug in candidate-building logic + + const double mass = invariantMass(pr.px, pr.py, pr.pz, MassProton, k.px, k.py, k.pz, MassKaonCharged); + + const float pxTot = pr.px + k.px; + const float pyTot = pr.py + k.py; + const float pzTot = pr.pz + k.pz; + const float ptPair = std::sqrt(pxTot * pxTot + pyTot * pyTot); + const float phiPair = phiFromPxPy(pxTot, pyTot); + + const double eTot = std::sqrt(mass * mass + static_cast(pxTot) * pxTot + static_cast(pyTot) * pyTot + static_cast(pzTot) * pzTot); + const float yPair = rapidityFromEPz(eTot, pzTot); + + // Fill mixed-event THnSparse + if (lstarEnableSparse.value != 0) { + histos.fill(HIST("hLambdaStarPKMixedSparse"), mass, ptPair, yPair, phiPair, eventMult); + histos.fill(HIST("hLambdaStarProxyMixedSparse"), mass, ptPair, yPair, phiPair, eventMult); + } + } + } + } + + // --- Update mixing buffer with current event --- + LStarMixEventEntry entry; + entry.mult = eventMult; + entry.zvtx = collision.posZ(); + entry.kaons = std::move(kaonCands); + entry.proxies = std::move(proxyCands); + + mLStarMixEvents.push_front(std::move(entry)); + if (mLStarMixEvents.size() > static_cast(lstarNoMixedEvents.value)) { + mLStarMixEvents.pop_back(); + } + } + + PROCESS_SWITCH(Lambdastarproxy, process, "Lambda* proxy via (d/2)+K", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc)}; +} From dcedbb015738b919eaba937979acae8d7e4e34b8 Mon Sep 17 00:00:00 2001 From: Jaideep Tanwar <141036812+jtanwar2212@users.noreply.github.com> Date: Mon, 23 Feb 2026 18:02:19 +0530 Subject: [PATCH 039/347] [PWGLF] [pwglf] new DCA for secondary rejection (#15115) --- PWGLF/Tasks/Nuspex/nucleitpcpbpb.cxx | 448 +++++++++------------------ 1 file changed, 149 insertions(+), 299 deletions(-) diff --git a/PWGLF/Tasks/Nuspex/nucleitpcpbpb.cxx b/PWGLF/Tasks/Nuspex/nucleitpcpbpb.cxx index 237c91ca787..f1ee505a4e5 100644 --- a/PWGLF/Tasks/Nuspex/nucleitpcpbpb.cxx +++ b/PWGLF/Tasks/Nuspex/nucleitpcpbpb.cxx @@ -128,7 +128,6 @@ struct NucleitpcPbPb { HistogramRegistry histomc{"histomc", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; // Event Selection Configurables - Configurable removeITSROFrameBorder{"removeITSROFrameBorder", false, "Remove ITS RO frame border"}; Configurable removeNoSameBunchPileup{"removeNoSameBunchPileup", false, "Remove no same bunch pileup"}; Configurable requireIsGoodZvtxFT0vsPV{"requireIsGoodZvtxFT0vsPV", false, "Require is good Zvtx FT0 vs PV"}; Configurable requireIsVertexITSTPC{"requireIsVertexITSTPC", false, "Require is vertex ITS TPC"}; @@ -183,7 +182,6 @@ struct NucleitpcPbPb { Configurable cfgRigidityCorrection{"cfgRigidityCorrection", false, "apply rigidity correction"}; Configurable cfgRequirebetaplot{"cfgRequirebetaplot", true, "Require beta plot"}; Configurable cfgmass2{"cfgmass2", true, "Fill mass square difference"}; - Configurable cfgFillhspectra{"cfgFillhspectra", true, "fill data sparsh"}; Configurable cfgFillmass{"cfgFillmass", false, "Fill mass histograms"}; Configurable cfgFillmassnsigma{"cfgFillmassnsigma", true, "Fill mass vs nsigma histograms"}; @@ -207,12 +205,9 @@ struct NucleitpcPbPb { ConfigurableAxis axismass{"axismass", {1200, 0, 12}, "mass"}; ConfigurableAxis axismassnsigma{"axismassnsigma", {1200, 0, 12}, "nsigma mass"}; ConfigurableAxis nsigmaAxis{"nsigmaAxis", {160, -10, 10}, "n#sigma_{#pi^{+}}"}; - ConfigurableAxis speciesBitAxis{"speciesBitAxis", {8, -0.5, 7.5}, "particle type 0: pion, 1: proton, 2: deuteron, 3: triton, 4:He3, 5:He4"}; - ConfigurableAxis speciesTrackingAxis{"speciesTrackingAxis", {11, -0.5, 10.5}, "particle type 0: pion, 1: proton, 2: deuteron, 3: triton, 4:He3, 5:He4"}; ConfigurableAxis axisDCA{"axisDCA", {400, -10., 10.}, "DCA axis"}; ConfigurableAxis particleAntiAxis{"particleAntiAxis", {2, -0.5, 1.5}, "Particle/Anti-particle"}; // 0 = particle, 1 = anti-particle ConfigurableAxis decayTypeAxis{"decayTypeAxis", {3, -0.5, 2.5}, "Decay type"}; // 0 = primary, 1 = from decay, 2 = material - ConfigurableAxis axisTPCsig{"axisTPCsig", {1000, 0, 2000}, "TPC signal (a.u.)"}; // CCDB Service ccdb; @@ -230,6 +225,8 @@ struct NucleitpcPbPb { int mRunNumber, occupancy; float dBz; TRandom3 rand; + + float de = 2; float triton = 3; float he3 = 4; float he4 = 5; @@ -254,99 +251,80 @@ struct NucleitpcPbPb { histos.add("histCentFT0C", "histCentFT0C", kTH1F, {axisCent}); histos.add("histCentFT0M", "histCentFT0M", kTH1F, {axisCent}); histos.add("histCentFTOC_cut", "histCentFTOC_cut", kTH1F, {axisCent}); - histos.add("hSpectra", " ", HistType::kTHnSparseF, {speciesBitAxis, ptAxis, nsigmaAxis, {5, -2.5, 2.5}, axisCent, axisDCA, axisDCA, axisOccupancy}); - histos.add("DCAxy_vs_pT_He3_data", "DCA_{xy} vs p_{T} for He3 (Data);p_{T} (GeV/c);DCA_{xy} (cm)", - {HistType::kTH2F, {ptAxis, axisDCA}}); - histos.add("DCAxy_vs_pT_antiHe3_data", "DCA_{xy} vs p_{T} for anti-He3 (Data);p_{T} (GeV/c);DCA_{xy} (cm)", - {HistType::kTH2F, {ptAxis, axisDCA}}); - - histos.add("TPCsig_triton", "TPC signal for triton;p/z (GeV/c);TPC signal", - {HistType::kTH2F, {axisRigidity, axisTPCsig}}); - histos.add("TPCsig_he3", "TPC signal for he3;p/z (GeV/c);TPC signal", - {HistType::kTH2F, {axisRigidity, axisTPCsig}}); - histos.add("TPCsig_he4", "TPC signal for he4;p/z (GeV/c);TPC signal", - {HistType::kTH2F, {axisRigidity, axisTPCsig}}); + histos.add("hSpectra", " ", HistType::kTHnSparseF, {ptAxis, nsigmaAxis, {5, -2.5, 2.5}, axisCent}); + histos.add("DCAxy_vs_pT_data", "DCA_{xy} vs p_{T} for He3 (Data);p_{T} (GeV/c);DCA_{xy} (cm)", + {HistType::kTH3F, {ptAxis, axisDCA, axisCent}}); + histos.add("DCAxy_vs_pT_anti_data", "DCA_{xy} vs p_{T} for anti-He3 (Data);p_{T} (GeV/c);DCA_{xy} (cm)", + {HistType::kTH3F, {ptAxis, axisDCA, axisCent}}); + + hmass.resize(2 * nParticles + 2); + hmassnsigma.resize(2 * nParticles + 2); + + for (int i = 0; i < nParticles; i++) { + TString histName = primaryParticles[i].name; + if (cfgFillmass) { + hmass[2 * i] = histos.add(Form("histmass_pt/histmass_%s", histName.Data()), ";p_T{TPC} (GeV/#it{c}); mass^{2}; centrality(%)", HistType::kTH3F, {ptAxis, axismass, axisCent}); + hmass[2 * i + 1] = histos.add(Form("histmass_ptanti/histmass_%s", histName.Data()), ";p_T{TPC} (GeV/#it{c}); mass^{2}; centrality(%)", HistType::kTH3F, {ptAxis, axismass, axisCent}); + } + } + for (int i = 0; i < nParticles; i++) { + TString histName = primaryParticles[i].name; + if (cfgFillmassnsigma) { + hmassnsigma[2 * i] = histos.add(Form("histmass_nsigma/histmass_%s", histName.Data()), ";p_T{TPC} (GeV/#it{c}); mass^{2}/z^{2}; Centrality(%)", HistType::kTH3F, {ptAxis, axismassnsigma, axisCent}); + hmassnsigma[2 * i + 1] = histos.add(Form("histmass_nsigmaanti/histmass_%s", histName.Data()), ";p_T{TPC} (GeV/#it{c}); mass^{2}/z^{2}; centrality(%)", HistType::kTH3F, {ptAxis, axismassnsigma, axisCent}); + } + } + + histos.add("histeta", "histeta", kTH1F, {axiseta}); + + histos.add("histEvents", "histEvents", kTH2F, {axisCent, axisOccupancy}); } - histos.add("histeta", "histeta", kTH1F, {axiseta}); - histos.add("histEvents", "histEvents", kTH2F, {axisCent, axisOccupancy}); + histos.add("dcaZ", "dcaZ", kTH2F, {ptAxis, axisDCA}); histos.add("dcaXY", "dcaXY", kTH2F, {ptAxis, axisDCA}); histos.add("Tofsignal", "Tofsignal", kTH2F, {axisRigidity, {4000, 0.2, 1.2, "#beta"}}); histos.add("Tpcsignal", "Tpcsignal", kTH2F, {axisRigidity, axisdEdx}); - hmass.resize(2 * nParticles + 2); - hmassnsigma.resize(2 * nParticles + 2); - - for (int i = 0; i < nParticles; i++) { - TString histName = primaryParticles[i].name; - if (cfgFillmass) { - hmass[2 * i] = histos.add(Form("histmass_pt/histmass_%s", histName.Data()), ";p_T{TPC} (GeV/#it{c}); mass^{2}; centrality(%)", HistType::kTH3F, {ptAxis, axismass, axisCent}); - hmass[2 * i + 1] = histos.add(Form("histmass_ptanti/histmass_%s", histName.Data()), ";p_T{TPC} (GeV/#it{c}); mass^{2}; centrality(%)", HistType::kTH3F, {ptAxis, axismass, axisCent}); - } - } - for (int i = 0; i < nParticles; i++) { - TString histName = primaryParticles[i].name; - if (cfgFillmassnsigma) { - hmassnsigma[2 * i] = histos.add(Form("histmass_nsigma/histmass_%s", histName.Data()), ";p_T{TPC} (GeV/#it{c}); mass^{2}/z^{2}; Centrality(%)", HistType::kTH3F, {ptAxis, axismassnsigma, axisCent}); - hmassnsigma[2 * i + 1] = histos.add(Form("histmass_nsigmaanti/histmass_%s", histName.Data()), ";p_T{TPC} (GeV/#it{c}); mass^{2}/z^{2}; centrality(%)", HistType::kTH3F, {ptAxis, axismassnsigma, axisCent}); - } - } - if (doprocessMC) { - histomc.add("hSpectramc", " ", HistType::kTHnSparseF, {speciesBitAxis, {5, -2.5, 2.5}, axisCent, ptAxis, ptAxis}); + histomc.add("hSpectramc", " ", HistType::kTHnSparseF, {{5, -2.5, 2.5}, axisCent, ptAxis, ptAxis}); // Efficiency x Acceptance histomc.add("hDenomEffAcc", "Denominator for Efficiency x Acceptance", - {HistType::kTHnSparseF, {speciesBitAxis, ptAxis, axisrapidity, axisCent, particleAntiAxis, decayTypeAxis}}); + {HistType::kTHnSparseF, {ptAxis, axisCent, particleAntiAxis, decayTypeAxis}}); histomc.add("hNumerEffAcc", "Numerator for Efficiency x Acceptance", - {HistType::kTHnSparseF, {speciesBitAxis, ptAxis, axisrapidity, axisCent, particleAntiAxis, decayTypeAxis}}); + {HistType::kTHnSparseF, {ptAxis, axisCent, particleAntiAxis, decayTypeAxis}}); // The Signal loss correction - histomc.add("hHe3SignalLossDenom", "He3 Signal Loss Denominator", kTH1F, {axisCent}); - histomc.add("hHe3SignalLossNumer", "He3 Signal Loss Numerator", kTH1F, {axisCent}); - histomc.add("hHe4SignalLossDenom", "He4 Signal Loss Denominator", kTH1F, {axisCent}); - histomc.add("hHe4SignalLossNumer", "He4 Signal Loss Numerator", kTH1F, {axisCent}); + histomc.add("hSignalLossDenom", "Signal Loss Denominator", kTH2F, {axisCent, ptAxis}); + histomc.add("hSignalLossNumer", "Signal Loss Numerator", kTH2F, {axisCent, ptAxis}); - histomc.add("haHe3SignalLossDenom", "He3 Signal Loss Denominator", kTH1F, {axisCent}); - histomc.add("haHe3SignalLossNumer", "He3 Signal Loss Numerator", kTH1F, {axisCent}); - histomc.add("haHe4SignalLossDenom", "He4 Signal Loss Denominator", kTH1F, {axisCent}); - histomc.add("haHe4SignalLossNumer", "He4 Signal Loss Numerator", kTH1F, {axisCent}); + histomc.add("haSignalLossDenom", "anti particle Signal Loss Denominator", kTH2F, {axisCent, ptAxis}); + histomc.add("haSignalLossNumer", "antiparticle Signal Loss Numerator", kTH2F, {axisCent, ptAxis}); // The event loss correction histomc.add("hEventLossDenom", "Event loss denominator", kTH1F, {axisCent}); histomc.add("hEventLossNumer", "Event loss numerator", kTH1F, {axisCent}); histomc.add("histVtxZgen", "histVtxZgen", kTH1F, {axisVtxZ}); - histomc.add("histNevReco", "histNevReco", kTH1F, {axisNev}); histomc.add("histVtxZReco", "histVtxZReco", kTH1F, {axisVtxZ}); - histomc.add("histCentFT0CReco", "histCentFT0CReco", kTH1F, {axisCent}); - histomc.add("histCentFT0MReco", "histCentFT0MReco", kTH1F, {axisCent}); - - histomc.add("histdetapttriton", " delta pt vs pt rec for trition detected", HistType::kTH2F, {{1000, 0, 10}, {1000, -0.5, 0.5, "p_{T}(reco) - p_{T}(gen);p_{T}(reco)"}}); - histomc.add("histdetapttritonanti", " delta pt vs pt rec for trition detected", HistType::kTH2F, {{1000, 0, 10}, {1000, -0.5, 0.5, "p_{T}(reco) - p_{T}(gen);p_{T}(reco)"}}); - histomc.add("histDeltaPtVsPtGen", " delta pt vs pt rec", HistType::kTH2F, {{1000, 0, 10}, {1000, -0.5, 0.5, "p_{T}(reco) - p_{T}(gen);p_{T}(reco)"}}); histomc.add("histDeltaPtVsPtGenanti", " delta pt vs pt rec", HistType::kTH2F, {{1000, 0, 10}, {1000, -0.5, 0.5, "p_{T}(reco) - p_{T}(gen);p_{T}(reco)"}}); - histomc.add("histDeltaPtVsPtGenHe4", " delta pt vs pt rec", HistType::kTH2F, {{1000, 0, 10}, {1000, -0.5, 0.5, "p_{T}(reco) - p_{T}(gen);p_{T}(reco)"}}); - histomc.add("histDeltaPtVsPtGenHe4anti", " delta pt vs pt rec", HistType::kTH2F, {{1000, 0, 10}, {1000, -0.5, 0.5, "p_{T}(reco) - p_{T}(gen);p_{T}(reco)"}}); + histomc.add("histDeltaPtVsPtGen", " delta pt vs pt rec", HistType::kTH2F, {{1000, 0, 10}, {1000, -0.5, 0.5, "p_{T}(reco) - p_{T}(gen);p_{T}(reco)"}}); histomc.add("histPIDtrack", " delta pt vs pt rec", HistType::kTH2F, {{1000, 0, 10, "p_{T}(reco)"}, {9, -0.5, 8.5, "p_{T}(reco) - p_{T}(gen)"}}); histomc.add("histPIDtrackanti", " delta pt vs pt rec", HistType::kTH2F, {{1000, 0, 10, "p_{T}(reco)"}, {9, -0.5, 8.5, "p_{T}(reco) - p_{T}(gen)"}}); - histomc.add("histPIDtrackhe4", " delta pt vs pt rec", HistType::kTH2F, {{1000, 0, 10, "p_{T}(reco)"}, {9, -0.5, 8.5, "p_{T}(reco) - p_{T}(gen)"}}); - histomc.add("histPIDtrackantihe4", " delta pt vs pt rec", HistType::kTH2F, {{1000, 0, 10, "p_{T}(reco)"}, {9, -0.5, 8.5, "p_{T}(reco) - p_{T}(gen)"}}); } if (doprocessDCA) { - histomc.add("hSpectraDCA", " ", HistType::kTHnSparseF, {speciesBitAxis, {5, -2.5, 2.5}, axisCent, ptAxis, ptAxis, decayTypeAxis, axisDCA}); // NEW: Add DCAxy vs pT histograms for MC - histomc.add("DCAxy_vs_pT_He3_transport", "DCA_{xy} vs p_{T} for He3 (Transport);p_{T} (GeV/c);DCA_{xy} (cm)", - {HistType::kTH2F, {ptAxis, axisDCA}}); - histomc.add("DCAxy_vs_pT_He3_weakdecay", "DCA_{xy} vs p_{T} for He3 (Weak Decay);p_{T} (GeV/c);DCA_{xy} (cm)", - {HistType::kTH2F, {ptAxis, axisDCA}}); - histomc.add("DCAxy_vs_pT_He3_total", "DCA_{xy} vs p_{T} for He3 (Total);p_{T} (GeV/c);DCA_{xy} (cm)", - {HistType::kTH2F, {ptAxis, axisDCA}}); - histomc.add("DCAxy_vs_pT_antiHe3_total", "DCA_{xy} vs p_{T} for anti-He3 (Total);p_{T} (GeV/c);DCA_{xy} (cm)", - {HistType::kTH2F, {ptAxis, axisDCA}}); + histomc.add("DCAxy_vs_pT_transport", "DCA_{xy} vs p_{T} (Transport);p_{T} (GeV/c);DCA_{xy} (cm)", + {HistType::kTH3F, {ptAxis, axisDCA, axisCent}}); + histomc.add("DCAxy_vs_pT_weakdecay", "DCA_{xy} vs p_{T} (Weak Decay);p_{T} (GeV/c);DCA_{xy} (cm)", + {HistType::kTH3F, {ptAxis, axisDCA, axisCent}}); + histomc.add("DCAxy_vs_pT_total", "DCA_{xy} vs p_{T} (Total);p_{T} (GeV/c);DCA_{xy} (cm)", + {HistType::kTH3F, {ptAxis, axisDCA, axisCent}}); + histomc.add("DCAxy_vs_pT_anti_total", "DCA_{xy} vs p_{T} for anti (Total);p_{T} (GeV/c);DCA_{xy} (cm)", + {HistType::kTH3F, {ptAxis, axisDCA, axisCent}}); } } //---------------------------------------------------------------------------------------------------------------- @@ -362,39 +340,34 @@ struct NucleitpcPbPb { if (!collPassedEvSel) continue; - if (removeITSROFrameBorder && !collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) - continue; - histos.fill(HIST("histNev"), 2.5); if (removeNoSameBunchPileup && !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) continue; - histos.fill(HIST("histNev"), 3.5); + histos.fill(HIST("histNev"), 2.5); if (requireIsGoodZvtxFT0vsPV && !collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) continue; - histos.fill(HIST("histNev"), 4.5); + histos.fill(HIST("histNev"), 3.5); if (requireIsVertexITSTPC && !collision.selection_bit(aod::evsel::kIsVertexITSTPC)) continue; - histos.fill(HIST("histNev"), 5.5); + histos.fill(HIST("histNev"), 4.5); if (removeNoTimeFrameBorder && !collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) continue; - histos.fill(HIST("histNev"), 6.5); + histos.fill(HIST("histNev"), 5.5); histos.fill(HIST("histEvents"), collision.centFT0C(), occupancy); histos.fill(HIST("histVtxZ"), collision.posZ()); histos.fill(HIST("histCentFT0C"), collision.centFT0C()); histos.fill(HIST("histCentFT0M"), collision.centFT0M()); if (collision.centFT0C() > centcut) continue; - histos.fill(HIST("histNev"), 7.5); + histos.fill(HIST("histNev"), 6.5); histos.fill(HIST("histCentFTOC_cut"), collision.centFT0C()); // new slicing auto tracksInColl = tracks.sliceBy(tracksPerCollision, collision.globalIndex()); - // loop over sliced tracks for (const auto& track : tracksInColl) { if (!track.isPVContributor() && cfgUsePVcontributors) continue; - if (!track.hasTPC()) continue; if (!track.passedITSRefit() && cfgPassedITSRefit) @@ -403,13 +376,13 @@ struct NucleitpcPbPb { continue; if (std::abs(track.eta()) > cfgCutEta && cfgetaRequire) continue; - for (size_t i = 0; i < primaryParticles.size(); i++) { + if (cfgTrackPIDsettings2->get(i, "fillsparsh") != 1) + continue; float ptMomn; setTrackParCov(track, mTrackParCov); mTrackParCov.setPID(track.pidForTracking()); ptMomn = (i == he3 || i == he4) ? 2 * mTrackParCov.getPt() : mTrackParCov.getPt(); - float tpcNsigma = getTPCnSigma(track, primaryParticles.at(i)); if ((std::abs(tpcNsigma) > cfgTrackPIDsettings->get(i, "maxTPCnSigma")) && cfgmaxTPCnSigmaRequire) continue; @@ -422,23 +395,19 @@ struct NucleitpcPbPb { } else if (i == he4) { param = (track.sign() > 0) ? 2 : 3; } - if (param >= 0) { a = cfgktrackcorrection->get(param, "a"); b = cfgktrackcorrection->get(param, "b"); c = cfgktrackcorrection->get(param, "c"); } - if (i == he4 && ptMomn < pTcorrectHe4) { ptMomn = ptMomn + a + b * std::exp(c * ptMomn); } - if (i == he3 && ptMomn < pTcorrectHe3) { ptMomn = ptMomn - a + b * ptMomn - c * ptMomn * ptMomn; } } int sign = (track.sign() > 0) ? 1 : ((track.sign() < 0) ? -1 : 0); - if (std::abs(getRapidity(track, i)) > cfgCutRapidity && cfgRapidityRequire) continue; if (track.tpcNClsFound() < cfgTrackPIDsettings->get(i, "minTPCnCls")) @@ -453,7 +422,6 @@ struct NucleitpcPbPb { continue; if (track.itsNCls() < cfgTrackPIDsettings->get(i, "minITSnCls") && cfgminITSnClsRequire) continue; - double cosheta = std::cosh(track.eta()); if ((track.itsNCls() / cosheta) < cfgTrackPIDsettings->get(i, "minITSnClscos") && cfgminITSnClscosRequire) continue; @@ -463,9 +431,7 @@ struct NucleitpcPbPb { continue; if (getMeanItsClsSize(track) < cfgTrackPIDsettings->get(i, "minITSclsSize") && cfgminGetMeanItsClsSizeRequire) continue; - bool insideDCAxy = false; - if (cfgUseNewDCAxyCut) { double sigmaFactor = cfgTrackPIDsettings->get(i, "maxDcaXY"); double sigma_base = (0.0118 * std::exp(-0.6889 * ptMomn) + 0.0017); @@ -514,51 +480,37 @@ struct NucleitpcPbPb { if (i == he4) { tpcNsigmaDe = track.tpcNSigmaDe(); } - if (i == triton || i == he3 || i == he4) { - float rigidity = getRigidity(track); - if (i == triton) { - histos.fill(HIST("TPCsig_triton"), rigidity * track.sign(), track.tpcSignal()); - } else if (i == he3) { - histos.fill(HIST("TPCsig_he3"), rigidity * track.sign(), track.tpcSignal()); - } else if (i == he4) { - histos.fill(HIST("TPCsig_he4"), rigidity * track.sign(), track.tpcSignal()); - } - } - if (i == he3) { - if (track.sign() > 0) { - histos.fill(HIST("DCAxy_vs_pT_He3_data"), ptMomn, track.dcaXY()); - } else if (track.sign() < 0) { - histos.fill(HIST("DCAxy_vs_pT_antiHe3_data"), ptMomn, track.dcaXY()); - } + if (track.sign() > 0) { + histos.fill(HIST("DCAxy_vs_pT_data"), ptMomn, track.dcaXY(), collision.centFT0C()); + } else if (track.sign() < 0) { + histos.fill(HIST("DCAxy_vs_pT_anti_data"), ptMomn, track.dcaXY(), collision.centFT0C()); } - if (cfgFillhspectra && cfgTrackPIDsettings2->get(i, "fillsparsh") == 1) { - if (i != he4) { - histos.fill(HIST("hSpectra"), i, ptMomn, tpcNsigma, sign, collision.centFT0C(), track.dcaZ(), track.dcaXY(), collision.trackOccupancyInTimeRange()); + if (i != he4) { + histos.fill(HIST("hSpectra"), ptMomn, tpcNsigma, sign, collision.centFT0C()); + } else { + if (!track.hasTOF()) { + if (std::abs(tpcNsigmaDe) > deuteronsigmarejection) { + histos.fill(HIST("hSpectra"), ptMomn, tpcNsigma, sign, collision.centFT0C()); + } } else { - if (!track.hasTOF()) { - if (std::abs(tpcNsigmaDe) > deuteronsigmarejection) { - histos.fill(HIST("hSpectra"), i, ptMomn, tpcNsigma, sign, collision.centFT0C(), track.dcaZ(), track.dcaXY(), collision.trackOccupancyInTimeRange()); - } - } else { - // Has TOF - apply mass cut - float beta = o2::pid::tof::Beta::GetBeta(track); - const float eps = 1e-6f; - if (beta < eps || beta > 1.0f - eps) - continue; - - float charge = 2.f; // he4 has charge 2 - float p = getRigidity(track); - float massTOF = p * charge * std::sqrt(1.f / (beta * beta) - 1.f); - - // Apply mass cut for he4 (mass^2 around 3.73^2 = 13.9) - if (cfghe3massrejreq && (massTOF * massTOF > cfgminmassrejection && massTOF * massTOF < cfgmaxmassrejection)) { - continue; // Skip if mass cut fails - } - if (std::abs(tpcNsigmaDe) > deuteronsigmarejection) { - histos.fill(HIST("hSpectra"), i, ptMomn, tpcNsigma, sign, collision.centFT0C(), track.dcaZ(), track.dcaXY(), collision.trackOccupancyInTimeRange()); - } + // Has TOF - apply mass cut + float beta = o2::pid::tof::Beta::GetBeta(track); + const float eps = 1e-6f; + if (beta < eps || beta > 1.0f - eps) + continue; + + float charge = 2.f; // he4 has charge 2 + float p = getRigidity(track); + float massTOF = p * charge * std::sqrt(1.f / (beta * beta) - 1.f); + + // Apply mass cut for he4 (mass^2 around 3.73^2 = 13.9) + if (cfghe3massrejreq && (massTOF * massTOF > cfgminmassrejection && massTOF * massTOF < cfgmaxmassrejection)) { + continue; // Skip if mass cut fails + } + if (std::abs(tpcNsigmaDe) > deuteronsigmarejection) { + histos.fill(HIST("hSpectra"), ptMomn, tpcNsigma, sign, collision.centFT0C()); } } } @@ -631,9 +583,6 @@ struct NucleitpcPbPb { if (collision.centFT0C() > centcut) continue; - // Additional cuts - if (removeITSROFrameBorder && !collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) - continue; if (removeNoSameBunchPileup && !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) continue; if (requireIsGoodZvtxFT0vsPV && !collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) @@ -656,7 +605,7 @@ struct NucleitpcPbPb { // FILL EVENT LOSS AND SIGNAL LOSS: Combined loop per MC collision for (size_t i = 0; i < mcCollInfos.size(); i++) { if (mcCollInfos[i].centrality >= 0) { // Only if we found a matching collision - // Event loss denominator + // Event loss denominator (always filled regardless of fillsparsh) histomc.fill(HIST("hEventLossDenom"), mcCollInfos[i].centrality); // Event loss numerator (if passed selection) @@ -673,29 +622,31 @@ struct NucleitpcPbPb { continue; } - // Signal loss denominator - if (mcParticle.pdgCode() == particlePdgCodes.at(4)) { // He3 - histomc.fill(HIST("hHe3SignalLossDenom"), mcCollInfos[i].centrality); + // Check if this particle type has fillsparsh enabled + int particleType = -1; + for (size_t j = 0; j < primaryParticles.size(); j++) { + if (std::abs(mcParticle.pdgCode()) == std::abs(particlePdgCodes.at(j))) { + particleType = j; + break; + } + } - } else if (mcParticle.pdgCode() == particlePdgCodes.at(5)) { // He4 - histomc.fill(HIST("hHe4SignalLossDenom"), mcCollInfos[i].centrality); - } else if (mcParticle.pdgCode() == -particlePdgCodes.at(4)) { // anti-He3 - histomc.fill(HIST("haHe3SignalLossDenom"), mcCollInfos[i].centrality); + // Skip if fillsparsh is not enabled for this particle + if (particleType < 0 || cfgTrackPIDsettings2->get(particleType, "fillsparsh") != 1) + continue; - } else if (mcParticle.pdgCode() == -particlePdgCodes.at(5)) { // He4 - histomc.fill(HIST("haHe4SignalLossDenom"), mcCollInfos[i].centrality); + // Signal loss denominator + if (mcParticle.pdgCode() == particlePdgCodes.at(particleType)) { // particle + histomc.fill(HIST("hSignalLossDenom"), mcCollInfos[i].centrality, mcParticle.pt()); + } else if (mcParticle.pdgCode() == -particlePdgCodes.at(particleType)) { // anti-particle + histomc.fill(HIST("haSignalLossDenom"), mcCollInfos[i].centrality, mcParticle.pt()); } - // Signal loss numerator (if event passed selection) if (mcCollInfos[i].passedEvSel) { - if (mcParticle.pdgCode() == particlePdgCodes.at(4)) { // He3 - histomc.fill(HIST("hHe3SignalLossNumer"), mcCollInfos[i].centrality); - } else if (mcParticle.pdgCode() == particlePdgCodes.at(5)) { // He4 - histomc.fill(HIST("hHe4SignalLossNumer"), mcCollInfos[i].centrality); - } else if (mcParticle.pdgCode() == -particlePdgCodes.at(4)) { // anti-He3 - histomc.fill(HIST("haHe3SignalLossNumer"), mcCollInfos[i].centrality); - } else if (mcParticle.pdgCode() == -particlePdgCodes.at(5)) { // anti-He4 - histomc.fill(HIST("haHe4SignalLossNumer"), mcCollInfos[i].centrality); + if (mcParticle.pdgCode() == particlePdgCodes.at(particleType)) { // particle + histomc.fill(HIST("hSignalLossNumer"), mcCollInfos[i].centrality, mcParticle.pt()); + } else if (mcParticle.pdgCode() == -particlePdgCodes.at(particleType)) { // anti-particle + histomc.fill(HIST("haSignalLossNumer"), mcCollInfos[i].centrality, mcParticle.pt()); } } } @@ -709,7 +660,6 @@ struct NucleitpcPbPb { continue; float centrality = mcCollInfos[idx].centrality; - // bool passedEvSel = mcCollInfos[idx].passedEvSel; bool passedEvSelVtZ = mcCollInfos[idx].passedEvSelVtZ; // Process generated particles for efficiency denominators @@ -720,10 +670,18 @@ struct NucleitpcPbPb { continue; int pdgCode = mcParticle.pdgCode(); - bool isHe3 = (std::abs(pdgCode) == particlePdgCodes.at(4)); - bool isHe4 = (std::abs(pdgCode) == particlePdgCodes.at(5)); - if (!isHe3 && !isHe4) + // Check which particle type this is + int particleType = -1; + for (size_t j = 0; j < primaryParticles.size(); j++) { + if (std::abs(pdgCode) == std::abs(particlePdgCodes.at(j))) { + particleType = j; + break; + } + } + + // Only process if this particle type has fillsparsh enabled + if (particleType < 0 || cfgTrackPIDsettings2->get(particleType, "fillsparsh") != 1) continue; if (std::abs(mcParticle.eta()) > cfgCutEta && cfgetaRequireMC) @@ -751,24 +709,10 @@ struct NucleitpcPbPb { decayType = 2; continue; } - bool isFromWeakDecay = (decayType == 1); - if (!mcParticle.isPhysicalPrimary() && !isFromWeakDecay) - // if (!mcParticle.isPhysicalPrimary()) - continue; - - int particleType = -1; - if (std::abs(pdgCode) == particlePdgCodes.at(4)) - particleType = he3; - else if (std::abs(pdgCode) == particlePdgCodes.at(5)) - particleType = he4; - - if (particleType >= 0) { - - // Efficiency x Acceptance histograms - if (passedEvSelVtZ) { - histomc.fill(HIST("hDenomEffAcc"), particleType, mcParticle.pt(), mcParticle.y(), centrality, particleAnti, decayType); - } + // Efficiency x Acceptance histograms - Denominator + if (passedEvSelVtZ) { + histomc.fill(HIST("hDenomEffAcc"), mcParticle.pt(), centrality, particleAnti, decayType); } } @@ -782,10 +726,7 @@ struct NucleitpcPbPb { auto bc = collision.bc_as(); initCCDB(bc); - histomc.fill(HIST("histNevReco"), 0.5); histomc.fill(HIST("histVtxZReco"), collision.posZ()); - histomc.fill(HIST("histCentFT0CReco"), collision.centFT0C()); - histomc.fill(HIST("histCentFT0MReco"), collision.centFT0M()); auto tracksInColl = tracks.sliceBy(tracksPerCollision, collision.globalIndex()); @@ -800,11 +741,6 @@ struct NucleitpcPbPb { continue; int pdg = matchedMCParticle.pdgCode(); - bool isHe3 = (std::abs(pdg) == particlePdgCodes.at(4)); - bool isHe4 = (std::abs(pdg) == particlePdgCodes.at(5)); - - if (!isHe3 && !isHe4) - continue; int decayType = 0; @@ -836,13 +772,15 @@ struct NucleitpcPbPb { continue; if (std::abs(track.eta()) > cfgCutEta && cfgetaRequire) continue; - if (!matchedMCParticle.isPhysicalPrimary()) - continue; for (size_t i = 0; i < primaryParticles.size(); i++) { if (std::abs(pdg) != std::abs(particlePdgCodes.at(i))) continue; + // CRITICAL: Only process if fillsparsh is enabled for this particle + if (cfgTrackPIDsettings2->get(i, "fillsparsh") != 1) + continue; + float ptReco; setTrackParCov(track, mTrackParCov); mTrackParCov.setPID(track.pidForTracking()); @@ -855,9 +793,9 @@ struct NucleitpcPbPb { int param = -1; if (i == he3) { - param = (-particlePdgCodes.at(4) > 0) ? 0 : 1; + param = (pdg > 0) ? 0 : 1; } else if (i == he4) { - param = (-particlePdgCodes.at(4) > 0) ? 2 : 3; + param = (pdg > 0) ? 2 : 3; } if (param >= 0) { @@ -907,31 +845,22 @@ struct NucleitpcPbPb { double sigmaFactor = cfgTrackPIDsettings->get(i, "maxDcaXY"); double sigma_base = (0.0118 * std::exp(-0.6889 * ptReco) + 0.0017); double sigma_new = sigmaFactor * sigma_base; - insideDCAxy = (std::abs(track.dcaXY()) <= sigma_new); } else { - insideDCAxy = - cfgdcaxynopt - ? (std::abs(track.dcaXY()) <= cfgTrackPIDsettings->get(i, "maxDcaXY")) - : (std::abs(track.dcaXY()) <= - (cfgTrackPIDsettings->get(i, "maxDcaXY") * - (0.0105f + 0.0350f / std::pow(ptReco, 1.1f)))); + insideDCAxy = cfgdcaxynopt + ? (std::abs(track.dcaXY()) <= cfgTrackPIDsettings->get(i, "maxDcaXY")) + : (std::abs(track.dcaXY()) <= (cfgTrackPIDsettings->get(i, "maxDcaXY") * (0.0105f + 0.0350f / std::pow(ptReco, 1.1f)))); } bool insideDCAz = false; if (cfgUseNewDCAzCut) { - double sigmaFactorZ = cfgTrackPIDsettings->get(i, "maxDcaZ"); - double p0 = 0.1014; double p1 = 1.7512; double p2 = 0.0024; - double sigma_base_z = p0 * std::exp(-p1 * ptReco) + p2; - double sigma_new_z = sigmaFactorZ * sigma_base_z; - insideDCAz = (std::abs(track.dcaZ()) <= sigma_new_z); } else { insideDCAz = (std::abs(track.dcaZ()) <= cfgTrackPIDsettings->get(i, "maxDcaZ")); @@ -945,56 +874,32 @@ struct NucleitpcPbPb { if ((std::abs(tpcNsigma) > cfgTrackPIDsettings->get(i, "maxTPCnSigma")) && cfgmaxTPCnSigmaRequire) continue; - if (i == he3 || i == he4) { - histomc.fill(HIST("hNumerEffAcc"), i, ptReco, getRapidity(track, i), collision.centFT0C(), particleAnti, decayType); - } + // Efficiency x Acceptance - Numerator + histomc.fill(HIST("hNumerEffAcc"), ptReco, collision.centFT0C(), particleAnti, decayType); - float ptTOF = -1.0; // Default: no TOF + // Sparse histogram + float ptTOF = -1.0; if (track.hasTOF()) { ptTOF = ptReco; } + histomc.fill(HIST("hSpectramc"), particleAnti, collision.centFT0C(), ptReco, ptTOF); - if (cfgTrackPIDsettings2->get(i, "fillsparsh") == 1) { - histomc.fill(HIST("hSpectramc"), i, particleAnti, collision.centFT0C(), - ptReco, ptTOF); - } - + // Basic track histograms histos.fill(HIST("dcaXY"), ptReco, track.dcaXY()); histos.fill(HIST("dcaZ"), ptReco, track.dcaZ()); - histos.fill(HIST("Tpcsignal"), getRigidity(track) * track.sign(), track.tpcSignal()); - // Fill the requested histograms + // Delta Pt histograms float ptGen = matchedMCParticle.pt(); float deltaPt = ptReco - ptGen; - if (pdg == -particlePdgCodes.at(4)) { + if (pdg == -particlePdgCodes.at(i)) { // Anti-particle histomc.fill(HIST("histDeltaPtVsPtGenanti"), ptReco, deltaPt); histomc.fill(HIST("histPIDtrackanti"), ptReco, track.pidForTracking()); - - int pidGuess = track.pidForTracking(); - int antitriton = 6; - if (pidGuess == antitriton) { - histomc.fill(HIST("histdetapttritonanti"), ptReco, deltaPt); - } } - if (pdg == particlePdgCodes.at(4)) { + if (pdg == particlePdgCodes.at(i)) { // Particle histomc.fill(HIST("histDeltaPtVsPtGen"), ptReco, deltaPt); histomc.fill(HIST("histPIDtrack"), ptReco, track.pidForTracking()); - - int pidGuess = track.pidForTracking(); - int antitriton = 6; - if (pidGuess == antitriton) { - histomc.fill(HIST("histdetapttriton"), ptReco, deltaPt); - } - } - if (pdg == -particlePdgCodes.at(5)) { - histomc.fill(HIST("histDeltaPtVsPtGenHe4anti"), ptReco, deltaPt); - histomc.fill(HIST("histPIDtrackantihe4"), ptReco, track.pidForTracking()); - } - if (pdg == particlePdgCodes.at(5)) { - histomc.fill(HIST("histDeltaPtVsPtGenHe4"), ptReco, deltaPt); - histomc.fill(HIST("histPIDtrackhe4"), ptReco, track.pidForTracking()); } } } @@ -1005,9 +910,6 @@ struct NucleitpcPbPb { } PROCESS_SWITCH(NucleitpcPbPb, processMC, "MC reco+gen analysis with efficiency corrections", false); //=-=-=-==-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= - //---------------------------------------------------------------------------------------------------------------- - // MC particles - DCA secondary fraction - //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= void processDCA(CollisionsFullMC const& collisions, aod::McCollisions const& mcCollisions, aod::McParticles const& particlesMC, @@ -1034,9 +936,6 @@ struct NucleitpcPbPb { if (collision.centFT0C() > centcut) continue; - // Additional cuts - if (removeITSROFrameBorder && !collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) - continue; if (removeNoSameBunchPileup && !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) continue; if (requireIsGoodZvtxFT0vsPV && !collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) @@ -1086,11 +985,6 @@ struct NucleitpcPbPb { continue; int pdg = matchedMCParticle.pdgCode(); - bool isHe3 = (std::abs(pdg) == particlePdgCodes.at(4)); - bool isHe4 = (std::abs(pdg) == particlePdgCodes.at(5)); - - if (!isHe3 && !isHe4) - continue; if (!track.isPVContributor() && cfgUsePVcontributors) continue; @@ -1108,14 +1002,15 @@ struct NucleitpcPbPb { if (std::abs(pdg) != std::abs(particlePdgCodes.at(i))) continue; + if (cfgTrackPIDsettings2->get(i, "fillsparsh") != 1) + continue; + float ptReco; setTrackParCov(track, mTrackParCov); mTrackParCov.setPID(track.pidForTracking()); ptReco = (std::abs(pdg) == particlePdgCodes.at(4) || std::abs(pdg) == particlePdgCodes.at(5)) ? 2 * mTrackParCov.getPt() : mTrackParCov.getPt(); - int particleAnti = (pdg > 0) ? 0 : 1; - double a = 0, b = 0, c = 0; int param = -1; @@ -1199,67 +1094,23 @@ struct NucleitpcPbPb { decayType = 2; } - if (i == he3) { - if (pdg == particlePdgCodes.at(4)) { // He3 - histomc.fill(HIST("DCAxy_vs_pT_He3_total"), ptReco, track.dcaXY()); - if (decayType == 2) { // Transport/Material - histomc.fill(HIST("DCAxy_vs_pT_He3_transport"), ptReco, track.dcaXY()); - } else if (decayType == 1) { // Weak decay (including HF) - histomc.fill(HIST("DCAxy_vs_pT_He3_weakdecay"), ptReco, track.dcaXY()); - } - } else if (pdg == -particlePdgCodes.at(4)) { // anti-He3 - histomc.fill(HIST("DCAxy_vs_pT_antiHe3_total"), ptReco, track.dcaXY()); - } - } - - bool insideDCAxy = false; - - if (cfgUseNewDCAxyCut) { - double sigmaFactor = cfgTrackPIDsettings->get(i, "maxDcaXY"); - double sigma_base = (0.0118 * std::exp(-0.6889 * ptReco) + 0.0017); - double sigma_new = sigmaFactor * sigma_base; - - insideDCAxy = (std::abs(track.dcaXY()) <= sigma_new); - } else { - insideDCAxy = - cfgdcaxynopt - ? (std::abs(track.dcaXY()) <= cfgTrackPIDsettings->get(i, "maxDcaXY")) - : (std::abs(track.dcaXY()) <= - (cfgTrackPIDsettings->get(i, "maxDcaXY") * - (0.0105f + 0.0350f / std::pow(ptReco, 1.1f)))); - } - - bool insideDCAz = false; - - if (cfgUseNewDCAzCut) { - - double sigmaFactorZ = cfgTrackPIDsettings->get(i, "maxDcaZ"); - - double p0 = 0.1014; - double p1 = 1.7512; - double p2 = 0.0024; - - double sigma_base_z = p0 * std::exp(-p1 * ptReco) + p2; + float ptDCA; - double sigma_new_z = sigmaFactorZ * sigma_base_z; - - insideDCAz = (std::abs(track.dcaZ()) <= sigma_new_z); + if (i == he3 || i == he4) { + ptDCA = ptReco; } else { - insideDCAz = (std::abs(track.dcaZ()) <= cfgTrackPIDsettings->get(i, "maxDcaZ")); + ptDCA = 2 * ptReco; } - if ((!insideDCAxy || !insideDCAz)) { - continue; - } - - float ptTOF = -1.0; // Default: no TOF - if (track.hasTOF()) { - ptTOF = ptReco; - } - - if (cfgTrackPIDsettings2->get(i, "fillsparsh") == 1) { - histomc.fill(HIST("hSpectraDCA"), i, particleAnti, collision.centFT0C(), - ptReco, ptTOF, decayType, track.dcaXY()); + if (pdg == particlePdgCodes.at(i)) { // He3 + histomc.fill(HIST("DCAxy_vs_pT_total"), ptDCA, track.dcaXY(), collision.centFT0C()); + if (decayType == 2) { // Transport/Material + histomc.fill(HIST("DCAxy_vs_pT_transport"), ptDCA, track.dcaXY(), collision.centFT0C()); + } else if (decayType == 1) { // Weak decay (including HF) + histomc.fill(HIST("DCAxy_vs_pT_weakdecay"), ptDCA, track.dcaXY(), collision.centFT0C()); + } + } else if (pdg == -particlePdgCodes.at(i)) { // anti-He3 + histomc.fill(HIST("DCAxy_vs_pT_anti_total"), ptDCA, track.dcaXY(), collision.centFT0C()); } } } @@ -1392,7 +1243,6 @@ struct NucleitpcPbPb { return; } - // Get pT similar to fillhmass float ptMomn; setTrackParCov(track, mTrackParCov); mTrackParCov.setPID(track.pidForTracking()); From 6fdda133ab72ec204e238d6d997c17c50598bba1 Mon Sep 17 00:00:00 2001 From: nzardosh Date: Mon, 23 Feb 2026 14:02:42 +0000 Subject: [PATCH 040/347] fixing background candidate rejection in jet finder (#15117) --- PWGJE/JetFinders/jetFinderHF.h | 16 +++++++--------- PWGJE/JetFinders/jetFinderHFHFBar.h | 12 +++++------- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/PWGJE/JetFinders/jetFinderHF.h b/PWGJE/JetFinders/jetFinderHF.h index 494f793cbaf..47289f4691f 100644 --- a/PWGJE/JetFinders/jetFinderHF.h +++ b/PWGJE/JetFinders/jetFinderHF.h @@ -210,7 +210,7 @@ struct JetFinderHFTask { o2::framework::PresliceOptional> perDielectronMcCandidate = o2::aod::bkgdielectronmc::candidateId; // function that generalically processes Data and reco level events - template + template void analyseCharged(T const& collision, U const& tracks, V const& candidate, M& jetsTableInput, N& constituentsTableInput, O& /*originalTracks*/, float minJetPt, float maxJetPt) { if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections) || !jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { @@ -218,13 +218,11 @@ struct JetFinderHFTask { } inputParticles.clear(); - if constexpr (jetcandidateutilities::isCandidate()) { + if constexpr (!isMC) { if (!jetfindingutilities::analyseCandidate(inputParticles, candidate, candPtMin, candPtMax, candYMin, candYMax)) { return; } - } - - if constexpr (jetcandidateutilities::isMcCandidate()) { + } else { if (!jetfindingutilities::analyseCandidateMC(inputParticles, candidate, candPtMin, candPtMax, candYMin, candYMax, rejectBackgroundMCDCandidates)) { return; } @@ -269,7 +267,7 @@ struct JetFinderHFTask { void processChargedJetsData(o2::soa::Filtered::iterator const& collision, o2::soa::Filtered const& tracks, CandidateTableData const& candidates) { for (typename CandidateTableData::iterator const& candidate : candidates) { // why can the type not be auto? try const auto - analyseCharged(collision, tracks, candidate, jetsTable, constituentsTable, tracks, jetPtMin, jetPtMax); + analyseCharged(collision, tracks, candidate, jetsTable, constituentsTable, tracks, jetPtMin, jetPtMax); } } PROCESS_SWITCH(JetFinderHFTask, processChargedJetsData, "charged hf jet finding on data", false); @@ -277,7 +275,7 @@ struct JetFinderHFTask { void processChargedEvtWiseSubJetsData(o2::soa::Filtered::iterator const& collision, o2::soa::Filtered const& tracks, CandidateTableData const& candidates) { for (typename CandidateTableData::iterator const& candidate : candidates) { - analyseCharged(collision, jetcandidateutilities::slicedPerCandidate(tracks, candidate, perD0Candidate, perDplusCandidate, perDsCandidate, perDstarCandidate, perLcCandidate, perB0Candidate, perBplusCandidate, perXicToXiPiPiCandidate, perDielectronCandidate), candidate, jetsEvtWiseSubTable, constituentsEvtWiseSubTable, tracks, jetEWSPtMin, jetEWSPtMax); + analyseCharged(collision, jetcandidateutilities::slicedPerCandidate(tracks, candidate, perD0Candidate, perDplusCandidate, perDsCandidate, perDstarCandidate, perLcCandidate, perB0Candidate, perBplusCandidate, perXicToXiPiPiCandidate, perDielectronCandidate), candidate, jetsEvtWiseSubTable, constituentsEvtWiseSubTable, tracks, jetEWSPtMin, jetEWSPtMax); } } PROCESS_SWITCH(JetFinderHFTask, processChargedEvtWiseSubJetsData, "charged hf jet finding on data with event-wise constituent subtraction", false); @@ -285,7 +283,7 @@ struct JetFinderHFTask { void processChargedJetsMCD(o2::soa::Filtered::iterator const& collision, o2::soa::Filtered const& tracks, CandidateTableMCD const& candidates) { for (typename CandidateTableMCD::iterator const& candidate : candidates) { - analyseCharged(collision, tracks, candidate, jetsTable, constituentsTable, tracks, jetPtMin, jetPtMax); + analyseCharged(collision, tracks, candidate, jetsTable, constituentsTable, tracks, jetPtMin, jetPtMax); } } PROCESS_SWITCH(JetFinderHFTask, processChargedJetsMCD, "charged hf jet finding on MC detector level", false); @@ -293,7 +291,7 @@ struct JetFinderHFTask { void processChargedEvtWiseSubJetsMCD(o2::soa::Filtered::iterator const& collision, o2::soa::Filtered const& tracks, CandidateTableMCD const& candidates) { for (typename CandidateTableMCD::iterator const& candidate : candidates) { - analyseCharged(collision, jetcandidateutilities::slicedPerCandidate(tracks, candidate, perD0Candidate, perDplusCandidate, perDsCandidate, perDstarCandidate, perLcCandidate, perB0Candidate, perBplusCandidate, perXicToXiPiPiCandidate, perDielectronCandidate), candidate, jetsEvtWiseSubTable, constituentsEvtWiseSubTable, tracks, jetEWSPtMin, jetEWSPtMax); + analyseCharged(collision, jetcandidateutilities::slicedPerCandidate(tracks, candidate, perD0Candidate, perDplusCandidate, perDsCandidate, perDstarCandidate, perLcCandidate, perB0Candidate, perBplusCandidate, perXicToXiPiPiCandidate, perDielectronCandidate), candidate, jetsEvtWiseSubTable, constituentsEvtWiseSubTable, tracks, jetEWSPtMin, jetEWSPtMax); } } PROCESS_SWITCH(JetFinderHFTask, processChargedEvtWiseSubJetsMCD, "charged hf jet finding on MC detector level with event-wise constituent subtraction", false); diff --git a/PWGJE/JetFinders/jetFinderHFHFBar.h b/PWGJE/JetFinders/jetFinderHFHFBar.h index 4173008f0f0..28d3a4000bf 100644 --- a/PWGJE/JetFinders/jetFinderHFHFBar.h +++ b/PWGJE/JetFinders/jetFinderHFHFBar.h @@ -208,7 +208,7 @@ struct JetFinderHFHFBarTask { o2::framework::PresliceOptional> perDielectronMcCandidate = o2::aod::bkgdielectronmc::candidateId; // function that generalically processes Data and reco level events - template + template void analyseCharged(T const& collision, U const& tracks, V const& candidate, V const& candidateBar, M& jetsTableInput, N& constituentsTableInput, O& /*originalTracks*/, float minJetPt, float maxJetPt) { if (candidate.globalIndex() == candidateBar.globalIndex() || candidate.candidateSelFlag() == candidateBar.candidateSelFlag()) { @@ -224,13 +224,11 @@ struct JetFinderHFHFBarTask { } inputParticles.clear(); - if constexpr (jetcandidateutilities::isCandidate()) { + if constexpr (!isMC) { if (!jetfindingutilities::analyseCandidate(inputParticles, candidate, candPtMin, candPtMax, candYMin, candYMax) || !jetfindingutilities::analyseCandidate(inputParticles, candidateBar, candPtMin, candPtMax, candYMin, candYMax)) { return; } - } - - if constexpr (jetcandidateutilities::isMcCandidate()) { + } else { if (!jetfindingutilities::analyseCandidateMC(inputParticles, candidate, candPtMin, candPtMax, candYMin, candYMax, rejectBackgroundMCDCandidates) || !jetfindingutilities::analyseCandidateMC(inputParticles, candidateBar, candPtMin, candPtMax, candYMin, candYMax, rejectBackgroundMCDCandidates)) { return; } @@ -282,7 +280,7 @@ struct JetFinderHFHFBarTask { for (; candidateBarIterator != candidates.end(); ++candidateBarIterator) { typename CandidateTableData::iterator const& candidate = *candidateIterator; typename CandidateTableData::iterator const& candidateBar = *candidateBarIterator; - analyseCharged(collision, tracks, candidate, candidateBar, jetsTable, constituentsTable, tracks, jetPtMin, jetPtMax); + analyseCharged(collision, tracks, candidate, candidateBar, jetsTable, constituentsTable, tracks, jetPtMin, jetPtMax); } } } @@ -296,7 +294,7 @@ struct JetFinderHFHFBarTask { for (; candidateBarIterator != candidates.end(); ++candidateBarIterator) { typename CandidateTableMCD::iterator const& candidate = *candidateIterator; typename CandidateTableMCD::iterator const& candidateBar = *candidateBarIterator; - analyseCharged(collision, tracks, candidate, candidateBar, jetsTable, constituentsTable, tracks, jetPtMin, jetPtMax); + analyseCharged(collision, tracks, candidate, candidateBar, jetsTable, constituentsTable, tracks, jetPtMin, jetPtMax); } } } From 4fbdd134086f6bb874b16df5f9f99c8c809d54d6 Mon Sep 17 00:00:00 2001 From: Giorgio Alberto Lucia <87222843+GiorgioAlbertoLucia@users.noreply.github.com> Date: Mon, 23 Feb 2026 16:13:18 +0100 Subject: [PATCH 041/347] [PWGLF] missing absolute value for kstar resolution (#15068) --- PWGLF/TableProducer/Nuspex/he3HadronFemto.cxx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/PWGLF/TableProducer/Nuspex/he3HadronFemto.cxx b/PWGLF/TableProducer/Nuspex/he3HadronFemto.cxx index b960cd49ba8..029b8e95b89 100644 --- a/PWGLF/TableProducer/Nuspex/he3HadronFemto.cxx +++ b/PWGLF/TableProducer/Nuspex/he3HadronFemto.cxx @@ -966,11 +966,11 @@ struct he3HadronFemto { mQaRegistry.fill(HIST("Had/hChi2NClHadITS"), he3Hadcand.chi2nclITSHad); if (isMc) { - const float correctedPtHe3 = correctPtHe3TrackedAsTriton(he3Hadcand.recoPtHe3(), he3Hadcand.pidtrkHe3); - const float kstarGen = getkstar(he3Hadcand.momHe3MC, he3Hadcand.etaHe3MC, he3Hadcand.phiHe3MC, o2::constants::physics::MassHelium3, 1., - he3Hadcand.momHadMC, he3Hadcand.etaHadMC, he3Hadcand.phiHadMC, settingHadPDGCode == PDG_t::kPiPlus ? o2::constants::physics::MassPiPlus : o2::constants::physics::MassProton, 1.); - const float kstarRec = getkstar(correctedPtHe3, he3Hadcand.recoEtaHe3(), he3Hadcand.recoPhiHe3(), o2::constants::physics::MassHelium3, 1., - he3Hadcand.recoPtHad(), he3Hadcand.recoEtaHad(), he3Hadcand.recoPhiHad(), settingHadPDGCode == PDG_t::kPiPlus ? o2::constants::physics::MassPiPlus : o2::constants::physics::MassProton, 1.); + const float correctedPtHe3 = correctPtHe3TrackedAsTriton(std::abs(he3Hadcand.recoPtHe3()), he3Hadcand.pidtrkHe3); + const float kstarGen = getkstar(std::abs(he3Hadcand.momHe3MC), he3Hadcand.etaHe3MC, he3Hadcand.phiHe3MC, o2::constants::physics::MassHelium3, 1., + std::abs(he3Hadcand.momHadMC), he3Hadcand.etaHadMC, he3Hadcand.phiHadMC, settingHadPDGCode == PDG_t::kPiPlus ? o2::constants::physics::MassPiPlus : o2::constants::physics::MassProton, 1.); + const float kstarRec = getkstar(std::abs(correctedPtHe3), he3Hadcand.recoEtaHe3(), he3Hadcand.recoPhiHe3(), o2::constants::physics::MassHelium3, 1., + std::abs(he3Hadcand.recoPtHad()), he3Hadcand.recoEtaHad(), he3Hadcand.recoPhiHad(), settingHadPDGCode == PDG_t::kPiPlus ? o2::constants::physics::MassPiPlus : o2::constants::physics::MassProton, 1.); mQaRegistry.fill(HIST("hKstarRecVsKstarGen"), kstarGen, kstarRec); } } From ec2ac4c95ad084b62b3dab78b9fdfda901511d20 Mon Sep 17 00:00:00 2001 From: Swati <69241911+SwatiSaha-1997@users.noreply.github.com> Date: Mon, 23 Feb 2026 21:10:56 +0530 Subject: [PATCH 042/347] [PWGCF] Add multiplicity correlation cut in MC process (#15116) --- .../Tasks/MeanptFluctuations.cxx | 55 ++++++++++++++----- 1 file changed, 42 insertions(+), 13 deletions(-) diff --git a/PWGCF/EbyEFluctuations/Tasks/MeanptFluctuations.cxx b/PWGCF/EbyEFluctuations/Tasks/MeanptFluctuations.cxx index 6a9707cacb2..a517e00f62a 100644 --- a/PWGCF/EbyEFluctuations/Tasks/MeanptFluctuations.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/MeanptFluctuations.cxx @@ -152,6 +152,8 @@ struct MeanptFluctuationsAnalysis { using MyMCTracks = soa::Filtered>; using EventCandidatesMC = soa::Join; + Preslice perCollision = aod::track::collisionId; + // Event selection cuts - Alex TF1* fMultPVCutLow = nullptr; TF1* fMultPVCutHigh = nullptr; @@ -170,6 +172,7 @@ struct MeanptFluctuationsAnalysis { AxisSpec ptAxis = {ptBinning, "#it{p}_{T} (GeV/#it{c})"}; // Add histograms to histogram manager (as in the output object of in AliPhysics) + histos.add("hEventStatData", "Data Event statistics", kTH1F, {{10, 0.0f, 10.0f}}); histos.add("hZvtx_after_sel", ";Z (cm)", kTH1F, {vtxZAxis}); histos.add("hP", ";#it{p} (GeV/#it{c})", kTH1F, {{35, 0.2, 4.}}); histos.add("hPt", ";#it{p}_{T} (GeV/#it{c})", kTH1F, {ptAxis}); @@ -376,26 +379,40 @@ struct MeanptFluctuationsAnalysis { } template - void eventSelectionDefaultCuts(TCollision coll) + bool eventSelectionDefaultCuts(TCollision coll) { + histos.fill(HIST("hEventStatData"), 0.5); if (!coll.sel8()) { - return; + return 0; } + + histos.fill(HIST("hEventStatData"), 1.5); if (cfgUseGoodITSLayerAllCut && !(coll.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll))) { - return; + return 0; } + + histos.fill(HIST("hEventStatData"), 2.5); if (cfgEvSelkNoSameBunchPileup && !(coll.selection_bit(o2::aod::evsel::kNoSameBunchPileup))) { - return; + return 0; } + + histos.fill(HIST("hEventStatData"), 3.5); if (cfgEvSelkNoITSROFrameBorder && !(coll.selection_bit(o2::aod::evsel::kNoITSROFrameBorder))) { - return; + return 0; } + + histos.fill(HIST("hEventStatData"), 4.5); if (cfgEvSelkNoTimeFrameBorder && !(coll.selection_bit(o2::aod::evsel::kNoTimeFrameBorder))) { - return; + return 0; } + + histos.fill(HIST("hEventStatData"), 5.5); if (cfgEvSelUseGoodZvtxFT0vsPV && !(coll.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV))) { - return; + return 0; } + + histos.fill(HIST("hEventStatData"), 6.5); + return 1; } template @@ -461,11 +478,12 @@ struct MeanptFluctuationsAnalysis { if (cfgEvSelUseGoodZvtxFT0vsPV && !(collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV))) { continue; } - if (cfgUseSmallIonAdditionalEventCutInMC && !eventSelectedSmallion(collision, tracks.size(), cent)) { - continue; - } + auto rectrackspart = tracks.sliceBy(perCollision, collision.globalIndex()); cent = collision.centFT0C(); + if (cfgUseSmallIonAdditionalEventCutInMC && !eventSelectedSmallion(collision, rectrackspart.size(), cent)) { + continue; + } selectedEvents[nevts++] = collision.mcCollision_as().globalIndex(); } @@ -554,10 +572,17 @@ struct MeanptFluctuationsAnalysis { void processMCRec(MyMCRecCollisions::iterator const& collision, MyMCTracks const& tracks, aod::McCollisions const&, aod::McParticles const&) { + histos.fill(HIST("MCGenerated/hMC"), 5.5); + if (!collision.has_mcCollision()) { return; } - eventSelectionDefaultCuts(collision); + histos.fill(HIST("MCGenerated/hMC"), 6.5); + + if (!eventSelectionDefaultCuts(collision)) { + return; + } + histos.fill(HIST("MCGenerated/hMC"), 7.5); fillMultCorrPlotsBeforeSel(collision, tracks); @@ -571,7 +596,7 @@ struct MeanptFluctuationsAnalysis { fillMultCorrPlotsAfterSel(collision, tracks); } - histos.fill(HIST("MCGenerated/hMC"), 5.5); + histos.fill(HIST("MCGenerated/hMC"), 8.5); histos.fill(HIST("hZvtx_after_sel"), collision.posZ()); double cent = 0.0; @@ -688,7 +713,9 @@ struct MeanptFluctuationsAnalysis { // void process(aod::Collision const& coll, aod::Tracks const& inputTracks) void processData(AodCollisions::iterator const& coll, aod::BCsWithTimestamps const&, AodTracks const& inputTracks) { - eventSelectionDefaultCuts(coll); + if (!eventSelectionDefaultCuts(coll)) { + return; + } fillMultCorrPlotsBeforeSel(coll, inputTracks); @@ -702,6 +729,8 @@ struct MeanptFluctuationsAnalysis { fillMultCorrPlotsAfterSel(coll, inputTracks); } + histos.fill(HIST("hEventStatData"), 7.5); + histos.fill(HIST("hZvtx_after_sel"), coll.posZ()); double cent = 0.0; From b4fe5ecf2bb99640ca81f120ca6ed8a73555db37 Mon Sep 17 00:00:00 2001 From: Jesper Karlsson Gumprecht <113693781+jesgum@users.noreply.github.com> Date: Mon, 23 Feb 2026 17:14:21 +0100 Subject: [PATCH 043/347] [ALICE3] Update A3 Multi-charm (#15118) --- ALICE3/DataModel/OTFMulticharm.h | 50 --- .../TableProducer/alice3MulticharmFinder.cxx | 305 +++++++++--------- ALICE3/Tasks/alice3Multicharm.cxx | 82 +---- 3 files changed, 151 insertions(+), 286 deletions(-) diff --git a/ALICE3/DataModel/OTFMulticharm.h b/ALICE3/DataModel/OTFMulticharm.h index 944aa578ab2..5c4224bdce5 100644 --- a/ALICE3/DataModel/OTFMulticharm.h +++ b/ALICE3/DataModel/OTFMulticharm.h @@ -75,31 +75,6 @@ DECLARE_SOA_COLUMN(XicProperLength, xicProperLength, float); DECLARE_SOA_COLUMN(XicDistanceFromPV, xicDistanceFromPV, float); DECLARE_SOA_COLUMN(XiccProperLength, xiccProperLength, float); -// PID -DECLARE_SOA_COLUMN(Pi1cTofDeltaInner, pi1cTofDeltaInner, float); -DECLARE_SOA_COLUMN(Pi1cTofNSigmaInner, pi1cTofNSigmaInner, float); -DECLARE_SOA_COLUMN(Pi1cTofDeltaOuter, pi1cTofDeltaOuter, float); -DECLARE_SOA_COLUMN(Pi1cTofNSigmaOuter, pi1cTofNSigmaOuter, float); -DECLARE_SOA_COLUMN(Pi1cHasRichSignal, pi1cHasRichSignal, bool); -DECLARE_SOA_COLUMN(Pi1cRichNSigma, pi1cRichNSigma, float); -DECLARE_SOA_COLUMN(Pi1cPdgCode, pi1cPdgCode, int); - -DECLARE_SOA_COLUMN(Pi2cTofDeltaInner, pi2cTofDeltaInner, float); -DECLARE_SOA_COLUMN(Pi2cTofNSigmaInner, pi2cTofNSigmaInner, float); -DECLARE_SOA_COLUMN(Pi2cTofDeltaOuter, pi2cTofDeltaOuter, float); -DECLARE_SOA_COLUMN(Pi2cTofNSigmaOuter, pi2cTofNSigmaOuter, float); -DECLARE_SOA_COLUMN(Pi2cHasRichSignal, pi2cHasRichSignal, bool); -DECLARE_SOA_COLUMN(Pi2cRichNSigma, pi2cRichNSigma, float); -DECLARE_SOA_COLUMN(Pi2cPdgCode, pi2cPdgCode, int); - -DECLARE_SOA_COLUMN(PiccTofDeltaInner, piccTofDeltaInner, float); -DECLARE_SOA_COLUMN(PiccTofNSigmaInner, piccTofNSigmaInner, float); -DECLARE_SOA_COLUMN(PiccTofDeltaOuter, piccTofDeltaOuter, float); -DECLARE_SOA_COLUMN(PiccTofNSigmaOuter, piccTofNSigmaOuter, float); -DECLARE_SOA_COLUMN(PiccHasRichSignal, piccHasRichSignal, bool); -DECLARE_SOA_COLUMN(PiccRichNSigma, piccRichNSigma, float); -DECLARE_SOA_COLUMN(PiccPdgCode, piccPdgCode, int); - // Daughter info DECLARE_SOA_COLUMN(PosPt, posPt, float); DECLARE_SOA_COLUMN(PosEta, posEta, float); @@ -159,31 +134,6 @@ DECLARE_SOA_TABLE(MCharmCores, "AOD", "MCharmCores", otfmulticharm::PiccPt, otfmulticharm::LUTConfigId); -DECLARE_SOA_TABLE(MCharmPID, "AOD", "MCharmPID", - otfmulticharm::Pi1cTofDeltaInner, - otfmulticharm::Pi1cTofNSigmaInner, - otfmulticharm::Pi1cTofDeltaOuter, - otfmulticharm::Pi1cTofNSigmaOuter, - otfmulticharm::Pi1cHasRichSignal, - otfmulticharm::Pi1cRichNSigma, - otfmulticharm::Pi1cPdgCode, - - otfmulticharm::Pi2cTofDeltaInner, - otfmulticharm::Pi2cTofNSigmaInner, - otfmulticharm::Pi2cTofDeltaOuter, - otfmulticharm::Pi2cTofNSigmaOuter, - otfmulticharm::Pi2cHasRichSignal, - otfmulticharm::Pi2cRichNSigma, - otfmulticharm::Pi2cPdgCode, - - otfmulticharm::PiccTofDeltaInner, - otfmulticharm::PiccTofNSigmaInner, - otfmulticharm::PiccTofDeltaOuter, - otfmulticharm::PiccTofNSigmaOuter, - otfmulticharm::PiccHasRichSignal, - otfmulticharm::PiccRichNSigma, - otfmulticharm::PiccPdgCode); - DECLARE_SOA_TABLE(MCharmExtra, "AOD", "MCharmExtra", otfmulticharm::BachPt, otfmulticharm::BachEta, diff --git a/ALICE3/TableProducer/alice3MulticharmFinder.cxx b/ALICE3/TableProducer/alice3MulticharmFinder.cxx index 9b636b03bb4..e66708bd911 100644 --- a/ALICE3/TableProducer/alice3MulticharmFinder.cxx +++ b/ALICE3/TableProducer/alice3MulticharmFinder.cxx @@ -28,6 +28,7 @@ #include "ALICE3/DataModel/OTFTOF.h" #include "ALICE3/DataModel/tracksAlice3.h" #include "Common/Core/RecoDecay.h" +#include "Common/Core/TableHelper.h" #include "Common/Core/TrackSelection.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/TrackSelectionTables.h" @@ -69,7 +70,7 @@ using namespace o2::framework::expressions; #define GET_HIST(type, name) std::get>(histPointers[name]) #define INSERT_HIST(name, ...) histPointers[name] = histos.add((name).c_str(), __VA_ARGS__); -using Alice3Tracks = soa::Join; +using Alice3Tracks = soa::Join; using Alice3Collision = soa::Join::iterator; struct Alice3MulticharmFinder { @@ -77,12 +78,18 @@ struct Alice3MulticharmFinder { Produces multiCharmIdx; Produces multiCharmCore; - Produces multiCharmPID; Produces multiCharmExtra; // Operation and minimisation criteria - Configurable fillDerivedTable{"fillDerivedTable", false, "fill MCharm[] tables (careful: memory)"}; - Configurable magneticField{"magneticField", 20.0f, "Magnetic field (in kilogauss)"}; + + struct : ConfigurableGroup { + std::string prefix = "derivedTable"; // JSON group name + Configurable fillMCharmIdx{"fillMCharmIdx", true, "fill MCharmIdx[] tables (careful: memory)"}; + Configurable fillMCharmCore{"fillMCharmCore", true, "fill MCharmCores[] tables (careful: memory)"}; + Configurable fillMCharmExtra{"fillMCharmExtra", false, "fill MCharmExtra[] tables (careful: memory)"}; + } derivedTable; // allows for gap between peak and bg in case someone wants to + + Configurable cfgMagneticField{"cfgMagneticField", 20.0f, "Magnetic field (in kilogauss) if value not found from geo provider"}; Configurable doDCAplots{"doDCAplots", true, "do daughter prong DCA plots for D mesons"}; Configurable mcSameMotherCheck{"mcSameMotherCheck", true, "check if tracks come from the same MC mother"}; Configurable> minNTracks{"minNTracks", {-1}, "Minimum number of tracks"}; @@ -94,7 +101,6 @@ struct Alice3MulticharmFinder { Configurable xiMinDecayRadius{"xiMinDecayRadius", 0.5, "Minimum R2D for XiC decay (cm)"}; Configurable xiMassWindow{"xiMassWindow", 0.005, "Mass window around Xi peak (GeV/c)"}; - Configurable picTofDiffInner{"picTofDiffInner", 99999, "|signal - expected| (ps)"}; Configurable picMinConstDCAxy{"picMinConstDCAxy", 0.0005f, "[0] in |DCAxy| > [0]+[1]/pT"}; Configurable picMinConstDCAz{"picMinConstDCAz", 0.0005f, "[0] in |DCAxy| > [0]+[1]/pT"}; Configurable picMinPtDepDCAxy{"picMinPtDepDCAxy", 0.0, "[1] in |DCAxy| > [0]+[1]/pT"}; @@ -110,7 +116,6 @@ struct Alice3MulticharmFinder { Configurable xicMaxProperLength{"xicMaxProperLength", 0.1, "Minimum proper length for XiC decay (cm)"}; Configurable xicMassWindow{"xicMassWindow", 0.012, "Mass window around XiC peak (GeV/c)"}; - Configurable piccTofDiffInner{"piccTofDiffInner", 99999, "|signal - expected| (ps)"}; Configurable piccMinConstDCAxy{"piccMinConstDCAxy", 0.0005f, "[0] in |DCAxy| > [0]+[1]/pT"}; Configurable piccMinConstDCAz{"piccMinConstDCAz", 0.0005f, "[0] in |DCAxy| > [0]+[1]/pT"}; Configurable piccMinPtDepDCAxy{"piccMinPtDepDCAxy", 0.0, "[1] in |DCAxy| > [0]+[1]/pT"}; @@ -154,11 +159,12 @@ struct Alice3MulticharmFinder { // Constants static constexpr std::array MomentumIndices = {9, 13, 14, 18, 19, 20}; // cov matrix elements for momentum component + static constexpr float ToMicrons = 1e+4; - static constexpr float toMicrons = 1e+4; // filter expressions for pions static constexpr uint32_t TrackSelectionPic = 1 << kInnerTOFPion | 1 << kOuterTOFPion | 1 << kRICHPion | 1 << kTruePiFromXiC; static constexpr uint32_t TrackSelectionPicc = 1 << kInnerTOFPion | 1 << kOuterTOFPion | 1 << kRICHPion | 1 << kTruePiFromXiCC; + float magneticField{}; // partitions Partition trueXi = aod::mcparticle::pdgCode == static_cast(PDG_t::kXiMinus); @@ -183,7 +189,7 @@ struct Alice3MulticharmFinder { std::array prong1mom; std::array prong2mom; std::array parentTrackCovMatrix; - } thisXiCcandidate; + } thisXicCandidate; struct { float dca; @@ -198,7 +204,7 @@ struct Alice3MulticharmFinder { // charm daughters int nSiliconHitsPiCC; int nTPCHitsPiCC; - } thisXiCCcandidate; + } thisXiccCandidate; struct ProngInfo { float pt = 1e+10; @@ -225,18 +231,18 @@ struct Alice3MulticharmFinder { o2::track::TrackParCov t0new = fitter.getTrack(0); o2::track::TrackParCov t1new = fitter.getTrack(1); - t0new.getPxPyPzGlo(thisXiCCcandidate.prong0mom); - t1new.getPxPyPzGlo(thisXiCCcandidate.prong1mom); + t0new.getPxPyPzGlo(thisXiccCandidate.prong0mom); + t1new.getPxPyPzGlo(thisXiccCandidate.prong1mom); // get decay vertex coordinates const auto& vtx = fitter.getPCACandidate(); - for (size_t i = 0; i < thisXiCCcandidate.xyz.size(); i++) { - thisXiCCcandidate.xyz[i] = vtx[i]; + for (size_t i = 0; i < thisXiccCandidate.xyz.size(); i++) { + thisXiccCandidate.xyz[i] = vtx[i]; } // compute cov mat for (int ii = 0; ii < o2::track::kLabCovMatSize; ii++) { - thisXiCCcandidate.parentTrackCovMatrix[ii] = 0.0f; + thisXiccCandidate.parentTrackCovMatrix[ii] = 0.0f; } std::array covA = {0}; @@ -246,31 +252,31 @@ struct Alice3MulticharmFinder { for (size_t i = 0; i < MomentumIndices.size(); i++) { int j = MomentumIndices[i]; - thisXiCCcandidate.parentTrackCovMatrix[j] = covA[j] + covB[j]; + thisXiccCandidate.parentTrackCovMatrix[j] = covA[j] + covB[j]; } auto covVtx = fitter.calcPCACovMatrix(); - thisXiCCcandidate.parentTrackCovMatrix[0] = covVtx(0, 0); - thisXiCCcandidate.parentTrackCovMatrix[1] = covVtx(1, 0); - thisXiCCcandidate.parentTrackCovMatrix[2] = covVtx(1, 1); - thisXiCCcandidate.parentTrackCovMatrix[3] = covVtx(2, 0); - thisXiCCcandidate.parentTrackCovMatrix[4] = covVtx(2, 1); - thisXiCCcandidate.parentTrackCovMatrix[5] = covVtx(2, 2); + thisXiccCandidate.parentTrackCovMatrix[0] = covVtx(0, 0); + thisXiccCandidate.parentTrackCovMatrix[1] = covVtx(1, 0); + thisXiccCandidate.parentTrackCovMatrix[2] = covVtx(1, 1); + thisXiccCandidate.parentTrackCovMatrix[3] = covVtx(2, 0); + thisXiccCandidate.parentTrackCovMatrix[4] = covVtx(2, 1); + thisXiccCandidate.parentTrackCovMatrix[5] = covVtx(2, 2); // set relevant values - thisXiCCcandidate.dca = std::sqrt(fitter.getChi2AtPCACandidate()); - if (thisXiCCcandidate.dca > xiccMaxDauDCA) { + thisXiccCandidate.dca = std::sqrt(fitter.getChi2AtPCACandidate()); + if (thisXiccCandidate.dca > xiccMaxDauDCA) { return false; } - thisXiCCcandidate.mass = RecoDecay::m(std::array{std::array{thisXiCCcandidate.prong0mom[0], thisXiCCcandidate.prong0mom[1], thisXiCCcandidate.prong0mom[2]}, std::array{thisXiCCcandidate.prong1mom[0], thisXiCCcandidate.prong1mom[1], thisXiCCcandidate.prong1mom[2]}}, std::array{mass0, mass1}); + thisXiccCandidate.mass = RecoDecay::m(std::array{std::array{thisXiccCandidate.prong0mom[0], thisXiccCandidate.prong0mom[1], thisXiccCandidate.prong0mom[2]}, std::array{thisXiccCandidate.prong1mom[0], thisXiccCandidate.prong1mom[1], thisXiccCandidate.prong1mom[2]}}, std::array{mass0, mass1}); - if (std::fabs(thisXiCCcandidate.mass - o2::constants::physics::MassXiCCPlusPlus) > xiccMassWindow) { + if (std::fabs(thisXiccCandidate.mass - o2::constants::physics::MassXiCCPlusPlus) > xiccMassWindow) { return false; } - thisXiCCcandidate.pt = std::hypot(thisXiCCcandidate.prong0mom[0] + thisXiCCcandidate.prong1mom[0], thisXiCCcandidate.prong0mom[1] + thisXiCCcandidate.prong1mom[1]); - thisXiCCcandidate.eta = RecoDecay::eta(std::array{thisXiCCcandidate.prong0mom[0] + thisXiCCcandidate.prong1mom[0], thisXiCCcandidate.prong0mom[1] + thisXiCCcandidate.prong1mom[1], thisXiCCcandidate.prong0mom[2] + thisXiCCcandidate.prong1mom[2]}); + thisXiccCandidate.pt = std::hypot(thisXiccCandidate.prong0mom[0] + thisXiccCandidate.prong1mom[0], thisXiccCandidate.prong0mom[1] + thisXiccCandidate.prong1mom[1]); + thisXiccCandidate.eta = RecoDecay::eta(std::array{thisXiccCandidate.prong0mom[0] + thisXiccCandidate.prong1mom[0], thisXiccCandidate.prong0mom[1] + thisXiccCandidate.prong1mom[1], thisXiccCandidate.prong0mom[2] + thisXiccCandidate.prong1mom[2]}); return true; } @@ -297,19 +303,19 @@ struct Alice3MulticharmFinder { t0 = fitter3.getTrack(0); t1 = fitter3.getTrack(1); t2 = fitter3.getTrack(2); - t0.getPxPyPzGlo(thisXiCcandidate.prong0mom); - t1.getPxPyPzGlo(thisXiCcandidate.prong1mom); - t2.getPxPyPzGlo(thisXiCcandidate.prong2mom); + t0.getPxPyPzGlo(thisXicCandidate.prong0mom); + t1.getPxPyPzGlo(thisXicCandidate.prong1mom); + t2.getPxPyPzGlo(thisXicCandidate.prong2mom); // get decay vertex coordinates const auto& vtx = fitter3.getPCACandidate(); - for (size_t i = 0; i < thisXiCcandidate.xyz.size(); i++) { - thisXiCcandidate.xyz[i] = vtx[i]; + for (size_t i = 0; i < thisXicCandidate.xyz.size(); i++) { + thisXicCandidate.xyz[i] = vtx[i]; } // compute cov mat for (int ii = 0; ii < o2::track::kLabCovMatSize; ii++) { - thisXiCcandidate.parentTrackCovMatrix[ii] = 0.0f; + thisXicCandidate.parentTrackCovMatrix[ii] = 0.0f; } std::array covA = {0}; @@ -321,35 +327,28 @@ struct Alice3MulticharmFinder { for (size_t i = 0; i < MomentumIndices.size(); i++) { int j = MomentumIndices[i]; - thisXiCcandidate.parentTrackCovMatrix[j] = covA[j] + covB[j] + covC[j]; + thisXicCandidate.parentTrackCovMatrix[j] = covA[j] + covB[j] + covC[j]; } auto covVtx = fitter3.calcPCACovMatrix(); - thisXiCcandidate.parentTrackCovMatrix[0] = covVtx(0, 0); - thisXiCcandidate.parentTrackCovMatrix[1] = covVtx(1, 0); - thisXiCcandidate.parentTrackCovMatrix[2] = covVtx(1, 1); - thisXiCcandidate.parentTrackCovMatrix[3] = covVtx(2, 0); - thisXiCcandidate.parentTrackCovMatrix[4] = covVtx(2, 1); - thisXiCcandidate.parentTrackCovMatrix[5] = covVtx(2, 2); + thisXicCandidate.parentTrackCovMatrix[0] = covVtx(0, 0); + thisXicCandidate.parentTrackCovMatrix[1] = covVtx(1, 0); + thisXicCandidate.parentTrackCovMatrix[2] = covVtx(1, 1); + thisXicCandidate.parentTrackCovMatrix[3] = covVtx(2, 0); + thisXicCandidate.parentTrackCovMatrix[4] = covVtx(2, 1); + thisXicCandidate.parentTrackCovMatrix[5] = covVtx(2, 2); // set relevant values - thisXiCcandidate.dca = std::sqrt(fitter3.getChi2AtPCACandidate()); - if (thisXiCcandidate.dca > xicMaxDauDCA) { + thisXicCandidate.dca = std::sqrt(fitter3.getChi2AtPCACandidate()); + if (thisXicCandidate.dca > xicMaxDauDCA) { return false; } - thisXiCcandidate.mass = RecoDecay::m(std::array{std::array{thisXiCcandidate.prong0mom[0], thisXiCcandidate.prong0mom[1], thisXiCcandidate.prong0mom[2]}, std::array{thisXiCcandidate.prong1mom[0], thisXiCcandidate.prong1mom[1], thisXiCcandidate.prong1mom[2]}, std::array{thisXiCcandidate.prong2mom[0], thisXiCcandidate.prong2mom[1], thisXiCcandidate.prong2mom[2]}}, std::array{p0mass, p1mass, p2mass}); - thisXiCcandidate.pt = std::hypot(thisXiCcandidate.prong0mom[0] + thisXiCcandidate.prong1mom[0] + thisXiCcandidate.prong2mom[0], thisXiCcandidate.prong0mom[1] + thisXiCcandidate.prong1mom[1] + thisXiCcandidate.prong2mom[1]); - thisXiCcandidate.eta = RecoDecay::eta(std::array{thisXiCcandidate.prong0mom[0] + thisXiCcandidate.prong1mom[0] + thisXiCcandidate.prong2mom[0], thisXiCcandidate.prong0mom[1] + thisXiCcandidate.prong1mom[1] + thisXiCcandidate.prong2mom[1], thisXiCcandidate.prong0mom[2] + thisXiCcandidate.prong1mom[2] + thisXiCcandidate.prong2mom[2]}); + thisXicCandidate.mass = RecoDecay::m(std::array{std::array{thisXicCandidate.prong0mom[0], thisXicCandidate.prong0mom[1], thisXicCandidate.prong0mom[2]}, std::array{thisXicCandidate.prong1mom[0], thisXicCandidate.prong1mom[1], thisXicCandidate.prong1mom[2]}, std::array{thisXicCandidate.prong2mom[0], thisXicCandidate.prong2mom[1], thisXicCandidate.prong2mom[2]}}, std::array{p0mass, p1mass, p2mass}); + thisXicCandidate.pt = std::hypot(thisXicCandidate.prong0mom[0] + thisXicCandidate.prong1mom[0] + thisXicCandidate.prong2mom[0], thisXicCandidate.prong0mom[1] + thisXicCandidate.prong1mom[1] + thisXicCandidate.prong2mom[1]); + thisXicCandidate.eta = RecoDecay::eta(std::array{thisXicCandidate.prong0mom[0] + thisXicCandidate.prong1mom[0] + thisXicCandidate.prong2mom[0], thisXicCandidate.prong0mom[1] + thisXicCandidate.prong1mom[1] + thisXicCandidate.prong2mom[1], thisXicCandidate.prong0mom[2] + thisXicCandidate.prong1mom[2] + thisXicCandidate.prong2mom[2]}); return true; } - template - int getPdgCodeForTrack(const TTrackType& track) - { - auto mcParticle = track.template mcParticle_as(); - return mcParticle.pdgCode(); - } - /// function to check if tracks have the same mother in MC template bool checkSameMother(TTrackType1 const& track1, TTrackType2 const& track2) @@ -400,8 +399,17 @@ struct Alice3MulticharmFinder { return returnValue; } - void init(InitContext&) + void init(o2::framework::InitContext& initContext) { + const bool foundMagneticField = common::core::getTaskOptionValue(initContext, "on-the-fly-detector-geometry-provider", "magneticField", magneticField, false); + if (!foundMagneticField) { + LOG(info) << "Could not retrieve magnetic field from geometry provider."; + LOG(info) << "Using value from configurable cfgMagneticField: " << cfgMagneticField; + magneticField = cfgMagneticField; + } else { + LOG(info) << "Using magnetic field form geometry provider with value: " << magneticField; + } + // initialize O2 2-prong fitter (only once) fitter.setPropagateToPCA(true); fitter.setMaxR(200.); @@ -444,6 +452,7 @@ struct Alice3MulticharmFinder { // --- 0: attempt XiC, 1: success XiC // --- 2: attempt XiCC, 3: success XiCC INSERT_HIST(histPath + "hCharmBuilding", "hCharmBuilding", {kTH1D, {{10, -0.5, 9.5f}}}); + INSERT_HIST(histPath + "hMultiCharmBuilding", "hMultiCharmBuilding", {kTH1D, {{10, -0.5, 9.5f}}}); INSERT_HIST(histPath + "hMassXi", "hMassXi", {kTH1D, {{axisXiMass}}}); INSERT_HIST(histPath + "hMassXiC", "hMassXiC", {kTH1D, {{axisXiCMass}}}); @@ -478,7 +487,7 @@ struct Alice3MulticharmFinder { INSERT_HIST(histPath + "hMinXiCDecayRadius", "hMinXiCDecayRadius", {kTH1D, {{axisRadius}}}); INSERT_HIST(histPath + "hMinXiCCDecayRadius", "hMinXiCCDecayRadius", {kTH1D, {{axisRadius}}}); - INSERT_HIST(histPath + "hMinxicDecayDistanceFromPV", "hMinxicDecayDistanceFromPV", {kTH1D, {{axisDecayLength}}}); + INSERT_HIST(histPath + "hMinXicDecayDistanceFromPV", "hMinXicDecayDistanceFromPV", {kTH1D, {{axisDecayLength}}}); INSERT_HIST(histPath + "hProperLengthXiC", "hProperLengthXiC", {kTH1D, {{axisDecayLength}}}); INSERT_HIST(histPath + "hProperLengthXiCC", "hProperLengthXiCC", {kTH1D, {{axisDecayLength}}}); @@ -486,6 +495,10 @@ struct Alice3MulticharmFinder { INSERT_HIST(histPath + "hInnerTOFTrackTimeRecoPi2c", "hInnerTOFTrackTimeRecoPi2c", {kTH1D, {{axisTOFTrack}}}); INSERT_HIST(histPath + "hInnerTOFTrackTimeRecoPicc", "hInnerTOFTrackTimeRecoPicc", {kTH1D, {{axisTOFTrack}}}); + INSERT_HIST(histPath + "hOuterTOFTrackTimeRecoPi1c", "hOuterTOFTrackTimeRecoPi1c", {kTH1D, {{axisTOFTrack}}}); + INSERT_HIST(histPath + "hOuterTOFTrackTimeRecoPi2c", "hOuterTOFTrackTimeRecoPi2c", {kTH1D, {{axisTOFTrack}}}); + INSERT_HIST(histPath + "hOuterTOFTrackTimeRecoPicc", "hOuterTOFTrackTimeRecoPicc", {kTH1D, {{axisTOFTrack}}}); + INSERT_HIST(histPath + "hXiRadiusVsXicRadius", "hXiRadiusVsXicRadius", {kTH2D, {{axisRadius2D, axisRadius2D}}}); INSERT_HIST(histPath + "hXicRadiusVsXiccRadius", "hXicRadiusVsXiccRadius", {kTH2D, {{axisRadius2D, axisRadius2D}}}); @@ -525,7 +538,7 @@ struct Alice3MulticharmFinder { } //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* - void processFindXiCC(Alice3Collision const& collision, Alice3Tracks const& tracks, aod::McParticles const&, aod::UpgradeCascades const& cascades) + void processFindXicc(Alice3Collision const& collision, Alice3Tracks const& tracks, aod::McParticles const&, aod::UpgradeCascades const& cascades) { const std::string histPath = "Configuration_" + std::to_string(collision.lutConfigId()) + "/"; initDetectorConfiguration(collision.lutConfigId()); @@ -544,20 +557,20 @@ struct Alice3MulticharmFinder { for (auto const& track : tracks) { if (BIT_CHECK(track.decayMap(), kTruePiFromXiC)) { - GET_HIST(TH2, histPath + "h2dDCAxyVsPtPiFromXiC")->Fill(track.pt(), track.dcaXY() * toMicrons); - GET_HIST(TH2, histPath + "h2dDCAxyVsPtPiFromXiC")->Fill(track.pt(), track.dcaZ() * toMicrons); + GET_HIST(TH2, histPath + "h2dDCAxyVsPtPiFromXiC")->Fill(track.pt(), track.dcaXY() * ToMicrons); + GET_HIST(TH2, histPath + "h2dDCAxyVsPtPiFromXiC")->Fill(track.pt(), track.dcaZ() * ToMicrons); } if (BIT_CHECK(track.decayMap(), kTruePiFromXiCC)) { - GET_HIST(TH2, histPath + "h2dDCAxyVsPtPiFromXiCC")->Fill(track.pt(), track.dcaXY() * toMicrons); - GET_HIST(TH2, histPath + "h2dDCAxyVsPtPiFromXiCC")->Fill(track.pt(), track.dcaZ() * toMicrons); + GET_HIST(TH2, histPath + "h2dDCAxyVsPtPiFromXiCC")->Fill(track.pt(), track.dcaXY() * ToMicrons); + GET_HIST(TH2, histPath + "h2dDCAxyVsPtPiFromXiCC")->Fill(track.pt(), track.dcaZ() * ToMicrons); } } for (auto const& xiCand : cascades) { auto xi = xiCand.cascadeTrack_as(); // de-reference cascade track GET_HIST(TH1, histPath + "hMassXi")->Fill(xiCand.mXi()); - GET_HIST(TH2, histPath + "h2dDCAxyVsPtXiFromXiC")->Fill(xi.pt(), xi.dcaXY() * toMicrons); - GET_HIST(TH2, histPath + "h2dDCAzVsPtXiFromXiC")->Fill(xi.pt(), xi.dcaZ() * toMicrons); + GET_HIST(TH2, histPath + "h2dDCAxyVsPtXiFromXiC")->Fill(xi.pt(), xi.dcaXY() * ToMicrons); + GET_HIST(TH2, histPath + "h2dDCAzVsPtXiFromXiC")->Fill(xi.pt(), xi.dcaZ() * ToMicrons); if (std::fabs(xiCand.mXi() - o2::constants::physics::MassXiMinus) > xiMassWindow) { continue; // out of mass region @@ -572,8 +585,8 @@ struct Alice3MulticharmFinder { continue; // likely a primary xi } - GET_HIST(TH1, histPath + "hDCAxyXi")->Fill(xi.dcaXY() * toMicrons); - GET_HIST(TH1, histPath + "hDCAzXi")->Fill(xi.dcaZ() * toMicrons); + GET_HIST(TH1, histPath + "hDCAxyXi")->Fill(xi.dcaXY() * ToMicrons); + GET_HIST(TH1, histPath + "hDCAzXi")->Fill(xi.dcaZ() * ToMicrons); if (xiCand.cascRadius() < xiMinDecayRadius) { continue; } @@ -593,13 +606,6 @@ struct Alice3MulticharmFinder { } GET_HIST(TH1, histPath + "hPi1cPt")->Fill(pi1c.pt()); - float pi1cTOFDiffInner = std::fabs(pi1c.innerTOFTrackTimeReco() - pi1c.innerTOFExpectedTimePi()); - float pi1cTOFDiffOuter = std::fabs(pi1c.outerTOFTrackTimeReco() - pi1c.outerTOFExpectedTimePi()); - if (pi1cTOFDiffInner > picTofDiffInner) { - continue; // did not arrive at expected time - } - - GET_HIST(TH1, histPath + "hInnerTOFTrackTimeRecoPi1c")->Fill(pi1cTOFDiffInner); // second pion from XiC decay for starts here for (auto const& pi2c : picTracksGrouped) { if (mcSameMotherCheck && !checkSameMother(xi, pi2c)) { @@ -619,44 +625,40 @@ struct Alice3MulticharmFinder { } GET_HIST(TH1, histPath + "hPi2cPt")->Fill(pi2c.pt()); - float pi2cTOFDiffInner = std::fabs(pi2c.innerTOFTrackTimeReco() - pi2c.innerTOFExpectedTimePi()); - float pi2cTOFDiffOuter = std::fabs(pi2c.outerTOFTrackTimeReco() - pi2c.outerTOFExpectedTimePi()); - if (pi2cTOFDiffInner > picTofDiffInner) { - continue; // did not arrive at expected time - } - - GET_HIST(TH1, histPath + "hInnerTOFTrackTimeRecoPi2c")->Fill(pi2cTOFDiffInner); // if I am here, it means this is a triplet to be considered for XiC vertexing. // will now attempt to build a three-body decay candidate with these three track rows. - nCombinationsC++; GET_HIST(TH1, histPath + "hCharmBuilding")->Fill(0.0f); + if (!buildDecayCandidateThreeBody(xi, pi1c, pi2c, o2::constants::physics::MassXiMinus, o2::constants::physics::MassPionCharged, o2::constants::physics::MassPionCharged)) { continue; // failed at building candidate } - GET_HIST(TH1, histPath + "hDCAXiCDaughters")->Fill(thisXiCcandidate.dca * toMicrons); - if (std::fabs(thisXiCcandidate.mass - o2::constants::physics::MassXiCPlus) > xicMassWindow) { + GET_HIST(TH1, histPath + "hDCAXiCDaughters")->Fill(thisXicCandidate.dca * ToMicrons); + if (std::fabs(thisXicCandidate.mass - o2::constants::physics::MassXiCPlus) > xicMassWindow) { continue; // out of mass region } GET_HIST(TH1, histPath + "hCharmBuilding")->Fill(1.0f); const std::array momentumC = { - thisXiCcandidate.prong0mom[0] + thisXiCcandidate.prong1mom[0] + thisXiCcandidate.prong2mom[0], - thisXiCcandidate.prong0mom[1] + thisXiCcandidate.prong1mom[1] + thisXiCcandidate.prong2mom[1], - thisXiCcandidate.prong0mom[2] + thisXiCcandidate.prong1mom[2] + thisXiCcandidate.prong2mom[2]}; + thisXicCandidate.prong0mom[0] + thisXicCandidate.prong1mom[0] + thisXicCandidate.prong2mom[0], + thisXicCandidate.prong0mom[1] + thisXicCandidate.prong1mom[1] + thisXicCandidate.prong2mom[1], + thisXicCandidate.prong0mom[2] + thisXicCandidate.prong1mom[2] + thisXicCandidate.prong2mom[2]}; - o2::track::TrackParCov xicTrack(thisXiCcandidate.xyz, momentumC, thisXiCcandidate.parentTrackCovMatrix, +1); - float xicDecayRadius2D = std::hypot(thisXiCcandidate.xyz[0], thisXiCcandidate.xyz[1]); - if (xicDecayRadius2D < xiccMinDecayRadius) + o2::track::TrackParCov xicTrack(thisXicCandidate.xyz, momentumC, thisXicCandidate.parentTrackCovMatrix, +1); + float xicDecayRadius2D = std::hypot(thisXicCandidate.xyz[0], thisXicCandidate.xyz[1]); + if (xicDecayRadius2D < xiccMinDecayRadius) { continue; // do not take if radius too small, likely a primary combination + } - GET_HIST(TH1, histPath + "hMinXiCDecayRadius")->Fill(xicDecayRadius2D * toMicrons); + GET_HIST(TH1, histPath + "hCharmBuilding")->Fill(2.0f); + GET_HIST(TH1, histPath + "hMinXiCDecayRadius")->Fill(xicDecayRadius2D * ToMicrons); if (xicDecayRadius2D > xiCand.cascRadius()) { continue; } - GET_HIST(TH2, histPath + "hXiRadiusVsXicRadius")->Fill(xiCand.cascRadius() * toMicrons, xicDecayRadius2D * toMicrons); + GET_HIST(TH1, histPath + "hCharmBuilding")->Fill(3.0f); + GET_HIST(TH2, histPath + "hXiRadiusVsXicRadius")->Fill(xiCand.cascRadius() * ToMicrons, xicDecayRadius2D * ToMicrons); o2::dataformats::DCA dcaInfo; float xicdcaXY = 1e+10, xicdcaZ = 1e+10; o2::track::TrackParCov xicTrackCopy(xicTrack); // paranoia @@ -672,9 +674,10 @@ struct Alice3MulticharmFinder { continue; // likely a primary xic } - GET_HIST(TH1, histPath + "hDCAxyXiC")->Fill(std::fabs(xicdcaXY * toMicrons)); - GET_HIST(TH1, histPath + "hDCAzXiC")->Fill(std::fabs(xicdcaZ * toMicrons)); - GET_HIST(TH1, histPath + "hMassXiC")->Fill(thisXiCcandidate.mass); + GET_HIST(TH1, histPath + "hCharmBuilding")->Fill(4.0f); + GET_HIST(TH1, histPath + "hDCAxyXiC")->Fill(std::fabs(xicdcaXY * ToMicrons)); + GET_HIST(TH1, histPath + "hDCAzXiC")->Fill(std::fabs(xicdcaZ * ToMicrons)); + GET_HIST(TH1, histPath + "hMassXiC")->Fill(thisXicCandidate.mass); // attempt XiCC finding uint32_t nCombinationsCC = 0; @@ -691,72 +694,71 @@ struct Alice3MulticharmFinder { continue; // too low momentum } + GET_HIST(TH1, histPath + "hMultiCharmBuilding")->Fill(0.0f); GET_HIST(TH1, histPath + "hPiccPt")->Fill(picc.pt()); - float piccTOFDiffInner = std::fabs(picc.innerTOFTrackTimeReco() - picc.innerTOFExpectedTimePi()); - float piccTOFDiffOuter = std::fabs(picc.outerTOFTrackTimeReco() - picc.outerTOFExpectedTimePi()); - if (piccTOFDiffInner > piccTofDiffInner) { - continue; // did not arrive at expected time - } - - GET_HIST(TH1, histPath + "hInnerTOFTrackTimeRecoPicc")->Fill(piccTOFDiffInner); o2::track::TrackParCov piccTrack = getTrackParCov(picc); nCombinationsCC++; - GET_HIST(TH1, histPath + "hCharmBuilding")->Fill(2.0f); if (!buildDecayCandidateTwoBody(xicTrack, piccTrack, o2::constants::physics::MassXiCPlus, o2::constants::physics::MassPionCharged)) { continue; // failed at building candidate } - GET_HIST(TH1, histPath + "hDCAXiCCDaughters")->Fill(thisXiCCcandidate.dca * toMicrons); + GET_HIST(TH1, histPath + "hMultiCharmBuilding")->Fill(1.0f); + GET_HIST(TH1, histPath + "hDCAXiCCDaughters")->Fill(thisXiccCandidate.dca * ToMicrons); const std::array momentumCC = { - thisXiCCcandidate.prong0mom[0] + thisXiCCcandidate.prong1mom[0], - thisXiCCcandidate.prong0mom[1] + thisXiCCcandidate.prong1mom[1], - thisXiCCcandidate.prong0mom[2] + thisXiCCcandidate.prong1mom[2]}; + thisXiccCandidate.prong0mom[0] + thisXiccCandidate.prong1mom[0], + thisXiccCandidate.prong0mom[1] + thisXiccCandidate.prong1mom[1], + thisXiccCandidate.prong0mom[2] + thisXiccCandidate.prong1mom[2]}; - o2::track::TrackParCov xiccTrack(thisXiCCcandidate.xyz, momentumCC, thisXiCCcandidate.parentTrackCovMatrix, +2); - float xiccDecayRadius2D = std::hypot(thisXiCCcandidate.xyz[0], thisXiCCcandidate.xyz[1]); + o2::track::TrackParCov xiccTrack(thisXiccCandidate.xyz, momentumCC, thisXiccCandidate.parentTrackCovMatrix, +2); + float xiccDecayRadius2D = std::hypot(thisXiccCandidate.xyz[0], thisXiccCandidate.xyz[1]); if (xiccDecayRadius2D < xiccMinDecayRadius) { continue; // do not take if radius too small, likely a primary combination } - GET_HIST(TH1, histPath + "hDCAXiCCDaughters")->Fill(thisXiCCcandidate.dca * toMicrons); + GET_HIST(TH1, histPath + "hMultiCharmBuilding")->Fill(2.0f); + GET_HIST(TH1, histPath + "hDCAXiCCDaughters")->Fill(thisXiccCandidate.dca * ToMicrons); float totalMomentumC = std::hypot(momentumC[0], momentumC[1], momentumC[2]); float decayLengthXiC = std::hypot( - thisXiCcandidate.xyz[0] - thisXiCCcandidate.xyz[0], - thisXiCcandidate.xyz[1] - thisXiCCcandidate.xyz[1], - thisXiCcandidate.xyz[2] - thisXiCCcandidate.xyz[2]); - float xicProperLength = decayLengthXiC * thisXiCcandidate.mass / totalMomentumC; + thisXicCandidate.xyz[0] - thisXiccCandidate.xyz[0], + thisXicCandidate.xyz[1] - thisXiccCandidate.xyz[1], + thisXicCandidate.xyz[2] - thisXiccCandidate.xyz[2]); + float xicProperLength = decayLengthXiC * thisXicCandidate.mass / totalMomentumC; if (xicProperLength < xicMinProperLength || xicProperLength > xicMaxProperLength) { continue; // likely background } - GET_HIST(TH1, histPath + "hProperLengthXiC")->Fill(xicProperLength * toMicrons); + GET_HIST(TH1, histPath + "hMultiCharmBuilding")->Fill(3.0f); + GET_HIST(TH1, histPath + "hProperLengthXiC")->Fill(xicProperLength * ToMicrons); float xicDistanceFromPV = std::hypot( - thisXiCcandidate.xyz[0] - collision.posX(), - thisXiCcandidate.xyz[1] - collision.posY(), - thisXiCcandidate.xyz[2] - collision.posZ()); - float xicDecayDistanceFromPV = xicDistanceFromPV * thisXiCcandidate.mass / totalMomentumC; + thisXicCandidate.xyz[0] - collision.posX(), + thisXicCandidate.xyz[1] - collision.posY(), + thisXicCandidate.xyz[2] - collision.posZ()); + float xicDecayDistanceFromPV = xicDistanceFromPV * thisXicCandidate.mass / totalMomentumC; if (xicDecayDistanceFromPV < xicMinDecayDistanceFromPV) { continue; // too close to PV } - GET_HIST(TH1, histPath + "hMinxicDecayDistanceFromPV")->Fill(xicDecayDistanceFromPV * toMicrons); + GET_HIST(TH1, histPath + "hMultiCharmBuilding")->Fill(4.0f); + GET_HIST(TH1, histPath + "hMinXicDecayDistanceFromPV")->Fill(xicDecayDistanceFromPV * ToMicrons); float totalMomentumCC = std::hypot(momentumCC[0], momentumCC[1], momentumCC[2]); float decayLengthXiCC = std::hypot( - thisXiCCcandidate.xyz[0] - collision.posX(), - thisXiCCcandidate.xyz[1] - collision.posY(), - thisXiCCcandidate.xyz[2] - collision.posZ()); - float xiccProperLength = decayLengthXiCC * thisXiCCcandidate.mass / totalMomentumCC; + thisXiccCandidate.xyz[0] - collision.posX(), + thisXiccCandidate.xyz[1] - collision.posY(), + thisXiccCandidate.xyz[2] - collision.posZ()); + float xiccProperLength = decayLengthXiCC * thisXiccCandidate.mass / totalMomentumCC; if (xiccProperLength < xiccMinProperLength || xiccProperLength > xicMaxProperLength) { continue; // likely background } - GET_HIST(TH1, histPath + "hProperLengthXiCC")->Fill(xiccProperLength * toMicrons); + GET_HIST(TH1, histPath + "hMultiCharmBuilding")->Fill(5.0f); + GET_HIST(TH1, histPath + "hProperLengthXiCC")->Fill(xiccProperLength * ToMicrons); if (xiccDecayRadius2D > xicDecayRadius2D) { continue; // XiCC should decay before XiC } - GET_HIST(TH2, histPath + "hXicRadiusVsXiccRadius")->Fill(xicDecayRadius2D * toMicrons, xiccDecayRadius2D * toMicrons); + GET_HIST(TH1, histPath + "hMultiCharmBuilding")->Fill(6.0f); + GET_HIST(TH2, histPath + "hXicRadiusVsXiccRadius")->Fill(xicDecayRadius2D * ToMicrons, xiccDecayRadius2D * ToMicrons); float xiccdcaXY = 1e+10, xiccdcaZ = 1e+10; if (xiccTrack.propagateToDCA(primaryVertex, magneticField, &dcaInfo)) { xiccdcaXY = dcaInfo.getY(); @@ -767,37 +769,40 @@ struct Alice3MulticharmFinder { continue; // not pointing to PV } - GET_HIST(TH1, histPath + "hDCAxyXiCC")->Fill(xiccdcaXY * toMicrons); - GET_HIST(TH1, histPath + "hDCAzXiCC")->Fill(xiccdcaZ * toMicrons); - if (std::fabs(thisXiCCcandidate.eta) > xiccMaxEta) { + GET_HIST(TH1, histPath + "hMultiCharmBuilding")->Fill(7.0f); + GET_HIST(TH1, histPath + "hDCAxyXiCC")->Fill(xiccdcaXY * ToMicrons); + GET_HIST(TH1, histPath + "hDCAzXiCC")->Fill(xiccdcaZ * ToMicrons); + if (std::fabs(thisXiccCandidate.eta) > xiccMaxEta) { continue; // not in central barrel } - GET_HIST(TH1, histPath + "hCharmBuilding")->Fill(3.0f); - GET_HIST(TH1, histPath + "hMassXiCC")->Fill(thisXiCCcandidate.mass); - GET_HIST(TH1, histPath + "hPtXiCC")->Fill(thisXiCCcandidate.pt); - GET_HIST(TH1, histPath + "hEtaXiCC")->Fill(thisXiCCcandidate.eta); - GET_HIST(TH3, histPath + "h3dMassXiCC")->Fill(thisXiCCcandidate.pt, thisXiCCcandidate.eta, thisXiCCcandidate.mass); + GET_HIST(TH1, histPath + "hMultiCharmBuilding")->Fill(8.0f); + GET_HIST(TH1, histPath + "hMassXiCC")->Fill(thisXiccCandidate.mass); + GET_HIST(TH1, histPath + "hPtXiCC")->Fill(thisXiccCandidate.pt); + GET_HIST(TH1, histPath + "hEtaXiCC")->Fill(thisXiccCandidate.eta); + GET_HIST(TH3, histPath + "h3dMassXiCC")->Fill(thisXiccCandidate.pt, thisXiccCandidate.eta, thisXiccCandidate.mass); - GET_HIST(TH1, histPath + "hPi1cDCAxy")->Fill(std::abs(pi1c.dcaXY() * toMicrons)); - GET_HIST(TH1, histPath + "hPi1cDCAz")->Fill(std::abs(pi1c.dcaZ() * toMicrons)); - GET_HIST(TH1, histPath + "hPi2cDCAxy")->Fill(std::abs(pi2c.dcaXY() * toMicrons)); - GET_HIST(TH1, histPath + "hPi2cDCAz")->Fill(std::abs(pi2c.dcaZ() * toMicrons)); - GET_HIST(TH1, histPath + "hPiccDCAxy")->Fill(std::abs(picc.dcaXY() * toMicrons)); - GET_HIST(TH1, histPath + "hPiccDCAz")->Fill(std::abs(picc.dcaZ() * toMicrons)); + GET_HIST(TH1, histPath + "hPi1cDCAxy")->Fill(std::abs(pi1c.dcaXY() * ToMicrons)); + GET_HIST(TH1, histPath + "hPi1cDCAz")->Fill(std::abs(pi1c.dcaZ() * ToMicrons)); + GET_HIST(TH1, histPath + "hPi2cDCAxy")->Fill(std::abs(pi2c.dcaXY() * ToMicrons)); + GET_HIST(TH1, histPath + "hPi2cDCAz")->Fill(std::abs(pi2c.dcaZ() * ToMicrons)); + GET_HIST(TH1, histPath + "hPiccDCAxy")->Fill(std::abs(picc.dcaXY() * ToMicrons)); + GET_HIST(TH1, histPath + "hPiccDCAz")->Fill(std::abs(picc.dcaZ() * ToMicrons)); // produce multi-charm table for posterior analysis - if (fillDerivedTable) { + if (derivedTable.fillMCharmIdx) { multiCharmIdx( xiCand.globalIndex(), pi1c.globalIndex(), pi2c.globalIndex(), picc.globalIndex()); + } + if (derivedTable.fillMCharmCore) { multiCharmCore( - thisXiCCcandidate.mass, thisXiCCcandidate.pt, - thisXiCCcandidate.eta, thisXiCCcandidate.dca, - thisXiCcandidate.mass, thisXiCcandidate.pt, - thisXiCcandidate.eta, thisXiCcandidate.dca, + thisXiccCandidate.mass, thisXiccCandidate.pt, + thisXiccCandidate.eta, thisXiccCandidate.dca, + thisXicCandidate.mass, thisXicCandidate.pt, + thisXicCandidate.eta, thisXicCandidate.dca, xi.dcaXY(), xi.dcaZ(), xicdcaXY, xicdcaZ, xiccdcaXY, xiccdcaZ, @@ -810,21 +815,9 @@ struct Alice3MulticharmFinder { xiccProperLength, pi1c.pt(), pi2c.pt(), picc.pt(), collision.lutConfigId()); + } - multiCharmPID( - pi1cTOFDiffInner, pi1c.nSigmaPionInnerTOF(), - pi1cTOFDiffOuter, pi1c.nSigmaPionOuterTOF(), - pi1c.hasSigPi(), pi1c.nSigmaPionRich(), - getPdgCodeForTrack(pi1c), - pi2cTOFDiffInner, pi2c.nSigmaPionInnerTOF(), - pi2cTOFDiffOuter, pi2c.nSigmaPionOuterTOF(), - pi2c.hasSigPi(), pi2c.nSigmaPionRich(), - getPdgCodeForTrack(pi2c), - piccTOFDiffInner, picc.nSigmaPionInnerTOF(), - piccTOFDiffOuter, picc.nSigmaPionOuterTOF(), - picc.hasSigPi(), picc.nSigmaPionRich(), - getPdgCodeForTrack(picc)); - + if (derivedTable.fillMCharmExtra) { ProngInfo bachelor, positive, negative; if (xiCand.has_bachTrack()) { auto bach = xiCand.bachTrack_as(); // de-reference bach track @@ -870,7 +863,7 @@ struct Alice3MulticharmFinder { //*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<* PROCESS_SWITCH(Alice3MulticharmFinder, processGenerated, "fill MC-only histograms", true); - PROCESS_SWITCH(Alice3MulticharmFinder, processFindXiCC, "find XiCC baryons", true); + PROCESS_SWITCH(Alice3MulticharmFinder, processFindXicc, "find XiCC baryons", true); //*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<* }; diff --git a/ALICE3/Tasks/alice3Multicharm.cxx b/ALICE3/Tasks/alice3Multicharm.cxx index 69c6fce9a5c..41ff2f2b38a 100644 --- a/ALICE3/Tasks/alice3Multicharm.cxx +++ b/ALICE3/Tasks/alice3Multicharm.cxx @@ -64,8 +64,8 @@ using namespace o2::ml; using namespace o2::framework; using namespace o2::framework::expressions; -using MultiCharmTracksPID = soa::Join; -using MultiCharmTracksFull = soa::Join; +using MultiCharmTracksPID = soa::Join; +using MultiCharmTracksFull = soa::Join; struct Alice3Multicharm { HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -179,44 +179,6 @@ struct Alice3Multicharm { hMCharmBuilding->GetXaxis()->SetBinLabel(21, "xiccMaxProperLength"); hMCharmBuilding->GetXaxis()->SetBinLabel(22, "xicMinDecayDistanceFromPV"); - if (doprocessXiccPID || doprocessXiccExtra) { - auto hPdgCodes = histos.add("PIDQA/hPdgCodes", "hPdgCodes", kTH2D, {{3, 0.5, 3.5}, {7, 0.5, 7.5}}); - hPdgCodes->GetXaxis()->SetBinLabel(1, "pi1c"); - hPdgCodes->GetXaxis()->SetBinLabel(2, "pi2c"); - hPdgCodes->GetXaxis()->SetBinLabel(3, "picc"); - hPdgCodes->GetYaxis()->SetBinLabel(1, "el"); - hPdgCodes->GetYaxis()->SetBinLabel(2, "mu"); - hPdgCodes->GetYaxis()->SetBinLabel(3, "pi"); - hPdgCodes->GetYaxis()->SetBinLabel(4, "ka"); - hPdgCodes->GetYaxis()->SetBinLabel(5, "pr"); - hPdgCodes->GetYaxis()->SetBinLabel(6, "xi"); - hPdgCodes->GetYaxis()->SetBinLabel(7, "other"); - pdgToBin.insert({kElectron, 1}); - pdgToBin.insert({kMuonMinus, 2}); - pdgToBin.insert({kPiPlus, 3}); - pdgToBin.insert({kKPlus, 4}); - pdgToBin.insert({kProton, 5}); - pdgToBin.insert({kXiMinus, 6}); - - histos.add("PIDQA/hInnerTofTimeDeltaPi1c", "hInnerTofTimeDeltaPi1c; Reco - expected pion (ps)", kTH1D, {axisTofTrackDelta}); - histos.add("PIDQA/hInnerTofTimeDeltaPi2c", "hInnerTofTimeDeltaPi2c; Reco - expected pion (ps)", kTH1D, {axisTofTrackDelta}); - histos.add("PIDQA/hInnerTofTimeDeltaPicc", "hInnerTofTimeDeltaPicc; Reco - expected pion (ps)", kTH1D, {axisTofTrackDelta}); - histos.add("PIDQA/hOuterTofTimeDeltaPi1c", "hOuterTofTimeDeltaPi1c; Reco - expected pion (ps)", kTH1D, {axisTofTrackDelta}); - histos.add("PIDQA/hOuterTofTimeDeltaPi2c", "hOuterTofTimeDeltaPi2c; Reco - expected pion (ps)", kTH1D, {axisTofTrackDelta}); - histos.add("PIDQA/hOuterTofTimeDeltaPicc", "hOuterTofTimeDeltaPicc; Reco - expected pion (ps)", kTH1D, {axisTofTrackDelta}); - - histos.add("PIDQA/hInnerTofNSigmaPi1c", "hInnerTofNSigmaPi1c; TOF NSigma pion", kTH2D, {axisPt, axisNSigma}); - histos.add("PIDQA/hOuterTofNSigmaPi1c", "hOuterTofNSigmaPi1c; TOF NSigma pion", kTH2D, {axisPt, axisNSigma}); - histos.add("PIDQA/hInnerTofNSigmaPi2c", "hInnerTofNSigmaPi2c; TOF NSigma pion", kTH2D, {axisPt, axisNSigma}); - histos.add("PIDQA/hOuterTofNSigmaPi2c", "hOuterTofNSigmaPi2c; TOF NSigma pion", kTH2D, {axisPt, axisNSigma}); - histos.add("PIDQA/hInnerTofNSigmaPicc", "hInnerTofNSigmaPicc; TOF NSigma pion", kTH2D, {axisPt, axisNSigma}); - histos.add("PIDQA/hOuterTofNSigmaPicc", "hOuterTofNSigmaPicc; TOF NSigma pion", kTH2D, {axisPt, axisNSigma}); - - histos.add("PIDQA/hRichNSigmaPi1c", "hRichNSigmaPi1c; RICH NSigma pion", kTH2D, {axisPt, axisNSigma}); - histos.add("PIDQA/hRichNSigmaPi2c", "hRichNSigmaPi2c; RICH NSigma pion", kTH2D, {axisPt, axisNSigma}); - histos.add("PIDQA/hRichNSigmaPicc", "hRichNSigmaPicc; RICH NSigma pion", kTH2D, {axisPt, axisNSigma}); - } - if (doprocessXiccExtra) { histos.add("XiccProngs/h3dPos", "h3dPos; Xicc pT (GeV/#it(c)); Pos pT (GeV/#it(c)); Pos #eta", kTH3D, {axisPt, axisPt, axisEta}); histos.add("XiccProngs/h3dNeg", "h3dNeg; Xicc pT (GeV/#it(c)); Neg pT (GeV/#it(c)); Neg #eta", kTH3D, {axisPt, axisPt, axisEta}); @@ -282,12 +244,6 @@ struct Alice3Multicharm { } } - int getBin(const std::map& pdgToBin, int pdg) - { - auto it = pdgToBin.find(pdg); - return (it != pdgToBin.end()) ? it->second : 7; - } - template void genericProcessXicc(TMCharmCands const& xiccCands) { @@ -502,34 +458,6 @@ struct Alice3Multicharm { histos.fill(HIST("SelectionQA/hPi2cPt"), xiccCand.pi2cPt()); histos.fill(HIST("SelectionQA/hPiccPt"), xiccCand.piccPt()); - if constexpr (requires { xiccCand.pi1cTofDeltaInner(); }) { // if pid table - histos.fill(HIST("PIDQA/hInnerTofTimeDeltaPi1c"), xiccCand.pi1cTofDeltaInner()); - histos.fill(HIST("PIDQA/hInnerTofTimeDeltaPi2c"), xiccCand.pi2cTofDeltaInner()); - histos.fill(HIST("PIDQA/hInnerTofTimeDeltaPicc"), xiccCand.piccTofDeltaInner()); - histos.fill(HIST("PIDQA/hOuterTofTimeDeltaPi1c"), xiccCand.pi1cTofDeltaOuter()); - histos.fill(HIST("PIDQA/hOuterTofTimeDeltaPi2c"), xiccCand.pi2cTofDeltaOuter()); - histos.fill(HIST("PIDQA/hOuterTofTimeDeltaPicc"), xiccCand.piccTofDeltaOuter()); - histos.fill(HIST("PIDQA/hInnerTofNSigmaPi1c"), xiccCand.pi1cPt(), xiccCand.pi1cTofNSigmaInner()); - histos.fill(HIST("PIDQA/hOuterTofNSigmaPi1c"), xiccCand.pi1cPt(), xiccCand.pi1cTofNSigmaOuter()); - histos.fill(HIST("PIDQA/hInnerTofNSigmaPi2c"), xiccCand.pi2cPt(), xiccCand.pi2cTofNSigmaInner()); - histos.fill(HIST("PIDQA/hOuterTofNSigmaPi2c"), xiccCand.pi2cPt(), xiccCand.pi2cTofNSigmaOuter()); - histos.fill(HIST("PIDQA/hInnerTofNSigmaPicc"), xiccCand.piccPt(), xiccCand.piccTofNSigmaInner()); - histos.fill(HIST("PIDQA/hOuterTofNSigmaPicc"), xiccCand.piccPt(), xiccCand.piccTofNSigmaOuter()); - if (xiccCand.pi1cHasRichSignal()) { - histos.fill(HIST("PIDQA/hRichNSigmaPi1c"), xiccCand.pi1cPt(), xiccCand.pi1cRichNSigma()); - } - if (xiccCand.pi2cHasRichSignal()) { - histos.fill(HIST("PIDQA/hRichNSigmaPi2c"), xiccCand.pi2cPt(), xiccCand.pi2cRichNSigma()); - } - if (xiccCand.piccHasRichSignal()) { - histos.fill(HIST("PIDQA/hRichNSigmaPicc"), xiccCand.piccPt(), xiccCand.piccRichNSigma()); - } - - histos.fill(HIST("PIDQA/hPdgCodes"), 1, getBin(pdgToBin, std::abs(xiccCand.pi1cPdgCode()))); - histos.fill(HIST("PIDQA/hPdgCodes"), 2, getBin(pdgToBin, std::abs(xiccCand.pi2cPdgCode()))); - histos.fill(HIST("PIDQA/hPdgCodes"), 3, getBin(pdgToBin, std::abs(xiccCand.piccPdgCode()))); - } - if constexpr (requires { xiccCand.negPt(); }) { // if extra table histos.fill(HIST("XiccProngs/h3dNeg"), xiccCand.xiccPt(), xiccCand.negPt(), xiccCand.negEta()); histos.fill(HIST("XiccProngs/h3dPos"), xiccCand.xiccPt(), xiccCand.posPt(), xiccCand.posEta()); @@ -552,18 +480,12 @@ struct Alice3Multicharm { genericProcessXicc(multiCharmTracks); } - void processXiccPID(soa::Filtered const& multiCharmTracks) - { - genericProcessXicc(multiCharmTracks); - } - void processXiccExtra(soa::Filtered const& multiCharmTracks) { genericProcessXicc(multiCharmTracks); } PROCESS_SWITCH(Alice3Multicharm, processXicc, "find Xicc baryons", true); - PROCESS_SWITCH(Alice3Multicharm, processXiccPID, "find Xicc baryons with more QA from PID information", false); PROCESS_SWITCH(Alice3Multicharm, processXiccExtra, "find Xicc baryons with all QA", false); }; From f6e10cafc5a2c2c8f4d07408b1aa3067a5090c36 Mon Sep 17 00:00:00 2001 From: Junlee Kim Date: Tue, 24 Feb 2026 00:30:42 +0800 Subject: [PATCH 044/347] [PWGCF] fixing bug for efficiency correction (#15064) Co-authored-by: ALICE Action Bot --- PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx b/PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx index 79c5c4e2df6..13c2e3e72fc 100644 --- a/PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx +++ b/PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx @@ -169,6 +169,7 @@ struct jEPFlowAnalysis { effVars[1] = eff->GetAxis(1)->FindBin(pt); effVars[2] = eff->GetAxis(2)->FindBin(multiplicity); effVars[3] = eff->GetAxis(3)->FindBin(posZ); + return eff->GetBinContent(effVars); } @@ -251,7 +252,11 @@ struct jEPFlowAnalysis { if (cfgEffCor) { auto bc = coll.bc_as(); - effMap = ccdb->getForTimeStamp>(cfgEffCorDir, bc.timestamp()); + currentRunNumber = bc.runNumber(); + if (currentRunNumber != lastRunNumber) { + effMap = ccdb->getForTimeStamp>(cfgEffCorDir, bc.timestamp()); + lastRunNumber = currentRunNumber; + } } float cent = coll.cent(); @@ -350,7 +355,7 @@ struct jEPFlowAnalysis { continue; if (cfgEffCor) { - weight /= getEfficiencyCorrection(effMap, track.eta(), track.pt(), cent, coll.posZ()); + weight = getEfficiencyCorrection(effMap, track.eta(), track.pt(), cent, coll.posZ()); } float vn = std::cos((i + 2) * (track.phi() - eps[0])); From 49036b1e4b1a8ebd27c762ade048c4cc920bcc54 Mon Sep 17 00:00:00 2001 From: baasingh <142407539+baasingh@users.noreply.github.com> Date: Mon, 23 Feb 2026 22:01:31 +0530 Subject: [PATCH 045/347] [PWGCF] Run3/mc anaysis validation (#15066) Signed-off-by: baasingh --- PWGCF/EbyEFluctuations/Tasks/FactorialMomentsTask.cxx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/PWGCF/EbyEFluctuations/Tasks/FactorialMomentsTask.cxx b/PWGCF/EbyEFluctuations/Tasks/FactorialMomentsTask.cxx index f91bfb86088..9ca0bbb7e3f 100644 --- a/PWGCF/EbyEFluctuations/Tasks/FactorialMomentsTask.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/FactorialMomentsTask.cxx @@ -431,8 +431,9 @@ struct FactorialMomentsTask { histos.fill(HIST("mNFractionShClsTPC"), track.tpcFractionSharedCls()); histos.fill(HIST("mSharedClsvsPt"), track.pt(), track.tpcNClsShared()); histos.fill(HIST("mSharedClsProbvsPt"), track.pt(), track.tpcFractionSharedCls() / track.tpcNClsCrossedRows()); - checkpT(track); - //} + if (applyCheckPtForRec && !applyCheckPtForMC) { + checkpT(track); + } } auto mcParts = mcParticles.sliceBy(perMcCollision, coll.mcCollision().globalIndex()); for (auto const& mc : mcParts) { From a8722ea243bb4ce6dd8da93379579defc1dfec40 Mon Sep 17 00:00:00 2001 From: Preet-Bhanjan Date: Mon, 23 Feb 2026 17:32:33 +0100 Subject: [PATCH 046/347] [PWGCF] Addition of QA for TPC dEdx (#15088) Co-authored-by: Preet Pati Co-authored-by: ALICE Action Bot --- .../Tasks/pidDiHadron.cxx | 74 +++++++++++++++---- 1 file changed, 58 insertions(+), 16 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/pidDiHadron.cxx b/PWGCF/TwoParticleCorrelations/Tasks/pidDiHadron.cxx index b6bd2c3afcc..66890f79424 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/pidDiHadron.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/pidDiHadron.cxx @@ -118,6 +118,7 @@ struct PidDiHadron { O2_DEFINE_CONFIGURABLE(cfgUseOnlyTPC, bool, true, "Use only TPC PID for daughter selection") O2_DEFINE_CONFIGURABLE(cfgPIDParticle, int, 0, "1 = pion, 2 = kaon, 3 = proton, 4 = kshort, 5 = lambda, 6 = phi, 0 for no PID") O2_DEFINE_CONFIGURABLE(cfgGetNsigmaQA, bool, true, "Get QA histograms for selection of pions, kaons, and protons") + O2_DEFINE_CONFIGURABLE(cfgGetdEdx, bool, true, "Get QA histograms for selection of pions, kaons, and protons") O2_DEFINE_CONFIGURABLE(cfgUseAntiLambda, bool, true, "Use AntiLambda candidates for analysis") O2_DEFINE_CONFIGURABLE(cfgPIDUseRejection, bool, true, "Turn off and on the exclusion criteria for PID determination") @@ -172,6 +173,7 @@ struct PidDiHadron { ConfigurableAxis axisNsigmaTOF{"axisNsigmaTOF", {80, -5, 5}, "nsigmaTOF axis"}; ConfigurableAxis axisNsigmaITS{"axisNsigmaITS", {80, -5, 5}, "nsigmaITS axis"}; ConfigurableAxis axisTpcSignal{"axisTpcSignal", {250, 0, 250}, "dEdx axis for TPC"}; + ConfigurableAxis axisSigma{"axisSigma", {200, 0, 20}, "sigma axis for TPC"}; Configurable> cfgUseEventCuts{"cfgUseEventCuts", {LongArrayInt[0], 15, 1, {"Filtered Events", "Sel8", "kNoTimeFrameBorder", "kNoITSROFrameBorder", "kNoSameBunchPileup", "kIsGoodZvtxFT0vsPV", "kNoCollInTimeRangeStandard", "kIsGoodITSLayersAll", "kNoCollInRofStandard", "kNoHighMultCollInPrevRof", "Occupancy", "Multcorrelation", "T0AV0ACut", "kIsVertexITSTPC", "kTVXinTRD"}, {"EvCuts"}}, "Labeled array (int) for various cuts on resonances"}; Configurable> nSigmas{"nSigmas", {LongArrayFloat[0], 6, 3, {"UpCut_pi", "UpCut_ka", "UpCut_pr", "LowCut_pi", "LowCut_ka", "LowCut_pr"}, {"TPC", "TOF", "ITS"}}, "Labeled array for n-sigma values for TPC, TOF, ITS for pions, kaons, protons (positive and negative)"}; @@ -497,15 +499,18 @@ struct PidDiHadron { if (!cfgUseItsPID) { histos.add("TofTpcNsigma_before", "", {HistType::kTHnSparseD, {{axisNsigmaTPC, axisNsigmaTOF, axisPt}}}); histos.add("TofTpcNsigma_after", "", {HistType::kTHnSparseD, {{axisNsigmaTPC, axisNsigmaTOF, axisPt}}}); - } + + if (cfgGetdEdx) { + histos.add("TpcdEdx_ptwise", "", {HistType::kTHnSparseD, {{axisPt, axisTpcSignal, axisNsigmaTOF}}}); + histos.add("ExpTpcdEdx_ptwise", "", {HistType::kTHnSparseD, {{axisPt, axisTpcSignal, axisNsigmaTOF}}}); + histos.add("ExpSigma_ptwise", "", {HistType::kTHnSparseD, {{axisPt, axisSigma, axisNsigmaTOF}}}); + } + } // TPC-TOF PID QA hists if (cfgUseItsPID) { histos.add("TofItsNsigma_before", "", {HistType::kTHnSparseD, {{axisNsigmaITS, axisNsigmaTOF, axisPt}}}); histos.add("TofItsNsigma_after", "", {HistType::kTHnSparseD, {{axisNsigmaITS, axisNsigmaTOF, axisPt}}}); - } - - histos.add("TpcdEdx_ptwise", "", {HistType::kTH2D, {{axisTpcSignal, axisPt}}}); - histos.add("TpcdEdx_ptwise_afterCut", "", {HistType::kTH2D, {{axisTpcSignal, axisPt}}}); - } + } // ITS-TOF PID QA hists + } // end of PID QA hists } if (cfgPIDParticle == kK0 || cfgPIDParticle == kLambda || cfgPIDParticle == kPhi) { @@ -527,6 +532,14 @@ struct PidDiHadron { histos.add("hNsigmaPionTrue", "hNsigmaPionTrue", {HistType::kTH1D, {axisPt}}); // All true pions from MC histos.add("hNsigmaKaonTrue", "hNsigmaKaonTrue", {HistType::kTH1D, {axisPt}}); // All true kaons from MC histos.add("hNsigmaProtonTrue", "hNsigmaProtonTrue", {HistType::kTH1D, {axisPt}}); // All true protons from MC + + histos.add("TpcdEdx_ptwise_pi", "", {HistType::kTHnSparseD, {{axisPt, axisTpcSignal, axisNsigmaTOF}}}); + histos.add("TpcdEdx_ptwise_ka", "", {HistType::kTHnSparseD, {{axisPt, axisTpcSignal, axisNsigmaTOF}}}); + histos.add("TpcdEdx_ptwise_pr", "", {HistType::kTHnSparseD, {{axisPt, axisTpcSignal, axisNsigmaTOF}}}); + + histos.add("ExpTpcdEdx_ptwise_pi", "", {HistType::kTHnSparseD, {{axisPt, axisTpcSignal, axisNsigmaTOF}}}); + histos.add("ExpTpcdEdx_ptwise_ka", "", {HistType::kTHnSparseD, {{axisPt, axisTpcSignal, axisNsigmaTOF}}}); + histos.add("ExpTpcdEdx_ptwise_pr", "", {HistType::kTHnSparseD, {{axisPt, axisTpcSignal, axisNsigmaTOF}}}); } histos.add("eventcount", "bin", {HistType::kTH1F, {{4, 0, 4, "bin"}}}); // histogram to see how many events are in the same and mixed event @@ -839,12 +852,36 @@ struct PidDiHadron { // Fill Nsigma QA if (cfgGetNsigmaQA && !cfgUseItsPID) { - if (cfgPIDParticle == kPions) + if (cfgPIDParticle == kPions) { histos.fill(HIST("TofTpcNsigma_before"), track1.tpcNSigmaPi(), track1.tofNSigmaPi(), track1.pt()); - if (cfgPIDParticle == kKaons) + if (cfgGetdEdx) { + double tpcExpSignalPi = track1.tpcSignal() - (track1.tpcNSigmaPi() * track1.tpcExpSigmaPi()); + + histos.fill(HIST("TpcdEdx_ptwise"), track1.pt(), track1.tpcSignal(), track1.tofNSigmaPi()); + histos.fill(HIST("ExpTpcdEdx_ptwise"), track1.pt(), tpcExpSignalPi, track1.tofNSigmaPi()); + histos.fill(HIST("ExpSigma_ptwise"), track1.pt(), track1.tpcExpSigmaPi(), track1.tofNSigmaPi()); + } + } + if (cfgPIDParticle == kKaons) { histos.fill(HIST("TofTpcNsigma_before"), track1.tpcNSigmaKa(), track1.tofNSigmaKa(), track1.pt()); - if (cfgPIDParticle == kProtons) + if (cfgGetdEdx) { + double tpcExpSignalKa = track1.tpcSignal() - (track1.tpcNSigmaKa() * track1.tpcExpSigmaKa()); + + histos.fill(HIST("TpcdEdx_ptwise"), track1.pt(), track1.tpcSignal(), track1.tofNSigmaKa()); + histos.fill(HIST("ExpTpcdEdx_ptwise"), track1.pt(), tpcExpSignalKa, track1.tofNSigmaKa()); + histos.fill(HIST("ExpSigma_ptwise"), track1.pt(), track1.tpcExpSigmaKa(), track1.tofNSigmaKa()); + } + } + if (cfgPIDParticle == kProtons) { histos.fill(HIST("TofTpcNsigma_before"), track1.tpcNSigmaPr(), track1.tofNSigmaPr(), track1.pt()); + if (cfgGetdEdx) { + double tpcExpSignalPr = track1.tpcSignal() - (track1.tpcNSigmaPr() * track1.tpcExpSigmaPr()); + + histos.fill(HIST("TpcdEdx_ptwise"), track1.pt(), track1.tpcSignal(), track1.tofNSigmaPr()); + histos.fill(HIST("ExpTpcdEdx_ptwise"), track1.pt(), tpcExpSignalPr, track1.tofNSigmaPr()); + histos.fill(HIST("ExpSigma_ptwise"), track1.pt(), track1.tpcExpSigmaPr(), track1.tofNSigmaPr()); + } + } } if (cfgGetNsigmaQA && cfgUseItsPID) { if (cfgPIDParticle == kPions) @@ -855,18 +892,12 @@ struct PidDiHadron { histos.fill(HIST("TofItsNsigma_before"), itsResponse.nSigmaITS(track1), track1.tofNSigmaPr(), track1.pt()); } - if (cfgGetNsigmaQA) - histos.fill(HIST("TpcdEdx_ptwise"), track1.tpcSignal(), track1.pt()); - if (cfgPIDParticle && getNsigmaPID(track1) != cfgPIDParticle) continue; // if PID is selected, check if the track has the right PID if (cfgGetNsigmaQA) fillNsigmaAfterCut(track1, cfgPIDParticle); - if (cfgGetNsigmaQA) - histos.fill(HIST("TpcdEdx_ptwise_afterCut"), track1.tpcSignal(), track1.pt()); - if (!getEfficiencyCorrection(triggerWeight, track1.eta(), track1.pt(), posZ)) continue; if (system == SameEvent) { @@ -1518,6 +1549,10 @@ struct PidDiHadron { // Check the PDG code for the particles (MC truth) and match with analysed Nsigma PID if (std::abs(track.mcParticle().pdgCode()) == PDG_t::kPiPlus) { histos.fill(HIST("hNsigmaPionTrue"), track.pt()); + histos.fill(HIST("TpcdEdx_ptwise_pi"), track.pt(), track.tpcSignal(), track.tofNSigmaPi()); + + double tpcExpSignalPi = track.tpcSignal() - (track.tpcNSigmaPi() * track.tpcExpSigmaPi()); + histos.fill(HIST("ExpTpcdEdx_ptwise_pi"), track.pt(), tpcExpSignalPi, track.tofNSigmaPi()); if (pidIndex == kPions) { histos.fill(HIST("hNsigmaPionTruePositives"), track.pt()); @@ -1526,6 +1561,10 @@ struct PidDiHadron { if (std::abs(track.mcParticle().pdgCode()) == PDG_t::kKPlus) { histos.fill(HIST("hNsigmaKaonTrue"), track.pt()); + histos.fill(HIST("TpcdEdx_ptwise_ka"), track.pt(), track.tpcSignal(), track.tofNSigmaKa()); + + double tpcExpSignalKa = track.tpcSignal() - (track.tpcNSigmaKa() * track.tpcExpSigmaKa()); + histos.fill(HIST("ExpTpcdEdx_ptwise_ka"), track.pt(), tpcExpSignalKa, track.tofNSigmaKa()); if (pidIndex == kKaons) { histos.fill(HIST("hNsigmaKaonTruePositives"), track.pt()); @@ -1534,12 +1573,15 @@ struct PidDiHadron { if (std::abs(track.mcParticle().pdgCode()) == PDG_t::kProton) { histos.fill(HIST("hNsigmaProtonTrue"), track.pt()); + histos.fill(HIST("TpcdEdx_ptwise_pr"), track.pt(), track.tpcSignal(), track.tofNSigmaPr()); + + double tpcExpSignalPr = track.tpcSignal() - (track.tpcNSigmaPr() * track.tpcExpSigmaPr()); + histos.fill(HIST("ExpTpcdEdx_ptwise_pr"), track.pt(), tpcExpSignalPr, track.tofNSigmaPr()); if (pidIndex == kProtons) { histos.fill(HIST("hNsigmaProtonTruePositives"), track.pt()); } } // Proton condition - } // end of tracks MC loop } // end of process MC PROCESS_SWITCH(PidDiHadron, processMC, "Process Monte Carlo", true); From d3bd2724bbe07c0fd02bab69d41b94b4f73fc66b Mon Sep 17 00:00:00 2001 From: lcernusa Date: Mon, 23 Feb 2026 17:33:21 +0100 Subject: [PATCH 047/347] [PWGCF] Solved run-by-run histo bug (#15091) --- .../TwoParticleCorrelations/Tasks/longRangeDihadronCor.cxx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/longRangeDihadronCor.cxx b/PWGCF/TwoParticleCorrelations/Tasks/longRangeDihadronCor.cxx index 3977ba0edac..f50d8f15e6c 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/longRangeDihadronCor.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/longRangeDihadronCor.cxx @@ -691,7 +691,8 @@ struct LongRangeDihadronCor { ampl = ampl / cstFT0RelGain[id]; if (system == SameEvent) { registry.fill(HIST("FT0AmpCorrect"), id, ampl); - histAmpCorrectPerRun[lastRunNumber]->Fill(id, ampl); + if (cfgFwdConfig.cfgRunbyRunAmplitudeFT0) + histAmpCorrectPerRun[lastRunNumber]->Fill(id, ampl); } } else if (fitType == kFT0A) { id = ft0.channelA()[iCh]; @@ -703,7 +704,8 @@ struct LongRangeDihadronCor { ampl = ampl / cstFT0RelGain[id]; if (system == SameEvent) { registry.fill(HIST("FT0AmpCorrect"), id, ampl); - histAmpCorrectPerRun[lastRunNumber]->Fill(id, ampl); + if (cfgFwdConfig.cfgRunbyRunAmplitudeFT0) + histAmpCorrectPerRun[lastRunNumber]->Fill(id, ampl); } } else { LOGF(fatal, "Cor Index %d out of range", fitType); From a9ea3913ce037d2424fa169d74e95a4efa19987c Mon Sep 17 00:00:00 2001 From: Zhiyong <71517277+Luzhiyongg@users.noreply.github.com> Date: Mon, 23 Feb 2026 18:14:17 +0100 Subject: [PATCH 048/347] [PWGCF] Add new histograms for pt and delta pt distributions (#15120) --- PWGCF/Flow/Tasks/flowTask.cxx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/PWGCF/Flow/Tasks/flowTask.cxx b/PWGCF/Flow/Tasks/flowTask.cxx index b74f2d5bb15..3e3fbb181dc 100644 --- a/PWGCF/Flow/Tasks/flowTask.cxx +++ b/PWGCF/Flow/Tasks/flowTask.cxx @@ -394,6 +394,8 @@ struct FlowTask { registry.add("PtVariance_partB_WithinGap08", "", {HistType::kTProfile, {axisIndependent}}); if (cfgAdditionObs.cfgDptDisEnable) { registry.add("hNormDeltaPt_X", "; #delta p_{T}/[p_{T}]; X", {HistType::kTH2D, {cfgAdditionObs.cfgDptDisAxisNormal, axisIndependent}}); + registry.add("hNormDeltaPt_X_afterCut", "; #delta p_{T}/[p_{T}]; X", {HistType::kTH2D, {cfgAdditionObs.cfgDptDisAxisNormal, axisIndependent}}); + registry.add("hPt_afterDptCut", "p_{T} distribution", {HistType::kTH1D, {axisPt}}); } if (doprocessMCGen) { registry.add("MCGen/MChPhi", "#phi distribution", {HistType::kTH1D, {axisPhi}}); @@ -1222,6 +1224,7 @@ struct FlowTask { std::vector consistentEventVector = cfgUserIO.cfgConsistentEventVector; if (cfgUserIO.cfgConsistentEventFlag) LOGF(info, "consistentEventVector.size = %u", consistentEventVector.size()); + std::vector ptVec; double psi2Est = 0, psi3Est = 0, psi4Est = 0; float wEPeff = 1; @@ -1290,6 +1293,8 @@ struct FlowTask { } } registry.fill(HIST("hPt"), track.pt()); + if (cfgAdditionObs.cfgDptDisEnable) + ptVec.push_back(track.pt()); if (cfgAdditionObs.cfgV02Enabled && track.eta() >= cfgAdditionObs.cfgV02FracEtaMin && track.eta() <= cfgAdditionObs.cfgV02FracEtaMax) { cfgAdditionObs.listPtX[0]->Fill(independent, track.pt(), weff); cfgAdditionObs.listPtX[sampleIndex + 1]->Fill(independent, track.pt(), weff); @@ -1373,6 +1378,11 @@ struct FlowTask { // only keep high 10% dpt event return; } + registry.fill(HIST("hNormDeltaPt_X_afterCut"), normDeltaPt, independent, weffEvent); + if (ptVec.size() > 0) { + for (auto trpt : ptVec) + registry.fill(HIST("hPt_afterDptCut"), trpt); + } } double weffEventDiffWithGap08 = weffEventWithinGap08 * weffEventWithinGap08 - weffEventSquareWithinGap08; From 20ca41eaaa59e2f08a1a8b4537a5dc9e45212ce2 Mon Sep 17 00:00:00 2001 From: omvazque Date: Mon, 23 Feb 2026 12:02:54 -0600 Subject: [PATCH 049/347] [PWGLF] Reduces disk space by using TH2 instead of TH3 (#15109) --- PWGLF/Tasks/Nuspex/piKpRAA.cxx | 304 ++------------------------------- 1 file changed, 16 insertions(+), 288 deletions(-) diff --git a/PWGLF/Tasks/Nuspex/piKpRAA.cxx b/PWGLF/Tasks/Nuspex/piKpRAA.cxx index c42d395cd42..9d046f974db 100644 --- a/PWGLF/Tasks/Nuspex/piKpRAA.cxx +++ b/PWGLF/Tasks/Nuspex/piKpRAA.cxx @@ -81,10 +81,10 @@ using TracksMC = soa::Join, kNEtaHists> dEdxPiV0{}; -std::array, kNEtaHists> dEdxPrV0{}; -std::array, kNEtaHists> dEdxElV0{}; -std::array, kNEtaHists> dEdxPiTOF{}; +std::array, kNEtaHists> dEdxPiV0{}; +std::array, kNEtaHists> dEdxPrV0{}; +std::array, kNEtaHists> dEdxElV0{}; +std::array, kNEtaHists> dEdxPiTOF{}; std::array, kNEtaHists> dEdx{}; std::array, kNEtaHists> nClVsdEdxPiV0{}; std::array, kNEtaHists> nClVsdEdxElV0{}; @@ -218,7 +218,6 @@ struct PiKpRAA { Configurable selINELgt0{"selINELgt0", true, "Select INEL > 0?"}; Configurable isApplyFT0CbasedOccupancy{"isApplyFT0CbasedOccupancy", false, "T0C Occu cut"}; Configurable applyNchSel{"applyNchSel", false, "Use mid-rapidity-based Nch selection"}; - Configurable skipRecoColGTOne{"skipRecoColGTOne", true, "Remove collisions if reconstructed more than once"}; // Event selection Configurable posZcut{"posZcut", +10.0, "z-vertex position cut"}; @@ -489,10 +488,10 @@ struct PiKpRAA { for (int i = 0; i < kNEtaHists; ++i) { dEdx[i] = registry.add(Form("dEdx_%s", endingEta[i]), Form("%s;Momentum (GeV/#it{c});dE/dx;", latexEta[i]), kTH3F, {axisPt, axisdEdx, axisCent}); pTVsP[i] = registry.add(Form("pTVsP_%s", endingEta[i]), Form("%s;Momentum (GeV/#it{c});#it{p}_{T} (GeV/#it{c});", latexEta[i]), kTH2F, {axisPt, axisPt}); - dEdxPiV0[i] = registry.add(Form("dEdxPiV0_%s", endingEta[i]), Form("#pi^{+} + #pi^{-}, %s;Momentum (GeV/#it{c});dE/dx;", latexEta[i]), kTH3F, {axisPtV0s, axisdEdx, axisCent}); - dEdxPrV0[i] = registry.add(Form("dEdxPrV0_%s", endingEta[i]), Form("p + #bar{p}, %s;Momentum (GeV/#it{c});dE/dx;", latexEta[i]), kTH3F, {axisPtV0s, axisdEdx, axisCent}); - dEdxElV0[i] = registry.add(Form("dEdxElV0_%s", endingEta[i]), Form("e^{+} + e^{-}, %s;Momentum (GeV/#it{c});dE/dx;", latexEta[i]), kTH3F, {axisPtV0s, axisdEdx, axisCent}); - dEdxPiTOF[i] = registry.add(Form("dEdxPiTOF_%s", endingEta[i]), Form("#pi^{+} + #pi^{-}, %s;Momentum (GeV/#it{c});dE/dx;", latexEta[i]), kTH3F, {axisPtV0s, axisdEdx, axisCent}); + dEdxPiV0[i] = registry.add(Form("dEdxPiV0_%s", endingEta[i]), Form("#pi^{+} + #pi^{-}, %s;Momentum (GeV/#it{c});dE/dx;", latexEta[i]), kTH2F, {axisPtV0s, axisdEdx}); + dEdxPrV0[i] = registry.add(Form("dEdxPrV0_%s", endingEta[i]), Form("p + #bar{p}, %s;Momentum (GeV/#it{c});dE/dx;", latexEta[i]), kTH2F, {axisPtV0s, axisdEdx}); + dEdxElV0[i] = registry.add(Form("dEdxElV0_%s", endingEta[i]), Form("e^{+} + e^{-}, %s;Momentum (GeV/#it{c});dE/dx;", latexEta[i]), kTH2F, {axisPtV0s, axisdEdx}); + dEdxPiTOF[i] = registry.add(Form("dEdxPiTOF_%s", endingEta[i]), Form("#pi^{+} + #pi^{-}, %s;Momentum (GeV/#it{c});dE/dx;", latexEta[i]), kTH2F, {axisPtV0s, axisdEdx}); nClVsdEdxPiV0[i] = registry.add(Form("NclVsdEdxPiV0_%s", endingEta[i]), Form("%s;#it{N}_{cl} used for PID;dE/dx;", latexEta[i]), kTH2F, {axisNcl, axisdEdx}); nClVsdEdxElV0[i] = registry.add(Form("NclVsdEdxElV0_%s", endingEta[i]), Form("%s;#it{N}_{cl} used for PID;dE/dx;", latexEta[i]), kTH2F, {axisNcl, axisdEdx}); nClVsdEdxPrV0[i] = registry.add(Form("NclVsdEdxPrV0_%s", endingEta[i]), Form("%s;#it{N}_{cl} used for PID;dE/dx;", latexEta[i]), kTH2F, {axisNcl, axisdEdx}); @@ -525,7 +524,7 @@ struct PiKpRAA { xtrkSel->SetBinLabel(12, "Passed all"); } - if (doprocessMC || doprocessSim) { + if (doprocessSim) { registry.add("zPosMC", "Generated Events With at least One Rec. Collision + Sel. criteria;;Entries;", kTH1F, {axisZpos}); registry.add("dcaVsPtPiDec", "Secondary pions from decays;#it{p}_{T} (GeV/#it{c});DCA_{xy} (cm);Centrality Perc.;", kTH3F, {axisPt, axisDCAxy, axisCent}); registry.add("dcaVsPtPrDec", "Secondary protons from decays;#it{p}_{T} (GeV/#it{c});DCA_{xy} (cm);Centrality Perc.;", kTH3F, {axisPt, axisDCAxy, axisCent}); @@ -534,19 +533,6 @@ struct PiKpRAA { registry.add("NclVsPhip", Form("#LTNcl#GT used for PID;%s (GeV/#it{c});#varphi", titlePorPt.data()), kTProfile2D, {{{axisXPhiCut}, {350, 0.0, 0.35}}}); } - if (doprocessMC) { - - registry.add("EventCounterMC", "Event counter", kTH1F, {axisEvent}); - - registry.add("PtPiVsCent", "", kTH2F, {axisPt, axisCent}); - registry.add("PtKaVsCent", "", kTH2F, {axisPt, axisCent}); - registry.add("PtPrVsCent", "", kTH2F, {axisPt, axisCent}); - - registry.add("PtPiVsCentMC", "", kTH2F, {axisPt, axisCent}); - registry.add("PtKaVsCentMC", "", kTH2F, {axisPt, axisCent}); - registry.add("PtPrVsCentMC", "", kTH2F, {axisPt, axisCent}); - } - if (doprocessSim) { // MC events passing the TVX requirement @@ -906,7 +892,7 @@ struct PiKpRAA { // registry.fill(HIST("TOFExpEl2TOF"), momentum, tExpElTOF / tTOF); if (std::abs((tExpPiTOF / tTOF) - kOne) < v0Selections.maxExpTOFPi) { - dEdxPiTOF[indexEta]->Fill(momentum, dedx, centrality); + dEdxPiTOF[indexEta]->Fill(momentum, dedx); } } } @@ -1042,8 +1028,8 @@ struct PiKpRAA { nClVsdEdxPiV0[posIndexEta]->Fill(posNcl, posTrkdEdx); nClVsdEdxpPiV0[posIndexEta]->Fill(posNcl, posTrkdEdx); nClVsPpPiV0[negIndexEta]->Fill(negPorPt, negNcl); - dEdxPiV0[posIndexEta]->Fill(posTrkP, posTrkdEdx, centrality); - dEdxPiV0[negIndexEta]->Fill(negTrkP, negTrkdEdx, centrality); + dEdxPiV0[posIndexEta]->Fill(posTrkP, posTrkdEdx); + dEdxPiV0[negIndexEta]->Fill(negTrkP, negTrkdEdx); if (posTrkP > kMinPMIP && posTrkP < kMaxPMIP && posTrkdEdx > kMindEdxMIP && posTrkdEdx < kMaxdEdxMIP) { registry.fill(HIST("dEdxVsEtaPiMIPV0"), posTrkEta, posTrkdEdx); @@ -1068,7 +1054,7 @@ struct PiKpRAA { nClVsPpPrV0[posIndexEta]->Fill(posPorPt, posNcl); nClVsdEdxPrV0[posIndexEta]->Fill(posNcl, posTrkdEdx); nClVsdEdxpPrV0[posIndexEta]->Fill(posNcl, posTrkdEdx); - dEdxPrV0[posIndexEta]->Fill(posTrkP, posTrkdEdx, centrality); + dEdxPrV0[posIndexEta]->Fill(posTrkP, posTrkdEdx); } if (negTrackCharge < kZero) { registry.fill(HIST("nSigPiFromL"), negTrkPt, negTrack.tpcNSigmaPi()); @@ -1104,7 +1090,7 @@ struct PiKpRAA { nClVsPpPrV0[negIndexEta]->Fill(negPorPt, negNcl); nClVsdEdxPrV0[negIndexEta]->Fill(negNcl, negTrkdEdx); nClVsdEdxpPrV0[negIndexEta]->Fill(negNcl, negTrkdEdx); - dEdxPrV0[negIndexEta]->Fill(negTrkP, negTrkdEdx, centrality); + dEdxPrV0[negIndexEta]->Fill(negTrkP, negTrkdEdx); } } @@ -1139,8 +1125,8 @@ struct PiKpRAA { registry.fill(HIST("dEdxVsEtaElMIPV0p"), posTrkEta, posTrkdEdx); registry.fill(HIST("dEdxVsEtaElMIPV0"), negTrkEta, negTrkdEdx); registry.fill(HIST("dEdxVsEtaElMIPV0p"), negTrkEta, negTrkdEdx); - dEdxElV0[posIndexEta]->Fill(posTrkP, posTrkdEdx, centrality); - dEdxElV0[negIndexEta]->Fill(negTrkP, negTrkdEdx, centrality); + dEdxElV0[posIndexEta]->Fill(posTrkP, posTrkdEdx); + dEdxElV0[negIndexEta]->Fill(negTrkP, negTrkdEdx); } } } // v0s @@ -1149,264 +1135,6 @@ struct PiKpRAA { Preslice perCollision = aod::track::collisionId; Service pdg; - void processMC(aod::McCollisions::iterator const& mccollision, soa::SmallGroups const& collisions, BCsRun3 const& /*bcs*/, aod::FT0s const& /*ft0s*/, aod::McParticles const& mcParticles, TracksMC const& tracksMC) - { - for (const auto& collision : collisions) { - // Event selection - if (!isEventSelected(collision)) { - continue; - } - // MC collision? - if (!collision.has_mcCollision()) { - continue; - } - - registry.fill(HIST("EventCounterMC"), EvCutLabel::All); - - if (std::fabs(mccollision.posZ()) > posZcut) - continue; - - registry.fill(HIST("zPos"), collision.posZ()); - registry.fill(HIST("zPosMC"), mccollision.posZ()); - registry.fill(HIST("EventCounterMC"), EvCutLabel::VtxZ); - - const auto& foundBC = collision.foundBC_as(); - uint64_t timeStamp{foundBC.timestamp()}; - const int magField{getMagneticField(timeStamp)}; - - if (v0Selections.applyPhiCut) { - const int nextRunNumber{foundBC.runNumber()}; - if (currentRunNumberPhiSel != nextRunNumber) { - loadPhiCutSelections(timeStamp); - currentRunNumberPhiSel = nextRunNumber; - LOG(info) << "\tcurrentRunNumberPhiSel= " << currentRunNumberPhiSel << " timeStamp = " << timeStamp; - } - - // return if phi cut objects are nullptr - if (!(phiCut.hPhiCutHigh && phiCut.hPhiCutLow)) - return; - } - - // Remove collisions if reconstructed more than once - if (skipRecoColGTOne && (collisions.size() > kOne)) - continue; - - const float centrality{isT0Ccent ? collision.centFT0C() : collision.centFT0M()}; - registry.fill(HIST("T0Ccent"), centrality); - - const auto& groupedTracks{tracksMC.sliceBy(perCollision, collision.globalIndex())}; - - // Track selection with Open DCAxy - for (const auto& track : groupedTracks) { - // Track Selection - if (track.eta() < v0Selections.minEtaDaughter || track.eta() > v0Selections.maxEtaDaughter) - continue; - - if (track.pt() < v0Selections.minPt || track.pt() > v0Selections.maxPt) - continue; - - if (!trkSelGlobalOpenDCAxy.IsSelected(track)) - continue; - - if (!track.has_mcParticle()) - continue; - - // Get the MC particle - const auto& particle{track.mcParticle()}; - auto charge{0.}; - auto* pdgParticle = pdg->GetParticle(particle.pdgCode()); - if (pdgParticle != nullptr) - charge = pdgParticle->Charge(); - else - continue; - - // Is it a charged particle? - if (std::abs(charge) < kMinCharge) - continue; - - float phiPrime{track.phi()}; - phiPrimeFunc(phiPrime, magField, charge); - - const float pOrPt{v0Selections.usePinPhiSelection ? track.p() : track.pt()}; - if (v0Selections.applyPhiCut) { - if (!passesPhiSelection(pOrPt, phiPrime)) - continue; - } - - const int16_t nclFound{track.tpcNClsFound()}; - const int16_t nclPID{track.tpcNClsPID()}; - const int16_t ncl = v0Selections.useNclsPID ? nclPID : nclFound; - if (v0Selections.applyNclSel && ncl < v0Selections.minNcl) - continue; - - bool isPrimary{false}; - bool isDecay{false}; - bool isMaterial{false}; - if (particle.isPhysicalPrimary()) - isPrimary = true; - else if (particle.getProcess() == TMCProcess::kPDecay) - isDecay = true; - else - isMaterial = true; - - bool isPi{false}; - bool isPr{false}; - if (particle.pdgCode() == PDG_t::kPiPlus || particle.pdgCode() == PDG_t::kPiMinus) - isPi = true; - else if (particle.pdgCode() == PDG_t::kProton || particle.pdgCode() == PDG_t::kProtonBar) - isPr = true; - else - continue; - - if (isPrimary && !isDecay && !isMaterial) { - if (isPi && !isPr) - registry.fill(HIST("dcaVsPtPi"), track.pt(), track.dcaXY(), centrality); - if (isPr && !isPi) - registry.fill(HIST("dcaVsPtPr"), track.pt(), track.dcaXY(), centrality); - } - - if (isDecay && !isPrimary && !isMaterial) { - if (isPi && !isPr) - registry.fill(HIST("dcaVsPtPiDec"), track.pt(), track.dcaXY(), centrality); - if (isPr && !isPi) - registry.fill(HIST("dcaVsPtPrDec"), track.pt(), track.dcaXY(), centrality); - } - - if (isMaterial && !isPrimary && !isDecay) { - if (isPi && !isPr) - registry.fill(HIST("dcaVsPtPiMat"), track.pt(), track.dcaXY(), centrality); - if (isPr && !isPi) - registry.fill(HIST("dcaVsPtPrMat"), track.pt(), track.dcaXY(), centrality); - } - } - - // Global track + DCAxy selections - for (const auto& track : groupedTracks) { - // Track Selection - if (track.eta() < v0Selections.minEtaDaughter || track.eta() > v0Selections.maxEtaDaughter) - continue; - - if (track.pt() < v0Selections.minPt || track.pt() > v0Selections.maxPt) - continue; - - if (!trkSelGlobal.IsSelected(track)) - continue; - - // Has MC particle? - if (!track.has_mcParticle()) - continue; - - // Get the MC particle - const auto& particle{track.mcParticle()}; - auto charge{0.}; - auto* pdgParticle = pdg->GetParticle(particle.pdgCode()); - if (pdgParticle != nullptr) - charge = pdgParticle->Charge(); - else - continue; - - // Is it a charged particle? - if (std::abs(charge) < kMinCharge) - continue; - - float phiPrime{track.phi()}; - phiPrimeFunc(phiPrime, magField, charge); - - const float pOrPt{v0Selections.usePinPhiSelection ? track.p() : track.pt()}; - if (v0Selections.applyPhiCut) { - if (!passesPhiSelection(pOrPt, phiPrime)) - continue; - } - - const int16_t nclFound{track.tpcNClsFound()}; - const int16_t nclPID{track.tpcNClsPID()}; - const int16_t ncl = v0Selections.useNclsPID ? nclPID : nclFound; - if (v0Selections.applyNclSel && ncl < v0Selections.minNcl) - continue; - - int indexEta{-999}; - const float eta{track.eta()}; - for (int i = 0; i < kNEtaHists; ++i) { - if (eta >= kLowEta[i] && eta < kHighEta[i]) { - indexEta = i; - break; - } - } - - if (indexEta < kZeroInt || indexEta > kSevenInt) - continue; - - registry.fill(HIST("NclVsPhip"), pOrPt, phiPrime, ncl); - registry.fill(HIST("NclVsEtaPID"), eta, ncl); - registry.fill(HIST("NclVsEtaPIDp"), eta, ncl); - - bool isPrimary{false}; - if (particle.isPhysicalPrimary()) - isPrimary = true; - - if (!isPrimary) - continue; - - bool isPi{false}; - bool isKa{false}; - bool isPr{false}; - - if (particle.pdgCode() == PDG_t::kPiPlus || particle.pdgCode() == PDG_t::kPiMinus) - isPi = true; - else if (particle.pdgCode() == PDG_t::kKPlus || particle.pdgCode() == PDG_t::kKMinus) - isKa = true; - else if (particle.pdgCode() == PDG_t::kProton || particle.pdgCode() == PDG_t::kProtonBar) - isPr = true; - else - continue; - - if (isPi && !isKa && !isPr) - registry.fill(HIST("PtPiVsCent"), track.pt(), centrality); - if (isKa && !isPi && !isPr) - registry.fill(HIST("PtKaVsCent"), track.pt(), centrality); - if (isPr && !isPi && !isKa) - registry.fill(HIST("PtPrVsCent"), track.pt(), centrality); - } - - // Generated MC - for (const auto& particle : mcParticles) { - if (particle.eta() < v0Selections.minEtaDaughter || particle.eta() > v0Selections.maxEtaDaughter) - continue; - - if (particle.pt() < v0Selections.minPt || particle.pt() > v0Selections.maxPt) - continue; - - auto charge{0.}; - // Get the MC particle - auto* pdgParticle = pdg->GetParticle(particle.pdgCode()); - if (pdgParticle != nullptr) - charge = pdgParticle->Charge(); - else - continue; - - // Is it a charged particle? - if (std::abs(charge) < kMinCharge) - continue; - - // Is it a primary particle? - bool isPrimary{true}; - if (!particle.isPhysicalPrimary()) - isPrimary = false; - - if (isPrimary) { - if (particle.pdgCode() == PDG_t::kPiPlus || particle.pdgCode() == PDG_t::kPiMinus) // pion - registry.fill(HIST("PtPiVsCentMC"), particle.pt(), centrality); - else if (particle.pdgCode() == PDG_t::kKPlus || particle.pdgCode() == PDG_t::kKMinus) // kaon - registry.fill(HIST("PtKaVsCentMC"), particle.pt(), centrality); - else if (particle.pdgCode() == PDG_t::kProton || particle.pdgCode() == PDG_t::kProtonBar) // proton - registry.fill(HIST("PtPrVsCentMC"), particle.pt(), centrality); - else - continue; - } - } - } // Collisions - } - PROCESS_SWITCH(PiKpRAA, processMC, "Process MC closure", false); void processSim(aod::McCollisions::iterator const& mccollision, soa::SmallGroups const& collisions, BCsRun3 const& /*bcs*/, aod::FT0s const& /*ft0s*/, aod::McParticles const& mcParticles, TracksMC const& tracksMC) { From 4a04c9d271b4514ce18b6d96f8859b369c44463f Mon Sep 17 00:00:00 2001 From: Lucia Anna Tarasovicova Date: Mon, 23 Feb 2026 19:29:32 +0100 Subject: [PATCH 050/347] [ALICE3] update in the strangeness finding (#15072) Co-authored-by: Lucia Anna Tarasovicova --- .../TableProducer/alice3strangenessFinder.cxx | 308 +++++++++++++----- ALICE3/Tasks/alice3Strangeness.cxx | 8 +- 2 files changed, 231 insertions(+), 85 deletions(-) diff --git a/ALICE3/TableProducer/alice3strangenessFinder.cxx b/ALICE3/TableProducer/alice3strangenessFinder.cxx index 5419509d951..2d36590ede0 100644 --- a/ALICE3/TableProducer/alice3strangenessFinder.cxx +++ b/ALICE3/TableProducer/alice3strangenessFinder.cxx @@ -21,11 +21,13 @@ #include "PWGLF/DataModel/LFStrangenessTables.h" +#include "ALICE3/Core/TrackUtilities.h" #include "ALICE3/DataModel/OTFPIDTrk.h" #include "ALICE3/DataModel/OTFRICH.h" #include "ALICE3/DataModel/OTFStrangeness.h" #include "ALICE3/DataModel/OTFTOF.h" #include "ALICE3/DataModel/tracksAlice3.h" +#include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/TrackSelectionTables.h" @@ -36,6 +38,10 @@ #include "ReconstructionDataFormats/Track.h" #include #include +#include +#include + +#include #include @@ -45,8 +51,8 @@ using namespace o2::framework; using namespace o2::constants::physics; using Alice3TracksWPid = soa::Join; -using Alice3Tracks = soa::Join; - +using Alice3Tracks = soa::Join; +using Alice3MCParticles = soa::Join; struct Alice3strangenessFinder { SliceCache cache; @@ -57,9 +63,12 @@ struct Alice3strangenessFinder { Produces tableCascadeCores; Produces tableCascadeIndices; + Configurable buildCascade{"buildCascade", false, "build cascade candidates"}; + Configurable nSigmaTOF{"nSigmaTOF", 5.0f, "Nsigma for TOF PID (if enabled)"}; Configurable dcaXYconstant{"dcaXYconstant", -1.0f, "[0] in |DCAxy| > [0]+[1]/pT"}; Configurable dcaXYpTdep{"dcaXYpTdep", 0.0, "[1] in |DCAxy| > [0]+[1]/pT"}; + ConfigurableAxis axisPt{"axisPt", {VARIABLE_WIDTH, 0.0f, 0.025f, 0.05f, 0.075f, 0.1f, 0.125f, 0.15f, 0.175f, 0.2f, 0.225f, 0.25f, 0.275f, 0.3f, 0.325f, 0.35f, 0.375f, 0.4f, 0.425f, 0.45f, 0.475f, 0.5f, 0.525f, 0.55f, 0.575f, 0.6f, 0.625f, 0.65f, 0.675f, 0.7f, 0.725f, 0.75f, 0.775f, 0.8f, 0.82f, 0.85f, 0.875f, 0.9f, 0.925f, 0.95f, 0.975f, 1.0f, 1.05f, 1.1f}, "pt axis for QA histograms"}; Configurable bachMinConstDCAxy{"bachMinConstDCAxy", -1.0f, "[0] in |DCAxy| > [0]+[1]/pT"}; Configurable bachMinPtDepDCAxy{"bachMinPtDepDCAxy", 0.0, "[1] in |DCAxy| > [0]+[1]/pT"}; @@ -73,26 +82,31 @@ struct Alice3strangenessFinder { Configurable maxR{"maxR", 150., "reject PCA's above this radius"}; Configurable maxDZIni{"maxDZIni", 5, "reject (if>0) PCA candidate if tracks DZ exceeds threshold"}; Configurable maxDXYIni{"maxDXYIni", 4, "reject (if>0) PCA candidate if tracks DXY exceeds threshold"}; - Configurable maxVtxChi2{"maxVtxChi2", 2, "reject (if>0) vtx. chi2 above this value"}; + Configurable maxVtxChi2{"maxVtxChi2", 10, "reject (if>0) vtx. chi2 above this value"}; Configurable minParamChange{"minParamChange", 1.e-3, "stop iterations if largest change of any X is smaller than this"}; Configurable minRelChi2Change{"minRelChi2Change", 0.9, "stop iterations is chi2/chi2old > this"}; Configurable acceptedLambdaMassWindow{"acceptedLambdaMassWindow", 0.2f, "accepted Lambda mass window around PDG mass"}; - // Operation and minimisation criteria + // Operation Configurable magneticField{"magneticField", 20.0f, "Magnetic field (in kilogauss)"}; - Configurable doDCAplotsD{"doDCAplotsD", true, "do daughter prong DCA plots for D mesons"}; - Configurable doDCAplots3Prong{"doDCAplots3Prong", true, "do daughter prong DCA plots for Lc baryons"}; - Configurable doTopoPlotsForSAndB{"doTopoPlotsForSAndB", true, "do topological variable distributions for S and B separately"}; - Configurable dcaDaughtersSelection{"dcaDaughtersSelection", 1000.0f, "DCA between daughters (cm)"}; Configurable mcSameMotherCheck{"mcSameMotherCheck", true, "check if tracks come from the same MC mother"}; // propagation options Configurable usePropagator{"usePropagator", false, "use external propagator"}; Configurable refitWithMatCorr{"refitWithMatCorr", false, "refit V0 applying material corrections"}; Configurable useCollinearV0{"useCollinearV0", true, "use collinear approximation for V0 fitting"}; + Configurable maxIter{"maxIter", 30, "maximum number of iterations for vertex fitter"}; + + // for the ACTS study + Configurable isK0Gun{"isK0Gun", false, "is K0s Monte Carlo gun used"}; + Configurable isLambdaGun{"isLambdaGun", true, "is Lambda Monte Carlo gun used"}; + Configurable skipFitter{"skipFitter", false, "calculate V0 properties without calling the DCA fitter, using only the track parameters "}; + Configurable useOriginalTrackParams{"useOriginalTrackParams", false, "use original track parameters instead of the ones propagated to PCA (effective only if skipFitter is false) and for MC truth info"}; o2::vertexing::DCAFitterN<2> fitter; o2::vertexing::DCAFitterN<3> fitter3; + Service pdgDB; + // partitions for D mesons Partition positiveSecondaryTracks = aod::track::signed1Pt > 0.0f && nabs(aod::track::dcaXY) > dcaXYconstant + dcaXYpTdep* nabs(aod::track::signed1Pt); @@ -100,7 +114,8 @@ struct Alice3strangenessFinder { aod::track::signed1Pt < 0.0f && nabs(aod::track::dcaXY) > dcaXYconstant + dcaXYpTdep* nabs(aod::track::signed1Pt); Partition bachelorTracks = nabs(aod::track::dcaXY) > bachMinConstDCAxy + bachMinPtDepDCAxy* nabs(aod::track::signed1Pt) && nabs(aod::track::dcaZ) > bachMinConstDCAz + bachMinPtDepDCAz* nabs(aod::track::signed1Pt); - + Partition positiveMCParticles = aod::mcparticle_alice3::charge > 0.0f; + Partition negativeMCParticles = aod::mcparticle_alice3::charge < 0.0f; // Partition negativeSecondaryPions = nabs(aod::upgrade_tof::nSigmaPionInnerTOF) < nSigmaTOF && nabs(aod::upgrade_tof::nSigmaPionOuterTOF) < nSigmaTOF && aod::track::signed1Pt < 0.0f && nabs(aod::track::dcaXY) > dcaXYconstant + dcaXYpTdep* nabs(aod::track::signed1Pt); // Partition positiveSecondaryPions = nabs(aod::upgrade_tof::nSigmaPionInnerTOF) < nSigmaTOF && nabs(aod::upgrade_tof::nSigmaPionOuterTOF) < nSigmaTOF && aod::track::signed1Pt > 0.0f && nabs(aod::track::dcaXY) > dcaXYconstant + dcaXYpTdep* nabs(aod::track::signed1Pt); // Partition secondaryProtons = nabs(aod::upgrade_tof::nSigmaProtonInnerTOF) < nSigmaTOF && nabs(aod::upgrade_tof::nSigmaProtonOuterTOF) < nSigmaTOF && aod::track::signed1Pt > 0.0f && nabs(aod::track::dcaXY) > dcaXYconstant + dcaXYpTdep* nabs(aod::track::signed1Pt); @@ -134,8 +149,15 @@ struct Alice3strangenessFinder { fitter.setUsePropagator(usePropagator); fitter.setRefitWithMatCorr(refitWithMatCorr); fitter.setCollinear(useCollinearV0); + fitter.setMaxIter(maxIter); fitter.setMatCorrType(o2::base::Propagator::MatCorrType::USEMatCorrNONE); + histos.add("hFitterQA", "", kTH1D, {{10, 0, 10}}); // For QA reasons, counting found candidates at different stages + histos.add("hPtPosDau", "", kTH1D, {axisPt}); + histos.add("hPtNegDau", "", kTH1D, {axisPt}); + histos.add("hPtPosDauAfterV0Finding", "", kTH2D, {axisPt, axisPt}); + histos.add("hPtNegDauAfterV0Finding", "", kTH2D, {axisPt, axisPt}); + histos.add("hEventCounter", "", kTH1D, {{1, 0, 2}}); // counting processed events auto hV0Counter = histos.add("hV0Counter", "hV0Counter", kTH1D, {{4, 0, 4}}); hV0Counter->GetXaxis()->SetBinLabel(1, "K0S"); hV0Counter->GetXaxis()->SetBinLabel(2, "Lambda"); @@ -148,6 +170,9 @@ struct Alice3strangenessFinder { hCascadeCounter->GetXaxis()->SetBinLabel(3, "Omega"); hCascadeCounter->GetXaxis()->SetBinLabel(4, "AntiOmega"); hCascadeCounter->GetXaxis()->SetBinLabel(5, "Misidentified"); + histos.add("hRadiusVsHitsNeg", "", kTH2D, {{400, 0, 400}, {12, 0.5, 12.5}}); // radius vs hist for MC studies + histos.add("hRadiusVsHitsPos", "", kTH2D, {{400, 0, 400}, {12, 0.5, 12.5}}); // radius vs hist for MC studies + histos.print(); } float calculateDCAStraightToPV(float X, float Y, float Z, float Px, float Py, float Pz, float pvX, float pvY, float pvZ) @@ -180,65 +205,104 @@ struct Alice3strangenessFinder { template bool buildDecayCandidateTwoBody(TTrackType const& t0, TTrackType const& t1, std::array vtx, Candidate& thisCandidate) { - //}-{}-{}-{}-{}-{}-{}-{}-{}-{} - // Move close to minima - int nCand = 0; - try { - nCand = fitter.process(t0, t1); - } catch (...) { - return false; - } - if (nCand == 0) { - return false; - } - //}-{}-{}-{}-{}-{}-{}-{}-{}-{} - if (!fitter.isPropagateTracksToVertexDone() && !fitter.propagateTracksToVertex()) { - LOG(debug) << "RejProp failed"; - return false; - } - o2::track::TrackParCov t0New = fitter.getTrack(0); - o2::track::TrackParCov t1New = fitter.getTrack(1); - t0New.getPxPyPzGlo(thisCandidate.pDau0); - t1New.getPxPyPzGlo(thisCandidate.pDau1); - - thisCandidate.dcaDau = std::sqrt(fitter.getChi2AtPCACandidate()); - thisCandidate.p[0] = thisCandidate.pDau0[0] + thisCandidate.pDau1[0]; - thisCandidate.p[1] = thisCandidate.pDau0[1] + thisCandidate.pDau1[1]; - thisCandidate.p[2] = thisCandidate.pDau0[2] + thisCandidate.pDau1[2]; - - const auto posSV = fitter.getPCACandidatePos(); - thisCandidate.posSV[0] = posSV[0]; - thisCandidate.posSV[1] = posSV[1]; - thisCandidate.posSV[2] = posSV[2]; - - std::array covA = {0}; - std::array covB = {0}; - fitter.getTrack(0).getCovXYZPxPyPzGlo(covA); - fitter.getTrack(1).getCovXYZPxPyPzGlo(covB); - - static constexpr std::array MomentumIndices = {9, 13, 14, 18, 19, 20}; // cov matrix elements for momentum component - for (size_t i = 0; i < MomentumIndices.size(); i++) { - int j = MomentumIndices[i]; - thisCandidate.parentTrackCovMatrix[j] = covA[j] + covB[j]; - } + histos.fill(HIST("hPtNegDau"), t1.getPt()); + histos.fill(HIST("hPtPosDau"), t0.getPt()); + + if (!skipFitter) { - auto covVtx = fitter.calcPCACovMatrix(); - thisCandidate.parentTrackCovMatrix[0] = covVtx(0, 0); - thisCandidate.parentTrackCovMatrix[1] = covVtx(1, 0); - thisCandidate.parentTrackCovMatrix[2] = covVtx(1, 1); - thisCandidate.parentTrackCovMatrix[3] = covVtx(2, 0); - thisCandidate.parentTrackCovMatrix[4] = covVtx(2, 1); - thisCandidate.parentTrackCovMatrix[5] = covVtx(2, 2); - - thisCandidate.eta = RecoDecay::eta(std::array{thisCandidate.p[0], thisCandidate.p[1], thisCandidate.p[2]}); - thisCandidate.cosPA = RecoDecay::cpa(vtx, std::array{thisCandidate.posSV[0], thisCandidate.posSV[1], thisCandidate.posSV[2]}, - std::array{thisCandidate.p[0], thisCandidate.p[1], thisCandidate.p[2]}); - thisCandidate.dcaToPV = calculateDCAStraightToPV(thisCandidate.posSV[0], thisCandidate.posSV[1], thisCandidate.posSV[2], - thisCandidate.p[0], thisCandidate.p[1], thisCandidate.p[2], - vtx[0], vtx[1], vtx[2]); - - return true; + histos.fill(HIST("hFitterQA"), 0.5); + //}-{}-{}-{}-{}-{}-{}-{}-{}-{} + // Move close to minima + int nCand = 0; + try { + nCand = fitter.process(t0, t1); + } catch (...) { + return false; + } + histos.fill(HIST("hFitterQA"), 1.5); + if (nCand == 0) { + LOG(info) << "0 candidates found by fitter"; + return false; + } + histos.fill(HIST("hFitterQA"), 2.5); + //}-{}-{}-{}-{}-{}-{}-{}-{}-{} + if (!fitter.isPropagateTracksToVertexDone() && !fitter.propagateTracksToVertex()) { + LOG(info) << "RejProp failed"; + return false; + } + histos.fill(HIST("hFitterQA"), 3.5); + o2::track::TrackParCov t0New = fitter.getTrack(0); + o2::track::TrackParCov t1New = fitter.getTrack(1); + t0New.getPxPyPzGlo(thisCandidate.pDau0); + t1New.getPxPyPzGlo(thisCandidate.pDau1); + if (useOriginalTrackParams) { + t0.getPxPyPzGlo(thisCandidate.pDau0); + t1.getPxPyPzGlo(thisCandidate.pDau1); + } + histos.fill(HIST("hPtNegDauAfterV0Finding"), std::sqrt(thisCandidate.pDau1[0] * thisCandidate.pDau1[0] + thisCandidate.pDau1[1] + thisCandidate.pDau1[1]), t1.getPt()); + histos.fill(HIST("hPtPosDauAfterV0Finding"), std::sqrt(thisCandidate.pDau0[0] * thisCandidate.pDau0[0] + thisCandidate.pDau0[1] + thisCandidate.pDau0[1]), t0.getPt()); + + thisCandidate.dcaDau = std::sqrt(fitter.getChi2AtPCACandidate()); + thisCandidate.p[0] = thisCandidate.pDau0[0] + thisCandidate.pDau1[0]; + thisCandidate.p[1] = thisCandidate.pDau0[1] + thisCandidate.pDau1[1]; + thisCandidate.p[2] = thisCandidate.pDau0[2] + thisCandidate.pDau1[2]; + const auto posSV = fitter.getPCACandidatePos(); + thisCandidate.posSV[0] = posSV[0]; + thisCandidate.posSV[1] = posSV[1]; + thisCandidate.posSV[2] = posSV[2]; + + std::array covA = {0}; + std::array covB = {0}; + fitter.getTrack(0).getCovXYZPxPyPzGlo(covA); + fitter.getTrack(1).getCovXYZPxPyPzGlo(covB); + + static constexpr std::array MomentumIndices = {9, 13, 14, 18, 19, 20}; // cov matrix elements for momentum component + for (size_t i = 0; i < MomentumIndices.size(); i++) { + int j = MomentumIndices[i]; + thisCandidate.parentTrackCovMatrix[j] = covA[j] + covB[j]; + } + + auto covVtx = fitter.calcPCACovMatrix(); + thisCandidate.parentTrackCovMatrix[0] = covVtx(0, 0); + thisCandidate.parentTrackCovMatrix[1] = covVtx(1, 0); + thisCandidate.parentTrackCovMatrix[2] = covVtx(1, 1); + thisCandidate.parentTrackCovMatrix[3] = covVtx(2, 0); + thisCandidate.parentTrackCovMatrix[4] = covVtx(2, 1); + thisCandidate.parentTrackCovMatrix[5] = covVtx(2, 2); + thisCandidate.parentTrackCovMatrix[0] = 0; + thisCandidate.parentTrackCovMatrix[1] = 0; + thisCandidate.parentTrackCovMatrix[2] = 0; + thisCandidate.parentTrackCovMatrix[3] = 0; + thisCandidate.parentTrackCovMatrix[4] = 0; + thisCandidate.parentTrackCovMatrix[5] = 0; + + thisCandidate.eta = RecoDecay::eta(std::array{thisCandidate.p[0], thisCandidate.p[1], thisCandidate.p[2]}); + thisCandidate.cosPA = RecoDecay::cpa(vtx, std::array{thisCandidate.posSV[0], thisCandidate.posSV[1], thisCandidate.posSV[2]}, + std::array{thisCandidate.p[0], thisCandidate.p[1], thisCandidate.p[2]}); + thisCandidate.dcaToPV = calculateDCAStraightToPV(thisCandidate.posSV[0], thisCandidate.posSV[1], thisCandidate.posSV[2], + thisCandidate.p[0], thisCandidate.p[1], thisCandidate.p[2], + vtx[0], vtx[1], vtx[2]); + + return true; + } else { + t0.getPxPyPzGlo(thisCandidate.pDau0); + t1.getPxPyPzGlo(thisCandidate.pDau1); + thisCandidate.dcaDau = 0; + thisCandidate.p[0] = thisCandidate.pDau0[0] + thisCandidate.pDau1[0]; + thisCandidate.p[1] = thisCandidate.pDau0[1] + thisCandidate.pDau1[1]; + thisCandidate.p[2] = thisCandidate.pDau0[2] + thisCandidate.pDau1[2]; + thisCandidate.posSV[0] = 0; + thisCandidate.posSV[1] = 0; + thisCandidate.posSV[2] = 0; + thisCandidate.eta = RecoDecay::eta(std::array{thisCandidate.p[0], thisCandidate.p[1], thisCandidate.p[2]}); + thisCandidate.cosPA = RecoDecay::cpa(vtx, std::array{thisCandidate.posSV[0], thisCandidate.posSV[1], thisCandidate.posSV[2]}, + std::array{thisCandidate.p[0], thisCandidate.p[1], thisCandidate.p[2]}); + thisCandidate.dcaToPV = calculateDCAStraightToPV(thisCandidate.posSV[0], thisCandidate.posSV[1], thisCandidate.posSV[2], + thisCandidate.p[0], thisCandidate.p[1], thisCandidate.p[2], + vtx[0], vtx[1], vtx[2]); + return true; + } } void processFindV0CandidateNoPid(aod::Collision const& collision, Alice3Tracks const&, aod::McParticles const&) @@ -248,12 +312,15 @@ struct Alice3strangenessFinder { auto bachelorTracksGrouped = bachelorTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); const std::array vtx = {collision.posX(), collision.posY(), collision.posZ()}; + histos.fill(HIST("hEventCounter"), 1.0); + for (auto const& posTrack : positiveSecondaryTracksGrouped) { if (!posTrack.isReconstructed()) { continue; // no ghost tracks } o2::track::TrackParCov pos = getTrackParCov(posTrack); + for (auto const& negTrack : negativeSecondaryTracksGrouped) { if (!negTrack.isReconstructed()) { continue; // no ghost tracks @@ -262,28 +329,32 @@ struct Alice3strangenessFinder { if (mcSameMotherCheck && !checkSameMother(posTrack, negTrack)) { continue; // keep only if same mother } - + if ((posTrack.pdgCode() != kPiPlus && negTrack.pdgCode() != kPiMinus) && isK0Gun) + continue; + if ((posTrack.pdgCode() != kProton && negTrack.pdgCode() != kPiMinus) && isLambdaGun) + continue; o2::track::TrackParCov neg = getTrackParCov(negTrack); Candidate v0cand; if (!buildDecayCandidateTwoBody(pos, neg, vtx, v0cand)) { continue; // failed at building candidate } - auto mcParticle1 = posTrack.template mcParticle_as(); - if (mcParticle1.pdgCode() == kK0Short) { - histos.fill(HIST("hV0Counter"), 0.5); - } else if (mcParticle1.pdgCode() == kLambda0) { - histos.fill(HIST("hV0Counter"), 1.5); - } else if (mcParticle1.pdgCode() == kLambda0Bar) { - histos.fill(HIST("hV0Counter"), 2.5); - } else { - histos.fill(HIST("hV0Counter"), 3.5); - } + // TODO: not all ACTS tracks have MC association, so this check is not possible for all candidates, fix is needed + // auto mcParticle1 = posTrack.template mcParticle_as(); + // if (mcParticle1.pdgCode() == kK0Short) { + // histos.fill(HIST("hV0Counter"), 0.5); + // } else if (mcParticle1.pdgCode() == kLambda0) { + // histos.fill(HIST("hV0Counter"), 1.5); + // } else if (mcParticle1.pdgCode() == kLambda0Bar) { + // histos.fill(HIST("hV0Counter"), 2.5); + // } else { + // histos.fill(HIST("hV0Counter"), 3.5); + // } v0CandidateIndices(collision.globalIndex(), posTrack.globalIndex(), negTrack.globalIndex(), - mcParticle1.globalIndex()); + -1); v0CandidateCores(v0cand.posSV[0], v0cand.posSV[1], v0cand.posSV[2], v0cand.pDau0[0], v0cand.pDau0[1], v0cand.pDau0[2], @@ -300,12 +371,14 @@ struct Alice3strangenessFinder { std::array{v0cand.pDau1[0], v0cand.pDau1[1], v0cand.pDau1[2]}}, std::array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassProton}); - const bool inLambdaMassWindow = std::abs(lambdaMassHypothesis - o2::constants::physics::MassLambda0) > acceptedLambdaMassWindow; - const bool inAntiLambdaMassWindow = std::abs(antiLambdaMassHypothesis - o2::constants::physics::MassLambda0) > acceptedLambdaMassWindow; - if (inLambdaMassWindow || inAntiLambdaMassWindow) { + const bool inLambdaMassWindow = std::abs(lambdaMassHypothesis - o2::constants::physics::MassLambda0) < acceptedLambdaMassWindow; + const bool inAntiLambdaMassWindow = std::abs(antiLambdaMassHypothesis - o2::constants::physics::MassLambda0) < acceptedLambdaMassWindow; + if (!buildCascade) { + continue; // not building cascades, so skip the rest + } + if (!inLambdaMassWindow && !inAntiLambdaMassWindow) { continue; // Likely not a lambda, should not be considered for cascade building } - for (const auto& bachTrack : bachelorTracksGrouped) { if (bachTrack.globalIndex() == posTrack.globalIndex() || bachTrack.globalIndex() == negTrack.globalIndex()) { continue; // avoid using any track that was already used @@ -380,6 +453,76 @@ struct Alice3strangenessFinder { } // end negTrack } // end posTrack } + void processMCTrueFromACTS(aod::McCollision const& collision, Alice3MCParticles const&) + { + + auto negativeMCParticlesGrouped = negativeMCParticles->sliceByCached(aod::mcparticle::mcCollisionId, collision.globalIndex(), cache); + auto positiveMCParticlesGrouped = positiveMCParticles->sliceByCached(aod::mcparticle::mcCollisionId, collision.globalIndex(), cache); + const std::array vtx = {collision.posX(), collision.posY(), collision.posZ()}; + + float radiusPos = 0.0f; + float radiusNeg = 0.0f; + bool isK0s = false; + bool isLambda = false; + bool isAntiLambda = false; + int iPosPart = 0; + for (auto const& posParticle : positiveMCParticlesGrouped) { + radiusPos = std::hypot(posParticle.vx(), posParticle.vy()); + histos.fill(HIST("hRadiusVsHitsPos"), radiusPos, posParticle.nHits()); + for (auto const& negParticle : negativeMCParticlesGrouped) { + if (negParticle.pdgCode() != kPiMinus && negParticle.pdgCode() != kProtonBar) { + continue; + } + radiusNeg = std::hypot(negParticle.vx(), negParticle.vy()); + if (iPosPart == 0) { + histos.fill(HIST("hRadiusVsHitsNeg"), radiusNeg, negParticle.nHits()); + } + if (radiusPos == radiusNeg) { + isK0s = (posParticle.pdgCode() == kPiPlus && negParticle.pdgCode() == kPiMinus); + isLambda = (posParticle.pdgCode() == kProton && negParticle.pdgCode() == kPiMinus); + isAntiLambda = (posParticle.pdgCode() == kPiPlus && negParticle.pdgCode() == kProtonBar); + if (isK0s || isLambda || isAntiLambda) { + if (!isK0s && isK0Gun) + continue; + if (!isLambda && isLambdaGun) + continue; + Candidate v0cand; + std::vector v0DecayVertex; + v0DecayVertex.push_back(negParticle.vx()); + v0DecayVertex.push_back(negParticle.vy()); + v0DecayVertex.push_back(negParticle.vz()); + TLorentzVector posLorVector = {posParticle.px(), posParticle.py(), posParticle.pz(), posParticle.e()}; + TLorentzVector negLorVector = {negParticle.px(), negParticle.py(), negParticle.pz(), negParticle.e()}; + o2::track::TrackParCov posParCov; + o2::track::TrackParCov negParCov; + o2::upgrade::convertTLorentzVectorToO2Track(1, posLorVector, v0DecayVertex, posParCov); + o2::upgrade::convertTLorentzVectorToO2Track(-1, negLorVector, v0DecayVertex, negParCov); + if (!buildDecayCandidateTwoBody(posParCov, negParCov, vtx, v0cand)) + continue; + v0CandidateIndices(collision.globalIndex(), + posParticle.globalIndex(), + negParticle.globalIndex(), + 0); + v0CandidateCores(v0cand.posSV[0], v0cand.posSV[1], v0cand.posSV[2], + v0cand.pDau0[0], v0cand.pDau0[1], v0cand.pDau0[2], + v0cand.pDau1[0], v0cand.pDau1[1], v0cand.pDau1[2], + v0cand.dcaDau, 0, 0, + v0cand.cosPA, v0cand.dcaToPV); + if (isK0s) { + histos.fill(HIST("hV0Counter"), 0.5); + } else if (isLambda) { + histos.fill(HIST("hV0Counter"), 1.5); + } else if (isAntiLambda) { + histos.fill(HIST("hV0Counter"), 2.5); + } else { + histos.fill(HIST("hV0Counter"), 3.5); + } + } + } + } + iPosPart++; + } + } // void processFindV0CandidateWithPid(aod::Collision const& collision, aod::McParticles const& mcParticles, Alice3TracksWPid const&) // { // auto negativeSecondaryPionsGrouped = negativeSecondaryPions->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); @@ -388,6 +531,7 @@ struct Alice3strangenessFinder { // auto secondaryAntiProtonsGrouped = secondaryAntiProtons->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); // } PROCESS_SWITCH(Alice3strangenessFinder, processFindV0CandidateNoPid, "find V0 without PID", true); + PROCESS_SWITCH(Alice3strangenessFinder, processMCTrueFromACTS, "process MC truth from ACTS", false); // PROCESS_SWITCH(alice3strangenessFinder, processFindV0CandidateWithPid, "find V0 with PID", false); }; diff --git a/ALICE3/Tasks/alice3Strangeness.cxx b/ALICE3/Tasks/alice3Strangeness.cxx index 8d005b59ebd..3b539616fab 100644 --- a/ALICE3/Tasks/alice3Strangeness.cxx +++ b/ALICE3/Tasks/alice3Strangeness.cxx @@ -246,10 +246,12 @@ struct Alice3Strangeness { { // if(collision.lutConfigId()!=idGeometry) // return; + float collisionZ = collision.posZ(); + histos.fill(HIST("hPVz"), collisionZ); for (auto const& v0 : v0Candidates) { - bool isK0 = (v0.mK0Short() - o2::constants::physics::MassK0Short) < selectionValues.acceptedK0MassWindow; - bool isLambda = (v0.mLambda() - o2::constants::physics::MassLambda0) < selectionValues.acceptedLambdaMassWindow; - bool isAntiLambda = (v0.mAntiLambda() - o2::constants::physics::MassLambda0) < selectionValues.acceptedLambdaMassWindow; + bool isK0 = std::abs(v0.mK0Short() - o2::constants::physics::MassK0Short) < selectionValues.acceptedK0MassWindow; + bool isLambda = std::abs(v0.mLambda() - o2::constants::physics::MassLambda0) < selectionValues.acceptedLambdaMassWindow; + bool isAntiLambda = std::abs(v0.mAntiLambda() - o2::constants::physics::MassLambda0) < selectionValues.acceptedLambdaMassWindow; histos.fill(HIST("reconstructedCandidates/hArmeterosBeforeAllSelections"), v0.alpha(), v0.qtArm()); histos.fill(HIST("hV0CandidateCounter"), 0.5); From 689bf7e8b5f128f67eb651c0230da0fb807dc04e Mon Sep 17 00:00:00 2001 From: rbailhac Date: Mon, 23 Feb 2026 19:36:30 +0100 Subject: [PATCH 051/347] [ALICE3] Running with different scenario at the same time (#15123) --- ALICE3/Tasks/alice3-dilepton.cxx | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/ALICE3/Tasks/alice3-dilepton.cxx b/ALICE3/Tasks/alice3-dilepton.cxx index c901664cec8..bb142b11834 100644 --- a/ALICE3/Tasks/alice3-dilepton.cxx +++ b/ALICE3/Tasks/alice3-dilepton.cxx @@ -14,6 +14,7 @@ /// \author s.scheid@cern.ch, daiki.sekihata@cern.ch /// +#include "ALICE3/DataModel/OTFCollision.h" #include "ALICE3/DataModel/OTFRICH.h" #include "ALICE3/DataModel/OTFTOF.h" #include "ALICE3/DataModel/tracksAlice3.h" @@ -24,6 +25,7 @@ #include #include #include +#include #include #include @@ -54,6 +56,8 @@ struct Alice3Dilepton { SliceCache cache_mc; SliceCache cache_rec; + Service inspdg; + Configurable pdg{"pdg", 11, "pdg code for analysis. dielectron:11, dimuon:13"}; Configurable requireHFEid{"requireHFEid", true, "Require HFE identification for both leptons"}; Configurable ptMin{"pt-min", 0.f, "Lower limit in pT"}; @@ -68,6 +72,7 @@ struct Alice3Dilepton { Configurable nSigmaPionCutInnerTOF{"nSigmaPionCutInnerTOF", 3., "Pion exclusion in inner TOF"}; Configurable nSigmaElectronRich{"nSigmaElectronRich", 3., "Electron inclusion RICH"}; Configurable nSigmaPionRich{"nSigmaPionRich", 3., "Pion exclusion RICH"}; + Configurable otfConfig{"otfConfig", 0, "OTF configuration flag"}; HistogramRegistry registry{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -100,6 +105,7 @@ struct Alice3Dilepton { registry.add("Generated/Particle/prodVy", "Particle Prod. Vertex Y", kTH1F, {axisPrody}); registry.add("Generated/Particle/prodVz", "Particle Prod. Vertex Z", kTH1F, {axisProdz}); registry.add("Generated/Particle/ParticlesPerEvent", "Particles per event", kTH1F, {{100, 0, 100}}); + registry.add("Generated/Particle/ParticlesFit", "Charged Particles in Fit acceptance per event", kTH1F, {{15000, 0, 15000}}); registry.add("Generated/Pair/ULS/Tried", "Pair tries", kTH1F, {{10, -0.5, 9.5}}); registry.add("Generated/Pair/ULS/Mass", "Pair Mass", kTH1F, {axisM}); @@ -601,7 +607,19 @@ struct Alice3Dilepton { auto mcParticles_per_coll = mcParticles.sliceBy(perMCCollision, mccollision.globalIndex()); int nParticlesInEvent = 0; + int nParticlesFIT = 0; for (const auto& mcParticle : mcParticles_per_coll) { + if (mcParticle.isPhysicalPrimary()) { + if ((2.2 < mcParticle.eta() && mcParticle.eta() < 5.0) || (-3.4 < mcParticle.eta() && mcParticle.eta() < -2.3)) { + auto pdgParticle = inspdg->GetParticle(mcParticle.pdgCode()); + if (pdgParticle) { + float charge = pdgParticle->Charge() / 3.f; // Charge in units of |e| + if (std::abs(charge) >= 1.) { + nParticlesFIT++; + } + } + } + } if (std::abs(mcParticle.pdgCode()) != pdg) { continue; } @@ -624,6 +642,7 @@ struct Alice3Dilepton { } // end of mc particle loop registry.fill(HIST("Generated/Particle/ParticlesPerEvent"), nParticlesInEvent); + registry.fill(HIST("Generated/Particle/ParticlesFIT"), nParticlesFIT); auto neg_mcParticles_coll = neg_mcParticles->sliceByCached(o2::aod::mcparticle::mcCollisionId, mccollision.globalIndex(), cache_mc); auto pos_mcParticles_coll = pos_mcParticles->sliceByCached(o2::aod::mcparticle::mcCollisionId, mccollision.globalIndex(), cache_mc); @@ -636,6 +655,8 @@ struct Alice3Dilepton { } // end of processGen using MyTracksMC = soa::Join; + using Alice3Collision = soa::Join; + // Filter trackFilter = etaMin < o2::aod::track::eta && // o2::aod::track::eta < etaMax && // ptMin < o2::aod::track::pt && @@ -643,11 +664,13 @@ struct Alice3Dilepton { // o2::aod::track_alice3::isReconstructed == selectReconstructed; Filter trackFilter = o2::aod::track_alice3::isReconstructed == selectReconstructed; using MyFilteredTracksMC = soa::Filtered; + Filter configFilter = (aod::upgrade_collision::lutConfigId == otfConfig); + using MyFilteredAlice3Collision = soa::Filtered; Preslice perCollision = aod::track::collisionId; Partition posTracks = o2::aod::track::signed1Pt > 0.f; Partition negTracks = o2::aod::track::signed1Pt < 0.f; - void processRec(const o2::aod::Collisions& collisions, + void processRec(MyFilteredAlice3Collision const& collisions, MyFilteredTracksMC const& tracks, const o2::aod::McCollisions&, const aod::McParticles& mcParticles) From 9598667e96ac90d33980eb3d2e67fcf8a5727c2a Mon Sep 17 00:00:00 2001 From: samrangy Date: Mon, 23 Feb 2026 20:39:37 +0100 Subject: [PATCH 052/347] [PWGHF] Add D0 efficiency info at THnSparse (#15060) --- PWGHF/HFC/TableProducer/correlatorD0Hadrons.cxx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/PWGHF/HFC/TableProducer/correlatorD0Hadrons.cxx b/PWGHF/HFC/TableProducer/correlatorD0Hadrons.cxx index a1aee46c5bc..a53cbd6c862 100644 --- a/PWGHF/HFC/TableProducer/correlatorD0Hadrons.cxx +++ b/PWGHF/HFC/TableProducer/correlatorD0Hadrons.cxx @@ -430,7 +430,7 @@ struct HfCorrelatorD0Hadrons { for (unsigned int iclass = 0; iclass < classMl->size(); iclass++) { outputMlD0[iclass] = candidate.mlProbD0()[classMl->at(iclass)]; } - registry.fill(HIST("hMLScoresVsMassVsPtVsEtaVsOriginVsCent"), outputMlD0[0], outputMlD0[1], outputMlD0[2], invMassD0, candidate.pt(), candidate.eta(), (candidate.isSelD0bar() != 0) ? o2::aod::hf_correlation_d0_hadron::D0D0barBoth : o2::aod::hf_correlation_d0_hadron::D0Only, cent); + registry.fill(HIST("hMLScoresVsMassVsPtVsEtaVsOriginVsCent"), outputMlD0[0], outputMlD0[1], outputMlD0[2], invMassD0, candidate.pt(), candidate.eta(), (candidate.isSelD0bar() != 0) ? o2::aod::hf_correlation_d0_hadron::D0D0barBoth : o2::aod::hf_correlation_d0_hadron::D0Only, cent, efficiencyWeight); } if (candidate.isSelD0bar() >= selectionFlagD0bar) { registry.fill(HIST("hMass"), invMassD0bar, candidate.pt(), efficiencyWeight); @@ -440,7 +440,7 @@ struct HfCorrelatorD0Hadrons { for (unsigned int iclass = 0; iclass < classMl->size(); iclass++) { outputMlD0bar[iclass] = candidate.mlProbD0bar()[classMl->at(iclass)]; } - registry.fill(HIST("hMLScoresVsMassVsPtVsEtaVsOriginVsCent"), outputMlD0bar[0], outputMlD0bar[1], outputMlD0bar[2], invMassD0bar, candidate.pt(), candidate.eta(), (candidate.isSelD0() != 0) ? o2::aod::hf_correlation_d0_hadron::D0D0barBoth : o2::aod::hf_correlation_d0_hadron::D0barOnly, cent); + registry.fill(HIST("hMLScoresVsMassVsPtVsEtaVsOriginVsCent"), outputMlD0bar[0], outputMlD0bar[1], outputMlD0bar[2], invMassD0bar, candidate.pt(), candidate.eta(), (candidate.isSelD0() != 0) ? o2::aod::hf_correlation_d0_hadron::D0D0barBoth : o2::aod::hf_correlation_d0_hadron::D0barOnly, cent, efficiencyWeight); } entryD0CandRecoInfo(invMassD0, invMassD0bar, candidate.pt(), outputMlD0[0], outputMlD0[2], outputMlD0bar[0], outputMlD0bar[2]); @@ -620,7 +620,7 @@ struct HfCorrelatorD0Hadrons { for (unsigned int iclass = 0; iclass < classMl->size(); iclass++) { outputMlD0[iclass] = candidate.mlProbD0()[classMl->at(iclass)]; } - registry.fill(HIST("hMLScoresVsMassVsPtVsEtaVsOriginVsCent"), outputMlD0[0], outputMlD0[1], outputMlD0[2], invMassD0, candidate.pt(), candidate.eta(), isD0Prompt, cent); + registry.fill(HIST("hMLScoresVsMassVsPtVsEtaVsOriginVsCent"), outputMlD0[0], outputMlD0[1], outputMlD0[2], invMassD0, candidate.pt(), candidate.eta(), isD0Prompt, cent, efficiencyWeight); } if (candidate.isSelD0bar() >= selectionFlagD0bar) { // only reco as D0bar if (candidate.flagMcMatchRec() == -o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { // also matched as D0bar @@ -642,7 +642,7 @@ struct HfCorrelatorD0Hadrons { for (unsigned int iclass = 0; iclass < classMl->size(); iclass++) { outputMlD0bar[iclass] = candidate.mlProbD0bar()[classMl->at(iclass)]; } - registry.fill(HIST("hMLScoresVsMassVsPtVsEtaVsOriginVsCent"), outputMlD0bar[0], outputMlD0bar[1], outputMlD0bar[2], invMassD0bar, candidate.pt(), candidate.eta(), isD0Prompt, cent); + registry.fill(HIST("hMLScoresVsMassVsPtVsEtaVsOriginVsCent"), outputMlD0bar[0], outputMlD0bar[1], outputMlD0bar[2], invMassD0bar, candidate.pt(), candidate.eta(), isD0Prompt, cent, efficiencyWeight); } entryD0CandRecoInfo(invMassD0, invMassD0bar, candidate.pt(), outputMlD0[0], outputMlD0[2], outputMlD0bar[0], outputMlD0bar[2]); entryD0CandGenInfo(isD0Prompt); From 5917c887bcf80f926371692f9cf593cf576f94a1 Mon Sep 17 00:00:00 2001 From: Roman Lietava Date: Mon, 23 Feb 2026 23:21:59 +0100 Subject: [PATCH 053/347] [PWGLF] Omegahm: pileup (#15124) --- PWGLF/DataModel/LFNonPromptCascadeTables.h | 9 ++++- PWGLF/Tasks/Strangeness/nonPromptCascade.cxx | 36 +++++++++++++++----- 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/PWGLF/DataModel/LFNonPromptCascadeTables.h b/PWGLF/DataModel/LFNonPromptCascadeTables.h index d9ed41fe6bf..16c86667ad1 100644 --- a/PWGLF/DataModel/LFNonPromptCascadeTables.h +++ b/PWGLF/DataModel/LFNonPromptCascadeTables.h @@ -123,6 +123,7 @@ DECLARE_SOA_COLUMN(MultNTracksGlobal, multNTracksGlobal, int); DECLARE_SOA_COLUMN(ToiMask, toiMask, uint32_t); DECLARE_SOA_COLUMN(RunNumber, runNumber, int); DECLARE_SOA_COLUMN(NoSameBunchPileup, noSameBunchPileup, bool); +DECLARE_SOA_COLUMN(GlobalBC, globalBC, uint64_t); } // namespace NPCascadeTable DECLARE_SOA_TABLE(NPCascTable, "AOD", "NPCASCTABLE", @@ -447,7 +448,13 @@ DECLARE_SOA_TABLE(NPCascTableGen, "AOD", "NPCASCTABLEGen", NPCascadeTable::IsFromBeauty, NPCascadeTable::IsFromCharm, NPCascadeTable::MotherDecayDaughters) - +DECLARE_SOA_TABLE(NPPileUpTable, "AOD", "NPPileUpTABLE", + NPCascadeTable::RunNumber, + NPCascadeTable::GlobalBC, + aod::collision::NumContrib, + NPCascadeTable::MultNTracksGlobal, + NPCascadeTable::CentFT0M, + NPCascadeTable::MultFT0M); } // namespace o2::aod #endif // PWGLF_DATAMODEL_LFNONPROMPTCASCADETABLES_H_ diff --git a/PWGLF/Tasks/Strangeness/nonPromptCascade.cxx b/PWGLF/Tasks/Strangeness/nonPromptCascade.cxx index bd9fa236ca6..59a460d0324 100644 --- a/PWGLF/Tasks/Strangeness/nonPromptCascade.cxx +++ b/PWGLF/Tasks/Strangeness/nonPromptCascade.cxx @@ -24,7 +24,6 @@ #include "DCAFitter/DCAFitterN.h" #include "DataFormatsParameters/GRPMagField.h" #include "DataFormatsParameters/GRPObject.h" -#include "MathUtils/BetheBlochAleph.h" #include "DetectorsBase/Propagator.h" #include "DetectorsVertexing/PVertexer.h" #include "Framework/ASoA.h" @@ -32,7 +31,9 @@ #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" +#include "Framework/O2DatabasePDGPlugin.h" #include "Framework/runDataProcessing.h" +#include "MathUtils/BetheBlochAleph.h" #include "ReconstructionDataFormats/Vertex.h" #include "Math/Vector4D.h" @@ -175,12 +176,12 @@ std::vector gCandidatesNT; } // namespace struct NonPromptCascadeTask { - Produces NPCTable; Produces NPCTableMC; Produces NPCTableNT; Produces NPCTableMCNT; Produces NPCTableGen; + Produces NPPUTable; using TracksExtData = soa::Join; using TracksExtMC = soa::Join; @@ -227,6 +228,7 @@ struct NonPromptCascadeTask { std::array mProcessCounter = {0, 0}; // {Tracked, All} std::map mToiMap; // + Service pdgDB; HistogramRegistry mRegistryMults{"Multhistos"}; HistogramRegistry mRegistrydNdeta{"dNdetahistos"}; @@ -315,9 +317,10 @@ struct NonPromptCascadeTask { AxisSpec centAxisFV0{centBinning, "Centrality FV0 (%)"}; AxisSpec trackAxisMC{trackBinning, "NTracks MC"}; AxisSpec trackAxis{trackBinning, "NTracks Global Reco"}; + AxisSpec numContribAxis{trackBinning, "Num of Contrib"}; AxisSpec runsAxis{runsBinning, "Run Number"}; - mRegistryMults.add("hCentMultsRuns", "hCentMultsRuns", HistType::kTHnSparseF, {centAxisFT0M, multAxis, centAxisFV0, multAxisFV0, nTracksAxis, runsAxis}); + mRegistryMults.add("hCentMultsRuns", "hCentMultsRuns", HistType::kTHnSparseF, {centAxisFT0M, multAxis, numContribAxis, nTracksAxis, runsAxis}); // // dN/deta // @@ -411,11 +414,12 @@ struct NonPromptCascadeTask { for (const auto& coll : collisions) { float centFT0M = coll.centFT0M(); float multFT0M = coll.multFT0M(); - float centFV0A = coll.centFV0A(); - float multFV0A = coll.multFV0A(); + // float centFV0A = coll.centFV0A(); + // float multFV0A = coll.multFV0A(); float multNTracks = coll.multNTracksGlobal(); float run = mRunNumber; - mRegistryMults.fill(HIST("hCentMultsRuns"), centFT0M, multFT0M, centFV0A, multFV0A, multNTracks, run); + float numContrib = coll.numContrib(); + mRegistryMults.fill(HIST("hCentMultsRuns"), centFT0M, multFT0M, numContrib, multNTracks, run); } }; @@ -729,7 +733,7 @@ struct NonPromptCascadeTask { fillCandidatesVector(collisions, tracks, trackedCascades, gCandidates); fillMCtable(mcParticles, collisions, gCandidates); } - PROCESS_SWITCH(NonPromptCascadeTask, processTrackedCascadesMC, "process cascades from strangeness tracking: MC analysis", true); + PROCESS_SWITCH(NonPromptCascadeTask, processTrackedCascadesMC, "process cascades from strangeness tracking: MC analysis", false); void processCascadesMC(CollisionCandidatesRun3MC const& collisions, aod::Cascades const& cascades, aod::V0s const& /*v0s*/, TracksExtMC const& tracks, @@ -817,7 +821,7 @@ struct NonPromptCascadeTask { if (std::abs(mcp.eta()) > 0.5f) continue; int q = 0; - if (auto pdg = TDatabasePDG::Instance()->GetParticle(mcp.pdgCode())) { + if (auto pdg = pdgDB->GetParticle(mcp.pdgCode())) { q = int(std::round(pdg->Charge() / 3.0)); } if (q == 0) @@ -928,7 +932,7 @@ struct NonPromptCascadeTask { } int q = 0; - if (auto pdgEntry = TDatabasePDG::Instance()->GetParticle(mcPar.pdgCode())) { + if (auto pdgEntry = pdgDB->GetParticle(mcPar.pdgCode())) { q = int(std::round(pdgEntry->Charge() / 3.0)); } if (q == 0) { @@ -971,6 +975,20 @@ struct NonPromptCascadeTask { } PROCESS_SWITCH(NonPromptCascadeTask, processdNdetaMC, "process mc dN/deta", false); + + void processPileUp(CollisionCandidatesRun3 const& collisions, aod::BCsWithTimestamps const&) + { + std::cout << "Processing pile up" << std::endl; + for (const auto& coll : collisions) { + float centFT0M = coll.centFT0M(); + float multFT0M = coll.multFT0M(); + auto bc = coll.template bc_as(); + uint64_t globalBC = bc.globalBC(); + NPPUTable(mRunNumber, globalBC, coll.numContrib(), coll.multNTracksGlobal(), centFT0M, multFT0M); + // NPPileUpTable(mRunNumber, globalBC, multNTracks, centFT0M, multFT0M); + } + }; + PROCESS_SWITCH(NonPromptCascadeTask, processPileUp, "pile up studies", true); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) From ff5efea5de4dc534f54773d77f636147980e751b Mon Sep 17 00:00:00 2001 From: mhartung71 <50153519+mhartung71@users.noreply.github.com> Date: Tue, 24 Feb 2026 00:22:26 +0100 Subject: [PATCH 054/347] [PWGLF] Fix bug in tree creator (#15127) --- PWGLF/TableProducer/Nuspex/hypKfTreeCreator.cxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/PWGLF/TableProducer/Nuspex/hypKfTreeCreator.cxx b/PWGLF/TableProducer/Nuspex/hypKfTreeCreator.cxx index 7999fe2de82..d1335959545 100644 --- a/PWGLF/TableProducer/Nuspex/hypKfTreeCreator.cxx +++ b/PWGLF/TableProducer/Nuspex/hypKfTreeCreator.cxx @@ -302,6 +302,8 @@ struct HypKfTreeCreator { cand.occu = coll.occupancy(); cand.runNumber = coll.runNumber(); cand.passedEvSel = coll.passedEvSel(); + cand.ct = ct(coll, hypNuc); + cand.cpaPv = cpa(coll, hypNuc); cand.mass = hypNuc.mass(); cand.y = hypNuc.y(); cand.pt = hypNuc.pt(); From 59fae3e1b647c8f536bc50f175129c1a6d14e08f Mon Sep 17 00:00:00 2001 From: AlexianL <123153896+AlexianL@users.noreply.github.com> Date: Tue, 24 Feb 2026 01:07:59 +0100 Subject: [PATCH 055/347] [PWGHF] taskFlow.cxx : add FT0 gain equalization, add more event selections (#15074) --- PWGHF/HFC/Tasks/taskFlow.cxx | 378 +++++++++++++++++++++++++++-------- 1 file changed, 299 insertions(+), 79 deletions(-) diff --git a/PWGHF/HFC/Tasks/taskFlow.cxx b/PWGHF/HFC/Tasks/taskFlow.cxx index 7bda2ee8dc5..add129f9673 100644 --- a/PWGHF/HFC/Tasks/taskFlow.cxx +++ b/PWGHF/HFC/Tasks/taskFlow.cxx @@ -26,6 +26,7 @@ #include "PWGMM/Mult/DataModel/bestCollisionTable.h" #include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/RCTSelectionFlags.h" #include "Common/Core/RecoDecay.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" @@ -74,6 +75,7 @@ using namespace o2; using namespace o2::analysis; using namespace o2::aod::pid_tpc_tof_utils; +using namespace o2::aod::rctsel; using namespace o2::aod::track; using namespace o2::constants::math; using namespace o2::framework; @@ -142,6 +144,21 @@ enum MultiplicityEstimators { MultFT0M }; +enum SpecificEventSelectionStep { + AllEventsPrecise = 0, + IsSel8, + IsNoSameBunchPileup, + IsGoodItsLayersAll, + IsGoodZvtxFT0vsPV, + IsNoCollInRofStandard, + IsNoCollInRofStrict, + IsNoCollInTimeRangeStandard, + IsNoCollInTimeRangeStrict, + IsNoHighMultCollInPrevRof, + IsRctFlagChecked, + NSpecificEventSelectionSteps +}; + enum TrackSelection { TrackSelectionNoCut = 0, TrackSelectionGlobalTrack @@ -185,6 +202,7 @@ struct HfTaskFlow { Configurable doReferenceFlow{"doReferenceFlow", false, "Flag to know if reference flow should be done"}; Configurable isReadoutCenter{"isReadoutCenter", false, "Enable Readout Center"}; Configurable nMixedEvents{"nMixedEvents", 5, "Number of mixed events per event"}; + Configurable nSamples{"nSamples", 10, "number of different samples for correlations"}; } configTask; // configurables for collisions @@ -192,11 +210,21 @@ struct HfTaskFlow { std::string prefix = "ConfigCollision_group"; Configurable isApplyGoodItsLayersAll{"isApplyGoodItsLayersAll", false, "Enable GoodITSLayersAll"}; Configurable isApplyGoodZvtxFT0vsPV{"isApplyGoodZvtxFT0vsPV", false, "Enable GoodZvtxFT0vsPV cut"}; + Configurable isApplyNoCollInRofStandard{"isApplyNoCollInRofStandard", false, ""}; + Configurable isApplyNoCollInRofStrict{"isApplyNoCollInRofStrict", false, ""}; + Configurable isApplyNoCollInTimeRangeStandard{"isApplyNoCollInTimeRangeStandard", false, ""}; + Configurable isApplyNoCollInTimeRangeStrict{"isApplyNoCollInTimeRangeStrict", false, ""}; + Configurable isApplyNoHighMultCollInPrevRof{"isApplyNoHighMultCollInPrevRof", false, ""}; Configurable isApplySameBunchPileup{"isApplySameBunchPileup", false, "Enable SameBunchPileup cut"}; Configurable maxMultiplicity{"maxMultiplicity", 300, "maximum multiplicity selection for collision"}; Configurable minMultiplicity{"minMultiplicity", 0, "minimum multiplicity selection for collision"}; Configurable multiplicityEstimator{"multiplicityEstimator", 0, "0: multNTracksPV, 1: numContrib, 2: multFT0C, 3: multFT0M, 4: centFT0C, 5: centFT0CVariants1s, 6: centFT0M, 7: centFV0A, 8: centNTracksPV, 9: centNGlobal, 10: centMFT"}; - Configurable isApplyNoCollInTimeRangeStrict{"isApplyNoCollInTimeRangeStrict", false, ""}; + Configurable requireRCTFlagChecker{"requireRCTFlagChecker", false, "Check event quality in run condition table"}; + Configurable requireCorrelationAnalysisRCTFlagChecker{"requireCorrelationAnalysisRCTFlagChecker", false, "Check event quality in run condition table for correlation analysis"}; + Configurable setRCTFlagCheckerLabel{"setRCTFlagCheckerLabel", "CBT_muon_global", "Evt sel: RCT flag checker label"}; + Configurable requireRCTFlagCheckerLimitAcceptanceAsBad{"requireRCTFlagCheckerLimitAcceptanceAsBad", true, "Evt sel: RCT flag checker treat Limited Acceptance As Bad"}; + Configurable requireZDCCheck{"requireZDCCheck", false, "Evt sel: RCT flag checker ZDC check"}; + Configurable rctFlagCheckerLabel{"rctFlagCheckerLabel", "CBT_fw", "Evt sel: RCT flag checker label"}; Configurable zVertexMax{"zVertexMax", 10.0f, "Accepted z-vertex range"}; } configCollision; @@ -251,6 +279,13 @@ struct HfTaskFlow { Configurable useMftPtCut{"useMftPtCut", false, "if true, use the Mft pt function cut"}; } configMft; + // configurables for MFT tracks + struct : ConfigurableGroup { + std::string prefix = "ConfigFit_group"; + Configurable cfgGainEqPath{"cfgGainEqPath", "Analysis/EventPlane/GainEq", "CCDB path for gain equalization constants"}; + Configurable cfgCorrLevel{"cfgCorrLevel", 1, "calibration step: 0 = no corr, 1 = gain corr"}; + } configFit; + TF1* fPtDepDCAxy = nullptr; SliceCache cache; @@ -261,6 +296,9 @@ struct HfTaskFlow { o2::ccdb::CcdbApi ccdbApi; o2::ft0::Geometry ft0Det; o2::fv0::Geometry* fv0Det{}; + std::vector cstFT0RelGain{}; + RCTFlagsChecker rctChecker; + RCTFlagsChecker correlationAnalysisRctChecker{kFT0Bad, kITSBad, kTPCBadTracking, kMFTBad}; // ========================= // using declarations : DATA @@ -343,6 +381,10 @@ struct HfTaskFlow { ConfigurableAxis axisPtTrigger{"axisPtTrigger", {VARIABLE_WIDTH, 0.2, 0.5, 1, 1.5, 2, 3, 4, 6, 10}, "pt trigger axis for histograms"}; ConfigurableAxis axisVertex{"axisVertex", {20, -10, 10}, "vertex axis for histograms"}; ConfigurableAxis axisVertexEfficiency{"axisVertexEfficiency", {1, -10, 10}, "vertex axis for efficiency histograms"}; + ConfigurableAxis axisAmplitudeFit{"axisAmplitudeFit", {5000, 0, 1000}, "FT0A amplitude axis"}; + ConfigurableAxis axisChannelFt0a{"axisChannelFt0a", {96, 0.0, 96.0}, "FT0A channel axis"}; + ConfigurableAxis axisSamples{"axisSamples", {10, 0, 10}, "sample axis for correlation containers"}; + ConfigurableAxis axisChID{"axisChID", {220, 0, 220}, "FIT channel ID"}; } configAxis; HistogramRegistry registry{"registry"}; @@ -429,13 +471,15 @@ struct HfTaskFlow { LOGF(info, "Offset for FT0C: x = %.3f y = %.3f z = %.3f\n", (*offsetFT0)[1].getX(), (*offsetFT0)[1].getY(), (*offsetFT0)[1].getZ()); LOGF(info, "Offset for FV0-left: x = %.3f y = %.3f z = %.3f\n", (*offsetFV0)[0].getX(), (*offsetFV0)[0].getY(), (*offsetFV0)[0].getZ()); LOGF(info, "Offset for FV0-right: x = %.3f y = %.3f z = %.3f\n", (*offsetFV0)[1].getX(), (*offsetFV0)[1].getY(), (*offsetFV0)[1].getZ()); - fv0Det = o2::fv0::Geometry::instance(o2::fv0::Geometry::eUninitialized); // ========================= // Event histograms // ========================= + rctChecker.init(configCollision.setRCTFlagCheckerLabel, configCollision.requireZDCCheck, configCollision.requireRCTFlagCheckerLimitAcceptanceAsBad); + correlationAnalysisRctChecker.init({kFT0Bad, kITSBad, kTPCBadTracking, kMFTBad}, configCollision.requireZDCCheck, configCollision.requireRCTFlagCheckerLimitAcceptanceAsBad); + registry.add("Data/hVtxZ", "v_{z} (cm)", {HistType::kTH1D, {configAxis.axisVertex}}); registry.add("Data/hNTracks", "", {HistType::kTH1F, {configAxis.axisMultiplicity}}); registry.add(Form("Data/hMultiplicity_%s", WhatMultiplicityEstimator[configCollision.multiplicityEstimator].data()), "", {HistType::kTH1D, {configAxis.axisMultiplicity}}); @@ -450,6 +494,25 @@ struct HfTaskFlow { registry.get(HIST("Data/hEventCounter"))->GetXaxis()->SetBinLabel(iBin + 1, labels[iBin].data()); } + registry.add("Data/hPreciseEventCounter", "hPreciseEventCounter", {HistType::kTH1D, {{SpecificEventSelectionStep::NSpecificEventSelectionSteps, -0.5, +SpecificEventSelectionStep::NSpecificEventSelectionSteps - 0.5}}}); + std::string labelsPreciseEventSelection[SpecificEventSelectionStep::NSpecificEventSelectionSteps]; + labelsPreciseEventSelection[SpecificEventSelectionStep::AllEventsPrecise] = "all"; + labelsPreciseEventSelection[SpecificEventSelectionStep::IsSel8] = "sel8"; + labelsPreciseEventSelection[SpecificEventSelectionStep::IsNoSameBunchPileup] = "IsNoSameBunchPileup"; + labelsPreciseEventSelection[SpecificEventSelectionStep::IsGoodItsLayersAll] = "IsGoodItsLayersAll"; + labelsPreciseEventSelection[SpecificEventSelectionStep::IsGoodZvtxFT0vsPV] = "IsGoodZvtxFT0vsPV"; + labelsPreciseEventSelection[SpecificEventSelectionStep::IsNoCollInRofStandard] = "IsNoCollInRofStandard"; + labelsPreciseEventSelection[SpecificEventSelectionStep::IsNoCollInRofStrict] = "IsNoCollInRofStrict"; + labelsPreciseEventSelection[SpecificEventSelectionStep::IsNoCollInTimeRangeStandard] = "IsNoCollInTimeRangeStandard"; + labelsPreciseEventSelection[SpecificEventSelectionStep::IsNoCollInTimeRangeStrict] = "IsNoCollInTimeRangeStrict"; + labelsPreciseEventSelection[SpecificEventSelectionStep::IsNoHighMultCollInPrevRof] = "IsNoHighMultCollInPrevRof"; + labelsPreciseEventSelection[SpecificEventSelectionStep::IsRctFlagChecked] = "IsRctFlagChecked"; + registry.get(HIST("Data/hPreciseEventCounter"))->SetMinimum(0); + + for (int iBin = 0; iBin < SpecificEventSelectionStep::NSpecificEventSelectionSteps; iBin++) { + registry.get(HIST("Data/hPreciseEventCounter"))->GetXaxis()->SetBinLabel(iBin + 1, labelsPreciseEventSelection[iBin].data()); + } + mPairCuts.SetHistogramRegistry(®istry); if (configCentral.pairCut->get("Photon") > 0 || configCentral.pairCut->get("K0") > 0 || configCentral.pairCut->get("Lambda") > 0 || configCentral.pairCut->get("Phi") > 0 || configCentral.pairCut->get("Rho") > 0) { mPairCuts.SetPairCut(PairCuts::Photon, configCentral.pairCut->get("Photon")); @@ -472,7 +535,9 @@ struct HfTaskFlow { std::vector const effAxis = {{configAxis.axisEtaEfficiency, "#eta"}, {configAxis.axisPtEfficiency, "p_{T} (GeV/c)"}, {configAxis.axisVertexEfficiency, "z-vtx (cm)"}}; - std::vector const userAxis = {{configAxis.axisMass, "m_{inv} (GeV/c^{2})"}}; + std::vector const userAxis = {{configAxis.axisSamples, "sampling"}}; + std::vector const hfUserAxis = {{configAxis.axisMass, "m_{inv} (GeV/c^{2})"}, + {configAxis.axisSamples, "sampling"}}; // ========================= // Initialization of histograms and CorrelationContainers for TpcTpc cases @@ -480,20 +545,23 @@ struct HfTaskFlow { if (doprocessSameTpcTpcChCh) { addHistograms(); - sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, {})); - mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, {})); + + sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, userAxis)); + mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, userAxis)); } if (doprocessSameTpcTpcD0Ch) { addHistograms(); - sameEventHf.setObject(new CorrelationContainer("sameEventHf", "sameEventHf", corrAxis, effAxis, userAxis)); - mixedEventHf.setObject(new CorrelationContainer("mixedEventHf", "mixedEventHf", corrAxis, effAxis, userAxis)); + + sameEventHf.setObject(new CorrelationContainer("sameEventHf", "sameEventHf", corrAxis, effAxis, hfUserAxis)); + mixedEventHf.setObject(new CorrelationContainer("mixedEventHf", "mixedEventHf", corrAxis, effAxis, hfUserAxis)); } if (doprocessSameTpcTpcLcCh) { addHistograms(); - sameEventHf.setObject(new CorrelationContainer("sameEventHf", "sameEventHf", corrAxis, effAxis, userAxis)); - mixedEventHf.setObject(new CorrelationContainer("mixedEventHf", "mixedEventHf", corrAxis, effAxis, userAxis)); + + sameEventHf.setObject(new CorrelationContainer("sameEventHf", "sameEventHf", corrAxis, effAxis, hfUserAxis)); + mixedEventHf.setObject(new CorrelationContainer("mixedEventHf", "mixedEventHf", corrAxis, effAxis, hfUserAxis)); } // ========================= @@ -504,24 +572,24 @@ struct HfTaskFlow { addHistograms(); addMftHistograms(); - sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, {})); - mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, {})); + sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, userAxis)); + mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, userAxis)); } if (doprocessSameTpcMftD0Ch || doprocessSameTpcMftD0ChReassociated) { addHistograms(); addMftHistograms(); - sameEventHf.setObject(new CorrelationContainer("sameEventHf", "sameEventHf", corrAxis, effAxis, userAxis)); - mixedEventHf.setObject(new CorrelationContainer("mixedEventHf", "mixedEventHf", corrAxis, effAxis, userAxis)); + sameEventHf.setObject(new CorrelationContainer("sameEventHf", "sameEventHf", corrAxis, effAxis, hfUserAxis)); + mixedEventHf.setObject(new CorrelationContainer("mixedEventHf", "mixedEventHf", corrAxis, effAxis, hfUserAxis)); } if (doprocessSameTpcMftLcCh || doprocessSameTpcMftLcChReassociated) { addHistograms(); addMftHistograms(); - sameEventHf.setObject(new CorrelationContainer("sameEventHf", "sameEventHf", corrAxis, effAxis, userAxis)); - mixedEventHf.setObject(new CorrelationContainer("mixedEventHf", "mixedEventHf", corrAxis, effAxis, userAxis)); + sameEventHf.setObject(new CorrelationContainer("sameEventHf", "sameEventHf", corrAxis, effAxis, hfUserAxis)); + mixedEventHf.setObject(new CorrelationContainer("mixedEventHf", "mixedEventHf", corrAxis, effAxis, hfUserAxis)); } // ========================= @@ -531,22 +599,22 @@ struct HfTaskFlow { if (doprocessSameTpcFv0aChCh) { addHistograms(); - sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, {})); - mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, {})); + sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, userAxis)); + mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, userAxis)); } if (doprocessSameTpcFv0aD0Ch) { addHistograms(); - sameEventHf.setObject(new CorrelationContainer("sameEventHf", "sameEventHf", corrAxis, effAxis, userAxis)); - mixedEventHf.setObject(new CorrelationContainer("mixedEventHf", "mixedEventHf", corrAxis, effAxis, userAxis)); + sameEventHf.setObject(new CorrelationContainer("sameEventHf", "sameEventHf", corrAxis, effAxis, hfUserAxis)); + mixedEventHf.setObject(new CorrelationContainer("mixedEventHf", "mixedEventHf", corrAxis, effAxis, hfUserAxis)); } if (doprocessSameTpcFv0aLcCh) { addHistograms(); - sameEventHf.setObject(new CorrelationContainer("sameEventHf", "sameEventHf", corrAxis, effAxis, userAxis)); - mixedEventHf.setObject(new CorrelationContainer("mixedEventHf", "mixedEventHf", corrAxis, effAxis, userAxis)); + sameEventHf.setObject(new CorrelationContainer("sameEventHf", "sameEventHf", corrAxis, effAxis, hfUserAxis)); + mixedEventHf.setObject(new CorrelationContainer("mixedEventHf", "mixedEventHf", corrAxis, effAxis, hfUserAxis)); } // ========================= @@ -558,8 +626,8 @@ struct HfTaskFlow { addHistograms(); addMftHistograms(); - sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, {})); - mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, {})); + sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, userAxis)); + mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, userAxis)); } // ========================= @@ -568,23 +636,29 @@ struct HfTaskFlow { if (doprocessSameTpcFt0aChCh) { addHistograms(); + registry.add("Data/FT0Amp", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); + registry.add("Data/FT0AmpCorr", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); - sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, {})); - mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, {})); + sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, userAxis)); + mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, userAxis)); } if (doprocessSameTpcFt0aD0Ch) { addHistograms(); + registry.add("Data/FT0Amp", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); + registry.add("Data/FT0AmpCorr", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); - sameEventHf.setObject(new CorrelationContainer("sameEventHf", "sameEventHf", corrAxis, effAxis, userAxis)); - mixedEventHf.setObject(new CorrelationContainer("mixedEventHf", "mixedEventHf", corrAxis, effAxis, userAxis)); + sameEventHf.setObject(new CorrelationContainer("sameEventHf", "sameEventHf", corrAxis, effAxis, hfUserAxis)); + mixedEventHf.setObject(new CorrelationContainer("mixedEventHf", "mixedEventHf", corrAxis, effAxis, hfUserAxis)); } if (doprocessSameTpcFt0aLcCh) { addHistograms(); + registry.add("Data/FT0Amp", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); + registry.add("Data/FT0AmpCorr", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); - sameEventHf.setObject(new CorrelationContainer("sameEventHf", "sameEventHf", corrAxis, effAxis, userAxis)); - mixedEventHf.setObject(new CorrelationContainer("mixedEventHf", "mixedEventHf", corrAxis, effAxis, userAxis)); + sameEventHf.setObject(new CorrelationContainer("sameEventHf", "sameEventHf", corrAxis, effAxis, hfUserAxis)); + mixedEventHf.setObject(new CorrelationContainer("mixedEventHf", "mixedEventHf", corrAxis, effAxis, hfUserAxis)); } // ========================= @@ -594,9 +668,11 @@ struct HfTaskFlow { if (doprocessSameMftFt0aChCh || doprocessSameMftFt0aChChReassociated || doprocessSameMftFt0aChChReassociated3d || doprocessSameMftFt0aChChNonAmbiguous) { addHistograms(); addMftHistograms(); + registry.add("Data/FT0Amp", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); + registry.add("Data/FT0AmpCorr", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); - sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, {})); - mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, {})); + sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, userAxis)); + mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, userAxis)); } // ========================= @@ -605,23 +681,29 @@ struct HfTaskFlow { if (doprocessSameTpcFt0cChCh) { addHistograms(); + registry.add("Data/FT0Amp", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); + registry.add("Data/FT0AmpCorr", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); - sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, {})); - mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, {})); + sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, userAxis)); + mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, userAxis)); } if (doprocessSameTpcFt0cD0Ch) { addHistograms(); + registry.add("Data/FT0Amp", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); + registry.add("Data/FT0AmpCorr", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); - sameEventHf.setObject(new CorrelationContainer("sameEventHf", "sameEventHf", corrAxis, effAxis, userAxis)); - mixedEventHf.setObject(new CorrelationContainer("mixedEventHf", "mixedEventHf", corrAxis, effAxis, userAxis)); + sameEventHf.setObject(new CorrelationContainer("sameEventHf", "sameEventHf", corrAxis, effAxis, hfUserAxis)); + mixedEventHf.setObject(new CorrelationContainer("mixedEventHf", "mixedEventHf", corrAxis, effAxis, hfUserAxis)); } if (doprocessSameTpcFt0cLcCh) { addHistograms(); + registry.add("Data/FT0Amp", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); + registry.add("Data/FT0AmpCorr", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); - sameEventHf.setObject(new CorrelationContainer("sameEventHf", "sameEventHf", corrAxis, effAxis, userAxis)); - mixedEventHf.setObject(new CorrelationContainer("mixedEventHf", "mixedEventHf", corrAxis, effAxis, userAxis)); + sameEventHf.setObject(new CorrelationContainer("sameEventHf", "sameEventHf", corrAxis, effAxis, hfUserAxis)); + mixedEventHf.setObject(new CorrelationContainer("mixedEventHf", "mixedEventHf", corrAxis, effAxis, hfUserAxis)); } // ========================= @@ -630,9 +712,11 @@ struct HfTaskFlow { if (doprocessSameFt0aFt0cChCh) { addHistograms(); + registry.add("Data/FT0Amp", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); + registry.add("Data/FT0AmpCorr", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); - sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, {})); - mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, {})); + sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, userAxis)); + mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, userAxis)); } } // End of init() function @@ -824,15 +908,49 @@ struct HfTaskFlow { } template - void getChannel(TFT0s const& ft0, std::size_t const& iCh, int& id, int fitType) + void getChannel(TFT0s const& ft0, std::size_t const& iCh, int& id, int fitType, float& amplitude) { + int rID{0}; if (fitType == isFT0C) { id = ft0.channelC()[iCh] + MinFt0cCell; + rID = id + MinFt0cCell; + amplitude = ft0.amplitudeC()[iCh]; } else if (fitType == isFT0A) { id = ft0.channelA()[iCh]; + rID = id; + amplitude = ft0.amplitudeA()[iCh]; } else { LOGF(fatal, "Cor Index %d out of range", fitType); } + registry.fill(HIST("Data/FT0Amp"), rID, amplitude); + amplitude = amplitude / cstFT0RelGain[iCh]; + registry.fill(HIST("Data/FT0AmpCorr"), rID, amplitude); + } + + void loadGain(aod::BCsWithTimestamps::iterator const& bc) + { + cstFT0RelGain.clear(); + cstFT0RelGain = {}; + std::string fullPath; + + auto timestamp = bc.timestamp(); + constexpr int ChannelsFT0 = 208; + if (configFit.cfgCorrLevel == 0) { + for (auto i{0u}; i < ChannelsFT0; i++) { + cstFT0RelGain.push_back(1.); + } + } else { + fullPath = configFit.cfgGainEqPath; + fullPath += "/FT0"; + const auto objft0Gain = ccdb->getForTimeStamp>(fullPath, timestamp); + if (!objft0Gain) { + for (auto i{0u}; i < ChannelsFT0; i++) { + cstFT0RelGain.push_back(1.); + } + } else { + cstFT0RelGain = *(objft0Gain); + } + } } // ========================= @@ -845,23 +963,72 @@ struct HfTaskFlow { { if (fillHistograms) { registry.fill(HIST("Data/hEventCounter"), EventSelectionStep::AllEvents); + registry.fill(HIST("Data/hPreciseEventCounter"), SpecificEventSelectionStep::AllEventsPrecise); } if (!collision.sel8()) { return false; } + if (fillHistograms) { + registry.fill(HIST("Data/hPreciseEventCounter"), SpecificEventSelectionStep::IsSel8); + } if (configCollision.isApplySameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { return false; } + if (fillHistograms) { + registry.fill(HIST("Data/hPreciseEventCounter"), SpecificEventSelectionStep::IsNoSameBunchPileup); + } + if (configCollision.isApplyGoodItsLayersAll && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + return false; + } + if (fillHistograms) { + registry.fill(HIST("Data/hPreciseEventCounter"), SpecificEventSelectionStep::IsGoodItsLayersAll); + } if (configCollision.isApplyGoodZvtxFT0vsPV && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { return false; } + if (fillHistograms) { + registry.fill(HIST("Data/hPreciseEventCounter"), SpecificEventSelectionStep::IsGoodZvtxFT0vsPV); + } + if (configCollision.isApplyNoCollInRofStandard && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { + return false; + } + if (fillHistograms) { + registry.fill(HIST("Data/hPreciseEventCounter"), SpecificEventSelectionStep::IsNoCollInRofStandard); + } + if (configCollision.isApplyNoCollInRofStrict && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStrict)) { + return false; + } + if (fillHistograms) { + registry.fill(HIST("Data/hPreciseEventCounter"), SpecificEventSelectionStep::IsNoCollInRofStrict); + } + if (configCollision.isApplyNoCollInTimeRangeStandard && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + return false; + } + if (fillHistograms) { + registry.fill(HIST("Data/hPreciseEventCounter"), SpecificEventSelectionStep::IsNoCollInTimeRangeStandard); + } if (configCollision.isApplyNoCollInTimeRangeStrict && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStrict)) { return false; } - if (configCollision.isApplyGoodItsLayersAll && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + if (fillHistograms) { + registry.fill(HIST("Data/hPreciseEventCounter"), SpecificEventSelectionStep::IsNoCollInTimeRangeStrict); + } + if (configCollision.isApplyNoHighMultCollInPrevRof && !collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { + return false; + } + if (fillHistograms) { + registry.fill(HIST("Data/hPreciseEventCounter"), SpecificEventSelectionStep::IsNoHighMultCollInPrevRof); + } + if (configCollision.requireRCTFlagChecker && !rctChecker(collision)) { return false; } + if (configCollision.requireCorrelationAnalysisRCTFlagChecker && !correlationAnalysisRctChecker(collision)) { + return false; + } + if (fillHistograms) { + registry.fill(HIST("Data/hPreciseEventCounter"), SpecificEventSelectionStep::IsRctFlagChecked); + } if (fillHistograms) { registry.fill(HIST("Data/hEventCounter"), EventSelectionStep::AfterEventSelection); @@ -989,6 +1156,7 @@ struct HfTaskFlow { auto triggerWeight = 1; auto associatedWeight = 1; auto loopCounter = 0; // To avoid filling associated tracks QA many times, I fill it only for the first trigger track of the collision + int sampleIndex = gRandom->Uniform(0, configTask.nSamples); // TRIGGER PARTICLE for (const auto& track1 : tracks1) { @@ -1024,9 +1192,9 @@ struct HfTaskFlow { // fill single-track distributions if (!fillingHFcontainer) { // if not HF-h case - target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, triggerWeight); + target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, sampleIndex, triggerWeight); } else { - target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, invmass, triggerWeight); + target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, invmass, sampleIndex, triggerWeight); } // FILL QA PLOTS for trigger particle @@ -1151,10 +1319,10 @@ struct HfTaskFlow { if (!fillingHFcontainer) { // fill pair correlations - target->getPairHist()->Fill(step, eta1 - eta2, pt2, pt1, multiplicity, deltaPhi, posZ, + target->getPairHist()->Fill(step, sampleIndex, eta1 - eta2, pt2, pt1, multiplicity, deltaPhi, posZ, triggerWeight * associatedWeight); } else { - target->getPairHist()->Fill(step, eta1 - eta2, pt2, pt1, multiplicity, deltaPhi, posZ, invmass, + target->getPairHist()->Fill(step, sampleIndex, eta1 - eta2, pt2, pt1, multiplicity, deltaPhi, posZ, invmass, triggerWeight * associatedWeight); } @@ -1194,6 +1362,7 @@ struct HfTaskFlow { auto triggerWeight = 1; auto associatedWeight = 1; auto loopCounter = 0; // To avoid filling associated tracks QA many times, I fill it only for the first trigger track of the collision + int sampleIndex = gRandom->Uniform(0, configTask.nSamples); // TRIGGER PARTICLE for (const auto& track1 : tracks1) { @@ -1225,9 +1394,9 @@ struct HfTaskFlow { // fill single-track distributions if (!fillingHFcontainer) { // if not HF-h case - target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, triggerWeight); + target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, sampleIndex, triggerWeight); } else { - target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, invmass, triggerWeight); + target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, invmass, sampleIndex, triggerWeight); } // FILL QA PLOTS for trigger particle @@ -1318,10 +1487,10 @@ struct HfTaskFlow { deltaPhi = RecoDecay::constrainAngle(deltaPhi, -PIHalf); if (!fillingHFcontainer) { - target->getPairHist()->Fill(step, eta1 - eta2, pt2, pt1, multiplicity, deltaPhi, posZ, + target->getPairHist()->Fill(step, sampleIndex, eta1 - eta2, pt2, pt1, multiplicity, deltaPhi, posZ, triggerWeight * associatedWeight); } else { - target->getPairHist()->Fill(step, eta1 - eta2, pt2, pt1, multiplicity, deltaPhi, posZ, invmass, + target->getPairHist()->Fill(step, sampleIndex, eta1 - eta2, pt2, pt1, multiplicity, deltaPhi, posZ, invmass, triggerWeight * associatedWeight); } @@ -1350,6 +1519,7 @@ struct HfTaskFlow { auto triggerWeight = 1; auto associatedWeight = 1; auto loopCounter = 0; // To avoid filling associated tracks QA many times, I fill it only for the first trigger track of the collision + int sampleIndex = gRandom->Uniform(0, configTask.nSamples); // TRIGGER PARTICLE for (auto const& track1 : tracks1) { @@ -1388,9 +1558,9 @@ struct HfTaskFlow { // fill single-track distributions if (!fillingHFcontainer) { // if not HF-h case - target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, triggerWeight); + target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, sampleIndex, triggerWeight); } else { - target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, invmass, triggerWeight); + target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, invmass, sampleIndex, triggerWeight); } // FILL QA PLOTS for trigger particle @@ -1450,10 +1620,10 @@ struct HfTaskFlow { deltaPhi = RecoDecay::constrainAngle(deltaPhi, -PIHalf); // set range of delta phi in (-pi/2 , 3/2*pi) if (!fillingHFcontainer) { - target->getPairHist()->Fill(step, eta1 - eta2, pt1, pt1, multiplicity, deltaPhi, posZ, + target->getPairHist()->Fill(step, sampleIndex, eta1 - eta2, pt1, pt1, multiplicity, deltaPhi, posZ, triggerWeight * associatedWeight); } else { - target->getPairHist()->Fill(step, eta1 - eta2, pt1, pt1, multiplicity, deltaPhi, posZ, invmass, + target->getPairHist()->Fill(step, sampleIndex, eta1 - eta2, pt1, pt1, multiplicity, deltaPhi, posZ, invmass, triggerWeight * associatedWeight); } @@ -1490,18 +1660,19 @@ struct HfTaskFlow { for (std::size_t indexChannel = 0; indexChannel < channelSize; indexChannel++) { int channelId = 0; - getChannel(tracks2, indexChannel, channelId, fitType); + float amplitude = 0.; + getChannel(tracks2, indexChannel, channelId, fitType, amplitude); auto phi2 = getPhiFT0(channelId, fitType); auto eta2 = getEtaFT0(channelId, fitType); float deltaPhi = phi1 - phi2; deltaPhi = RecoDecay::constrainAngle(deltaPhi, -PIHalf); // set range of delta phi in (-pi/2 , 3/2*pi) if (!fillingHFcontainer) { - target->getPairHist()->Fill(step, eta1 - eta2, pt1, pt1, multiplicity, deltaPhi, posZ, - triggerWeight * associatedWeight); + target->getPairHist()->Fill(step, sampleIndex, eta1 - eta2, pt1, pt1, multiplicity, deltaPhi, posZ, + amplitude * triggerWeight * associatedWeight); } else { - target->getPairHist()->Fill(step, eta1 - eta2, pt1, pt1, multiplicity, deltaPhi, posZ, invmass, - triggerWeight * associatedWeight); + target->getPairHist()->Fill(step, sampleIndex, eta1 - eta2, pt1, pt1, multiplicity, deltaPhi, posZ, invmass, + amplitude * triggerWeight * associatedWeight); } // FILL QA PLOTS for associated particle @@ -1548,6 +1719,7 @@ struct HfTaskFlow { auto triggerWeight = 1; auto associatedWeight = 1; auto loopCounter = 0; // To avoid filling associated tracks QA many times, I fill it only for the first trigger track of the collision + int sampleIndex = gRandom->Uniform(0, configTask.nSamples); // TRIGGER PARTICLE for (auto const& track1 : tracks1) { @@ -1570,7 +1742,7 @@ struct HfTaskFlow { float phi1 = reassociatedMftTrack.phi(); o2::math_utils::bringTo02Pi(phi1); - target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, triggerWeight); + target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, sampleIndex, triggerWeight); // FILL QA PLOTS for trigger particle if (sameEvent && (step == CorrelationContainer::kCFStepReconstructed)) { @@ -1594,7 +1766,7 @@ struct HfTaskFlow { float deltaPhi = phi1 - phi2; deltaPhi = RecoDecay::constrainAngle(deltaPhi, -PIHalf); // set range of delta phi in (-pi/2 , 3/2*pi) - target->getPairHist()->Fill(step, eta1 - eta2, pt1, pt1, multiplicity, deltaPhi, posZ, + target->getPairHist()->Fill(step, sampleIndex, eta1 - eta2, pt1, pt1, multiplicity, deltaPhi, posZ, triggerWeight * associatedWeight); // FILL QA PLOTS for associated particle @@ -1620,14 +1792,15 @@ struct HfTaskFlow { for (std::size_t indexChannel = 0; indexChannel < channelSize; indexChannel++) { int channelId = 0; - getChannel(tracks2, indexChannel, channelId, fitType); + float amplitude = 0.; + getChannel(tracks2, indexChannel, channelId, fitType, amplitude); auto phi2 = getPhiFT0(channelId, fitType); auto eta2 = getEtaFT0(channelId, fitType); float deltaPhi = phi1 - phi2; deltaPhi = RecoDecay::constrainAngle(deltaPhi, -PIHalf); // set range of delta phi in (-pi/2 , 3/2*pi) - target->getPairHist()->Fill(step, eta1 - eta2, pt1, pt1, multiplicity, deltaPhi, posZ, - triggerWeight * associatedWeight); + target->getPairHist()->Fill(step, sampleIndex, eta1 - eta2, pt1, pt1, multiplicity, deltaPhi, posZ, + amplitude * triggerWeight * associatedWeight); // FILL QA PLOTS for associated particle if (sameEvent && (loopCounter == 1) && (step == CorrelationContainer::kCFStepReconstructed)) { @@ -1648,16 +1821,18 @@ struct HfTaskFlow { auto triggerWeight = 1; auto associatedWeight = 1; auto loopCounter = 0; // To avoid filling associated tracks QA many times, I fill it only for the first trigger track of the collision + int sampleIndex = gRandom->Uniform(0, configTask.nSamples); // TRIGGER PARTICLE FROM FT0A for (std::size_t indexChannelA = 0; indexChannelA < ft0as.channelA().size(); indexChannelA++) { loopCounter++; int channelIdA = 0; - getChannel(ft0as, indexChannelA, channelIdA, isFT0A); + float amplitude = 0.; + getChannel(ft0as, indexChannelA, channelIdA, isFT0A, amplitude); auto phiA = getPhiFT0(channelIdA, isFT0A); auto etaA = getEtaFT0(channelIdA, isFT0A); - target->getTriggerHist()->Fill(step, 0.f, multiplicity, posZ, triggerWeight); + target->getTriggerHist()->Fill(step, 0.f, multiplicity, posZ, sampleIndex, amplitude * triggerWeight); if (sameEvent && (step == CorrelationContainer::kCFStepReconstructed)) { fillTriggerQa(multiplicity, etaA, phiA, 0.f); @@ -1667,13 +1842,14 @@ struct HfTaskFlow { for (std::size_t indexChannelC = 0; indexChannelC < ft0cs.channelC().size(); indexChannelC++) { int channelIdC = 0; - getChannel(ft0cs, indexChannelC, channelIdC, isFT0C); + float amplitude = 0.; + getChannel(ft0cs, indexChannelC, channelIdC, isFT0C, amplitude); auto phiC = getPhiFT0(channelIdC, isFT0C); auto etaC = getEtaFT0(channelIdC, isFT0C); float deltaPhi = RecoDecay::constrainAngle(phiA - phiC, -PIHalf); - target->getPairHist()->Fill(step, etaA - etaC, 0.f, 0.f, multiplicity, deltaPhi, posZ, - triggerWeight * associatedWeight); + target->getPairHist()->Fill(step, sampleIndex, etaA - etaC, 0.f, 0.f, multiplicity, deltaPhi, posZ, + amplitude * triggerWeight * associatedWeight); if (sameEvent && (loopCounter == 1) && (step == CorrelationContainer::kCFStepReconstructed)) { fillAssociatedQa(multiplicity, etaC, phiC); @@ -2303,13 +2479,17 @@ struct HfTaskFlow { void processSameTpcFt0aChCh(FilteredCollisionsWSelMult::iterator const& collision, FilteredTracksWDcaSel const& tracks, - aod::FT0s const& ft0as) + aod::FT0s const& ft0as, + aod::BCsWithTimestamps const&) { if (!(isAcceptedCollision(collision, true))) { return; } + auto bc = collision.bc_as(); + if (collision.has_foundFT0()) { + loadGain(bc); const auto& ft0 = collision.foundFT0(); registry.fill(HIST("Data/hNTracks"), tracks.size()); const auto multiplicity = getMultiplicityEstimator(collision, true); @@ -2330,13 +2510,17 @@ struct HfTaskFlow { void processSameTpcFt0aD0Ch(FilteredCollisionsWSelMult::iterator const& collision, HfCandidatesSelD0 const& candidates, - aod::FT0s const& ft0as) + aod::FT0s const& ft0as, + aod::BCsWithTimestamps const&) { if (!(isAcceptedCollision(collision, true))) { return; } + auto bc = collision.bc_as(); + if (collision.has_foundFT0()) { + loadGain(bc); const auto& ft0 = collision.foundFT0(); const auto multiplicity = getMultiplicityEstimator(collision, true); @@ -2356,13 +2540,17 @@ struct HfTaskFlow { void processSameTpcFt0aLcCh(FilteredCollisionsWSelMult::iterator const& collision, HfCandidatesSelLc const& candidates, - aod::FT0s const& ft0as) + aod::FT0s const& ft0as, + aod::BCsWithTimestamps const&) { if (!(isAcceptedCollision(collision, true))) { return; } + auto bc = collision.bc_as(); + if (collision.has_foundFT0()) { + loadGain(bc); const auto& ft0 = collision.foundFT0(); const auto multiplicity = getMultiplicityEstimator(collision, true); @@ -2382,13 +2570,17 @@ struct HfTaskFlow { void processSameMftFt0aChCh(FilteredCollisionsWSelMult::iterator const& collision, FilteredMftTracks const& mftTracks, - aod::FT0s const& ft0as) + aod::FT0s const& ft0as, + aod::BCsWithTimestamps const&) { if (!(isAcceptedCollision(collision, true))) { return; } + auto bc = collision.bc_as(); + if (collision.has_foundFT0()) { + loadGain(bc); const auto& ft0 = collision.foundFT0(); const auto multiplicity = getMultiplicityEstimator(collision, true); @@ -2405,13 +2597,17 @@ struct HfTaskFlow { void processSameMftFt0aChChReassociated(FilteredCollisionsWSelMult::iterator const& collision, soa::SmallGroups const& reassociatedMftTracks, FilteredMftTracks const&, - aod::FT0s const& ft0as) + aod::FT0s const& ft0as, + aod::BCsWithTimestamps const&) { if (!(isAcceptedCollision(collision, true))) { return; } + auto bc = collision.bc_as(); + if (collision.has_foundFT0()) { + loadGain(bc); const auto& ft0 = collision.foundFT0(); const auto multiplicity = getMultiplicityEstimator(collision, true); @@ -2428,13 +2624,17 @@ struct HfTaskFlow { void processSameMftFt0aChChReassociated3d(FilteredCollisionsWSelMult::iterator const& collision, soa::SmallGroups const& reassociatedMftTracks, FilteredMftTracks const&, - aod::FT0s const& ft0as) + aod::FT0s const& ft0as, + aod::BCsWithTimestamps const&) { if (!(isAcceptedCollision(collision, true))) { return; } + auto bc = collision.bc_as(); + if (collision.has_foundFT0()) { + loadGain(bc); const auto& ft0 = collision.foundFT0(); const auto multiplicity = getMultiplicityEstimator(collision, true); @@ -2451,13 +2651,17 @@ struct HfTaskFlow { void processSameMftFt0aChChNonAmbiguous(FilteredCollisionsWSelMult::iterator const& collision, soa::SmallGroups const& reassociatedMftTracks, FilteredMftTracks const&, - aod::FT0s const& ft0as) + aod::FT0s const& ft0as, + aod::BCsWithTimestamps const&) { if (!(isAcceptedCollision(collision, true))) { return; } + auto bc = collision.bc_as(); + if (collision.has_foundFT0()) { + loadGain(bc); const auto& ft0 = collision.foundFT0(); const auto multiplicity = getMultiplicityEstimator(collision, true); @@ -2477,13 +2681,17 @@ struct HfTaskFlow { void processSameTpcFt0cChCh(FilteredCollisionsWSelMult::iterator const& collision, FilteredTracksWDcaSel const& tracks, - aod::FT0s const& ft0cs) + aod::FT0s const& ft0cs, + aod::BCsWithTimestamps const&) { if (!(isAcceptedCollision(collision, true))) { return; } + auto bc = collision.bc_as(); + if (collision.has_foundFT0()) { + loadGain(bc); const auto& ft0 = collision.foundFT0(); registry.fill(HIST("Data/hNTracks"), tracks.size()); const auto multiplicity = getMultiplicityEstimator(collision, true); @@ -2504,13 +2712,17 @@ struct HfTaskFlow { void processSameTpcFt0cD0Ch(FilteredCollisionsWSelMult::iterator const& collision, HfCandidatesSelD0 const& candidates, - aod::FT0s const& ft0cs) + aod::FT0s const& ft0cs, + aod::BCsWithTimestamps const&) { if (!(isAcceptedCollision(collision, true))) { return; } + auto bc = collision.bc_as(); + if (collision.has_foundFT0()) { + loadGain(bc); const auto& ft0 = collision.foundFT0(); const auto multiplicity = getMultiplicityEstimator(collision, true); @@ -2530,13 +2742,17 @@ struct HfTaskFlow { void processSameTpcFt0cLcCh(FilteredCollisionsWSelMult::iterator const& collision, HfCandidatesSelLc const& candidates, - aod::FT0s const& ft0cs) + aod::FT0s const& ft0cs, + aod::BCsWithTimestamps const&) { if (!(isAcceptedCollision(collision, true))) { return; } + auto bc = collision.bc_as(); + if (collision.has_foundFT0()) { + loadGain(bc); const auto& ft0 = collision.foundFT0(); const auto multiplicity = getMultiplicityEstimator(collision, true); @@ -2555,13 +2771,17 @@ struct HfTaskFlow { // ===================================== void processSameFt0aFt0cChCh(FilteredCollisionsWSelMult::iterator const& collision, - aod::FT0s const&) + aod::FT0s const&, + aod::BCsWithTimestamps const&) { if (!(isAcceptedCollision(collision, true))) { return; } + auto bc = collision.bc_as(); + if (collision.has_foundFT0()) { + loadGain(bc); const auto& ft0 = collision.foundFT0(); const auto multiplicity = getMultiplicityEstimator(collision, true); From 4d62aa96a7cb279ee8ccc2936267fa247b1f491d Mon Sep 17 00:00:00 2001 From: Evgeny Kryshen Date: Tue, 24 Feb 2026 10:30:34 +0300 Subject: [PATCH 056/347] [Common] Accessing pass-specific rct flags from ccdb (#15021) --- Common/Tools/EventSelectionModule.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Common/Tools/EventSelectionModule.h b/Common/Tools/EventSelectionModule.h index 8d449c8cf9a..344ad7578da 100644 --- a/Common/Tools/EventSelectionModule.h +++ b/Common/Tools/EventSelectionModule.h @@ -159,6 +159,7 @@ class BcSelectionModule int mTimeFrameStartBorderMargin = 300; // default value int mTimeFrameEndBorderMargin = 4000; // default value std::string strLPMProductionTag = ""; // MC production tag to be retrieved from AO2D metadata + std::string strPassName = ""; // RecoPassName (for data) or AnchorPassName (for MC) from metadata bool isMC = false; TriggerAliases* aliases = nullptr; @@ -195,8 +196,9 @@ class BcSelectionModule return; } } - strLPMProductionTag = metadataInfo.get("LPMProductionTag"); // to extract info from ccdb by the tag isMC = metadataInfo.isMC(); + strLPMProductionTag = metadataInfo.get("LPMProductionTag"); // to extract info from ccdb by the tag + strPassName = metadataInfo.get(isMC ? "AnchorPassName" : "RecoPassName"); // add counter histos.add("bcselection/hCounterInvalidBCTimestamp", "", o2::framework::kTH1D, {{1, 0., 1.}}); @@ -279,8 +281,15 @@ class BcSelectionModule // QC info std::map metadata; metadata["run"] = Form("%d", run); + metadata["passName"] = strPassName; + LOGP(info, "accessing pass-specific rct object for run={} and passName={} from ccdb", run, strPassName); ccdb->setFatalWhenNull(0); mapRCT = ccdb->template getSpecific>("RCT/Flags/RunFlags", ts, metadata); + if (mapRCT == nullptr) { + LOGP(info, "pass-specific rct object missing... trying the latest"); + metadata.erase("passName"); + mapRCT = ccdb->template getSpecific>("RCT/Flags/RunFlags", ts, metadata); + } ccdb->setFatalWhenNull(1); if (mapRCT == nullptr) { LOGP(info, "rct object missing... inserting dummy rct flags"); From b55c5529f8b2d709a69867a68b8da936227f8abc Mon Sep 17 00:00:00 2001 From: Fabrizio Chinu <91954233+fchinu@users.noreply.github.com> Date: Tue, 24 Feb 2026 09:25:03 +0100 Subject: [PATCH 057/347] [PWGLF,PWGMM] Fix last run number of 2023 in luminosity stability task (#15125) --- PWGMM/Lumi/Tasks/lumiStabilityPP.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWGMM/Lumi/Tasks/lumiStabilityPP.cxx b/PWGMM/Lumi/Tasks/lumiStabilityPP.cxx index e0ca847029b..c1b391a1375 100644 --- a/PWGMM/Lumi/Tasks/lumiStabilityPP.cxx +++ b/PWGMM/Lumi/Tasks/lumiStabilityPP.cxx @@ -161,7 +161,7 @@ struct LumiStabilityPP { } const int runStart2023{535069}; - const int runStop2023{539908}; + const int runStop2023{543113}; if (bc.runNumber() >= runStart2023 && bc.runNumber() <= runStop2023) { isData23 = true; } From 1709abcb98e08f4abb9e153321841ea904f11123 Mon Sep 17 00:00:00 2001 From: ffionda <33261977+ffionda@users.noreply.github.com> Date: Tue, 24 Feb 2026 09:26:52 +0100 Subject: [PATCH 058/347] [PWGDQ] Fix for tableReader_withAss_direct task (Zorro and CCDB paths)+minor fix in dqEff-direct task (#15094) Co-authored-by: ALICE Action Bot --- PWGDQ/Tasks/CMakeLists.txt | 2 +- PWGDQ/Tasks/dqEfficiency_withAssoc_direct.cxx | 11 +- PWGDQ/Tasks/tableReader_withAssoc_direct.cxx | 176 ++++++++++++++++-- 3 files changed, 173 insertions(+), 16 deletions(-) diff --git a/PWGDQ/Tasks/CMakeLists.txt b/PWGDQ/Tasks/CMakeLists.txt index 086bb63bca0..cc660b53202 100644 --- a/PWGDQ/Tasks/CMakeLists.txt +++ b/PWGDQ/Tasks/CMakeLists.txt @@ -21,7 +21,7 @@ o2physics_add_dpl_workflow(table-reader-with-assoc o2physics_add_dpl_workflow(table-reader-with-assoc-direct SOURCES tableReader_withAssoc_direct.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2Physics::PWGDQCore O2Physics::MLCore O2::ReconstructionDataFormats O2::DetectorsCommonDataFormats O2::DetectorsVertexing + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2Physics::PWGDQCore O2Physics::MLCore O2::ReconstructionDataFormats O2::DetectorsCommonDataFormats O2::DetectorsVertexing O2Physics::EventFilteringUtils COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(efficiency diff --git a/PWGDQ/Tasks/dqEfficiency_withAssoc_direct.cxx b/PWGDQ/Tasks/dqEfficiency_withAssoc_direct.cxx index eefc7e1852a..948493f9cf4 100644 --- a/PWGDQ/Tasks/dqEfficiency_withAssoc_direct.cxx +++ b/PWGDQ/Tasks/dqEfficiency_withAssoc_direct.cxx @@ -733,6 +733,13 @@ struct AnalysisTrackSelection { trackSel(0); continue; } + /// + auto track = tracks.rawIteratorAt(assoc.trackId()); + auto evFromTrack = events.rawIteratorAt(track.collisionId()); + if (!evFromTrack.isEventSelected_bit(0)) { + trackSel(0); + continue; + } // cout << "Processing association: event global index " << event.globalIndex() << endl; VarManager::ResetValues(VarManager::kNTFWiseVariables, VarManager::kNBarrelTrackVariables); @@ -743,10 +750,10 @@ struct AnalysisTrackSelection { } // cout << "Filled event observables for association" << endl; - auto track = tracks.rawIteratorAt(assoc.trackId()); VarManager::FillTrack(track); // compute quantities which depend on the associated collision, such as DCA - VarManager::FillTrackCollision(track, event); + if (track.collisionId() != event.globalIndex()) + VarManager::FillTrackCollision(track, event); // cout << "Filled track observables for association" << endl; bool isCorrectAssoc = false; diff --git a/PWGDQ/Tasks/tableReader_withAssoc_direct.cxx b/PWGDQ/Tasks/tableReader_withAssoc_direct.cxx index 34ce76c8971..49e0d596d50 100644 --- a/PWGDQ/Tasks/tableReader_withAssoc_direct.cxx +++ b/PWGDQ/Tasks/tableReader_withAssoc_direct.cxx @@ -22,8 +22,11 @@ #include "PWGDQ/Core/VarManager.h" #include "PWGDQ/DataModel/ReducedInfoTables.h" +#include "Common/CCDB/TriggerAliases.h" +#include "Common/CCDB/ctpRateFetcher.h" #include "Common/Core/PID/PIDTOFParamService.h" #include "Common/Core/TableHelper.h" +#include "Common/Core/Zorro.h" #include "Common/DataModel/CollisionAssociationTables.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/McCollisionExtra.h" @@ -70,6 +73,8 @@ using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::aod; +Zorro zorro; + // Some definitions namespace o2::aod { @@ -233,10 +238,17 @@ void PrintBitMap(TMap map, int nbits) } } +// Enum containing the ordering of statistics histograms to be written in the QA file +enum ZorroStatHist { + kStatsZorroInfo = 0, + kStatsZorroSel +}; + struct AnalysisEventSelection { Produces eventSel; Produces hash; OutputObj fOutputList{"output"}; + OutputObj fStatsList{"Statistics"}; Configurable fConfigMixingVariables{"cfgMixingVars", "", "Mixing configs separated by a comma, default no mixing"}; Configurable fConfigEventCuts{"cfgEventCuts", "eventStandard", "Event selection"}; Configurable fConfigEventCutsJSON{"cfgEventCutsJSON", "", "Additional event cuts specified in JSON format"}; @@ -248,14 +260,55 @@ struct AnalysisEventSelection { Configurable fConfigSplitCollisionsDeltaBC{"cfgSplitCollisionsDeltaBC", 100, "maximum delta-BC between two collisions to consider them as split candidates; do not apply if value is negative"}; Configurable fConfigCheckSplitCollisions{"cfgCheckSplitCollisions", false, "If true, run the split collision check and fill histograms"}; - Configurable fConfigCcdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; - Configurable fConfigNoLaterThan{"ccdb-no-later-than", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object"}; + // Zorro selection + struct : ConfigurableGroup { + Configurable fConfigRunZorro{"cfgRunZorro", false, "Enable event selection with zorro"}; + Configurable fConfigZorroTrigMask{"cfgZorroTriggerMask", "fDiMuon", "DQ Trigger masks: fSingleE,fLMeeIMR,fLMeeHMR,fDiElectron,fSingleMuLow,fSingleMuHigh,fDiMuon"}; + Configurable fConfigRunZorroSel{"cfgRunZorroSel", false, "Select events with trigger mask"}; + Configurable fBcTolerance{"cfgBcTolerance", 100, "Number of BCs of margin for software triggers"}; + Configurable fConfigCcdbPathZorro{"ccdb-path-zorro", "/Users/m/mpuccio/EventFiltering/OTS/Chunked/", "base path to the ccdb object for zorro"}; + } fConfigZorro; + + // RCT selection + struct : ConfigurableGroup { + Configurable fConfigUseRCT{"cfgUseRCT", false, "Enable event selection with RCT flags"}; + Configurable fConfigRCTLabel{"cfgRCTLabel", "CBT", "RCT flag labels : CBT, CBT_hadronPID, CBT_electronPID, CBT_calo, CBT_muon, CBT_muon_glo"}; + } fConfigRCT; + + // CCDB connection configurables + struct : ConfigurableGroup { + Configurable fConfigCcdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable fConfigCcdbPathTPC{"ccdb-path-tpc", "Users/z/zhxiong/TPCPID/PostCalib", "base path to the ccdb object"}; + Configurable fConfigNoLaterThan{"ccdb-no-later-than", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object"}; + Configurable fConfigGeoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; + Configurable fConfigGrpMagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + Configurable fZShiftPath{"zShiftPath", "Users/m/mcoquet/ZShift", "CCDB path for z shift to apply to forward tracks"}; + Configurable fConfigGrpMagPathRun2{"grpmagPathRun2", "GLO/GRP/GRP", "CCDB path of the GRPObject (Usage for Run 2)"}; + } fConfigCCDB; + + // TPC postcalibration related options + struct : ConfigurableGroup { + Configurable fConfigComputeTPCpostCalib{"cfgTPCpostCalib", false, "If true, compute TPC post-calibrated n-sigmas(electrons, pions, protons)"}; + Configurable fConfigTPCpostCalibType{"cfgTPCpostCalibType", 1, "1: (TPCncls,pIN,eta) calibration typically for pp, 2: (eta,nPV,nLong,tLong) calibration typically for PbPb"}; + Configurable fConfigTPCuseInterpolatedCalib{"cfgTPCpostCalibUseInterpolation", true, "If true, use interpolated calibration values (default: true)"}; + Configurable fConfigComputeTPCpostCalibKaon{"cfgTPCpostCalibKaon", false, "If true, compute TPC post-calibrated n-sigmas for kaons"}; + Configurable fConfigIsOnlyforMaps{"cfgIsforMaps", false, "If true, run for postcalibration maps only"}; + Configurable fConfigSaveElectronSample{"cfgSaveElectronSample", false, "If true, only save electron sample"}; + } fConfigPostCalibTPC; + + Configurable fIsRun2{"cfgIsRun2", false, "Whether we analyze Run-2 or Run-3 data"}; + + // RCT flag checker + o2::aod::rctsel::RCTFlagsChecker rctChecker{"CBT"}; HistogramManager* fHistMan = nullptr; MixingHandler* fMixHandler = nullptr; AnalysisCompositeCut* fEventCut; + o2::parameters::GRPObject* fGrpMagRun2 = nullptr; // for run 2, we access the GRPObject from GLO/GRP/GRP + o2::parameters::GRPMagField* fGrpMag = nullptr; // for run 3, we access GRPMagField from GLO/Config/GRPMagField + Service fCCDB; o2::ccdb::CcdbApi fCCDBApi; @@ -304,6 +357,16 @@ struct AnalysisEventSelection { fOutputList.setObject(fHistMan->GetMainHistogramList()); } + // Zorro information: kStatsZorroInfo + // Zorro trigger selection: kStatsZorroSel + fStatsList.setObject(new TList()); + fStatsList->SetOwner(kTRUE); + TH2D* histZorroInfo = new TH2D("ZorroInfo", "Zorro information", 1, -0.5, 0.5, 1, -0.5, 0.5); + fStatsList->AddAt(histZorroInfo, kStatsZorroInfo); + + TH2D* histZorroSel = new TH2D("ZorroSel", "trigger of interested", 1, -0.5, 0.5, 1, -0.5, 0.5); + fStatsList->AddAt(histZorroSel, kStatsZorroSel); + TString mixVarsString = fConfigMixingVariables.value; std::unique_ptr objArray(mixVarsString.Tokenize(",")); if (objArray->GetEntries() > 0) { @@ -315,11 +378,20 @@ struct AnalysisEventSelection { } fCurrentRun = -1; - fCCDB->setURL(fConfigCcdbUrl.value); + fCCDB->setURL(fConfigCCDB.fConfigCcdbUrl.value); fCCDB->setCaching(true); fCCDB->setLocalObjectValidityChecking(); - fCCDB->setCreatedNotAfter(fConfigNoLaterThan.value); - fCCDBApi.init(fConfigCcdbUrl.value); + fCCDB->setCreatedNotAfter(fConfigCCDB.fConfigNoLaterThan.value); + fCCDBApi.init(fConfigCCDB.fConfigCcdbUrl.value); + + if (!o2::base::GeometryManager::isGeometryLoaded()) { + fCCDB->get(fConfigCCDB.fConfigGeoPath.value); + } + + if (fConfigRCT.fConfigUseRCT.value) { + rctChecker.init(fConfigRCT.fConfigRCTLabel); + } + cout << "AnalysisEventSelection::init() completed" << endl; } @@ -327,13 +399,57 @@ struct AnalysisEventSelection { void runEventSelection(TEvents const& events, BCsWithTimestamps const& bcs) { cout << "AnalysisEventSelection::runEventSelection() called with " << events.size() << " events and " << bcs.size() << " BCs" << endl; - if (bcs.size() > 0 && bcs.begin().runNumber() != fCurrentRun) { + + if (bcs.size() > 0 && fCurrentRun != bcs.begin().runNumber()) { + if (fConfigPostCalibTPC.fConfigComputeTPCpostCalib) { + auto calibList = fCCDB->getForTimeStamp(fConfigCCDB.fConfigCcdbPathTPC.value, bcs.begin().timestamp()); + VarManager::SetCalibrationObject(VarManager::kTPCElectronMean, calibList->FindObject("mean_map_electron")); + VarManager::SetCalibrationObject(VarManager::kTPCElectronSigma, calibList->FindObject("sigma_map_electron")); + VarManager::SetCalibrationObject(VarManager::kTPCPionMean, calibList->FindObject("mean_map_pion")); + VarManager::SetCalibrationObject(VarManager::kTPCPionSigma, calibList->FindObject("sigma_map_pion")); + VarManager::SetCalibrationObject(VarManager::kTPCProtonMean, calibList->FindObject("mean_map_proton")); + VarManager::SetCalibrationObject(VarManager::kTPCProtonSigma, calibList->FindObject("sigma_map_proton")); + if (fConfigPostCalibTPC.fConfigComputeTPCpostCalibKaon) { + VarManager::SetCalibrationObject(VarManager::kTPCKaonMean, calibList->FindObject("mean_map_kaon")); + VarManager::SetCalibrationObject(VarManager::kTPCKaonSigma, calibList->FindObject("sigma_map_kaon")); + } + if (fConfigPostCalibTPC.fConfigTPCpostCalibType == 2) { + VarManager::SetCalibrationObject(VarManager::kTPCElectronStatus, calibList->FindObject("status_map_electron")); + VarManager::SetCalibrationObject(VarManager::kTPCPionStatus, calibList->FindObject("status_map_pion")); + VarManager::SetCalibrationObject(VarManager::kTPCProtonStatus, calibList->FindObject("status_map_proton")); + if (fConfigPostCalibTPC.fConfigComputeTPCpostCalibKaon) { + VarManager::SetCalibrationObject(VarManager::kTPCKaonStatus, calibList->FindObject("status_map_kaon")); + } + } + VarManager::SetCalibrationType(fConfigPostCalibTPC.fConfigTPCpostCalibType, fConfigPostCalibTPC.fConfigTPCuseInterpolatedCalib); + } + if (fIsRun2 == true) { + fGrpMagRun2 = fCCDB->getForTimeStamp(fConfigCCDB.fConfigGrpMagPathRun2, bcs.begin().timestamp()); + if (fGrpMagRun2 != nullptr) { + o2::base::Propagator::initFieldFromGRP(fGrpMagRun2); + } + } else { + fGrpMag = fCCDB->getForTimeStamp(fConfigCCDB.fConfigGrpMagPath, bcs.begin().timestamp()); + auto* fZShift = fCCDB->getForTimeStamp>(fConfigCCDB.fZShiftPath, bcs.begin().timestamp()); + if (fGrpMag != nullptr) { + o2::base::Propagator::initFieldFromGRP(fGrpMag); + VarManager::SetMagneticField(fGrpMag->getNominalL3Field()); + } + if (fZShift != nullptr && !fZShift->empty()) { + VarManager::SetZShift((*fZShift)[0]); + } + /*if (fConfigVariousOptions.fPropMuon) { + VarManager::SetupMuonMagField(); + }*/ + } std::map metadataRCT, header; header = fCCDBApi.retrieveHeaders(Form("RCT/Info/RunInformation/%i", bcs.begin().runNumber()), metadataRCT, -1); uint64_t sor = std::atol(header["SOR"].c_str()); uint64_t eor = std::atol(header["EOR"].c_str()); VarManager::SetSORandEOR(sor, eor); - } + + fCurrentRun = bcs.begin().runNumber(); + } // end updating the CCDB quantities at change of run cout << "Filling TimeFrame statistics histograms" << endl; VarManager::ResetValues(0, VarManager::kNEventWiseVariables); @@ -358,12 +474,33 @@ struct AnalysisEventSelection { if (fConfigQA) { fHistMan->FillHistClass("Event_BeforeCuts", VarManager::fgValues); } - if (fEventCut->IsSelected(VarManager::fgValues)) { - if (fConfigQA) { - fHistMan->FillHistClass("Event_AfterCuts", VarManager::fgValues); + + if (fConfigZorro.fConfigRunZorro) { + zorro.setBaseCCDBPath(fConfigZorro.fConfigCcdbPathZorro.value); + zorro.setBCtolerance(fConfigZorro.fBcTolerance); + zorro.initCCDB(fCCDB.service, fCurrentRun, bc.timestamp(), fConfigZorro.fConfigZorroTrigMask.value); + zorro.populateExternalHists(fCurrentRun, reinterpret_cast(fStatsList->At(kStatsZorroInfo)), reinterpret_cast(fStatsList->At(kStatsZorroSel))); + + if (!fEventCut->IsSelected(VarManager::fgValues) || (fConfigRCT.fConfigUseRCT.value && !rctChecker(event))) { + continue; + } + + bool zorroSel = zorro.isSelected(bc.globalBC(), fConfigZorro.fBcTolerance, reinterpret_cast(fStatsList->At(kStatsZorroSel))); + if (fConfigZorro.fConfigRunZorroSel && (!zorroSel)) { + continue; } - decision = true; + } else { + + if (!fEventCut->IsSelected(VarManager::fgValues) || (fConfigRCT.fConfigUseRCT.value && !rctChecker(event))) { + continue; + } + } + + decision = true; + if (fConfigQA) { + fHistMan->FillHistClass("Event_AfterCuts", VarManager::fgValues); } + fSelMap[event.globalIndex()] = decision; if (fBCCollMap.find(bc.globalBC()) == fBCCollMap.end()) { std::vector evIndices = {event.globalIndex()}; @@ -616,14 +753,22 @@ struct AnalysisTrackSelection { continue; } + /// + auto track = tracks.rawIteratorAt(assoc.trackId()); + auto evFromTrack = events.rawIteratorAt(track.collisionId()); + if (!evFromTrack.isEventSelected_bit(0)) { + trackSel(0); + continue; + } + VarManager::ResetValues(VarManager::kNTFWiseVariables, VarManager::kNBarrelTrackVariables); // fill event information which might be needed in histograms/cuts that combine track and event properties VarManager::FillEvent(event); - auto track = tracks.rawIteratorAt(assoc.trackId()); VarManager::FillTrack(track); // compute quantities which depend on the associated collision, such as DCA - VarManager::FillTrackCollision(track, event); + if (track.collisionId() != event.globalIndex()) + VarManager::FillTrackCollision(track, event); if (fConfigQA) fHistMan->FillHistClass("AssocsBarrel_BeforeCuts", VarManager::fgValues); @@ -946,6 +1091,7 @@ struct AnalysisSameEventPairing { Configurable track{"cfgTrackCuts", "jpsiO2MCdebugCuts2", "Comma separated list of barrel track cuts"}; Configurable muon{"cfgMuonCuts", "", "Comma separated list of muon cuts"}; Configurable pair{"cfgPairCuts", "", "Comma separated list of pair cuts, !!! Use only if you know what you are doing, otherwise leave empty"}; + Configurable collSplitting{"cfgRemoveCollSplittingCandidates", false, "If true, remove collision splitting candidates as determined by the event selection task upstream"}; Configurable fConfigQA{"cfgQA", false, "If true, fill QA histograms"}; Configurable fConfigAddSEPHistogram{"cfgAddSEPHistogram", "", "Comma separated list of histograms"}; Configurable fConfigAddJSONHistograms{"cfgAddJSONHistograms", "", "Histograms in JSON format"}; @@ -1356,6 +1502,10 @@ struct AnalysisSameEventPairing { if (!event.isEventSelected_bit(0)) continue; + if (fConfigOptions.collSplitting && event.isEventSelected_bit(2)) { + continue; + } + VarManager::ResetValues(0, VarManager::kNVars); VarManager::FillEvent(event, VarManager::fgValues); From edf2fee914675581ceee005ee73716aecaba2f15 Mon Sep 17 00:00:00 2001 From: Jerome Jung Date: Tue, 24 Feb 2026 10:33:40 +0100 Subject: [PATCH 059/347] =?UTF-8?q?[PWGEM]=20LMee:=20Added=20variable=20bi?= =?UTF-8?q?nning=20for=20Eta=20and=20Phi=20in=20the=20SingleTra=E2=80=A6?= =?UTF-8?q?=20(#15131)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- PWGEM/Dilepton/Core/SingleTrackQC.h | 10 ++++++---- PWGEM/Dilepton/Core/SingleTrackQCMC.h | 10 ++++++---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/PWGEM/Dilepton/Core/SingleTrackQC.h b/PWGEM/Dilepton/Core/SingleTrackQC.h index ea22e1b3d0e..8b2d00019a3 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQC.h @@ -82,6 +82,8 @@ struct SingleTrackQC { Configurable cfgApplyWeightTTCA{"cfgApplyWeightTTCA", false, "flag to apply weighting by 1/N"}; ConfigurableAxis ConfPtlBins{"ConfPtlBins", {VARIABLE_WIDTH, 0.00, 0.05, 0.10, 0.15, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90, 1.00, 1.10, 1.20, 1.30, 1.40, 1.50, 1.60, 1.70, 1.80, 1.90, 2.00, 2.50, 3.00, 3.50, 4.00, 4.50, 5.00, 6.00, 7.00, 8.00, 9.00, 10.00}, "pTl bins for output histograms"}; + ConfigurableAxis ConfEtaBins{"ConfEtaBins", {20, -1, 1}, "eta bins for output histograms"}; + ConfigurableAxis ConfPhiBins{"ConfPhiBins", {36, 0, 2 * M_PI}, "phi bins for output histograms"}; ConfigurableAxis ConfDCA3DBins{"ConfDCA3DBins", {VARIABLE_WIDTH, 0.0, 10.0}, "DCA3d bins in sigma for output histograms"}; ConfigurableAxis ConfDCAXYBins{"ConfDCAXYBins", {VARIABLE_WIDTH, -10.0, 10.0}, "DCAxy bins in sigma for output histograms"}; ConfigurableAxis ConfDCAZBins{"ConfDCAZBins", {VARIABLE_WIDTH, -10.0, 10.0}, "DCAz bins in sigma for output histograms"}; @@ -243,8 +245,8 @@ struct SingleTrackQC { if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { const AxisSpec axis_pt{ConfPtlBins, "p_{T,e} (GeV/c)"}; - const AxisSpec axis_eta{20, -1.0, +1.0, "#eta_{e}"}; - const AxisSpec axis_phi{36, 0.0, 2 * M_PI, "#varphi_{e} (rad.)"}; + const AxisSpec axis_eta{ConfEtaBins, "#eta_{e}"}; + const AxisSpec axis_phi{ConfPhiBins, "#varphi_{e} (rad.)"}; const AxisSpec axis_phiposition{36, 0.0, 2 * M_PI, "#varphi_{e}^{*} (rad.)"}; const AxisSpec axis_dca3D{ConfDCA3DBins, "DCA_{e}^{3D} (#sigma)"}; const AxisSpec axis_dcaXY{ConfDCAXYBins, "DCA_{e}^{XY} (#sigma)"}; @@ -293,8 +295,8 @@ struct SingleTrackQC { fRegistry.addClone("Track/positive/", "Track/negative/"); } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { const AxisSpec axis_pt{ConfPtlBins, "p_{T,#mu} (GeV/c)"}; - const AxisSpec axis_eta{50, -6, -1, "#eta_{#mu}"}; - const AxisSpec axis_phi{36, 0, 2 * M_PI, "#varphi_{#mu} (rad.)"}; + const AxisSpec axis_eta{ConfEtaBins, "#eta_{#mu}"}; + const AxisSpec axis_phi{ConfPhiBins, "#varphi_{#mu} (rad.)"}; const AxisSpec axis_dca{ConfDCAXYBins, "DCA_{#mu}^{XY} (#sigma)"}; // track info diff --git a/PWGEM/Dilepton/Core/SingleTrackQCMC.h b/PWGEM/Dilepton/Core/SingleTrackQCMC.h index 888102d0090..32169f6330f 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQCMC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQCMC.h @@ -92,6 +92,8 @@ struct SingleTrackQCMC { Configurable cfgRequireTrueAssociation{"cfgRequireTrueAssociation", false, "flag to require true mc collision association"}; ConfigurableAxis ConfPtlBins{"ConfPtlBins", {VARIABLE_WIDTH, 0.00, 0.05, 0.10, 0.15, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90, 1.00, 1.10, 1.20, 1.30, 1.40, 1.50, 1.60, 1.70, 1.80, 1.90, 2.00, 2.50, 3.00, 3.50, 4.00, 4.50, 5.00, 6.00, 7.00, 8.00, 9.00, 10.00}, "pTl bins for output histograms"}; + ConfigurableAxis ConfEtaBins{"ConfEtaBins", {20, -1, 1}, "eta bins for output histograms"}; + ConfigurableAxis ConfPhiBins{"ConfPhiBins", {36, 0, 2 * M_PI}, "phi bins for output histograms"}; ConfigurableAxis ConfDCA3DBins{"ConfDCA3DBins", {VARIABLE_WIDTH, 0.0, 10.0}, "DCA3d bins in sigma for output histograms"}; ConfigurableAxis ConfDCAXYBins{"ConfDCAXYBins", {VARIABLE_WIDTH, -10.0, 10.0}, "DCAxy bins in sigma for output histograms"}; ConfigurableAxis ConfDCAZBins{"ConfDCAZBins", {VARIABLE_WIDTH, -10.0, 10.0}, "DCAz bins in sigma for output histograms"}; @@ -250,8 +252,8 @@ struct SingleTrackQCMC { if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { const AxisSpec axis_pt{ConfPtlBins, "p_{T,e} (GeV/c)"}; - const AxisSpec axis_eta{20, -1.0, +1.0, "#eta_{e}"}; - const AxisSpec axis_phi{36, 0.0, 2 * M_PI, "#varphi_{e} (rad.)"}; + const AxisSpec axis_eta{ConfEtaBins, "#eta_{e}"}; + const AxisSpec axis_phi{ConfPhiBins, "#varphi_{e} (rad.)"}; const AxisSpec axis_phiposition{36, 0.0, 2 * M_PI, "#varphi_{e}^{*} (rad.)"}; const AxisSpec axis_charge_gen{3, -1.5, +1.5, "true charge"}; const AxisSpec axis_dca3D{ConfDCA3DBins, "DCA_{e}^{3D} (#sigma)"}; @@ -322,8 +324,8 @@ struct SingleTrackQCMC { } } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { const AxisSpec axis_pt{ConfPtlBins, "p_{T,#mu} (GeV/c)"}; - const AxisSpec axis_eta{50, -6, -1, "#eta_{#mu}"}; - const AxisSpec axis_phi{36, 0.0, 2 * M_PI, "#varphi_{#mu} (rad.)"}; + const AxisSpec axis_eta{ConfEtaBins, "#eta_{#mu}"}; + const AxisSpec axis_phi{ConfPhiBins, "#varphi_{#mu} (rad.)"}; const AxisSpec axis_dca{ConfDCAXYBins, "DCA_{#mu}^{XY} (#sigma)"}; const AxisSpec axis_charge_gen{3, -1.5, +1.5, "true charge"}; From 5a57092a0309c61b0b9df8a9599ebf44402f4f20 Mon Sep 17 00:00:00 2001 From: dajones2 <140733426+dajones2@users.noreply.github.com> Date: Tue, 24 Feb 2026 13:08:30 +0000 Subject: [PATCH 060/347] [PWGJE] Fixing missing table bug in MCD task (#15121) --- PWGJE/Tasks/jetHadronRecoil.cxx | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/PWGJE/Tasks/jetHadronRecoil.cxx b/PWGJE/Tasks/jetHadronRecoil.cxx index 1040911e0dc..94044235003 100644 --- a/PWGJE/Tasks/jetHadronRecoil.cxx +++ b/PWGJE/Tasks/jetHadronRecoil.cxx @@ -188,8 +188,6 @@ struct JetHadronRecoil { registry.add("hDeltaRpTReference", "jet p_{T} vs #DeltaR;p_{T,jet};#DeltaR", {HistType::kTH2F, {{500, -100, 400}, dRAxis}}, doSumw); registry.add("hDeltaRpTDPhiReference", "jet p_{T} vs #DeltaR vs #Delta#phi;p_{T,jet};#Delta#phi;#DeltaR", {HistType::kTH3F, {{500, -100, 400}, {100, 0, o2::constants::math::TwoPI}, dRAxis}}, doSumw); registry.add("hDeltaRpTDPhiReferenceShifts", "testing shifts;p_{T,jet};#Delta#phi;#DeltaR;shifts", {HistType::kTHnSparseD, {{500, -100, 400}, {100, 0, o2::constants::math::TwoPI}, dRAxis, {20, 0.0, 2.0}}}, doSumw); - registry.add("hPtTrackMatched", "Track p_{T};p_{T};entries", {HistType::kTH1F, {{200, 0, 200}}}, doSumw); - registry.add("hPtTrackMatchedToCollisions", "Track p_{T};p_{T};entries", {HistType::kTH1F, {{200, 0, 200}}}, doSumw); } if (doprocessMCP || doprocessMCPWeighted || doprocessMCPOnTheFly || doprocessMCPOnTheFlyWeighted) { @@ -383,7 +381,7 @@ struct JetHadronRecoil { } template - void fillHistogramsMCD(T const& jets, U const& tracks, float weight = 1.0, float rho = 0.0, float pTHat = 999.0, auto collisionID = 0) + void fillHistogramsMCD(T const& jets, U const& tracks, float weight = 1.0, float rho = 0.0, float pTHat = 999.0) { bool isSigCol; std::vector phiTTAr; @@ -433,13 +431,6 @@ struct JetHadronRecoil { registry.fill(HIST("hPhiTrack"), track.phi(), weight); registry.fill(HIST("hTrack3D"), track.pt(), track.eta(), track.phi(), weight); registry.fill(HIST("hPtTrackPtHard"), track.pt() / pTHat, track.pt(), weight); - if (track.has_mcParticle()) { - registry.fill(HIST("hPtTrackMatched"), track.pt(), weight); - auto mcParticle = track.mcParticle(); - if (mcParticle.mcCollisionId() == collisionID) { - registry.fill(HIST("hPtTrackMatchedToCollisions"), track.pt(), weight); - } - } } if (nTT > 0) { int trigNumber = rand->Integer(nTT); @@ -891,7 +882,7 @@ struct JetHadronRecoil { return; } registry.fill(HIST("hZvtxSelected"), collision.posZ()); - fillHistogramsMCD(jets, tracks, 1.0, 0.0, collision.mcCollision().ptHard(), collision.mcCollisionId()); + fillHistogramsMCD(jets, tracks, 1.0, 0.0, collision.mcCollision().ptHard()); } PROCESS_SWITCH(JetHadronRecoil, processMCD, "process MC detector level", false); @@ -913,7 +904,7 @@ struct JetHadronRecoil { return; } registry.fill(HIST("hZvtxSelected"), collision.posZ()); - fillHistogramsMCD(jets, tracks, 1.0, collision.rho(), collision.mcCollision().ptHard(), collision.mcCollisionId()); + fillHistogramsMCD(jets, tracks, 1.0, collision.rho(), collision.mcCollision().ptHard()); } PROCESS_SWITCH(JetHadronRecoil, processMCDWithRhoSubtraction, "process MC detector level with rho subtraction", false); @@ -935,7 +926,7 @@ struct JetHadronRecoil { return; } registry.fill(HIST("hZvtxSelected"), collision.posZ(), collision.mcCollision().weight()); - fillHistogramsMCD(jets, tracks, collision.mcCollision().weight(), 0.0, collision.mcCollision().ptHard(), collision.mcCollisionId()); + fillHistogramsMCD(jets, tracks, collision.mcCollision().weight(), 0.0, collision.mcCollision().ptHard()); } PROCESS_SWITCH(JetHadronRecoil, processMCDWeighted, "process MC detector level with event weights", false); @@ -957,7 +948,7 @@ struct JetHadronRecoil { return; } registry.fill(HIST("hZvtxSelected"), collision.posZ(), collision.mcCollision().weight()); - fillHistogramsMCD(jets, tracks, collision.mcCollision().weight(), collision.rho(), collision.mcCollision().ptHard(), collision.mcCollisionId()); + fillHistogramsMCD(jets, tracks, collision.mcCollision().weight(), collision.rho(), collision.mcCollision().ptHard()); } PROCESS_SWITCH(JetHadronRecoil, processMCDWeightedWithRhoSubtraction, "process MC detector level with event weights and rho subtraction", false); From 2355eebc6e3372c0b644a19f686321a76f263253 Mon Sep 17 00:00:00 2001 From: SCHOTTER Romain <47983209+romainschotter@users.noreply.github.com> Date: Tue, 24 Feb 2026 16:39:40 +0100 Subject: [PATCH 061/347] [PWGLF] Require TOF on at least one of the decay daughters (#15128) Co-authored-by: ALICE Builder --- .../derivedlambdakzeroanalysis.cxx | 98 +++++++++++++------ 1 file changed, 68 insertions(+), 30 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/derivedlambdakzeroanalysis.cxx b/PWGLF/Tasks/Strangeness/derivedlambdakzeroanalysis.cxx index 5a5f720e1ad..8700b91bfd0 100644 --- a/PWGLF/Tasks/Strangeness/derivedlambdakzeroanalysis.cxx +++ b/PWGLF/Tasks/Strangeness/derivedlambdakzeroanalysis.cxx @@ -215,6 +215,8 @@ struct derivedlambdakzeroanalysis { Configurable rejectNegITSafterburner{"rejectNegITSafterburner", false, "reject negative track formed out of afterburner ITS tracks"}; Configurable requirePosITSafterburnerOnly{"requirePosITSafterburnerOnly", false, "require positive track formed out of afterburner ITS tracks"}; Configurable requireNegITSafterburnerOnly{"requireNegITSafterburnerOnly", false, "require negative track formed out of afterburner ITS tracks"}; + Configurable requirePosHasTOF{"requirePosHasTOF", false, "require that positive track has an associated TOF signal. On false, TOF requirement (if any) is only applied IF the track has an associated TOF signal."}; + Configurable requireNegHasTOF{"requireNegHasTOF", false, "require that negative track has an associated TOF signal. On false, TOF requirement (if any) is only applied IF the track has an associated TOF signal."}; Configurable rejectTPCsectorBoundary{"rejectTPCsectorBoundary", false, "reject tracks close to the TPC sector boundaries"}; Configurable phiLowCut{"phiLowCut", "0.06/x+pi/18.0-0.06", "Low azimuth cut parametrisation"}; Configurable phiHighCut{"phiHighCut", "0.1/x+pi/18.0+0.06", "High azimuth cut parametrisation"}; @@ -527,15 +529,15 @@ struct derivedlambdakzeroanalysis { BITSET(maskAntiLambdaSpecific, selTPCPIDPositivePion); } // TOF PID - if (v0Selections.tofPidNsigmaCutK0Pi < 1e+5) { // safeguard for no cut + if (v0Selections.requirePosHasTOF || v0Selections.tofPidNsigmaCutK0Pi < 1e+5 || v0Selections.maxDeltaTimePion < 1e+6) { // safeguard for no cut BITSET(maskK0ShortSpecific, selTOFNSigmaPositivePionK0Short); BITSET(maskK0ShortSpecific, selTOFDeltaTPositivePionK0Short); } - if (v0Selections.tofPidNsigmaCutLaPr < 1e+5) { // safeguard for no cut + if (v0Selections.requirePosHasTOF || v0Selections.tofPidNsigmaCutLaPr < 1e+5 || v0Selections.maxDeltaTimeProton < 1e+6) { // safeguard for no cut BITSET(maskLambdaSpecific, selTOFNSigmaPositiveProtonLambda); BITSET(maskLambdaSpecific, selTOFDeltaTPositiveProtonLambda); } - if (v0Selections.tofPidNsigmaCutLaPi < 1e+5) { // safeguard for no cut + if (v0Selections.requirePosHasTOF || v0Selections.tofPidNsigmaCutLaPi < 1e+5 || v0Selections.maxDeltaTimePion < 1e+6) { // safeguard for no cut BITSET(maskAntiLambdaSpecific, selTOFNSigmaPositivePionLambda); BITSET(maskAntiLambdaSpecific, selTOFDeltaTPositivePionLambda); } @@ -553,15 +555,15 @@ struct derivedlambdakzeroanalysis { BITSET(maskAntiLambdaSpecific, selTPCPIDNegativeProton); } // TOF PID - if (v0Selections.tofPidNsigmaCutK0Pi < 1e+5) { // safeguard for no cut + if (v0Selections.requireNegHasTOF || v0Selections.tofPidNsigmaCutK0Pi < 1e+5 || v0Selections.maxDeltaTimePion < 1e+6) { // safeguard for no cut BITSET(maskK0ShortSpecific, selTOFNSigmaNegativePionK0Short); BITSET(maskK0ShortSpecific, selTOFDeltaTNegativePionK0Short); } - if (v0Selections.tofPidNsigmaCutLaPi < 1e+5) { // safeguard for no cut + if (v0Selections.requireNegHasTOF || v0Selections.tofPidNsigmaCutLaPi < 1e+5 || v0Selections.maxDeltaTimePion < 1e+6) { // safeguard for no cut BITSET(maskLambdaSpecific, selTOFNSigmaNegativePionLambda); BITSET(maskLambdaSpecific, selTOFDeltaTNegativePionLambda); } - if (v0Selections.tofPidNsigmaCutLaPr < 1e+5) { // safeguard for no cut + if (v0Selections.requireNegHasTOF || v0Selections.tofPidNsigmaCutLaPr < 1e+5 || v0Selections.maxDeltaTimeProton < 1e+6) { // safeguard for no cut BITSET(maskAntiLambdaSpecific, selTOFNSigmaNegativeProtonLambda); BITSET(maskAntiLambdaSpecific, selTOFDeltaTNegativeProtonLambda); } @@ -1312,35 +1314,71 @@ struct derivedlambdakzeroanalysis { // TOF PID in DeltaT // Positive track - if (!posTrackExtra.hasTOF() || std::fabs(v0.posTOFDeltaTLaPr()) < v0Selections.maxDeltaTimeProton) - BITSET(bitMap, selTOFDeltaTPositiveProtonLambda); - if (!posTrackExtra.hasTOF() || std::fabs(v0.posTOFDeltaTLaPi()) < v0Selections.maxDeltaTimePion) - BITSET(bitMap, selTOFDeltaTPositivePionLambda); - if (!posTrackExtra.hasTOF() || std::fabs(v0.posTOFDeltaTK0Pi()) < v0Selections.maxDeltaTimePion) - BITSET(bitMap, selTOFDeltaTPositivePionK0Short); + if (v0Selections.requirePosHasTOF) { + if (v0.positiveHasTOF() && std::fabs(v0.posTOFDeltaTLaPr()) < v0Selections.maxDeltaTimeProton) + BITSET(bitMap, selTOFDeltaTPositiveProtonLambda); + if (v0.positiveHasTOF() && std::fabs(v0.posTOFDeltaTLaPi()) < v0Selections.maxDeltaTimePion) + BITSET(bitMap, selTOFDeltaTPositivePionLambda); + if (v0.positiveHasTOF() && std::fabs(v0.posTOFDeltaTK0Pi()) < v0Selections.maxDeltaTimePion) + BITSET(bitMap, selTOFDeltaTPositivePionK0Short); + } else { // only apply TOF requirement if available + if (!v0.positiveHasTOF() || std::fabs(v0.posTOFDeltaTLaPr()) < v0Selections.maxDeltaTimeProton) + BITSET(bitMap, selTOFDeltaTPositiveProtonLambda); + if (!v0.positiveHasTOF() || std::fabs(v0.posTOFDeltaTLaPi()) < v0Selections.maxDeltaTimePion) + BITSET(bitMap, selTOFDeltaTPositivePionLambda); + if (!v0.positiveHasTOF() || std::fabs(v0.posTOFDeltaTK0Pi()) < v0Selections.maxDeltaTimePion) + BITSET(bitMap, selTOFDeltaTPositivePionK0Short); + } // Negative track - if (!negTrackExtra.hasTOF() || std::fabs(v0.negTOFDeltaTLaPr()) < v0Selections.maxDeltaTimeProton) - BITSET(bitMap, selTOFDeltaTNegativeProtonLambda); - if (!negTrackExtra.hasTOF() || std::fabs(v0.negTOFDeltaTLaPi()) < v0Selections.maxDeltaTimePion) - BITSET(bitMap, selTOFDeltaTNegativePionLambda); - if (!negTrackExtra.hasTOF() || std::fabs(v0.negTOFDeltaTK0Pi()) < v0Selections.maxDeltaTimePion) - BITSET(bitMap, selTOFDeltaTNegativePionK0Short); + if (v0Selections.requireNegHasTOF) { + if (v0.negativeHasTOF() && std::fabs(v0.negTOFDeltaTLaPr()) < v0Selections.maxDeltaTimeProton) + BITSET(bitMap, selTOFDeltaTNegativeProtonLambda); + if (v0.negativeHasTOF() && std::fabs(v0.negTOFDeltaTLaPi()) < v0Selections.maxDeltaTimePion) + BITSET(bitMap, selTOFDeltaTNegativePionLambda); + if (v0.negativeHasTOF() && std::fabs(v0.negTOFDeltaTK0Pi()) < v0Selections.maxDeltaTimePion) + BITSET(bitMap, selTOFDeltaTNegativePionK0Short); + } else { // only apply TOF requirement if available + if (!v0.negativeHasTOF() || std::fabs(v0.negTOFDeltaTLaPr()) < v0Selections.maxDeltaTimeProton) + BITSET(bitMap, selTOFDeltaTNegativeProtonLambda); + if (!v0.negativeHasTOF() || std::fabs(v0.negTOFDeltaTLaPi()) < v0Selections.maxDeltaTimePion) + BITSET(bitMap, selTOFDeltaTNegativePionLambda); + if (!v0.negativeHasTOF() || std::fabs(v0.negTOFDeltaTK0Pi()) < v0Selections.maxDeltaTimePion) + BITSET(bitMap, selTOFDeltaTNegativePionK0Short); + } // TOF PID in NSigma // Positive track - if (!posTrackExtra.hasTOF() || std::fabs(v0.tofNSigmaLaPr()) < v0Selections.tofPidNsigmaCutLaPr) - BITSET(bitMap, selTOFNSigmaPositiveProtonLambda); - if (!posTrackExtra.hasTOF() || std::fabs(v0.tofNSigmaALaPi()) < v0Selections.tofPidNsigmaCutLaPi) - BITSET(bitMap, selTOFNSigmaPositivePionLambda); - if (!posTrackExtra.hasTOF() || std::fabs(v0.tofNSigmaK0PiPlus()) < v0Selections.tofPidNsigmaCutK0Pi) - BITSET(bitMap, selTOFNSigmaPositivePionK0Short); + if (v0Selections.requirePosHasTOF) { + if (v0.positiveHasTOF() && std::fabs(v0.tofNSigmaLaPr()) < v0Selections.tofPidNsigmaCutLaPr) + BITSET(bitMap, selTOFNSigmaPositiveProtonLambda); + if (v0.positiveHasTOF() && std::fabs(v0.tofNSigmaALaPi()) < v0Selections.tofPidNsigmaCutLaPi) + BITSET(bitMap, selTOFNSigmaPositivePionLambda); + if (v0.positiveHasTOF() && std::fabs(v0.tofNSigmaK0PiPlus()) < v0Selections.tofPidNsigmaCutK0Pi) + BITSET(bitMap, selTOFNSigmaPositivePionK0Short); + } else { // only apply TOF requirement if available + if (!v0.positiveHasTOF() || std::fabs(v0.tofNSigmaLaPr()) < v0Selections.tofPidNsigmaCutLaPr) + BITSET(bitMap, selTOFNSigmaPositiveProtonLambda); + if (!v0.positiveHasTOF() || std::fabs(v0.tofNSigmaALaPi()) < v0Selections.tofPidNsigmaCutLaPi) + BITSET(bitMap, selTOFNSigmaPositivePionLambda); + if (!v0.positiveHasTOF() || std::fabs(v0.tofNSigmaK0PiPlus()) < v0Selections.tofPidNsigmaCutK0Pi) + BITSET(bitMap, selTOFNSigmaPositivePionK0Short); + } // Negative track - if (!negTrackExtra.hasTOF() || std::fabs(v0.tofNSigmaALaPr()) < v0Selections.tofPidNsigmaCutLaPr) - BITSET(bitMap, selTOFNSigmaNegativeProtonLambda); - if (!negTrackExtra.hasTOF() || std::fabs(v0.tofNSigmaLaPi()) < v0Selections.tofPidNsigmaCutLaPi) - BITSET(bitMap, selTOFNSigmaNegativePionLambda); - if (!negTrackExtra.hasTOF() || std::fabs(v0.tofNSigmaK0PiMinus()) < v0Selections.tofPidNsigmaCutK0Pi) - BITSET(bitMap, selTOFNSigmaNegativePionK0Short); + if (v0Selections.requireNegHasTOF) { + if (v0.negativeHasTOF() && std::fabs(v0.tofNSigmaALaPr()) < v0Selections.tofPidNsigmaCutLaPr) + BITSET(bitMap, selTOFNSigmaNegativeProtonLambda); + if (v0.negativeHasTOF() && std::fabs(v0.tofNSigmaLaPi()) < v0Selections.tofPidNsigmaCutLaPi) + BITSET(bitMap, selTOFNSigmaNegativePionLambda); + if (v0.negativeHasTOF() && std::fabs(v0.tofNSigmaK0PiMinus()) < v0Selections.tofPidNsigmaCutK0Pi) + BITSET(bitMap, selTOFNSigmaNegativePionK0Short); + } else { // only apply TOF requirement if available + if (!v0.negativeHasTOF() || std::fabs(v0.tofNSigmaALaPr()) < v0Selections.tofPidNsigmaCutLaPr) + BITSET(bitMap, selTOFNSigmaNegativeProtonLambda); + if (!v0.negativeHasTOF() || std::fabs(v0.tofNSigmaLaPi()) < v0Selections.tofPidNsigmaCutLaPi) + BITSET(bitMap, selTOFNSigmaNegativePionLambda); + if (!v0.negativeHasTOF() || std::fabs(v0.tofNSigmaK0PiMinus()) < v0Selections.tofPidNsigmaCutK0Pi) + BITSET(bitMap, selTOFNSigmaNegativePionK0Short); + } // ITS only tag if (posTrackExtra.tpcCrossedRows() < 1) From fe1ed0b5925b5d8bb9dc82a78676aff3720e908c Mon Sep 17 00:00:00 2001 From: Chiara De Martin <39315597+ChiaraDeMartin95@users.noreply.github.com> Date: Tue, 24 Feb 2026 16:39:42 +0100 Subject: [PATCH 062/347] Addition of one histogram for rapidities (#15134) Co-authored-by: Chiara De Martin --- PWGLF/TableProducer/Strangeness/cascadeflow.cxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/PWGLF/TableProducer/Strangeness/cascadeflow.cxx b/PWGLF/TableProducer/Strangeness/cascadeflow.cxx index d3439736b36..d342a3effcd 100644 --- a/PWGLF/TableProducer/Strangeness/cascadeflow.cxx +++ b/PWGLF/TableProducer/Strangeness/cascadeflow.cxx @@ -930,6 +930,7 @@ struct cascadeFlow { histos.add("hv2CEPvsv2CSP", "hv2CEPvsV2CSP", HistType::kTH2F, {{100, -1, 1}, {100, -1, 1}}); histos.add("hv1EPvsv1SP", "hV1EPvsV1SP", HistType::kTH2F, {{100, -1, 1}, {100, -1, 1}}); histos.add("hv1SP_ZDCA_vs_ZDCC", "hv1SP_ZDCA_vs_ZDCC", HistType::kTH2F, {{100, -1, 1}, {100, -1, 1}}); + histos.add("hV0RapidityvsPt", "hV0RapidityvsPt", HistType::kTH2F, {{100, 0, 10}, {100, -2, 2}}); histos.add("hEtaV0", "hEtaV0", HistType::kTH1F, {{100, -1, 1}}); histos.add("hEtaV0posDau", "hEtaV0posDau", HistType::kTH1F, {{100, -1, 1}}); histos.add("hEtaV0negDau", "hEtaV0negDau", HistType::kTH1F, {{100, -1, 1}}); @@ -2039,6 +2040,7 @@ struct cascadeFlow { if (!isSelectedV0[0] && !isSelectedV0[1]) continue; + histos.fill(HIST("hV0RapidityvsPt"), v0.pt(), v0.yLambda()); histos.fill(HIST("hEtaV0"), v0.eta()); Float_t posDauEta = RecoDecay::eta(std::array{v0.pxpos(), v0.pypos(), v0.pzpos()}); histos.fill(HIST("hEtaV0posDau"), posDauEta); From af85197d502337840d8b8bdfc35c5623e77d1bb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?BiaoZhang=20=28=E5=BC=A0=E5=BD=AA=29?= <52267892+zhangbiao-phy@users.noreply.github.com> Date: Tue, 24 Feb 2026 16:49:30 +0100 Subject: [PATCH 063/347] [PWGHF] Add missing headers in PID utilities and 3-prong candidate creator (#15141) --- PWGHF/TableProducer/candidateCreator3Prong.cxx | 1 + PWGHF/Utils/utilsPid.h | 2 ++ 2 files changed, 3 insertions(+) diff --git a/PWGHF/TableProducer/candidateCreator3Prong.cxx b/PWGHF/TableProducer/candidateCreator3Prong.cxx index 334f185a169..7ae95c956b7 100644 --- a/PWGHF/TableProducer/candidateCreator3Prong.cxx +++ b/PWGHF/TableProducer/candidateCreator3Prong.cxx @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include diff --git a/PWGHF/Utils/utilsPid.h b/PWGHF/Utils/utilsPid.h index 3f7aa28f5cc..674315edc81 100644 --- a/PWGHF/Utils/utilsPid.h +++ b/PWGHF/Utils/utilsPid.h @@ -21,6 +21,8 @@ #include "Common/DataModel/PIDResponseTPC.h" #include +#include +#include #include #include From f581998054ad0532df9165758de67faa26b242c8 Mon Sep 17 00:00:00 2001 From: Shirajum Monira <38348689+Eloviyo@users.noreply.github.com> Date: Tue, 24 Feb 2026 18:00:47 +0200 Subject: [PATCH 064/347] [PWGCF] FemtoUniverse Producer -- fixed mc collision reco check for v0 (#15142) Co-authored-by: Shirajum Monira --- PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx b/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx index f39369b4052..97d4e4f7437 100644 --- a/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx +++ b/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx @@ -2581,6 +2581,7 @@ struct FemtoUniverseProducerTask { fillCascade(col, groupedStrageParts, groupedTracks); } } else { + mcColIds.insert(col.mcCollisionId()); fillCollisionsAndTracksAndV0AndPhi(col, groupedTracks, groupedStrageParts); } for (const auto& track : groupedTracks) { From 4707dfae1ed836822c7bdb944dc8ea3b7e008b99 Mon Sep 17 00:00:00 2001 From: nzardosh Date: Tue, 24 Feb 2026 18:53:13 +0000 Subject: [PATCH 065/347] [PWGHF] fixing missing particle enabling for Alphas (#15145) --- PWGHF/TableProducer/mcPidTof.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWGHF/TableProducer/mcPidTof.cxx b/PWGHF/TableProducer/mcPidTof.cxx index dba9eb2753f..89dfc8530f9 100644 --- a/PWGHF/TableProducer/mcPidTof.cxx +++ b/PWGHF/TableProducer/mcPidTof.cxx @@ -777,7 +777,7 @@ struct McPidTof { { mTOFCalibConfig.inheritFromBaseTask(initContext); // Checking the tables are requested in the workflow and enabling them (only pi, K, p) - std::array supportedSpecies = {IdxPi, IdxKa, IdxPr, IdxDe, IdxTr, IdxHe}; + std::array supportedSpecies = {IdxPi, IdxKa, IdxPr, IdxDe, IdxTr, IdxHe, IdxAl}; for (auto iSpecie{0u}; iSpecie < supportedSpecies.size(); ++iSpecie) { // First checking tiny int flag = -1; From 1210c2fc3eddd5b43c0562f9c2265b53fef6ca32 Mon Sep 17 00:00:00 2001 From: nkaratze Date: Tue, 24 Feb 2026 21:10:27 +0100 Subject: [PATCH 066/347] [PWGLF] Corrected centrality calibration in RecoMC process (#15148) --- PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx | 103 ++++++++++--------- 1 file changed, 54 insertions(+), 49 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx b/PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx index 62bfb559261..976e0f3a4bf 100644 --- a/PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx +++ b/PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx @@ -378,6 +378,7 @@ struct V0PtInvMassPlots { rPtAnalysis.fill(HIST("hNEvents"), 5.5, collision.centFT0M()); rPtAnalysis.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(6, "cutZVertex"); if (doisInelGt0 && !(collision.multNTracksPVeta1() > 0)) { + // if (doisInelGt0 && !(collision.multMCNParticlesEta10() > 0)) { //CHANGE TO THIS return false; } rPtAnalysis.fill(HIST("hNEvents"), 6.5, collision.centFT0M()); @@ -694,17 +695,18 @@ struct V0PtInvMassPlots { using DaughterTracksDerived = soa::Join; o2::framework::Service pdgDB; - void genMCProcess( - soa::Join::iterator const& mcCollision, - soa::SmallGroups> const& collisions, - aod::McParticles const& mcParticles) + // This is the process for Generated Particles + void genMCProcess(soa::Join::iterator const& mcCollision, + soa::SmallGroups> const& collisions, + aod::McParticles const& mcParticles) { // Event Efficiency, Event Split and V0 Signal Loss Corrections rMCCorrections.fill(HIST("hNEvents_Corrections"), 0.5, mcCollision.centFT0M()); // All Events if (std::abs(mcCollision.posZ()) > cutZVertex) { return; } - if (!pwglf::isINELgtNmc(mcParticles, 0, pdgDB)) { + if (!(mcCollision.multMCNParticlesEta10() > 0)) { // TRY TO CHANGE TO THIS + // if (!pwglf::isINELgtNmc(mcParticles, 0, pdgDB)) { return; } rMCCorrections.fill(HIST("hNEvents_Corrections"), 1.5, mcCollision.centFT0M()); // Event Efficiency Denominator @@ -787,7 +789,8 @@ struct V0PtInvMassPlots { // End of Signal Loss Numenator Loop } // This is the Process for the MC reconstructed Data - void recMCProcess(soa::Join::iterator const& collision, + void recMCProcess(soa::Join::iterator const& collision, + soa::Join const& /*mcCollisions*/, soa::Join const& V0s, DaughterTracks const&, // no need to define a variable for tracks, if we don't access them directly aod::McParticles const& /*mcParticles*/) @@ -808,6 +811,9 @@ struct V0PtInvMassPlots { std::vector lambdaptedgevalues(nLambdaHistograms + 1); std::vector antilambdaptedgevalues(nAntilambdaHistograms + 1); + // For centrality estimation + const auto& mcCollision = collision.mcCollision_as>(); + for (int i = 0; i < nKaonHistograms + 1; i++) { kaonptedgevalues[i] = std::stod(pthistos::kaonPtBins[i]); } @@ -820,21 +826,21 @@ struct V0PtInvMassPlots { if (!acceptEvent(collision)) { // Event Selection return; } - rPtAnalysis.fill(HIST("hNRecEvents"), 0.5, collision.centFT0M()); // Event Split Numenator + rPtAnalysis.fill(HIST("hNRecEvents"), 0.5, mcCollision.centFT0M()); // Event Split Numenator for (const auto& v0 : V0s) { // Checking that the V0 is a true K0s/Lambdas/Antilambdas and then filling the parameter histograms and the invariant mass plots for different cuts (which are taken from namespace) const auto& posDaughterTrack = v0.template posTrack_as(); const auto& negDaughterTrack = v0.template negTrack_as(); - if (!acceptV0(v0, posDaughterTrack, negDaughterTrack, collision)) { // V0 Selections + if (!acceptV0(v0, posDaughterTrack, negDaughterTrack, mcCollision)) { // V0 Selections continue; } // kzero analysis if (kzeroAnalysis == true) { - if (acceptK0sh(v0, posDaughterTrack, negDaughterTrack, collision)) { // K0sh Selection + if (acceptK0sh(v0, posDaughterTrack, negDaughterTrack, mcCollision)) { // K0sh Selection // K0sh Signal Split Numerator Start for (int i = 0; i < nKaonHistograms; i++) { if (kaonptedgevalues[i] <= v0.pt() && v0.pt() < kaonptedgevalues[i + 1]) { // finding v0s with pt within the range of our bin edges for K0sh Splitting Numerator - pthistos::kaonSplit[i]->Fill(v0.mK0Short(), collision.centFT0M()); // filling the k0s namespace histograms for K0sh Splitting Numerator + pthistos::kaonSplit[i]->Fill(v0.mK0Short(), mcCollision.centFT0M()); // filling the k0s namespace histograms for K0sh Splitting Numerator } } // K0sh Signla Split Numerator End @@ -844,7 +850,7 @@ struct V0PtInvMassPlots { if (v0mcParticle.isPhysicalPrimary()) { for (int i = 0; i < nKaonHistograms; i++) { if (kaonptedgevalues[i] <= v0.pt() && v0.pt() < kaonptedgevalues[i + 1]) { // finding v0s with pt within the range of our bin edges - pthistos::kaonPt[i]->Fill(v0.mK0Short(), collision.centFT0M()); // filling the k0s namespace histograms + pthistos::kaonPt[i]->Fill(v0.mK0Short(), mcCollision.centFT0M()); // filling the k0s namespace histograms } } } @@ -852,9 +858,9 @@ struct V0PtInvMassPlots { auto v0mothers = v0mcParticle.mothers_as(); // Get mothers if (!v0mothers.empty()) { auto& v0mcParticleMother = v0mothers.front(); // First mother - rFeeddownMatrices.fill(HIST("hK0shFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt(), collision.centFT0M()); + rFeeddownMatrices.fill(HIST("hK0shFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt(), mcCollision.centFT0M()); if (v0mcParticleMother.pdgCode() == kPhi) { // Phi Mother Matched - rFeeddownMatrices.fill(HIST("hK0shPhiFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt(), collision.centFT0M()); + rFeeddownMatrices.fill(HIST("hK0shPhiFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt(), mcCollision.centFT0M()); } } } @@ -864,11 +870,11 @@ struct V0PtInvMassPlots { } // lambda analysis if (lambdaAnalysis == true) { - if (acceptLambda(v0, posDaughterTrack, negDaughterTrack, collision)) { // Lambda Selections + if (acceptLambda(v0, posDaughterTrack, negDaughterTrack, mcCollision)) { // Lambda Selections // Lambda Signal Split Numerator Start for (int i = 0; i < nLambdaHistograms; i++) { if (lambdaptedgevalues[i] <= v0.pt() && v0.pt() < lambdaptedgevalues[i + 1]) { - pthistos::lambdaSplit[i]->Fill(v0.mLambda(), collision.centFT0M()); + pthistos::lambdaSplit[i]->Fill(v0.mLambda(), mcCollision.centFT0M()); } } // Lambda Signal Split Numerator End @@ -878,7 +884,7 @@ struct V0PtInvMassPlots { if (v0mcParticle.isPhysicalPrimary()) { for (int i = 0; i < nLambdaHistograms; i++) { if (lambdaptedgevalues[i] <= v0.pt() && v0.pt() < lambdaptedgevalues[i + 1]) { - pthistos::lambdaPt[i]->Fill(v0.mLambda(), collision.centFT0M()); + pthistos::lambdaPt[i]->Fill(v0.mLambda(), mcCollision.centFT0M()); } } } @@ -886,15 +892,15 @@ struct V0PtInvMassPlots { auto v0mothers = v0mcParticle.mothers_as(); // Get mothers if (!v0mothers.empty()) { auto& v0mcParticleMother = v0mothers.front(); // First mother - rFeeddownMatrices.fill(HIST("hLambdaFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt(), collision.centFT0M()); + rFeeddownMatrices.fill(HIST("hLambdaFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt(), mcCollision.centFT0M()); if (v0mcParticleMother.pdgCode() == kXiMinus) { // Xi Minus Mother Matched - rFeeddownMatrices.fill(HIST("hLambdaXiMinusFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt(), collision.centFT0M()); + rFeeddownMatrices.fill(HIST("hLambdaXiMinusFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt(), mcCollision.centFT0M()); } if (v0mcParticleMother.pdgCode() == kXi0) { // Xi Zero Mother Matched - rFeeddownMatrices.fill(HIST("hLambdaXiZeroFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt(), collision.centFT0M()); + rFeeddownMatrices.fill(HIST("hLambdaXiZeroFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt(), mcCollision.centFT0M()); } if (v0mcParticleMother.pdgCode() == kOmegaMinus) { // Omega Mother Matched - rFeeddownMatrices.fill(HIST("hLambdaOmegaFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt(), collision.centFT0M()); + rFeeddownMatrices.fill(HIST("hLambdaOmegaFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt(), mcCollision.centFT0M()); } } } @@ -904,11 +910,11 @@ struct V0PtInvMassPlots { } // antilambda analysis if (antiLambdaAnalysis == true) { - if (acceptAntilambda(v0, posDaughterTrack, negDaughterTrack, collision)) { // Antilambda Selections + if (acceptAntilambda(v0, posDaughterTrack, negDaughterTrack, mcCollision)) { // Antilambda Selections // Antilambda Signal Split Numerator End for (int i = 0; i < nAntilambdaHistograms; i++) { if (antilambdaptedgevalues[i] <= v0.pt() && v0.pt() < antilambdaptedgevalues[i + 1]) { - pthistos::antilambdaSplit[i]->Fill(v0.mAntiLambda(), collision.centFT0M()); + pthistos::antilambdaSplit[i]->Fill(v0.mAntiLambda(), mcCollision.centFT0M()); } } // Antilambda Signal Split Numerator End @@ -918,7 +924,7 @@ struct V0PtInvMassPlots { if (v0mcParticle.isPhysicalPrimary()) { for (int i = 0; i < nAntilambdaHistograms; i++) { if (antilambdaptedgevalues[i] <= v0.pt() && v0.pt() < antilambdaptedgevalues[i + 1]) { - pthistos::antilambdaPt[i]->Fill(v0.mAntiLambda(), collision.centFT0M()); + pthistos::antilambdaPt[i]->Fill(v0.mAntiLambda(), mcCollision.centFT0M()); } } } @@ -926,15 +932,15 @@ struct V0PtInvMassPlots { auto v0mothers = v0mcParticle.mothers_as(); // Get mothers if (!v0mothers.empty()) { auto& v0mcParticleMother = v0mothers.front(); // First mother - rFeeddownMatrices.fill(HIST("hAntiLambdaFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt(), collision.centFT0M()); + rFeeddownMatrices.fill(HIST("hAntiLambdaFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt(), mcCollision.centFT0M()); if (v0mcParticleMother.pdgCode() == kXiPlusBar) { // Xi Plus Mother Matched - rFeeddownMatrices.fill(HIST("hAntiLambdaXiPlusFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt(), collision.centFT0M()); + rFeeddownMatrices.fill(HIST("hAntiLambdaXiPlusFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt(), mcCollision.centFT0M()); } if (v0mcParticleMother.pdgCode() == -kXi0) { // Anti-Xi Zero Mother Matched - rFeeddownMatrices.fill(HIST("hAntiLambdaAntiXiZeroFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt(), collision.centFT0M()); + rFeeddownMatrices.fill(HIST("hAntiLambdaAntiXiZeroFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt(), mcCollision.centFT0M()); } if (v0mcParticleMother.pdgCode() == kOmegaPlusBar) { // Anti-Omega (minus) Mother Matched - rFeeddownMatrices.fill(HIST("hAntiLambdaAntiOmegaFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt(), collision.centFT0M()); + rFeeddownMatrices.fill(HIST("hAntiLambdaAntiOmegaFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt(), mcCollision.centFT0M()); } } } @@ -945,7 +951,7 @@ struct V0PtInvMassPlots { } } // This is the process for Real Data - void dataProcess(soa::Join::iterator const& collision, + void dataProcess(soa::Join::iterator const& collision, aod::V0Datas const& V0s, DaughterTracks const&) { @@ -975,9 +981,9 @@ struct V0PtInvMassPlots { antilambdaptedgevalues[i] = std::stod(pthistos::antilambdaPtBins[i]); } - if (!acceptEvent(collision)) { // Event Selection - return; - } + // if (!acceptEvent(collision)) { // Event Selection + // return; + // } rPtAnalysis.fill(HIST("hNRecEvents"), 0.5, collision.centFT0M()); // Number of recorded events for (const auto& v0 : V0s) { // Checking that the V0 is a true K0s/Lambdas/Antilambdas and then filling the parameter histograms and the invariant mass plots for different cuts (which are taken from namespace) @@ -1049,9 +1055,9 @@ struct V0PtInvMassPlots { antilambdaptedgevalues[i] = std::stod(pthistos::antilambdaPtBins[i]); } - if (!acceptEvent(collision)) { // Event Selection - return; - } + // if (!acceptEvent(collision)) { // Event Selection + // return; + // } rPtAnalysis.fill(HIST("hNRecEvents"), 0.5, collision.centFT0M()); // Number of recorded events for (const auto& v0 : V0s) { // Checking that the V0 is a true K0s/Lambdas/Antilambdas and then filling the parameter histograms and the invariant mass plots for different cuts (which are taken from namespace) @@ -1092,10 +1098,9 @@ struct V0PtInvMassPlots { } } } - // This is the Process for the MC reconstructed Data void recMCProcessDerived(soa::Join::iterator const& collision, - // const& /*mcCollisions*/, - soa::Join const& V0s, + // To add McCentFT0Ms + soa::Join const& V0s, DaughterTracksDerived const&) { // tokenise strings into individual values @@ -1123,9 +1128,9 @@ struct V0PtInvMassPlots { for (int i = 0; i < nAntilambdaHistograms + 1; i++) { antilambdaptedgevalues[i] = std::stod(pthistos::antilambdaPtBins[i]); } - if (!acceptEvent(collision)) { // Event Selection - return; - } + // if (!acceptEvent(collision)) { // Event Selection + // return; + // } rPtAnalysis.fill(HIST("hNRecEvents"), 0.5, collision.centFT0M()); // Event Split Numenator for (const auto& v0 : V0s) { // Checking that the V0 is a true K0s/Lambdas/Antilambdas and then filling the parameter histograms and the invariant mass plots for different cuts (which are taken from namespace) @@ -1139,18 +1144,18 @@ struct V0PtInvMassPlots { if (acceptK0sh(v0, posDaughterTrack, negDaughterTrack, collision)) { // K0sh Selection // K0sh Signal Split Numerator Start for (int i = 0; i < nKaonHistograms; i++) { - if (kaonptedgevalues[i] <= v0.pt() && v0.pt() < kaonptedgevalues[i + 1]) { // finding v0s with pt within the range of our bin edges for K0sh Splitting Numerator - pthistos::kaonSplit[i]->Fill(v0.mK0Short(), collision.centFT0M()); // filling the k0s namespace histograms for K0sh Splitting Numerator + if (kaonptedgevalues[i] <= v0.ptMC() && v0.ptMC() < kaonptedgevalues[i + 1]) { // finding v0s with pt within the range of our bin edges for K0sh Splitting Numerator + pthistos::kaonSplit[i]->Fill(v0.mK0Short(), collision.centFT0M()); // filling the k0s namespace histograms for K0sh Splitting Numerator } } - // K0sh Signla Split Numerator End + // K0sh SignaL Split Numerator End if (v0.has_v0MCCore()) { auto v0mcParticle = v0.v0MCCore_as(); if (dotruthk0sh && (v0mcParticle.pdgCode() == kK0Short)) { // kzero matched if (v0mcParticle.isPhysicalPrimary()) { for (int i = 0; i < nKaonHistograms; i++) { - if (kaonptedgevalues[i] <= v0.pt() && v0.pt() < kaonptedgevalues[i + 1]) { // finding v0s with pt within the range of our bin edges - pthistos::kaonPt[i]->Fill(v0.mK0Short(), collision.centFT0M()); // filling the k0s namespace histograms + if (kaonptedgevalues[i] <= v0.ptMC() && v0.ptMC() < kaonptedgevalues[i + 1]) { // finding v0s with pt within the range of our bin edges + pthistos::kaonPt[i]->Fill(v0.mK0Short(), collision.centFT0M()); // filling the k0s namespace histograms } } } @@ -1170,7 +1175,7 @@ struct V0PtInvMassPlots { if (acceptLambda(v0, posDaughterTrack, negDaughterTrack, collision)) { // Lambda Selections // Lambda Signal Split Numerator Start for (int i = 0; i < nLambdaHistograms; i++) { - if (lambdaptedgevalues[i] <= v0.pt() && v0.pt() < lambdaptedgevalues[i + 1]) { + if (lambdaptedgevalues[i] <= v0.ptMC() && v0.ptMC() < lambdaptedgevalues[i + 1]) { pthistos::lambdaSplit[i]->Fill(v0.mLambda(), collision.centFT0M()); } } @@ -1180,7 +1185,7 @@ struct V0PtInvMassPlots { if (dotruthLambda && (v0mcParticle.pdgCode() == kLambda0)) { // lambda matched if (v0mcParticle.isPhysicalPrimary()) { for (int i = 0; i < nLambdaHistograms; i++) { - if (lambdaptedgevalues[i] <= v0.pt() && v0.pt() < lambdaptedgevalues[i + 1]) { + if (lambdaptedgevalues[i] <= v0.ptMC() && v0.ptMC() < lambdaptedgevalues[i + 1]) { pthistos::lambdaPt[i]->Fill(v0.mLambda(), collision.centFT0M()); } } @@ -1207,7 +1212,7 @@ struct V0PtInvMassPlots { if (acceptAntilambda(v0, posDaughterTrack, negDaughterTrack, collision)) { // Antilambda Selections // Antilambda Signal Split Numerator End for (int i = 0; i < nAntilambdaHistograms; i++) { - if (antilambdaptedgevalues[i] <= v0.pt() && v0.pt() < antilambdaptedgevalues[i + 1]) { + if (antilambdaptedgevalues[i] <= v0.ptMC() && v0.ptMC() < antilambdaptedgevalues[i + 1]) { pthistos::antilambdaSplit[i]->Fill(v0.mAntiLambda(), collision.centFT0M()); } } @@ -1217,7 +1222,7 @@ struct V0PtInvMassPlots { if (dotruthAntilambda && (v0mcParticle.pdgCode() == kLambda0Bar)) { // antilambda matched if (v0mcParticle.isPhysicalPrimary()) { for (int i = 0; i < nAntilambdaHistograms; i++) { - if (antilambdaptedgevalues[i] <= v0.pt() && v0.pt() < antilambdaptedgevalues[i + 1]) { + if (antilambdaptedgevalues[i] <= v0.ptMC() && v0.ptMC() < antilambdaptedgevalues[i + 1]) { pthistos::antilambdaPt[i]->Fill(v0.mAntiLambda(), collision.centFT0M()); } } From 2ebbfae883ceb307842f002f43bef390a3191af1 Mon Sep 17 00:00:00 2001 From: skundu692 <86804743+skundu692@users.noreply.github.com> Date: Tue, 24 Feb 2026 21:19:03 +0100 Subject: [PATCH 067/347] [PWGLF] Add additional THnsparse in output (#15146) --- .../Strangeness/lambdaspincorrderived.cxx | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx b/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx index 09528b50873..c2d50cfbc87 100644 --- a/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx +++ b/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx @@ -139,6 +139,11 @@ struct lambdaspincorrderived { ConfigurableAxis configThnAxisRapidity{"configThnAxisRapidity", {VARIABLE_WIDTH, 0.0, 1.0}, "Rapidity"}; ConfigurableAxis configThnAxisPairMass{"configThnAxisPairMass", {VARIABLE_WIDTH, 2.0, 3.0}, "PairMass"}; ConfigurableAxis configThnAxisPhi{"configThnAxisPhi", {VARIABLE_WIDTH, 0.0, 2.0 * TMath::Pi()}, "Phi"}; + + ConfigurableAxis configThnAxisDeltaPhi{"configThnAxisDeltaPhi", {VARIABLE_WIDTH, 0.0, TMath::Pi() / 6, 2.0 * TMath::Pi() / 6, 3.0 * TMath::Pi() / 6, 4.0 * TMath::Pi() / 6, 5.0 * TMath::Pi() / 6, TMath::Pi()}, "Delta Phi"}; + ConfigurableAxis configThnAxisDeltaR{"configThnAxisDeltaR", {VARIABLE_WIDTH, 0.0, 0.5, 1.2, 2.0, 3.1, 4.0}, "Delta R"}; + ConfigurableAxis configThnAxisDeltaRap{"configThnAxisDeltaRap", {VARIABLE_WIDTH, 0.0, 0.2, 0.5, 1.0, 1.6}, "Delta Rap"}; + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; void init(o2::framework::InitContext&) @@ -181,6 +186,17 @@ struct lambdaspincorrderived { histos.add("hSparseLambdaAntiLambdaMixed", "hSparseLambdaAntiLambdaMixed", HistType::kTHnSparseF, {configThnAxisInvMass, configThnAxisInvMass, configThnAxisPol, configThnAxisR}, true); histos.add("hSparseAntiLambdaLambdaMixed", "hSparseAntiLambdaLambdaMixed", HistType::kTHnSparseF, {configThnAxisInvMass, configThnAxisInvMass, configThnAxisPol, configThnAxisR}, true); histos.add("hSparseAntiLambdaAntiLambdaMixed", "hSparseAntiLambdaAntiLambdaMixed", HistType::kTHnSparseF, {configThnAxisInvMass, configThnAxisInvMass, configThnAxisPol, configThnAxisR}, true); + + histos.add("hSparseLambdaLambdaAnalysis", "hSparseLambdaLambdaAnalysis", HistType::kTHnSparseF, {configThnAxisInvMass, configThnAxisInvMass, configThnAxisPol, configThnAxisDeltaR, configThnAxisDeltaRap, configThnAxisDeltaPhi}, true); + histos.add("hSparseLambdaAntiLambdaAnalysis", "hSparseLambdaAntiLambdaAnalysis", HistType::kTHnSparseF, {configThnAxisInvMass, configThnAxisInvMass, configThnAxisPol, configThnAxisDeltaR, configThnAxisDeltaRap, configThnAxisDeltaPhi}, true); + histos.add("hSparseAntiLambdaLambdaAnalysis", "hSparseAntiLambdLambdaAnalysis", HistType::kTHnSparseF, {configThnAxisInvMass, configThnAxisInvMass, configThnAxisPol, configThnAxisDeltaR, configThnAxisDeltaRap, configThnAxisDeltaPhi}, true); + histos.add("hSparseAntiLambdaAntiLambdaAnalysis", "hSparseAntiLambdaAntiLambdaAnalysis", HistType::kTHnSparseF, {configThnAxisInvMass, configThnAxisInvMass, configThnAxisPol, configThnAxisDeltaR, configThnAxisDeltaRap, configThnAxisDeltaPhi}, true); + + histos.add("hSparseLambdaLambdaMixedAnalysis", "hSparseLambdaLambdaMixedAnalysis", HistType::kTHnSparseF, {configThnAxisInvMass, configThnAxisInvMass, configThnAxisPol, configThnAxisDeltaR, configThnAxisDeltaRap, configThnAxisDeltaPhi}, true); + histos.add("hSparseLambdaAntiLambdaMixedAnalysis", "hSparseLambdaAntiLambdaMixedAnalysis", HistType::kTHnSparseF, {configThnAxisInvMass, configThnAxisInvMass, configThnAxisPol, configThnAxisDeltaR, configThnAxisDeltaRap, configThnAxisDeltaPhi}, true); + histos.add("hSparseAntiLambdaLambdaMixedAnalysis", "hSparseAntiLambdaLambdaMixedAnalysis", HistType::kTHnSparseF, {configThnAxisInvMass, configThnAxisInvMass, configThnAxisPol, configThnAxisDeltaR, configThnAxisDeltaRap, configThnAxisDeltaPhi}, true); + histos.add("hSparseAntiLambdaAntiLambdaMixedAnalysis", "hSparseAntiLambdaAntiLambdaMixedAnalysis", HistType::kTHnSparseF, {configThnAxisInvMass, configThnAxisInvMass, configThnAxisPol, configThnAxisDeltaR, configThnAxisDeltaRap, configThnAxisDeltaPhi}, true); + if (useAdditionalHisto) { histos.add("hSparseRapLambdaLambda", "hSparseRapLambdaLambda", HistType::kTHnSparseF, {configThnAxisInvMass, configThnAxisInvMass, configThnAxisPol, configThnAxisRapidity}, true); histos.add("hSparseRapLambdaAntiLambda", "hSparseRapLambdaAntiLambda", HistType::kTHnSparseF, {configThnAxisInvMass, configThnAxisInvMass, configThnAxisPol, configThnAxisRapidity}, true); @@ -381,7 +397,6 @@ struct lambdaspincorrderived { // double deta_pair = std::abs(deta1 - deta2); double dphi_pair = RecoDecay::constrainAngle(dphi1 - dphi2, -TMath::Pi(), harmonicDphi); - // double deltaR = TMath::Sqrt(deta_pair * deta_pair + dphi_pair * dphi_pair); double deltaRap = std::abs(particle1.Rapidity() - particle2.Rapidity()); double deltaR = TMath::Sqrt(deltaRap * deltaRap + dphi_pair * dphi_pair); @@ -412,6 +427,7 @@ struct lambdaspincorrderived { histos.fill(HIST("SE_LL"), dphi1, deta1, pt1, mixpairweight); histos.fill(HIST("SE_LL2"), dphi2, deta2, pt2, mixpairweight); histos.fill(HIST("hSparseLambdaLambda"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, mixpairweight); + histos.fill(HIST("hSparseLambdaLambdaAnalysis"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, deltaRap, std::abs(dphi_pair), mixpairweight); if (useAdditionalHisto) { histos.fill(HIST("hSparseRapLambdaLambda"), particle1.M(), particle2.M(), cosThetaDiff, deltaRap, mixpairweight); histos.fill(HIST("hSparsePhiLambdaLambda"), particle1.M(), particle2.M(), cosThetaDiff, dphi_pair, mixpairweight); @@ -421,6 +437,7 @@ struct lambdaspincorrderived { histos.fill(HIST("SE_LAL"), dphi1, deta1, pt1, mixpairweight); histos.fill(HIST("SE_LAL2"), dphi2, deta2, pt2, mixpairweight); histos.fill(HIST("hSparseLambdaAntiLambda"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, mixpairweight); + histos.fill(HIST("hSparseLambdaAntiLambdaAnalysis"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, deltaRap, std::abs(dphi_pair), mixpairweight); if (useAdditionalHisto) { histos.fill(HIST("hSparseRapLambdaAntiLambda"), particle1.M(), particle2.M(), cosThetaDiff, deltaRap, mixpairweight); histos.fill(HIST("hSparsePhiLambdaAntiLambda"), particle1.M(), particle2.M(), cosThetaDiff, dphi_pair, mixpairweight); @@ -428,6 +445,7 @@ struct lambdaspincorrderived { } } else if (tag1 == 1 && tag2 == 0) { histos.fill(HIST("hSparseAntiLambdaLambda"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, mixpairweight); + histos.fill(HIST("hSparseAntiLambdaLambdaAnalysis"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, deltaRap, std::abs(dphi_pair), mixpairweight); histos.fill(HIST("SE_ALL"), dphi1, deta1, pt1, mixpairweight); histos.fill(HIST("SE_ALL2"), dphi2, deta2, pt2, mixpairweight); if (useAdditionalHisto) { @@ -437,6 +455,7 @@ struct lambdaspincorrderived { } } else if (tag1 == 1 && tag2 == 1) { histos.fill(HIST("hSparseAntiLambdaAntiLambda"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, mixpairweight); + histos.fill(HIST("hSparseAntiLambdaAntiLambdaAnalysis"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, deltaRap, std::abs(dphi_pair), mixpairweight); histos.fill(HIST("SE_ALAL"), dphi1, deta1, pt1, mixpairweight); histos.fill(HIST("SE_ALAL2"), dphi2, deta2, pt2, mixpairweight); if (useAdditionalHisto) { @@ -462,6 +481,7 @@ struct lambdaspincorrderived { histos.fill(HIST("ME_LL"), dphi1, deta1, pt1, mixpairweight); histos.fill(HIST("ME_LL2"), dphi2, deta2, pt2, mixpairweight); histos.fill(HIST("hSparseLambdaLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, weight); + histos.fill(HIST("hSparseLambdaLambdaMixedAnalysis"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, deltaRap, std::abs(dphi_pair), weight); if (useAdditionalHisto) { histos.fill(HIST("hSparseRapLambdaLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, deltaRap, weight); histos.fill(HIST("hSparsePhiLambdaLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, dphi_pair, weight); @@ -471,6 +491,7 @@ struct lambdaspincorrderived { histos.fill(HIST("ME_LAL"), dphi1, deta1, pt1, mixpairweight); histos.fill(HIST("ME_LAL2"), dphi2, deta2, pt2, mixpairweight); histos.fill(HIST("hSparseLambdaAntiLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, weight); + histos.fill(HIST("hSparseLambdaAntiLambdaMixedAnalysis"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, deltaRap, std::abs(dphi_pair), weight); if (useAdditionalHisto) { histos.fill(HIST("hSparseRapLambdaAntiLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, deltaRap, weight); histos.fill(HIST("hSparsePhiLambdaAntiLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, dphi_pair, weight); @@ -480,6 +501,7 @@ struct lambdaspincorrderived { histos.fill(HIST("ME_ALL"), dphi1, deta1, pt1, mixpairweight); histos.fill(HIST("ME_ALL2"), dphi2, deta2, pt2, mixpairweight); histos.fill(HIST("hSparseAntiLambdaLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, weight); + histos.fill(HIST("hSparseAntiLambdaLambdaMixedAnalysis"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, deltaRap, std::abs(dphi_pair), weight); if (useAdditionalHisto) { histos.fill(HIST("hSparseRapAntiLambdaLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, deltaRap, weight); histos.fill(HIST("hSparsePhiAntiLambdaLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, dphi_pair, weight); @@ -489,6 +511,7 @@ struct lambdaspincorrderived { histos.fill(HIST("ME_ALAL"), dphi1, deta1, pt1, mixpairweight); histos.fill(HIST("ME_ALAL2"), dphi2, deta2, pt2, mixpairweight); histos.fill(HIST("hSparseAntiLambdaAntiLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, weight); + histos.fill(HIST("hSparseAntiLambdaAntiLambdaMixedAnalysis"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, deltaRap, std::abs(dphi_pair), weight); if (useAdditionalHisto) { histos.fill(HIST("hSparseRapAntiLambdaAntiLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, deltaRap, weight); histos.fill(HIST("hSparsePhiAntiLambdaAntiLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, dphi_pair, weight); From 3e7bdd70559c1db86b7229e0062429ed366b4c9a Mon Sep 17 00:00:00 2001 From: Junlee Kim Date: Wed, 25 Feb 2026 05:38:15 +0800 Subject: [PATCH 068/347] [PWGCF] adding MC processes (#15126) Co-authored-by: ALICE Action Bot --- PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx | 118 ++++++++++++++++++++++++ 1 file changed, 118 insertions(+) diff --git a/PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx b/PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx index 13c2e3e72fc..c7e2386d409 100644 --- a/PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx +++ b/PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx @@ -18,6 +18,7 @@ #include "Common/Core/EventPlaneHelper.h" #include "Common/Core/TrackSelection.h" +#include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Qvectors.h" #include "Common/DataModel/TrackSelectionTables.h" @@ -29,6 +30,8 @@ #include "Framework/RunningWorkflowInfo.h" #include "Framework/runDataProcessing.h" +#include + #include #include @@ -39,6 +42,8 @@ using namespace std; using MyCollisions = soa::Join; using MyTracks = soa::Join; +using MyCollisionsMC = soa::Join; +using MyTracksMC = soa::Join; struct jEPFlowAnalysis { @@ -96,6 +101,12 @@ struct jEPFlowAnalysis { ConfigurableAxis cfgAxisCos{"cfgAxisCos", {102, -1.02, 1.02}, ""}; ConfigurableAxis cfgAxisQvec{"cfgAxisQvec", {200, -5.0, 5.0}, ""}; + ConfigurableAxis cfgAxisCentMC{"cfgAxisCentMC", {5, 0, 100}, ""}; + ConfigurableAxis cfgAxisVtxZMC{"cfgAxisVtxZMC", {20, -10, 10}, ""}; + ConfigurableAxis cfgAxisEtaMC{"cfgAxisEtaMC", {20, -1, 1}, ""}; + ConfigurableAxis cfgAxisPhiMC{"cfgAxisPhiMC", {36, 0, constants::math::PI * 2.0}, ""}; + ConfigurableAxis cfgAxisPtMC{"cfgAxisPtMC", {VARIABLE_WIDTH, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.5, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0, 10.0, 12.0, 15.0, 30.0, 50.0, 70.0, 100.0}, ""}; + Filter trackFilter = (aod::track::pt > cfgTrackCuts.cfgPtMin) && (nabs(aod::track::eta) < cfgTrackCuts.cfgEtaMax); int detId; @@ -194,6 +205,12 @@ struct jEPFlowAnalysis { AxisSpec axisCos{cfgAxisCos, "cos"}; AxisSpec axisQvec{cfgAxisQvec, "Qvec"}; + AxisSpec axisCentMC{cfgAxisCentMC, "cent"}; + AxisSpec axisVtxZMC{cfgAxisVtxZMC, "vtxz"}; + AxisSpec axisEtaMC{cfgAxisEtaMC, "eta"}; + AxisSpec axisPhiMC{cfgAxisPhiMC, "phi"}; + AxisSpec axisPtMC{cfgAxisPtMC, "pt"}; + epFlowHistograms.add("EpDet", "", {HistType::kTH3F, {axisMod, axisCent, axisEvtPl}}); epFlowHistograms.add("EpRefA", "", {HistType::kTH3F, {axisMod, axisCent, axisEvtPl}}); epFlowHistograms.add("EpRefB", "", {HistType::kTH3F, {axisMod, axisCent, axisEvtPl}}); @@ -217,6 +234,10 @@ struct jEPFlowAnalysis { epFlowHistograms.add("hCentrality", "", {HistType::kTH1F, {axisCent}}); epFlowHistograms.add("hVertex", "", {HistType::kTH1F, {axisVertex}}); + + epFlowHistograms.add("MC/hPartGen", "", {kTHnSparseF, {cfgAxisCentMC, cfgAxisVtxZMC, cfgAxisEtaMC, cfgAxisPhiMC, cfgAxisPtMC}}); + epFlowHistograms.add("MC/hPartRecPr", "", {kTHnSparseF, {cfgAxisCentMC, cfgAxisVtxZMC, cfgAxisEtaMC, cfgAxisPhiMC, cfgAxisPtMC}}); + epFlowHistograms.add("MC/hPartRec", "", {kTHnSparseF, {cfgAxisCentMC, cfgAxisVtxZMC, cfgAxisEtaMC, cfgAxisPhiMC, cfgAxisPtMC}}); } void processDefault(MyCollisions::iterator const& coll, soa::Filtered const& tracks, aod::BCsWithTimestamps const&) @@ -370,6 +391,103 @@ struct jEPFlowAnalysis { } } PROCESS_SWITCH(jEPFlowAnalysis, processDefault, "default process", true); + + void processMCRec(MyCollisionsMC::iterator const& coll, MyTracksMC const& tracks, aod::McParticles const& /*mcParticles*/, aod::McCollisions const& /*mcCollisions*/) + { + if (!coll.has_mcCollision()) { + return; + } + + if (cfgAddEvtSel) { + if (std::abs(coll.posZ()) > cfgVertexZ) + return; + switch (cfgEvtSel) { + case 0: // Sel8 + if (!coll.sel8()) + return; + break; + case 1: // PbPb standard + if (!coll.sel8() || !coll.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) || !coll.selection_bit(aod::evsel::kNoSameBunchPileup)) + return; + break; + case 2: // PbPb with pileup + if (!coll.sel8() || !coll.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard) || + !coll.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) || !coll.selection_bit(aod::evsel::kNoSameBunchPileup)) + return; + break; + case 3: // Small systems (OO, NeNe, pp) + if (!coll.sel8() || !coll.selection_bit(aod::evsel::kNoSameBunchPileup)) + return; + break; + default: + LOGF(warning, "Event selection flag was not found, continuing without basic event selections!\n"); + } + // Check occupancy + if (coll.trackOccupancyInTimeRange() > cfgMaxOccupancy || coll.trackOccupancyInTimeRange() < cfgMinOccupancy) + return; + } + + float cent = coll.centFT0C(); + + if (cfgEffCor) { + auto bc = coll.bc_as(); + currentRunNumber = bc.runNumber(); + if (currentRunNumber != lastRunNumber) { + effMap = ccdb->getForTimeStamp>(cfgEffCorDir, bc.timestamp()); + lastRunNumber = currentRunNumber; + } + } + + for (auto trk : tracks) { + if (!trk.has_mcParticle()) { + continue; + } + + if (trackSel(trk)) { + continue; + } + + epFlowHistograms.fill(HIST("MC/hPartRec"), cent, coll.posZ(), trk.eta(), trk.phi(), trk.pt()); + auto mctrk = trk.mcParticle(); + if (mctrk.isPhysicalPrimary()) { + epFlowHistograms.fill(HIST("MChPartRecPr"), cent, coll.posZ(), trk.eta(), trk.phi(), trk.pt()); + } + } + } + PROCESS_SWITCH(jEPFlowAnalysis, processMCRec, "process for MC", false); + + void processMCGen(MyCollisionsMC::iterator const& coll, aod::McParticles const& mcParticles, aod::McCollisions const&) + { + if (!coll.has_mcCollision()) + return; + const auto mcColl = coll.mcCollision(); + + if (cfgAddEvtSel) { + if (std::abs(mcColl.posZ()) > cfgVertexZ) { + return; + } + } + + float cent = coll.centFT0C(); + + for (auto& mcParticle : mcParticles) { + if (std::abs(mcParticle.eta()) > cfgTrackCuts.cfgEtaMax) + continue; + + auto* p = TDatabasePDG::Instance()->GetParticle(mcParticle.pdgCode()); + if (p) { + if (std::abs(p->Charge()) < 1e-1) { + continue; + } + } + + if (!mcParticle.isPhysicalPrimary()) + continue; + + epFlowHistograms.fill(HIST("MC/hPartGen"), cent, mcColl.posZ(), mcParticle.eta(), mcParticle.phi(), mcParticle.pt()); + } + } + PROCESS_SWITCH(jEPFlowAnalysis, processMCGen, "process for MC", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) From c215d082455919cf9b11d912035c77d838bb9013 Mon Sep 17 00:00:00 2001 From: JStaa <39123272+JStaa@users.noreply.github.com> Date: Tue, 24 Feb 2026 22:39:59 +0100 Subject: [PATCH 069/347] [PWGCF] Added a number of track selection configurable parameters (#15135) Co-authored-by: ALICE Action Bot --- .../Tasks/threeParticleCorrelations.cxx | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/PWGCF/MultiparticleCorrelations/Tasks/threeParticleCorrelations.cxx b/PWGCF/MultiparticleCorrelations/Tasks/threeParticleCorrelations.cxx index c6af9ac57b1..f74b90da6c3 100644 --- a/PWGCF/MultiparticleCorrelations/Tasks/threeParticleCorrelations.cxx +++ b/PWGCF/MultiparticleCorrelations/Tasks/threeParticleCorrelations.cxx @@ -79,6 +79,9 @@ struct ThreeParticleCorrelations { float pionPtMid1 = 1.6, pionPtMid2 = 2.0, kaonPtMid1 = 1.5, kaonPtMid2 = 2.0, protonPtMid = 2.3; struct : ConfigurableGroup { std::string prefix = "TrackSelection"; + Configurable chi2PerClusterTPC{"chi2PerClusterTPC", 4.0, "Maximum TPC goodness-of-fit Chi2 per cluster"}; + Configurable chi2PerClusterITS{"chi2PerClusterITS", 36.0, "Maximum ITS goodness-of-fit Chi2 per cluster"}; + Configurable dcaZ{"dcaZ", 2.0, "Maximum longitudinal DCA (cm)"}; Configurable nSigmaTPCvar{"nSigmaTPCvar", 0.0, "Variation in the TPC nSigma"}; Configurable nSigmaTOFvar{"nSigmaTOFvar", 0.0, "Variation in the TOF nSigma"}; } trackSelGroup; @@ -117,7 +120,7 @@ struct ThreeParticleCorrelations { // Table aliases - Data using MyFilteredCollisions = soa::Filtered>; using MyFilteredCollision = MyFilteredCollisions::iterator; - using MyFilteredTracks = soa::Filtered>; @@ -130,7 +133,7 @@ struct ThreeParticleCorrelations { using MCRecCollisions = soa::Join; using MyFilteredMCRecCollisions = soa::Filtered; using MyMCV0s = soa::Join; - using MyFilteredMCTracks = soa::Filtered>; @@ -1108,6 +1111,13 @@ struct ThreeParticleCorrelations { bool trackFilters(const TrackCand& track) // Track filter { + if (track.tpcChi2NCl() > trackSelGroup.chi2PerClusterTPC || track.itsChi2NCl() > trackSelGroup.chi2PerClusterITS) { + return false; + } + if (track.dcaZ() > trackSelGroup.dcaZ) { + return false; + } + if (!track.hasTOF()) { return false; } From 300e30420c64c6f26dea9fc1125d3e8a813c82fc Mon Sep 17 00:00:00 2001 From: Preet-Bhanjan Date: Tue, 24 Feb 2026 22:43:05 +0100 Subject: [PATCH 070/347] [PWGCF] Addition of extra dEdx information (#15133) Co-authored-by: Preet Pati Co-authored-by: ALICE Action Bot --- .../Tasks/pidDiHadron.cxx | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/pidDiHadron.cxx b/PWGCF/TwoParticleCorrelations/Tasks/pidDiHadron.cxx index 66890f79424..58e5162ba1e 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/pidDiHadron.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/pidDiHadron.cxx @@ -118,7 +118,7 @@ struct PidDiHadron { O2_DEFINE_CONFIGURABLE(cfgUseOnlyTPC, bool, true, "Use only TPC PID for daughter selection") O2_DEFINE_CONFIGURABLE(cfgPIDParticle, int, 0, "1 = pion, 2 = kaon, 3 = proton, 4 = kshort, 5 = lambda, 6 = phi, 0 for no PID") O2_DEFINE_CONFIGURABLE(cfgGetNsigmaQA, bool, true, "Get QA histograms for selection of pions, kaons, and protons") - O2_DEFINE_CONFIGURABLE(cfgGetdEdx, bool, true, "Get QA histograms for selection of pions, kaons, and protons") + O2_DEFINE_CONFIGURABLE(cfgGetdEdx, bool, true, "Get dEdx histograms for pions, kaons, and protons") O2_DEFINE_CONFIGURABLE(cfgUseAntiLambda, bool, true, "Use AntiLambda candidates for analysis") O2_DEFINE_CONFIGURABLE(cfgPIDUseRejection, bool, true, "Turn off and on the exclusion criteria for PID determination") @@ -540,6 +540,12 @@ struct PidDiHadron { histos.add("ExpTpcdEdx_ptwise_pi", "", {HistType::kTHnSparseD, {{axisPt, axisTpcSignal, axisNsigmaTOF}}}); histos.add("ExpTpcdEdx_ptwise_ka", "", {HistType::kTHnSparseD, {{axisPt, axisTpcSignal, axisNsigmaTOF}}}); histos.add("ExpTpcdEdx_ptwise_pr", "", {HistType::kTHnSparseD, {{axisPt, axisTpcSignal, axisNsigmaTOF}}}); + + histos.add("TpcdEdx_ptwise_pi_physprim", "", {HistType::kTHnSparseD, {{axisPt, axisTpcSignal, axisNsigmaTOF}}}); + histos.add("TpcdEdx_ptwise_ka_physprim", "", {HistType::kTHnSparseD, {{axisPt, axisTpcSignal, axisNsigmaTOF}}}); + histos.add("TpcdEdx_ptwise_pr_physprim", "", {HistType::kTHnSparseD, {{axisPt, axisTpcSignal, axisNsigmaTOF}}}); + + histos.add("TpcdEdx_ptwise_all_physprim", "", {HistType::kTHnSparseD, {{axisPt, axisTpcSignal, axisNsigmaTOF}}}); } histos.add("eventcount", "bin", {HistType::kTH1F, {{4, 0, 4, "bin"}}}); // histogram to see how many events are in the same and mixed event @@ -1546,10 +1552,21 @@ struct PidDiHadron { if (pidIndex == kProtons) histos.fill(HIST("hNsigmaProtonSelected"), track.pt()); + if (track.mcParticle().isPhysicalPrimary()) { + if (cfgPIDParticle == kPions) + histos.fill(HIST("TpcdEdx_ptwise_all_physprim"), track.pt(), track.tpcSignal(), track.tofNSigmaPi()); + if (cfgPIDParticle == kKaons) + histos.fill(HIST("TpcdEdx_ptwise_all_physprim"), track.pt(), track.tpcSignal(), track.tofNSigmaKa()); + if (cfgPIDParticle == kProtons) + histos.fill(HIST("TpcdEdx_ptwise_all_physprim"), track.pt(), track.tpcSignal(), track.tofNSigmaPr()); + } + // Check the PDG code for the particles (MC truth) and match with analysed Nsigma PID if (std::abs(track.mcParticle().pdgCode()) == PDG_t::kPiPlus) { histos.fill(HIST("hNsigmaPionTrue"), track.pt()); histos.fill(HIST("TpcdEdx_ptwise_pi"), track.pt(), track.tpcSignal(), track.tofNSigmaPi()); + if (track.mcParticle().isPhysicalPrimary()) + histos.fill(HIST("TpcdEdx_ptwise_pi_physprim"), track.pt(), track.tpcSignal(), track.tofNSigmaPi()); double tpcExpSignalPi = track.tpcSignal() - (track.tpcNSigmaPi() * track.tpcExpSigmaPi()); histos.fill(HIST("ExpTpcdEdx_ptwise_pi"), track.pt(), tpcExpSignalPi, track.tofNSigmaPi()); @@ -1562,6 +1579,8 @@ struct PidDiHadron { if (std::abs(track.mcParticle().pdgCode()) == PDG_t::kKPlus) { histos.fill(HIST("hNsigmaKaonTrue"), track.pt()); histos.fill(HIST("TpcdEdx_ptwise_ka"), track.pt(), track.tpcSignal(), track.tofNSigmaKa()); + if (track.mcParticle().isPhysicalPrimary()) + histos.fill(HIST("TpcdEdx_ptwise_ka_physprim"), track.pt(), track.tpcSignal(), track.tofNSigmaKa()); double tpcExpSignalKa = track.tpcSignal() - (track.tpcNSigmaKa() * track.tpcExpSigmaKa()); histos.fill(HIST("ExpTpcdEdx_ptwise_ka"), track.pt(), tpcExpSignalKa, track.tofNSigmaKa()); @@ -1574,6 +1593,8 @@ struct PidDiHadron { if (std::abs(track.mcParticle().pdgCode()) == PDG_t::kProton) { histos.fill(HIST("hNsigmaProtonTrue"), track.pt()); histos.fill(HIST("TpcdEdx_ptwise_pr"), track.pt(), track.tpcSignal(), track.tofNSigmaPr()); + if (track.mcParticle().isPhysicalPrimary()) + histos.fill(HIST("TpcdEdx_ptwise_pr_physprim"), track.pt(), track.tpcSignal(), track.tofNSigmaPr()); double tpcExpSignalPr = track.tpcSignal() - (track.tpcNSigmaPr() * track.tpcExpSigmaPr()); histos.fill(HIST("ExpTpcdEdx_ptwise_pr"), track.pt(), tpcExpSignalPr, track.tofNSigmaPr()); From 0bac9d6bc953e02eb1028bd521897d1b0241ccc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Eduardo=20Mu=C3=B1oz=20M=C3=A9ndez?= <56033627+jmunozme@users.noreply.github.com> Date: Tue, 24 Feb 2026 16:23:08 -0600 Subject: [PATCH 071/347] [PWGLF,PWGMM] Update eff parametrization (#15082) --- PWGMM/UE/Tasks/uecharged.cxx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/PWGMM/UE/Tasks/uecharged.cxx b/PWGMM/UE/Tasks/uecharged.cxx index 69b4e46f713..56bd369a290 100644 --- a/PWGMM/UE/Tasks/uecharged.cxx +++ b/PWGMM/UE/Tasks/uecharged.cxx @@ -170,12 +170,12 @@ struct ueCharged { AxisSpec ptAxis = {ptBinning, "#it{p}_{T}^{assoc} (GeV/#it{c})"}; fEff.setObject(new TF1("fpara", - "(x<0.3)*((0.315318)+x*(2.38596)+x*x*(-4.388)) +" - "(x>=0.3&&x<1.8)*((0.604051)+(0.154763)*x+(-0.103004)*" - "x*x+(0.0266487)*x*x*x) +" - "(x>=1.8&&x<14.)*((0.700444)+(-0.00115506)*x+(0." - "000667608)*x*x+(-3.82915e-05)*x*x*x) +" - "(x>=14)*((0.731778)+(-0.000994634)*x)", + "(x<0.3)*((0.402353)+x*(1.90824)+x*x*(-3.37295)) +" + "(x>=0.3&&x<1.8)*((0.603846)+(0.30189)*x+(-0.240649)*" + "x*x+(0.0635382)*x*x*x) +" + "(x>=1.8&&x<14.)*((0.75982)+(-0.0241023)*x+" + "(0.00560107)*x*x+(-0.00048451)*x*x*x+" + "(1.43868e-05)*x*x*x*x)+(x>=14)*((0.755339)+(-0.000986326)*x)", 0., 1e5)); if (doprocessMC || doprocessMCTrue) { From 6bb880a32345d79c50aafe60cc541ecceaf6f28a Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Wed, 25 Feb 2026 00:17:09 +0100 Subject: [PATCH 072/347] [PWGEM/Dilepton] update muon analyses (#15153) --- PWGEM/Dilepton/Core/DielectronCut.h | 48 ++-- PWGEM/Dilepton/Core/Dilepton.h | 10 +- PWGEM/Dilepton/Core/DileptonMC.h | 10 +- .../TableProducer/createEMEventDilepton.cxx | 10 - PWGEM/Dilepton/Tasks/createResolutionMap.cxx | 213 ++++++++++++------ PWGEM/Dilepton/Tasks/matchingMFT.cxx | 147 ++++-------- PWGEM/Dilepton/Tasks/prefilterDielectron.cxx | 36 +-- 7 files changed, 234 insertions(+), 240 deletions(-) diff --git a/PWGEM/Dilepton/Core/DielectronCut.h b/PWGEM/Dilepton/Core/DielectronCut.h index 64bdd069f18..5c629c3f45d 100644 --- a/PWGEM/Dilepton/Core/DielectronCut.h +++ b/PWGEM/Dilepton/Core/DielectronCut.h @@ -170,7 +170,7 @@ class DielectronCut : public TNamed template bool IsSelectedTrack(TTrack const& track) const { - if (!track.hasITS()) { + if (!track.hasITS() || !track.hasTPC()) { return false; } @@ -225,34 +225,32 @@ class DielectronCut : public TNamed } } - if (!mIncludeITSsa && (!track.hasITS() || !track.hasTPC())) { // track has to be ITS-TPC matched track + // if (!mIncludeITSsa && (!track.hasITS() || !track.hasTPC())) { // track has to be ITS-TPC matched track + // return false; + // } + + // if ((track.hasITS() && !track.hasTPC() && !track.hasTRD() && !track.hasTOF()) && track.pt() > mMaxPtITSsa) { // ITSsa + // return false; + // } + + // TPC cuts + if (!IsSelectedTrack(track, DielectronCuts::kTPCNCls)) { return false; } - - if ((track.hasITS() && !track.hasTPC() && !track.hasTRD() && !track.hasTOF()) && track.pt() > mMaxPtITSsa) { // ITSsa + if (!IsSelectedTrack(track, DielectronCuts::kTPCCrossedRows)) { return false; } - - // TPC cuts - if (track.hasTPC()) { - if (!IsSelectedTrack(track, DielectronCuts::kTPCNCls)) { - return false; - } - if (!IsSelectedTrack(track, DielectronCuts::kTPCCrossedRows)) { - return false; - } - if (!IsSelectedTrack(track, DielectronCuts::kTPCCrossedRowsOverNCls)) { - return false; - } - if (!IsSelectedTrack(track, DielectronCuts::kTPCFracSharedClusters)) { - return false; - } - if (!IsSelectedTrack(track, DielectronCuts::kRelDiffPin)) { - return false; - } - if (!IsSelectedTrack(track, DielectronCuts::kTPCChi2NDF)) { - return false; - } + if (!IsSelectedTrack(track, DielectronCuts::kTPCCrossedRowsOverNCls)) { + return false; + } + if (!IsSelectedTrack(track, DielectronCuts::kTPCFracSharedClusters)) { + return false; + } + if (!IsSelectedTrack(track, DielectronCuts::kRelDiffPin)) { + return false; + } + if (!IsSelectedTrack(track, DielectronCuts::kTPCChi2NDF)) { + return false; } if (mApplyPF && !IsSelectedTrack(track, DielectronCuts::kPrefilter)) { diff --git a/PWGEM/Dilepton/Core/Dilepton.h b/PWGEM/Dilepton/Core/Dilepton.h index f0b0aa28156..9291314d00c 100644 --- a/PWGEM/Dilepton/Core/Dilepton.h +++ b/PWGEM/Dilepton/Core/Dilepton.h @@ -209,8 +209,8 @@ struct Dilepton { Configurable cfg_max_chi2tpc{"cfg_max_chi2tpc", 4.0, "max chi2/NclsTPC"}; Configurable cfg_max_chi2its{"cfg_max_chi2its", 5.0, "max chi2/NclsITS"}; Configurable cfg_max_chi2tof{"cfg_max_chi2tof", 1e+10, "max chi2 TOF"}; - Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 0.2, "max dca XY for single track in cm"}; - Configurable cfg_max_dcaz{"cfg_max_dcaz", 0.2, "max dca Z for single track in cm"}; + Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1.0, "max dca XY for single track in cm"}; + Configurable cfg_max_dcaz{"cfg_max_dcaz", 1.0, "max dca Z for single track in cm"}; Configurable cfg_require_itsib_any{"cfg_require_itsib_any", false, "flag to require ITS ib any hits"}; Configurable cfg_require_itsib_1st{"cfg_require_itsib_1st", true, "flag to require ITS ib 1st hit"}; Configurable cfg_min_its_cluster_size{"cfg_min_its_cluster_size", 0.f, "min ITS cluster size"}; @@ -237,8 +237,6 @@ struct Dilepton { Configurable cfg_min_pin_pirejTPC{"cfg_min_pin_pirejTPC", 0.f, "min. pin for pion rejection in TPC"}; Configurable cfg_max_pin_pirejTPC{"cfg_max_pin_pirejTPC", 1e+10, "max. pin for pion rejection in TPC"}; Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; - Configurable includeITSsa{"includeITSsa", false, "Flag to enable ITSsa tracks"}; - Configurable cfg_max_pt_track_ITSsa{"cfg_max_pt_track_ITSsa", 0.15, "max pt for ITSsa tracks"}; // configuration for PID ML Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; @@ -730,7 +728,6 @@ struct Dilepton { fDielectronCut.RequireITSib1st(dielectroncuts.cfg_require_itsib_1st); fDielectronCut.SetChi2TOF(0, dielectroncuts.cfg_max_chi2tof); fDielectronCut.SetRelDiffPin(dielectroncuts.cfg_min_rel_diff_pin, dielectroncuts.cfg_max_rel_diff_pin); - fDielectronCut.IncludeITSsa(dielectroncuts.includeITSsa, dielectroncuts.cfg_max_pt_track_ITSsa); // for eID fDielectronCut.SetPIDScheme(dielectroncuts.cfg_pid_scheme); @@ -1143,7 +1140,8 @@ struct Dilepton { SliceCache cache; Preslice perCollision_electron = aod::emprimaryelectron::emeventId; - Filter trackFilter_electron = dielectroncuts.cfg_min_pt_track < o2::aod::track::pt && dielectroncuts.cfg_min_eta_track < o2::aod::track::eta && o2::aod::track::eta < dielectroncuts.cfg_max_eta_track && nabs(o2::aod::track::dcaXY) < dielectroncuts.cfg_max_dcaxy && nabs(o2::aod::track::dcaZ) < dielectroncuts.cfg_max_dcaz; + Filter trackFilter_electron = dielectroncuts.cfg_min_pt_track < o2::aod::track::pt && dielectroncuts.cfg_min_eta_track < o2::aod::track::eta && o2::aod::track::eta < dielectroncuts.cfg_max_eta_track && nabs(o2::aod::track::dcaXY) < dielectroncuts.cfg_max_dcaxy && nabs(o2::aod::track::dcaZ) < dielectroncuts.cfg_max_dcaz && o2::aod::track::itsChi2NCl < dielectroncuts.cfg_max_chi2its && o2::aod::track::tpcChi2NCl < dielectroncuts.cfg_max_chi2tpc; + Filter pidFilter_electron = dielectroncuts.cfg_min_TPCNsigmaEl < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < dielectroncuts.cfg_max_TPCNsigmaEl; Filter ttcaFilter_electron = ifnode(dielectroncuts.enableTTCA.node(), o2::aod::emprimaryelectron::isAssociatedToMPC == true || o2::aod::emprimaryelectron::isAssociatedToMPC == false, o2::aod::emprimaryelectron::isAssociatedToMPC == true); Filter prefilter_derived_electron = ifnode(dielectroncuts.cfg_apply_cuts_from_prefilter_derived.node() && dielectroncuts.cfg_prefilter_bits_derived.node() >= static_cast(1), ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kMee))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kMee))) <= static_cast(0), true) && diff --git a/PWGEM/Dilepton/Core/DileptonMC.h b/PWGEM/Dilepton/Core/DileptonMC.h index e323fee60a9..b20a9be3820 100644 --- a/PWGEM/Dilepton/Core/DileptonMC.h +++ b/PWGEM/Dilepton/Core/DileptonMC.h @@ -211,8 +211,8 @@ struct DileptonMC { Configurable cfg_max_chi2tpc{"cfg_max_chi2tpc", 4.0, "max chi2/NclsTPC"}; Configurable cfg_max_chi2its{"cfg_max_chi2its", 5.0, "max chi2/NclsITS"}; Configurable cfg_max_chi2tof{"cfg_max_chi2tof", 1e+10, "max chi2 TOF"}; - Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 0.2, "max dca XY for single track in cm"}; - Configurable cfg_max_dcaz{"cfg_max_dcaz", 0.2, "max dca Z for single track in cm"}; + Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1.0, "max dca XY for single track in cm"}; + Configurable cfg_max_dcaz{"cfg_max_dcaz", 1.0, "max dca Z for single track in cm"}; Configurable cfg_require_itsib_any{"cfg_require_itsib_any", false, "flag to require ITS ib any hits"}; Configurable cfg_require_itsib_1st{"cfg_require_itsib_1st", true, "flag to require ITS ib 1st hit"}; Configurable cfg_min_its_cluster_size{"cfg_min_its_cluster_size", 0.f, "min ITS cluster size"}; @@ -239,8 +239,6 @@ struct DileptonMC { Configurable cfg_min_pin_pirejTPC{"cfg_min_pin_pirejTPC", 0.f, "min. pin for pion rejection in TPC"}; Configurable cfg_max_pin_pirejTPC{"cfg_max_pin_pirejTPC", 1e+10, "max. pin for pion rejection in TPC"}; Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; - Configurable includeITSsa{"includeITSsa", false, "Flag to enable ITSsa tracks"}; - Configurable cfg_max_pt_track_ITSsa{"cfg_max_pt_track_ITSsa", 0.15, "max pt for ITSsa tracks"}; // configuration for PID ML Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; @@ -737,7 +735,6 @@ struct DileptonMC { fDielectronCut.RequireITSib1st(dielectroncuts.cfg_require_itsib_1st); fDielectronCut.SetChi2TOF(0.0, dielectroncuts.cfg_max_chi2tof); fDielectronCut.SetRelDiffPin(dielectroncuts.cfg_min_rel_diff_pin, dielectroncuts.cfg_max_rel_diff_pin); - fDielectronCut.IncludeITSsa(dielectroncuts.includeITSsa, dielectroncuts.cfg_max_pt_track_ITSsa); // for eID fDielectronCut.SetPIDScheme(dielectroncuts.cfg_pid_scheme); @@ -2484,7 +2481,8 @@ struct DileptonMC { SliceCache cache; Preslice perCollision_electron = aod::emprimaryelectron::emeventId; - Filter trackFilter_electron = nabs(o2::aod::track::dcaXY) < dielectroncuts.cfg_max_dcaxy && nabs(o2::aod::track::dcaZ) < dielectroncuts.cfg_max_dcaz; + Filter trackFilter_electron = nabs(o2::aod::track::dcaXY) < dielectroncuts.cfg_max_dcaxy && nabs(o2::aod::track::dcaZ) < dielectroncuts.cfg_max_dcaz && o2::aod::track::itsChi2NCl < dielectroncuts.cfg_max_chi2its && o2::aod::track::tpcChi2NCl < dielectroncuts.cfg_max_chi2tpc; + Filter pidFilter_electron = dielectroncuts.cfg_min_TPCNsigmaEl < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < dielectroncuts.cfg_max_TPCNsigmaEl; Filter ttcaFilter_electron = ifnode(dielectroncuts.enableTTCA.node(), o2::aod::emprimaryelectron::isAssociatedToMPC == true || o2::aod::emprimaryelectron::isAssociatedToMPC == false, o2::aod::emprimaryelectron::isAssociatedToMPC == true); Filter prefilter_derived_electron = ifnode(dielectroncuts.cfg_apply_cuts_from_prefilter_derived.node() && dielectroncuts.cfg_prefilter_bits_derived.node() >= static_cast(1), ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kMee))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kMee))) <= static_cast(0), true) && diff --git a/PWGEM/Dilepton/TableProducer/createEMEventDilepton.cxx b/PWGEM/Dilepton/TableProducer/createEMEventDilepton.cxx index a4ab164a4b2..4c92285441c 100644 --- a/PWGEM/Dilepton/TableProducer/createEMEventDilepton.cxx +++ b/PWGEM/Dilepton/TableProducer/createEMEventDilepton.cxx @@ -14,7 +14,6 @@ /// \author Daiki Sekihata, daiki.sekihata@cern.ch #include "PWGEM/Dilepton/DataModel/dileptonTables.h" -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "Common/CCDB/EventSelectionParams.h" #include "Common/DataModel/Centrality.h" @@ -294,16 +293,13 @@ struct CreateEMEventDilepton { PROCESS_SWITCH(CreateEMEventDilepton, processDummy, "processDummy", true); }; struct AssociateDileptonToEMEvent { - Produces v0kfeventid; Produces prmeleventid; Produces prmmueventid; Produces prmtrackeventid; - Preslice perCollision_pcm = aod::v0photonkf::collisionId; PresliceUnsorted perCollision_el = aod::emprimaryelectron::collisionId; PresliceUnsorted perCollision_mu = aod::emprimarymuon::collisionId; Preslice perCollision_track = aod::emprimarytrack::collisionId; - // Preslice perCollision_track = aod::track::collisionId; void init(o2::framework::InitContext&) {} @@ -323,11 +319,6 @@ struct AssociateDileptonToEMEvent { // This struct is for both data and MC. // Note that reconstructed collisions without mc collisions are already rejected in CreateEMEventDilepton in MC. - // void processPCM(aod::EMEvents const& collisions, aod::V0PhotonsKF const& photons) - // { - // fillEventId(collisions, photons, v0kfeventid, perCollision_pcm); - // } - void processElectron(aod::EMEvents const& collisions, aod::EMPrimaryElectrons const& tracks) { fillEventId(collisions, tracks, prmeleventid, perCollision_el); @@ -345,7 +336,6 @@ struct AssociateDileptonToEMEvent { void processDummy(aod::EMEvents const&) {} - // PROCESS_SWITCH(AssociateDileptonToEMEvent, processPCM, "process indexing for PCM", false); PROCESS_SWITCH(AssociateDileptonToEMEvent, processElectron, "process indexing for electrons", false); PROCESS_SWITCH(AssociateDileptonToEMEvent, processFwdMuon, "process indexing for forward muons", false); PROCESS_SWITCH(AssociateDileptonToEMEvent, processChargedTrack, "process indexing for charged tracks", false); diff --git a/PWGEM/Dilepton/Tasks/createResolutionMap.cxx b/PWGEM/Dilepton/Tasks/createResolutionMap.cxx index 5df5855d171..891667627a1 100644 --- a/PWGEM/Dilepton/Tasks/createResolutionMap.cxx +++ b/PWGEM/Dilepton/Tasks/createResolutionMap.cxx @@ -179,6 +179,7 @@ struct CreateResolutionMap { Configurable requireMFTHitMap{"requireMFTHitMap", false, "flag to require MFT hit map"}; Configurable> requiredMFTDisks{"requiredMFTDisks", std::vector{4}, "hit map on MFT disks [0,1,2,3,4]. logical-OR of each double-sided disk"}; Configurable matchingZ{"matchingZ", -77.5, "z position where matching is performed"}; + Configurable cfgApplyPreselectionInBestMatch{"cfgApplyPreselectionInBestMatch", false, "flag to apply preselection in find best match function"}; } muoncuts; HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -556,7 +557,7 @@ struct CreateResolutionMap { if (muon.chi2MatchMCHMID() < 0.f) { // this should never happen. only for protection. return; } - o2::dataformats::GlobalFwdTrack propmuonAtPV = propagateMuon(muon, muon, collision, propagationPoint::kToVertex, muoncuts.matchingZ, mBzMFT); + o2::dataformats::GlobalFwdTrack propmuonAtPV = propagateMuon(muon, muon, collision, propagationPoint::kToVertex, muoncuts.matchingZ, mBzMFT, 0.0); float pt = propmuonAtPV.getPt(); float eta = propmuonAtPV.getEta(); @@ -592,17 +593,17 @@ struct CreateResolutionMap { if (mcparticle.globalIndex() != mcparticle_MCHMID.globalIndex()) { // this should not happen. this is only for protection. return; } - if (cfg_reject_fake_match_mft_mch && mcparticle.globalIndex() != mcparticle_MFT.globalIndex()) { // evaluate mismatch + if (cfg_reject_fake_match_mft_mch && mcparticle_MCHMID.globalIndex() != mcparticle_MFT.globalIndex()) { // evaluate mismatch return; } - o2::dataformats::GlobalFwdTrack propmuonAtPV_Matched = propagateMuon(mchtrack, mchtrack, collision, propagationPoint::kToVertex, muoncuts.matchingZ, mBzMFT); + o2::dataformats::GlobalFwdTrack propmuonAtPV_Matched = propagateMuon(mchtrack, mchtrack, collision, propagationPoint::kToVertex, muoncuts.matchingZ, mBzMFT, 0.0); ptMatchedMCHMID = propmuonAtPV_Matched.getPt(); etaMatchedMCHMID = propmuonAtPV_Matched.getEta(); phiMatchedMCHMID = propmuonAtPV_Matched.getPhi(); o2::math_utils::bringTo02Pi(phiMatchedMCHMID); - // o2::dataformats::GlobalFwdTrack propmuonAtDCA_Matched = propagateMuon(mchtrack, mchtrack, collision, propagationPoint::kToDCA, muoncuts.matchingZ, mBzMFT); + // o2::dataformats::GlobalFwdTrack propmuonAtDCA_Matched = propagateMuon(mchtrack, mchtrack, collision, propagationPoint::kToDCA, muoncuts.matchingZ, mBzMFT, 0.0); // float dcaX_Matched = propmuonAtDCA_Matched.getX() - collision.posX(); // float dcaY_Matched = propmuonAtDCA_Matched.getY() - collision.posY(); // float dcaXY_Matched = std::sqrt(dcaX_Matched * dcaX_Matched + dcaY_Matched * dcaY_Matched); @@ -626,7 +627,7 @@ struct CreateResolutionMap { if constexpr (withMFTCov) { auto mfttrackcov = mftCovs.rawIteratorAt(map_mfttrackcovs[mfttrack.globalIndex()]); - auto muonAtMP = propagateMuon(mchtrack, mchtrack, collision, propagationPoint::kToMatchingPlane, muoncuts.matchingZ, mBzMFT); // propagated to matching plane + auto muonAtMP = propagateMuon(mchtrack, mchtrack, collision, propagationPoint::kToMatchingPlane, muoncuts.matchingZ, mBzMFT, 0.0); // propagated to matching plane o2::track::TrackParCovFwd mftsaAtMP = getTrackParCovFwd(mfttrack, mfttrackcov); // values at innermost update mftsaAtMP.propagateToZhelix(muoncuts.matchingZ, mBzMFT); // propagated to matching plane etaMatchedMFTatMP = mftsaAtMP.getEta(); @@ -680,12 +681,12 @@ struct CreateResolutionMap { } } else if (muon.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { - o2::dataformats::GlobalFwdTrack propmuonAtRabs = propagateMuon(muon, muon, collision, propagationPoint::kToRabs, muoncuts.matchingZ, mBzMFT); // this is necessary only for MuonStandaloneTrack + o2::dataformats::GlobalFwdTrack propmuonAtRabs = propagateMuon(muon, muon, collision, propagationPoint::kToRabs, muoncuts.matchingZ, mBzMFT, 0.0); // this is necessary only for MuonStandaloneTrack float xAbs = propmuonAtRabs.getX(); float yAbs = propmuonAtRabs.getY(); rAtAbsorberEnd = std::sqrt(xAbs * xAbs + yAbs * yAbs); // Redo propagation only for muon tracks // propagation of MFT tracks alredy done in reconstruction - o2::dataformats::GlobalFwdTrack propmuonAtDCA = propagateMuon(muon, muon, collision, propagationPoint::kToDCA, muoncuts.matchingZ, mBzMFT); + o2::dataformats::GlobalFwdTrack propmuonAtDCA = propagateMuon(muon, muon, collision, propagationPoint::kToDCA, muoncuts.matchingZ, mBzMFT, 0.0); dcaX = propmuonAtDCA.getX() - collision.posX(); dcaY = propmuonAtDCA.getY() - collision.posY(); dcaXY = std::sqrt(dcaX * dcaX + dcaY * dcaY); @@ -874,31 +875,80 @@ struct CreateResolutionMap { } std::vector> vec_min_chi2MatchMCHMFT; // std::pair -> chi2MatchMCHMFT; - template - void findBestMatchPerMCHMID(TMuons const& muons) + template + void findBestMatchPerMCHMID(TCollision const& collision, TFwdTrack const& fwdtrack, TFwdTracks const& fwdtracks, TMFTTracks const&) { - vec_min_chi2MatchMCHMFT.reserve(muons.size()); - for (const auto& muon : muons) { - if (muon.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { - const auto& muons_per_MCHMID = muons.sliceBy(fwdtracksPerMCHTrack, muon.globalIndex()); - // LOGF(info, "stanadalone: muon.globalIndex() = %d, muon.chi2MatchMCHMFT() = %f", muon.globalIndex(), muon.chi2MatchMCHMFT()); - // LOGF(info, "muons_per_MCHMID.size() = %d", muons_per_MCHMID.size()); - - float min_chi2MatchMCHMFT = 1e+10; - std::tuple tupleIds_at_min; - for (const auto& muon_tmp : muons_per_MCHMID) { - if (muon_tmp.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { - // LOGF(info, "muon_tmp.globalIndex() = %d, muon_tmp.matchMCHTrackId() = %d, muon_tmp.matchMFTTrackId() = %d, muon_tmp.chi2MatchMCHMFT() = %f", muon_tmp.globalIndex(), muon_tmp.matchMCHTrackId(), muon_tmp.matchMFTTrackId(), muon_tmp.chi2MatchMCHMFT()); - if (0.f < muon_tmp.chi2MatchMCHMFT() && muon_tmp.chi2MatchMCHMFT() < min_chi2MatchMCHMFT) { - min_chi2MatchMCHMFT = muon_tmp.chi2MatchMCHMFT(); - tupleIds_at_min = std::make_tuple(muon_tmp.globalIndex(), muon_tmp.matchMCHTrackId(), muon_tmp.matchMFTTrackId()); - } + if (fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { + return; + } + if (!fwdtrack.has_mcParticle()) { + return; + } + + o2::dataformats::GlobalFwdTrack propmuonAtPV_Matched = propagateMuon(fwdtrack, fwdtrack, collision, propagationPoint::kToVertex, muoncuts.matchingZ, mBzMFT, 0.0); + float etaMatchedMCHMID = propmuonAtPV_Matched.getEta(); + float phiMatchedMCHMID = propmuonAtPV_Matched.getPhi(); + o2::math_utils::bringTo02Pi(phiMatchedMCHMID); + + o2::dataformats::GlobalFwdTrack propmuonAtDCA_Matched = propagateMuon(fwdtrack, fwdtrack, collision, propagationPoint::kToDCA, muoncuts.matchingZ, mBzMFT, 0.0); + float dcaX_Matched = propmuonAtDCA_Matched.getX() - collision.posX(); + float dcaY_Matched = propmuonAtDCA_Matched.getY() - collision.posY(); + float dcaXY_Matched = std::sqrt(dcaX_Matched * dcaX_Matched + dcaY_Matched * dcaY_Matched); + float pDCA = fwdtrack.p() * dcaXY_Matched; + + auto muons_per_MCHMID = fwdtracks.sliceBy(fwdtracksPerMCHTrack, fwdtrack.globalIndex()); + + float min_chi2MatchMCHMFT = 1e+10; + std::tuple tupleIds_at_min; + for (const auto& muon_tmp : muons_per_MCHMID) { + if (muon_tmp.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { + // LOGF(info, "muon_tmp.globalIndex() = %d, muon_tmp.matchMCHTrackId() = %d, muon_tmp.matchMFTTrackId() = %d, muon_tmp.chi2MatchMCHMFT() = %f", muon_tmp.globalIndex(), muon_tmp.matchMCHTrackId(), muon_tmp.matchMFTTrackId(), muon_tmp.chi2MatchMCHMFT()); + auto mchtrack = muon_tmp.template matchMCHTrack_as(); // MCH-MID + auto mfttrack = muon_tmp.template matchMFTTrack_as(); // MFTsa + + if (muon_tmp.chi2() < 0.f || muon_tmp.chi2MatchMCHMFT() < 0.f || muon_tmp.chi2MatchMCHMID() < 0.f || mfttrack.chi2() < 0.f) { // reject negative chi2, i.e. wrong. + continue; + } + + o2::dataformats::GlobalFwdTrack propmuonAtPV = propagateMuon(muon_tmp, muon_tmp, collision, propagationPoint::kToVertex, muoncuts.matchingZ, mBzMFT, 0.0); + float pt = propmuonAtPV.getPt(); + float eta = propmuonAtPV.getEta(); + float phi = propmuonAtPV.getPhi(); + o2::math_utils::bringTo02Pi(phi); + + if (muoncuts.refitGlobalMuon) { + pt = propmuonAtPV_Matched.getP() * std::sin(2.f * std::atan(std::exp(-eta))); + } + + float deta = etaMatchedMCHMID - eta; + float dphi = phiMatchedMCHMID - phi; + o2::math_utils::bringToPMPi(dphi); + int ndf = 2 * (mchtrack.nClusters() + mfttrack.nClusters()) - 5; + + float dcaX = propmuonAtPV.getX() - collision.posX(); + float dcaY = propmuonAtPV.getY() - collision.posY(); + float dcaXY = std::sqrt(dcaX * dcaX + dcaY * dcaY); + + if (muoncuts.cfgApplyPreselectionInBestMatch) { + if (!isSelectedMuon(pt, eta, muon_tmp.rAtAbsorberEnd(), pDCA, muon_tmp.chi2() / ndf, muon_tmp.trackType(), dcaXY)) { + continue; + } + if (std::sqrt(std::pow(deta / muoncuts.cfg_max_deta, 2) + std::pow(dphi / muoncuts.cfg_max_dphi, 2)) > 1.f) { + continue; + } + if (muon_tmp.chi2MatchMCHMFT() > muoncuts.cfg_max_matching_chi2_mftmch) { + continue; } } - vec_min_chi2MatchMCHMFT.emplace_back(tupleIds_at_min); - // LOGF(info, "min: muon_tmp.globalIndex() = %d, muon_tmp.matchMCHTrackId() = %d, muon_tmp.matchMFTTrackId() = %d, muon_tmp.chi2MatchMCHMFT() = %f", std::get<0>(tupleIds_at_min), std::get<1>(tupleIds_at_min), std::get<2>(tupleIds_at_min), min_chi2MatchMCHMFT); + + if (0.f < muon_tmp.chi2MatchMCHMFT() && muon_tmp.chi2MatchMCHMFT() < min_chi2MatchMCHMFT) { + min_chi2MatchMCHMFT = muon_tmp.chi2MatchMCHMFT(); + tupleIds_at_min = std::make_tuple(muon_tmp.globalIndex(), muon_tmp.matchMCHTrackId(), muon_tmp.matchMFTTrackId()); + } } - } // end of muon loop + } + vec_min_chi2MatchMCHMFT.emplace_back(tupleIds_at_min); + // LOGF(info, "min: muon_tmp.globalIndex() = %d, muon_tmp.matchMCHTrackId() = %d, muon_tmp.matchMFTTrackId() = %d, muon_tmp.chi2MatchMCHMFT() = %f", std::get<0>(tupleIds_at_min), std::get<1>(tupleIds_at_min), std::get<2>(tupleIds_at_min), min_chi2MatchMCHMFT); } void processElectronSA(MyCollisions const& collisions, aod::BCsWithTimestamps const&, MyTracks const& tracks, aod::McCollisions const&, aod::McParticles const&) @@ -976,9 +1026,19 @@ struct CreateResolutionMap { // Partition sa_muons = o2::aod::fwdtrack::trackType == uint8_t(o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack); // MCH-MID // Partition global_muons = o2::aod::fwdtrack::trackType == uint8_t(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack); // MFT-MCH-MID - void processMuonSA(MyCollisions const& collisions, aod::BCsWithTimestamps const&, MyFwdTracks const& fwdtracks, MyMFTTracks const&, aod::McCollisions const&, aod::McParticles const&) + void processMuonSA(MyCollisions const& collisions, aod::BCsWithTimestamps const&, MyFwdTracks const& fwdtracks, MyMFTTracks const& mfttracks, aod::McCollisions const&, aod::McParticles const&) { - findBestMatchPerMCHMID(fwdtracks); + vec_min_chi2MatchMCHMFT.reserve(fwdtracks.size()); + + for (const auto& collision : collisions) { + auto bc = collision.template bc_as(); + initCCDB(bc); + const auto& fwdtracks_per_coll = fwdtracks.sliceBy(perCollision_fwd, collision.globalIndex()); + for (const auto& fwdtrack : fwdtracks_per_coll) { + findBestMatchPerMCHMID(collision, fwdtrack, fwdtracks, mfttracks); + } // end of fwdtrack loop + } // end of collision loop + for (const auto& collision : collisions) { auto bc = collision.template foundBC_as(); initCCDB(bc); @@ -1016,51 +1076,18 @@ struct CreateResolutionMap { PROCESS_SWITCH(CreateResolutionMap, processMuonSA, "create resolution map for muon at forward rapidity", true); Preslice fwdtrackIndicesPerCollision = aod::track_association::collisionId; - void processMuonTTCA(MyCollisions const& collisions, aod::BCsWithTimestamps const&, MyFwdTracks const& fwdtracks, MyMFTTracks const&, aod::FwdTrackAssoc const& fwdtrackIndices, aod::McCollisions const&, aod::McParticles const&) + void processMuonTTCA(MyCollisions const& collisions, aod::BCsWithTimestamps const&, MyFwdTracks const& fwdtracks, MyMFTTracks const& mfttracks, aod::FwdTrackAssoc const& fwdtrackIndices, aod::McCollisions const&, aod::McParticles const&) { - findBestMatchPerMCHMID(fwdtracks); + vec_min_chi2MatchMCHMFT.reserve(fwdtracks.size()); for (const auto& collision : collisions) { - auto bc = collision.template foundBC_as(); + auto bc = collision.template bc_as(); initCCDB(bc); - - if (!isSelectedEvent(collision)) { - continue; - } - - if (!collision.has_mcCollision()) { - continue; - } - - float centrality = std::array{collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}[cfgCentEstimator]; - // auto mccollision = collision.template mcCollision_as(); - // registry.fill(HIST("Event/Muon/hImpPar_Centrality"), mccollision.impactParameter(), centrality); - auto fwdtrackIdsThisCollision = fwdtrackIndices.sliceBy(fwdtrackIndicesPerCollision, collision.globalIndex()); for (const auto& fwdtrackId : fwdtrackIdsThisCollision) { - auto muon = fwdtrackId.template fwdtrack_as(); - if (!muon.has_mcParticle()) { - continue; - } - auto mctrack = muon.template mcParticle_as(); - auto mccollision_from_mctrack = mctrack.template mcCollision_as(); - if (cfgEventGeneratorType >= 0 && mccollision_from_mctrack.getSubGeneratorId() != cfgEventGeneratorType) { - continue; - } - fillMuon(collision, muon, nullptr, centrality); + auto fwdtrack = fwdtrackId.template fwdtrack_as(); + findBestMatchPerMCHMID(collision, fwdtrack, fwdtracks, mfttracks); } // end of fwdtrack loop } // end of collision loop - vec_min_chi2MatchMCHMFT.clear(); - vec_min_chi2MatchMCHMFT.shrink_to_fit(); - } - PROCESS_SWITCH(CreateResolutionMap, processMuonTTCA, "create resolution map for muon at forward rapidity", false); - - std::unordered_map map_mfttrackcovs; - void processMuonTTCA_withMFTCov(MyCollisions const& collisions, aod::BCsWithTimestamps const&, MyFwdTracks const& fwdtracks, MyMFTTracks const&, aod::MFTTracksCov const& mftCovs, aod::FwdTrackAssoc const& fwdtrackIndices, aod::McCollisions const&, aod::McParticles const&) - { - for (const auto& mfttrackConv : mftCovs) { - map_mfttrackcovs[mfttrackConv.matchMFTTrackId()] = mfttrackConv.globalIndex(); - } - findBestMatchPerMCHMID(fwdtracks); for (const auto& collision : collisions) { auto bc = collision.template foundBC_as(); @@ -1089,14 +1116,58 @@ struct CreateResolutionMap { if (cfgEventGeneratorType >= 0 && mccollision_from_mctrack.getSubGeneratorId() != cfgEventGeneratorType) { continue; } - fillMuon(collision, muon, mftCovs, centrality); + fillMuon(collision, muon, nullptr, centrality); } // end of fwdtrack loop } // end of collision loop - map_mfttrackcovs.clear(); vec_min_chi2MatchMCHMFT.clear(); vec_min_chi2MatchMCHMFT.shrink_to_fit(); } - PROCESS_SWITCH(CreateResolutionMap, processMuonTTCA_withMFTCov, "create resolution map for muon at forward rapidity", false); + PROCESS_SWITCH(CreateResolutionMap, processMuonTTCA, "create resolution map for muon at forward rapidity", false); + + std::unordered_map map_mfttrackcovs; + + // void processMuonTTCA_withMFTCov(MyCollisions const& collisions, aod::BCsWithTimestamps const&, MyFwdTracks const& fwdtracks, MyMFTTracks const&, aod::MFTTracksCov const& mftCovs, aod::FwdTrackAssoc const& fwdtrackIndices, aod::McCollisions const&, aod::McParticles const&) + // { + // for (const auto& mfttrackConv : mftCovs) { + // map_mfttrackcovs[mfttrackConv.matchMFTTrackId()] = mfttrackConv.globalIndex(); + // } + // findBestMatchPerMCHMID(fwdtracks); + + // for (const auto& collision : collisions) { + // auto bc = collision.template foundBC_as(); + // initCCDB(bc); + + // if (!isSelectedEvent(collision)) { + // continue; + // } + + // if (!collision.has_mcCollision()) { + // continue; + // } + + // float centrality = std::array{collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}[cfgCentEstimator]; + // // auto mccollision = collision.template mcCollision_as(); + // // registry.fill(HIST("Event/Muon/hImpPar_Centrality"), mccollision.impactParameter(), centrality); + + // auto fwdtrackIdsThisCollision = fwdtrackIndices.sliceBy(fwdtrackIndicesPerCollision, collision.globalIndex()); + // for (const auto& fwdtrackId : fwdtrackIdsThisCollision) { + // auto muon = fwdtrackId.template fwdtrack_as(); + // if (!muon.has_mcParticle()) { + // continue; + // } + // auto mctrack = muon.template mcParticle_as(); + // auto mccollision_from_mctrack = mctrack.template mcCollision_as(); + // if (cfgEventGeneratorType >= 0 && mccollision_from_mctrack.getSubGeneratorId() != cfgEventGeneratorType) { + // continue; + // } + // fillMuon(collision, muon, mftCovs, centrality); + // } // end of fwdtrack loop + // } // end of collision loop + // map_mfttrackcovs.clear(); + // vec_min_chi2MatchMCHMFT.clear(); + // vec_min_chi2MatchMCHMFT.shrink_to_fit(); + // } + // PROCESS_SWITCH(CreateResolutionMap, processMuonTTCA_withMFTCov, "create resolution map for muon at forward rapidity", false); void processGen(aod::McCollisions const& mcCollisions) { diff --git a/PWGEM/Dilepton/Tasks/matchingMFT.cxx b/PWGEM/Dilepton/Tasks/matchingMFT.cxx index 558d0f418d0..e38648e48d0 100644 --- a/PWGEM/Dilepton/Tasks/matchingMFT.cxx +++ b/PWGEM/Dilepton/Tasks/matchingMFT.cxx @@ -88,7 +88,6 @@ struct matchingMFT { Configurable cfgManualZShift{"cfgManualZShift", 0, "manual z-shift for propagation of global muon to PV"}; Configurable requireTrueAssociation{"requireTrueAssociation", false, "flag to require true mc collision association"}; - Configurable maxRelDPt{"maxRelDPt", 1e+10f, "max. relative dpt between MFT-MCH-MID and MCH-MID"}; Configurable maxDEta{"maxDEta", 1e+10f, "max. deta between MFT-MCH-MID and MCH-MID"}; Configurable maxDPhi{"maxDPhi", 1e+10f, "max. dphi between MFT-MCH-MID and MCH-MID"}; Configurable maxDXMP{"maxDXMP", 1e+10f, "max. dx between MFT and MCH-MID at matching plane Z"}; @@ -96,12 +95,7 @@ struct matchingMFT { Configurable requireMFTHitMap{"requireMFTHitMap", false, "flag to require MFT hit map"}; Configurable> requiredMFTDisks{"requiredMFTDisks", std::vector{0}, "hit map on MFT disks [0,1,2,3,4]. logical-OR of each double-sided disk"}; Configurable matchingZ{"matchingZ", -77.5, "z position where matching is performed"}; - Configurable cfgBestMatchFinder{"cfgBestMatchFinder", 0, "matching chi2:0, dr:1, 2d:2"}; Configurable cfgApplyPreselectionInBestMatch{"cfgApplyPreselectionInBestMatch", false, "flag to apply preselection in find best match function"}; - Configurable cfgSlope_dr_chi2MatchMFTMCH{"cfgSlope_dr_chi2MatchMFTMCH", -0.15 / 30, "slope of chiMatchMCHMFT vs. dR"}; - Configurable cfgIntercept_dr_chi2MatchMFTMCH{"cfgIntercept_dr_chi2MatchMFTMCH", 1e+10f, "intercept of chiMatchMCHMFT vs. dR"}; - Configurable cfgPeakPosition_chi2MatchMFTMCH{"cfgPeakPosition_chi2MatchMFTMCH", 2.f, "peak position of chiMatchMCHMFT distribution"}; - Configurable cfgPeakPosition_dr{"cfgPeakPosition_dr", 0.01, "peak position of dr distribution"}; Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; Configurable cfgCentMin{"cfgCentMin", -1.f, "min. centrality"}; @@ -541,7 +535,6 @@ struct matchingMFT { float deta = etaMatchedMCHMID - eta; float dphi = phiMatchedMCHMID - phi; o2::math_utils::bringToPMPi(dphi); - float dr = std::sqrt(deta * deta + dphi * dphi); if (std::sqrt(std::pow(deta / maxDEta, 2) + std::pow(dphi / maxDPhi, 2)) > 1.f) { return; @@ -549,13 +542,6 @@ struct matchingMFT { if (std::sqrt(std::pow(dxMP / maxDXMP, 2) + std::pow(dyMP / maxDYMP, 2)) > 1.f) { return; } - if (std::fabs(dpt) > maxRelDPt) { - return; - } - - if (cfgSlope_dr_chi2MatchMFTMCH * fwdtrack.chi2MatchMCHMFT() + cfgIntercept_dr_chi2MatchMFTMCH < dr) { - return; - } if (!isSelected(pt, eta, rAtAbsorberEnd, pDCA, fwdtrack.chi2() / (2.f * (mchtrack.nClusters() + nClustersMFT) - 5.f), fwdtrack.trackType(), dcaXY)) { return; @@ -753,9 +739,7 @@ struct matchingMFT { } std::vector> vec_min_chi2MatchMCHMFT; // std::pair -> chi2MatchMCHMFT; - std::vector> vec_min_dr; // std::pair -> deta + dphi; - std::vector> vec_min_2d; // std::pair -> deta + dphi; - std::map, bool> mapCorrectMatch; + // std::map, bool> mapCorrectMatch; template void findBestMatchPerMCHMID(TCollision const& collision, TFwdTrack const& fwdtrack, TFwdTracks const& fwdtracks, TMFTTracks const&) @@ -768,11 +752,7 @@ struct matchingMFT { } std::tuple tupleIds_at_min_chi2mftmch; - std::tuple tupleIds_at_min_dr; - std::tuple tupleIds_at_min_distance_2d; float min_chi2MatchMCHMFT = 1e+10; - float min_dr = 1e+10; - float min_distance_2d = 1e+10; auto muons_per_MCHMID = fwdtracks.sliceBy(fwdtracksPerMCHTrack, fwdtrack.globalIndex()); // LOGF(info, "muons_per_MCHMID.size() = %d", muons_per_MCHMID.size()); @@ -781,12 +761,22 @@ struct matchingMFT { float phiMatchedMCHMID = propmuonAtPV_Matched.getPhi(); o2::math_utils::bringTo02Pi(phiMatchedMCHMID); + o2::dataformats::GlobalFwdTrack propmuonAtDCA_Matched = propagateMuon(fwdtrack, fwdtrack, collision, propagationPoint::kToDCA, matchingZ, mBz, mZShift); + float dcaX_Matched = propmuonAtDCA_Matched.getX() - collision.posX(); + float dcaY_Matched = propmuonAtDCA_Matched.getY() - collision.posY(); + float dcaXY_Matched = std::sqrt(dcaX_Matched * dcaX_Matched + dcaY_Matched * dcaY_Matched); + float pDCA = fwdtrack.p() * dcaXY_Matched; + for (const auto& muon_tmp : muons_per_MCHMID) { if (muon_tmp.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { auto tupleId = std::make_tuple(muon_tmp.globalIndex(), muon_tmp.matchMCHTrackId(), muon_tmp.matchMFTTrackId()); auto mchtrack = muon_tmp.template matchMCHTrack_as(); // MCH-MID auto mfttrack = muon_tmp.template matchMFTTrack_as(); + if (muon_tmp.chi2() < 0.f || muon_tmp.chi2MatchMCHMFT() < 0.f || muon_tmp.chi2MatchMCHMID() < 0.f || mfttrack.chi2() < 0.f) { // reject negative chi2, i.e. wrong. + continue; + } + // LOGF(info, "muon_tmp.has_mcParticle() = %d, mchtrack.has_mcParticle() = %d, mfttrack.has_mcParticle() = %d", muon_tmp.has_mcParticle(), mchtrack.has_mcParticle(), mfttrack.has_mcParticle()); if (!muon_tmp.has_mcParticle() || !mchtrack.has_mcParticle() || !mfttrack.has_mcParticle()) { @@ -801,23 +791,23 @@ struct matchingMFT { bool isMatched = (mcParticle_MFT.globalIndex() == mcParticle_MCHMID.globalIndex()) && (mcParticle_MFT.mcCollisionId() == mcParticle_MCHMID.mcCollisionId()); o2::dataformats::GlobalFwdTrack propmuonAtPV = propagateMuon(muon_tmp, muon_tmp, collision, propagationPoint::kToVertex, matchingZ, mBz, mZShift); - // float pt = propmuonAtPV.getPt(); + float pt = propmuonAtPV.getPt(); float eta = propmuonAtPV.getEta(); float phi = propmuonAtPV.getPhi(); o2::math_utils::bringTo02Pi(phi); - // if (refitGlobalMuon) { - // pt = propmuonAtPV_Matched.getP() * std::sin(2.f * std::atan(std::exp(-eta))); - // } + if (refitGlobalMuon) { + pt = propmuonAtPV_Matched.getP() * std::sin(2.f * std::atan(std::exp(-eta))); + } float deta = etaMatchedMCHMID - eta; float dphi = phiMatchedMCHMID - phi; o2::math_utils::bringToPMPi(dphi); float dr = std::sqrt(deta * deta + dphi * dphi); - // float chi2ndf = muon_tmp.chi2() / (2.f * (mchtrack.nClusters() + mfttrack.nClusters()) - 5.f); + float chi2ndf = muon_tmp.chi2() / (2.f * (mchtrack.nClusters() + mfttrack.nClusters()) - 5.f); - if (cfgApplyPreselectionInBestMatch && cfgSlope_dr_chi2MatchMFTMCH * muon_tmp.chi2MatchMCHMFT() + cfgIntercept_dr_chi2MatchMFTMCH < dr) { - continue; - } + float dcaX = propmuonAtPV.getX() - collision.posX(); + float dcaY = propmuonAtPV.getY() - collision.posY(); + float dcaXY = std::sqrt(dcaX * dcaX + dcaY * dcaY); if (isPrimary) { if (isMatched) { @@ -833,11 +823,11 @@ struct matchingMFT { } } - if (mcParticle_MFT.globalIndex() == mcParticle_MCHMID.globalIndex()) { - mapCorrectMatch[tupleId] = true; - } else { - mapCorrectMatch[tupleId] = false; - } + // if (mcParticle_MFT.globalIndex() == mcParticle_MCHMID.globalIndex()) { + // mapCorrectMatch[tupleId] = true; + // } else { + // mapCorrectMatch[tupleId] = false; + // } // if (std::abs(mcParticle_MCHMID.pdgCode()) == 13 && mcParticle_MCHMID.isPhysicalPrimary()) { // if (mcParticle_MFT.globalIndex() == mcParticle_MCHMID.globalIndex()) { @@ -847,34 +837,31 @@ struct matchingMFT { // } // } - if (0.f < muon_tmp.chi2MatchMCHMFT() && std::sqrt(std::pow(muon_tmp.chi2MatchMCHMFT() - cfgPeakPosition_chi2MatchMFTMCH, 2)) < min_chi2MatchMCHMFT) { - min_chi2MatchMCHMFT = std::sqrt(std::pow(muon_tmp.chi2MatchMCHMFT() - cfgPeakPosition_chi2MatchMFTMCH, 2)); - tupleIds_at_min_chi2mftmch = tupleId; - } - - if (std::sqrt(std::pow(dr - cfgPeakPosition_dr, 2)) < min_dr) { - min_dr = std::sqrt(std::pow(dr - cfgPeakPosition_dr, 2)); - tupleIds_at_min_dr = tupleId; + if (cfgApplyPreselectionInBestMatch) { + if (!isSelected(pt, eta, muon_tmp.rAtAbsorberEnd(), pDCA, chi2ndf, fwdtrack.trackType(), dcaXY)) { + continue; + } + if (std::sqrt(std::pow(deta / maxDEta, 2) + std::pow(dphi / maxDPhi, 2)) > 1.f) { + continue; + } + if (muon_tmp.chi2MatchMCHMFT() > maxMatchingChi2MCHMFT) { + continue; + } } - float distance_2d = std::sqrt(std::pow(muon_tmp.chi2MatchMCHMFT() - cfgPeakPosition_chi2MatchMFTMCH, 2) + std::pow(dr - cfgPeakPosition_dr, 2)); - if (distance_2d < min_distance_2d) { - min_distance_2d = distance_2d; - tupleIds_at_min_distance_2d = tupleId; + if (0.f < muon_tmp.chi2MatchMCHMFT() && muon_tmp.chi2MatchMCHMFT() < min_chi2MatchMCHMFT) { + min_chi2MatchMCHMFT = muon_tmp.chi2MatchMCHMFT(); + tupleIds_at_min_chi2mftmch = tupleId; } } // end of if global muon } // end of candidates loop vec_min_chi2MatchMCHMFT.emplace_back(tupleIds_at_min_chi2mftmch); - vec_min_dr.emplace_back(tupleIds_at_min_dr); - vec_min_2d.emplace_back(tupleIds_at_min_distance_2d); // auto mcParticleTMP = fwdtrack.template mcParticle_as(); // this is identical to mcParticle_MFTMCHMID // if (std::abs(mcParticleTMP.pdgCode()) == 13 && mcParticleTMP.isPhysicalPrimary()) { // LOGF(info, "min chi2: muon_tmp.globalIndex() = %d, muon_tmp.matchMCHTrackId() = %d, muon_tmp.matchMFTTrackId() = %d, muon_tmp.chi2MatchMCHMFT() = %f, correct match = %d", std::get<0>(tupleIds_at_min_chi2mftmch), std::get<1>(tupleIds_at_min_chi2mftmch), std::get<2>(tupleIds_at_min_chi2mftmch), min_chi2MatchMCHMFT, mapCorrectMatch[tupleIds_at_min_chi2mftmch]); - // LOGF(info, "min dr: muon_tmp.globalIndex() = %d, muon_tmp.matchMCHTrackId() = %d, muon_tmp.matchMFTTrackId() = %d, correct match = %d", std::get<0>(tupleIds_at_min_dr), std::get<1>(tupleIds_at_min_dr), std::get<2>(tupleIds_at_min_dr), mapCorrectMatch[tupleIds_at_min_dr]); - // LOGF(info, "min 2d: muon_tmp.globalIndex() = %d, muon_tmp.matchMCHTrackId() = %d, muon_tmp.matchMFTTrackId() = %d, correct match = %d", std::get<0>(tupleIds_at_min_distance_2d), std::get<1>(tupleIds_at_min_distance_2d), std::get<2>(tupleIds_at_min_distance_2d), mapCorrectMatch[tupleIds_at_min_distance_2d]); // } } @@ -1022,8 +1009,6 @@ struct matchingMFT { void processWithoutFTTCA(FilteredMyCollisions const& collisions, MyFwdTracks const& fwdtracks, MyMFTTracks const& mfttracks, aod::BCsWithTimestamps const&, aod::McParticles const&) { vec_min_chi2MatchMCHMFT.reserve(fwdtracks.size()); - vec_min_dr.reserve(fwdtracks.size()); - vec_min_2d.reserve(fwdtracks.size()); for (const auto& collision : collisions) { auto bc = collision.template bc_as(); initCCDB(bc); @@ -1060,18 +1045,8 @@ struct matchingMFT { continue; } - if (cfgBestMatchFinder == 0) { // chi2 - if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { - continue; - } - } else if (cfgBestMatchFinder == 1) { // dr - if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_dr.begin(), vec_min_dr.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_dr.end()) { - continue; - } - } else if (cfgBestMatchFinder == 2) { // 2d - if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_2d.begin(), vec_min_2d.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_2d.end()) { - continue; - } + if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { + continue; } fillHistograms(collision, fwdtrack, fwdtracks, mfttracks, nullptr); @@ -1080,18 +1055,12 @@ struct matchingMFT { vec_min_chi2MatchMCHMFT.clear(); vec_min_chi2MatchMCHMFT.shrink_to_fit(); - vec_min_dr.clear(); - vec_min_dr.shrink_to_fit(); - vec_min_2d.clear(); - vec_min_2d.shrink_to_fit(); } PROCESS_SWITCH(matchingMFT, processWithoutFTTCA, "process without FTTCA", false); void processWithFTTCA(FilteredMyCollisions const& collisions, MyFwdTracks const& fwdtracks, MyMFTTracks const& mfttracks, aod::BCsWithTimestamps const&, aod::FwdTrackAssoc const& fwdtrackIndices, aod::McParticles const&) { vec_min_chi2MatchMCHMFT.reserve(fwdtracks.size()); - vec_min_dr.reserve(fwdtracks.size()); - vec_min_2d.reserve(fwdtracks.size()); for (const auto& collision : collisions) { auto bc = collision.template bc_as(); initCCDB(bc); @@ -1129,18 +1098,8 @@ struct matchingMFT { continue; } - if (cfgBestMatchFinder == 0) { // chi2 - if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { - continue; - } - } else if (cfgBestMatchFinder == 1) { // dr - if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_dr.begin(), vec_min_dr.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_dr.end()) { - continue; - } - } else if (cfgBestMatchFinder == 2) { // 2d - if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_2d.begin(), vec_min_2d.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_2d.end()) { - continue; - } + if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { + continue; } fillHistograms(collision, fwdtrack, fwdtracks, mfttracks, nullptr); @@ -1149,10 +1108,6 @@ struct matchingMFT { vec_min_chi2MatchMCHMFT.clear(); vec_min_chi2MatchMCHMFT.shrink_to_fit(); - vec_min_dr.clear(); - vec_min_dr.shrink_to_fit(); - vec_min_2d.clear(); - vec_min_2d.shrink_to_fit(); } PROCESS_SWITCH(matchingMFT, processWithFTTCA, "process with FTTCA", true); @@ -1165,8 +1120,6 @@ struct matchingMFT { } vec_min_chi2MatchMCHMFT.reserve(fwdtracks.size()); - vec_min_dr.reserve(fwdtracks.size()); - vec_min_2d.reserve(fwdtracks.size()); for (const auto& collision : collisions) { auto bc = collision.template bc_as(); @@ -1205,18 +1158,8 @@ struct matchingMFT { continue; } - if (cfgBestMatchFinder == 0) { // chi2 - if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { - continue; - } - } else if (cfgBestMatchFinder == 1) { // dr - if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_dr.begin(), vec_min_dr.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_dr.end()) { - continue; - } - } else if (cfgBestMatchFinder == 2) { // 2d - if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_2d.begin(), vec_min_2d.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_2d.end()) { - continue; - } + if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { + continue; } fillHistograms(collision, fwdtrack, fwdtracks, mfttracks, mftCovs); } // end of fwdtrack loop @@ -1225,10 +1168,6 @@ struct matchingMFT { map_mfttrackcovs.clear(); vec_min_chi2MatchMCHMFT.clear(); vec_min_chi2MatchMCHMFT.shrink_to_fit(); - vec_min_dr.clear(); - vec_min_dr.shrink_to_fit(); - vec_min_2d.clear(); - vec_min_2d.shrink_to_fit(); } PROCESS_SWITCH(matchingMFT, processWithFTTCA_withMFTCov, "process with FTTCA with MFTCov", false); }; diff --git a/PWGEM/Dilepton/Tasks/prefilterDielectron.cxx b/PWGEM/Dilepton/Tasks/prefilterDielectron.cxx index 2b8d6a12321..c384f47a749 100644 --- a/PWGEM/Dilepton/Tasks/prefilterDielectron.cxx +++ b/PWGEM/Dilepton/Tasks/prefilterDielectron.cxx @@ -50,13 +50,13 @@ using namespace o2::soa; using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; using namespace o2::aod::pwgem::dilepton::utils::pairutil; -using MyCollisions = soa::Join; -using MyCollision = MyCollisions::iterator; +struct prefilterDielectron { + using MyCollisions = soa::Join; + using MyCollision = MyCollisions::iterator; -using MyTracks = soa::Join; -using MyTrack = MyTracks::iterator; + using MyTracks = soa::Join; + using MyTrack = MyTracks::iterator; -struct prefilterDielectron { Produces pfb_derived; // Configurables @@ -249,7 +249,7 @@ struct prefilterDielectron { fEMEventCut = EMEventCut("fEMEventCut", "fEMEventCut"); fEMEventCut.SetRequireSel8(eventcuts.cfgRequireSel8); fEMEventCut.SetRequireFT0AND(eventcuts.cfgRequireFT0AND); - fEMEventCut.SetZvtxRange(eventcuts.cfgZvtxMin, +eventcuts.cfgZvtxMax); + fEMEventCut.SetZvtxRange(eventcuts.cfgZvtxMin, eventcuts.cfgZvtxMax); fEMEventCut.SetRequireNoTFB(eventcuts.cfgRequireNoTFB); fEMEventCut.SetRequireNoITSROFB(eventcuts.cfgRequireNoITSROFB); fEMEventCut.SetRequireNoSameBunchPileup(eventcuts.cfgRequireNoSameBunchPileup); @@ -356,11 +356,11 @@ struct prefilterDielectron { int ndf = 0; void processPFB(FilteredMyCollisions const& collisions, MyTracks const& tracks) { - for (auto& track : tracks) { + for (const auto& track : tracks) { map_pfb[track.globalIndex()] = 0; } // end of track loop - for (auto& collision : collisions) { + for (const auto& collision : collisions) { initCCDB(collision); const float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; bool is_cent_ok = true; @@ -372,10 +372,10 @@ struct prefilterDielectron { auto negTracks_per_coll = negTracks->sliceByCached(o2::aod::emprimaryelectron::emeventId, collision.globalIndex(), cache); if (!fEMEventCut.IsSelected(collision) || !is_cent_ok) { - for (auto& pos : posTracks_per_coll) { + for (const auto& pos : posTracks_per_coll) { map_pfb[pos.globalIndex()] = 0; } - for (auto& neg : negTracks_per_coll) { + for (const auto& neg : negTracks_per_coll) { map_pfb[neg.globalIndex()] = 0; } continue; @@ -383,7 +383,7 @@ struct prefilterDielectron { // LOGF(info, "centrality = %f , posTracks_per_coll.size() = %d, negTracks_per_coll.size() = %d", centralities[cfgCentEstimator], posTracks_per_coll.size(), negTracks_per_coll.size()); - for (auto& [pos, ele] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS + for (const auto& [pos, ele] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS if (!fDielectronCut.IsSelectedTrack(pos) || !fDielectronCut.IsSelectedTrack(ele)) { continue; } @@ -417,7 +417,7 @@ struct prefilterDielectron { } } // end of ULS pairing - for (auto& [pos1, pos2] : combinations(CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { // LS++ + for (const auto& [pos1, pos2] : combinations(CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { // LS++ if (!fDielectronCut.IsSelectedTrack(pos1) || !fDielectronCut.IsSelectedTrack(pos2)) { continue; } @@ -441,7 +441,7 @@ struct prefilterDielectron { } } // end of LS++ pairing - for (auto& [ele1, ele2] : combinations(CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { // LS-- + for (const auto& [ele1, ele2] : combinations(CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { // LS-- if (!fDielectronCut.IsSelectedTrack(ele1) || !fDielectronCut.IsSelectedTrack(ele2)) { continue; } @@ -467,13 +467,13 @@ struct prefilterDielectron { } // end of collision loop - for (auto& track : tracks) { + for (const auto& track : tracks) { // LOGF(info, "map_pfb[%d] = %d", track.globalIndex(), map_pfb[track.globalIndex()]); pfb_derived(map_pfb[track.globalIndex()]); } // end of track loop // check pfb. - for (auto& collision : collisions) { + for (const auto& collision : collisions) { const float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { continue; @@ -486,7 +486,7 @@ struct prefilterDielectron { continue; } - for (auto& [pos, ele] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS + for (const auto& [pos, ele] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS if (!fDielectronCut.IsSelectedTrack(pos) || !fDielectronCut.IsSelectedTrack(ele)) { continue; } @@ -507,7 +507,7 @@ struct prefilterDielectron { fRegistry.fill(HIST("Pair/after/uls/hDeltaEtaDeltaPhi"), dphi, deta); } - for (auto& [pos1, pos2] : combinations(CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { // LS++ + for (const auto& [pos1, pos2] : combinations(CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { // LS++ if (!fDielectronCut.IsSelectedTrack(pos1) || !fDielectronCut.IsSelectedTrack(pos2)) { continue; } @@ -528,7 +528,7 @@ struct prefilterDielectron { fRegistry.fill(HIST("Pair/after/lspp/hDeltaEtaDeltaPhi"), dphi, deta); } - for (auto& [ele1, ele2] : combinations(CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { // LS-- + for (const auto& [ele1, ele2] : combinations(CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { // LS-- if (!fDielectronCut.IsSelectedTrack(ele1) || !fDielectronCut.IsSelectedTrack(ele2)) { continue; } From b3f5eae600ebf97ab2eadb501060ad84b8a4f7dd Mon Sep 17 00:00:00 2001 From: Subhadeep Mandal <147193283+5ub-Man@users.noreply.github.com> Date: Wed, 25 Feb 2026 09:54:05 +0530 Subject: [PATCH 073/347] [PWGLF] Optimised reflection process function (#15149) --- PWGLF/Tasks/Resonances/kstar892LightIon.cxx | 106 +++++++++----------- 1 file changed, 47 insertions(+), 59 deletions(-) diff --git a/PWGLF/Tasks/Resonances/kstar892LightIon.cxx b/PWGLF/Tasks/Resonances/kstar892LightIon.cxx index 6badcceea3c..47a723d44d4 100644 --- a/PWGLF/Tasks/Resonances/kstar892LightIon.cxx +++ b/PWGLF/Tasks/Resonances/kstar892LightIon.cxx @@ -175,8 +175,6 @@ struct Kstar892LightIon { Configurable selectCentEstimator{"selectCentEstimator", 0, "Select centrality estimator: 0 - FT0M, 1 - FT0A, 2 - FT0C, 3 - FV0A"}; - Configurable reflectionType{"reflectionType", 0, "Reflection: 0=Rho, 1=Omega, 2=Phi, 3=Kstar (for processRecReflection)"}; - Configurable nchAcceptance{"nchAcceptance", 0.5, "Eta window to measure Nch MC for Nch vs Cent distribution"}; Configurable nBinsNch{"nBinsNch", 400, "N bins Nch (|eta|<0.8)"}; @@ -208,13 +206,6 @@ struct Kstar892LightIon { kProton }; - enum PartReflection { - kRho, - kOmega, - kPhi, - kKstar - }; - int noOfDaughters = 2; double pionPIDpTlow = 1, pionPIDpThigh = 2.5, kaonPIDpTlow = 0.7, kaonPIDpThigh = 2.5; @@ -384,7 +375,10 @@ struct Kstar892LightIon { } if (doprocessRecReflection) { - hMC.add("Reflections/hReflection", "Refelction template of Rho", kTH3F, {ptAxis, centralityAxis, invmassAxis}); + hMC.add("Reflections/hRhoToKpi", "Refelction template of Rho", kTH3F, {ptAxis, centralityAxis, invmassAxis}); + hMC.add("Reflections/hOmegaToKpi", "Refelction template of Omega", kTH3F, {ptAxis, centralityAxis, invmassAxis}); + hMC.add("Reflections/hPhiToKpi", "Refelction template of Phi", kTH3F, {ptAxis, centralityAxis, invmassAxis}); + hMC.add("Reflections/hKstarSelf", "Refelction template of Kstar", kTH3F, {ptAxis, centralityAxis, invmassAxis}); } if (doprocessMCCheck) { @@ -1905,6 +1899,8 @@ struct Kstar892LightIon { if (!selectionEvent(collision, false)) return; + centrality = -1.f; + if (selectCentEstimator == kFT0M) { centrality = collision.centFT0M(); } else if (selectCentEstimator == kFT0A) { @@ -1914,10 +1910,11 @@ struct Kstar892LightIon { } else if (selectCentEstimator == kFV0A) { centrality = collision.centFV0A(); } else { - centrality = collision.centFT0M(); // default + centrality = collision.centFT0M(); } - for (const auto& [track1, track2] : combinations(CombinationsFullIndexPolicy(tracks, tracks))) { + for (const auto& [track1, track2] : + combinations(CombinationsFullIndexPolicy(tracks, tracks))) { if (!selectionTrack(track1) || !selectionTrack(track2)) continue; @@ -1943,8 +1940,8 @@ struct Kstar892LightIon { for (const auto& m1 : mc1.mothers_as()) { for (const auto& m2 : mc2.mothers_as()) { if (m1.globalIndex() == m2.globalIndex()) { - motherPDG = std::abs(m1.pdgCode()); sameMother = true; + motherPDG = std::abs(m1.pdgCode()); break; } } @@ -1955,101 +1952,92 @@ struct Kstar892LightIon { if (!sameMother) continue; - if (reflectionType == kRho) { // Rho0 (770) -> pi pi -> K pi - if (motherPDG != PDG_t::kRho770_0) - continue; + int pdg1 = std::abs(mc1.pdgCode()); + int pdg2 = std::abs(mc2.pdgCode()); - if (std::abs(mc1.pdgCode()) != PDG_t::kPiPlus || - std::abs(mc2.pdgCode()) != PDG_t::kPiPlus) - continue; + // ===================================================== + // Rho0 (770) -> pi pi -> K pi + // ===================================================== + if (motherPDG == PDG_t::kRho770_0 && pdg1 == PDG_t::kPiPlus && pdg2 == PDG_t::kPiPlus) { - // ---- permutation 1: track1 -> K + // track 1 -> K ROOT::Math::PxPyPzMVector p1K(track1.px(), track1.py(), track1.pz(), massKa); ROOT::Math::PxPyPzMVector p2Pi(track2.px(), track2.py(), track2.pz(), massPi); - auto fake1 = p1K + p2Pi; if (fake1.Rapidity() > selectionConfig.motherRapidityMin && fake1.Rapidity() < selectionConfig.motherRapidityMax) - hMC.fill(HIST("Reflections/hReflection"), fake1.Pt(), centrality, fake1.M()); + hMC.fill(HIST("Reflections/hRhoToKpi"), fake1.Pt(), centrality, fake1.M()); - // ---- permutation 2: track2 -> K + // track 2 -> K ROOT::Math::PxPyPzMVector p1Pi(track1.px(), track1.py(), track1.pz(), massPi); ROOT::Math::PxPyPzMVector p2K(track2.px(), track2.py(), track2.pz(), massKa); - auto fake2 = p1Pi + p2K; if (fake2.Rapidity() > selectionConfig.motherRapidityMin && fake2.Rapidity() < selectionConfig.motherRapidityMax) - hMC.fill(HIST("Reflections/hReflection"), fake2.Pt(), centrality, fake2.M()); - - } else if (reflectionType == kOmega) { // Omega (782) -> pi pi (pi0) -> K pi - if (motherPDG != o2::constants::physics::kOmega) - continue; + hMC.fill(HIST("Reflections/hRhoToKpi"), fake2.Pt(), centrality, fake2.M()); + } - if (std::abs(mc1.pdgCode()) != PDG_t::kPiPlus || - std::abs(mc2.pdgCode()) != PDG_t::kPiPlus) - continue; + // ===================================================== + // Omega (782) -> pi pi(pi0) -> K pi + // ===================================================== + if (motherPDG == o2::constants::physics::kOmega && pdg1 == PDG_t::kPiPlus && pdg2 == PDG_t::kPiPlus) { - // same two permutations as rho + // track 1 -> K ROOT::Math::PxPyPzMVector p1K(track1.px(), track1.py(), track1.pz(), massKa); ROOT::Math::PxPyPzMVector p2Pi(track2.px(), track2.py(), track2.pz(), massPi); - auto fake1 = p1K + p2Pi; if (fake1.Rapidity() > selectionConfig.motherRapidityMin && fake1.Rapidity() < selectionConfig.motherRapidityMax) - hMC.fill(HIST("Reflections/hReflection"), fake1.Pt(), centrality, fake1.M()); + hMC.fill(HIST("Reflections/hOmegaToKpi"), fake1.Pt(), centrality, fake1.M()); + // track 2 -> K ROOT::Math::PxPyPzMVector p1Pi(track1.px(), track1.py(), track1.pz(), massPi); ROOT::Math::PxPyPzMVector p2K(track2.px(), track2.py(), track2.pz(), massKa); - auto fake2 = p1Pi + p2K; if (fake2.Rapidity() > selectionConfig.motherRapidityMin && fake2.Rapidity() < selectionConfig.motherRapidityMax) - hMC.fill(HIST("Reflections/hReflection"), fake2.Pt(), centrality, fake2.M()); - - } else if (reflectionType == kPhi) { // Phi (1020) -> K K -> K pi - if (motherPDG != o2::constants::physics::kPhi) - continue; + hMC.fill(HIST("Reflections/hOmegaToKpi"), fake2.Pt(), centrality, fake2.M()); + } - if (std::abs(mc1.pdgCode()) != PDG_t::kKPlus || std::abs(mc2.pdgCode()) != PDG_t::kKPlus) - continue; + // ===================================================== + // Phi (1020) -> KK -> K pi + // ===================================================== + if (motherPDG == o2::constants::physics::kPhi && pdg1 == PDG_t::kKPlus && pdg2 == PDG_t::kKPlus) { - // ---- permutation 1: track1 -> π + // track 1 -> pi ROOT::Math::PxPyPzMVector p1Pi(track1.px(), track1.py(), track1.pz(), massPi); ROOT::Math::PxPyPzMVector p2K(track2.px(), track2.py(), track2.pz(), massKa); - auto fake1 = p1Pi + p2K; if (fake1.Rapidity() > selectionConfig.motherRapidityMin && fake1.Rapidity() < selectionConfig.motherRapidityMax) - hMC.fill(HIST("Reflections/hReflection"), fake1.Pt(), centrality, fake1.M()); + hMC.fill(HIST("Reflections/hPhiToKpi"), fake1.Pt(), centrality, fake1.M()); - // ---- permutation 2: track2 -> π + // track 2 -> pi ROOT::Math::PxPyPzMVector p1K(track1.px(), track1.py(), track1.pz(), massKa); ROOT::Math::PxPyPzMVector p2Pi(track2.px(), track2.py(), track2.pz(), massPi); - auto fake2 = p1K + p2Pi; if (fake2.Rapidity() > selectionConfig.motherRapidityMin && fake2.Rapidity() < selectionConfig.motherRapidityMax) - hMC.fill(HIST("Reflections/hReflection"), fake2.Pt(), centrality, fake2.M()); - } else if (reflectionType == kKstar) { // K*0 (892) Self-Reflection (swap) - - if (motherPDG != o2::constants::physics::kK0Star892) - continue; + hMC.fill(HIST("Reflections/hPhiToKpi"), fake2.Pt(), centrality, fake2.M()); + } - if (!((std::abs(mc1.pdgCode()) == PDG_t::kPiPlus && std::abs(mc2.pdgCode()) == PDG_t::kKPlus) || (std::abs(mc1.pdgCode()) == PDG_t::kKPlus && std::abs(mc2.pdgCode()) == PDG_t::kPiPlus))) - continue; + // ===================================================== + // K*0 Self-reflection + // ===================================================== + if (motherPDG == o2::constants::physics::kK0Star892 && ((pdg1 == PDG_t::kPiPlus && pdg2 == PDG_t::kKPlus) || (pdg1 == PDG_t::kKPlus && pdg2 == PDG_t::kPiPlus))) { - ROOT::Math::PxPyPzMVector p1Swap(track1.px(), track1.py(), track1.pz(), std::abs(mc1.pdgCode()) == PDG_t::kKPlus ? massPi : massKa); + ROOT::Math::PxPyPzMVector p1Swap(track1.px(), track1.py(), track1.pz(), pdg1 == PDG_t::kKPlus ? massPi : massKa); - ROOT::Math::PxPyPzMVector p2Swap(track2.px(), track2.py(), track2.pz(), std::abs(mc2.pdgCode()) == PDG_t::kKPlus ? massPi : massKa); + ROOT::Math::PxPyPzMVector p2Swap(track2.px(), track2.py(), track2.pz(), pdg2 == PDG_t::kKPlus ? massPi : massKa); auto fake = p1Swap + p2Swap; if (fake.Rapidity() > selectionConfig.motherRapidityMin && fake.Rapidity() < selectionConfig.motherRapidityMax) - hMC.fill(HIST("Reflections/hReflection"), fake.Pt(), centrality, fake.M()); + hMC.fill(HIST("Reflections/hKstarSelf"), fake.Pt(), centrality, fake.M()); } } } - PROCESS_SWITCH(Kstar892LightIon, processRecReflection, "Process particle reflection", false); + PROCESS_SWITCH(Kstar892LightIon, processRecReflection, "Process reconstructed reflections", false); Service pdg; From 099a3e64b6bb5cd9da10b22c85c14c27af458676 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Wed, 25 Feb 2026 08:06:04 +0100 Subject: [PATCH 074/347] [PWGLF,PWGMM] Revert BCL defition requiring not-BCB instead of BCE and reduce number of bins (#15152) --- PWGMM/Lumi/Tasks/lumiStabilityPP.cxx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/PWGMM/Lumi/Tasks/lumiStabilityPP.cxx b/PWGMM/Lumi/Tasks/lumiStabilityPP.cxx index c1b391a1375..9143f524ff3 100644 --- a/PWGMM/Lumi/Tasks/lumiStabilityPP.cxx +++ b/PWGMM/Lumi/Tasks/lumiStabilityPP.cxx @@ -75,7 +75,7 @@ struct LumiStabilityPP { static constexpr int defaulFlags[1][NBCCategories] = {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}; Configurable> doTypeBC{"doTypeBC", {defaulFlags[0], NBCCategories, {"BCA", "BCB", "BCC", "BCE", "BCL", "BCSLFDD", "BCSLFT0", "BCNL", "BCNSLFDD", "BCNSLFT0"}}, "Create and fill histograms for different BC types"}; - Configurable numEmptyBCsBeforeLeadingBC{"numEmptyBCsBeforeLeadingBC", 5, "Number of empty BCs before a (super)leading BC"}; + Configurable numEmptyBCsBeforeLeadingBC{"numEmptyBCsBeforeLeadingBC", 5, "Number of (empty) non-B BCs before a (super)leading BC"}; Configurable bcShiftFDDForData2023{"bcShiftFDDForData2023", 7, "Number of bc to shift for FDD to be applied for 2023 data only"}; std::bitset beamPatternA, beamPatternC; @@ -146,8 +146,8 @@ struct LumiStabilityPP { if (doTypeBC->get(0u, iBCCategory)) { histBcVsTime[iTrigger][iBCCategory][runNumber] = registry.add(Form("%d/%s", runNumber, std::string(NBCsVsTimeHistNames[iTrigger][iBCCategory]).c_str()), "Time of triggered BCs since the start of fill;#bf{t-t_{SOF} (min)};#bf{#it{N}_{BC}}", HistType::kTH1D, {timeAxis}); histBcVsBcId[iTrigger][iBCCategory][runNumber] = registry.add(Form("%d/%s", runNumber, std::string(NBCsVsBCIDHistNames[iTrigger][iBCCategory]).c_str()), "BC ID of triggered BCs;#bf{BC ID in orbit};#bf{#it{N}_{BC}}", HistType::kTH1D, {bcIDAxis}); - histMu[iTrigger][iBCCategory][runNumber] = registry.add(Form("%d/%s", runNumber, std::string(MuHistNames[iTrigger][iBCCategory]).c_str()), "pile-up #mu of different triggers;#mu;counts", HistType::kTH1D, {{1000, 0., 0.2}}); - histMuPerBcId[iTrigger][iBCCategory][runNumber] = registry.add(Form("%d/%sVsBcId", runNumber, std::string(MuHistNames[iTrigger][iBCCategory]).c_str()), "pile-up #mu of different triggers per BCId;#mu;counts", HistType::kTH2D, {{bcIDAxis}, {1000, 0., 0.2}}); + histMu[iTrigger][iBCCategory][runNumber] = registry.add(Form("%d/%s", runNumber, std::string(MuHistNames[iTrigger][iBCCategory]).c_str()), "pile-up #mu of different triggers;#mu;counts", HistType::kTH1D, {{400, 0., 0.2}}); + histMuPerBcId[iTrigger][iBCCategory][runNumber] = registry.add(Form("%d/%sVsBcId", runNumber, std::string(MuHistNames[iTrigger][iBCCategory]).c_str()), "pile-up #mu of different triggers per BCId;#mu;counts", HistType::kTH2D, {{bcIDAxis}, {400, 0., 0.2}}); } } } @@ -203,16 +203,16 @@ struct LumiStabilityPP { int totalLeadingBCs = 0; for (int iBC = 0; iBC < o2::constants::lhc::LHCMaxBunches; iBC++) { if (bcPatternB[iBC]) { // Check if current BC is of type B - int emptyBCsBefore = 0; // Count how many consecutive BCs before this one are empty + int nonBtypeBCsBefore = 0; // Count how many consecutive BCs before this one are non-B for (int j = 1; j <= numEmptyBCsBeforeLeadingBC; j++) { int prevBC = (iBC - j + o2::constants::lhc::LHCMaxBunches) % o2::constants::lhc::LHCMaxBunches; // Protection for BCs at small indices to check the end of the orbit - if (bcPatternE[prevBC]) { - emptyBCsBefore++; + if (!bcPatternB[prevBC]) { + nonBtypeBCsBefore++; } else { - break; // Stop counting if we hit a non-empty BC + break; // Stop counting if we hit a BCB } } - if (emptyBCsBefore >= numEmptyBCsBeforeLeadingBC) { // If we found at least numEmptyBCsBeforeLeadingBC empty BCs before this one, mark it as leading + if (nonBtypeBCsBefore >= numEmptyBCsBeforeLeadingBC) { // If we found at least numEmptyBCsBeforeLeadingBC non-B BCs before this one, mark it as leading bcPatternL[iBC] = true; totalLeadingBCs++; } From 48bc4c87881784c8b819a8e9a942c3c29f70f201 Mon Sep 17 00:00:00 2001 From: ikantak <149821212+ikantak@users.noreply.github.com> Date: Wed, 25 Feb 2026 08:08:33 +0100 Subject: [PATCH 075/347] [PWGEM] Change from sliceByCached back to sliceBy (#15113) --- PWGEM/PhotonMeson/Tasks/pcmQC.cxx | 15 ++++++++------- PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx | 15 ++++++++------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/PWGEM/PhotonMeson/Tasks/pcmQC.cxx b/PWGEM/PhotonMeson/Tasks/pcmQC.cxx index 4bb4e38f583..d8a006afd3f 100644 --- a/PWGEM/PhotonMeson/Tasks/pcmQC.cxx +++ b/PWGEM/PhotonMeson/Tasks/pcmQC.cxx @@ -54,7 +54,7 @@ using MyCollision = MyCollisions::iterator; using MyV0Photons = soa::Join; using MyV0Photon = MyV0Photons::iterator; -using MyV0PhotonsML = soa::Join; +using MyV0PhotonsML = soa::Join; using MyV0PhotonML = MyV0PhotonsML::iterator; struct PCMQC { @@ -476,14 +476,15 @@ struct PCMQC { // fRegistry.fill(HIST("V0Leg/hZY"), leg.z(), leg.y()); } - o2::framework::SliceCache v0cache; + Preslice perCollisionV0 = aod::v0photonkf::emphotoneventId; + Preslice perCollisionV0ML = aod::v0photonkf::emphotoneventId; Filter collisionFilter_centrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); Filter collisionFilter_occupancy_track = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; Filter collisionFilter_occupancy_ft0c = eventcuts.cfgFT0COccupancyMin <= o2::aod::evsel::ft0cOccupancyInTimeRange && o2::aod::evsel::ft0cOccupancyInTimeRange < eventcuts.cfgFT0COccupancyMax; using FilteredMyCollisions = soa::Filtered; - template - void process(FilteredMyCollisions const& collisions, TV0Photon const& v0photons, aod::V0Legs const&) + template + void process(FilteredMyCollisions const& collisions, TV0Photon const& v0photons, aod::V0Legs const&, TPerCollision const& perCollision) { for (const auto& collision : collisions) { initCCDB(collision); @@ -502,7 +503,7 @@ struct PCMQC { fV0PhotonCut.SetCentrality(centralities[cfgCentEstimator]); int nv0 = 0; - auto v0photons_coll = v0photons.sliceByCached(aod::v0photonkf::emeventId, collision.globalIndex(), v0cache); + auto v0photons_coll = v0photons.sliceBy(perCollision, collision.globalIndex()); for (const auto& v0 : v0photons_coll) { auto pos = v0.template posTrack_as(); auto ele = v0.template negTrack_as(); @@ -525,12 +526,12 @@ struct PCMQC { } void processQC(FilteredMyCollisions const& collisions, MyV0Photons const& v0photons, aod::V0Legs const& v0legs) { - process(collisions, v0photons, v0legs); + process(collisions, v0photons, v0legs, perCollisionV0); } // end of process void processQCML(FilteredMyCollisions const& collisions, MyV0PhotonsML const& v0photonsML, aod::V0Legs const& v0legs) { - process(collisions, v0photonsML, v0legs); + process(collisions, v0photonsML, v0legs, perCollisionV0ML); } // end of ML process void processDummy(MyCollisions const&) {} diff --git a/PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx b/PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx index 0e3f56909ca..5516dfdac41 100644 --- a/PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx +++ b/PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx @@ -63,7 +63,7 @@ using MyMCCollision = MyMCCollisions::iterator; using MyV0Photons = o2::soa::Join; using MyV0Photon = MyV0Photons::iterator; -using MyV0PhotonsML = soa::Join; +using MyV0PhotonsML = soa::Join; using MyV0PhotonML = MyV0PhotonsML::iterator; using MyMCV0Legs = soa::Join; @@ -568,14 +568,15 @@ struct PCMQCMC { fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hRxyGen_DeltaEta"), std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2)), leg.eta() - mcleg.eta()); fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hRxyGen_DeltaPhi"), std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2)), leg.phi() - mcleg.phi()); } - o2::framework::SliceCache v0cache; + Preslice perCollisionV0 = aod::v0photonkf::emphotoneventId; + Preslice perCollisionV0ML = aod::v0photonkf::emphotoneventId; Filter collisionFilter_centrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); Filter collisionFilter_occupancy_track = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; Filter collisionFilter_occupancy_ft0c = eventcuts.cfgFT0COccupancyMin <= o2::aod::evsel::ft0cOccupancyInTimeRange && o2::aod::evsel::ft0cOccupancyInTimeRange < eventcuts.cfgFT0COccupancyMax; using FilteredMyCollisions = soa::Filtered; - template - void processMC(FilteredMyCollisions const& collisions, TV0Photons const& v0photons, aod::EMMCParticles const& mcparticles, MyMCV0Legs const&, aod::EMMCEvents const&) + template + void processMC(FilteredMyCollisions const& collisions, TV0Photons const& v0photons, aod::EMMCParticles const& mcparticles, MyMCV0Legs const&, aod::EMMCEvents const&, TPerCollision const& percollision) { for (const auto& collision : collisions) { initCCDB(collision); @@ -593,7 +594,7 @@ struct PCMQCMC { fRegistry.fill(HIST("Event/after/hCollisionCounter"), 10.0); // accepted fV0PhotonCut.SetCentrality(centralities[cfgCentEstimator]); // set centrality for BDT response - auto V0Photons_coll = v0photons.sliceByCached(aod::v0photonkf::emeventId, collision.globalIndex(), v0cache); + auto V0Photons_coll = v0photons.sliceBy(percollision, collision.globalIndex()); int ng_primary = 0, ng_wd = 0, ng_hs = 0, nee_pi0 = 0, nee_eta = 0; for (const auto& v0 : V0Photons_coll) { auto pos = v0.template posTrack_as(); @@ -683,12 +684,12 @@ struct PCMQCMC { void processQCMC(FilteredMyCollisions const& collisions, MyV0Photons const& v0photons, aod::EMMCParticles const& mcparticles, MyMCV0Legs const& mcv0legs, aod::EMMCEvents const& mcevents) { - processMC(collisions, v0photons, mcparticles, mcv0legs, mcevents); + processMC(collisions, v0photons, mcparticles, mcv0legs, mcevents, perCollisionV0); } // end of QC process void processQCMCML(FilteredMyCollisions const& collisions, MyV0PhotonsML const& v0photonsML, aod::EMMCParticles const& mcparticles, MyMCV0Legs const& mcv0legs, aod::EMMCEvents const& mcevents) { - processMC(collisions, v0photonsML, mcparticles, mcv0legs, mcevents); + processMC(collisions, v0photonsML, mcparticles, mcv0legs, mcevents, perCollisionV0ML); } // end of QC process with ML cuts template From 7a06b495a0142a20e86911830af8863c396d4396 Mon Sep 17 00:00:00 2001 From: Marvin Hemmer <53471402+mhemmer-cern@users.noreply.github.com> Date: Wed, 25 Feb 2026 08:10:05 +0100 Subject: [PATCH 076/347] [PWGEM] PhotonMeson: Fix bug in EMNonLin (#15137) --- PWGEM/PhotonMeson/Core/EMNonLin.cxx | 23 +++++++++------ .../TableProducer/nonLinProducer.cxx | 28 ++++++++----------- 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/PWGEM/PhotonMeson/Core/EMNonLin.cxx b/PWGEM/PhotonMeson/Core/EMNonLin.cxx index bb5102dfc2a..571d7efbae8 100644 --- a/PWGEM/PhotonMeson/Core/EMNonLin.cxx +++ b/PWGEM/PhotonMeson/Core/EMNonLin.cxx @@ -25,22 +25,27 @@ float EMNonLin::getCorrectionFactor(float x, const Context& ctx) return x; } - float val = x; - // safety measure int maxIter = std::min(ctx.nIter, MaxIter - 1); + float scale = 1.f; // cumulative scale + float refVal = x; // reference value for computing next scale + for (int i = 0; i <= maxIter; ++i) { - if (val == 0.f) { + if (refVal == 0.f) { break; } - float inv = 1.f / val; - val *= (1.f + ctx.params[i].par0 * inv + - ctx.params[i].par1 * inv * inv) / - (1.f + ctx.params[i].par2 * inv); - } + const auto& p = ctx.params[i]; - return val; + // scale function (x + a + b/x)/(x + c) which goes towards 1 for large x since x >> a,b,c -> x/x = 1 + float iterScale = + (refVal + p.par0 + p.par1 / refVal) / + (refVal + p.par2); + + scale *= iterScale; // total scale = product over itertaion scale + refVal = x * scale; // next iteration uses scaled original input + } + return scale; } const EMNonLin::NonLinParams* EMNonLin::resolveParams(PhotonType type, float cent) diff --git a/PWGEM/PhotonMeson/TableProducer/nonLinProducer.cxx b/PWGEM/PhotonMeson/TableProducer/nonLinProducer.cxx index 9d3847ffb8a..74ac6e4ed5e 100644 --- a/PWGEM/PhotonMeson/TableProducer/nonLinProducer.cxx +++ b/PWGEM/PhotonMeson/TableProducer/nonLinProducer.cxx @@ -109,32 +109,30 @@ struct NonLinProducer { template void runEMC(TClusters const& clusters, TCollisio& collision) { - float cent = getCentrality(collision); int32_t collIndex = collision.globalIndex(); + float cent = getCentrality(collision); + emNonLinContextEMC.setParams(emNonLinEMC.resolveParams(o2::pwgem::nonlin::EMNonLin::PhotonType::kEMC, cent)); + for (const auto& cluster : clusters) { - float nonLinE = 0.f; - float nonLinPt = 0.f; - float nonLinFactor = 1.f; // check that we are at the correct collision if (cluster.emphotoneventId() != collIndex) { collIndex = cluster.emphotoneventId(); collision.setCursor(collIndex); cent = getCentrality(collision); + emNonLinContextEMC.setParams(emNonLinEMC.resolveParams(o2::pwgem::nonlin::EMNonLin::PhotonType::kEMC, cent)); } - emNonLinContextEMC.setParams(emNonLinEMC.resolveParams(o2::pwgem::nonlin::EMNonLin::PhotonType::kEMC, cent)); - // fill before non lin histograms historeg.fill(HIST("QA/EMC/EIn"), cluster.e()); historeg.fill(HIST("QA/EMC/PtIn"), cluster.pt()); // get NonLin factor from class dependent on the centrality - nonLinFactor = emNonLinEMC.getCorrectionFactor(cluster.e(), emNonLinContextEMC); + float nonLinFactor = emNonLinEMC.getCorrectionFactor(cluster.e(), emNonLinContextEMC); - nonLinE = nonLinFactor * cluster.e(); - nonLinPt = nonLinFactor * cluster.pt(); + float nonLinE = nonLinFactor * cluster.e(); + float nonLinPt = nonLinFactor * cluster.pt(); // fill after non lin histograms historeg.fill(HIST("QA/EMC/EOut"), nonLinE); @@ -147,29 +145,27 @@ struct NonLinProducer { template void runPCM(TV0 const& v0s, TCollisio& collision) { - float cent = getCentrality(collision); int32_t collIndex = collision.globalIndex(); + float cent = getCentrality(collision); + emNonLinContextPCM.setParams(emNonLinPCM.resolveParams(o2::pwgem::nonlin::EMNonLin::PhotonType::kPCM, cent)); for (const auto& v0 : v0s) { - float nonLinPt = 0.f; - float nonLinFactor = 1.f; // check that we are at the correct collision if (v0.emphotoneventId() != collIndex) { collIndex = v0.emphotoneventId(); collision.setCursor(collIndex); cent = getCentrality(collision); + emNonLinContextPCM.setParams(emNonLinPCM.resolveParams(o2::pwgem::nonlin::EMNonLin::PhotonType::kPCM, cent)); } - emNonLinContextPCM.setParams(emNonLinPCM.resolveParams(o2::pwgem::nonlin::EMNonLin::PhotonType::kPCM, cent)); - // fill before non lin histograms historeg.fill(HIST("QA/PCM/PtIn"), v0.pt()); // get NonLin factor from class dependent on the centrality - nonLinFactor = emNonLinEMC.getCorrectionFactor(v0.pt(), emNonLinContextPCM); + float nonLinFactor = emNonLinEMC.getCorrectionFactor(v0.pt(), emNonLinContextPCM); - nonLinPt = nonLinFactor * v0.pt(); + float nonLinPt = nonLinFactor * v0.pt(); // fill after non lin histograms historeg.fill(HIST("QA/PCM/PtOut"), nonLinPt); From 621812b080657deb15deddd78a87f55c589c1a1e Mon Sep 17 00:00:00 2001 From: swapneshkhade <107178389+swapneshkhade@users.noreply.github.com> Date: Wed, 25 Feb 2026 13:37:35 +0530 Subject: [PATCH 077/347] [PWGHF] Adding efficiency weight (#15097) --- PWGHF/HFC/Tasks/taskCorrelationD0Hadrons.cxx | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/PWGHF/HFC/Tasks/taskCorrelationD0Hadrons.cxx b/PWGHF/HFC/Tasks/taskCorrelationD0Hadrons.cxx index 74c33e0868e..2d51bc7ece9 100644 --- a/PWGHF/HFC/Tasks/taskCorrelationD0Hadrons.cxx +++ b/PWGHF/HFC/Tasks/taskCorrelationD0Hadrons.cxx @@ -164,6 +164,12 @@ struct HfTaskCorrelationD0Hadrons { AxisSpec axisCentFT0M = {binsCentFt0m, "Centrality percentile (FT0M)"}; // Histograms for data + + registry.add("hBdtScorePrompt", "D0 BDT prompt score", {HistType::kTH1F, {axisBdtScore}}); + registry.add("hBdtScoreBkg", "D0 BDT bkg score", {HistType::kTH1F, {axisBdtScore}}); + registry.add("hMassD0VsPt", "D0 candidates massVsPt", {HistType::kTH2F, {{axisMassD}, {axisPtD}}}); + registry.add("hMassD0VsPtWoEff", "D0 candidates massVsPt without efficiency", {HistType::kTH2F, {{axisMassD}, {axisPtD}}}); + registry.add("hDeltaEtaPtIntSignalRegion", "D0-h deltaEta signal region", {HistType::kTH1F, {axisDeltaEta}}); registry.add("hDeltaPhiPtIntSignalRegion", "D0-h deltaPhi signal region", {HistType::kTH1F, {axisDeltaPhi}}); registry.add("hCorrel2DPtIntSignalRegion", "D0-h deltaPhi vs deltaEta signal region", {HistType::kTH2F, {{axisDeltaPhi}, {axisDeltaEta}}}); @@ -308,6 +314,7 @@ struct HfTaskCorrelationD0Hadrons { aod::D0CandRecoInfo const& candidates) { for (const auto& candidate : candidates) { + float const massD = candidate.mD(); float const ptD = candidate.ptD(); float const bdtScorePromptD0 = candidate.mlScorePromptD0(); float const bdtScoreBkgD0 = candidate.mlScoreBkgD0(); @@ -324,6 +331,16 @@ struct HfTaskCorrelationD0Hadrons { (bdtScorePromptD0bar < mlOutputPromptD0bar->at(effBinD) || bdtScoreBkgD0bar > mlOutputBkgD0bar->at(effBinD))) { continue; } + + double efficiencyWeightD = 1.; + if (applyEfficiency != 0) { + efficiencyWeightD = 1. / efficiencyDmeson->at(o2::analysis::findBin(binsPtEfficiencyD, ptD)); + } + + registry.fill(HIST("hMassD0VsPt"), massD, ptD, efficiencyWeightD); + registry.fill(HIST("hMassD0VsPtWoEff"), massD, ptD); + registry.fill(HIST("hBdtScorePrompt"), bdtScorePromptD0); + registry.fill(HIST("hBdtScoreBkg"), bdtScoreBkgD0); } for (const auto& pairEntry : pairEntries) { From d3c2b2fd1375b5eae5a7ccfb8536db3590ee5945 Mon Sep 17 00:00:00 2001 From: nzardosh Date: Wed, 25 Feb 2026 10:00:40 +0000 Subject: [PATCH 078/347] [PWGJE] fixing track selection in selector (#15144) --- PWGJE/TableProducer/derivedDataSelector.cxx | 2 +- PWGJE/TableProducer/derivedDataWriter.cxx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/PWGJE/TableProducer/derivedDataSelector.cxx b/PWGJE/TableProducer/derivedDataSelector.cxx index 20c96a74372..fcd4c3f5ffe 100644 --- a/PWGJE/TableProducer/derivedDataSelector.cxx +++ b/PWGJE/TableProducer/derivedDataSelector.cxx @@ -362,7 +362,7 @@ struct JetDerivedDataSelector { } } else { if constexpr (std::is_same_v, aod::JTracks>) { - if (config.performTrackSelection && !(selectionObject.trackSel() & ~(1 << jetderiveddatautilities::JTrackSel::trackSign))) { + if (config.performTrackSelection && !(selectionObject.trackSel() & ~((1ULL << jetderiveddatautilities::JTrackSel::trackSign) | (1ULL << jetderiveddatautilities::JTrackSel::notBadMcTrack)))) { continue; } if (selectionObject.pt() < config.trackPtSelectionMin || std::abs(selectionObject.eta()) > config.trackEtaSelectionMax) { diff --git a/PWGJE/TableProducer/derivedDataWriter.cxx b/PWGJE/TableProducer/derivedDataWriter.cxx index e59c04afa8c..61bbefed01a 100644 --- a/PWGJE/TableProducer/derivedDataWriter.cxx +++ b/PWGJE/TableProducer/derivedDataWriter.cxx @@ -284,7 +284,7 @@ struct JetDerivedDataWriter { template bool trackSelection(T const& track) { - if (config.performTrackSelection && !(track.trackSel() & ~((1 << jetderiveddatautilities::JTrackSel::trackSign) | (1 << jetderiveddatautilities::JTrackSel::notBadMcTrack)))) { // skips tracks that pass no selections. This might cause a problem with tracks matched with clusters. We should generate a track selection purely for cluster matched tracks so that they are kept. This includes also the track pT selction. + if (config.performTrackSelection && !(track.trackSel() & ~((1ULL << jetderiveddatautilities::JTrackSel::trackSign) | (1ULL << jetderiveddatautilities::JTrackSel::notBadMcTrack)))) { // skips tracks that pass no selections. This might cause a problem with tracks matched with clusters. We should generate a track selection purely for cluster matched tracks so that they are kept. This includes also the track pT selction. return false; } if (track.pt() < config.trackPtSelectionMin || std::abs(track.eta()) > config.trackEtaSelectionMax) { From e8090f92c35a2adfe3091a15b46061634d4e9a65 Mon Sep 17 00:00:00 2001 From: somabhatta <48771326+somabhatta@users.noreply.github.com> Date: Wed, 25 Feb 2026 13:59:50 +0100 Subject: [PATCH 079/347] [PWGCF] Add 2d matrices for decorrelation (#15155) --- .../Tasks/radialFlowDecorr.cxx | 3069 ++++++++++------- 1 file changed, 1906 insertions(+), 1163 deletions(-) diff --git a/PWGCF/EbyEFluctuations/Tasks/radialFlowDecorr.cxx b/PWGCF/EbyEFluctuations/Tasks/radialFlowDecorr.cxx index ce3b6eccf2e..8a6cf4b5f61 100644 --- a/PWGCF/EbyEFluctuations/Tasks/radialFlowDecorr.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/radialFlowDecorr.cxx @@ -78,6 +78,7 @@ struct RadialFlowDecorr { static constexpr int KPiPlus = 211; static constexpr int KKPlus = 321; static constexpr int KProton = 2212; + static constexpr int KNsp = 4; static constexpr float KCentTestMin = 10.f; static constexpr float KCentTestMaxLo = 60.f; @@ -104,6 +105,7 @@ struct RadialFlowDecorr { static constexpr float KEtaAxisMin = -0.8f; static constexpr float KEtaAxisMax = 0.8f; static constexpr int KNbinsPhiFine = 16; + static constexpr int KNbinsPtRes = 50; static constexpr float KPtResMax = 1.f; static constexpr int KNbinsEtaRes = 100; @@ -122,9 +124,16 @@ struct RadialFlowDecorr { static constexpr float KPtHighMax = 5.0f; static constexpr float KPtFullMax = 10.0f; static constexpr float KCentMax = 90; - enum PID { kInclusive = 0, - kCombinedPID, - kNumPID }; + enum PID { + numKInclusive = 0, // Suffix "" + numKPion, // Suffix "_Pi" + numKKaon, // Suffix "_Ka" + numKProton, // Suffix "_Pr" + numKNumPID // Total: 4 + }; + + const std::vector pidSuffix = {"", "_Pi", "_Ka", "_Pr"}; + enum ECentralityEstimator { kCentFT0C = 1, kCentFT0A = 2, @@ -138,8 +147,6 @@ struct RadialFlowDecorr { kpp = 4 }; static constexpr float KinvalidCentrality = -1.0f; - const std::vector pidSuffix = {"", "_PID"}; - const std::vector etaLw = { -0.8, -0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.1, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7}; @@ -208,12 +215,12 @@ struct RadialFlowDecorr { AxisSpec nChAxis{1, 0., 1., "Nch", "Nch"}; AxisSpec nChAxis2{1, 0., 1., "Nch", "Nch"}; - const AxisSpec vzAxis{5, -12.5, 12.5, - "Vz" - "Vz"}; + const AxisSpec vzAxis{5, -12.5, 12.5, "Vz"}; const AxisSpec chgAxis{3, -1.5, 1.5}; - ConfigurableAxis cfgpTAxis{"cfgpTAxis", {0.0, 0.2, 0.5, 1, 3, 5, 7.5, 10}, "pT axis for flattening"}; - const AxisSpec pTAxis{cfgpTAxis, "pT"}; + const AxisSpec pTAxis{{0.0, 0.2, 0.5, 1, 3, 5, 7.5, 10}, "pT Axis"}; + const AxisSpec etaAxis{{-0.9, -0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.1, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9}, "Eta"}; + const AxisSpec gapAxis{{-1.55, -1.45, -1.35, -1.25, -1.15, -1.05, -0.95, -0.85, -0.75, -0.65, -0.55, -0.45, -0.35, -0.25, -0.15, -0.05, 0.05, 0.15, 0.25, 0.35, 0.45, 0.55, 0.65, 0.75, 0.85, 0.95, 1.05, 1.15, 1.25, 1.35, 1.45, 1.55}, "Gaps"}; + const AxisSpec sumAxis{{-0.775, -0.725, -0.675, -0.625, -0.575, -0.525, -0.475, -0.425, -0.375, -0.325, -0.275, -0.225, -0.175, -0.125, -0.075, -0.025, 0.025, 0.075, 0.125, 0.175, 0.225, 0.275, 0.325, 0.375, 0.425, 0.475, 0.525, 0.575, 0.625, 0.675, 0.725, 0.775}, "Sums"}; Configurable cfgRunGetEff{"cfgRunGetEff", false, "Run MC pass to build efficiency/fake maps"}; Configurable cfgRunGetMCFlat{"cfgRunGetMCFlat", false, "Run MC to Get Flattening Weights"}; @@ -227,27 +234,21 @@ struct RadialFlowDecorr { Service pdg; HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; - std::array hEff{}; - std::array hFake{}; - std::array hFlatWeight{}; - - TProfile3D* pmeanTruNchEtabinPtbinStep2 = nullptr; - TProfile3D* pmeanRecoNchEtabinPtbinStep2 = nullptr; - TProfile3D* pmeanRecoEffcorrNchEtabinPtbinStep2 = nullptr; + std::array hEff{}; + std::array hFake{}; + std::array hFlatWeight{}; - TProfile3D* pmeanEtTruNchEtabinPtbinStep2 = nullptr; - TProfile3D* pmeanEtRecoNchEtabinPtbinStep2 = nullptr; - TProfile3D* pmeanEtRecoEffcorrNchEtabinPtbinStep2 = nullptr; + std::array pmeanTruNchEtabinPtbinStep2{}; + std::array pmeanRecoNchEtabinPtbinStep2{}; + std::array pmeanRecoEffcorrNchEtabinPtbinStep2{}; - TProfile3D* pmeanMultTruNchEtabinPtbinStep2 = nullptr; - TProfile3D* pmeanMultRecoNchEtabinPtbinStep2 = nullptr; - TProfile3D* pmeanMultRecoEffcorrNchEtabinPtbinStep2 = nullptr; + std::array pmeanMultTruNchEtabinPtbinStep2{}; + std::array pmeanMultRecoNchEtabinPtbinStep2{}; + std::array pmeanMultRecoEffcorrNchEtabinPtbinStep2{}; - TProfile3D* pmeanNchEtabinPtbinStep2 = nullptr; - TProfile3D* pmeanEtNchEtabinPtbinStep2 = nullptr; - TProfile3D* pmeanMultNchEtabinPtbinStep2 = nullptr; + std::array pmeanNchEtabinPtbinStep2{}; + std::array pmeanMultNchEtabinPtbinStep2{}; - // Helper to calculate all three combined PID sigmas at once template static std::tuple getAllCombinedNSigmas(const T& candidate) { @@ -267,10 +268,6 @@ struct RadialFlowDecorr { return false; if (cfgEvSelkNoSameBunchPileup && !col.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) return false; - if (cfgEvSelkNoITSROFrameBorder && !col.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) - return false; - if (cfgEvSelkNoTimeFrameBorder && !col.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) - return false; if (cfgIsGoodZvtxFT0VsPV && !col.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) return false; @@ -570,12 +567,17 @@ struct RadialFlowDecorr { histos.add("hPt", ";p_{T} (GeV/c)", kTH1F, {{KNbinsPt, KPtMin, KPtMax}}); histos.add("hEta", ";#eta", kTH1F, {{KNbinsEta, KEtaMin, KEtaMax}}); histos.add("hPhi", ";#phi", kTH1F, {{KNbinsPhi, KPhiMin, TwoPI}}); - - histos.add("hEtaPhiReco", "hEtaPhiReco", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); - histos.add("hEtaPhiReco_PID", "hEtaPhiReco_PID", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); } void declareMCCommonHists() { + for (const auto& suf : pidSuffix) { + histos.add("h3_AllPrimary" + suf, ";N_{PV};p_{T};#eta", kTH3F, {{nChAxis2}, {KNbinsPtRes, cfgPtMin, cfgPtMax}, {KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); + histos.add("h3_RecoMatchedToPrimary" + suf, ";N_{PV};p_{T};#eta", kTH3F, {{nChAxis2}, {KNbinsPtRes, cfgPtMin, cfgPtMax}, {KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); + histos.add("h3_AllReco" + suf, ";N_{PV};p_{T};#eta", kTH3F, {{nChAxis2}, {KNbinsPtRes, cfgPtMin, cfgPtMax}, {KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); + histos.add("h3_RecoUnMatchedToPrimary_Secondary" + suf, ";N_{PV};p_{T};#eta", kTH3F, {{nChAxis2}, {KNbinsPtRes, cfgPtMin, cfgPtMax}, {KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); + histos.add("h3_RecoUnMatchedToPrimary_Fake" + suf, ";N_{PV};p_{T};#eta", kTH3F, {{nChAxis2}, {KNbinsPtRes, cfgPtMin, cfgPtMax}, {KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); + histos.add("hTruth_ParticleWeight" + suf, ";cent;p_{T};#eta", kTH3F, {{centAxis1Per}, {KNbinsPtRes, cfgPtMin, cfgPtMax}, {KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); + } histos.add("ptResolution", ";p_{T}^{MC};p_{T}^{MC}-p_{T}^{reco}", kTH2F, {{KNbinsPtRes, cfgPtMin, cfgPtMax}, {KNbinsPtRes, -KPtResMax, KPtResMax}}); histos.add("ptTruthReco", ";p_{T}^{MC};p_{T}^{reco}", kTH2F, {{KNbinsPtRes, cfgPtMin, cfgPtMax}, {KNbinsPtRes, cfgPtMin, cfgPtMax}}); @@ -584,27 +586,12 @@ struct RadialFlowDecorr { histos.add("TruthTracKVz", ";Vz^{MC};Vz^{Reco}", kTH2F, {{KNbinsVz, KVzMin, KVzMax}, {KNbinsVz, KVzMin, KVzMax}}); histos.add("vzResolution", ";Vz^{MC};Vz^{MC}-Vz^{Reco}", kTH2F, {{KNbinsVz, KVzMin, KVzMax}, {KNbinsVz, -KVzResMax, KVzResMax}}); - histos.add("h3_AllPrimary", ";N_{PV};p_{T};#eta", kTH3F, {{nChAxis2}, {KNbinsPtRes, cfgPtMin, cfgPtMax}, {KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); - histos.add("h3_RecoMatchedToPrimary", ";N_{PV};p_{T};#eta", kTH3F, {{nChAxis2}, {KNbinsPtRes, cfgPtMin, cfgPtMax}, {KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); - histos.add("h3_RecoUnMatchedToPrimary_Secondary", ";N_{PV};p_{T};#eta", kTH3F, {{nChAxis2}, {KNbinsPtRes, cfgPtMin, cfgPtMax}, {KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); - histos.add("h3_RecoUnMatchedToPrimary_Fake", ";N_{PV};p_{T};#eta", kTH3F, {{nChAxis2}, {KNbinsPtRes, cfgPtMin, cfgPtMax}, {KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); - histos.add("h3_AllReco", ";N_{PV};p_{T};#eta", kTH3F, {{nChAxis2}, {KNbinsPtRes, cfgPtMin, cfgPtMax}, {KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); - - histos.add("h3_AllPrimary_PID", ";N_{PV};p_{T};#eta", kTH3F, {{nChAxis2}, {KNbinsPtRes, cfgPtMin, cfgPtMax}, {KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); - histos.add("h3_RecoMatchedToPrimary_PID", ";N_{PV};p_{T};#eta", kTH3F, {{nChAxis2}, {KNbinsPtRes, cfgPtMin, cfgPtMax}, {KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); - histos.add("h3_RecoUnMatchedToPrimary_Secondary_PID", ";N_{PV};p_{T};#eta", kTH3F, {{nChAxis2}, {KNbinsPtRes, cfgPtMin, cfgPtMax}, {KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); - histos.add("h3_RecoUnMatchedToPrimary_Fake_PID", ";N_{PV};p_{T};#eta", kTH3F, {{nChAxis2}, {KNbinsPtRes, cfgPtMin, cfgPtMax}, {KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); - histos.add("h3_AllReco_PID", ";N_{PV};p_{T};#eta", kTH3F, {{nChAxis2}, {KNbinsPtRes, cfgPtMin, cfgPtMax}, {KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); - histos.add("h_AllPrimary", ";p_{T}", kTH1F, {{KNbinsPtRes, cfgPtMin, cfgPtMax}}); histos.add("h_RecoMatchedToPrimary", ";p_{T}", kTH1F, {{KNbinsPtRes, cfgPtMin, cfgPtMax}}); histos.add("h_RecoUnMatchedToPrimary", ";p_{T}", kTH1F, {{KNbinsPtRes, cfgPtMin, cfgPtMax}}); histos.add("h_AllReco", ";p_{T}", kTH1F, {{KNbinsPtRes, cfgPtMin, cfgPtMax}}); histos.add("h_AllRecoEffCorr", ";p_{T}", kTH1F, {{KNbinsPtRes, cfgPtMin, cfgPtMax}}); - histos.add("hReco_ParticleWeight", ";cent;p_{T};#eta", kTH3F, {{centAxis1Per}, {KNbinsPtRes, cfgPtMin, cfgPtMax}, {KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); - histos.add("hTruth_ParticleWeight", ";cent;p_{T};#eta", kTH3F, {{centAxis1Per}, {KNbinsPtRes, cfgPtMin, cfgPtMax}, {KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); - histos.add("hDCAxy_Unmatched", ";DCA_{xy} (cm)", kTH1F, {{KNbinsDca, -KDcaMax, KDcaMax}}); histos.add("hDCAz_Unmatched", ";DCA_{z} (cm)", kTH1F, {{KNbinsDca, -KDcaMax, KDcaMax}}); histos.add("hDCAxy_NotPrimary", ";DCA_{xy} (cm)", kTH1F, {{KNbinsDca, -KDcaMax, KDcaMax}}); @@ -617,10 +604,15 @@ struct RadialFlowDecorr { void declareMCGetFlatHists() { - histos.add("hEtaPhiRecoWtd", "hEtaPhiRecoWtd", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); - histos.add("hEtaPhiRecoEffWtd", "hEtaPhiRecoEffWtd", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); - histos.add("hEtaPhiRecoWtd_PID", "hEtaPhiRecoWtd_PID", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); - histos.add("hEtaPhiRecoEffWtd_PID", "hEtaPhiRecoEffWtd_PID", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); + for (const auto& suf : pidSuffix) { + std::string nameEff = "hEtaPhiReco" + suf; + std::string nameWtd = "hEtaPhiRecoWtd" + suf; + std::string nameEffWtd = "hEtaPhiRecoEffWtd" + suf; + + histos.add(nameEffWtd, nameEffWtd.c_str(), kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); + histos.add(nameEff, nameEff.c_str(), kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); + histos.add(nameWtd, nameWtd.c_str(), kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); + } } void declareMCMeanHists() @@ -637,151 +629,164 @@ struct RadialFlowDecorr { histos.add("Eff_eta", ";#eta;#epsilon", kTProfile, {{KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); histos.add("Fake_eta", ";#eta;f_{fake}", kTProfile, {{KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); histos.add("wgt_eta", ";#eta;w", kTProfile, {{KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); - histos.add("hEtaPhiRecoWtd", "hEtaPhiRecoWtd", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); - histos.add("hEtaPhiRecoEffWtd", "hEtaPhiRecoEffWtd", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); - histos.add("hEtaPhiRecoWtd_PID", "hEtaPhiRecoWtd_PID", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); - histos.add("hEtaPhiRecoEffWtd_PID", "hEtaPhiRecoEffWtd_PID", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); - // MC mean profiles (pT & Et) for various selections - histos.add("MCGen/Prof_cent_Nchrec", ";cent;#LT N_{PV}#GT", kTProfile, {centAxis1Per}); + for (const auto& suf : pidSuffix) { + // Basic Profiles + histos.add("MCGen/Prof_Cent_Nchrec" + suf, ";cent;#LT N_{PV}#GT", kTProfile, {centAxis1Per}); + histos.add("MCGen/Prof_Mult_Nchrec" + suf, ";N_{PV};#LT N_{PV}#GT", kTProfile, {nChAxis}); - histos.add("MCGen/Prof_Cent_MeanpT", ";cent;#LT p_{T}#GT", kTProfile, {centAxis1Per}); - histos.add("MCGen/Prof_Mult_MeanpT", ";N_{PV};#LT p_{T}#GT", kTProfile, {nChAxis}); + histos.add("MCGen/Prof_Cent_MeanpT" + suf, ";cent;#LT p_{T}#GT", kTProfile, {centAxis1Per}); + histos.add("MCGen/Prof_Mult_MeanpT" + suf, ";N_{PV};#LT p_{T}#GT", kTProfile, {nChAxis}); - histos.add("pmeanTruNchEtabinPtbin", ";N_{PV};#eta; p_{T}", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("pmeanRecoNchEtabinPtbin", ";N_{PV};#eta; p_{T}", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("pmeanRecoEffcorrNchEtabinPtbin", ";N_{PV};#eta; p_{T}", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); + histos.add("pmeanTruNchEtabinPtbin" + suf, ";N_{PV};#eta bin;p_{T} bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); + histos.add("pmeanRecoNchEtabinPtbin" + suf, ";N_{PV};#eta bin;p_{T} bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); + histos.add("pmeanRecoEffcorrNchEtabinPtbin" + suf, ";N_{PV};#eta bin;p_{T} bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("MCGen/Prof_Cent_MeanEt", ";cent;#LT E_{T}#GT", kTProfile, {centAxis1Per}); - histos.add("MCGen/Prof_Mult_MeanEt", ";N_{PV};#LT E_{T}#GT", kTProfile, {nChAxis}); + histos.add("pmeanMultTruNchEtabinPtbin" + suf, ";N_{PV};#eta bin;p_{T} bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); + histos.add("pmeanMultRecoNchEtabinPtbin" + suf, ";N_{PV};#eta bin;p_{T} bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); + histos.add("pmeanMultRecoEffcorrNchEtabinPtbin" + suf, ";N_{PV};#eta bin;p_{T} bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); + + for (const int& i : {0, 1, 2}) { + std::string ptTag = "_ipt" + std::to_string(i); + histos.add("Prof2D_MeanpT_Sub" + ptTag + "_Tru" + suf, ";cent;etaA;etaB", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}}); + histos.add("Prof2D_MeanpT_Sub" + ptTag + "_Reco" + suf, ";cent;etaA;etaB", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}}); + histos.add("Prof2D_MeanpT_Sub" + ptTag + "_RecoEffCorr" + suf, ";cent;etaA;etaB", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}}); + } + } - histos.add("pmeanEtTruNchEtabinPtbin", ";N_{PV};#eta; p_{T}", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("pmeanEtRecoNchEtabinPtbin", ";N_{PV};#eta; p_{T}", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("pmeanEtRecoEffcorrNchEtabinPtbin", ";N_{PV};#eta; p_{T}", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); + for (const auto& suf : pidSuffix) { + std::string nameEff = "hEtaPhiReco" + suf; + std::string nameWtd = "hEtaPhiRecoWtd" + suf; + std::string nameEffWtd = "hEtaPhiRecoEffWtd" + suf; - histos.add("pmeanMultTruNchEtabinPtbin", ";N_{PV};#eta; p_{T}", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("pmeanMultRecoNchEtabinPtbin", ";N_{PV};#eta; p_{T}", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("pmeanMultRecoEffcorrNchEtabinPtbin", ";N_{PV};#eta; p_{T}", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); + histos.add(nameEffWtd, nameEffWtd.c_str(), kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); + histos.add(nameEff, nameEff.c_str(), kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); + histos.add(nameWtd, nameWtd.c_str(), kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); + } } void declareMCFlucHists() { - // Full Event Calc - histos.add("MCGen/Prof_Cent_MeanpT_etabin_ptbin", ";cent;#eta-bin; p_{T}-bin", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("MCGen/Prof_Cent_MeanEt_etabin_ptbin", ";cent;#eta-bin; p_{T}-bin", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("MCGen/Prof_Mult_MeanpT_etabin_ptbin", ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis2}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("MCGen/Prof_Mult_MeanEt_etabin_ptbin", ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis2}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - - histos.add("MCGen/Prof_Cent_C2_etabin_ptbin", ";cent;#eta-bin; p_{T}-bin", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("MCGen/Prof_Cent_C2Et_etabin_ptbin", ";cent;#eta-bin; p_{T}-bin", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("MCGen/Prof_C2_Mult_etabin_ptbin", ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis2}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("MCGen/Prof_C2Et_Mult_etabin_ptbin", ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis2}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - - // Sub Event Calc - histos.add("MCGen/Prof_C2Sub_Cent_etabin_ptbin", ";Centrality;#eta-bin; p_{T}-bin", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("MCGen/Prof_C2EtSub_Cent_etabin_ptbin", ";Centrality;#eta-bin; p_{T}-bin", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("MCGen/Prof_C2Sub_Mult_etabin_ptbin", ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis2}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("MCGen/Prof_C2EtSub_Mult_etabin_ptbin", ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis2}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - - histos.add("MCGen/Prof_Cov_Cent_etabin_ptbin", ";cent;#eta-bin; p_{T}-bin", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("MCGen/Prof_Cov_Mult_etabin_ptbin", ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis2}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - - // Sub Event 2D Calc - histos.add("MCGen/Prof_ipt0_C2Sub2D_Cent_etaA_etaC", ";cent;#eta_{A};#eta_{C}", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}}); - histos.add("MCGen/Prof_ipt1_C2Sub2D_Cent_etaA_etaC", ";cent;#eta_{A};#eta_{C}", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}}); - histos.add("MCGen/Prof_ipt2_C2Sub2D_Cent_etaA_etaC", ";cent;#eta_{A};#eta_{C}", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}}); - histos.add("MCGen/Prof_ipt0_C2EtSub2D_Cent_etaA_etaC", ";cent;#eta_{A};#eta_{C}", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}}); - histos.add("MCGen/Prof_ipt1_C2EtSub2D_Cent_etaA_etaC", ";cent;#eta_{A};#eta_{C}", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}}); - histos.add("MCGen/Prof_ipt2_C2EtSub2D_Cent_etaA_etaC", ";cent;#eta_{A};#eta_{C}", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}}); - - histos.add("MCGen/Prof_ipt0_Cov2D_Cent_etaA_etaC", ";cent;#eta_{A};#eta_{C}", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}}); - histos.add("MCGen/Prof_ipt1_Cov2D_Cent_etaA_etaC", ";cent;#eta_{A};#eta_{C}", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}}); - histos.add("MCGen/Prof_ipt2_Cov2D_Cent_etaA_etaC", ";cent;#eta_{A};#eta_{C}", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}}); - - histos.add("MCGen/Prof_cent_Nchrec", ";cent;#LT N_{PV}#GT", kTProfile, {centAxis1Per}); - histos.add("MCGen/Prof_Cent_MeanpT", ";cent;#LT p_{T}#GT", kTProfile, {centAxis1Per}); - histos.add("MCGen/Prof_Cent_MeanEt", ";cent;#LT E_{T}#GT", kTProfile, {centAxis1Per}); - - histos.add("MCGen/Prof_Mult_MeanpT", ";N_{PV};#LT p_{T}#GT", kTProfile, {nChAxis}); - histos.add("MCGen/Prof_Mult_MeanEt", ";N_{PV};#LT E_{T}#GT", kTProfile, {nChAxis}); - - histos.add("hEtaPhiRecoWtd", "hEtaPhiRecoWtd", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); - histos.add("hEtaPhiRecoEffWtd", "hEtaPhiRecoEffWtd", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); - histos.add("hEtaPhiRecoWtd_PID", "hEtaPhiRecoWtd_PID", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); - histos.add("hEtaPhiRecoEffWtd_PID", "hEtaPhiRecoEffWtd_PID", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); + + for (const auto& suf : pidSuffix) { + // --- 1D Full Event Calc Profiles --- + histos.add("MCGen/Prof_MeanpT_Cent_etabin_ptbin" + suf, ";cent;#eta-bin; p_{T}-bin", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); + histos.add("MCGen/Prof_MeanpT_Mult_etabin_ptbin" + suf, ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); + + histos.add("MCGen/Prof_C2_Cent_etabin_ptbin" + suf, ";cent;#eta-bin; p_{T}-bin", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); + histos.add("MCGen/Prof_C2_Mult_etabin_ptbin" + suf, ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); + + // --- 1D Sub-Event Covariances --- + histos.add("MCGen/Prof_C2Sub_Cent_etabin_ptbin" + suf, ";Centrality;#eta-bin; p_{T}-bin", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); + histos.add("MCGen/Prof_C2Sub_Mult_etabin_ptbin" + suf, ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); + + histos.add("MCGen/Prof_Cov_Cent_etabin_ptbin" + suf, ";Centrality;#eta-bin; p_{T}-bin", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); + histos.add("MCGen/Prof_Cov_Mult_etabin_ptbin" + suf, ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); + + for (const int& i : {0, 1, 2}) { + std::string ptTag = "_ipt" + std::to_string(i); + histos.add("MCGen/Prof" + ptTag + "_C2Sub2D_Cent_etaA_etaC" + suf, ";cent;#eta_{A};#eta_{B}", kTProfile3D, {{centAxis1Per}, {etaAxis}, {etaAxis}}); + histos.add("MCGen/Prof" + ptTag + "_Cov2D_Cent_etaA_etaC" + suf, ";cent;#eta_{A};#eta_{B}", kTProfile3D, {{centAxis1Per}, {etaAxis}, {etaAxis}}); + histos.add("MCGen/Prof" + ptTag + "_GapSum2D" + suf, ";cent;#Delta#eta (Gap);#Sigma#eta/2 (Sum)", kTProfile3D, {{centAxis1Per}, {gapAxis}, {sumAxis}}); + } + + std::string nameEff = "hEtaPhiReco" + suf; + std::string nameWtd = "hEtaPhiRecoWtd" + suf; + std::string nameEffWtd = "hEtaPhiRecoEffWtd" + suf; + histos.add(nameEffWtd, nameEffWtd.c_str(), kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); + histos.add(nameEff, nameEff.c_str(), kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); + histos.add(nameWtd, nameWtd.c_str(), kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); + + histos.add("MCGen/Prof_Cent_Nchrec" + suf, ";cent;#LT N_{PV}#GT", kTProfile, {centAxis1Per}); + histos.add("MCGen/Prof_Mult_Nchrec" + suf, ";N_{PV};#LT N_{PV}#GT", kTProfile, {nChAxis}); + histos.add("MCGen/Prof_Cent_MeanpT" + suf, ";cent;#LT p_{T}#GT", kTProfile, {centAxis1Per}); + histos.add("MCGen/Prof_Mult_MeanpT" + suf, ";N_{PV};#LT p_{T}#GT", kTProfile, {nChAxis}); + } } void declareDataGetFlatHists() { - histos.add("hEtaPhiRecoWtd", "hEtaPhiRecoWtd", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); - histos.add("hEtaPhiRecoEffWtd", "hEtaPhiRecoEffWtd", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); - histos.add("hEtaPhiRecoWtd_PID", "hEtaPhiRecoWtd_PID", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); - histos.add("hEtaPhiRecoEffWtd_PID", "hEtaPhiRecoEffWtd_PID", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); + // 1. Species-dependent Sparse Histograms + for (const auto& suf : pidSuffix) { + std::string nameEff = "hEtaPhiReco" + suf; + std::string nameWtd = "hEtaPhiRecoWtd" + suf; + std::string nameEffWtd = "hEtaPhiRecoEffWtd" + suf; + + histos.add(nameEffWtd, nameEffWtd.c_str(), kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); + histos.add(nameEff, nameEff.c_str(), kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); + histos.add(nameWtd, nameWtd.c_str(), kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); + } - histos.add("hnTrkPVZDC", ";ZDC_{A+C};N_{PV}", kTH2F, {{nChAxis2}, {200, 0, 3000}}); - histos.add("hNchZDC", ";ZDC_{A+C};N_{trk}", kTH2F, {{nChAxis2}, {200, 0, 30000}}); + histos.add("hnTrkPVZDC", ";N_{PV};ZDC_{A+C}", kTH2F, {{nChAxis2}, {200, 0, 3000}}); + histos.add("hNchZDC", ";N_{trk};ZDC_{A+C}", kTH2F, {{nChAxis2}, {200, 0, 30000}}); histos.add("hCentnTrk", ";Centrality (%);N_{trk}", kTH2F, {{centAxis1Per}, {nChAxis2}}); - histos.add("hCentnTrkPV", ";Centrality (%),N_{trk, PV}", kTH2F, {{centAxis1Per}, {nChAxis2}}); + histos.add("hCentnTrkPV", ";Centrality (%);N_{trk, PV}", kTH2F, {{centAxis1Per}, {nChAxis2}}); } void declareDataMeanHists() { - histos.add("hEtaPhiRecoWtd", "hEtaPhiRecoWtd", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); - histos.add("hEtaPhiRecoEffWtd", "hEtaPhiRecoEffWtd", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); - histos.add("hEtaPhiRecoWtd_PID", "hEtaPhiRecoWtd_PID", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); - histos.add("hEtaPhiRecoEffWtd_PID", "hEtaPhiRecoEffWtd_PID", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); - - histos.add("Prof_cent_Nchrec", ";cent;#LT N_{PV}#GT", kTProfile, {centAxis1Per}); - histos.add("Prof_Cent_MeanpT", ";cent;#LT p_{T}#GT", kTProfile, {centAxis1Per}); - histos.add("Prof_Cent_MeanEt", ";cent;#LT E_{T}#GT", kTProfile, {centAxis1Per}); - - histos.add("pmean_nch_etabin_ptbin", ";N_{PV};#eta-bin;p_{T}-bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("pmeanEt_nch_etabin_ptbin", ";N_{PV};#eta-bin;p_{T}-bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("pmeanMult_nch_etabin_ptbin", ";N_{PV};#eta-bin;p_{T}-bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - - histos.add("pmean_cent_etabin_ptbin", ";Centrality (%) ;#eta-bin;p_{T}-bin", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("pmeanEt_cent_etabin_ptbin", ";Centrality (%) ;#eta-bin;p_{T}-bin", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("pmeanMult_cent_etabin_ptbin", ";Centrality (%) ;#eta-bin;p_{T}-bin", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); + for (const auto& suf : pidSuffix) { + std::string nameReco = "hEtaPhiReco" + suf; + std::string nameWtd = "hEtaPhiRecoWtd" + suf; + std::string nameEffWtd = "hEtaPhiRecoEffWtd" + suf; + + histos.add(nameReco, nameReco.c_str(), kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); + histos.add(nameWtd, nameWtd.c_str(), kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); + histos.add(nameEffWtd, nameEffWtd.c_str(), kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); + + histos.add("Prof_Cent_Nchrec" + suf, ";cent;#LT N_{PV}#GT", kTProfile, {centAxis1Per}); + histos.add("Prof_Mult_Nchrec" + suf, ";N_{PV};#LT N_{PV}#GT", kTProfile, {nChAxis}); + histos.add("Prof_Cent_MeanpT" + suf, ";cent;#LT p_{T}#GT", kTProfile, {centAxis1Per}); + + histos.add("pmean_nch_etabin_ptbin" + suf, ";N_{PV};#eta-bin;p_{T}-bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); + histos.add("pmeanMult_nch_etabin_ptbin" + suf, ";N_{PV};#eta-bin;p_{T}-bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); + + histos.add("pmean_cent_etabin_ptbin" + suf, ";Centrality (%) ;#eta-bin;p_{T}-bin", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); + histos.add("pmeanMult_cent_etabin_ptbin" + suf, ";Centrality (%) ;#eta-bin;p_{T}-bin", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); + + for (const int& i : {0, 1, 2}) { + std::string ptTag = "_ipt" + std::to_string(i); + std::string histName = "Prof2D_MeanpT_Sub" + ptTag + suf; + histos.add(histName, ";cent;#eta_{A} bin;#eta_{B} bin", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}}); + } + } } void declareDataFlucHists() { - histos.add("hEtaPhiRecoWtd", "hEtaPhiRecoWtd", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); - histos.add("hEtaPhiRecoEffWtd", "hEtaPhiRecoEffWtd", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); - histos.add("hEtaPhiRecoWtd_PID", "hEtaPhiRecoWtd_PID", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); - histos.add("hEtaPhiRecoEffWtd_PID", "hEtaPhiRecoEffWtd_PID", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); - - // Full Event Calc - histos.add("Prof_Cent_MeanpT_etabin_ptbin", ";cent;#eta-bin; p_{T}-bin", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("Prof_Cent_MeanEt_etabin_ptbin", ";cent;#eta-bin; p_{T}-bin", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("Prof_Mult_MeanpT_etabin_ptbin", ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis2}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("Prof_Mult_MeanEt_etabin_ptbin", ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis2}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - - histos.add("Prof_Cent_C2_etabin_ptbin", ";cent;#eta-bin; p_{T}-bin", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("Prof_Cent_C2Et_etabin_ptbin", ";cent;#eta-bin; p_{T}-bin", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("Prof_C2_Mult_etabin_ptbin", ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis2}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("Prof_C2Et_Mult_etabin_ptbin", ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis2}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - - // Sub Event Calc - histos.add("Prof_C2Sub_Cent_etabin_ptbin", ";Centrality;#eta-bin; p_{T}-bin", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("Prof_C2EtSub_Cent_etabin_ptbin", ";Centrality;#eta-bin; p_{T}-bin", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("Prof_C2Sub_Mult_etabin_ptbin", ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis2}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("Prof_C2EtSub_Mult_etabin_ptbin", ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis2}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("Prof_Cov_Cent_etabin_ptbin", ";Centrality;#eta-bin; p_{T}-bin", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("Prof_Cov_Mult_etabin_ptbin", ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis2}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - - // Sub Event 2D Calc - histos.add("Prof_ipt0_C2Sub2D_Cent_etaA_etaC", ";cent;#eta_{A};#eta_{C}", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}}); - histos.add("Prof_ipt1_C2Sub2D_Cent_etaA_etaC", ";cent;#eta_{A};#eta_{C}", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}}); - histos.add("Prof_ipt2_C2Sub2D_Cent_etaA_etaC", ";cent;#eta_{A};#eta_{C}", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}}); - histos.add("Prof_ipt0_C2EtSub2D_Cent_etaA_etaC", ";cent;#eta_{A};#eta_{C}", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}}); - histos.add("Prof_ipt1_C2EtSub2D_Cent_etaA_etaC", ";cent;#eta_{A};#eta_{C}", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}}); - histos.add("Prof_ipt2_C2EtSub2D_Cent_etaA_etaC", ";cent;#eta_{A};#eta_{C}", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}}); - - histos.add("Prof_ipt0_Cov2D_Cent_etaA_etaC", ";cent;#eta_{A};#eta_{C}", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}}); - histos.add("Prof_ipt1_Cov2D_Cent_etaA_etaC", ";cent;#eta_{A};#eta_{C}", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}}); - histos.add("Prof_ipt2_Cov2D_Cent_etaA_etaC", ";cent;#eta_{A};#eta_{C}", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}}); + for (const auto& suf : pidSuffix) { + + // --- THnSparse QA Histograms --- + std::string nameReco = "hEtaPhiReco" + suf; + std::string nameEff = "hEtaPhiRecoEffWtd" + suf; + std::string nameWtd = "hEtaPhiRecoWtd" + suf; + + histos.add(nameReco, nameReco.c_str(), kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); + histos.add(nameEff, nameEff.c_str(), kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); + histos.add(nameWtd, nameWtd.c_str(), kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); + + // --- 1D Full Event Calc Profiles --- + histos.add("Prof_MeanpT_Cent_etabin_ptbin" + suf, ";cent;#eta-bin; p_{T}-bin", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); + histos.add("Prof_MeanpT_Mult_etabin_ptbin" + suf, ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); + + histos.add("Prof_C2_Cent_etabin_ptbin" + suf, ";cent;#eta-bin; p_{T}-bin", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); + histos.add("Prof_C2_Mult_etabin_ptbin" + suf, ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); + + // --- 1D Sub-Event Covariances --- + histos.add("Prof_C2Sub_Cent_etabin_ptbin" + suf, ";Centrality;#eta-bin; p_{T}-bin", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); + histos.add("Prof_C2Sub_Mult_etabin_ptbin" + suf, ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); + + histos.add("Prof_Cov_Cent_etabin_ptbin" + suf, ";Centrality;#eta-bin; p_{T}-bin", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); + histos.add("Prof_Cov_Mult_etabin_ptbin" + suf, ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); + + for (const int& i : {0, 1, 2}) { + std::string ptTag = "_ipt" + std::to_string(i); + histos.add("Prof" + ptTag + "_C2Sub2D_Cent_etaA_etaC" + suf, ";cent;#eta_{A};#eta_{C}", kTProfile3D, {{centAxis1Per}, {etaAxis}, {etaAxis}}); + histos.add("Prof" + ptTag + "_GapSum2D" + suf, ";cent;#Delta#eta (Gap);#Sigma#eta/2 (Sum)", kTProfile3D, {{centAxis1Per}, {gapAxis}, {sumAxis}}); + histos.add("Prof" + ptTag + "_Cov2D_Cent_etaA_etaC" + suf, ";cent;#eta_{A} bin;#eta_{C} bin", kTProfile3D, {{centAxis1Per}, {etaAxis}, {etaAxis}}); + } + } } THnSparseF* buildWeightMapFromRaw(THnSparseF* hRaw, const char* mapName) @@ -853,12 +858,15 @@ struct RadialFlowDecorr { void init(InitContext&) { - if (cfgSys == 1) { - nChAxis = {cfgNchPbMax / 5, KBinOffset, cfgNchPbMax + KBinOffset, "Nch", "PV-contributor track multiplicity"}; - nChAxis2 = {cfgNchPbMax / 100, KBinOffset, cfgNchPbMax + KBinOffset, "Nch", "PV-contributor track multiplicity"}; + if (cfgSys == kPbPb) { + nChAxis = {cfgNchPbMax / 4, KBinOffset, cfgNchPbMax + KBinOffset, "Nch", "PV-contributor track multiplicity"}; + nChAxis2 = {cfgNchPbMax / 20, KBinOffset, cfgNchPbMax + KBinOffset, "Nch", "PV-contributor track multiplicity"}; + } else if (cfgSys == kOO || cfgSys == kpPb) { + nChAxis = {cfgNchOMax / 2, KBinOffset, cfgNchOMax + KBinOffset, "Nch", "PV-contributor track multiplicity"}; + nChAxis2 = {cfgNchOMax / 5, KBinOffset, cfgNchOMax + KBinOffset, "Nch", "PV-contributor track multiplicity"}; } else { - nChAxis = {cfgNchOMax / 10, KBinOffset, cfgNchOMax + KBinOffset, "Nch", "PV-contributor track multiplicity"}; - nChAxis2 = {cfgNchOMax / 30, KBinOffset, cfgNchOMax + KBinOffset, "Nch", "PV-contributor track multiplicity"}; + nChAxis = {cfgNchOMax / 2, KBinOffset, cfgNchOMax + KBinOffset, "Nch", "PV-contributor track multiplicity"}; + nChAxis2 = {cfgNchOMax / 5, KBinOffset, cfgNchOMax + KBinOffset, "Nch", "PV-contributor track multiplicity"}; } ccdb->setURL(cfgCCDBurl.value); @@ -939,7 +947,7 @@ struct RadialFlowDecorr { LOGF(fatal, "Efficiency maps required but CCDB list is null at %s!", pathEff.c_str()); } - LOGF(info, "Loading Eff/Fake maps from TList..."); + LOGF(info, "Loading Eff/Fake maps from TList for all species..."); auto loadEffFakeForPID = [&](PID pidType) { std::string suffix = pidSuffix[pidType]; @@ -957,7 +965,7 @@ struct RadialFlowDecorr { hEff[pidType]->SetDirectory(nullptr); hEff[pidType]->Divide(hDen); } else { - LOGF(error, "Missing CCDB objects for efficiency. Checked in list: %s, %s", hEffNumName.c_str(), hEffDenName.c_str()); + LOGF(error, "Missing CCDB objects for efficiency. Checked: %s, %s", hEffNumName.c_str(), hEffDenName.c_str()); } auto* hNumS = reinterpret_cast(lst->FindObject(hFakeNumSecName.c_str())); @@ -974,59 +982,75 @@ struct RadialFlowDecorr { } }; - loadEffFakeForPID(kInclusive); - loadEffFakeForPID(kCombinedPID); + // Loop through all PID types: kInclusive, kPion, kKaon, KProton + for (int i = 0; i < PID::numKNumPID; ++i) { + loadEffFakeForPID(static_cast(i)); + } } if (!cfgRunGetEff && (cfgFlat)) { - // --- 1. Load Data Flattening Maps (if DataMean or DataFluc) --- + // --- 1. Load Data Flattening Maps --- if (cfgRunDataMean || cfgRunDataFluc) { - LOGF(info, "Data Run: Loading flattening maps from CCDB path: %s", pathDataFlat.c_str()); - + LOGF(info, "Data Run: Loading flattening maps from %s", pathDataFlat.c_str()); TList* lstDataFlat = ccdb->getForTimeStamp(pathDataFlat, now); if (lstDataFlat) { - auto* hRawIncl = reinterpret_cast(lstDataFlat->FindObject("hEtaPhiRecoEffWtd")); - if (hRawIncl) { - hFlatWeight[kInclusive] = buildWeightMapFromRaw(hRawIncl, "hFlatWeight"); - } else { - LOGF(error, "Data flattening 'hEtaPhiRecoEffWtd' not found in list from %s", pathDataFlat.c_str()); - } + // Use a loop to load species-specific flattening weights if they exist in data + for (int i = 0; i < PID::numKNumPID; ++i) { + std::string suffix = pidSuffix[i]; + std::string hName; + + if (cfgEff && cfgFlat) { + hName = "hEtaPhiRecoWtd" + suffix; + } else if (cfgEff) { + hName = "hEtaPhiRecoEffWtd" + suffix; + } else { + hName = "hEtaPhiReco" + suffix; + } + auto* hRaw = reinterpret_cast(lstDataFlat->FindObject(hName.c_str())); - auto* hRawPID = reinterpret_cast(lstDataFlat->FindObject("hEtaPhiRecoEffWtd_PID")); - if (hRawPID) { - hFlatWeight[kCombinedPID] = buildWeightMapFromRaw(hRawPID, "hFlatWeight_PID"); - } else { - LOGF(error, "Data flattening 'hEtaPhiRecoEffWtd_PID' not found in list from %s", pathDataFlat.c_str()); + if (hRaw) { + hFlatWeight[i] = buildWeightMapFromRaw(hRaw, Form("hFlatWeight%s", suffix.c_str())); + } else { + LOGF(error, "Data flattening map '%s' not found.", hName.c_str()); + } } } else { - LOGF(error, "Could not retrieve TList for Data Flattening from: %s", pathDataFlat.c_str()); + LOGF(error, "Could not retrieve Data Flattening TList from: %s", pathDataFlat.c_str()); } } - // --- 2. Load MC Flattening Maps (if MCMean or MCFluc) --- + // --- 2. Load MC Flattening Maps --- if (cfgRunMCMean || cfgRunMCFluc) { - LOGF(info, "MC Run: Loading flattening maps from MC Flat list (%s)...", pathMCFlat.c_str()); - + LOGF(info, "MC Run: Loading flattening maps from %s", pathMCFlat.c_str()); TList* lstMCFlat = ccdb->getForTimeStamp(pathMCFlat, now); + if (lstMCFlat) { auto loadFlatForPID = [&](PID pidType) { std::string suffix = pidSuffix[pidType]; - std::string hFlatSrcName = "hEtaPhiRecoEffWtd" + suffix; + std::string hFlatSrcName; + if (cfgEff && cfgFlat) { + hFlatSrcName = "hEtaPhiRecoWtd" + suffix; + } else if (cfgEff) { + hFlatSrcName = "hEtaPhiRecoEffWtd" + suffix; + } else { + hFlatSrcName = "hEtaPhiReco" + suffix; + } auto* hRaw = reinterpret_cast(lstMCFlat->FindObject(hFlatSrcName.c_str())); if (hRaw) { hFlatWeight[pidType] = buildWeightMapFromRaw(hRaw, Form("hFlatWeight%s", suffix.c_str())); } else { - LOGF(warning, "MC flattening source '%s' not found in list; skipping this PID.", hFlatSrcName.c_str()); + LOGF(warning, "MC flattening source '%s' not found in list.", hFlatSrcName.c_str()); } }; - loadFlatForPID(kInclusive); - loadFlatForPID(kCombinedPID); + for (int i = 0; i < PID::numKNumPID; ++i) { + loadFlatForPID(static_cast(i)); + } } else { - LOGF(error, "Could not retrieve TList for MC Flattening from: %s", pathMCFlat.c_str()); + LOGF(error, "Could not retrieve MC Flattening TList from: %s", pathMCFlat.c_str()); } } } @@ -1050,18 +1074,16 @@ struct RadialFlowDecorr { TList* lstMCMean = ccdb->getForTimeStamp(pathMCMean, now); if (lstMCMean) { - loadTProfile3DFromList(lstMCMean, "pmeanTruNchEtabinPtbin", pmeanTruNchEtabinPtbinStep2); - loadTProfile3DFromList(lstMCMean, "pmeanRecoNchEtabinPtbin", pmeanRecoNchEtabinPtbinStep2); - loadTProfile3DFromList(lstMCMean, "pmeanRecoEffcorrNchEtabinPtbin", pmeanRecoEffcorrNchEtabinPtbinStep2); - - loadTProfile3DFromList(lstMCMean, "pmeanEtTruNchEtabinPtbin", pmeanEtTruNchEtabinPtbinStep2); - loadTProfile3DFromList(lstMCMean, "pmeanEtRecoNchEtabinPtbin", pmeanEtRecoNchEtabinPtbinStep2); - loadTProfile3DFromList(lstMCMean, "pmeanEtRecoEffcorrNchEtabinPtbin", pmeanEtRecoEffcorrNchEtabinPtbinStep2); - - loadTProfile3DFromList(lstMCMean, "pmeanMultTruNchEtabinPtbin", pmeanMultTruNchEtabinPtbinStep2); - loadTProfile3DFromList(lstMCMean, "pmeanMultRecoNchEtabinPtbin", pmeanMultRecoNchEtabinPtbinStep2); - loadTProfile3DFromList(lstMCMean, "pmeanMultRecoEffcorrNchEtabinPtbin", pmeanMultRecoEffcorrNchEtabinPtbinStep2); - + for (int isp = 0; isp < KNsp; ++isp) { + std::string suf = pidSuffix[isp]; + loadTProfile3DFromList(lstMCMean, ("pmeanTruNchEtabinPtbin" + suf).c_str(), pmeanTruNchEtabinPtbinStep2[isp]); + loadTProfile3DFromList(lstMCMean, ("pmeanRecoNchEtabinPtbin" + suf).c_str(), pmeanRecoNchEtabinPtbinStep2[isp]); + loadTProfile3DFromList(lstMCMean, ("pmeanRecoEffcorrNchEtabinPtbin" + suf).c_str(), pmeanRecoEffcorrNchEtabinPtbinStep2[isp]); + + loadTProfile3DFromList(lstMCMean, ("pmeanMultTruNchEtabinPtbin" + suf).c_str(), pmeanMultTruNchEtabinPtbinStep2[isp]); + loadTProfile3DFromList(lstMCMean, ("pmeanMultRecoNchEtabinPtbin" + suf).c_str(), pmeanMultRecoNchEtabinPtbinStep2[isp]); + loadTProfile3DFromList(lstMCMean, ("pmeanMultRecoEffcorrNchEtabinPtbin" + suf).c_str(), pmeanMultRecoEffcorrNchEtabinPtbinStep2[isp]); + } } else { LOGF(error, "Could not retrieve TList for MC Mean from: %s", pathMCMean.c_str()); } @@ -1072,9 +1094,11 @@ struct RadialFlowDecorr { TList* lstDataMean = ccdb->getForTimeStamp(pathDataMean, now); if (lstDataMean) { - loadTProfile3DFromList(lstDataMean, "pmean_nch_etabin_ptbin", pmeanNchEtabinPtbinStep2); - loadTProfile3DFromList(lstDataMean, "pmeanEt_nch_etabin_ptbin", pmeanEtNchEtabinPtbinStep2); - loadTProfile3DFromList(lstDataMean, "pmeanMult_nch_etabin_ptbin", pmeanMultNchEtabinPtbinStep2); + for (int isp = 0; isp < KNsp; ++isp) { + std::string suf = pidSuffix[isp]; + loadTProfile3DFromList(lstDataMean, ("pmean_nch_etabin_ptbin" + suf).c_str(), pmeanNchEtabinPtbinStep2[isp]); + loadTProfile3DFromList(lstDataMean, ("pmeanMult_nch_etabin_ptbin" + suf).c_str(), pmeanMultNchEtabinPtbinStep2[isp]); + } } else { LOGF(error, "Could not retrieve TList for Data Mean from: %s", pathDataMean.c_str()); } @@ -1082,7 +1106,7 @@ struct RadialFlowDecorr { LOGF(info, "CCDB initialization complete for RadialFlowDecorr."); } - void processGetEffHists(aod::McCollisions const& mcColl, soa::SmallGroups const& collisions, TCs const& tracks, FilteredTCs const& /*filteredTracks*/, aod::McParticles const& mcParticles) + void processGetEffHists(aod::McCollisions const& mcColl, MyRun3MCCollisions const& collisions, /*soa::SmallGroups const& collisions,*/ TCs const& tracks, FilteredTCs const& /*filteredTracks*/, aod::McParticles const& mcParticles) { for (const auto& mcCollision : mcColl) { auto colSlice = collisions.sliceBy(colPerMcCollision, mcCollision.globalIndex()); @@ -1097,123 +1121,131 @@ struct RadialFlowDecorr { continue; auto trackSlice = tracks.sliceBy(trackPerCollision, col.globalIndex()); - if (trackSlice.size() < 1) - continue; - auto partSlice = mcParticles.sliceBy(partPerMcCollision, mcCollision.globalIndex()); - if (partSlice.size() < 1) + if (trackSlice.size() < 1 || partSlice.size() < 1) continue; float cent = getCentrality(col); if (cent > KCentMax) continue; + float multPV = col.multNTracksPV(); histos.fill(HIST("hZvtx_after_sel"), col.posZ()); - histos.fill(HIST("hCentrality"), cent); - histos.fill(HIST("Hist2D_globalTracks_PVTracks"), col.multNTracksPV(), tracks.size()); - histos.fill(HIST("Hist2D_cent_nch"), col.multNTracksPV(), cent); + histos.fill(HIST("Hist2D_globalTracks_PVTracks"), multPV, tracks.size()); + histos.fill(HIST("Hist2D_cent_nch"), multPV, cent); + // --- Denominator: Truth Particles --- for (const auto& particle : partSlice) { - if (!isParticleSelected(particle)) - continue; - if (!particle.isPhysicalPrimary()) + if (!isParticleSelected(particle) || !particle.isPhysicalPrimary()) continue; const int absPdgId = std::abs(particle.pdgCode()); - const bool isPion = (absPdgId == KPiPlus); - const bool isKaon = (absPdgId == KKPlus); - const bool isProton = (absPdgId == KProton); - const bool isPid = (isPion || isKaon || isProton); - - histos.fill(HIST("hTruth_ParticleWeight"), cent, particle.pt(), particle.eta(), particle.weight()); - histos.fill(HIST("h3_AllPrimary"), col.multNTracksPV(), particle.pt(), particle.eta()); - histos.fill(HIST("h_AllPrimary"), particle.pt()); - - if (isPid) { - histos.fill(HIST("h3_AllPrimary_PID"), col.multNTracksPV(), particle.pt(), particle.eta()); + float pt = particle.pt(); + float eta = particle.eta(); + float w = particle.weight(); + + // Inclusive (Denominator) + histos.fill(HIST("hTruth_ParticleWeight"), cent, pt, eta, w); + histos.fill(HIST("h3_AllPrimary"), multPV, pt, eta); + histos.fill(HIST("h_AllPrimary"), pt); + + // Species Specific Denominators + if (absPdgId == KPiPlus) { + histos.fill(HIST("hTruth_ParticleWeight_Pi"), cent, pt, eta, w); + histos.fill(HIST("h3_AllPrimary_Pi"), multPV, pt, eta); + } else if (absPdgId == KKPlus) { + histos.fill(HIST("hTruth_ParticleWeight_Ka"), cent, pt, eta, w); + histos.fill(HIST("h3_AllPrimary_Ka"), multPV, pt, eta); + } else if (absPdgId == KProton) { + histos.fill(HIST("hTruth_ParticleWeight_Pr"), cent, pt, eta, w); + histos.fill(HIST("h3_AllPrimary_Pr"), multPV, pt, eta); } } - histos.fill(HIST("TruthTracKVz"), mcCollision.posZ(), col.posZ()); - histos.fill(HIST("vzResolution"), mcCollision.posZ(), mcCollision.posZ() - col.posZ()); - // Reconstructed + // --- Numerator and Fakes: Reconstructed Tracks --- for (const auto& track : trackSlice) { if (!isTrackSelected(track)) continue; - const bool isPion = selectionPion(track); - const bool isKaon = selectionKaon(track); - const bool isProton = selectionProton(track); - const bool isPid = (isPion || isKaon || isProton); - histos.fill(HIST("hP"), track.p()); - histos.fill(HIST("hPt"), track.pt()); - histos.fill(HIST("hEta"), track.eta()); - histos.fill(HIST("hPhi"), track.phi()); - histos.fill(HIST("h_AllReco"), track.pt()); - - histos.fill(HIST("h3_AllReco"), col.multNTracksPV(), track.pt(), track.eta()); - histos.fill(HIST("hEtaPhiReco"), col.posZ(), track.sign(), track.pt(), track.eta(), track.phi()); - - histos.fill(HIST("hDCAxy_Reco"), track.dcaXY()); - histos.fill(HIST("hDCAz_Reco"), track.dcaZ()); - if (isPid) { - histos.fill(HIST("h3_AllReco_PID"), col.multNTracksPV(), track.pt(), track.eta()); - histos.fill(HIST("hEtaPhiReco_PID"), col.posZ(), track.sign(), track.pt(), track.eta(), track.phi()); + float pt = track.pt(); + float eta = track.eta(); + float phi = track.phi(); + + bool isPi = selectionPion(track); + bool isKa = selectionKaon(track); + bool isPr = selectionProton(track); + + // Inclusive QA + histos.fill(HIST("h_AllReco"), pt); + histos.fill(HIST("h3_AllReco"), multPV, pt, eta); + histos.fill(HIST("hEtaPhiReco"), col.posZ(), track.sign(), pt, eta, phi); + + // Species QA (Fills based on your PID selection) + if (isPi) { + histos.fill(HIST("h3_AllReco_Pi"), multPV, pt, eta); + } + if (isKa) { + histos.fill(HIST("h3_AllReco_Ka"), multPV, pt, eta); + } + if (isPr) { + histos.fill(HIST("h3_AllReco_Pr"), multPV, pt, eta); } if (track.has_mcParticle()) { auto mcPart2 = track.mcParticle(); + const int absPdgId = std::abs(mcPart2.pdgCode()); + if (mcPart2.isPhysicalPrimary()) { - const int absPdgId = std::abs(mcPart2.pdgCode()); - const bool isPionTrue = (absPdgId == kPiPlus); - const bool isKaonTrue = (absPdgId == kKPlus); - const bool isProtonTrue = (absPdgId == kProton); - const bool isPidTrue = (isPionTrue || isKaonTrue || isProtonTrue); - - histos.fill(HIST("hReco_ParticleWeight"), cent, mcPart2.pt(), mcPart2.eta(), mcPart2.weight()); - histos.fill(HIST("ptResolution"), mcPart2.pt(), mcPart2.pt() - track.pt()); - histos.fill(HIST("ptTruthReco"), mcPart2.pt(), track.pt()); - histos.fill(HIST("etaResolution"), mcPart2.eta(), mcPart2.eta() - track.eta()); - histos.fill(HIST("etaTruthReco"), mcPart2.eta(), track.eta()); - histos.fill(HIST("h3_RecoMatchedToPrimary"), col.multNTracksPV(), mcPart2.pt(), mcPart2.eta()); - histos.fill(HIST("h_RecoMatchedToPrimary"), mcPart2.pt()); - - histos.fill(HIST("hDCAxy_RecoMatched"), track.dcaXY()); - histos.fill(HIST("hDCAz_RecoMatched"), track.dcaZ()); - - if (isPid && isPidTrue) { - histos.fill(HIST("h3_RecoMatchedToPrimary_PID"), col.multNTracksPV(), mcPart2.pt(), mcPart2.eta()); - } + + histos.fill(HIST("ptResolution"), mcPart2.pt(), (pt - mcPart2.pt()) / mcPart2.pt()); + histos.fill(HIST("etaResolution"), mcPart2.eta(), eta - mcPart2.eta()); + histos.fill(HIST("etaTruthReco"), mcPart2.eta(), eta); + histos.fill(HIST("vzResolution"), mcPart2.vz(), (col.posZ() - mcPart2.vz()) / mcPart2.vz()); + histos.fill(HIST("TruthTracKVz"), mcPart2.vz(), col.posZ()); + + // Reconstructed Numerator (Inclusive) + histos.fill(HIST("h3_RecoMatchedToPrimary"), multPV, mcPart2.pt(), mcPart2.eta()); + histos.fill(HIST("h_RecoMatchedToPrimary"), pt); + + // Species Matching (Efficiency Numerator) + // We fill ONLY if the reconstructed PID matches the Truth PDG + if (isPi && absPdgId == KPiPlus) + histos.fill(HIST("h3_RecoMatchedToPrimary_Pi"), multPV, mcPart2.pt(), mcPart2.eta()); + if (isKa && absPdgId == KKPlus) + histos.fill(HIST("h3_RecoMatchedToPrimary_Ka"), multPV, mcPart2.pt(), mcPart2.eta()); + if (isPr && absPdgId == KProton) + histos.fill(HIST("h3_RecoMatchedToPrimary_Pr"), multPV, mcPart2.pt(), mcPart2.eta()); } else { - // Matched to secondary - histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary"), col.multNTracksPV(), track.pt(), track.eta()); - histos.fill(HIST("h_RecoUnMatchedToPrimary"), track.pt()); - histos.fill(HIST("hDCAxy_Unmatched"), track.dcaXY()); - histos.fill(HIST("hDCAz_Unmatched"), track.dcaZ()); - if (isPid) { - histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_PID"), col.multNTracksPV(), track.pt(), track.eta()); - } + // Secondary (Contamination) + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary"), multPV, pt, eta); + histos.fill(HIST("h_RecoUnMatchedToPrimary"), pt); + if (isPi) + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_Pi"), multPV, pt, eta); + if (isKa) + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_Ka"), multPV, pt, eta); + if (isPr) + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_Pr"), multPV, pt, eta); } } else { - // Fake track - histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake"), col.multNTracksPV(), track.pt(), track.eta()); - histos.fill(HIST("h_RecoUnMatchedToPrimary"), track.pt()); - histos.fill(HIST("hDCAxy_NotPrimary"), track.dcaXY()); - histos.fill(HIST("hDCAz_NotPrimary"), track.dcaZ()); - if (isPid) { - histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_PID"), col.multNTracksPV(), track.pt(), track.eta()); - } + // Fake Tracks (No MC matching) + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake"), multPV, pt, eta); + if (isPi) + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_Pi"), multPV, pt, eta); + if (isKa) + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_Ka"), multPV, pt, eta); + if (isPr) + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_Pr"), multPV, pt, eta); } - } // tracks - } // cols - } // mcColl + } + } + } LOGF(info, "FINISHED RUNNING processGetEffHists"); } PROCESS_SWITCH(RadialFlowDecorr, processGetEffHists, "process MC to calculate Eff and Fakes", cfgRunGetEff); - void processMCFlat(aod::McCollisions const& mcColl, soa::SmallGroups const& collisions, TCs const& tracks, FilteredTCs const& /*filteredTracks*/, aod::McParticles const& mcParticles) + void processMCFlat(aod::McCollisions const& mcColl, MyRun3MCCollisions const& collisions, /*soa::SmallGroups const& collisions,*/ TCs const& tracks, FilteredTCs const& /*filteredTracks*/, aod::McParticles const& mcParticles) { for (const auto& mcCollision : mcColl) { auto colSlice = collisions.sliceBy(colPerMcCollision, mcCollision.globalIndex()); @@ -1221,384 +1253,550 @@ struct RadialFlowDecorr { continue; for (const auto& col : colSlice) { - if (!col.has_mcCollision()) - continue; - if (!isEventSelected(col)) + if (!col.has_mcCollision() || !isEventSelected(col)) continue; - auto trackSlice = tracks.sliceBy(trackPerCollision, col.globalIndex()); - if (trackSlice.size() < 1) - continue; - auto partSlice = mcParticles.sliceBy(partPerMcCollision, mcCollision.globalIndex()); - if (partSlice.size() < 1) + if (trackSlice.size() < 1 || partSlice.size() < 1) continue; - float cent = getCentrality(col); - if (cent > KCentMax) - continue; + float multPV = col.multNTracksPV(); + float vz = col.posZ(); - // Reconstructed for (const auto& track : trackSlice) { if (!isTrackSelected(track)) continue; - float effIncl = getEfficiency(col.multNTracksPV(), track.pt(), track.eta(), kInclusive, 0, cfgEff); - float fakeIncl = getEfficiency(col.multNTracksPV(), track.pt(), track.eta(), kInclusive, 1, cfgEff); + float pt = track.pt(); + float eta = track.eta(); + float phi = track.phi(); + auto sign = track.sign(); + + // 1. Inclusive Weighting (Always filled for selected tracks) + float effIncl = getEfficiency(multPV, pt, eta, numKInclusive, 0, cfgEff); + float fakeIncl = getEfficiency(multPV, pt, eta, numKInclusive, 1, cfgEff); float wIncl = (1.0 - fakeIncl) / effIncl; - if (!std::isfinite(wIncl) || wIncl <= 0.f) - continue; - if (effIncl <= 0 || !std::isfinite(effIncl) || !std::isfinite(fakeIncl)) - continue; - histos.fill(HIST("hEtaPhiRecoEffWtd"), col.posZ(), track.sign(), track.pt(), track.eta(), track.phi(), wIncl); - const bool isPion = selectionPion(track); - const bool isKaon = selectionKaon(track); - const bool isProton = selectionProton(track); - const bool isPid = (isPion || isKaon || isProton); - float effPid = getEfficiency(col.multNTracksPV(), track.pt(), track.eta(), kCombinedPID, 0, cfgEff); - float fakePid = getEfficiency(col.multNTracksPV(), track.pt(), track.eta(), kCombinedPID, 1, cfgEff); - float wPid = (1.0 - fakePid) / effPid; - if (effPid >= 1 || fakePid >= 1 || !std::isfinite(effPid) || effPid <= KFloatEpsilon || !std::isfinite(fakePid)) - continue; - if (isPid) { - histos.fill(HIST("hEtaPhiRecoEffWtd_PID"), col.posZ(), track.sign(), track.pt(), track.eta(), track.phi(), wPid); + if (std::isfinite(wIncl) && wIncl > 0.f && effIncl > KFloatEpsilon) { + histos.fill(HIST("hEtaPhiRecoEffWtd"), vz, sign, pt, eta, phi, wIncl); + histos.fill(HIST("hEtaPhiReco"), vz, sign, pt, eta, phi, 1.0); } - } // tracks - } // cols - } // mcColl + + // 2. Pion Weighting + if (selectionPion(track)) { + float effPi = getEfficiency(multPV, pt, eta, numKPion, 0, cfgEff); + float fakePi = getEfficiency(multPV, pt, eta, numKPion, 1, cfgEff); + float wPi = (1.0 - fakePi) / effPi; + if (std::isfinite(wPi) && wPi > 0.f && effPi > KFloatEpsilon) { + histos.fill(HIST("hEtaPhiRecoEffWtd_Pi"), vz, sign, pt, eta, phi, wPi); + histos.fill(HIST("hEtaPhiReco_Pi"), vz, sign, pt, eta, phi, 1.0); + } + } + + // 3. Kaon Weighting + if (selectionKaon(track)) { + float effKa = getEfficiency(multPV, pt, eta, numKKaon, 0, cfgEff); + float fakeKa = getEfficiency(multPV, pt, eta, numKKaon, 1, cfgEff); + float wKa = (1.0 - fakeKa) / effKa; + if (std::isfinite(wKa) && wKa > 0.f && effKa > KFloatEpsilon) { + histos.fill(HIST("hEtaPhiRecoEffWtd_Ka"), vz, sign, pt, eta, phi, wKa); + histos.fill(HIST("hEtaPhiReco_Ka"), vz, sign, pt, eta, phi, 1.0); + } + } + + // 4. Proton Weighting + if (selectionProton(track)) { + float effPr = getEfficiency(multPV, pt, eta, numKProton, 0, cfgEff); + float fakePr = getEfficiency(multPV, pt, eta, numKProton, 1, cfgEff); + float wPr = (1.0 - fakePr) / effPr; + if (std::isfinite(wPr) && wPr > 0.f && effPr > KFloatEpsilon) { + histos.fill(HIST("hEtaPhiRecoEffWtd_Pr"), vz, sign, pt, eta, phi, wPr); + histos.fill(HIST("hEtaPhiReco_Pr"), vz, sign, pt, eta, phi, 1.0); + } + } + } // end track loop + } // end col loop + } // end mcColl loop LOGF(info, "FINISHED RUNNING processMCFlat"); } PROCESS_SWITCH(RadialFlowDecorr, processMCFlat, "process MC to calculate FlatWeights", cfgRunGetMCFlat); void processMCMean(aod::McCollisions const& mcColl, MyRun3MCCollisions const& collisions, TCs const& tracks, FilteredTCs const& /*filteredTracks*/, aod::McParticles const& mcParticles) { - float sumWiTruth[KNEta][KNpT], sumWiptiTruth[KNEta][KNpT]; - float sumWiReco[KNEta][KNpT], sumWiptiReco[KNEta][KNpT]; - float sumWiRecoEffCorr[KNEta][KNpT], sumWiptiRecoEffCorr[KNEta][KNpT]; - float sumWiTruthEt[KNEta][KNpT], sumWiptiTruthEt[KNEta][KNpT]; - float sumWiRecoEt[KNEta][KNpT], sumWiptiRecoEt[KNEta][KNpT]; - float sumWiRecoEffCorrEt[KNEta][KNpT], sumWiptiRecoEffCorrEt[KNEta][KNpT]; + // Track-sum arrays using KNsp index (isp=0: Incl, 1: Pi, 2: Ka, 3: Pr) + double sumWiTruth[KNsp][KNEta][KNpT]{}, sumWiptiTruth[KNsp][KNEta][KNpT]{}; + double sumWiReco[KNsp][KNEta][KNpT]{}, sumWiptiReco[KNsp][KNEta][KNpT]{}; + double sumWiRecoEffCorr[KNsp][KNEta][KNpT]{}, sumWiptiRecoEffCorr[KNsp][KNEta][KNpT]{}; for (const auto& mcCollision : mcColl) { auto colSlice = collisions.sliceBy(colPerMcCollision, mcCollision.globalIndex()); - if (colSlice.size() != 1) continue; + for (const auto& col : colSlice) { - if (!col.has_mcCollision()) - continue; - if (!isEventSelected(col)) - continue; - histos.fill(HIST("hVtxZ"), col.posZ()); - auto trackSlice = tracks.sliceBy(trackPerCollision, col.globalIndex()); - if (trackSlice.size() < 1) + if (!col.has_mcCollision() || !isEventSelected(col)) continue; + auto trackSlice = tracks.sliceBy(trackPerCollision, col.globalIndex()); auto partSlice = mcParticles.sliceBy(partPerMcCollision, mcCollision.globalIndex()); - if (partSlice.size() < 1) + if (trackSlice.size() < 1 || partSlice.size() < 1) continue; float cent = getCentrality(col); if (cent > KCentMax) continue; + float multPV = col.multNTracksPV(); + float vz = col.posZ(); - histos.fill(HIST("hZvtx_after_sel"), col.posZ()); - histos.fill(HIST("hCentrality"), cent); - histos.fill(HIST("Hist2D_globalTracks_PVTracks"), col.multNTracksPV(), tracks.size()); - histos.fill(HIST("Hist2D_cent_nch"), col.multNTracksPV(), cent); - histos.fill(HIST("TruthTracKVz"), mcCollision.posZ(), col.posZ()); - histos.fill(HIST("vzResolution"), mcCollision.posZ(), mcCollision.posZ() - col.posZ()); - + // Reset local event sum memset(sumWiTruth, 0, sizeof(sumWiTruth)); memset(sumWiptiTruth, 0, sizeof(sumWiptiTruth)); memset(sumWiReco, 0, sizeof(sumWiReco)); memset(sumWiptiReco, 0, sizeof(sumWiptiReco)); memset(sumWiRecoEffCorr, 0, sizeof(sumWiRecoEffCorr)); memset(sumWiptiRecoEffCorr, 0, sizeof(sumWiptiRecoEffCorr)); - memset(sumWiTruthEt, 0, sizeof(sumWiTruthEt)); - memset(sumWiptiTruthEt, 0, sizeof(sumWiptiTruthEt)); - memset(sumWiRecoEt, 0, sizeof(sumWiRecoEt)); - memset(sumWiptiRecoEt, 0, sizeof(sumWiptiRecoEt)); - memset(sumWiRecoEffCorrEt, 0, sizeof(sumWiRecoEffCorrEt)); - memset(sumWiptiRecoEffCorrEt, 0, sizeof(sumWiptiRecoEffCorrEt)); - - // Truth + + // --- 1. Truth Loop --- for (const auto& particle : partSlice) { - if (!isParticleSelected(particle)) - continue; - if (!particle.isPhysicalPrimary()) + if (!isParticleSelected(particle) || !particle.isPhysicalPrimary()) continue; - + float pt = particle.pt(), eta = particle.eta(); const int absPdgId = std::abs(particle.pdgCode()); - const bool isPion = (absPdgId == kPiPlus); - const bool isKaon = (absPdgId == kKPlus); - const bool isProton = (absPdgId == kProton); - - float pt = particle.pt(); - float eta = particle.eta(); - float p = particle.p(); - + bool isSpecies[KNsp] = {true, (absPdgId == KPiPlus), (absPdgId == KKPlus), (absPdgId == KProton)}; for (int ieta = 0; ieta < KNEta; ++ieta) { if (eta <= etaLw[ieta] || eta > etaUp[ieta]) continue; for (int ipt = 0; ipt < KNpT; ++ipt) { if (pt <= pTLw[ipt] || pt > pTUp[ipt]) continue; - sumWiTruth[ieta][ipt]++; - sumWiptiTruth[ieta][ipt] += pt; - if (isPion || isKaon || isProton) { - float m = isPion ? o2::constants::physics::MassPiPlus : isKaon ? o2::constants::physics::MassKPlus - : o2::constants::physics::MassProton; - float energy = std::sqrt(p * p + m * m); - float et = energy * (pt / p); // E_T = E * sin(theta) = E * (pT / p) - sumWiTruthEt[ieta][ipt]++; - sumWiptiTruthEt[ieta][ipt] += et; + for (int isp = 0; isp < KNsp; ++isp) { + if (isSpecies[isp]) { + sumWiTruth[isp][ieta][ipt]++; + sumWiptiTruth[isp][ieta][ipt] += pt; + } } } } } - for (const auto& track : trackSlice) { - if (!isTrackSelected(track)) - continue; + for (int isp = 0; isp < KNsp; ++isp) { + if (isp == numKInclusive) { + histos.fill(HIST("MCGen/Prof_Cent_Nchrec"), cent, sumWiTruth[0][0][0]); + histos.fill(HIST("MCGen/Prof_Mult_Nchrec"), multPV, sumWiTruth[0][0][0]); + if (sumWiTruth[0][0][0] > 1.0f) { + histos.fill(HIST("MCGen/Prof_Cent_MeanpT"), cent, sumWiptiTruth[0][0][0] / sumWiTruth[0][0][0]); + histos.fill(HIST("MCGen/Prof_Mult_MeanpT"), multPV, sumWiptiTruth[0][0][0] / sumWiTruth[0][0][0]); + } - float pt = track.pt(); - float eta = track.eta(); - float p = track.p(); - float phi = track.phi(); + } else if (isp == numKPion) { + histos.fill(HIST("MCGen/Prof_Cent_Nchrec_Pi"), cent, sumWiTruth[1][0][0]); + histos.fill(HIST("MCGen/Prof_Mult_Nchrec_Pi"), multPV, sumWiTruth[1][0][0]); - histos.fill(HIST("hEtaPhiReco"), col.posZ(), track.sign(), track.pt(), eta, phi); + if (sumWiTruth[1][0][0] > 1.0f) { + histos.fill(HIST("MCGen/Prof_Cent_MeanpT_Pi"), cent, sumWiptiTruth[1][0][0] / sumWiTruth[1][0][0]); + histos.fill(HIST("MCGen/Prof_Mult_MeanpT_Pi"), multPV, sumWiptiTruth[1][0][0] / sumWiTruth[1][0][0]); + } - float effIncl = getEfficiency(col.multNTracksPV(), pt, eta, kInclusive, 0, cfgEff); - float fakeIncl = getEfficiency(col.multNTracksPV(), pt, eta, kInclusive, 1, cfgEff); - float flatWeightIncl = getFlatteningWeight(col.posZ(), track.sign(), pt, eta, phi, kInclusive, cfgFlat); - float wIncl = flatWeightIncl * (1.0 - fakeIncl) / effIncl; - if (!std::isfinite(wIncl) || wIncl <= 0.f) - continue; - if (effIncl <= 0 || !std::isfinite(effIncl) || !std::isfinite(fakeIncl) || !std::isfinite(flatWeightIncl)) - continue; - histos.fill(HIST("hEtaPhiRecoWtd"), col.posZ(), track.sign(), pt, eta, phi, flatWeightIncl); - histos.fill(HIST("hEtaPhiRecoEffWtd"), col.posZ(), track.sign(), pt, eta, phi, wIncl); + } else if (isp == numKKaon) { + histos.fill(HIST("MCGen/Prof_Cent_Nchrec_Ka"), cent, sumWiTruth[2][0][0]); + histos.fill(HIST("MCGen/Prof_Mult_Nchrec_Ka"), multPV, sumWiTruth[2][0][0]); - for (int ieta = 0; ieta < KNEta; ++ieta) { - if (eta <= etaLw[ieta] || eta > etaUp[ieta]) - continue; - for (int ipt = 0; ipt < KNpT; ++ipt) { - if (pt <= pTLw[ipt] || pt > pTUp[ipt]) - continue; - sumWiReco[ieta][ipt] += 1.0; - sumWiptiReco[ieta][ipt] += pt; + if (sumWiTruth[2][0][0] > 1.0f) { + histos.fill(HIST("MCGen/Prof_Cent_MeanpT_Ka"), cent, sumWiptiTruth[2][0][0] / sumWiTruth[2][0][0]); + histos.fill(HIST("MCGen/Prof_Mult_MeanpT_Ka"), multPV, sumWiptiTruth[2][0][0] / sumWiTruth[2][0][0]); } - } - - if (!std::isfinite(wIncl) || !std::isfinite(fakeIncl) || !std::isfinite(flatWeightIncl)) - continue; + } else if (isp == numKProton) { + histos.fill(HIST("MCGen/Prof_Cent_Nchrec_Pr"), cent, sumWiTruth[3][0][0]); + histos.fill(HIST("MCGen/Prof_Mult_Nchrec_Pr"), multPV, sumWiTruth[3][0][0]); - for (int ieta = 0; ieta < KNEta; ++ieta) { - if (eta <= etaLw[ieta] || eta > etaUp[ieta]) - continue; - for (int ipt = 0; ipt < KNpT; ++ipt) { - if (pt <= pTLw[ipt] || pt > pTUp[ipt]) - continue; - sumWiRecoEffCorr[ieta][ipt] += wIncl; - sumWiptiRecoEffCorr[ieta][ipt] += wIncl * pt; + if (sumWiTruth[3][0][0] > 1.0f) { + histos.fill(HIST("MCGen/Prof_Cent_MeanpT_Pr"), cent, sumWiptiTruth[3][0][0] / sumWiTruth[3][0][0]); + histos.fill(HIST("MCGen/Prof_Mult_MeanpT_Pr"), multPV, sumWiptiTruth[3][0][0] / sumWiTruth[3][0][0]); } } + } - const bool isPion = selectionPion(track); - const bool isKaon = selectionKaon(track); - const bool isProton = selectionProton(track); - if (isPion || isKaon || isProton) { - histos.fill(HIST("hEtaPhiReco_PID"), col.posZ(), track.sign(), track.pt(), eta, phi); - float effPid = getEfficiency(col.multNTracksPV(), pt, eta, kCombinedPID, 0, cfgEff); - float fakePid = getEfficiency(col.multNTracksPV(), pt, eta, kCombinedPID, 1, cfgEff); - float flatWeightPid = getFlatteningWeight(col.posZ(), track.sign(), pt, eta, phi, kCombinedPID, cfgFlat); - float wPid = flatWeightPid * (1.0 - fakePid) / effPid; - if (!std::isfinite(effPid) || effPid <= KFloatEpsilon || !std::isfinite(fakePid) || !std::isfinite(flatWeightPid)) + // --- 2. Reco Loop --- + for (const auto& track : trackSlice) { + if (!isTrackSelected(track)) + continue; + float pt = track.pt(), eta = track.eta(), phi = track.phi(); + auto sign = track.sign(); + bool isSpecies[KNsp] = {true, selectionPion(track), selectionKaon(track), selectionProton(track)}; + for (int isp = 0; isp < KNsp; ++isp) { + if (!isSpecies[isp]) + continue; + float eff = getEfficiency(multPV, pt, eta, static_cast(isp), 0, cfgEff); + float fake = getEfficiency(multPV, pt, eta, static_cast(isp), 1, cfgEff); + float flatW = getFlatteningWeight(vz, sign, pt, eta, phi, static_cast(isp), cfgFlat); + float w = flatW * (1.0 - fake) / eff; + if (!std::isfinite(w) || w <= 0.f || eff <= KFloatEpsilon) continue; - histos.fill(HIST("hEtaPhiRecoWtd_PID"), col.posZ(), track.sign(), track.pt(), eta, track.phi(), flatWeightPid); - histos.fill(HIST("hEtaPhiRecoEffWtd_PID"), col.posZ(), track.sign(), track.pt(), eta, track.phi(), wPid); - float m = isPion ? o2::constants::physics::MassPiPlus : isKaon ? o2::constants::physics::MassKPlus - : o2::constants::physics::MassProton; - float energy = std::sqrt(p * p + m * m); - float et = energy * (pt / p); // E_T = E * sin(theta) for (int ieta = 0; ieta < KNEta; ++ieta) { if (eta <= etaLw[ieta] || eta > etaUp[ieta]) continue; for (int ipt = 0; ipt < KNpT; ++ipt) { if (pt <= pTLw[ipt] || pt > pTUp[ipt]) continue; - sumWiRecoEt[ieta][ipt] += 1.0; - sumWiptiRecoEt[ieta][ipt] += et; + sumWiReco[isp][ieta][ipt]++; + sumWiptiReco[isp][ieta][ipt] += pt; + sumWiRecoEffCorr[isp][ieta][ipt] += w; + sumWiptiRecoEffCorr[isp][ieta][ipt] += w * pt; + + if (ipt == 0) { + // Fill profiles vs. Centrality + histos.fill(HIST("Eff_cent"), cent, eff); + histos.fill(HIST("Fake_cent"), cent, fake); + histos.fill(HIST("wgt_cent"), cent, w); + + // Fill profiles vs. Multiplicity (Ntrk) + histos.fill(HIST("Eff_Ntrk"), multPV, eff); + histos.fill(HIST("Fake_Ntrk"), multPV, fake); + histos.fill(HIST("wgt_Ntrk"), multPV, w); + + // Fill profiles vs. pT + histos.fill(HIST("Eff_pT"), pt, eff); + histos.fill(HIST("Fake_pT"), pt, fake); + histos.fill(HIST("wgt_pT"), pt, w); + + // Fill profiles vs. Eta + histos.fill(HIST("Eff_eta"), eta, eff); + histos.fill(HIST("Fake_eta"), eta, fake); + histos.fill(HIST("wgt_eta"), eta, w); + } } } - if (!std::isfinite(wPid) || !std::isfinite(fakePid) || !std::isfinite(flatWeightPid)) - continue; + if (isp == numKInclusive) { - for (int ieta = 0; ieta < KNEta; ++ieta) { - if (eta <= etaLw[ieta] || eta > etaUp[ieta]) - continue; - for (int ipt = 0; ipt < KNpT; ++ipt) { - if (pt <= pTLw[ipt] || pt > pTUp[ipt]) - continue; - sumWiRecoEffCorrEt[ieta][ipt] += wPid; - sumWiptiRecoEffCorrEt[ieta][ipt] += wPid * et; - } - } - } + histos.fill(HIST("hEtaPhiReco"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - if (std::isfinite(wIncl)) { - if (cent < KCentTestMin) { - histos.fill(HIST("wgt_pT"), pt, wIncl); - histos.fill(HIST("Eff_pT"), pt, effIncl); - histos.fill(HIST("Fake_pT"), pt, fakeIncl); - histos.fill(HIST("Eff_eta"), eta, effIncl); - histos.fill(HIST("Fake_eta"), eta, fakeIncl); - histos.fill(HIST("wgt_eta"), eta, wIncl); - } - histos.fill(HIST("Eff_cent"), cent, effIncl); - histos.fill(HIST("Eff_Ntrk"), col.multNTracksPV(), effIncl); - histos.fill(HIST("Fake_cent"), cent, fakeIncl); - histos.fill(HIST("Fake_Ntrk"), col.multNTracksPV(), fakeIncl); - histos.fill(HIST("wgt_cent"), cent, wIncl); - histos.fill(HIST("wgt_Ntrk"), col.multNTracksPV(), wIncl); - } + } else if (isp == numKPion) { // Pion + histos.fill(HIST("hEtaPhiReco_Pi"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_Pi"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_Pi"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - } // end track loop + } else if (isp == numKKaon) { // Kaon + histos.fill(HIST("hEtaPhiReco_Ka"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_Ka"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_Ka"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - if (std::isfinite(sumWiTruth[0][0])) { - float meanPtTruth = sumWiptiTruth[0][0] / sumWiTruth[0][0]; - if (!std::isfinite(meanPtTruth)) - LOGF(info, "meanPtTruth = %.3f, num = %.3f, den =%.3f", meanPtTruth, sumWiptiTruth[0][0], sumWiTruth[0][0]); - if (std::isfinite(meanPtTruth)) { - histos.fill(HIST("MCGen/Prof_cent_Nchrec"), cent, sumWiTruth[0][0]); - histos.fill(HIST("MCGen/Prof_Cent_MeanpT"), cent, meanPtTruth); - histos.fill(HIST("MCGen/Prof_Mult_MeanpT"), col.multNTracksPV(), meanPtTruth); - } - } - if (std::isfinite(sumWiReco[0][0])) { - float meanPtReco = sumWiptiReco[0][0] / sumWiReco[0][0]; - if (!std::isfinite(meanPtReco)) - LOGF(info, "meanPtReco = %.3f, num = %.3f, den =%.3f", meanPtReco, sumWiptiReco[0][0], sumWiReco[0][0]); - if (std::isfinite(meanPtReco)) { - histos.fill(HIST("MCReco/Prof_cent_Nchrec"), cent, sumWiReco[0][0]); - histos.fill(HIST("MCReco/Prof_Cent_MeanpT"), cent, meanPtReco); - histos.fill(HIST("MCReco/Prof_Mult_MeanpT"), col.multNTracksPV(), meanPtReco); - } - } - if (std::isfinite(sumWiRecoEffCorr[0][0])) { - float meanpTeffcorr = sumWiptiRecoEffCorr[0][0] / sumWiRecoEffCorr[0][0]; - if (!std::isfinite(meanpTeffcorr)) - LOGF(info, "meanPtRecoEffcorr = %.3f, num = %.3f, den =%.3f", meanpTeffcorr, sumWiptiRecoEffCorr[0][0], sumWiRecoEffCorr[0][0]); - if (std::isfinite(meanpTeffcorr)) { - histos.fill(HIST("MCRecoEffCorr/Prof_cent_Nchrec"), cent, sumWiRecoEffCorr[0][0]); - histos.fill(HIST("MCRecoEffCorr/Prof_Cent_MeanpT"), cent, meanpTeffcorr); - histos.fill(HIST("MCRecoEffCorr/Prof_Mult_MeanpT"), col.multNTracksPV(), meanpTeffcorr); + } else if (isp == numKProton) { // Proton + histos.fill(HIST("hEtaPhiReco_Pr"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_Pr"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_Pr"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } } } - if (std::isfinite(sumWiTruthEt[0][0])) { - float meanEt = sumWiptiTruthEt[0][0] / sumWiTruthEt[0][0]; - if (!std::isfinite(meanEt)) - LOGF(info, "meanEtTruthEt = %.3f, num = %.3f, den =%.3f", meanEt, sumWiptiTruthEt[0][0], sumWiTruthEt[0][0]); - if (std::isfinite(meanEt)) { - histos.fill(HIST("MCGen/Prof_Cent_MeanEt"), cent, meanEt); - histos.fill(HIST("MCGen/Prof_Mult_MeanEt"), col.multNTracksPV(), meanEt); - } - } - // "MCReco" - if (std::isfinite(sumWiRecoEt[0][0])) { - float meanEt = sumWiptiRecoEt[0][0] / sumWiRecoEt[0][0]; - if (!std::isfinite(meanEt)) - LOGF(info, "meanEtRecoEt = %.3f, num = %.3f, den =%.3f", meanEt, sumWiptiRecoEt[0][0], sumWiRecoEt[0][0]); - if (std::isfinite(meanEt)) { - histos.fill(HIST("MCReco/Prof_Cent_MeanEt"), cent, meanEt); - histos.fill(HIST("MCReco/Prof_Mult_MeanEt"), col.multNTracksPV(), meanEt); - } - } - // "MCRecoEffCorr" - if (std::isfinite(sumWiRecoEffCorrEt[0][0])) { - float meanEt = sumWiptiRecoEffCorrEt[0][0] / sumWiRecoEffCorrEt[0][0]; - if (!std::isfinite(meanEt)) - LOGF(info, "meanEtRecoEffcorrEt = %.3f, num = %.3f, den =%.3f", meanEt, sumWiptiRecoEffCorrEt[0][0], sumWiRecoEffCorrEt[0][0]); - if (std::isfinite(meanEt)) { - histos.fill(HIST("MCRecoEffCorr/Prof_Cent_MeanEt"), cent, meanEt); - histos.fill(HIST("MCRecoEffCorr/Prof_Mult_MeanEt"), col.multNTracksPV(), meanEt); + for (int isp = 0; isp < KNsp; ++isp) { + if (isp == numKInclusive) { + histos.fill(HIST("MCReco/Prof_Cent_Nchrec"), cent, sumWiReco[0][0][0]); + histos.fill(HIST("MCReco/Prof_Mult_Nchrec"), multPV, sumWiReco[0][0][0]); + if (sumWiReco[0][0][0] > 1.0f) { + histos.fill(HIST("MCReco/Prof_Cent_MeanpT"), cent, sumWiptiReco[0][0][0] / sumWiReco[0][0][0]); + histos.fill(HIST("MCReco/Prof_Mult_MeanpT"), multPV, sumWiptiReco[0][0][0] / sumWiReco[0][0][0]); + } + + } else if (isp == numKPion) { + histos.fill(HIST("MCReco/Prof_Cent_Nchrec_Pi"), cent, sumWiReco[1][0][0]); + histos.fill(HIST("MCReco/Prof_Mult_Nchrec_Pi"), multPV, sumWiReco[1][0][0]); + + if (sumWiReco[1][0][0] > 1.0f) { + histos.fill(HIST("MCReco/Prof_Cent_MeanpT_Pi"), cent, sumWiptiReco[1][0][0] / sumWiReco[1][0][0]); + histos.fill(HIST("MCReco/Prof_Mult_MeanpT_Pi"), multPV, sumWiptiReco[1][0][0] / sumWiReco[1][0][0]); + } + + } else if (isp == numKKaon) { + histos.fill(HIST("MCReco/Prof_Cent_Nchrec_Ka"), cent, sumWiReco[2][0][0]); + histos.fill(HIST("MCReco/Prof_Mult_Nchrec_Ka"), multPV, sumWiReco[2][0][0]); + + if (sumWiReco[2][0][0] > 1.0f) { + histos.fill(HIST("MCReco/Prof_Cent_MeanpT_Ka"), cent, sumWiptiReco[2][0][0] / sumWiReco[2][0][0]); + histos.fill(HIST("MCReco/Prof_Mult_MeanpT_Ka"), multPV, sumWiptiReco[2][0][0] / sumWiReco[2][0][0]); + } + } else if (isp == numKProton) { + histos.fill(HIST("MCReco/Prof_Cent_Nchrec_Pr"), cent, sumWiReco[3][0][0]); + histos.fill(HIST("MCReco/Prof_Mult_Nchrec_Pr"), multPV, sumWiReco[3][0][0]); + if (sumWiReco[3][0][0] > 1.0f) { + histos.fill(HIST("MCReco/Prof_Cent_MeanpT_Pr"), cent, sumWiptiReco[3][0][0] / sumWiReco[3][0][0]); + histos.fill(HIST("MCReco/Prof_Mult_MeanpT_Pr"), multPV, sumWiptiReco[3][0][0] / sumWiReco[3][0][0]); + } } - } - for (int ieta = 0; ieta < KNEta; ++ieta) { - for (int ipt = 0; ipt < KNpT; ++ipt) { - if (std::isfinite(sumWiTruth[ieta][ipt])) - histos.fill(HIST("pmeanTruNchEtabinPtbin"), col.multNTracksPV(), ieta, ipt, sumWiptiTruth[ieta][ipt] / sumWiTruth[ieta][ipt]); - if (std::isfinite(sumWiReco[ieta][ipt])) - histos.fill(HIST("pmeanRecoNchEtabinPtbin"), col.multNTracksPV(), ieta, ipt, sumWiptiReco[ieta][ipt] / sumWiReco[ieta][ipt]); - if (std::isfinite(sumWiRecoEffCorr[ieta][ipt])) - histos.fill(HIST("pmeanRecoEffcorrNchEtabinPtbin"), col.multNTracksPV(), ieta, ipt, sumWiptiRecoEffCorr[ieta][ipt] / sumWiRecoEffCorr[ieta][ipt]); + if (isp == numKInclusive) { + histos.fill(HIST("MCRecoEffCorr/Prof_Cent_Nchrec"), cent, sumWiRecoEffCorr[0][0][0]); + histos.fill(HIST("MCRecoEffCorr/Prof_Mult_Nchrec"), multPV, sumWiRecoEffCorr[0][0][0]); + if (sumWiRecoEffCorr[0][0][0] > 1.0f) { + histos.fill(HIST("MCRecoEffCorr/Prof_Cent_MeanpT"), cent, sumWiptiRecoEffCorr[0][0][0] / sumWiRecoEffCorr[0][0][0]); + histos.fill(HIST("MCRecoEffCorr/Prof_Mult_MeanpT"), multPV, sumWiptiRecoEffCorr[0][0][0] / sumWiRecoEffCorr[0][0][0]); + } - if (std::isfinite(sumWiTruthEt[ieta][ipt])) { - histos.fill(HIST("pmeanEtTruNchEtabinPtbin"), col.multNTracksPV(), ieta, ipt, sumWiptiTruthEt[ieta][ipt] / sumWiTruthEt[ieta][ipt]); - histos.fill(HIST("pmeanMultTruNchEtabinPtbin"), col.multNTracksPV(), ieta, ipt, sumWiTruthEt[ieta][ipt]); + } else if (isp == numKPion) { + histos.fill(HIST("MCRecoEffCorr/Prof_Cent_Nchrec_Pi"), cent, sumWiRecoEffCorr[1][0][0]); + histos.fill(HIST("MCRecoEffCorr/Prof_Mult_Nchrec_Pi"), multPV, sumWiRecoEffCorr[1][0][0]); + if (sumWiRecoEffCorr[1][0][0] > 1.0f) { + histos.fill(HIST("MCRecoEffCorr/Prof_Cent_MeanpT_Pi"), cent, sumWiptiRecoEffCorr[1][0][0] / sumWiRecoEffCorr[1][0][0]); + histos.fill(HIST("MCRecoEffCorr/Prof_Mult_MeanpT_Pi"), multPV, sumWiptiRecoEffCorr[1][0][0] / sumWiRecoEffCorr[1][0][0]); } - if (std::isfinite(sumWiRecoEt[ieta][ipt])) { - histos.fill(HIST("pmeanEtRecoNchEtabinPtbin"), col.multNTracksPV(), ieta, ipt, sumWiptiRecoEt[ieta][ipt] / sumWiRecoEt[ieta][ipt]); - histos.fill(HIST("pmeanMultRecoNchEtabinPtbin"), col.multNTracksPV(), ieta, ipt, sumWiRecoEt[ieta][ipt]); + + } else if (isp == numKKaon) { + histos.fill(HIST("MCRecoEffCorr/Prof_Cent_Nchrec_Ka"), cent, sumWiRecoEffCorr[2][0][0]); + histos.fill(HIST("MCRecoEffCorr/Prof_Mult_Nchrec_Ka"), multPV, sumWiRecoEffCorr[2][0][0]); + if (sumWiRecoEffCorr[2][0][0] > 1.0f) { + histos.fill(HIST("MCRecoEffCorr/Prof_Cent_MeanpT_Ka"), cent, sumWiptiRecoEffCorr[2][0][0] / sumWiRecoEffCorr[2][0][0]); + histos.fill(HIST("MCRecoEffCorr/Prof_Mult_MeanpT_Ka"), multPV, sumWiptiRecoEffCorr[2][0][0] / sumWiRecoEffCorr[2][0][0]); } - if (std::isfinite(sumWiRecoEffCorrEt[ieta][ipt])) { - histos.fill(HIST("pmeanEtRecoEffcorrNchEtabinPtbin"), col.multNTracksPV(), ieta, ipt, sumWiptiRecoEffCorrEt[ieta][ipt] / sumWiRecoEffCorrEt[ieta][ipt]); - histos.fill(HIST("pmeanMultRecoEffcorrNchEtabinPtbin"), col.multNTracksPV(), ieta, ipt, sumWiRecoEffCorrEt[ieta][ipt]); + } else if (isp == numKProton) { + histos.fill(HIST("MCRecoEffCorr/Prof_Cent_Nchrec_Pr"), cent, sumWiRecoEffCorr[3][0][0]); + histos.fill(HIST("MCRecoEffCorr/Prof_Mult_Nchrec_Pr"), multPV, sumWiRecoEffCorr[3][0][0]); + if (sumWiRecoEffCorr[3][0][0] > 1.0f) { + histos.fill(HIST("MCRecoEffCorr/Prof_Cent_MeanpT_Pr"), cent, sumWiptiRecoEffCorr[3][0][0] / sumWiRecoEffCorr[3][0][0]); + histos.fill(HIST("MCRecoEffCorr/Prof_Mult_MeanpT_Pr"), multPV, sumWiptiRecoEffCorr[3][0][0] / sumWiRecoEffCorr[3][0][0]); } } } - } // end col loop + + for (int ietaA = 0; ietaA < KNEta; ++ietaA) { + for (int ietaB = 0; ietaB < KNEta; ++ietaB) { + for (int ipt = 0; ipt < KNpT; ++ipt) { + for (int isp = 0; isp < KNsp; ++isp) { + + // 1. Truth Sub-event Mean + double nTruAB = sumWiTruth[isp][ietaA][ipt] + sumWiTruth[isp][ietaB][ipt]; + if (nTruAB > 0) { + float mptsubTru = (sumWiptiTruth[isp][ietaA][ipt] + sumWiptiTruth[isp][ietaB][ipt]) / nTruAB; + if (isp == numKInclusive) { // Inclusive + if (ipt == 0) + histos.fill(HIST("Prof2D_MeanpT_Sub_ipt0_Tru"), cent, ietaA, ietaB, mptsubTru); + if (ipt == KNpT - 2) + histos.fill(HIST("Prof2D_MeanpT_Sub_ipt1_Tru"), cent, ietaA, ietaB, mptsubTru); + if (ipt == KNpT - 1) + histos.fill(HIST("Prof2D_MeanpT_Sub_ipt2_Tru"), cent, ietaA, ietaB, mptsubTru); + } else if (isp == numKPion) { // Pion + if (ipt == 0) + histos.fill(HIST("Prof2D_MeanpT_Sub_ipt0_Tru_Pi"), cent, ietaA, ietaB, mptsubTru); + if (ipt == KNpT - 2) + histos.fill(HIST("Prof2D_MeanpT_Sub_ipt1_Tru_Pi"), cent, ietaA, ietaB, mptsubTru); + if (ipt == KNpT - 1) + histos.fill(HIST("Prof2D_MeanpT_Sub_ipt2_Tru_Pi"), cent, ietaA, ietaB, mptsubTru); + } else if (isp == numKKaon) { // Kaon + if (ipt == 0) + histos.fill(HIST("Prof2D_MeanpT_Sub_ipt0_Tru_Ka"), cent, ietaA, ietaB, mptsubTru); + if (ipt == KNpT - 2) + histos.fill(HIST("Prof2D_MeanpT_Sub_ipt1_Tru_Ka"), cent, ietaA, ietaB, mptsubTru); + if (ipt == KNpT - 1) + histos.fill(HIST("Prof2D_MeanpT_Sub_ipt2_Tru_Ka"), cent, ietaA, ietaB, mptsubTru); + } else if (isp == numKProton) { // Proton + if (ipt == 0) + histos.fill(HIST("Prof2D_MeanpT_Sub_ipt0_Tru_Pr"), cent, ietaA, ietaB, mptsubTru); + if (ipt == KNpT - 2) + histos.fill(HIST("Prof2D_MeanpT_Sub_ipt1_Tru_Pr"), cent, ietaA, ietaB, mptsubTru); + if (ipt == KNpT - 1) + histos.fill(HIST("Prof2D_MeanpT_Sub_ipt2_Tru_Pr"), cent, ietaA, ietaB, mptsubTru); + } + } + + // 2. Reco Raw Sub-event Mean + double nRecAB = sumWiReco[isp][ietaA][ipt] + sumWiReco[isp][ietaB][ipt]; + if (nRecAB > 0) { + float mptsubReco = (sumWiptiReco[isp][ietaA][ipt] + sumWiptiReco[isp][ietaB][ipt]) / nRecAB; + if (isp == numKInclusive) { + if (ipt == 0) + histos.fill(HIST("Prof2D_MeanpT_Sub_ipt0_Reco"), cent, ietaA, ietaB, mptsubReco); + if (ipt == KNpT - 2) + histos.fill(HIST("Prof2D_MeanpT_Sub_ipt1_Reco"), cent, ietaA, ietaB, mptsubReco); + if (ipt == KNpT - 1) + histos.fill(HIST("Prof2D_MeanpT_Sub_ipt2_Reco"), cent, ietaA, ietaB, mptsubReco); + } else if (isp == numKPion) { + if (ipt == 0) + histos.fill(HIST("Prof2D_MeanpT_Sub_ipt0_Reco_Pi"), cent, ietaA, ietaB, mptsubReco); + if (ipt == KNpT - 2) + histos.fill(HIST("Prof2D_MeanpT_Sub_ipt1_Reco_Pi"), cent, ietaA, ietaB, mptsubReco); + if (ipt == KNpT - 1) + histos.fill(HIST("Prof2D_MeanpT_Sub_ipt2_Reco_Pi"), cent, ietaA, ietaB, mptsubReco); + } else if (isp == numKKaon) { + if (ipt == 0) + histos.fill(HIST("Prof2D_MeanpT_Sub_ipt0_Reco_Ka"), cent, ietaA, ietaB, mptsubReco); + if (ipt == KNpT - 2) + histos.fill(HIST("Prof2D_MeanpT_Sub_ipt1_Reco_Ka"), cent, ietaA, ietaB, mptsubReco); + if (ipt == KNpT - 1) + histos.fill(HIST("Prof2D_MeanpT_Sub_ipt2_Reco_Ka"), cent, ietaA, ietaB, mptsubReco); + } else if (isp == numKProton) { + if (ipt == 0) + histos.fill(HIST("Prof2D_MeanpT_Sub_ipt0_Reco_Pr"), cent, ietaA, ietaB, mptsubReco); + if (ipt == KNpT - 2) + histos.fill(HIST("Prof2D_MeanpT_Sub_ipt1_Reco_Pr"), cent, ietaA, ietaB, mptsubReco); + if (ipt == KNpT - 1) + histos.fill(HIST("Prof2D_MeanpT_Sub_ipt2_Reco_Pr"), cent, ietaA, ietaB, mptsubReco); + } + } + + // 3. Reco Efficiency Corrected Sub-event Mean + double wCorrAB = sumWiRecoEffCorr[isp][ietaA][ipt] + sumWiRecoEffCorr[isp][ietaB][ipt]; + if (wCorrAB > 0) { + float mptsubRecoEffCorr = (sumWiptiRecoEffCorr[isp][ietaA][ipt] + sumWiptiRecoEffCorr[isp][ietaB][ipt]) / wCorrAB; + if (isp == numKInclusive) { + if (ipt == 0) + histos.fill(HIST("Prof2D_MeanpT_Sub_ipt0_RecoEffCorr"), cent, ietaA, ietaB, mptsubRecoEffCorr); + if (ipt == KNpT - 2) + histos.fill(HIST("Prof2D_MeanpT_Sub_ipt1_RecoEffCorr"), cent, ietaA, ietaB, mptsubRecoEffCorr); + if (ipt == KNpT - 1) + histos.fill(HIST("Prof2D_MeanpT_Sub_ipt2_RecoEffCorr"), cent, ietaA, ietaB, mptsubRecoEffCorr); + } else if (isp == numKPion) { + if (ipt == 0) + histos.fill(HIST("Prof2D_MeanpT_Sub_ipt0_RecoEffCorr_Pi"), cent, ietaA, ietaB, mptsubRecoEffCorr); + if (ipt == KNpT - 2) + histos.fill(HIST("Prof2D_MeanpT_Sub_ipt1_RecoEffCorr_Pi"), cent, ietaA, ietaB, mptsubRecoEffCorr); + if (ipt == KNpT - 1) + histos.fill(HIST("Prof2D_MeanpT_Sub_ipt2_RecoEffCorr_Pi"), cent, ietaA, ietaB, mptsubRecoEffCorr); + } else if (isp == numKKaon) { + if (ipt == 0) + histos.fill(HIST("Prof2D_MeanpT_Sub_ipt0_RecoEffCorr_Ka"), cent, ietaA, ietaB, mptsubRecoEffCorr); + if (ipt == KNpT - 2) + histos.fill(HIST("Prof2D_MeanpT_Sub_ipt1_RecoEffCorr_Ka"), cent, ietaA, ietaB, mptsubRecoEffCorr); + if (ipt == KNpT - 1) + histos.fill(HIST("Prof2D_MeanpT_Sub_ipt2_RecoEffCorr_Ka"), cent, ietaA, ietaB, mptsubRecoEffCorr); + } else if (isp == numKProton) { + if (ipt == 0) + histos.fill(HIST("Prof2D_MeanpT_Sub_ipt0_RecoEffCorr_Pr"), cent, ietaA, ietaB, mptsubRecoEffCorr); + if (ipt == KNpT - 2) + histos.fill(HIST("Prof2D_MeanpT_Sub_ipt1_RecoEffCorr_Pr"), cent, ietaA, ietaB, mptsubRecoEffCorr); + if (ipt == KNpT - 1) + histos.fill(HIST("Prof2D_MeanpT_Sub_ipt2_RecoEffCorr_Pr"), cent, ietaA, ietaB, mptsubRecoEffCorr); + } + } + + // 4. pmean Profiles (Individual Bins) + if (ietaA == ietaB) { // only fill once per eta bin + if (sumWiTruth[isp][ietaA][ipt] > 0) { + float val = sumWiptiTruth[isp][ietaA][ipt] / sumWiTruth[isp][ietaA][ipt]; + if (isp == numKInclusive) + histos.fill(HIST("pmeanTruNchEtabinPtbin"), multPV, ietaA, ipt, val); + else if (isp == numKPion) + histos.fill(HIST("pmeanTruNchEtabinPtbin_Pi"), multPV, ietaA, ipt, val); + else if (isp == numKKaon) + histos.fill(HIST("pmeanTruNchEtabinPtbin_Ka"), multPV, ietaA, ipt, val); + else if (isp == numKProton) + histos.fill(HIST("pmeanTruNchEtabinPtbin_Pr"), multPV, ietaA, ipt, val); + } + + if (sumWiReco[isp][ietaA][ipt] > 0) { + float val = sumWiptiReco[isp][ietaA][ipt] / sumWiReco[isp][ietaA][ipt]; + if (isp == numKInclusive) + histos.fill(HIST("pmeanRecoNchEtabinPtbin"), multPV, ietaA, ipt, val); + else if (isp == numKPion) + histos.fill(HIST("pmeanRecoNchEtabinPtbin_Pi"), multPV, ietaA, ipt, val); + else if (isp == numKKaon) + histos.fill(HIST("pmeanRecoNchEtabinPtbin_Ka"), multPV, ietaA, ipt, val); + else if (isp == numKProton) + histos.fill(HIST("pmeanRecoNchEtabinPtbin_Pr"), multPV, ietaA, ipt, val); + } + if (sumWiRecoEffCorr[isp][ietaA][ipt] > 0) { + float val = sumWiptiRecoEffCorr[isp][ietaA][ipt] / sumWiRecoEffCorr[isp][ietaA][ipt]; + if (isp == numKInclusive) + histos.fill(HIST("pmeanRecoEffcorrNchEtabinPtbin"), multPV, ietaA, ipt, val); + else if (isp == numKPion) + histos.fill(HIST("pmeanRecoEffcorrNchEtabinPtbin_Pi"), multPV, ietaA, ipt, val); + else if (isp == numKKaon) + histos.fill(HIST("pmeanRecoEffcorrNchEtabinPtbin_Ka"), multPV, ietaA, ipt, val); + else if (isp == numKProton) + histos.fill(HIST("pmeanRecoEffcorrNchEtabinPtbin_Pr"), multPV, ietaA, ipt, val); + } + + if (sumWiTruth[isp][ietaA][ipt] > 0) { + if (isp == numKInclusive) + histos.fill(HIST("pmeanMultTruNchEtabinPtbin"), multPV, ietaA, ipt, sumWiTruth[isp][ietaA][ipt]); + else if (isp == numKPion) + histos.fill(HIST("pmeanMultTruNchEtabinPtbin_Pi"), multPV, ietaA, ipt, sumWiTruth[isp][ietaA][ipt]); + else if (isp == numKKaon) + histos.fill(HIST("pmeanMultTruNchEtabinPtbin_Ka"), multPV, ietaA, ipt, sumWiTruth[isp][ietaA][ipt]); + else if (isp == numKProton) + histos.fill(HIST("pmeanMultTruNchEtabinPtbin_Pr"), multPV, ietaA, ipt, sumWiTruth[isp][ietaA][ipt]); + } + + if (sumWiReco[isp][ietaA][ipt] > 0) { + if (isp == numKInclusive) + histos.fill(HIST("pmeanMultRecoNchEtabinPtbin"), multPV, ietaA, ipt, sumWiReco[isp][ietaA][ipt]); + else if (isp == numKPion) + histos.fill(HIST("pmeanMultRecoNchEtabinPtbin_Pi"), multPV, ietaA, ipt, sumWiReco[isp][ietaA][ipt]); + else if (isp == numKKaon) + histos.fill(HIST("pmeanMultRecoNchEtabinPtbin_Ka"), multPV, ietaA, ipt, sumWiReco[isp][ietaA][ipt]); + else if (isp == numKProton) + histos.fill(HIST("pmeanMultRecoNchEtabinPtbin_Pr"), multPV, ietaA, ipt, sumWiReco[isp][ietaA][ipt]); + } + if (sumWiRecoEffCorr[isp][ietaA][ipt] > 0) { + if (isp == numKInclusive) + histos.fill(HIST("pmeanMultRecoEffcorrNchEtabinPtbin"), multPV, ietaA, ipt, sumWiRecoEffCorr[isp][ietaA][ipt]); + else if (isp == numKPion) + histos.fill(HIST("pmeanMultRecoEffcorrNchEtabinPtbin_Pi"), multPV, ietaA, ipt, sumWiRecoEffCorr[isp][ietaA][ipt]); + else if (isp == numKKaon) + histos.fill(HIST("pmeanMultRecoEffcorrNchEtabinPtbin_Ka"), multPV, ietaA, ipt, sumWiRecoEffCorr[isp][ietaA][ipt]); + else if (isp == numKProton) + histos.fill(HIST("pmeanMultRecoEffcorrNchEtabinPtbin_Pr"), multPV, ietaA, ipt, sumWiRecoEffCorr[isp][ietaA][ipt]); + } + } + } // end isp + } // end ipt + } // end ietaB + } // end ietaA + } } - LOGF(info, "FINISHED RUNNING processMCMean (pT + Et)"); } PROCESS_SWITCH(RadialFlowDecorr, processMCMean, "process MC to calculate mean pt/Et and Eff Hists", cfgRunMCMean); void processMCFluc(aod::McCollisions const& mcColl, MyRun3MCCollisions const& collisions, TCs const& tracks, FilteredTCs const& /*filteredTracks*/, aod::McParticles const& mcParticles) { - double sumPmwkTru[KNEta][KNpT][KIntM][KIntK]{}; - double sumWkTru[KNEta][KNpT][KIntK]{}; - double sumPmwkReco[KNEta][KNpT][KIntM][KIntK]{}; - double sumWkReco[KNEta][KNpT][KIntK]{}; - double sumPmwkRecoEffCor[KNEta][KNpT][KIntM][KIntK]{}; - double sumWkRecoEffCor[KNEta][KNpT][KIntK]{}; - double sumPmwkTruEt[KNEta][KNpT][KIntM][KIntK]{}; - double sumWkTruEt[KNEta][KNpT][KIntK]{}; - double sumPmwkRecoEt[KNEta][KNpT][KIntM][KIntK]{}; - double sumWkRecoEt[KNEta][KNpT][KIntK]{}; - double sumPmwkRecoEffCorEt[KNEta][KNpT][KIntM][KIntK]{}; - double sumWkRecoEffCorEt[KNEta][KNpT][KIntK]{}; - double meanTru[KNEta][KNpT]{}, c2Tru[KNEta][KNpT]{}; - double meanReco[KNEta][KNpT]{}, c2Reco[KNEta][KNpT]{}; - double meanRecoEffCor[KNEta][KNpT]{}, c2RecoEffCor[KNEta][KNpT]{}; - double meanTruEt[KNEta][KNpT]{}, c2TruEt[KNEta][KNpT]{}; - double meanRecoEt[KNEta][KNpT]{}, c2RecoEt[KNEta][KNpT]{}; - double meanRecoEffCorEt[KNEta][KNpT]{}, c2RecoEffCorEt[KNEta][KNpT]{}; - - double meanTruMult[KNEta][KNpT]{}, covTruEt[KNEta][KNpT]{}; - double meanRecoMult[KNEta][KNpT]{}, covRecoEt[KNEta][KNpT]{}; - double meanRecoEffCorMult[KNEta][KNpT]{}, covRecoEffCorEt[KNEta][KNpT]{}; - - double p1kBarTru[KNEta][KNpT]{}, p1kBarReco[KNEta][KNpT]{}, p1kBarRecoEffCor[KNEta][KNpT]{}; - double p1kBarTruEt[KNEta][KNpT]{}, p1kBarRecoEt[KNEta][KNpT]{}, p1kBarRecoEffCorEt[KNEta][KNpT]{}; - double p1kBarTruMult[KNEta][KNpT]{}, p1kBarRecoMult[KNEta][KNpT]{}, p1kBarRecoEffCorMult[KNEta][KNpT]{}; + // 1. Safety Check: Step 2 Mean Maps + for (int isp = 0; isp < KNsp; ++isp) { + if (!pmeanTruNchEtabinPtbinStep2[isp] || !pmeanRecoNchEtabinPtbinStep2[isp] || !pmeanRecoEffcorrNchEtabinPtbinStep2[isp] || + !pmeanMultTruNchEtabinPtbinStep2[isp] || !pmeanMultRecoNchEtabinPtbinStep2[isp] || !pmeanMultRecoEffcorrNchEtabinPtbinStep2[isp]) { + LOGF(warning, "MC fluc: Mean pT or Mult map missing for species index %d", isp); + return; + } + } + + // Expanded with KNsp index (isp=0: Incl, 1: Pi, 2: Ka, 3: Pr) + double sumPmwkTru[KNsp][KNEta][KNpT][KIntM][KIntK]{}; + double sumWkTru[KNsp][KNEta][KNpT][KIntK]{}; + double sumPmwkReco[KNsp][KNEta][KNpT][KIntM][KIntK]{}; + double sumWkReco[KNsp][KNEta][KNpT][KIntK]{}; + double sumPmwkRecoEffCor[KNsp][KNEta][KNpT][KIntM][KIntK]{}; + double sumWkRecoEffCor[KNsp][KNEta][KNpT][KIntK]{}; + + double meanTru[KNsp][KNEta][KNpT]{}, c2Tru[KNsp][KNEta][KNpT]{}; + double meanReco[KNsp][KNEta][KNpT]{}, c2Reco[KNsp][KNEta][KNpT]{}; + double meanRecoEffCor[KNsp][KNEta][KNpT]{}, c2RecoEffCor[KNsp][KNEta][KNpT]{}; + + double meanTruMult[KNsp][KNEta][KNpT]{}; + double meanRecoMult[KNsp][KNEta][KNpT]{}; + double meanRecoEffCorMult[KNsp][KNEta][KNpT]{}; + + double p1kBarTru[KNsp][KNEta][KNpT]{}, p1kBarReco[KNsp][KNEta][KNpT]{}, p1kBarRecoEffCor[KNsp][KNEta][KNpT]{}; + double p1kBarTruMult[KNsp][KNEta][KNpT]{}, p1kBarRecoMult[KNsp][KNEta][KNpT]{}, p1kBarRecoEffCorMult[KNsp][KNEta][KNpT]{}; for (const auto& mcCollision : mcColl) { auto partSlice = mcParticles.sliceBy(partPerMcCollision, mcCollision.globalIndex()); auto colSlice = collisions.sliceBy(colPerMcCollision, mcCollision.globalIndex()); if (colSlice.size() != 1) continue; + for (const auto& col : colSlice) { + if (!col.has_mcCollision() || !isEventSelected(col)) + continue; auto trackSlice = tracks.sliceBy(trackPerCollision, col.globalIndex()); if (trackSlice.size() < 1) continue; + float cent = getCentrality(col); + if (cent > KCentMax) + continue; + float multPV = col.multNTracksPV(); + // Reset local arrays memset(sumPmwkTru, 0, sizeof(sumPmwkTru)); memset(sumWkTru, 0, sizeof(sumWkTru)); memset(sumPmwkReco, 0, sizeof(sumPmwkReco)); @@ -1606,13 +1804,6 @@ struct RadialFlowDecorr { memset(sumPmwkRecoEffCor, 0, sizeof(sumPmwkRecoEffCor)); memset(sumWkRecoEffCor, 0, sizeof(sumWkRecoEffCor)); - memset(sumPmwkTruEt, 0, sizeof(sumPmwkTruEt)); - memset(sumWkTruEt, 0, sizeof(sumWkTruEt)); - memset(sumPmwkRecoEt, 0, sizeof(sumPmwkRecoEt)); - memset(sumWkRecoEt, 0, sizeof(sumWkRecoEt)); - memset(sumPmwkRecoEffCorEt, 0, sizeof(sumPmwkRecoEffCorEt)); - memset(sumWkRecoEffCorEt, 0, sizeof(sumWkRecoEffCorEt)); - memset(meanTru, 0, sizeof(meanTru)); memset(c2Tru, 0, sizeof(c2Tru)); memset(meanReco, 0, sizeof(meanReco)); @@ -1620,48 +1811,27 @@ struct RadialFlowDecorr { memset(meanRecoEffCor, 0, sizeof(meanRecoEffCor)); memset(c2RecoEffCor, 0, sizeof(c2RecoEffCor)); - memset(meanTruEt, 0, sizeof(meanTruEt)); - memset(c2TruEt, 0, sizeof(c2TruEt)); - memset(meanRecoEt, 0, sizeof(meanRecoEt)); - memset(c2RecoEt, 0, sizeof(c2RecoEt)); - memset(meanRecoEffCorEt, 0, sizeof(meanRecoEffCorEt)); - memset(c2RecoEffCorEt, 0, sizeof(c2RecoEffCorEt)); - memset(meanTruMult, 0, sizeof(meanTruMult)); memset(meanRecoMult, 0, sizeof(meanRecoMult)); memset(meanRecoEffCorMult, 0, sizeof(meanRecoEffCorMult)); - memset(covTruEt, 0, sizeof(covTruEt)); - memset(covRecoEt, 0, sizeof(covRecoEt)); - memset(covRecoEffCorEt, 0, sizeof(covRecoEffCorEt)); - memset(p1kBarTru, 0, sizeof(p1kBarTru)); memset(p1kBarReco, 0, sizeof(p1kBarReco)); memset(p1kBarRecoEffCor, 0, sizeof(p1kBarRecoEffCor)); - memset(p1kBarTruEt, 0, sizeof(p1kBarTruEt)); - memset(p1kBarRecoEt, 0, sizeof(p1kBarRecoEt)); - memset(p1kBarRecoEffCorEt, 0, sizeof(p1kBarRecoEffCorEt)); - memset(p1kBarTruMult, 0, sizeof(p1kBarTruMult)); memset(p1kBarRecoMult, 0, sizeof(p1kBarRecoMult)); memset(p1kBarRecoEffCorMult, 0, sizeof(p1kBarRecoEffCorMult)); - if (!col.has_mcCollision() || !isEventSelected(col)) - continue; - float cent = getCentrality(col); - if (cent > KCentMax) - continue; - - // truth + // --- 1. Truth Loop --- for (const auto& particle : partSlice) { - if (!isParticleSelected(particle)) - continue; - if (!particle.isPhysicalPrimary()) + if (!isParticleSelected(particle) || !particle.isPhysicalPrimary()) continue; + float pt = particle.pt(); float eta = particle.eta(); - float p = particle.p(); + const int absPdgId = std::abs(particle.pdgCode()); + bool isSpecies[KNsp] = {true, (absPdgId == KPiPlus), (absPdgId == KKPlus), (absPdgId == KProton)}; for (int ieta = 0; ieta < KNEta; ++ieta) { if (eta <= etaLw[ieta] || eta > etaUp[ieta]) @@ -1669,89 +1839,43 @@ struct RadialFlowDecorr { for (int ipt = 0; ipt < KNpT; ++ipt) { if (pt <= pTLw[ipt] || pt > pTUp[ipt]) continue; - for (int k = 0; k < KIntK; ++k) { - for (int m = 0; m < KIntM; ++m) { - sumPmwkTru[ieta][ipt][m][k] += std::pow(pt, m); - } - sumWkTru[ieta][ipt][k]++; - } - } - } - const int absPdgId = std::abs(particle.pdgCode()); - const bool isPion = (absPdgId == kPiPlus); - const bool isKaon = (absPdgId == kKPlus); - const bool isProton = (absPdgId == kProton); - if (isPion || isKaon || isProton) { - - float m = isPion ? o2::constants::physics::MassPiPlus : isKaon ? o2::constants::physics::MassKPlus - : o2::constants::physics::MassProton; - float energy = std::sqrt(p * p + m * m); - float et = energy * (pt / p); - for (int ieta = 0; ieta < KNEta; ++ieta) { - if (eta <= etaLw[ieta] || eta > etaUp[ieta]) - continue; - for (int ipt = 0; ipt < KNpT; ++ipt) { - if (pt <= pTLw[ipt] || pt > pTUp[ipt]) - continue; - for (int k = 0; k < KIntK; ++k) { - for (int m = 0; m < KIntM; ++m) { - sumPmwkTruEt[ieta][ipt][m][k] += std::pow(et, m); + + for (int isp = 0; isp < KNsp; ++isp) { + if (isSpecies[isp]) { + for (int k = 0; k < KIntK; ++k) { + for (int m = 0; m < KIntM; ++m) { + sumPmwkTru[isp][ieta][ipt][m][k] += std::pow(pt, m); + } + sumWkTru[isp][ieta][ipt][k]++; } - sumWkTruEt[ieta][ipt][k]++; } } } } } // end truth loop + // --- 2. Reco Loop --- + float vz = col.posZ(); for (const auto& track : trackSlice) { if (!isTrackSelected(track)) continue; + float pt = track.pt(); float eta = track.eta(); - float p = track.p(); float phi = track.phi(); + float sign = track.sign(); + bool isSpecies[KNsp] = {true, selectionPion(track), selectionKaon(track), selectionProton(track)}; - float effIncl = getEfficiency(col.multNTracksPV(), pt, eta, kInclusive, 0, cfgEff); - float fakeIncl = getEfficiency(col.multNTracksPV(), pt, eta, kInclusive, 1, cfgEff); - float flatWeightIncl = getFlatteningWeight(col.posZ(), track.sign(), pt, eta, phi, kInclusive, cfgFlat); - float wIncl = flatWeightIncl * (1.0 - fakeIncl) / effIncl; - if (!std::isfinite(wIncl) || wIncl <= 0.f) - continue; - if (effIncl <= 0 || !std::isfinite(effIncl) || !std::isfinite(fakeIncl) || !std::isfinite(flatWeightIncl)) - continue; - - for (int ieta = 0; ieta < KNEta; ++ieta) { - if (eta <= etaLw[ieta] || eta > etaUp[ieta]) + for (int isp = 0; isp < KNsp; ++isp) { + if (!isSpecies[isp]) continue; - for (int ipt = 0; ipt < KNpT; ++ipt) { - if (pt <= pTLw[ipt] || pt > pTUp[ipt]) - continue; - for (int k = 0; k < KIntK; ++k) { - for (int m = 0; m < KIntM; ++m) { - sumPmwkReco[ieta][ipt][m][k] += std::pow(1.0, k) * std::pow(pt, m); - sumPmwkRecoEffCor[ieta][ipt][m][k] += std::pow(wIncl, k) * std::pow(pt, m); - } - sumWkReco[ieta][ipt][k] += std::pow(1.0, k); - sumWkRecoEffCor[ieta][ipt][k] += std::pow(wIncl, k); - } - } - } - const bool isPion = selectionPion(track); - const bool isKaon = selectionKaon(track); - const bool isProton = selectionProton(track); - - if (isPion || isKaon || isProton) { - float m = isPion ? o2::constants::physics::MassPiPlus : isKaon ? o2::constants::physics::MassKPlus - : o2::constants::physics::MassProton; - float energy = std::sqrt(p * p + m * m); - float et = energy * (pt / p); // E_T = E * sin(theta) - float effPid = getEfficiency(col.multNTracksPV(), pt, eta, kCombinedPID, 0, cfgEff); - float fakePid = getEfficiency(col.multNTracksPV(), pt, eta, kCombinedPID, 1, cfgEff); - float flatWeightPid = getFlatteningWeight(col.posZ(), track.sign(), pt, eta, phi, kCombinedPID, cfgFlat); - float wPid = flatWeightPid * (1 - fakePid) / effPid; - if (effPid >= 1 || fakePid >= 1 || !std::isfinite(effPid) || effPid <= KFloatEpsilon || !std::isfinite(fakePid) || !std::isfinite(flatWeightPid)) + float eff = getEfficiency(col.multNTracksPV(), pt, eta, static_cast(isp), 0, cfgEff); + float fake = getEfficiency(col.multNTracksPV(), pt, eta, static_cast(isp), 1, cfgEff); + float flatW = getFlatteningWeight(vz, sign, pt, eta, phi, static_cast(isp), cfgFlat); + float w = flatW * (1.0 - fake) / eff; + + if (!std::isfinite(w) || w <= 0.f || eff <= KFloatEpsilon) continue; for (int ieta = 0; ieta < KNEta; ++ieta) { @@ -1762,311 +1886,703 @@ struct RadialFlowDecorr { continue; for (int k = 0; k < KIntK; ++k) { for (int m = 0; m < KIntM; ++m) { - sumPmwkRecoEt[ieta][ipt][m][k] += std::pow(1.0, k) * std::pow(et, m); - sumPmwkRecoEffCorEt[ieta][ipt][m][k] += std::pow(wPid, k) * std::pow(et, m); + sumPmwkReco[isp][ieta][ipt][m][k] += std::pow(1.0, k) * std::pow(pt, m); + sumPmwkRecoEffCor[isp][ieta][ipt][m][k] += std::pow(w, k) * std::pow(pt, m); } - sumWkRecoEt[ieta][ipt][k] += std::pow(1.0, k); - sumWkRecoEffCorEt[ieta][ipt][k] += std::pow(wPid, k); + sumWkReco[isp][ieta][ipt][k] += std::pow(1.0, k); + sumWkRecoEffCor[isp][ieta][ipt][k] += std::pow(w, k); } } } + + if (isp == numKInclusive) { + histos.fill(HIST("hEtaPhiReco"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + + } else if (isp == numKPion) { // Pion + histos.fill(HIST("hEtaPhiReco_Pi"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_Pi"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_Pi"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + + } else if (isp == numKKaon) { // Kaon + histos.fill(HIST("hEtaPhiReco_Ka"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_Ka"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_Ka"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + + } else if (isp == numKProton) { // Proton + histos.fill(HIST("hEtaPhiReco_Pr"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_Pr"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_Pr"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } } - } + } // trkslice - // FullEvent calculation for all individual eta ranges + // --- 3. FullEvent calculation & Covariances --- for (int ieta = 0; ieta < KNEta; ++ieta) { for (int ipt = 0; ipt < KNpT; ++ipt) { - meanTruMult[ieta][ipt] = sumWkTru[ieta][ipt][1]; - meanRecoMult[ieta][ipt] = sumWkReco[ieta][ipt][1]; - meanRecoEffCorMult[ieta][ipt] = sumWkRecoEffCor[ieta][ipt][1]; - const int ibx = pmeanTruNchEtabinPtbinStep2->GetXaxis()->FindBin(col.multNTracksPV()); + // Safely get the X-axis bin using the Inclusive map [0] + const int ibx = pmeanTruNchEtabinPtbinStep2[0]->GetXaxis()->FindBin(col.multNTracksPV()); const int iby = ieta + 1; const int ibz = ipt + 1; - float mmptTru = pmeanTruNchEtabinPtbinStep2->GetBinContent(ibx, iby, ibz); - float mmptReco = pmeanRecoNchEtabinPtbinStep2->GetBinContent(ibx, iby, ibz); - float mmptRecoEffCor = pmeanRecoEffcorrNchEtabinPtbinStep2->GetBinContent(ibx, iby, ibz); - float mmetTru = pmeanEtTruNchEtabinPtbinStep2->GetBinContent(ibx, iby, ibz); - float mmetReco = pmeanEtRecoNchEtabinPtbinStep2->GetBinContent(ibx, iby, ibz); - float mmetRecoEffCor = pmeanEtRecoEffcorrNchEtabinPtbinStep2->GetBinContent(ibx, iby, ibz); - - if (std::isfinite(mmptTru)) - std::tie(meanTru[ieta][ipt], c2Tru[ieta][ipt]) = calculateMeanAndC2FromSums(sumPmwkTru[ieta][ipt], sumWkTru[ieta][ipt], mmptTru); - if (std::isfinite(mmptReco)) - std::tie(meanReco[ieta][ipt], c2Reco[ieta][ipt]) = calculateMeanAndC2FromSums(sumPmwkReco[ieta][ipt], sumWkReco[ieta][ipt], mmptReco); - if (std::isfinite(mmptRecoEffCor)) - std::tie(meanRecoEffCor[ieta][ipt], c2RecoEffCor[ieta][ipt]) = calculateMeanAndC2FromSums(sumPmwkRecoEffCor[ieta][ipt], sumWkRecoEffCor[ieta][ipt], mmptRecoEffCor); - - if (std::isfinite(mmetTru)) - std::tie(meanTruEt[ieta][ipt], c2TruEt[ieta][ipt]) = calculateMeanAndC2FromSums(sumPmwkTruEt[ieta][ipt], sumWkTruEt[ieta][ipt], mmetTru); - if (std::isfinite(mmetReco)) - std::tie(meanRecoEt[ieta][ipt], c2RecoEt[ieta][ipt]) = calculateMeanAndC2FromSums(sumPmwkRecoEt[ieta][ipt], sumWkRecoEt[ieta][ipt], mmetReco); - if (std::isfinite(mmetRecoEffCor)) - std::tie(meanRecoEffCorEt[ieta][ipt], c2RecoEffCorEt[ieta][ipt]) = calculateMeanAndC2FromSums(sumPmwkRecoEffCorEt[ieta][ipt], sumWkRecoEffCorEt[ieta][ipt], mmetRecoEffCor); - - //"Truth" - if (std::isfinite(meanTru[ieta][ipt])) { - histos.fill(HIST("MCGen/Prof_Cent_MeanpT_etabin_ptbin"), cent, ieta, ipt, meanTru[ieta][ipt]); - histos.fill(HIST("MCGen/Prof_Mult_MeanpT_etabin_ptbin"), col.multNTracksPV(), ieta, ipt, meanTru[ieta][ipt]); - } - if (std::isfinite(meanTruEt[ieta][ipt])) { - histos.fill(HIST("MCGen/Prof_Cent_MeanEt_etabin_ptbin"), cent, ieta, ipt, meanTruEt[ieta][ipt]); - histos.fill(HIST("MCGen/Prof_Mult_MeanEt_etabin_ptbin"), col.multNTracksPV(), ieta, ipt, meanTruEt[ieta][ipt]); - } - // "MCReco" - if (std::isfinite(meanReco[ieta][ipt])) { - histos.fill(HIST("MCReco/Prof_Cent_MeanpT_etabin_ptbin"), cent, ieta, ipt, meanReco[ieta][ipt]); - histos.fill(HIST("MCReco/Prof_Mult_MeanpT_etabin_ptbin"), col.multNTracksPV(), ieta, ipt, meanReco[ieta][ipt]); - } - if (std::isfinite(meanRecoEt[ieta][ipt])) { - histos.fill(HIST("MCReco/Prof_Cent_MeanEt_etabin_ptbin"), cent, ieta, ipt, meanRecoEt[ieta][ipt]); - histos.fill(HIST("MCReco/Prof_Mult_MeanEt_etabin_ptbin"), col.multNTracksPV(), ieta, ipt, meanRecoEt[ieta][ipt]); - } - // "MCRecoEffCor" - if (std::isfinite(meanRecoEffCor[ieta][ipt])) { - histos.fill(HIST("MCRecoEffCorr/Prof_Cent_MeanpT_etabin_ptbin"), cent, ieta, ipt, meanRecoEffCor[ieta][ipt]); - histos.fill(HIST("MCRecoEffCorr/Prof_Mult_MeanpT_etabin_ptbin"), col.multNTracksPV(), ieta, ipt, meanRecoEffCor[ieta][ipt]); - } - if (std::isfinite(meanRecoEffCorEt[ieta][ipt])) { - histos.fill(HIST("MCRecoEffCorr/Prof_Cent_MeanEt_etabin_ptbin"), cent, ieta, ipt, meanRecoEffCorEt[ieta][ipt]); - histos.fill(HIST("MCRecoEffCorr/Prof_Mult_MeanEt_etabin_ptbin"), col.multNTracksPV(), ieta, ipt, meanRecoEffCorEt[ieta][ipt]); - } - - //"Truth" - if (std::isfinite(c2Tru[ieta][ipt])) { - histos.fill(HIST("MCGen/Prof_Cent_C2_etabin_ptbin"), cent, ieta, ipt, c2Tru[ieta][ipt]); - histos.fill(HIST("MCGen/Prof_C2_Mult_etabin_ptbin"), col.multNTracksPV(), ieta, ipt, c2Tru[ieta][ipt]); - } - if (std::isfinite(c2TruEt[ieta][ipt])) { - histos.fill(HIST("MCGen/Prof_Cent_C2Et_etabin_ptbin"), cent, ieta, ipt, c2TruEt[ieta][ipt]); - histos.fill(HIST("MCGen/Prof_C2Et_Mult_etabin_ptbin"), col.multNTracksPV(), ieta, ipt, c2TruEt[ieta][ipt]); - } - // "MCReco" - if (std::isfinite(c2Reco[ieta][ipt])) { - histos.fill(HIST("MCReco/Prof_Cent_C2_etabin_ptbin"), cent, ieta, ipt, c2Reco[ieta][ipt]); - histos.fill(HIST("MCReco/Prof_C2_Mult_etabin_ptbin"), col.multNTracksPV(), ieta, ipt, c2Reco[ieta][ipt]); - } - if (std::isfinite(c2RecoEt[ieta][ipt])) { - histos.fill(HIST("MCReco/Prof_Cent_C2Et_etabin_ptbin"), cent, ieta, ipt, c2RecoEt[ieta][ipt]); - histos.fill(HIST("MCReco/Prof_C2Et_Mult_etabin_ptbin"), col.multNTracksPV(), ieta, ipt, c2RecoEt[ieta][ipt]); - } - // "MCRecoEffCor" - if (std::isfinite(c2RecoEffCor[ieta][ipt])) { - histos.fill(HIST("MCRecoEffCorr/Prof_Cent_C2_etabin_ptbin"), cent, ieta, ipt, c2RecoEffCor[ieta][ipt]); - histos.fill(HIST("MCRecoEffCorr/Prof_C2_Mult_etabin_ptbin"), col.multNTracksPV(), ieta, ipt, c2RecoEffCor[ieta][ipt]); - } - if (std::isfinite(c2RecoEffCorEt[ieta][ipt])) { - histos.fill(HIST("MCRecoEffCorr/Prof_Cent_C2Et_etabin_ptbin"), cent, ieta, ipt, c2RecoEffCorEt[ieta][ipt]); - histos.fill(HIST("MCRecoEffCorr/Prof_C2Et_Mult_etabin_ptbin"), col.multNTracksPV(), ieta, ipt, c2RecoEffCorEt[ieta][ipt]); + for (int isp = 0; isp < KNsp; ++isp) { + meanTruMult[isp][ieta][ipt] = sumWkTru[isp][ieta][ipt][1]; + meanRecoMult[isp][ieta][ipt] = sumWkReco[isp][ieta][ipt][1]; + meanRecoEffCorMult[isp][ieta][ipt] = sumWkRecoEffCor[isp][ieta][ipt][1]; + + // Dynamically fetch from the arrays using the 'isp' index! + float mmptTru = pmeanTruNchEtabinPtbinStep2[isp]->GetBinContent(ibx, iby, ibz); + float mmptReco = pmeanRecoNchEtabinPtbinStep2[isp]->GetBinContent(ibx, iby, ibz); + float mmptRecoEffCor = pmeanRecoEffcorrNchEtabinPtbinStep2[isp]->GetBinContent(ibx, iby, ibz); + + float mmMultTru = pmeanMultTruNchEtabinPtbinStep2[isp]->GetBinContent(ibx, iby, ibz); + float mmMultReco = pmeanMultRecoNchEtabinPtbinStep2[isp]->GetBinContent(ibx, iby, ibz); + float mmMultRecoEffCor = pmeanMultRecoEffcorrNchEtabinPtbinStep2[isp]->GetBinContent(ibx, iby, ibz); + + if (std::isfinite(mmptTru)) + std::tie(meanTru[isp][ieta][ipt], c2Tru[isp][ieta][ipt]) = calculateMeanAndC2FromSums(sumPmwkTru[isp][ieta][ipt], sumWkTru[isp][ieta][ipt], mmptTru); + if (std::isfinite(mmptReco)) + std::tie(meanReco[isp][ieta][ipt], c2Reco[isp][ieta][ipt]) = calculateMeanAndC2FromSums(sumPmwkReco[isp][ieta][ipt], sumWkReco[isp][ieta][ipt], mmptReco); + if (std::isfinite(mmptRecoEffCor)) + std::tie(meanRecoEffCor[isp][ieta][ipt], c2RecoEffCor[isp][ieta][ipt]) = calculateMeanAndC2FromSums(sumPmwkRecoEffCor[isp][ieta][ipt], sumWkRecoEffCor[isp][ieta][ipt], mmptRecoEffCor); + + if (mmptTru != 0.0f) + p1kBarTru[isp][ieta][ipt] = meanTru[isp][ieta][ipt] - mmptTru; + if (mmptReco != 0.0f) + p1kBarReco[isp][ieta][ipt] = meanReco[isp][ieta][ipt] - mmptReco; + if (mmptRecoEffCor != 0.0f) + p1kBarRecoEffCor[isp][ieta][ipt] = meanRecoEffCor[isp][ieta][ipt] - mmptRecoEffCor; + + if (mmMultTru != 0.0f) + p1kBarTruMult[isp][ieta][ipt] = meanTruMult[isp][ieta][ipt] - mmMultTru; + if (mmMultReco != 0.0f) + p1kBarRecoMult[isp][ieta][ipt] = meanRecoMult[isp][ieta][ipt] - mmMultReco; + if (mmMultRecoEffCor != 0.0f) + p1kBarRecoEffCorMult[isp][ieta][ipt] = meanRecoEffCorMult[isp][ieta][ipt] - mmMultRecoEffCor; } } } - for (int ieta = 0; ieta < KNEta; ++ieta) { - for (int ipt = 0; ipt < KNpT; ++ipt) { - const int ibx = pmeanTruNchEtabinPtbinStep2->GetXaxis()->FindBin(col.multNTracksPV()); - const int iby = ieta + 1; - const int ibz = ipt + 1; - - float mmptTru = pmeanTruNchEtabinPtbinStep2->GetBinContent(ibx, iby, ibz); - float mmptReco = pmeanRecoNchEtabinPtbinStep2->GetBinContent(ibx, iby, ibz); - float mmptRecoEffCor = pmeanRecoEffcorrNchEtabinPtbinStep2->GetBinContent(ibx, iby, ibz); - float mmetTru = pmeanEtTruNchEtabinPtbinStep2->GetBinContent(ibx, iby, ibz); - float mmetReco = pmeanEtRecoNchEtabinPtbinStep2->GetBinContent(ibx, iby, ibz); - float mmetRecoEffCor = pmeanEtRecoEffcorrNchEtabinPtbinStep2->GetBinContent(ibx, iby, ibz); - - float mmMultTru = pmeanMultTruNchEtabinPtbinStep2->GetBinContent(ibx, iby, ibz); - float mmMultReco = pmeanMultRecoNchEtabinPtbinStep2->GetBinContent(ibx, iby, ibz); - float mmMultRecoEffCor = pmeanMultRecoEffcorrNchEtabinPtbinStep2->GetBinContent(ibx, iby, ibz); - - if (mmptTru != 0.0f) - p1kBarTru[ieta][ipt] = meanTru[ieta][ipt] - mmptTru; - if (mmptReco != 0.0f) - p1kBarReco[ieta][ipt] = meanReco[ieta][ipt] - mmptReco; - if (mmptRecoEffCor != 0.0f) - p1kBarRecoEffCor[ieta][ipt] = meanRecoEffCor[ieta][ipt] - mmptRecoEffCor; - - if (mmetTru != 0.0f) - p1kBarTruEt[ieta][ipt] = meanTruEt[ieta][ipt] - mmetTru; - if (mmetReco != 0.0f) - p1kBarRecoEt[ieta][ipt] = meanRecoEt[ieta][ipt] - mmetReco; - if (mmetRecoEffCor != 0.0f) - p1kBarRecoEffCorEt[ieta][ipt] = meanRecoEffCorEt[ieta][ipt] - mmetRecoEffCor; - - if (mmMultTru != 0.0f) - p1kBarTruMult[ieta][ipt] = meanTruMult[ieta][ipt] - mmMultTru; - if (mmMultReco != 0.0f) - p1kBarRecoMult[ieta][ipt] = meanRecoMult[ieta][ipt] - mmMultReco; - if (mmMultRecoEffCor != 0.0f) - p1kBarRecoEffCorMult[ieta][ipt] = meanRecoEffCorMult[ieta][ipt] - mmMultRecoEffCor; - } - } + for (int isp = 0; isp < KNsp; ++isp) { + if (isp == numKInclusive) { + histos.fill(HIST("MCGen/Prof_Cent_Nchrec"), cent, sumWkTru[isp][0][0][1]); + histos.fill(HIST("MCGen/Prof_Mult_Nchrec"), multPV, sumWkTru[isp][0][0][1]); + if (sumWkTru[isp][0][0][1] > 1.0f) { + histos.fill(HIST("MCGen/Prof_Cent_MeanpT"), cent, meanTru[isp][0][0]); + histos.fill(HIST("MCGen/Prof_Mult_MeanpT"), multPV, meanTru[isp][0][0]); + } - for (int ietaA = 1; ietaA <= (KNEta - 1) / 2; ++ietaA) { - int ietaC = KNEta - ietaA; - for (int ipt = 0; ipt < KNpT; ++ipt) { - float c2Sub_Tru = p1kBarTru[ietaA][ipt] * p1kBarTru[ietaC][ipt]; - float c2SubEt_Tru = p1kBarTruEt[ietaA][ipt] * p1kBarTruEt[ietaC][ipt]; - float c2Sub_Reco = p1kBarReco[ietaA][ipt] * p1kBarReco[ietaC][ipt]; - float c2SubEt_Reco = p1kBarRecoEt[ietaA][ipt] * p1kBarRecoEt[ietaC][ipt]; - float c2Sub_RecoEffCor = p1kBarRecoEffCor[ietaA][ipt] * p1kBarRecoEffCor[ietaC][ipt]; - float c2SubEt_RecoEffCor = p1kBarRecoEffCorEt[ietaA][ipt] * p1kBarRecoEffCorEt[ietaC][ipt]; + } else if (isp == numKPion) { + histos.fill(HIST("MCGen/Prof_Cent_Nchrec_Pi"), cent, sumWkTru[isp][0][0][1]); + histos.fill(HIST("MCGen/Prof_Mult_Nchrec_Pi"), multPV, sumWkTru[isp][0][0][1]); - float cov_Tru_AC = p1kBarTruMult[ietaA][ipt] * p1kBarTru[ietaC][ipt]; - float cov_Reco_AC = p1kBarRecoMult[ietaA][ipt] * p1kBarReco[ietaC][ipt]; - float cov_RecoEffCor_AC = p1kBarRecoEffCorMult[ietaA][ipt] * p1kBarRecoEffCor[ietaC][ipt]; + if (sumWkTru[isp][0][0][1] > 1.0f) { + histos.fill(HIST("MCGen/Prof_Cent_MeanpT_Pi"), cent, meanTru[isp][0][0]); + histos.fill(HIST("MCGen/Prof_Mult_MeanpT_Pi"), multPV, meanTru[isp][0][0]); + } - float cov_Tru_CA = p1kBarTru[ietaA][ipt] * p1kBarTruMult[ietaC][ipt]; - float cov_Reco_CA = p1kBarReco[ietaA][ipt] * p1kBarRecoMult[ietaC][ipt]; - float cov_RecoEffCor_CA = p1kBarRecoEffCor[ietaA][ipt] * p1kBarRecoEffCorMult[ietaC][ipt]; + } else if (isp == numKKaon) { + histos.fill(HIST("MCGen/Prof_Cent_Nchrec_Ka"), cent, sumWkTru[isp][0][0][1]); + histos.fill(HIST("MCGen/Prof_Mult_Nchrec_Ka"), multPV, sumWkTru[isp][0][0][1]); - if (std::isfinite(c2Sub_Tru)) { - histos.fill(HIST("MCGen/Prof_C2Sub_Mult_etabin_ptbin"), col.multNTracksPV(), ietaA, ipt, c2Sub_Tru); - histos.fill(HIST("MCGen/Prof_C2Sub_Cent_etabin_ptbin"), cent, ietaA, ipt, c2Sub_Tru); + if (sumWkTru[isp][0][0][1] > 1.0f) { + histos.fill(HIST("MCGen/Prof_Cent_MeanpT_Ka"), cent, meanTru[isp][0][0]); + histos.fill(HIST("MCGen/Prof_Mult_MeanpT_Ka"), multPV, meanTru[isp][0][0]); } + } else if (isp == numKProton) { + histos.fill(HIST("MCGen/Prof_Cent_Nchrec_Pr"), cent, sumWkTru[isp][0][0][1]); + histos.fill(HIST("MCGen/Prof_Mult_Nchrec_Pr"), multPV, sumWkTru[isp][0][0][1]); - if (std::isfinite(c2SubEt_Tru)) { - histos.fill(HIST("MCGen/Prof_C2EtSub_Mult_etabin_ptbin"), col.multNTracksPV(), ietaA, ipt, c2SubEt_Tru); - histos.fill(HIST("MCGen/Prof_C2EtSub_Cent_etabin_ptbin"), cent, ietaA, ipt, c2SubEt_Tru); + if (sumWkTru[isp][0][0][1] > 1.0f) { + histos.fill(HIST("MCGen/Prof_Cent_MeanpT_Pr"), cent, meanTru[isp][0][0]); + histos.fill(HIST("MCGen/Prof_Mult_MeanpT_Pr"), multPV, meanTru[isp][0][0]); } + } + } - if (std::isfinite(cov_Tru_AC)) { - histos.fill(HIST("MCGen/Prof_Cov_Mult_etabin_ptbin"), col.multNTracksPV(), ietaA, ipt, cov_Tru_AC); - histos.fill(HIST("MCGen/Prof_Cov_Cent_etabin_ptbin"), cent, ietaA, ipt, cov_Tru_AC); - } - if (std::isfinite(cov_Tru_CA)) { - histos.fill(HIST("MCGen/Prof_Cov_Mult_etabin_ptbin"), col.multNTracksPV(), ietaA, ipt, cov_Tru_CA); - histos.fill(HIST("MCGen/Prof_Cov_Cent_etabin_ptbin"), cent, ietaA, ipt, cov_Tru_CA); + for (int isp = 0; isp < KNsp; ++isp) { + if (isp == numKInclusive) { + histos.fill(HIST("MCReco/Prof_Cent_Nchrec"), cent, sumWkReco[isp][0][0][1]); + histos.fill(HIST("MCReco/Prof_Mult_Nchrec"), multPV, sumWkReco[isp][0][0][1]); + if (sumWkReco[isp][0][0][1] > 1.0f) { + histos.fill(HIST("MCReco/Prof_Cent_MeanpT"), cent, meanReco[isp][0][0]); + histos.fill(HIST("MCReco/Prof_Mult_MeanpT"), multPV, meanReco[isp][0][0]); } - if (std::isfinite(c2Sub_Reco)) { - histos.fill(HIST("MCReco/Prof_C2Sub_Mult_etabin_ptbin"), col.multNTracksPV(), ietaA, ipt, c2Sub_Reco); - histos.fill(HIST("MCReco/Prof_C2Sub_Cent_etabin_ptbin"), cent, ietaA, ipt, c2Sub_Reco); + } else if (isp == numKPion) { + histos.fill(HIST("MCReco/Prof_Cent_Nchrec_Pi"), cent, sumWkReco[isp][0][0][1]); + histos.fill(HIST("MCReco/Prof_Mult_Nchrec_Pi"), multPV, sumWkReco[isp][0][0][1]); + + if (sumWkReco[isp][0][0][1] > 1.0f) { + histos.fill(HIST("MCReco/Prof_Cent_MeanpT_Pi"), cent, meanReco[isp][0][0]); + histos.fill(HIST("MCReco/Prof_Mult_MeanpT_Pi"), multPV, meanReco[isp][0][0]); } - if (std::isfinite(c2SubEt_Reco)) { - histos.fill(HIST("MCReco/Prof_C2EtSub_Mult_etabin_ptbin"), col.multNTracksPV(), ietaA, ipt, c2SubEt_Reco); - histos.fill(HIST("MCReco/Prof_C2EtSub_Cent_etabin_ptbin"), cent, ietaA, ipt, c2SubEt_Reco); + } else if (isp == numKKaon) { + histos.fill(HIST("MCReco/Prof_Cent_Nchrec_Ka"), cent, sumWkReco[isp][0][0][1]); + histos.fill(HIST("MCReco/Prof_Mult_Nchrec_Ka"), multPV, sumWkReco[isp][0][0][1]); + + if (sumWkReco[isp][0][0][1] > 1.0f) { + histos.fill(HIST("MCReco/Prof_Cent_MeanpT_Ka"), cent, meanReco[isp][0][0]); + histos.fill(HIST("MCReco/Prof_Mult_MeanpT_Ka"), multPV, meanReco[isp][0][0]); } - if (std::isfinite(cov_Reco_AC)) { - histos.fill(HIST("MCReco/Prof_Cov_Mult_etabin_ptbin"), col.multNTracksPV(), ietaA, ipt, cov_Reco_AC); - histos.fill(HIST("MCReco/Prof_Cov_Cent_etabin_ptbin"), cent, ietaA, ipt, cov_Reco_AC); + } else if (isp == numKProton) { + histos.fill(HIST("MCReco/Prof_Cent_Nchrec_Pr"), cent, sumWkReco[isp][0][0][1]); + histos.fill(HIST("MCReco/Prof_Mult_Nchrec_Pr"), multPV, sumWkReco[isp][0][0][1]); + if (sumWkReco[isp][0][0][1] > 1.0f) { + histos.fill(HIST("MCReco/Prof_Cent_MeanpT_Pr"), cent, meanReco[isp][0][0]); + histos.fill(HIST("MCReco/Prof_Mult_MeanpT_Pr"), multPV, meanReco[isp][0][0]); } - if (std::isfinite(cov_Reco_CA)) { - histos.fill(HIST("MCReco/Prof_Cov_Mult_etabin_ptbin"), col.multNTracksPV(), ietaA, ipt, cov_Reco_CA); - histos.fill(HIST("MCReco/Prof_Cov_Cent_etabin_ptbin"), cent, ietaA, ipt, cov_Reco_CA); + } + + if (isp == numKInclusive) { + histos.fill(HIST("MCRecoEffCorr/Prof_Cent_Nchrec"), cent, sumWkRecoEffCor[isp][0][0][1]); + histos.fill(HIST("MCRecoEffCorr/Prof_Mult_Nchrec"), multPV, sumWkRecoEffCor[isp][0][0][1]); + if (sumWkRecoEffCor[isp][0][0][1] > 1.0f) { + histos.fill(HIST("MCRecoEffCorr/Prof_Cent_MeanpT"), cent, meanRecoEffCor[isp][0][0]); + histos.fill(HIST("MCRecoEffCorr/Prof_Mult_MeanpT"), multPV, meanRecoEffCor[isp][0][0]); } - if (std::isfinite(c2Sub_RecoEffCor)) { - histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub_Mult_etabin_ptbin"), col.multNTracksPV(), ietaA, ipt, c2Sub_RecoEffCor); - histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub_Cent_etabin_ptbin"), cent, ietaA, ipt, c2Sub_RecoEffCor); + } else if (isp == numKPion) { + histos.fill(HIST("MCRecoEffCorr/Prof_Cent_Nchrec_Pi"), cent, sumWkRecoEffCor[isp][0][0][1]); + histos.fill(HIST("MCRecoEffCorr/Prof_Mult_Nchrec_Pi"), multPV, sumWkRecoEffCor[isp][0][0][1]); + if (sumWkRecoEffCor[isp][0][0][1] > 1.0f) { + histos.fill(HIST("MCRecoEffCorr/Prof_Cent_MeanpT_Pi"), cent, meanRecoEffCor[isp][0][0]); + histos.fill(HIST("MCRecoEffCorr/Prof_Mult_MeanpT_Pi"), multPV, meanRecoEffCor[isp][0][0]); } - if (std::isfinite(c2SubEt_RecoEffCor)) { - histos.fill(HIST("MCRecoEffCorr/Prof_C2EtSub_Mult_etabin_ptbin"), col.multNTracksPV(), ietaA, ipt, c2SubEt_RecoEffCor); - histos.fill(HIST("MCRecoEffCorr/Prof_C2EtSub_Cent_etabin_ptbin"), cent, ietaA, ipt, c2SubEt_RecoEffCor); + } else if (isp == numKKaon) { + histos.fill(HIST("MCRecoEffCorr/Prof_Cent_Nchrec_Ka"), cent, sumWkRecoEffCor[isp][0][0][1]); + histos.fill(HIST("MCRecoEffCorr/Prof_Mult_Nchrec_Ka"), multPV, sumWkRecoEffCor[isp][0][0][1]); + if (sumWkRecoEffCor[isp][0][0][1] > 1.0f) { + histos.fill(HIST("MCRecoEffCorr/Prof_Cent_MeanpT_Ka"), cent, meanRecoEffCor[isp][0][0]); + histos.fill(HIST("MCRecoEffCorr/Prof_Mult_MeanpT_Ka"), multPV, meanRecoEffCor[isp][0][0]); } + } else if (isp == numKProton) { + histos.fill(HIST("MCRecoEffCorr/Prof_Cent_Nchrec_Pr"), cent, sumWkRecoEffCor[isp][0][0][1]); + histos.fill(HIST("MCRecoEffCorr/Prof_Mult_Nchrec_Pr"), multPV, sumWkRecoEffCor[isp][0][0][1]); + if (sumWkRecoEffCor[isp][0][0][1] > 1.0f) { + histos.fill(HIST("MCRecoEffCorr/Prof_Cent_MeanpT_Pr"), cent, meanRecoEffCor[isp][0][0]); + histos.fill(HIST("MCRecoEffCorr/Prof_Mult_MeanpT_Pr"), multPV, meanRecoEffCor[isp][0][0]); + } + } + } + + // --- 3. Fill 1D Profiles: Gen, Reco, and EffCorr Levels --- + for (int ieta = 0; ieta < KNEta; ++ieta) { + for (int ipt = 0; ipt < KNpT; ++ipt) { + for (int isp = 0; isp < KNsp; ++isp) { + + if (isp == numKInclusive) { // Inclusive (No suffix) + // --- MCGen (Truth) --- + if (std::isfinite(meanTru[0][ieta][ipt])) { + histos.fill(HIST("MCGen/Prof_MeanpT_Cent_etabin_ptbin"), cent, ieta, ipt, meanTru[0][ieta][ipt]); + histos.fill(HIST("MCGen/Prof_MeanpT_Mult_etabin_ptbin"), col.multNTracksPV(), ieta, ipt, meanTru[0][ieta][ipt]); + } + if (std::isfinite(c2Tru[0][ieta][ipt])) { + histos.fill(HIST("MCGen/Prof_C2_Cent_etabin_ptbin"), cent, ieta, ipt, c2Tru[0][ieta][ipt]); + histos.fill(HIST("MCGen/Prof_C2_Mult_etabin_ptbin"), col.multNTracksPV(), ieta, ipt, c2Tru[0][ieta][ipt]); + } + // --- MCReco --- + if (std::isfinite(meanReco[0][ieta][ipt])) { + histos.fill(HIST("MCReco/Prof_MeanpT_Cent_etabin_ptbin"), cent, ieta, ipt, meanReco[0][ieta][ipt]); + histos.fill(HIST("MCReco/Prof_MeanpT_Mult_etabin_ptbin"), col.multNTracksPV(), ieta, ipt, meanReco[0][ieta][ipt]); + } + if (std::isfinite(c2Reco[0][ieta][ipt])) { + histos.fill(HIST("MCReco/Prof_C2_Cent_etabin_ptbin"), cent, ieta, ipt, c2Reco[0][ieta][ipt]); + histos.fill(HIST("MCReco/Prof_C2_Mult_etabin_ptbin"), col.multNTracksPV(), ieta, ipt, c2Reco[0][ieta][ipt]); + } + // --- MCRecoEffCorr --- + if (std::isfinite(meanRecoEffCor[0][ieta][ipt])) { + histos.fill(HIST("MCRecoEffCorr/Prof_MeanpT_Cent_etabin_ptbin"), cent, ieta, ipt, meanRecoEffCor[0][ieta][ipt]); + histos.fill(HIST("MCRecoEffCorr/Prof_MeanpT_Mult_etabin_ptbin"), col.multNTracksPV(), ieta, ipt, meanRecoEffCor[0][ieta][ipt]); + } + if (std::isfinite(c2RecoEffCor[0][ieta][ipt])) { + histos.fill(HIST("MCRecoEffCorr/Prof_C2_Cent_etabin_ptbin"), cent, ieta, ipt, c2RecoEffCor[0][ieta][ipt]); + histos.fill(HIST("MCRecoEffCorr/Prof_C2_Mult_etabin_ptbin"), col.multNTracksPV(), ieta, ipt, c2RecoEffCor[0][ieta][ipt]); + } + + } else if (isp == numKPion) { // Pions (_Pi) + // --- MCGen (Truth) --- + if (std::isfinite(meanTru[1][ieta][ipt])) { + histos.fill(HIST("MCGen/Prof_MeanpT_Cent_etabin_ptbin_Pi"), cent, ieta, ipt, meanTru[1][ieta][ipt]); + histos.fill(HIST("MCGen/Prof_MeanpT_Mult_etabin_ptbin_Pi"), col.multNTracksPV(), ieta, ipt, meanTru[1][ieta][ipt]); + } + if (std::isfinite(c2Tru[1][ieta][ipt])) { + histos.fill(HIST("MCGen/Prof_C2_Cent_etabin_ptbin_Pi"), cent, ieta, ipt, c2Tru[1][ieta][ipt]); + histos.fill(HIST("MCGen/Prof_C2_Mult_etabin_ptbin_Pi"), col.multNTracksPV(), ieta, ipt, c2Tru[1][ieta][ipt]); + } + // --- MCReco --- + if (std::isfinite(meanReco[1][ieta][ipt])) { + histos.fill(HIST("MCReco/Prof_MeanpT_Cent_etabin_ptbin_Pi"), cent, ieta, ipt, meanReco[1][ieta][ipt]); + histos.fill(HIST("MCReco/Prof_MeanpT_Mult_etabin_ptbin_Pi"), col.multNTracksPV(), ieta, ipt, meanReco[1][ieta][ipt]); + } + if (std::isfinite(c2Reco[1][ieta][ipt])) { + histos.fill(HIST("MCReco/Prof_C2_Cent_etabin_ptbin_Pi"), cent, ieta, ipt, c2Reco[1][ieta][ipt]); + histos.fill(HIST("MCReco/Prof_C2_Mult_etabin_ptbin_Pi"), col.multNTracksPV(), ieta, ipt, c2Reco[1][ieta][ipt]); + } + // --- MCRecoEffCorr --- + if (std::isfinite(meanRecoEffCor[1][ieta][ipt])) { + histos.fill(HIST("MCRecoEffCorr/Prof_MeanpT_Cent_etabin_ptbin_Pi"), cent, ieta, ipt, meanRecoEffCor[1][ieta][ipt]); + histos.fill(HIST("MCRecoEffCorr/Prof_MeanpT_Mult_etabin_ptbin_Pi"), col.multNTracksPV(), ieta, ipt, meanRecoEffCor[1][ieta][ipt]); + } + if (std::isfinite(c2RecoEffCor[1][ieta][ipt])) { + histos.fill(HIST("MCRecoEffCorr/Prof_C2_Cent_etabin_ptbin_Pi"), cent, ieta, ipt, c2RecoEffCor[1][ieta][ipt]); + histos.fill(HIST("MCRecoEffCorr/Prof_C2_Mult_etabin_ptbin_Pi"), col.multNTracksPV(), ieta, ipt, c2RecoEffCor[1][ieta][ipt]); + } + + } else if (isp == numKKaon) { // Kaons (_Ka) + // --- MCGen (Truth) --- + if (std::isfinite(meanTru[2][ieta][ipt])) { + histos.fill(HIST("MCGen/Prof_MeanpT_Cent_etabin_ptbin_Ka"), cent, ieta, ipt, meanTru[2][ieta][ipt]); + histos.fill(HIST("MCGen/Prof_MeanpT_Mult_etabin_ptbin_Ka"), col.multNTracksPV(), ieta, ipt, meanTru[2][ieta][ipt]); + } + if (std::isfinite(c2Tru[2][ieta][ipt])) { + histos.fill(HIST("MCGen/Prof_C2_Cent_etabin_ptbin_Ka"), cent, ieta, ipt, c2Tru[2][ieta][ipt]); + histos.fill(HIST("MCGen/Prof_C2_Mult_etabin_ptbin_Ka"), col.multNTracksPV(), ieta, ipt, c2Tru[2][ieta][ipt]); + } + // --- MCReco --- + if (std::isfinite(meanReco[2][ieta][ipt])) { + histos.fill(HIST("MCReco/Prof_MeanpT_Cent_etabin_ptbin_Ka"), cent, ieta, ipt, meanReco[2][ieta][ipt]); + histos.fill(HIST("MCReco/Prof_MeanpT_Mult_etabin_ptbin_Ka"), col.multNTracksPV(), ieta, ipt, meanReco[2][ieta][ipt]); + } + if (std::isfinite(c2Reco[2][ieta][ipt])) { + histos.fill(HIST("MCReco/Prof_C2_Cent_etabin_ptbin_Ka"), cent, ieta, ipt, c2Reco[2][ieta][ipt]); + histos.fill(HIST("MCReco/Prof_C2_Mult_etabin_ptbin_Ka"), col.multNTracksPV(), ieta, ipt, c2Reco[2][ieta][ipt]); + } + // --- MCRecoEffCorr --- + if (std::isfinite(meanRecoEffCor[2][ieta][ipt])) { + histos.fill(HIST("MCRecoEffCorr/Prof_MeanpT_Cent_etabin_ptbin_Ka"), cent, ieta, ipt, meanRecoEffCor[2][ieta][ipt]); + histos.fill(HIST("MCRecoEffCorr/Prof_MeanpT_Mult_etabin_ptbin_Ka"), col.multNTracksPV(), ieta, ipt, meanRecoEffCor[2][ieta][ipt]); + } + if (std::isfinite(c2RecoEffCor[2][ieta][ipt])) { + histos.fill(HIST("MCRecoEffCorr/Prof_C2_Cent_etabin_ptbin_Ka"), cent, ieta, ipt, c2RecoEffCor[2][ieta][ipt]); + histos.fill(HIST("MCRecoEffCorr/Prof_C2_Mult_etabin_ptbin_Ka"), col.multNTracksPV(), ieta, ipt, c2RecoEffCor[2][ieta][ipt]); + } - if (std::isfinite(cov_RecoEffCor_AC)) { - histos.fill(HIST("MCRecoEffCorr/Prof_Cov_Mult_etabin_ptbin"), col.multNTracksPV(), ietaA, ipt, cov_RecoEffCor_AC); - histos.fill(HIST("MCRecoEffCorr/Prof_Cov_Cent_etabin_ptbin"), cent, ietaA, ipt, cov_Reco_AC); + } else if (isp == numKProton) { // Protons (_Pr) + // --- MCGen (Truth) --- + if (std::isfinite(meanTru[3][ieta][ipt])) { + histos.fill(HIST("MCGen/Prof_MeanpT_Cent_etabin_ptbin_Pr"), cent, ieta, ipt, meanTru[3][ieta][ipt]); + histos.fill(HIST("MCGen/Prof_MeanpT_Mult_etabin_ptbin_Pr"), col.multNTracksPV(), ieta, ipt, meanTru[3][ieta][ipt]); + } + if (std::isfinite(c2Tru[3][ieta][ipt])) { + histos.fill(HIST("MCGen/Prof_C2_Cent_etabin_ptbin_Pr"), cent, ieta, ipt, c2Tru[3][ieta][ipt]); + histos.fill(HIST("MCGen/Prof_C2_Mult_etabin_ptbin_Pr"), col.multNTracksPV(), ieta, ipt, c2Tru[3][ieta][ipt]); + } + // --- MCReco --- + if (std::isfinite(meanReco[3][ieta][ipt])) { + histos.fill(HIST("MCReco/Prof_MeanpT_Cent_etabin_ptbin_Pr"), cent, ieta, ipt, meanReco[3][ieta][ipt]); + histos.fill(HIST("MCReco/Prof_MeanpT_Mult_etabin_ptbin_Pr"), col.multNTracksPV(), ieta, ipt, meanReco[3][ieta][ipt]); + } + if (std::isfinite(c2Reco[3][ieta][ipt])) { + histos.fill(HIST("MCReco/Prof_C2_Cent_etabin_ptbin_Pr"), cent, ieta, ipt, c2Reco[3][ieta][ipt]); + histos.fill(HIST("MCReco/Prof_C2_Mult_etabin_ptbin_Pr"), col.multNTracksPV(), ieta, ipt, c2Reco[3][ieta][ipt]); + } + // --- MCRecoEffCorr --- + if (std::isfinite(meanRecoEffCor[3][ieta][ipt])) { + histos.fill(HIST("MCRecoEffCorr/Prof_MeanpT_Cent_etabin_ptbin_Pr"), cent, ieta, ipt, meanRecoEffCor[3][ieta][ipt]); + histos.fill(HIST("MCRecoEffCorr/Prof_MeanpT_Mult_etabin_ptbin_Pr"), col.multNTracksPV(), ieta, ipt, meanRecoEffCor[3][ieta][ipt]); + } + if (std::isfinite(c2RecoEffCor[3][ieta][ipt])) { + histos.fill(HIST("MCRecoEffCorr/Prof_C2_Cent_etabin_ptbin_Pr"), cent, ieta, ipt, c2RecoEffCor[3][ieta][ipt]); + histos.fill(HIST("MCRecoEffCorr/Prof_C2_Mult_etabin_ptbin_Pr"), col.multNTracksPV(), ieta, ipt, c2RecoEffCor[3][ieta][ipt]); + } + } } - if (std::isfinite(cov_RecoEffCor_CA)) { - histos.fill(HIST("MCRecoEffCorr/Prof_Cov_Mult_etabin_ptbin"), col.multNTracksPV(), ietaA, ipt, cov_RecoEffCor_CA); - histos.fill(HIST("MCRecoEffCorr/Prof_Cov_Cent_etabin_ptbin"), cent, ietaA, ipt, cov_Reco_CA); + } + } + + // --- 4. Symmetric Sub-Event (1D) Covariances --- + for (int ietaA = 1; ietaA <= (KNEta - 1) / 2; ++ietaA) { + int ietaC = KNEta - ietaA; + for (int ipt = 0; ipt < KNpT; ++ipt) { + for (int isp = 0; isp < KNsp; ++isp) { + float c2SubTru = p1kBarTru[isp][ietaA][ipt] * p1kBarTru[isp][ietaC][ipt]; + float c2SubReco = p1kBarReco[isp][ietaA][ipt] * p1kBarReco[isp][ietaC][ipt]; + float c2SubRecoEffCor = p1kBarRecoEffCor[isp][ietaA][ipt] * p1kBarRecoEffCor[isp][ietaC][ipt]; + + float covTru = p1kBarTruMult[isp][ietaA][ipt] * p1kBarTru[isp][ietaC][ipt]; + float covReco = p1kBarRecoMult[isp][ietaA][ipt] * p1kBarReco[isp][ietaC][ipt]; + float covRecoEffCor = p1kBarRecoEffCorMult[isp][ietaA][ipt] * p1kBarRecoEffCor[isp][ietaC][ipt]; + + if (isp == numKInclusive) { + if (std::isfinite(c2SubTru)) { + histos.fill(HIST("MCGen/Prof_C2Sub_Cent_etabin_ptbin"), cent, ietaA, ipt, c2SubTru); + histos.fill(HIST("MCGen/Prof_C2Sub_Mult_etabin_ptbin"), col.multNTracksPV(), ietaA, ipt, c2SubTru); + } + if (std::isfinite(c2SubReco)) { + histos.fill(HIST("MCReco/Prof_C2Sub_Cent_etabin_ptbin"), cent, ietaA, ipt, c2SubReco); + histos.fill(HIST("MCReco/Prof_C2Sub_Mult_etabin_ptbin"), col.multNTracksPV(), ietaA, ipt, c2SubReco); + } + if (std::isfinite(c2SubRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub_Cent_etabin_ptbin"), cent, ietaA, ipt, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub_Mult_etabin_ptbin"), col.multNTracksPV(), ietaA, ipt, c2SubRecoEffCor); + } + if (std::isfinite(covTru)) { + histos.fill(HIST("MCGen/Prof_Cov_Cent_etabin_ptbin"), cent, ietaA, ipt, covTru); + histos.fill(HIST("MCGen/Prof_Cov_Mult_etabin_ptbin"), col.multNTracksPV(), ietaA, ipt, covTru); + } + if (std::isfinite(covReco)) { + histos.fill(HIST("MCReco/Prof_Cov_Cent_etabin_ptbin"), cent, ietaA, ipt, covReco); + histos.fill(HIST("MCReco/Prof_Cov_Mult_etabin_ptbin"), col.multNTracksPV(), ietaA, ipt, covReco); + } + if (std::isfinite(covRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_Cov_Cent_etabin_ptbin"), cent, ietaA, ipt, covRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_Cov_Mult_etabin_ptbin"), col.multNTracksPV(), ietaA, ipt, covRecoEffCor); + } + + } else if (isp == numKPion) { // Pion + if (std::isfinite(c2SubTru)) { + histos.fill(HIST("MCGen/Prof_C2Sub_Cent_etabin_ptbin_Pi"), cent, ietaA, ipt, c2SubTru); + histos.fill(HIST("MCGen/Prof_C2Sub_Mult_etabin_ptbin_Pi"), col.multNTracksPV(), ietaA, ipt, c2SubTru); + } + if (std::isfinite(c2SubReco)) { + histos.fill(HIST("MCReco/Prof_C2Sub_Cent_etabin_ptbin_Pi"), cent, ietaA, ipt, c2SubReco); + histos.fill(HIST("MCReco/Prof_C2Sub_Mult_etabin_ptbin_Pi"), col.multNTracksPV(), ietaA, ipt, c2SubReco); + } + if (std::isfinite(c2SubRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub_Cent_etabin_ptbin_Pi"), cent, ietaA, ipt, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub_Mult_etabin_ptbin_Pi"), col.multNTracksPV(), ietaA, ipt, c2SubRecoEffCor); + } + if (std::isfinite(covTru)) { + histos.fill(HIST("MCGen/Prof_Cov_Cent_etabin_ptbin_Pi"), cent, ietaA, ipt, covTru); + histos.fill(HIST("MCGen/Prof_Cov_Mult_etabin_ptbin_Pi"), col.multNTracksPV(), ietaA, ipt, covTru); + } + if (std::isfinite(covReco)) { + histos.fill(HIST("MCReco/Prof_Cov_Cent_etabin_ptbin_Pi"), cent, ietaA, ipt, covReco); + histos.fill(HIST("MCReco/Prof_Cov_Mult_etabin_ptbin_Pi"), col.multNTracksPV(), ietaA, ipt, covReco); + } + if (std::isfinite(covRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_Cov_Cent_etabin_ptbin_Pi"), cent, ietaA, ipt, covRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_Cov_Mult_etabin_ptbin_Pi"), col.multNTracksPV(), ietaA, ipt, covRecoEffCor); + } + + } else if (isp == numKKaon) { // Kaon + if (std::isfinite(c2SubTru)) { + histos.fill(HIST("MCGen/Prof_C2Sub_Cent_etabin_ptbin_Ka"), cent, ietaA, ipt, c2SubTru); + histos.fill(HIST("MCGen/Prof_C2Sub_Mult_etabin_ptbin_Ka"), col.multNTracksPV(), ietaA, ipt, c2SubTru); + } + if (std::isfinite(c2SubReco)) { + histos.fill(HIST("MCReco/Prof_C2Sub_Cent_etabin_ptbin_Ka"), cent, ietaA, ipt, c2SubReco); + histos.fill(HIST("MCReco/Prof_C2Sub_Mult_etabin_ptbin_Ka"), col.multNTracksPV(), ietaA, ipt, c2SubReco); + } + if (std::isfinite(c2SubRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub_Cent_etabin_ptbin_Ka"), cent, ietaA, ipt, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub_Mult_etabin_ptbin_Ka"), col.multNTracksPV(), ietaA, ipt, c2SubRecoEffCor); + } + if (std::isfinite(covTru)) { + histos.fill(HIST("MCGen/Prof_Cov_Cent_etabin_ptbin_Ka"), cent, ietaA, ipt, covTru); + histos.fill(HIST("MCGen/Prof_Cov_Mult_etabin_ptbin_Ka"), col.multNTracksPV(), ietaA, ipt, covTru); + } + if (std::isfinite(covReco)) { + histos.fill(HIST("MCReco/Prof_Cov_Cent_etabin_ptbin_Ka"), cent, ietaA, ipt, covReco); + histos.fill(HIST("MCReco/Prof_Cov_Mult_etabin_ptbin_Ka"), col.multNTracksPV(), ietaA, ipt, covReco); + } + if (std::isfinite(covRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_Cov_Cent_etabin_ptbin_Ka"), cent, ietaA, ipt, covRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_Cov_Mult_etabin_ptbin_Ka"), col.multNTracksPV(), ietaA, ipt, covRecoEffCor); + } + } else if (isp == numKProton) { // Proton + if (std::isfinite(c2SubTru)) { + histos.fill(HIST("MCGen/Prof_C2Sub_Cent_etabin_ptbin_Pr"), cent, ietaA, ipt, c2SubTru); + histos.fill(HIST("MCGen/Prof_C2Sub_Mult_etabin_ptbin_Pr"), col.multNTracksPV(), ietaA, ipt, c2SubTru); + } + if (std::isfinite(c2SubReco)) { + histos.fill(HIST("MCReco/Prof_C2Sub_Cent_etabin_ptbin_Pr"), cent, ietaA, ipt, c2SubReco); + histos.fill(HIST("MCReco/Prof_C2Sub_Mult_etabin_ptbin_Pr"), col.multNTracksPV(), ietaA, ipt, c2SubReco); + } + if (std::isfinite(c2SubRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub_Cent_etabin_ptbin_Pr"), cent, ietaA, ipt, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub_Mult_etabin_ptbin_Pr"), col.multNTracksPV(), ietaA, ipt, c2SubRecoEffCor); + } + if (std::isfinite(covTru)) { + histos.fill(HIST("MCGen/Prof_Cov_Cent_etabin_ptbin_Pr"), cent, ietaA, ipt, covTru); + histos.fill(HIST("MCGen/Prof_Cov_Mult_etabin_ptbin_Pr"), col.multNTracksPV(), ietaA, ipt, covTru); + } + if (std::isfinite(covReco)) { + histos.fill(HIST("MCReco/Prof_Cov_Cent_etabin_ptbin_Pr"), cent, ietaA, ipt, covReco); + histos.fill(HIST("MCReco/Prof_Cov_Mult_etabin_ptbin_Pr"), col.multNTracksPV(), ietaA, ipt, covReco); + } + if (std::isfinite(covRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_Cov_Cent_etabin_ptbin_Pr"), cent, ietaA, ipt, covRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_Cov_Mult_etabin_ptbin_Pr"), col.multNTracksPV(), ietaA, ipt, covRecoEffCor); + } + } } } } + // --- 5. Full 2D Covariances & GapSum2D Profiles --- for (int ietaA = 1; ietaA < KNEta; ++ietaA) { - for (int ietaC = 1; ietaC < KNEta; ++ietaC) { + for (int ietaB = 1; ietaB < KNEta; ++ietaB) { + + // Gap and Sum calculations + float etaValA = (etaLw[ietaA] + etaUp[ietaA]) / 2.0f; + float etaValB = (etaLw[ietaB] + etaUp[ietaB]) / 2.0f; + float gap = etaValA - etaValB; + float sum = (etaValA + etaValB) / 2.0f; + for (int ipt = 0; ipt < KNpT; ++ipt) { - float c2Sub_Tru = p1kBarTru[ietaA][ipt] * p1kBarTru[ietaC][ipt]; - float c2SubEt_Tru = p1kBarTruEt[ietaA][ipt] * p1kBarTruEt[ietaC][ipt]; - float c2Sub_Reco = p1kBarReco[ietaA][ipt] * p1kBarReco[ietaC][ipt]; - float c2SubEt_Reco = p1kBarRecoEt[ietaA][ipt] * p1kBarRecoEt[ietaC][ipt]; - float c2Sub_RecoEffCor = p1kBarRecoEffCor[ietaA][ipt] * p1kBarRecoEffCor[ietaC][ipt]; - float c2SubEt_RecoEffCor = p1kBarRecoEffCorEt[ietaA][ipt] * p1kBarRecoEffCorEt[ietaC][ipt]; - float cov_Tru = p1kBarTruMult[ietaA][ipt] * p1kBarTru[ietaC][ipt]; - float cov_Reco = p1kBarRecoMult[ietaA][ipt] * p1kBarReco[ietaC][ipt]; - float cov_RecoEffCor = p1kBarRecoEffCorMult[ietaA][ipt] * p1kBarRecoEffCor[ietaC][ipt]; - switch (ipt) { - case 0: - if (std::isfinite(c2Sub_Tru)) - histos.fill(HIST("MCGen/Prof_ipt0_C2Sub2D_Cent_etaA_etaC"), cent, ietaA, ietaC, c2Sub_Tru); - if (std::isfinite(c2SubEt_Tru)) - histos.fill(HIST("MCGen/Prof_ipt0_C2EtSub2D_Cent_etaA_etaC"), cent, ietaA, ietaC, c2SubEt_Tru); - if (std::isfinite(c2Sub_Reco)) - histos.fill(HIST("MCReco/Prof_ipt0_C2Sub2D_Cent_etaA_etaC"), cent, ietaA, ietaC, c2Sub_Reco); - if (std::isfinite(c2SubEt_Reco)) - histos.fill(HIST("MCReco/Prof_ipt0_C2EtSub2D_Cent_etaA_etaC"), cent, ietaA, ietaC, c2SubEt_Reco); - if (std::isfinite(c2Sub_RecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_ipt0_C2Sub2D_Cent_etaA_etaC"), cent, ietaA, ietaC, c2Sub_RecoEffCor); - if (std::isfinite(c2SubEt_RecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_ipt0_C2EtSub2D_Cent_etaA_etaC"), cent, ietaA, ietaC, c2SubEt_RecoEffCor); - - if (std::isfinite(cov_Tru)) - histos.fill(HIST("MCGen/Prof_ipt0_Cov2D_Cent_etaA_etaC"), cent, ietaA, ietaC, cov_Tru); - if (std::isfinite(cov_Reco)) - histos.fill(HIST("MCReco/Prof_ipt0_Cov2D_Cent_etaA_etaC"), cent, ietaA, ietaC, cov_Reco); - if (std::isfinite(cov_RecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_ipt0_Cov2D_Cent_etaA_etaC"), cent, ietaA, ietaC, cov_RecoEffCor); - - break; - case 1: - if (std::isfinite(c2Sub_Tru)) - histos.fill(HIST("MCGen/Prof_ipt1_C2Sub2D_Cent_etaA_etaC"), cent, ietaA, ietaC, c2Sub_Tru); - if (std::isfinite(c2SubEt_Tru)) - histos.fill(HIST("MCGen/Prof_ipt1_C2EtSub2D_Cent_etaA_etaC"), cent, ietaA, ietaC, c2SubEt_Tru); - if (std::isfinite(c2Sub_Reco)) - histos.fill(HIST("MCReco/Prof_ipt1_C2Sub2D_Cent_etaA_etaC"), cent, ietaA, ietaC, c2Sub_Reco); - if (std::isfinite(c2SubEt_Reco)) - histos.fill(HIST("MCReco/Prof_ipt1_C2EtSub2D_Cent_etaA_etaC"), cent, ietaA, ietaC, c2SubEt_Reco); - if (std::isfinite(c2Sub_RecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_ipt1_C2Sub2D_Cent_etaA_etaC"), cent, ietaA, ietaC, c2Sub_RecoEffCor); - if (std::isfinite(c2SubEt_RecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_ipt1_C2EtSub2D_Cent_etaA_etaC"), cent, ietaA, ietaC, c2SubEt_RecoEffCor); - - if (std::isfinite(cov_Tru)) - histos.fill(HIST("MCGen/Prof_ipt1_Cov2D_Cent_etaA_etaC"), cent, ietaA, ietaC, cov_Tru); - if (std::isfinite(cov_Reco)) - histos.fill(HIST("MCReco/Prof_ipt1_Cov2D_Cent_etaA_etaC"), cent, ietaA, ietaC, cov_Reco); - if (std::isfinite(cov_RecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_ipt1_Cov2D_Cent_etaA_etaC"), cent, ietaA, ietaC, cov_RecoEffCor); - - break; - case 2: - if (std::isfinite(c2Sub_Tru)) - histos.fill(HIST("MCGen/Prof_ipt2_C2Sub2D_Cent_etaA_etaC"), cent, ietaA, ietaC, c2Sub_Tru); - if (std::isfinite(c2SubEt_Tru)) - histos.fill(HIST("MCGen/Prof_ipt2_C2EtSub2D_Cent_etaA_etaC"), cent, ietaA, ietaC, c2SubEt_Tru); - if (std::isfinite(c2Sub_Reco)) - histos.fill(HIST("MCReco/Prof_ipt2_C2Sub2D_Cent_etaA_etaC"), cent, ietaA, ietaC, c2Sub_Reco); - if (std::isfinite(c2SubEt_Reco)) - histos.fill(HIST("MCReco/Prof_ipt2_C2EtSub2D_Cent_etaA_etaC"), cent, ietaA, ietaC, c2SubEt_Reco); - if (std::isfinite(c2Sub_RecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_ipt2_C2Sub2D_Cent_etaA_etaC"), cent, ietaA, ietaC, c2Sub_RecoEffCor); - if (std::isfinite(c2SubEt_RecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_ipt2_C2EtSub2D_Cent_etaA_etaC"), cent, ietaA, ietaC, c2SubEt_RecoEffCor); - - if (std::isfinite(cov_Tru)) - histos.fill(HIST("MCGen/Prof_ipt2_Cov2D_Cent_etaA_etaC"), cent, ietaA, ietaC, cov_Tru); - if (std::isfinite(cov_Reco)) - histos.fill(HIST("MCReco/Prof_ipt2_Cov2D_Cent_etaA_etaC"), cent, ietaA, ietaC, cov_Reco); - if (std::isfinite(cov_RecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_ipt2_Cov2D_Cent_etaA_etaC"), cent, ietaA, ietaC, cov_RecoEffCor); - - break; + for (int isp = 0; isp < KNsp; ++isp) { + + float c2SubTru = p1kBarTru[isp][ietaA][ipt] * p1kBarTru[isp][ietaB][ipt]; + float c2SubReco = p1kBarReco[isp][ietaA][ipt] * p1kBarReco[isp][ietaB][ipt]; + float c2SubRecoEffCor = p1kBarRecoEffCor[isp][ietaA][ipt] * p1kBarRecoEffCor[isp][ietaB][ipt]; + + float covTru = p1kBarTruMult[isp][ietaA][ipt] * p1kBarTru[isp][ietaB][ipt]; + float covReco = p1kBarRecoMult[isp][ietaA][ipt] * p1kBarReco[isp][ietaB][ipt]; + float covRecoEffCor = p1kBarRecoEffCorMult[isp][ietaA][ipt] * p1kBarRecoEffCor[isp][ietaB][ipt]; + + if (isp == numKInclusive) { // Inclusive + if (ipt == 0) { + if (std::isfinite(c2SubTru)) { + histos.fill(HIST("MCGen/Prof_ipt0_C2Sub2D_Cent_etaA_etaC"), cent, etaValA, etaValB, c2SubTru); + histos.fill(HIST("MCGen/Prof_ipt0_GapSum2D"), cent, gap, sum, c2SubTru); + } + if (std::isfinite(c2SubReco)) { + histos.fill(HIST("MCReco/Prof_ipt0_C2Sub2D_Cent_etaA_etaC"), cent, etaValA, etaValB, c2SubReco); + histos.fill(HIST("MCReco/Prof_ipt0_GapSum2D"), cent, gap, sum, c2SubReco); + } + if (std::isfinite(c2SubRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_ipt0_C2Sub2D_Cent_etaA_etaC"), cent, etaValA, etaValB, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_ipt0_GapSum2D"), cent, gap, sum, c2SubRecoEffCor); + } + if (std::isfinite(covTru)) + histos.fill(HIST("MCGen/Prof_ipt0_Cov2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covTru); + if (std::isfinite(covReco)) + histos.fill(HIST("MCReco/Prof_ipt0_Cov2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covReco); + if (std::isfinite(covRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_ipt0_Cov2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covRecoEffCor); + } else if (ipt == KNpT - 2) { + if (std::isfinite(c2SubTru)) { + histos.fill(HIST("MCGen/Prof_ipt1_C2Sub2D_Cent_etaA_etaC"), cent, etaValA, etaValB, c2SubTru); + histos.fill(HIST("MCGen/Prof_ipt1_GapSum2D"), cent, gap, sum, c2SubTru); + } + if (std::isfinite(c2SubReco)) { + histos.fill(HIST("MCReco/Prof_ipt1_C2Sub2D_Cent_etaA_etaC"), cent, etaValA, etaValB, c2SubReco); + histos.fill(HIST("MCReco/Prof_ipt1_GapSum2D"), cent, gap, sum, c2SubReco); + } + if (std::isfinite(c2SubRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_ipt1_C2Sub2D_Cent_etaA_etaC"), cent, etaValA, etaValB, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_ipt1_GapSum2D"), cent, gap, sum, c2SubRecoEffCor); + } + if (std::isfinite(covTru)) + histos.fill(HIST("MCGen/Prof_ipt1_Cov2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covTru); + if (std::isfinite(covReco)) + histos.fill(HIST("MCReco/Prof_ipt1_Cov2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covReco); + if (std::isfinite(covRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_ipt1_Cov2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covRecoEffCor); + } else if (ipt == KNpT - 1) { + if (std::isfinite(c2SubTru)) { + histos.fill(HIST("MCGen/Prof_ipt2_C2Sub2D_Cent_etaA_etaC"), cent, etaValA, etaValB, c2SubTru); + histos.fill(HIST("MCGen/Prof_ipt2_GapSum2D"), cent, gap, sum, c2SubTru); + } + if (std::isfinite(c2SubReco)) { + histos.fill(HIST("MCReco/Prof_ipt2_C2Sub2D_Cent_etaA_etaC"), cent, etaValA, etaValB, c2SubReco); + histos.fill(HIST("MCReco/Prof_ipt2_GapSum2D"), cent, gap, sum, c2SubReco); + } + if (std::isfinite(c2SubRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_ipt2_C2Sub2D_Cent_etaA_etaC"), cent, etaValA, etaValB, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_ipt2_GapSum2D"), cent, gap, sum, c2SubRecoEffCor); + } + if (std::isfinite(covTru)) + histos.fill(HIST("MCGen/Prof_ipt2_Cov2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covTru); + if (std::isfinite(covReco)) + histos.fill(HIST("MCReco/Prof_ipt2_Cov2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covReco); + if (std::isfinite(covRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_ipt2_Cov2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covRecoEffCor); + } + + } else if (isp == numKPion) { // Pion + if (ipt == 0) { + if (std::isfinite(c2SubTru)) { + histos.fill(HIST("MCGen/Prof_ipt0_C2Sub2D_Cent_etaA_etaC_Pi"), cent, etaValA, etaValB, c2SubTru); + histos.fill(HIST("MCGen/Prof_ipt0_GapSum2D_Pi"), cent, gap, sum, c2SubTru); + } + if (std::isfinite(c2SubReco)) { + histos.fill(HIST("MCReco/Prof_ipt0_C2Sub2D_Cent_etaA_etaC_Pi"), cent, etaValA, etaValB, c2SubReco); + histos.fill(HIST("MCReco/Prof_ipt0_GapSum2D_Pi"), cent, gap, sum, c2SubReco); + } + if (std::isfinite(c2SubRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_ipt0_C2Sub2D_Cent_etaA_etaC_Pi"), cent, etaValA, etaValB, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_ipt0_GapSum2D_Pi"), cent, gap, sum, c2SubRecoEffCor); + } + if (std::isfinite(covTru)) + histos.fill(HIST("MCGen/Prof_ipt0_Cov2D_Cent_etaA_etaC_Pi"), cent, etaValA, etaValB, covTru); + if (std::isfinite(covReco)) + histos.fill(HIST("MCReco/Prof_ipt0_Cov2D_Cent_etaA_etaC_Pi"), cent, etaValA, etaValB, covReco); + if (std::isfinite(covRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_ipt0_Cov2D_Cent_etaA_etaC_Pi"), cent, etaValA, etaValB, covRecoEffCor); + } else if (ipt == KNpT - 2) { + if (std::isfinite(c2SubTru)) { + histos.fill(HIST("MCGen/Prof_ipt1_C2Sub2D_Cent_etaA_etaC_Pi"), cent, etaValA, etaValB, c2SubTru); + histos.fill(HIST("MCGen/Prof_ipt1_GapSum2D_Pi"), cent, gap, sum, c2SubTru); + } + if (std::isfinite(c2SubReco)) { + histos.fill(HIST("MCReco/Prof_ipt1_C2Sub2D_Cent_etaA_etaC_Pi"), cent, etaValA, etaValB, c2SubReco); + histos.fill(HIST("MCReco/Prof_ipt1_GapSum2D_Pi"), cent, gap, sum, c2SubReco); + } + if (std::isfinite(c2SubRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_ipt1_C2Sub2D_Cent_etaA_etaC_Pi"), cent, etaValA, etaValB, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_ipt1_GapSum2D_Pi"), cent, gap, sum, c2SubRecoEffCor); + } + if (std::isfinite(covTru)) + histos.fill(HIST("MCGen/Prof_ipt1_Cov2D_Cent_etaA_etaC_Pi"), cent, etaValA, etaValB, covTru); + if (std::isfinite(covReco)) + histos.fill(HIST("MCReco/Prof_ipt1_Cov2D_Cent_etaA_etaC_Pi"), cent, etaValA, etaValB, covReco); + if (std::isfinite(covRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_ipt1_Cov2D_Cent_etaA_etaC_Pi"), cent, etaValA, etaValB, covRecoEffCor); + } else if (ipt == KNpT - 1) { + if (std::isfinite(c2SubTru)) { + histos.fill(HIST("MCGen/Prof_ipt2_C2Sub2D_Cent_etaA_etaC_Pi"), cent, etaValA, etaValB, c2SubTru); + histos.fill(HIST("MCGen/Prof_ipt2_GapSum2D_Pi"), cent, gap, sum, c2SubTru); + } + if (std::isfinite(c2SubReco)) { + histos.fill(HIST("MCReco/Prof_ipt2_C2Sub2D_Cent_etaA_etaC_Pi"), cent, etaValA, etaValB, c2SubReco); + histos.fill(HIST("MCReco/Prof_ipt2_GapSum2D_Pi"), cent, gap, sum, c2SubReco); + } + if (std::isfinite(c2SubRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_ipt2_C2Sub2D_Cent_etaA_etaC_Pi"), cent, etaValA, etaValB, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_ipt2_GapSum2D_Pi"), cent, gap, sum, c2SubRecoEffCor); + } + if (std::isfinite(covTru)) + histos.fill(HIST("MCGen/Prof_ipt2_Cov2D_Cent_etaA_etaC_Pi"), cent, etaValA, etaValB, covTru); + if (std::isfinite(covReco)) + histos.fill(HIST("MCReco/Prof_ipt2_Cov2D_Cent_etaA_etaC_Pi"), cent, etaValA, etaValB, covReco); + if (std::isfinite(covRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_ipt2_Cov2D_Cent_etaA_etaC_Pi"), cent, etaValA, etaValB, covRecoEffCor); + } + } else if (isp == numKKaon) { // Kaon + if (ipt == 0) { + if (std::isfinite(c2SubTru)) { + histos.fill(HIST("MCGen/Prof_ipt0_C2Sub2D_Cent_etaA_etaC_Ka"), cent, etaValA, etaValB, c2SubTru); + histos.fill(HIST("MCGen/Prof_ipt0_GapSum2D_Ka"), cent, gap, sum, c2SubTru); + } + if (std::isfinite(c2SubReco)) { + histos.fill(HIST("MCReco/Prof_ipt0_C2Sub2D_Cent_etaA_etaC_Ka"), cent, etaValA, etaValB, c2SubReco); + histos.fill(HIST("MCReco/Prof_ipt0_GapSum2D_Ka"), cent, gap, sum, c2SubReco); + } + if (std::isfinite(c2SubRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_ipt0_C2Sub2D_Cent_etaA_etaC_Ka"), cent, etaValA, etaValB, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_ipt0_GapSum2D_Ka"), cent, gap, sum, c2SubRecoEffCor); + } + if (std::isfinite(covTru)) + histos.fill(HIST("MCGen/Prof_ipt0_Cov2D_Cent_etaA_etaC_Ka"), cent, etaValA, etaValB, covTru); + if (std::isfinite(covReco)) + histos.fill(HIST("MCReco/Prof_ipt0_Cov2D_Cent_etaA_etaC_Ka"), cent, etaValA, etaValB, covReco); + if (std::isfinite(covRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_ipt0_Cov2D_Cent_etaA_etaC_Ka"), cent, etaValA, etaValB, covRecoEffCor); + } else if (ipt == KNpT - 2) { + if (std::isfinite(c2SubTru)) { + histos.fill(HIST("MCGen/Prof_ipt1_C2Sub2D_Cent_etaA_etaC_Ka"), cent, etaValA, etaValB, c2SubTru); + histos.fill(HIST("MCGen/Prof_ipt1_GapSum2D_Ka"), cent, gap, sum, c2SubTru); + } + if (std::isfinite(c2SubReco)) { + histos.fill(HIST("MCReco/Prof_ipt1_C2Sub2D_Cent_etaA_etaC_Ka"), cent, etaValA, etaValB, c2SubReco); + histos.fill(HIST("MCReco/Prof_ipt1_GapSum2D_Ka"), cent, gap, sum, c2SubReco); + } + if (std::isfinite(c2SubRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_ipt1_C2Sub2D_Cent_etaA_etaC_Ka"), cent, etaValA, etaValB, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_ipt1_GapSum2D_Ka"), cent, gap, sum, c2SubRecoEffCor); + } + if (std::isfinite(covTru)) + histos.fill(HIST("MCGen/Prof_ipt1_Cov2D_Cent_etaA_etaC_Ka"), cent, etaValA, etaValB, covTru); + if (std::isfinite(covReco)) + histos.fill(HIST("MCReco/Prof_ipt1_Cov2D_Cent_etaA_etaC_Ka"), cent, etaValA, etaValB, covReco); + if (std::isfinite(covRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_ipt1_Cov2D_Cent_etaA_etaC_Ka"), cent, etaValA, etaValB, covRecoEffCor); + } else if (ipt == KNpT - 1) { + if (std::isfinite(c2SubTru)) { + histos.fill(HIST("MCGen/Prof_ipt2_C2Sub2D_Cent_etaA_etaC_Ka"), cent, etaValA, etaValB, c2SubTru); + histos.fill(HIST("MCGen/Prof_ipt2_GapSum2D_Ka"), cent, gap, sum, c2SubTru); + } + if (std::isfinite(c2SubReco)) { + histos.fill(HIST("MCReco/Prof_ipt2_C2Sub2D_Cent_etaA_etaC_Ka"), cent, etaValA, etaValB, c2SubReco); + histos.fill(HIST("MCReco/Prof_ipt2_GapSum2D_Ka"), cent, gap, sum, c2SubReco); + } + if (std::isfinite(c2SubRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_ipt2_C2Sub2D_Cent_etaA_etaC_Ka"), cent, etaValA, etaValB, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_ipt2_GapSum2D_Ka"), cent, gap, sum, c2SubRecoEffCor); + } + if (std::isfinite(covTru)) + histos.fill(HIST("MCGen/Prof_ipt2_Cov2D_Cent_etaA_etaC_Ka"), cent, etaValA, etaValB, covTru); + if (std::isfinite(covReco)) + histos.fill(HIST("MCReco/Prof_ipt2_Cov2D_Cent_etaA_etaC_Ka"), cent, etaValA, etaValB, covReco); + if (std::isfinite(covRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_ipt2_Cov2D_Cent_etaA_etaC_Ka"), cent, etaValA, etaValB, covRecoEffCor); + } + } else if (isp == numKProton) { // Proton + if (ipt == 0) { + if (std::isfinite(c2SubTru)) { + histos.fill(HIST("MCGen/Prof_ipt0_C2Sub2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, c2SubTru); + histos.fill(HIST("MCGen/Prof_ipt0_GapSum2D_Pr"), cent, gap, sum, c2SubTru); + } + if (std::isfinite(c2SubReco)) { + histos.fill(HIST("MCReco/Prof_ipt0_C2Sub2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, c2SubReco); + histos.fill(HIST("MCReco/Prof_ipt0_GapSum2D_Pr"), cent, gap, sum, c2SubReco); + } + if (std::isfinite(c2SubRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_ipt0_C2Sub2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_ipt0_GapSum2D_Pr"), cent, gap, sum, c2SubRecoEffCor); + } + if (std::isfinite(covTru)) + histos.fill(HIST("MCGen/Prof_ipt0_Cov2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covTru); + if (std::isfinite(covReco)) + histos.fill(HIST("MCReco/Prof_ipt0_Cov2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covReco); + if (std::isfinite(covRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_ipt0_Cov2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covRecoEffCor); + } else if (ipt == KNpT - 2) { + if (std::isfinite(c2SubTru)) { + histos.fill(HIST("MCGen/Prof_ipt1_C2Sub2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, c2SubTru); + histos.fill(HIST("MCGen/Prof_ipt1_GapSum2D_Pr"), cent, gap, sum, c2SubTru); + } + if (std::isfinite(c2SubReco)) { + histos.fill(HIST("MCReco/Prof_ipt1_C2Sub2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, c2SubReco); + histos.fill(HIST("MCReco/Prof_ipt1_GapSum2D_Pr"), cent, gap, sum, c2SubReco); + } + if (std::isfinite(c2SubRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_ipt1_C2Sub2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_ipt1_GapSum2D_Pr"), cent, gap, sum, c2SubRecoEffCor); + } + if (std::isfinite(covTru)) + histos.fill(HIST("MCGen/Prof_ipt1_Cov2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covTru); + if (std::isfinite(covReco)) + histos.fill(HIST("MCReco/Prof_ipt1_Cov2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covReco); + if (std::isfinite(covRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_ipt1_Cov2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covRecoEffCor); + } else if (ipt == KNpT - 1) { + if (std::isfinite(c2SubTru)) { + histos.fill(HIST("MCGen/Prof_ipt2_C2Sub2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, c2SubTru); + histos.fill(HIST("MCGen/Prof_ipt2_GapSum2D_Pr"), cent, gap, sum, c2SubTru); + } + if (std::isfinite(c2SubReco)) { + histos.fill(HIST("MCReco/Prof_ipt2_C2Sub2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, c2SubReco); + histos.fill(HIST("MCReco/Prof_ipt2_GapSum2D_Pr"), cent, gap, sum, c2SubReco); + } + if (std::isfinite(c2SubRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_ipt2_C2Sub2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_ipt2_GapSum2D_Pr"), cent, gap, sum, c2SubRecoEffCor); + } + if (std::isfinite(covTru)) + histos.fill(HIST("MCGen/Prof_ipt2_Cov2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covTru); + if (std::isfinite(covReco)) + histos.fill(HIST("MCReco/Prof_ipt2_Cov2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covReco); + if (std::isfinite(covRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_ipt2_Cov2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covRecoEffCor); + } + } } } } } - } - } - LOGF(info, "FINISHED RUNNING processMCFluc (pT + Et)"); + } // colSlice + } // mcColl + LOGF(info, "FINISHED RUNNING processMCFluc"); } - PROCESS_SWITCH(RadialFlowDecorr, processMCFluc, "process MC to calculate pt/Et fluc", cfgRunMCFluc); + PROCESS_SWITCH(RadialFlowDecorr, processMCFluc, "process MC to calculate pt fluc", cfgRunMCFluc); void processGetDataFlat(AodCollisionsSel::iterator const& coll, BCsRun3 const& /*bcs*/, aod::Zdcs const& /*zdcsData*/, AodTracksSel const& tracks) { @@ -2084,42 +2600,64 @@ struct RadialFlowDecorr { histos.fill(HIST("Hist2D_cent_nch"), tracks.size(), cent); int ntrk = 0; + float vz = coll.posZ(); + for (const auto& track : tracks) { if (!isTrackSelected(track)) continue; + float p = track.p(); float pt = track.pt(); float eta = track.eta(); float phi = track.phi(); + auto sign = track.sign(); + if (p < KFloatEpsilon) continue; - float effIncl = getEfficiency(coll.multNTracksPV(), pt, eta, kInclusive, 0, cfgEff); - float fakeIncl = getEfficiency(coll.multNTracksPV(), pt, eta, kInclusive, 1, cfgEff); - float wIncl = (1.0 - fakeIncl) / effIncl; - if (!std::isfinite(wIncl) || wIncl <= KFloatEpsilon || effIncl <= KFloatEpsilon) - continue; - histos.fill(HIST("hEtaPhiReco"), coll.posZ(), track.sign(), pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoEffWtd"), coll.posZ(), track.sign(), pt, eta, phi, wIncl); + // Count tracks in the primary eta acceptance if (eta > etaLw[0] && eta < etaUp[0]) ntrk++; - const bool isPion = selectionPion(track); - const bool isKaon = selectionKaon(track); - const bool isProton = selectionProton(track); - if (isPion || isKaon || isProton) { - float effPid = getEfficiency(coll.multNTracksPV(), pt, eta, kCombinedPID, 0, cfgEff); - float fakePid = getEfficiency(coll.multNTracksPV(), pt, eta, kCombinedPID, 1, cfgEff); - float wPid = (1.0 - fakePid) / effPid; - if (!std::isfinite(wPid) || wPid <= KFloatEpsilon || effPid <= KFloatEpsilon) + // Define species array (0: Inclusive, 1: Pion, 2: Kaon, 3: Proton) + bool isSpecies[KNsp] = {true, selectionPion(track), selectionKaon(track), selectionProton(track)}; + + for (int isp = 0; isp < KNsp; ++isp) { + if (!isSpecies[isp]) + continue; + + // Fetch efficiency specifically for this particle species + float eff = getEfficiency(coll.multNTracksPV(), pt, eta, static_cast(isp), 0, cfgEff); + float fake = getEfficiency(coll.multNTracksPV(), pt, eta, static_cast(isp), 1, cfgEff); + float w = (1.0 - fake) / eff; + + if (!std::isfinite(w) || w <= KFloatEpsilon || eff <= KFloatEpsilon) continue; - histos.fill(HIST("hEtaPhiReco_PID"), coll.posZ(), track.sign(), pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoEffWtd_PID"), coll.posZ(), track.sign(), pt, eta, phi, wPid); + + // Unrolled THnSparse / QA Fills + if (isp == numKInclusive) { + histos.fill(HIST("hEtaPhiReco"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd"), vz, sign, pt, eta, phi, w); + } else if (isp == numKPion) { // Pion + histos.fill(HIST("hEtaPhiReco_Pi"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd_Pi"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd_Pi"), vz, sign, pt, eta, phi, w); + } else if (isp == numKKaon) { // Kaon + histos.fill(HIST("hEtaPhiReco_Ka"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd_Ka"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd_Ka"), vz, sign, pt, eta, phi, w); + } else if (isp == numKProton) { // Proton + histos.fill(HIST("hEtaPhiReco_Pr"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd_Pr"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd_Pr"), vz, sign, pt, eta, phi, w); + } } } histos.fill(HIST("hCentnTrk"), cent, ntrk); histos.fill(HIST("hCentnTrkPV"), cent, coll.multNTracksPV()); + if (cfgZDC) { const auto& foundBC = coll.foundBC_as(); if (!foundBC.has_zdc()) { @@ -2133,10 +2671,11 @@ struct RadialFlowDecorr { } PROCESS_SWITCH(RadialFlowDecorr, processGetDataFlat, "process data to calculate Flattening maps", cfgRunGetDataFlat); - void processDataMean(AodCollisionsSel::iterator const& coll, aod::BCsWithTimestamps const&, AodTracksSel const& tracks) + void processDataMean(AodCollisionsSel::iterator const& coll, BCsRun3 const& /*bcs*/, aod::Zdcs const& /*zdcsData*/, AodTracksSel const& tracks) { - float sumWi[KNEta][KNpT]{}, sumWipti[KNEta][KNpT]{}; - float sumWiEt[KNEta][KNpT]{}, sumWiEtVal[KNEta][KNpT]{}; + // Expanded to 4 species (isp = 0: Incl, 1: Pi, 2: Ka, 3: Pr) + double sumWi[KNsp][KNEta][KNpT]{}, sumWipti[KNsp][KNEta][KNpT]{}; + if (!isEventSelected(coll)) return; @@ -2150,174 +2689,260 @@ struct RadialFlowDecorr { histos.fill(HIST("Hist2D_globalTracks_PVTracks"), coll.multNTracksPV(), tracks.size()); histos.fill(HIST("Hist2D_cent_nch"), tracks.size(), cent); + float vz = coll.posZ(); + for (const auto& track : tracks) { if (!isTrackSelected(track)) continue; + float pt = track.pt(); float eta = track.eta(); float p = track.p(); float phi = track.phi(); + auto sign = track.sign(); + if (p < KFloatEpsilon) continue; + histos.fill(HIST("hP"), p); histos.fill(HIST("hPt"), pt); histos.fill(HIST("hEta"), eta); - histos.fill(HIST("hPhi"), track.phi()); - - float effIncl = getEfficiency(coll.multNTracksPV(), pt, eta, kInclusive, 0, cfgEff); - float fakeIncl = getEfficiency(coll.multNTracksPV(), pt, eta, kInclusive, 1, cfgEff); - float flatWeightIncl = getFlatteningWeight(coll.posZ(), track.sign(), pt, eta, phi, kInclusive, cfgFlat); - float wIncl = flatWeightIncl * (1.0 - fakeIncl) / effIncl; - if (!std::isfinite(wIncl) || wIncl <= KFloatEpsilon || effIncl <= KFloatEpsilon) - continue; + histos.fill(HIST("hPhi"), phi); - histos.fill(HIST("hEtaPhiReco"), coll.posZ(), track.sign(), pt, eta, track.phi()); - histos.fill(HIST("hEtaPhiRecoEffWtd"), coll.posZ(), track.sign(), eta, pt, track.phi(), (1.0 - fakeIncl) / effIncl); - histos.fill(HIST("hEtaPhiRecoWtd"), coll.posZ(), track.sign(), eta, pt, track.phi(), wIncl); + // Define species array + bool isSpecies[KNsp] = {true, selectionPion(track), selectionKaon(track), selectionProton(track)}; - for (int ieta = 0; ieta < KNEta; ++ieta) { - if (eta <= etaLw[ieta] || eta > etaUp[ieta]) + for (int isp = 0; isp < KNsp; ++isp) { + if (!isSpecies[isp]) continue; - for (int ipt = 0; ipt < KNpT; ++ipt) { - if (pt <= pTLw[ipt] || pt > pTUp[ipt]) - continue; - sumWi[ieta][ipt] += wIncl; - sumWipti[ieta][ipt] += wIncl * pt; - } - } - const bool isPion = selectionPion(track); - const bool isKaon = selectionKaon(track); - const bool isProton = selectionProton(track); - if (isPion || isKaon || isProton) { - float effPid = getEfficiency(coll.multNTracksPV(), pt, eta, kCombinedPID, 0, cfgEff); - float fakePid = getEfficiency(coll.multNTracksPV(), pt, eta, kCombinedPID, 1, cfgEff); - float flatWeightPid = getFlatteningWeight(coll.posZ(), track.sign(), pt, eta, phi, kCombinedPID, cfgFlat); - float wPid = flatWeightPid * (1.0 - fakePid) / effPid; - if (!std::isfinite(wPid) || wPid <= KFloatEpsilon || effPid <= KFloatEpsilon) + float eff = getEfficiency(coll.multNTracksPV(), pt, eta, static_cast(isp), 0, cfgEff); + float fake = getEfficiency(coll.multNTracksPV(), pt, eta, static_cast(isp), 1, cfgEff); + float flatWeight = getFlatteningWeight(vz, sign, pt, eta, phi, static_cast(isp), cfgFlat); + float w = flatWeight * (1.0 - fake) / eff; + + if (!std::isfinite(w) || w <= KFloatEpsilon || eff <= KFloatEpsilon) continue; - histos.fill(HIST("hEtaPhiReco_PID"), coll.posZ(), track.sign(), pt, eta, track.phi()); - histos.fill(HIST("hEtaPhiRecoEffWtd_PID"), coll.posZ(), track.sign(), eta, pt, track.phi(), (1.0 - fakePid) / effPid); - histos.fill(HIST("hEtaPhiRecoWtd_PID"), coll.posZ(), track.sign(), eta, pt, track.phi(), wPid); + // Unrolled THnSparse / QA Fills + if (isp == numKInclusive) { + histos.fill(HIST("hEtaPhiReco"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd"), vz, sign, pt, eta, phi, w); + } else if (isp == numKPion) { // Pion + histos.fill(HIST("hEtaPhiReco_Pi"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd_Pi"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd_Pi"), vz, sign, pt, eta, phi, w); + } else if (isp == numKKaon) { // Kaon + histos.fill(HIST("hEtaPhiReco_Ka"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd_Ka"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd_Ka"), vz, sign, pt, eta, phi, w); + } else if (isp == numKProton) { // Proton + histos.fill(HIST("hEtaPhiReco_Pr"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd_Pr"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd_Pr"), vz, sign, pt, eta, phi, w); + } - float m = isPion ? o2::constants::physics::MassPiPlus : isKaon ? o2::constants::physics::MassKPlus - : o2::constants::physics::MassProton; - float energy = std::sqrt(p * p + m * m); - float et = energy * (pt / p); // E_T = E * sin(theta) + // Accumulate sum for (int ieta = 0; ieta < KNEta; ++ieta) { if (eta <= etaLw[ieta] || eta > etaUp[ieta]) continue; for (int ipt = 0; ipt < KNpT; ++ipt) { if (pt <= pTLw[ipt] || pt > pTUp[ipt]) continue; - sumWiEt[ieta][ipt] += wPid; - sumWiEtVal[ieta][ipt] += wPid * et; + sumWi[isp][ieta][ipt] += w; + sumWipti[isp][ieta][ipt] += w * pt; } } } } - histos.fill(HIST("Prof_cent_Nchrec"), cent, sumWi[0][0]); - if (sumWi[0][0] > 1.0f) - histos.fill(HIST("Prof_Cent_MeanpT"), cent, sumWipti[0][0] / sumWi[0][0]); - if (sumWiEt[0][0] > 1.0f) - histos.fill(HIST("Prof_Cent_MeanEt"), cent, sumWiEtVal[0][0] / sumWiEt[0][0]); - for (int ieta = 0; ieta < KNEta; ++ieta) { - for (int ipt = 0; ipt < KNpT; ++ipt) { - if (sumWi[ieta][ipt] > 1.0f) { - histos.fill(HIST("pmean_nch_etabin_ptbin"), coll.multNTracksPV(), ieta, ipt, sumWipti[ieta][ipt] / sumWi[ieta][ipt]); - histos.fill(HIST("pmeanMult_nch_etabin_ptbin"), coll.multNTracksPV(), ieta, ipt, sumWi[ieta][ipt]); - histos.fill(HIST("pmean_cent_etabin_ptbin"), cent, ieta, ipt, sumWipti[ieta][ipt] / sumWi[ieta][ipt]); - histos.fill(HIST("pmeanMult_cent_etabin_ptbin"), cent, ieta, ipt, sumWi[ieta][ipt]); + // Full Event Means + for (int isp = 0; isp < KNsp; ++isp) { + if (isp == numKInclusive) { + histos.fill(HIST("Prof_Cent_Nchrec"), cent, sumWi[0][0][0]); + histos.fill(HIST("Prof_Mult_Nchrec"), coll.multNTracksPV(), sumWi[0][0][0]); + if (sumWi[0][0][0] > 1.0f) + histos.fill(HIST("Prof_Cent_MeanpT"), cent, sumWipti[0][0][0] / sumWi[0][0][0]); + } else if (isp == numKPion) { + histos.fill(HIST("Prof_Cent_Nchrec_Pi"), cent, sumWi[1][0][0]); + histos.fill(HIST("Prof_Mult_Nchrec_Pi"), coll.multNTracksPV(), sumWi[1][0][0]); + + if (sumWi[1][0][0] > 1.0f) + histos.fill(HIST("Prof_Cent_MeanpT_Pi"), cent, sumWipti[1][0][0] / sumWi[1][0][0]); + } else if (isp == numKKaon) { + histos.fill(HIST("Prof_Cent_Nchrec_Ka"), cent, sumWi[2][0][0]); + histos.fill(HIST("Prof_Mult_Nchrec_Ka"), coll.multNTracksPV(), sumWi[2][0][0]); + + if (sumWi[2][0][0] > 1.0f) + histos.fill(HIST("Prof_Cent_MeanpT_Ka"), cent, sumWipti[2][0][0] / sumWi[2][0][0]); + } else if (isp == numKProton) { + histos.fill(HIST("Prof_Cent_Nchrec_Pr"), cent, sumWi[3][0][0]); + histos.fill(HIST("Prof_Mult_Nchrec_Pr"), coll.multNTracksPV(), sumWi[3][0][0]); + + if (sumWi[3][0][0] > 1.0f) + histos.fill(HIST("Prof_Cent_MeanpT_Pr"), cent, sumWipti[3][0][0] / sumWi[3][0][0]); + } + } + + // Kinematic Bin Means (1D and 2D Sub-event) + for (int ietaA = 0; ietaA < KNEta; ++ietaA) { + for (int ietaB = 0; ietaB < KNEta; ++ietaB) { + for (int ipt = 0; ipt < KNpT; ++ipt) { + for (int isp = 0; isp < KNsp; ++isp) { + + // --- 2D Sub-Event Calculations --- + double wCorrAB = sumWi[isp][ietaA][ipt] + sumWi[isp][ietaB][ipt]; + if (wCorrAB > 0) { + float mptsub = (sumWipti[isp][ietaA][ipt] + sumWipti[isp][ietaB][ipt]) / wCorrAB; + if (isp == numKInclusive) { + if (ipt == 0) + histos.fill(HIST("Prof2D_MeanpT_Sub_ipt0"), cent, ietaA, ietaB, mptsub); + if (ipt == KNpT - 2) + histos.fill(HIST("Prof2D_MeanpT_Sub_ipt1"), cent, ietaA, ietaB, mptsub); + if (ipt == KNpT - 1) + histos.fill(HIST("Prof2D_MeanpT_Sub_ipt2"), cent, ietaA, ietaB, mptsub); + } else if (isp == numKPion) { + if (ipt == 0) + histos.fill(HIST("Prof2D_MeanpT_Sub_ipt0_Pi"), cent, ietaA, ietaB, mptsub); + if (ipt == KNpT - 2) + histos.fill(HIST("Prof2D_MeanpT_Sub_ipt1_Pi"), cent, ietaA, ietaB, mptsub); + if (ipt == KNpT - 1) + histos.fill(HIST("Prof2D_MeanpT_Sub_ipt2_Pi"), cent, ietaA, ietaB, mptsub); + } else if (isp == numKKaon) { + if (ipt == 0) + histos.fill(HIST("Prof2D_MeanpT_Sub_ipt0_Ka"), cent, ietaA, ietaB, mptsub); + if (ipt == KNpT - 2) + histos.fill(HIST("Prof2D_MeanpT_Sub_ipt1_Ka"), cent, ietaA, ietaB, mptsub); + if (ipt == KNpT - 1) + histos.fill(HIST("Prof2D_MeanpT_Sub_ipt2_Ka"), cent, ietaA, ietaB, mptsub); + } else if (isp == numKProton) { + if (ipt == 0) + histos.fill(HIST("Prof2D_MeanpT_Sub_ipt0_Pr"), cent, ietaA, ietaB, mptsub); + if (ipt == KNpT - 2) + histos.fill(HIST("Prof2D_MeanpT_Sub_ipt1_Pr"), cent, ietaA, ietaB, mptsub); + if (ipt == KNpT - 1) + histos.fill(HIST("Prof2D_MeanpT_Sub_ipt2_Pr"), cent, ietaA, ietaB, mptsub); + } + } + + // --- 1D Individual Bin Calculations (Only do when A == B to avoid overfilling) --- + if (ietaA == ietaB) { + double mpt = sumWipti[isp][ietaA][ipt] / sumWi[isp][ietaA][ipt]; + if (sumWi[isp][ietaA][ipt] >= 1.0f && std::isfinite(mpt)) { + if (isp == numKInclusive) { + histos.fill(HIST("pmean_nch_etabin_ptbin"), coll.multNTracksPV(), ietaA, ipt, mpt); + histos.fill(HIST("pmeanMult_nch_etabin_ptbin"), coll.multNTracksPV(), ietaA, ipt, sumWi[0][ietaA][ipt]); + histos.fill(HIST("pmean_cent_etabin_ptbin"), cent, ietaA, ipt, mpt); + histos.fill(HIST("pmeanMult_cent_etabin_ptbin"), cent, ietaA, ipt, sumWi[0][ietaA][ipt]); + } else if (isp == numKPion) { + histos.fill(HIST("pmean_nch_etabin_ptbin_Pi"), coll.multNTracksPV(), ietaA, ipt, mpt); + histos.fill(HIST("pmeanMult_nch_etabin_ptbin_Pi"), coll.multNTracksPV(), ietaA, ipt, sumWi[1][ietaA][ipt]); + histos.fill(HIST("pmean_cent_etabin_ptbin_Pi"), cent, ietaA, ipt, mpt); + histos.fill(HIST("pmeanMult_cent_etabin_ptbin_Pi"), cent, ietaA, ipt, sumWi[1][ietaA][ipt]); + } else if (isp == numKKaon) { + histos.fill(HIST("pmean_nch_etabin_ptbin_Ka"), coll.multNTracksPV(), ietaA, ipt, mpt); + histos.fill(HIST("pmeanMult_nch_etabin_ptbin_Ka"), coll.multNTracksPV(), ietaA, ipt, sumWi[2][ietaA][ipt]); + histos.fill(HIST("pmean_cent_etabin_ptbin_Ka"), cent, ietaA, ipt, mpt); + histos.fill(HIST("pmeanMult_cent_etabin_ptbin_Ka"), cent, ietaA, ipt, sumWi[2][ietaA][ipt]); + } else if (isp == numKProton) { + histos.fill(HIST("pmean_nch_etabin_ptbin_Pr"), coll.multNTracksPV(), ietaA, ipt, mpt); + histos.fill(HIST("pmeanMult_nch_etabin_ptbin_Pr"), coll.multNTracksPV(), ietaA, ipt, sumWi[3][ietaA][ipt]); + histos.fill(HIST("pmean_cent_etabin_ptbin_Pr"), cent, ietaA, ipt, mpt); + histos.fill(HIST("pmeanMult_cent_etabin_ptbin_Pr"), cent, ietaA, ipt, sumWi[3][ietaA][ipt]); + } + } + } + } } - if (sumWiEt[ieta][ipt] > 1.0f) - histos.fill(HIST("pmeanEt_nch_etabin_ptbin"), coll.multNTracksPV(), ieta, ipt, sumWiEtVal[ieta][ipt] / sumWiEt[ieta][ipt]); - histos.fill(HIST("pmeanEt_cent_etabin_ptbin"), cent, ieta, ipt, sumWiEtVal[ieta][ipt] / sumWiEt[ieta][ipt]); } } } - PROCESS_SWITCH(RadialFlowDecorr, processDataMean, "process data to calculate mean pT and Et", cfgRunDataMean); + PROCESS_SWITCH(RadialFlowDecorr, processDataMean, "process data to calculate mean pT", cfgRunDataMean); - void processDataFluc(AodCollisionsSel::iterator const& coll, aod::BCsWithTimestamps const&, AodTracksSel const& tracks) + void processDataFluc(AodCollisionsSel::iterator const& coll, BCsRun3 const& /*bcs*/, aod::Zdcs const& /*zdcsData*/, AodTracksSel const& tracks) { if (!isEventSelected(coll)) return; float cent = getCentrality(coll); if (cent > KCentMax) return; - if (!pmeanNchEtabinPtbinStep2 || !pmeanEtNchEtabinPtbinStep2 || !pmeanMultNchEtabinPtbinStep2) { - LOGF(warning, "Data fluc: Mean pT or Et map missing"); - return; + + // 1. Safety Check: Step 2 Mean Maps + for (int isp = 0; isp < KNsp; ++isp) { + if (!pmeanNchEtabinPtbinStep2[isp] || !pmeanMultNchEtabinPtbinStep2[isp]) { + LOGF(warning, "Data fluc: Mean pT or Mult map missing for species index %d", isp); + return; + } } - if (!hEff[kInclusive] || !hFake[kInclusive] || !hFlatWeight[kInclusive] || !hEff[kCombinedPID] || !hFake[kCombinedPID] || !hFlatWeight[kCombinedPID]) { - LOGF(warning, "Data fluc: Inclusive or PID correction maps are null"); - return; + // 2. Safety Check: Correction Maps (Looping over Inclusive, Pi, Ka, Pr) + for (int isp = 0; isp < KNsp; ++isp) { + auto pid = static_cast(isp); + if (!hEff[pid] || !hFake[pid] || !hFlatWeight[pid]) { + LOGF(warning, "Data fluc: Correction maps (Eff, Fake, or Flat) are null for species index %d", isp); + return; + } } - double sumpmwk[KNEta][KNpT][KIntM][KIntK]{}; - double sumwk[KNEta][KNpT][KIntK]{}; - double sumpmwkEt[KNEta][KNpT][KIntM][KIntK]{}; - double sumwkEt[KNEta][KNpT][KIntK]{}; - double mean[KNEta][KNpT]{}, c2[KNEta][KNpT]{}; - double p1kBar[KNEta][KNpT]{}; - double meanEt[KNEta][KNpT]{}, c2Et[KNEta][KNpT]{}; - double p1kBarEt[KNEta][KNpT]{}; - double p1kBarMult[KNEta][KNpT]{}, meanMult[KNEta][KNpT]{}; + // Expanded arrays to handle KNsp species (0: Incl, 1: Pi, 2: Ka, 3: Pr) + double sumpmwk[KNsp][KNEta][KNpT][KIntM][KIntK]{}; + double sumwk[KNsp][KNEta][KNpT][KIntK]{}; + + double mean[KNsp][KNEta][KNpT]{}, c2[KNsp][KNEta][KNpT]{}; + double p1kBar[KNsp][KNEta][KNpT]{}; + double meanMult[KNsp][KNEta][KNpT]{}, p1kBarMult[KNsp][KNEta][KNpT]{}; + + float vz = coll.posZ(); + + // --- 1. Track Loop: Accumulate sum --- for (const auto& track : tracks) { if (!isTrackSelected(track)) continue; + float pt = track.pt(); float eta = track.eta(); float p = track.p(); float phi = track.phi(); + auto sign = track.sign(); + if (p < KFloatEpsilon) continue; - float effIncl = getEfficiency(coll.multNTracksPV(), pt, eta, kInclusive, 0, cfgEff); - float fakeIncl = getEfficiency(coll.multNTracksPV(), pt, eta, kInclusive, 1, cfgEff); - float flatWeightIncl = getFlatteningWeight(coll.posZ(), track.sign(), pt, eta, phi, kInclusive, cfgFlat); - float wIncl = flatWeightIncl * (1.0 - fakeIncl) / effIncl; - if (!std::isfinite(wIncl) || wIncl <= KFloatEpsilon || effIncl <= KFloatEpsilon) - continue; - histos.fill(HIST("hEtaPhiReco"), coll.posZ(), track.sign(), pt, eta, track.phi()); - histos.fill(HIST("hEtaPhiRecoEffWtd"), coll.posZ(), track.sign(), eta, pt, track.phi(), (1.0 - fakeIncl) / effIncl); - histos.fill(HIST("hEtaPhiRecoWtd"), coll.posZ(), track.sign(), eta, pt, track.phi(), wIncl); + bool isSpecies[KNsp] = {true, selectionPion(track), selectionKaon(track), selectionProton(track)}; - for (int ieta = 0; ieta < KNEta; ++ieta) { - if (eta <= etaLw[ieta] || eta > etaUp[ieta]) + for (int isp = 0; isp < KNsp; ++isp) { + if (!isSpecies[isp]) continue; - for (int ipt = 0; ipt < KNpT; ++ipt) { - if (pt <= pTLw[ipt] || pt > pTUp[ipt]) - continue; - for (int k = 0; k < KIntK; ++k) { - for (int m = 0; m < KIntM; ++m) - sumpmwk[ieta][ipt][m][k] += std::pow(wIncl, k) * std::pow(pt, m); - sumwk[ieta][ipt][k] += std::pow(wIncl, k); - } - } - } - const bool isPion = selectionPion(track); - const bool isKaon = selectionKaon(track); - const bool isProton = selectionProton(track); - if (isPion || isKaon || isProton) { - float effPid = getEfficiency(coll.multNTracksPV(), pt, eta, kCombinedPID, 0, cfgEff); - float fakePid = getEfficiency(coll.multNTracksPV(), pt, eta, kCombinedPID, 1, cfgEff); - float flatWeightPid = getFlatteningWeight(coll.posZ(), track.sign(), pt, eta, phi, kCombinedPID, cfgFlat); - float wPid = flatWeightPid * (1.0 - fakePid) / effPid; - if (!std::isfinite(wPid) || wPid <= KFloatEpsilon || effPid <= KFloatEpsilon) + float eff = getEfficiency(coll.multNTracksPV(), pt, eta, static_cast(isp), 0, cfgEff); + float fake = getEfficiency(coll.multNTracksPV(), pt, eta, static_cast(isp), 1, cfgEff); + float flatWeight = getFlatteningWeight(vz, sign, pt, eta, phi, static_cast(isp), cfgFlat); + float w = flatWeight * (1.0 - fake) / eff; + + if (!std::isfinite(w) || w <= KFloatEpsilon || eff <= KFloatEpsilon) continue; - histos.fill(HIST("hEtaPhiReco_PID"), coll.posZ(), track.sign(), pt, eta, track.phi()); - histos.fill(HIST("hEtaPhiRecoEffWtd_PID"), coll.posZ(), track.sign(), eta, pt, track.phi(), (1.0 - fakePid) / effPid); - histos.fill(HIST("hEtaPhiRecoWtd_PID"), coll.posZ(), track.sign(), eta, pt, track.phi(), wPid); - float m = isPion ? o2::constants::physics::MassPiPlus : isKaon ? o2::constants::physics::MassKPlus - : o2::constants::physics::MassProton; + // QA Fills + if (isp == numKInclusive) { + histos.fill(HIST("hEtaPhiReco"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd"), vz, sign, pt, eta, phi, w); + } else if (isp == numKPion) { // Pion + histos.fill(HIST("hEtaPhiReco_Pi"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd_Pi"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd_Pi"), vz, sign, pt, eta, phi, w); + } else if (isp == numKKaon) { // Kaon + histos.fill(HIST("hEtaPhiReco_Ka"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd_Ka"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd_Ka"), vz, sign, pt, eta, phi, w); + } else if (isp == numKProton) { // Proton + histos.fill(HIST("hEtaPhiReco_Pr"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd_Pr"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd_Pr"), vz, sign, pt, eta, phi, w); + } - float energy = std::sqrt(p * p + m * m); - float et = energy * (pt / p); // E_T = E * sin(theta) + // Kinematic Bin sum for (int ieta = 0; ieta < KNEta; ++ieta) { if (eta <= etaLw[ieta] || eta > etaUp[ieta]) continue; @@ -2325,141 +2950,259 @@ struct RadialFlowDecorr { if (pt <= pTLw[ipt] || pt > pTUp[ipt]) continue; for (int k = 0; k < KIntK; ++k) { - for (int m = 0; m < KIntM; ++m) - sumpmwkEt[ieta][ipt][m][k] += std::pow(wPid, k) * std::pow(et, m); - sumwkEt[ieta][ipt][k] += std::pow(wPid, k); + for (int m = 0; m < KIntM; ++m) { + sumpmwk[isp][ieta][ipt][m][k] += std::pow(w, k) * std::pow(pt, m); + } + sumwk[isp][ieta][ipt][k] += std::pow(w, k); } } } } } + // --- 2. Step 2 Means and 1D Fluc Variables --- for (int ieta = 0; ieta < KNEta; ++ieta) { for (int ipt = 0; ipt < KNpT; ++ipt) { - const int ibx = pmeanNchEtabinPtbinStep2->GetXaxis()->FindBin(coll.multNTracksPV()); + + // Use [0] to safely grab the X-axis from the array! + const int ibx = pmeanNchEtabinPtbinStep2[0]->GetXaxis()->FindBin(coll.multNTracksPV()); const int iby = ieta + 1; const int ibz = ipt + 1; - float mmpt = pmeanNchEtabinPtbinStep2->GetBinContent(ibx, iby, ibz); - float mmet = pmeanEtNchEtabinPtbinStep2->GetBinContent(ibx, iby, ibz); - float mmMult = pmeanMultNchEtabinPtbinStep2->GetBinContent(ibx, iby, ibz); - - mean[ieta][ipt] = sumpmwk[ieta][ipt][1][1] / sumwk[ieta][ipt][1]; - meanEt[ieta][ipt] = sumpmwkEt[ieta][ipt][1][1] / sumwkEt[ieta][ipt][1]; - meanMult[ieta][ipt] = sumwk[ieta][ipt][1]; - if (std::isfinite(mmpt)) { - std::tie(mean[ieta][ipt], c2[ieta][ipt]) = - calculateMeanAndC2FromSums(sumpmwk[ieta][ipt], sumwk[ieta][ipt], mmpt); - p1kBar[ieta][ipt] = mean[ieta][ipt] - mmpt; - } - if (std::isfinite(mmet)) { - std::tie(meanEt[ieta][ipt], c2Et[ieta][ipt]) = - calculateMeanAndC2FromSums(sumpmwkEt[ieta][ipt], sumwkEt[ieta][ipt], mmet); - p1kBarEt[ieta][ipt] = meanEt[ieta][ipt] - mmet; + + for (int isp = 0; isp < KNsp; ++isp) { + // Dynamically fetch from the array + float mmpt = pmeanNchEtabinPtbinStep2[isp]->GetBinContent(ibx, iby, ibz); + float mmMult = pmeanMultNchEtabinPtbinStep2[isp]->GetBinContent(ibx, iby, ibz); + + mean[isp][ieta][ipt] = sumpmwk[isp][ieta][ipt][1][1] / sumwk[isp][ieta][ipt][1]; + meanMult[isp][ieta][ipt] = sumwk[isp][ieta][ipt][1]; + + if (std::isfinite(mmpt)) { + std::tie(mean[isp][ieta][ipt], c2[isp][ieta][ipt]) = calculateMeanAndC2FromSums(sumpmwk[isp][ieta][ipt], sumwk[isp][ieta][ipt], mmpt); + p1kBar[isp][ieta][ipt] = mean[isp][ieta][ipt] - mmpt; + } + p1kBarMult[isp][ieta][ipt] = meanMult[isp][ieta][ipt] - mmMult; } - p1kBarMult[ieta][ipt] = meanMult[ieta][ipt] - mmMult; } } + // --- 3. Fill 1D Profiles --- for (int ieta = 0; ieta < KNEta; ++ieta) { for (int ipt = 0; ipt < KNpT; ++ipt) { - if (sumwk[ieta][ipt][1] > 1.f) { - histos.fill(HIST("Prof_Cent_MeanpT_etabin_ptbin"), cent, ieta, ipt, mean[ieta][ipt]); - histos.fill(HIST("Prof_Mult_MeanpT_etabin_ptbin"), coll.multNTracksPV(), ieta, ipt, mean[ieta][ipt]); - } - if (sumwkEt[ieta][ipt][1] > 1.f) { - histos.fill(HIST("Prof_Cent_MeanEt_etabin_ptbin"), cent, ieta, ipt, meanEt[ieta][ipt]); - histos.fill(HIST("Prof_Mult_MeanEt_etabin_ptbin"), coll.multNTracksPV(), ieta, ipt, meanEt[ieta][ipt]); - } - if (std::isfinite(c2[ieta][ipt])) { - histos.fill(HIST("Prof_Cent_C2_etabin_ptbin"), cent, ieta, ipt, c2[ieta][ipt]); - histos.fill(HIST("Prof_Mult_C2_etabin_ptbin"), coll.multNTracksPV(), ieta, ipt, c2[ieta][ipt]); - } - if (std::isfinite(c2Et[ieta][ipt])) { - histos.fill(HIST("Prof_Cent_C2Et_etabin_ptbin"), cent, ieta, ipt, c2Et[ieta][ipt]); - histos.fill(HIST("Prof_Mult_C2Et_etabin_ptbin"), coll.multNTracksPV(), ieta, ipt, c2Et[ieta][ipt]); + for (int isp = 0; isp < KNsp; ++isp) { + if (isp == numKInclusive) { + if (std::isfinite(mean[0][ieta][ipt])) { + histos.fill(HIST("Prof_MeanpT_Cent_etabin_ptbin"), cent, ieta, ipt, mean[0][ieta][ipt]); + histos.fill(HIST("Prof_MeanpT_Mult_etabin_ptbin"), coll.multNTracksPV(), ieta, ipt, mean[0][ieta][ipt]); + } + if (std::isfinite(c2[0][ieta][ipt])) { + histos.fill(HIST("Prof_C2_Cent_etabin_ptbin"), cent, ieta, ipt, c2[0][ieta][ipt]); + histos.fill(HIST("Prof_C2_Mult_etabin_ptbin"), coll.multNTracksPV(), ieta, ipt, c2[0][ieta][ipt]); + } + } else if (isp == numKPion) { // Pi + if (std::isfinite(mean[1][ieta][ipt])) { + histos.fill(HIST("Prof_MeanpT_Cent_etabin_ptbin_Pi"), cent, ieta, ipt, mean[1][ieta][ipt]); + histos.fill(HIST("Prof_MeanpT_Mult_etabin_ptbin_Pi"), coll.multNTracksPV(), ieta, ipt, mean[1][ieta][ipt]); + } + if (std::isfinite(c2[1][ieta][ipt])) { + histos.fill(HIST("Prof_C2_Cent_etabin_ptbin_Pi"), cent, ieta, ipt, c2[1][ieta][ipt]); + histos.fill(HIST("Prof_C2_Mult_etabin_ptbin_Pi"), coll.multNTracksPV(), ieta, ipt, c2[1][ieta][ipt]); + } + } else if (isp == numKKaon) { // Ka + if (std::isfinite(mean[2][ieta][ipt])) { + histos.fill(HIST("Prof_MeanpT_Cent_etabin_ptbin_Ka"), cent, ieta, ipt, mean[2][ieta][ipt]); + histos.fill(HIST("Prof_MeanpT_Mult_etabin_ptbin_Ka"), coll.multNTracksPV(), ieta, ipt, mean[2][ieta][ipt]); + } + if (std::isfinite(c2[2][ieta][ipt])) { + histos.fill(HIST("Prof_C2_Cent_etabin_ptbin_Ka"), cent, ieta, ipt, c2[2][ieta][ipt]); + histos.fill(HIST("Prof_C2_Mult_etabin_ptbin_Ka"), coll.multNTracksPV(), ieta, ipt, c2[2][ieta][ipt]); + } + } else if (isp == numKProton) { // Pr + if (std::isfinite(mean[3][ieta][ipt])) { + histos.fill(HIST("Prof_MeanpT_Cent_etabin_ptbin_Pr"), cent, ieta, ipt, mean[3][ieta][ipt]); + histos.fill(HIST("Prof_MeanpT_Mult_etabin_ptbin_Pr"), coll.multNTracksPV(), ieta, ipt, mean[3][ieta][ipt]); + } + if (std::isfinite(c2[3][ieta][ipt])) { + histos.fill(HIST("Prof_C2_Cent_etabin_ptbin_Pr"), cent, ieta, ipt, c2[3][ieta][ipt]); + histos.fill(HIST("Prof_C2_Mult_etabin_ptbin_Pr"), coll.multNTracksPV(), ieta, ipt, c2[3][ieta][ipt]); + } + } } } } - for (int ieta = 0; ieta < KNEta; ++ieta) { - for (int ipt = 0; ipt < KNpT; ++ipt) { - if (std::isfinite(c2[ieta][ipt])) - histos.fill(HIST("Prof_C2_Mult_etabin_ptbin"), coll.multNTracksPV(), ieta, ipt, c2[ieta][ipt]); - if (std::isfinite(c2Et[ieta][ipt])) - histos.fill(HIST("Prof_C2Et_Mult_etabin_ptbin"), coll.multNTracksPV(), ieta, ipt, c2Et[ieta][ipt]); - } - } for (int ietaA = 1; ietaA <= (KNEta - 1) / 2; ++ietaA) { int ietaC = KNEta - ietaA; for (int ipt = 0; ipt < KNpT; ++ipt) { - float c2Sub = p1kBar[ietaA][ipt] * p1kBar[ietaC][ipt]; - float c2SubEt = p1kBarEt[ietaA][ipt] * p1kBarEt[ietaC][ipt]; - float cov_AC = p1kBarMult[ietaA][ipt] * p1kBar[ietaC][ipt]; - float cov_CA = p1kBar[ietaA][ipt] * p1kBarMult[ietaC][ipt]; - - if (std::isfinite(c2Sub)) { - histos.fill(HIST("Prof_C2Sub_Cent_etabin_ptbin"), cent, ietaA, ipt, c2Sub); - histos.fill(HIST("Prof_C2Sub_Mult_etabin_ptbin"), coll.multNTracksPV(), ietaA, ipt, c2Sub); - } - if (std::isfinite(c2SubEt)) { - histos.fill(HIST("Prof_C2EtSub_Cent_etabin_ptbin"), cent, ietaA, ipt, c2SubEt); - histos.fill(HIST("Prof_C2EtSub_Mult_etabin_ptbin"), coll.multNTracksPV(), ietaA, ipt, c2SubEt); - } - if (std::isfinite(cov_AC)) { - histos.fill(HIST("Prof_Cov_Cent_etabin_ptbin"), cent, ietaA, ipt, cov_AC); - histos.fill(HIST("Prof_Cov_Mult_etabin_ptbin"), coll.multNTracksPV(), ietaA, ipt, cov_AC); - } - if (std::isfinite(cov_CA)) { - histos.fill(HIST("Prof_Cov_Cent_etabin_ptbin"), cent, ietaA, ipt, cov_CA); - histos.fill(HIST("Prof_Cov_Mult_etabin_ptbin"), coll.multNTracksPV(), ietaA, ipt, cov_CA); + for (int isp = 0; isp < KNsp; ++isp) { + float c2Sub = p1kBar[isp][ietaA][ipt] * p1kBar[isp][ietaC][ipt]; + float covAC = p1kBarMult[isp][ietaA][ipt] * p1kBar[isp][ietaC][ipt]; + float covCA = p1kBar[isp][ietaA][ipt] * p1kBarMult[isp][ietaC][ipt]; + + if (isp == numKInclusive) { + if (std::isfinite(c2Sub)) { + histos.fill(HIST("Prof_C2Sub_Cent_etabin_ptbin"), cent, ietaA, ipt, c2Sub); + histos.fill(HIST("Prof_C2Sub_Mult_etabin_ptbin"), coll.multNTracksPV(), ietaA, ipt, c2Sub); + } + if (std::isfinite(covAC)) { + histos.fill(HIST("Prof_Cov_Cent_etabin_ptbin"), cent, ietaA, ipt, covAC); + histos.fill(HIST("Prof_Cov_Mult_etabin_ptbin"), coll.multNTracksPV(), ietaA, ipt, covAC); + } + if (std::isfinite(covCA)) { + histos.fill(HIST("Prof_Cov_Cent_etabin_ptbin"), cent, ietaA, ipt, covCA); + histos.fill(HIST("Prof_Cov_Mult_etabin_ptbin"), coll.multNTracksPV(), ietaA, ipt, covCA); + } + } else if (isp == numKPion) { // Pi + if (std::isfinite(c2Sub)) { + histos.fill(HIST("Prof_C2Sub_Cent_etabin_ptbin_Pi"), cent, ietaA, ipt, c2Sub); + histos.fill(HIST("Prof_C2Sub_Mult_etabin_ptbin_Pi"), coll.multNTracksPV(), ietaA, ipt, c2Sub); + } + if (std::isfinite(covAC)) { + histos.fill(HIST("Prof_Cov_Cent_etabin_ptbin_Pi"), cent, ietaA, ipt, covAC); + histos.fill(HIST("Prof_Cov_Mult_etabin_ptbin_Pi"), coll.multNTracksPV(), ietaA, ipt, covAC); + } + if (std::isfinite(covCA)) { + histos.fill(HIST("Prof_Cov_Cent_etabin_ptbin_Pi"), cent, ietaA, ipt, covCA); + histos.fill(HIST("Prof_Cov_Mult_etabin_ptbin_Pi"), coll.multNTracksPV(), ietaA, ipt, covCA); + } + } else if (isp == numKKaon) { // Ka + if (std::isfinite(c2Sub)) { + histos.fill(HIST("Prof_C2Sub_Cent_etabin_ptbin_Ka"), cent, ietaA, ipt, c2Sub); + histos.fill(HIST("Prof_C2Sub_Mult_etabin_ptbin_Ka"), coll.multNTracksPV(), ietaA, ipt, c2Sub); + } + if (std::isfinite(covAC)) { + histos.fill(HIST("Prof_Cov_Cent_etabin_ptbin_Ka"), cent, ietaA, ipt, covAC); + histos.fill(HIST("Prof_Cov_Mult_etabin_ptbin_Ka"), coll.multNTracksPV(), ietaA, ipt, covAC); + } + if (std::isfinite(covCA)) { + histos.fill(HIST("Prof_Cov_Cent_etabin_ptbin_Ka"), cent, ietaA, ipt, covCA); + histos.fill(HIST("Prof_Cov_Mult_etabin_ptbin_Ka"), coll.multNTracksPV(), ietaA, ipt, covCA); + } + } else if (isp == numKProton) { // Pr + if (std::isfinite(c2Sub)) { + histos.fill(HIST("Prof_C2Sub_Cent_etabin_ptbin_Pr"), cent, ietaA, ipt, c2Sub); + histos.fill(HIST("Prof_C2Sub_Mult_etabin_ptbin_Pr"), coll.multNTracksPV(), ietaA, ipt, c2Sub); + } + if (std::isfinite(covAC)) { + histos.fill(HIST("Prof_Cov_Cent_etabin_ptbin_Pr"), cent, ietaA, ipt, covAC); + histos.fill(HIST("Prof_Cov_Mult_etabin_ptbin_Pr"), coll.multNTracksPV(), ietaA, ipt, covAC); + } + if (std::isfinite(covCA)) { + histos.fill(HIST("Prof_Cov_Cent_etabin_ptbin_Pr"), cent, ietaA, ipt, covCA); + histos.fill(HIST("Prof_Cov_Mult_etabin_ptbin_Pr"), coll.multNTracksPV(), ietaA, ipt, covCA); + } + } } } } + // --- 5. Full 2D Covariances & GapSum Profiles --- for (int ietaA = 1; ietaA < KNEta; ++ietaA) { - for (int ietaC = 1; ietaC < KNEta; ++ietaC) { + for (int ietaB = 1; ietaB < KNEta; ++ietaB) { + + float etaValA = (etaLw[ietaA] + etaUp[ietaA]) / 2.0f; + float etaValB = (etaLw[ietaB] + etaUp[ietaB]) / 2.0f; + float gap = etaValA - etaValB; + float sum = (etaValA + etaValB) / 2.0f; + for (int ipt = 0; ipt < KNpT; ++ipt) { - float covpt = p1kBar[ietaA][ipt] * p1kBar[ietaC][ipt]; - if (std::isfinite(covpt)) { - switch (ipt) { - case 0: - histos.fill(HIST("Prof_ipt0_C2Sub2D_Cent_etaA_etaC"), cent, ietaA, ietaC, covpt); - break; - case 1: - histos.fill(HIST("Prof_ipt1_C2Sub2D_Cent_etaA_etaC"), cent, ietaA, ietaC, covpt); - break; - case 2: - histos.fill(HIST("Prof_ipt2_C2Sub2D_Cent_etaA_etaC"), cent, ietaA, ietaC, covpt); - break; - } - } + for (int isp = 0; isp < KNsp; ++isp) { - float covet = p1kBarEt[ietaA][ipt] * p1kBarEt[ietaC][ipt]; - if (std::isfinite(covet)) { - switch (ipt) { - case 0: - histos.fill(HIST("Prof_ipt0_C2EtSub2D_Cent_etaA_etaC"), cent, ietaA, ietaC, covet); - break; - case 1: - histos.fill(HIST("Prof_ipt1_C2EtSub2D_Cent_etaA_etaC"), cent, ietaA, ietaC, covet); - break; - case 2: - histos.fill(HIST("Prof_ipt2_C2EtSub2D_Cent_etaA_etaC"), cent, ietaA, ietaC, covet); - break; - } - } - float cov = p1kBarMult[ietaA][ipt] * p1kBar[ietaC][ipt]; - if (std::isfinite(cov)) { - switch (ipt) { - case 0: - histos.fill(HIST("Prof_ipt0_Cov2D_Cent_etaA_etaC"), cent, ietaA, ietaC, cov); - break; - case 1: - histos.fill(HIST("Prof_ipt1_Cov2D_Cent_etaA_etaC"), cent, ietaA, ietaC, cov); - break; - case 2: - histos.fill(HIST("Prof_ipt2_Cov2D_Cent_etaA_etaC"), cent, ietaA, ietaC, cov); - break; + float c2Sub = p1kBar[isp][ietaA][ipt] * p1kBar[isp][ietaB][ipt]; + float cov = p1kBarMult[isp][ietaA][ipt] * p1kBar[isp][ietaB][ipt]; + + if (isp == numKInclusive) { // Inclusive + if (ipt == 0) { + if (std::isfinite(c2Sub)) { + histos.fill(HIST("Prof_ipt0_C2Sub2D_Cent_etaA_etaC"), cent, etaValA, etaValB, c2Sub); + histos.fill(HIST("Prof_ipt0_GapSum2D"), cent, gap, sum, c2Sub); + } + if (std::isfinite(cov)) + histos.fill(HIST("Prof_ipt0_Cov2D_Cent_etaA_etaC"), cent, etaValA, etaValB, cov); + } else if (ipt == KNpT - 2) { + if (std::isfinite(c2Sub)) { + histos.fill(HIST("Prof_ipt1_C2Sub2D_Cent_etaA_etaC"), cent, etaValA, etaValB, c2Sub); + histos.fill(HIST("Prof_ipt1_GapSum2D"), cent, gap, sum, c2Sub); + } + if (std::isfinite(cov)) + histos.fill(HIST("Prof_ipt1_Cov2D_Cent_etaA_etaC"), cent, etaValA, etaValB, cov); + } else if (ipt == KNpT - 1) { + if (std::isfinite(c2Sub)) { + histos.fill(HIST("Prof_ipt2_C2Sub2D_Cent_etaA_etaC"), cent, etaValA, etaValB, c2Sub); + histos.fill(HIST("Prof_ipt2_GapSum2D"), cent, gap, sum, c2Sub); + } + if (std::isfinite(cov)) + histos.fill(HIST("Prof_ipt2_Cov2D_Cent_etaA_etaC"), cent, etaValA, etaValB, cov); + } + } else if (isp == numKPion) { // Pi + if (ipt == 0) { + if (std::isfinite(c2Sub)) { + histos.fill(HIST("Prof_ipt0_C2Sub2D_Cent_etaA_etaC_Pi"), cent, etaValA, etaValB, c2Sub); + histos.fill(HIST("Prof_ipt0_GapSum2D_Pi"), cent, gap, sum, c2Sub); + } + if (std::isfinite(cov)) + histos.fill(HIST("Prof_ipt0_Cov2D_Cent_etaA_etaC_Pi"), cent, etaValA, etaValB, cov); + } else if (ipt == KNpT - 2) { + if (std::isfinite(c2Sub)) { + histos.fill(HIST("Prof_ipt1_C2Sub2D_Cent_etaA_etaC_Pi"), cent, etaValA, etaValB, c2Sub); + histos.fill(HIST("Prof_ipt1_GapSum2D_Pi"), cent, gap, sum, c2Sub); + } + if (std::isfinite(cov)) + histos.fill(HIST("Prof_ipt1_Cov2D_Cent_etaA_etaC_Pi"), cent, etaValA, etaValB, cov); + } else if (ipt == KNpT - 1) { + if (std::isfinite(c2Sub)) { + histos.fill(HIST("Prof_ipt2_C2Sub2D_Cent_etaA_etaC_Pi"), cent, etaValA, etaValB, c2Sub); + histos.fill(HIST("Prof_ipt2_GapSum2D_Pi"), cent, gap, sum, c2Sub); + } + if (std::isfinite(cov)) + histos.fill(HIST("Prof_ipt2_Cov2D_Cent_etaA_etaC_Pi"), cent, etaValA, etaValB, cov); + } + } else if (isp == numKKaon) { // Ka + if (ipt == 0) { + if (std::isfinite(c2Sub)) { + histos.fill(HIST("Prof_ipt0_C2Sub2D_Cent_etaA_etaC_Ka"), cent, etaValA, etaValB, c2Sub); + histos.fill(HIST("Prof_ipt0_GapSum2D_Ka"), cent, gap, sum, c2Sub); + } + if (std::isfinite(cov)) + histos.fill(HIST("Prof_ipt0_Cov2D_Cent_etaA_etaC_Ka"), cent, etaValA, etaValB, cov); + } else if (ipt == KNpT - 2) { + if (std::isfinite(c2Sub)) { + histos.fill(HIST("Prof_ipt1_C2Sub2D_Cent_etaA_etaC_Ka"), cent, etaValA, etaValB, c2Sub); + histos.fill(HIST("Prof_ipt1_GapSum2D_Ka"), cent, gap, sum, c2Sub); + } + if (std::isfinite(cov)) + histos.fill(HIST("Prof_ipt1_Cov2D_Cent_etaA_etaC_Ka"), cent, etaValA, etaValB, cov); + } else if (ipt == KNpT - 1) { + if (std::isfinite(c2Sub)) { + histos.fill(HIST("Prof_ipt2_C2Sub2D_Cent_etaA_etaC_Ka"), cent, etaValA, etaValB, c2Sub); + histos.fill(HIST("Prof_ipt2_GapSum2D_Ka"), cent, gap, sum, c2Sub); + } + if (std::isfinite(cov)) + histos.fill(HIST("Prof_ipt2_Cov2D_Cent_etaA_etaC_Ka"), cent, etaValA, etaValB, cov); + } + } else if (isp == numKProton) { // Pr + if (ipt == 0) { + if (std::isfinite(c2Sub)) { + histos.fill(HIST("Prof_ipt0_C2Sub2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, c2Sub); + histos.fill(HIST("Prof_ipt0_GapSum2D_Pr"), cent, gap, sum, c2Sub); + } + if (std::isfinite(cov)) + histos.fill(HIST("Prof_ipt0_Cov2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, cov); + } else if (ipt == KNpT - 2) { + if (std::isfinite(c2Sub)) { + histos.fill(HIST("Prof_ipt1_C2Sub2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, c2Sub); + histos.fill(HIST("Prof_ipt1_GapSum2D_Pr"), cent, gap, sum, c2Sub); + } + if (std::isfinite(cov)) + histos.fill(HIST("Prof_ipt1_Cov2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, cov); + } else if (ipt == KNpT - 1) { + if (std::isfinite(c2Sub)) { + histos.fill(HIST("Prof_ipt2_C2Sub2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, c2Sub); + histos.fill(HIST("Prof_ipt2_GapSum2D_Pr"), cent, gap, sum, c2Sub); + } + if (std::isfinite(cov)) + histos.fill(HIST("Prof_ipt2_Cov2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, cov); + } } } } From 1dfb8b05be12b05b72e66b927a4acf61b0036882 Mon Sep 17 00:00:00 2001 From: Md Samsul Islam <56156956+mislam17@users.noreply.github.com> Date: Wed, 25 Feb 2026 18:35:16 +0530 Subject: [PATCH 080/347] [PWGHF] taskSingleMuonMultMc: Minor fixes. Add in CMakeLists. (#15147) --- PWGHF/HFL/Tasks/CMakeLists.txt | 5 ++ PWGHF/HFL/Tasks/taskSingleMuonMultMc.cxx | 87 ++++++++++++++---------- 2 files changed, 57 insertions(+), 35 deletions(-) diff --git a/PWGHF/HFL/Tasks/CMakeLists.txt b/PWGHF/HFL/Tasks/CMakeLists.txt index 2eac2ac28b6..925dc4e831d 100644 --- a/PWGHF/HFL/Tasks/CMakeLists.txt +++ b/PWGHF/HFL/Tasks/CMakeLists.txt @@ -34,6 +34,11 @@ o2physics_add_dpl_workflow(task-single-muon-mult PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(task-single-muon-mult-mc + SOURCES taskSingleMuonMultMc.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(task-single-muon-reader SOURCES taskSingleMuonReader.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::PWGDQCore diff --git a/PWGHF/HFL/Tasks/taskSingleMuonMultMc.cxx b/PWGHF/HFL/Tasks/taskSingleMuonMultMc.cxx index 1f67d77b14d..29ffc66229b 100644 --- a/PWGHF/HFL/Tasks/taskSingleMuonMultMc.cxx +++ b/PWGHF/HFL/Tasks/taskSingleMuonMultMc.cxx @@ -17,25 +17,34 @@ #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/TrackFwd.h" +#include +#include +#include +#include #include - +#include +#include +#include +#include +#include +#include + +#include #include +#include + +#include +#include + using namespace o2; using namespace o2::aod; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::aod::fwdtrack; -auto static constexpr MinCharge = 3.f; +// Minimum PDG charge (in units of 1/3 e) +auto static constexpr ChargeMin = 3.f; namespace { @@ -257,92 +266,92 @@ struct HfTaskSingleMuonMultMc { } // particle has an associated MC particle - bool isIdentified(const uint16_t& mask) + bool isIdentified(const uint16_t mask) { return (TESTBIT(mask, IsIdentified)); } // this particle is muon - bool isMuon(const uint16_t& mask) + bool isMuon(const uint16_t mask) { return (TESTBIT(mask, IsIdentified) && TESTBIT(mask, IsMuon)); } // this muon comes from transport - bool isSecondaryMu(const uint16_t& mask) + bool isSecondaryMu(const uint16_t mask) { return (isMuon(mask) && TESTBIT(mask, IsSecondary)); } // this muon comes from light flavor quark decay - bool isLightDecayMu(const uint16_t& mask) + bool isLightDecayMu(const uint16_t mask) { return (isMuon(mask) && TESTBIT(mask, HasLightParent) && (!TESTBIT(mask, IsSecondary))); } // this muon comes from tau decays - bool isTauDecayMu(const uint16_t& mask) + bool isTauDecayMu(const uint16_t mask) { return (isMuon(mask) && TESTBIT(mask, HasTauParent) && (!TESTBIT(mask, HasWParent)) && (!TESTBIT(mask, HasZParent)) && (!TESTBIT(mask, HasBeautyParent)) && (!TESTBIT(mask, HasCharmParent))); } // this muon comes from W+- decay - bool isWBosonDecayMu(const uint16_t& mask) + bool isWBosonDecayMu(const uint16_t mask) { return (isMuon(mask) && TESTBIT(mask, HasWParent) && (!TESTBIT(mask, HasZParent)) && (!TESTBIT(mask, HasTauParent)) && (!TESTBIT(mask, HasLightParent)) && (!TESTBIT(mask, IsSecondary))); } // this muon comes from Z decay - bool isZBosonDecayMu(const uint16_t& mask) + bool isZBosonDecayMu(const uint16_t mask) { return (isMuon(mask) && TESTBIT(mask, HasZParent) && (!TESTBIT(mask, HasWParent)) && (!TESTBIT(mask, HasTauParent)) && (!TESTBIT(mask, HasLightParent)) && (!TESTBIT(mask, IsSecondary))); } // this muon comes from quarkonium decay - bool isQuarkoniumDecayMu(const uint16_t& mask) + bool isQuarkoniumDecayMu(const uint16_t mask) { return (isMuon(mask) && TESTBIT(mask, HasQuarkoniumParent) && (!TESTBIT(mask, HasBeautyParent)) && (!TESTBIT(mask, HasCharmParent)) && (!TESTBIT(mask, HasLightParent))); } // this muon comes from beauty decay and does not have light flavor parent - bool isBeautyMu(const uint16_t& mask) + bool isBeautyMu(const uint16_t mask) { return (isMuon(mask) && TESTBIT(mask, HasBeautyParent) && (!TESTBIT(mask, HasQuarkoniumParent)) && (!TESTBIT(mask, HasLightParent)) && (!TESTBIT(mask, IsSecondary))); } // this muon comes directly from beauty decay - bool isBeautyDecayMu(const uint16_t& mask) + bool isBeautyDecayMu(const uint16_t mask) { return (isBeautyMu(mask) && (!TESTBIT(mask, HasCharmParent) && (!TESTBIT(mask, HasQuarkoniumParent))) && (!TESTBIT(mask, HasLightParent)) && (!TESTBIT(mask, IsSecondary))); } // this muon comes from non-prompt charm decay and does not have light flavor parent - bool isNonpromptCharmMu(const uint16_t& mask) + bool isNonpromptCharmMu(const uint16_t mask) { return (isBeautyMu(mask) && TESTBIT(mask, HasCharmParent) && (!TESTBIT(mask, HasQuarkoniumParent)) && (!TESTBIT(mask, HasLightParent)) && (!TESTBIT(mask, IsSecondary))); } // this muon comes from prompt charm decay and does not have light flavor parent - bool isPromptCharmMu(const uint16_t& mask) + bool isPromptCharmMu(const uint16_t mask) { return (isMuon(mask) && TESTBIT(mask, HasCharmParent) && (!TESTBIT(mask, HasBeautyParent)) && (!TESTBIT(mask, HasQuarkoniumParent)) && (!TESTBIT(mask, HasLightParent)) && (!TESTBIT(mask, IsSecondary))); } // this muon comes from other sources which have not classified above. - bool isOtherMu(const uint16_t& mask) + bool isOtherMu(const uint16_t mask) { return (isMuon(mask) && (!isSecondaryMu(mask)) && (!isLightDecayMu(mask)) && (!isTauDecayMu(mask)) && (!isWBosonDecayMu(mask)) && (!isZBosonDecayMu(mask)) && (!isQuarkoniumDecayMu(mask)) && (!isBeautyMu(mask)) && (!isPromptCharmMu(mask))); } // this is a hadron - bool isHadron(const uint16_t& mask) + bool isHadron(const uint16_t mask) { return (TESTBIT(mask, IsIdentified) && (!TESTBIT(mask, IsMuon))); } // this particle is unidentified - bool isUnidentified(const uint16_t& mask) + bool isUnidentified(const uint16_t mask) { - return ((!TESTBIT(mask, IsIdentified))); + return (!TESTBIT(mask, IsIdentified)); } // fill the histograms of each particle types @@ -398,7 +407,10 @@ struct HfTaskSingleMuonMultMc { } } - void process(McGenCollisions::iterator const& mccollision, McMuons const& muons, aod::McParticles const&, McRecCollisions const& collisions) + void process(McGenCollisions::iterator const& mccollision, + McMuons const& muons, + aod::McParticles const&, + McRecCollisions const& collisions) { // event selections @@ -409,14 +421,14 @@ struct HfTaskSingleMuonMultMc { registry.fill(HIST("hNEventGenMu"), 1); for (const auto& muon : muons) { - if (!(muon.has_mcParticle())) { + if (!muon.has_mcParticle()) { continue; } auto mcPart(muon.mcParticle()); auto pdgGen(mcPart.pdgCode()); auto etaGen(mcPart.eta()); - if (!(std::abs(pdgGen) == kMuonMinus)) { + if (std::abs(pdgGen) != kMuonMinus) { continue; } if ((etaGen >= etaMax) || (etaGen < etaMin)) { @@ -439,7 +451,7 @@ struct HfTaskSingleMuonMultMc { continue; } - if (!(muon.has_mcParticle())) { + if (!muon.has_mcParticle()) { continue; } const auto pt(muon.pt()), eta(muon.eta()), rAbsorb(muon.rAtAbsorberEnd()), pDca(muon.pDca()), chi2(muon.chi2MatchMCHMFT()); @@ -474,7 +486,10 @@ struct HfTaskSingleMuonMultMc { } } - void processResTrack(McGenCollisions::iterator const& mccollision, McRecCollisions const& collisions, aod::McParticles const& particles, MyTracks const& tracks) + void processResTrack(McGenCollisions::iterator const& mccollision, + McRecCollisions const& collisions, + aod::McParticles const& particles, + MyTracks const& tracks) { // event selections if (std::abs(mccollision.posZ()) > zVtxMax) { @@ -496,7 +511,7 @@ struct HfTaskSingleMuonMultMc { charge = p->Charge(); } - if (std::abs(charge) < MinCharge) { + if (std::abs(charge) < ChargeMin) { continue; } if (particle.pt() < ptTrackMin || std::abs(particle.eta()) >= etaTrackMax) { @@ -514,17 +529,19 @@ struct HfTaskSingleMuonMultMc { auto nTrk = 0; auto tracksample = tracks.sliceBy(perCol, collision.globalIndex()); for (const auto& track : tracksample) { - if (!track.isGlobalTrack()) + if (!track.isGlobalTrack()) { continue; + } registry.fill(HIST("hParticleRec"), track.pt(), track.eta()); ++nTrk; } - if (nTrk < 1) + if (nTrk < 1) { continue; + } registry.fill(HIST("hTrackResponse"), nP, nTrk); } } - PROCESS_SWITCH(HfTaskSingleMuonMultMc, processResTrack, "Process Track Reconstruction/Generation", true); + PROCESS_SWITCH(HfTaskSingleMuonMultMc, processResTrack, "Process Track Reconstruction/Generation", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) From 7fb9ed821f27587f58deffe3e79927ff87af2cc9 Mon Sep 17 00:00:00 2001 From: gengjiabin12 <997406694@qq.com> Date: Wed, 25 Feb 2026 23:57:31 +0800 Subject: [PATCH 081/347] [PWGLF] Mixing Event in buffer (#15163) --- .../Tasks/Strangeness/hStrangeCorrelation.cxx | 347 ++++++++++++++++-- 1 file changed, 307 insertions(+), 40 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx b/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx index 8d56b547a82..04e01e1347a 100644 --- a/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx +++ b/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx @@ -41,6 +41,7 @@ #include +#include #include #include @@ -69,7 +70,7 @@ struct HStrangeCorrelation { struct : ConfigurableGroup { Configurable doPPAnalysis{"doPPAnalysis", true, "if in pp, set to true"}; - Configurable collisionHasTrigOrAssoc{"collisionHasTriggOrAssoc", 0, "require the collisions containing (0:no requirement 1:trig 2:assoc 3:trig or assoc 4:trig and assoc"}; + Configurable collisionHasTriggOrAssoc{"collisionHasTriggOrAssoc", 0, "require the collisions containing (0:no requirement 1:trig 2:assoc 3:trig or assoc 4:trig and assoc"}; Configurable doFullCorrelationStudy{"doFullCorrelationStudy", true, "if true, do full correlation study by creating all THnSparse histograms for the correlation function"}; Configurable doCorrelationHadron{"doCorrelationHadron", false, "do Hadron correlation"}; Configurable doCorrelationK0Short{"doCorrelationK0Short", true, "do K0Short correlation"}; @@ -229,6 +230,35 @@ struct HStrangeCorrelation { // (N.B.: sources that can be investigated in post are not listed!) } systCuts; + struct ValidCollision { + struct ValidParticle { + float eta; + float phi; + float pt; + int region; + float efficiency; + float efficiencyError; + int type; + }; + float pvz; + float mult; + std::vector trigParticles; + std::vector assocParticles; + void addValidParticle(float eta, float phi, float pt, int region, float efficiency, float efficiencyError, int type) + { + ValidParticle particle{eta, phi, pt, region, efficiency, efficiencyError, type}; + + if (type == -1) { + trigParticles.push_back(particle); + } else { + assocParticles.push_back(particle); + } + } + }; + + using ValidCollisions = std::vector>; + ValidCollisions validCollisions; + // objects to use for efficiency corrections TH2F* hEfficiencyTrigger; TH3F* hEfficiencyTriggerMult; @@ -650,8 +680,22 @@ struct HStrangeCorrelation { hist->SetBinContent(bin, currentContent); hist->SetBinError2(bin, currentError2); } - void fillCorrelationsV0(aod::TriggerTracks const& triggers, aod::AssocV0s const& assocs, bool mixing, float pvx, float pvy, float pvz, float mult, double bField) + void fillCorrelationsV0(aod::TriggerTracks const& triggers, aod::AssocV0s const& assocs, bool mixing, bool mixingInBf, float pvx, float pvy, float pvz, float mult, double bField) { + ValidCollision currentCollision; + int binMult = 0; + int nBinsMult = 0; + int nBinsVtxZ = 0; + int binVtxZ = 0; + currentCollision.pvz = pvz; + currentCollision.mult = mult; + if (mixingInBf) { + nBinsMult = histos.get(HIST("axes/hMultAxis"))->GetNbinsX(); + binMult = histos.get(HIST("axes/hMultAxis"))->GetXaxis()->FindBin(mult) - 1; + nBinsVtxZ = histos.get(HIST("axes/hVertexZAxis"))->GetNbinsX(); + binVtxZ = histos.get(HIST("axes/hVertexZAxis"))->GetXaxis()->FindBin(pvz) - 1; + } + bool firstLoop = false; for (auto const& triggerTrack : triggers) { if (masterConfigurations.doTriggPhysicalPrimary && !triggerTrack.mcPhysicalPrimary()) continue; @@ -692,7 +736,13 @@ struct HStrangeCorrelation { double triggSign = trigg.sign(); double triggForDeltaPhiStar[] = {trigg.phi(), trigg.pt(), triggSign}; + if (mixingInBf) { + currentCollision.addValidParticle(trigg.eta(), trigg.phi(), trigg.pt(), -1, efficiencyTrigg, efficiencyTriggError, -1); + if (firstLoop) + continue; + } for (auto const& assocCandidate : assocs) { + firstLoop = true; auto assoc = assocCandidate.v0Core_as(); //---] syst cuts [--- @@ -709,14 +759,16 @@ struct HStrangeCorrelation { //---] removing autocorrelations [--- auto postrack = assoc.posTrack_as(); auto negtrack = assoc.negTrack_as(); - if (doAutocorrelationRejection) { - if (trigg.globalIndex() == postrack.globalIndex()) { - histos.fill(HIST("hNumberOfRejectedPairsV0"), 0.5); - continue; - } - if (trigg.globalIndex() == negtrack.globalIndex()) { - histos.fill(HIST("hNumberOfRejectedPairsV0"), 0.5); - continue; + if (!mixingInBf) { + if (doAutocorrelationRejection) { + if (trigg.globalIndex() == postrack.globalIndex()) { + histos.fill(HIST("hNumberOfRejectedPairsV0"), 0.5); + continue; + } + if (trigg.globalIndex() == negtrack.globalIndex()) { + histos.fill(HIST("hNumberOfRejectedPairsV0"), 0.5); + continue; + } } } @@ -864,20 +916,100 @@ struct HStrangeCorrelation { } } } - if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && -massWindowConfigurations.maxBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < -massWindowConfigurations.minBgNSigma) - fillCorrelationHistogram(histos.get(HIST("mixedEvent/LeftBg/") + HIST(V0names[Index])), binFillThn, 1, efficiency * efficiencyTrigg, totalEffUncert, purityTrigg, purityTriggErr); - if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && -massWindowConfigurations.maxPeakNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxPeakNSigma) - fillCorrelationHistogram(histos.get(HIST("mixedEvent/Signal/") + HIST(V0names[Index])), binFillThn, 1, efficiency * efficiencyTrigg, totalEffUncert, purityTrigg, purityTriggErr); - if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && +massWindowConfigurations.minBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxBgNSigma) - fillCorrelationHistogram(histos.get(HIST("mixedEvent/RightBg/") + HIST(V0names[Index])), binFillThn, 1, efficiency * efficiencyTrigg, totalEffUncert, purityTrigg, purityTriggErr); + if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && -massWindowConfigurations.maxBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < -massWindowConfigurations.minBgNSigma) { + if (mixingInBf) { + currentCollision.addValidParticle(assoc.eta(), assoc.phi(), assoc.pt(), 0, efficiency, efficiencyError, Index); + } else { + fillCorrelationHistogram(histos.get(HIST("mixedEvent/LeftBg/") + HIST(V0names[Index])), binFillThn, 1, efficiency * efficiencyTrigg, totalEffUncert, purityTrigg, purityTriggErr); + } + } + if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && -massWindowConfigurations.maxPeakNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxPeakNSigma) { + if (mixingInBf) { + currentCollision.addValidParticle(assoc.eta(), assoc.phi(), assoc.pt(), 1, efficiencyTrigg, efficiencyError, Index); + } else { + fillCorrelationHistogram(histos.get(HIST("mixedEvent/Signal/") + HIST(V0names[Index])), binFillThn, 1, efficiency * efficiencyTrigg, totalEffUncert, purityTrigg, purityTriggErr); + } + } + if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && +massWindowConfigurations.minBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxBgNSigma) { + if (mixingInBf) { + currentCollision.addValidParticle(assoc.eta(), assoc.phi(), assoc.pt(), 2, efficiencyTrigg, efficiencyError, Index); + } else { + fillCorrelationHistogram(histos.get(HIST("mixedEvent/RightBg/") + HIST(V0names[Index])), binFillThn, 1, efficiency * efficiencyTrigg, totalEffUncert, purityTrigg, purityTriggErr); + } + } } }); } } + if (!mixingInBf || binVtxZ < 0 || binVtxZ > nBinsVtxZ - 1 || binMult < 0 || binMult > nBinsMult - 1) + return; + int binnumb = binMult * nBinsVtxZ + binVtxZ; + int hastirgorassoc = masterConfigurations.collisionHasTriggOrAssoc; + if ((hastirgorassoc == 1 && currentCollision.trigParticles.empty()) || + (hastirgorassoc == 2 && currentCollision.assocParticles.empty()) || + (hastirgorassoc == 3 && currentCollision.trigParticles.empty() && currentCollision.assocParticles.empty()) || + (hastirgorassoc == 4 && (currentCollision.trigParticles.empty() || currentCollision.assocParticles.empty()))) + return; + for (const auto& collision : validCollisions[binnumb]) { + BinningTypePP colBinning{{axesConfigurations.axisVtxZ, axesConfigurations.axisMult}, true}; + // When 'collisionHasTriggOrAssoc' = 0: + // binContent(hMECollisionBins) = Σ(RunNumbers)[binContent(the same bin of hSECollisionBins) * masterConfigurations.mixingParameter - Σ(k=0 to min(masterConfigurations.mixingParameter,binContent)) k] + // When 'collisionHasTriggOrAssoc' = 3 + // More collision loss at higher peripheral centrality (fewer target particles); higher bincontent of HIST("mixedEvent/Signal/") + HIST(Cascadenames[Index]) + // due to avoiding vector occupancy by collisions with no trigger&associated particles + histos.fill(HIST("MixingQA/hMECollisionBins"), colBinning.getBin({collision.pvz, collision.mult})); + for (const auto& trigger : collision.trigParticles) { + for (const auto& assoc : currentCollision.assocParticles) { + float deltaeta = trigger.eta - assoc.eta; + float deltaphi = computeDeltaPhi(trigger.phi, assoc.phi); + float efficiencyTrigg = trigger.efficiency; + float efficiencyAssoc = assoc.efficiency; + float efficiencyTriggError = trigger.efficiencyError; + float efficiencyAssocError = assoc.efficiencyError; + float totalEffUncert = 0.0; + float ptassoc = assoc.pt; + float pttrigger = trigger.pt; + if (efficiencyFlags.applyEfficiencyPropagation) { + totalEffUncert = std::sqrt(std::pow(efficiencyTrigg * efficiencyAssocError, 2) + std::pow(efficiencyTriggError * efficiencyAssoc, 2)); + } + double binFillThn[6] = {deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult}; + static_for<0, 2>([&](auto i) { + constexpr int Index = i.value; + if (Index == assoc.type && assoc.region == 0) { + fillCorrelationHistogram(histos.get(HIST("mixedEvent/LeftBg/") + HIST(V0names[Index])), binFillThn, 1, efficiencyTrigg * efficiencyAssoc, totalEffUncert, 1., 0.); + } + if (Index == assoc.type && assoc.region == 1) { + fillCorrelationHistogram(histos.get(HIST("mixedEvent/Signal/") + HIST(V0names[Index])), binFillThn, 1, efficiencyTrigg * efficiencyAssoc, totalEffUncert, 1., 0.); + } + if (Index == assoc.type && assoc.region == 2) { + fillCorrelationHistogram(histos.get(HIST("mixedEvent/RightBg/") + HIST(V0names[Index])), binFillThn, 1, efficiencyTrigg * efficiencyAssoc, totalEffUncert, 1., 0.); + } + }); + } + } + } + if (validCollisions[binnumb].size() >= static_cast(masterConfigurations.mixingParameter)) { + validCollisions[binnumb].erase(validCollisions[binnumb].begin()); + } + validCollisions[binnumb].push_back(currentCollision); } - void fillCorrelationsCascade(aod::TriggerTracks const& triggers, aod::AssocCascades const& assocs, bool mixing, float pvx, float pvy, float pvz, float mult, double bField) + void fillCorrelationsCascade(aod::TriggerTracks const& triggers, aod::AssocCascades const& assocs, bool mixing, bool mixingInBf, float pvx, float pvy, float pvz, float mult, double bField) { + ValidCollision currentCollision; + int nBinsMult = 0; + int binMult = 0; + int nBinsVtxZ = 0; + int binVtxZ = 0; + currentCollision.pvz = pvz; + currentCollision.mult = mult; + if (mixingInBf) { + nBinsMult = histos.get(HIST("axes/hMultAxis"))->GetNbinsX(); + binMult = histos.get(HIST("axes/hMultAxis"))->GetXaxis()->FindBin(mult) - 1; + nBinsVtxZ = histos.get(HIST("axes/hVertexZAxis"))->GetNbinsX(); + binVtxZ = histos.get(HIST("axes/hVertexZAxis"))->GetXaxis()->FindBin(pvz) - 1; + } + bool firstLoop = false; for (auto const& triggerTrack : triggers) { if (masterConfigurations.doTriggPhysicalPrimary && !triggerTrack.mcPhysicalPrimary()) continue; @@ -929,7 +1061,13 @@ struct HStrangeCorrelation { double triggSign = trigg.sign(); double triggForDeltaPhiStar[] = {trigg.phi(), trigg.pt(), triggSign}; + if (mixingInBf) { + currentCollision.addValidParticle(trigg.eta(), trigg.phi(), trigg.pt(), -1, efficiencyTrigg, efficiencyTriggError, -1); + if (firstLoop) + continue; + } for (auto const& assocCandidate : assocs) { + firstLoop = true; auto assoc = assocCandidate.cascData(); //---] syst cuts [--- @@ -951,18 +1089,20 @@ struct HStrangeCorrelation { auto postrack = assoc.posTrack_as(); auto negtrack = assoc.negTrack_as(); auto bachtrack = assoc.bachelor_as(); - if (doAutocorrelationRejection) { - if (trigg.globalIndex() == postrack.globalIndex()) { - histos.fill(HIST("hNumberOfRejectedPairsCascades"), 0.5); - continue; - } - if (trigg.globalIndex() == negtrack.globalIndex()) { - histos.fill(HIST("hNumberOfRejectedPairsCascades"), 0.5); - continue; - } - if (trigg.globalIndex() == bachtrack.globalIndex()) { - histos.fill(HIST("hNumberOfRejectedPairsCascades"), 0.5); - continue; + if (!mixingInBf) { + if (doAutocorrelationRejection) { + if (trigg.globalIndex() == postrack.globalIndex()) { + histos.fill(HIST("hNumberOfRejectedPairsCascades"), 0.5); + continue; + } + if (trigg.globalIndex() == negtrack.globalIndex()) { + histos.fill(HIST("hNumberOfRejectedPairsCascades"), 0.5); + continue; + } + if (trigg.globalIndex() == bachtrack.globalIndex()) { + histos.fill(HIST("hNumberOfRejectedPairsCascades"), 0.5); + continue; + } } } double phiProton = postrack.phi(); @@ -1075,16 +1215,77 @@ struct HStrangeCorrelation { histos.fill(HIST("sameEvent/RightBg/") + HIST(Cascadenames[Index]) + HIST("DeltaPhiStar"), deltaPhiStar, trigg.eta() - etaProton, -0.5); } } - if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && -massWindowConfigurations.maxBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < -massWindowConfigurations.minBgNSigma) - fillCorrelationHistogram(histos.get(HIST("mixedEvent/LeftBg/") + HIST(Cascadenames[Index])), binFillThn, 1, efficiency * efficiencyTrigg, totalEffUncert, purityTrigg, purityTriggErr); - if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && -massWindowConfigurations.maxPeakNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxPeakNSigma) - fillCorrelationHistogram(histos.get(HIST("mixedEvent/Signal/") + HIST(Cascadenames[Index])), binFillThn, 1, efficiency * efficiencyTrigg, totalEffUncert, purityTrigg, purityTriggErr); - if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && +massWindowConfigurations.minBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxBgNSigma) - fillCorrelationHistogram(histos.get(HIST("mixedEvent/RightBg/") + HIST(Cascadenames[Index])), binFillThn, 1, efficiency * efficiencyTrigg, totalEffUncert, purityTrigg, purityTriggErr); + if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && -massWindowConfigurations.maxBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < -massWindowConfigurations.minBgNSigma) { + if (mixingInBf) { + currentCollision.addValidParticle(assoc.eta(), assoc.phi(), assoc.pt(), 0, efficiency, efficiencyError, Index); + } else { + fillCorrelationHistogram(histos.get(HIST("mixedEvent/LeftBg/") + HIST(Cascadenames[Index])), binFillThn, 1, efficiency * efficiencyTrigg, totalEffUncert, purityTrigg, purityTriggErr); + } + } + if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && -massWindowConfigurations.maxPeakNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxPeakNSigma) { + if (mixingInBf) { + currentCollision.addValidParticle(assoc.eta(), assoc.phi(), assoc.pt(), 1, efficiency, efficiencyError, Index); + } else { + fillCorrelationHistogram(histos.get(HIST("mixedEvent/Signal/") + HIST(Cascadenames[Index])), binFillThn, 1, efficiency * efficiencyTrigg, totalEffUncert, purityTrigg, purityTriggErr); + } + } + if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && +massWindowConfigurations.minBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxBgNSigma) { + if (mixingInBf) { + currentCollision.addValidParticle(assoc.eta(), assoc.phi(), assoc.pt(), 2, efficiency, efficiencyError, Index); + } else { + fillCorrelationHistogram(histos.get(HIST("mixedEvent/RightBg/") + HIST(Cascadenames[Index])), binFillThn, 1, efficiency * efficiencyTrigg, totalEffUncert, purityTrigg, purityTriggErr); + } + } } }); } } + if (!mixingInBf || binVtxZ < 0 || binVtxZ > nBinsVtxZ - 1 || binMult < 0 || binMult > nBinsMult - 1) + return; + int binnumb = binMult * nBinsVtxZ + binVtxZ; + int hastirgorassoc = masterConfigurations.collisionHasTriggOrAssoc; + if ((hastirgorassoc == 1 && currentCollision.trigParticles.empty()) || + (hastirgorassoc == 2 && currentCollision.assocParticles.empty()) || + (hastirgorassoc == 3 && currentCollision.trigParticles.empty() && currentCollision.assocParticles.empty()) || + (hastirgorassoc == 4 && (currentCollision.trigParticles.empty() || currentCollision.assocParticles.empty()))) + return; + for (const auto& collision : validCollisions[binnumb]) { + BinningTypePP colBinning{{axesConfigurations.axisVtxZ, axesConfigurations.axisMult}, true}; + histos.fill(HIST("MixingQA/hMECollisionBins"), colBinning.getBin({collision.pvz, collision.mult})); + for (const auto& trigger : collision.trigParticles) { + for (const auto& assoc : currentCollision.assocParticles) { + float deltaeta = trigger.eta - assoc.eta; + float deltaphi = computeDeltaPhi(trigger.phi, assoc.phi); + float efficiencyTrigg = trigger.efficiency; + float efficiencyAssoc = assoc.efficiency; + float efficiencyTriggError = trigger.efficiencyError; + float efficiencyAssocError = assoc.efficiencyError; + float totalEffUncert = 0.0; + float ptassoc = assoc.pt; + float pttrigger = trigger.pt; + if (efficiencyFlags.applyEfficiencyPropagation) { + totalEffUncert = std::sqrt(std::pow(efficiencyTrigg * efficiencyAssocError, 2) + std::pow(efficiencyTriggError * efficiencyAssoc, 2)); + } + double binFillThn[6] = {deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult}; + static_for<0, 3>([&](auto i) { + constexpr int Index = i.value; + if (Index == assoc.type && assoc.region == 0) { + fillCorrelationHistogram(histos.get(HIST("mixedEvent/LeftBg/") + HIST(Cascadenames[Index])), binFillThn, 1, efficiencyTrigg * efficiencyAssoc, totalEffUncert, 1., 0.); + } + if (Index == assoc.type && assoc.region == 1) { + fillCorrelationHistogram(histos.get(HIST("mixedEvent/Signal/") + HIST(Cascadenames[Index])), binFillThn, 1, efficiencyTrigg * efficiencyAssoc, totalEffUncert, 1., 0.); + } + if (Index == assoc.type && assoc.region == 2) { + fillCorrelationHistogram(histos.get(HIST("mixedEvent/RightBg/") + HIST(Cascadenames[Index])), binFillThn, 1, efficiencyTrigg * efficiencyAssoc, totalEffUncert, 1., 0.); + } + }); + } + } + } + if (validCollisions[binnumb].size() >= static_cast(masterConfigurations.mixingParameter)) { + validCollisions[binnumb].erase(validCollisions[binnumb].begin()); + } + validCollisions[binnumb].push_back(currentCollision); } template void fillCorrelationsHadron(TTriggers const& triggers, THadrons const& assocs, bool mixing, float pvz, float mult, double bField) @@ -1451,6 +1652,13 @@ struct HStrangeCorrelation { const AxisSpec axisPtTriggerNDim{edgesPtTrigger, "#it{p}_{T}^{trigger} (GeV/c)"}; const AxisSpec axisVtxZNDim{edgesVtxZ, "vertex Z (cm)"}; const AxisSpec axisMultNDim{edgesMult, "mult percentile"}; + + if (doprocessMixedEventHV0sInBuffer || doprocessMixedEventHCascadesInBuffer) { + validCollisions.resize(histos.get(HIST("axes/hMultAxis"))->GetNbinsX() * histos.get(HIST("axes/hVertexZAxis"))->GetNbinsX()); + for (auto& inner_vec : validCollisions) { + inner_vec.reserve(masterConfigurations.mixingParameter); + } + } if (!masterConfigurations.doPPAnalysis) { // event selections in Pb-Pb histos.add("hEventSelection", "hEventSelection", kTH1F, {{10, 0, 10}}); @@ -1559,7 +1767,7 @@ struct HStrangeCorrelation { LOGF(info, "Init THnFs done"); // mixed-event correlation functions - if ((doprocessMixedEventHV0s || doprocessMixedEventHCascades || doprocessMixedEventHPions || doprocessMixedEventHHadrons) && masterConfigurations.doFullCorrelationStudy) { + if ((doprocessMixedEventHV0sInBuffer || doprocessMixedEventHCascadesInBuffer || doprocessMixedEventHV0s || doprocessMixedEventHCascades || doprocessMixedEventHPions || doprocessMixedEventHHadrons) && masterConfigurations.doFullCorrelationStudy) { histos.addClone("sameEvent/", "mixedEvent/"); } if (doprocessSameEventHHadrons && masterConfigurations.doFullCorrelationStudy) @@ -2012,7 +2220,7 @@ struct HStrangeCorrelation { // ________________________________________________ // Do hadron - V0 correlations if (masterConfigurations.doFullCorrelationStudy) - fillCorrelationsV0(triggerTracks, associatedV0s, false, collision.posX(), collision.posY(), collision.posZ(), cent, bField); + fillCorrelationsV0(triggerTracks, associatedV0s, false, false, collision.posX(), collision.posY(), collision.posZ(), cent, bField); } void processSameEventHCascades(soa::Join::iterator const& collision, @@ -2158,7 +2366,7 @@ struct HStrangeCorrelation { // ________________________________________________ // Do hadron - cascade correlations if (masterConfigurations.doFullCorrelationStudy) - fillCorrelationsCascade(triggerTracks, associatedCascades, false, collision.posX(), collision.posY(), collision.posZ(), cent, bField); + fillCorrelationsCascade(triggerTracks, associatedCascades, false, false, collision.posX(), collision.posY(), collision.posZ(), cent, bField); } void processSameEventHPions(soa::Join::iterator const& collision, soa::Join const& associatedPions, soa::Join const& triggerTracks, @@ -2321,7 +2529,7 @@ struct HStrangeCorrelation { // ________________________________________________ // Do hadron - V0 correlations if (masterConfigurations.doFullCorrelationStudy) - fillCorrelationsV0(slicedTriggerTracks, slicedAssocV0s, true, collision1.posX(), collision1.posY(), collision1.posZ(), cent1, bField); + fillCorrelationsV0(slicedTriggerTracks, slicedAssocV0s, true, false, collision1.posX(), collision1.posY(), collision1.posZ(), cent1, bField); } }, colBinning); @@ -2376,7 +2584,7 @@ struct HStrangeCorrelation { // ________________________________________________ // Do hadron - cascade correlations if (masterConfigurations.doFullCorrelationStudy) - fillCorrelationsCascade(slicedTriggerTracks, slicedAssocCascades, true, collision1.posX(), collision1.posY(), collision1.posZ(), cent1, bField); + fillCorrelationsCascade(slicedTriggerTracks, slicedAssocCascades, true, false, collision1.posX(), collision1.posY(), collision1.posZ(), cent1, bField); } }, colBinning); @@ -2894,6 +3102,63 @@ struct HStrangeCorrelation { } } } + void processMixedEventHV0sInBuffer(soa::Join::iterator const& collision, + aod::AssocV0s const& associatedV0s, aod::TriggerTracks const& triggerTracks, + V0DatasWithoutTrackX const&, TracksComplete const&, aod::BCsWithTimestamps const&) + { + + double cent = masterConfigurations.doPPAnalysis ? collision.centFT0M() : collision.centFT0C(); + + auto bc = collision.template bc_as(); + auto bField = getMagneticField(bc.timestamp()); + // ________________________________________________ + if (efficiencyFlags.applyEfficiencyCorrection) { + initEfficiencyFromCCDB(bc); + } + // ________________________________________________ + // skip if desired trigger not found + if (triggerPresenceMap.size() > 0 && !TESTBIT(triggerPresenceMap[collision.globalIndex()], triggerBinToSelect)) { + return; + } + + // Perform basic event selection on both collisions + if (((masterConfigurations.doPPAnalysis && !isCollisionSelected(collision))) || (!masterConfigurations.doPPAnalysis && !isCollisionSelectedPbPb(collision, true))) { + return; + } + if (cent > axisRanges[5][1] || cent < axisRanges[5][0]) + return; + + // ________________________________________________ + if (masterConfigurations.doFullCorrelationStudy) + fillCorrelationsV0(triggerTracks, associatedV0s, true, true, collision.posX(), collision.posY(), collision.posZ(), cent, bField); + } + void processMixedEventHCascadesInBuffer(soa::Join::iterator const& collision, + aod::AssocV0s const&, aod::AssocCascades const& associatedCascades, aod::TriggerTracks const& triggerTracks, + V0DatasWithoutTrackX const&, aod::CascDatas const&, TracksComplete const&, aod::BCsWithTimestamps const&) + { + double cent = masterConfigurations.doPPAnalysis ? collision.centFT0M() : collision.centFT0C(); + // ________________________________________________ + auto bc = collision.template bc_as(); + auto bField = getMagneticField(bc.timestamp()); + if (efficiencyFlags.applyEfficiencyCorrection) { + initEfficiencyFromCCDB(bc); + } + // ________________________________________________ + // skip if desired trigger not found + if (triggerPresenceMap.size() > 0 && !TESTBIT(triggerPresenceMap[collision.globalIndex()], triggerBinToSelect)) { + return; + } + // Perform basic event selection on both collisions + if ((masterConfigurations.doPPAnalysis && !isCollisionSelected(collision)) || (!masterConfigurations.doPPAnalysis && (!isCollisionSelectedPbPb(collision, true)))) { + return; + } + if (cent > axisRanges[5][1] || cent < axisRanges[5][0]) + return; + // ________________________________________________ + // Do hadron - cascade correlations + if (masterConfigurations.doFullCorrelationStudy) + fillCorrelationsCascade(triggerTracks, associatedCascades, true, true, collision.posX(), collision.posY(), collision.posZ(), cent, bField); + } PROCESS_SWITCH(HStrangeCorrelation, processSelectEventWithTrigger, "Select events with trigger only", true); PROCESS_SWITCH(HStrangeCorrelation, processSameEventHV0s, "Process same events, h-V0s", true); PROCESS_SWITCH(HStrangeCorrelation, processSameEventHCascades, "Process same events, h-Cascades", true); @@ -2904,6 +3169,8 @@ struct HStrangeCorrelation { PROCESS_SWITCH(HStrangeCorrelation, processMixedEventHCascades, "Process mixed events, h-Cascades", true); PROCESS_SWITCH(HStrangeCorrelation, processMixedEventHPions, "Process mixed events, h-Pion", true); PROCESS_SWITCH(HStrangeCorrelation, processMixedEventHHadrons, "Process mixed events, h-h", true); + PROCESS_SWITCH(HStrangeCorrelation, processMixedEventHV0sInBuffer, "Process mixed events in buffer, h-h", true); + PROCESS_SWITCH(HStrangeCorrelation, processMixedEventHCascadesInBuffer, "Process mixed events in buffer, h-h", true); PROCESS_SWITCH(HStrangeCorrelation, processMCGenerated, "Process MC generated", false); PROCESS_SWITCH(HStrangeCorrelation, processClosureTest, "Process Closure Test", false); From 700ac3a2e8e20422995f14f9303974cc3a1416f7 Mon Sep 17 00:00:00 2001 From: Rocco Liotino Date: Wed, 25 Feb 2026 17:28:00 +0100 Subject: [PATCH 082/347] [DPG] updating table producer (#15119) --- .../AOTTrack/PID/HMPID/hmpidTableProducer.cxx | 88 +++++++++++++------ DPG/Tasks/AOTTrack/PID/HMPID/tableHMPID.h | 5 -- 2 files changed, 59 insertions(+), 34 deletions(-) diff --git a/DPG/Tasks/AOTTrack/PID/HMPID/hmpidTableProducer.cxx b/DPG/Tasks/AOTTrack/PID/HMPID/hmpidTableProducer.cxx index 76267171742..f2865d65be9 100644 --- a/DPG/Tasks/AOTTrack/PID/HMPID/hmpidTableProducer.cxx +++ b/DPG/Tasks/AOTTrack/PID/HMPID/hmpidTableProducer.cxx @@ -38,6 +38,7 @@ #include #include +#include using namespace o2; using namespace o2::framework; @@ -57,24 +58,28 @@ struct HmpidTableProducer { Produces hmpidAnalysis; - // using TrackCandidates = soa::Join; + // configurable for quality requirements + Configurable requireITS{"requireITS", true, "Require ITS track"}; + Configurable requireTPC{"requireTPC", true, "Require TPC track"}; + Configurable requireTOF{"requireTOF", true, "Require TOF track"}; - using CollisionCandidates = o2::soa::Join; + using CollisionCandidates = o2::soa::Join; using TrackCandidates = soa::Join; - // using CentralityClass = o2::soa::Join; - void init(o2::framework::InitContext&) { // Configure CCDB ccdb->setURL(ccdbConfig.ccdbUrl); ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); histos.add("eventCounter", "eventCounter", kTH1F, {axisEvtCounter}); + histos.add("goodEventCounter", "goodEventCounter", kTH1F, {axisEvtCounter}); + histos.add("eventsHmpid", "eventsWithHmpid", kTH1F, {axisEvtCounter}); } // function to manage ccdb @@ -87,50 +92,75 @@ struct HmpidTableProducer { mCCDBRunNumber = bc.runNumber(); } - void process(soa::Join::iterator const& col, - const aod::HMPIDs& hmpids, - TrackCandidates const&, - aod::BCsWithTimestamps const&) + void processEvent(CollisionCandidates::iterator const& col, + aod::BCsWithTimestamps const&) { histos.fill(HIST("eventCounter"), 0.5); + if (col.sel8()) { + histos.fill(HIST("goodEventCounter"), 0.5); + } + // initialize CCDB for current BC initCCDB(col.bc_as()); + } + PROCESS_SWITCH(HmpidTableProducer, processEvent, "Process event level - collisions", true); + + void processHmpid( + aod::HMPIDs const& hmpids, + TrackCandidates const&, + CollisionCandidates const&, + aod::BCsWithTimestamps const&) + { + // --- Static set to track unique collisions with HMPID tracks --- + static std::unordered_set collisionsWithHmpid; - for (const auto& t : hmpids) { + for (auto const& t : hmpids) { - // global tracks associated to hmpid tracks + // Access the global track associated to the HMPID track const auto& globalTrack = t.track_as(); - if (!globalTrack.isGlobalTrack()) - continue; - if (!globalTrack.hasITS() || !globalTrack.hasTPC() || !globalTrack.hasTOF()) + + if (!globalTrack.has_collision()) continue; - // verify accessible collision - if (!globalTrack.has_collision()) { + // Access the associated collision + const auto& col = globalTrack.collision_as(); + initCCDB(col.bc_as()); + uint32_t collId = col.globalIndex(); + + // --- Track quality selection --- + if ((requireITS && !globalTrack.hasITS()) || + (requireTPC && !globalTrack.hasTPC()) || + (requireTOF && !globalTrack.hasTOF())) { continue; } + // Count collisions with at least one valid HMPID track + if (collisionsWithHmpid.insert(collId).second) { + histos.fill(HIST("eventsHmpid"), 0.5); + } + + float centrality = col.centFV0A(); + float hmpidPhotsCharge2[o2::aod::kDimPhotonsCharge]; for (int i = 0; i < o2::aod::kDimPhotonsCharge; i++) { hmpidPhotsCharge2[i] = t.hmpidPhotsCharge()[i]; } - float centrality = col.centFV0A(); - - /////FILL TABLE - hmpidAnalysis( - t.hmpidSignal(), globalTrack.phi(), globalTrack.eta(), t.hmpidMom(), - globalTrack.p(), t.hmpidXTrack(), t.hmpidYTrack(), t.hmpidXMip(), - t.hmpidYMip(), t.hmpidNPhotons(), t.hmpidQMip(), (t.hmpidClusSize() % 1000000) / 1000, - t.hmpidClusSize() / 1000000, hmpidPhotsCharge2, globalTrack.eta(), globalTrack.phi(), - globalTrack.px(), globalTrack.py(), globalTrack.pz(), globalTrack.itsNCls(), - globalTrack.tpcNClsFound(), globalTrack.tpcNClsCrossedRows(), globalTrack.tpcChi2NCl(), globalTrack.itsChi2NCl(), - globalTrack.dcaXY(), globalTrack.dcaZ(), globalTrack.tpcNSigmaPi(), globalTrack.tofNSigmaPi(), - globalTrack.tpcNSigmaKa(), globalTrack.tofNSigmaKa(), globalTrack.tpcNSigmaPr(), globalTrack.tofNSigmaPr(), - globalTrack.tpcNSigmaDe(), globalTrack.tofNSigmaDe(), centrality); - } + /////FILL HMPID CUSTOM TABLE + hmpidAnalysis(t.hmpidSignal(), t.hmpidMom(), + globalTrack.p(), t.hmpidXTrack(), t.hmpidYTrack(), t.hmpidXMip(), + t.hmpidYMip(), t.hmpidNPhotons(), t.hmpidQMip(), (t.hmpidClusSize() % 1000000) / 1000, + t.hmpidClusSize() / 1000000, hmpidPhotsCharge2, globalTrack.eta(), globalTrack.phi(), + globalTrack.px(), globalTrack.py(), globalTrack.pz(), globalTrack.itsNCls(), + globalTrack.tpcNClsFound(), globalTrack.tpcNClsCrossedRows(), globalTrack.tpcChi2NCl(), globalTrack.itsChi2NCl(), + globalTrack.dcaXY(), globalTrack.dcaZ(), globalTrack.tpcNSigmaPi(), globalTrack.tofNSigmaPi(), + globalTrack.tpcNSigmaKa(), globalTrack.tofNSigmaKa(), globalTrack.tpcNSigmaPr(), globalTrack.tofNSigmaPr(), + globalTrack.tpcNSigmaDe(), globalTrack.tofNSigmaDe(), centrality); + } // end loop on hmpid table entries } + + PROCESS_SWITCH(HmpidTableProducer, processHmpid, "Process hmpid entries - tracks", true); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfg) { return WorkflowSpec{adaptAnalysisTask(cfg)}; } diff --git a/DPG/Tasks/AOTTrack/PID/HMPID/tableHMPID.h b/DPG/Tasks/AOTTrack/PID/HMPID/tableHMPID.h index 045282d3e0e..dff3a00ed4f 100644 --- a/DPG/Tasks/AOTTrack/PID/HMPID/tableHMPID.h +++ b/DPG/Tasks/AOTTrack/PID/HMPID/tableHMPID.h @@ -23,8 +23,6 @@ inline constexpr int kDimPhotonsCharge = 10; namespace variables_table { DECLARE_SOA_COLUMN(ChAngle, chAngle, float); -DECLARE_SOA_COLUMN(Phi, phi, float); -DECLARE_SOA_COLUMN(Eta, eta, float); DECLARE_SOA_COLUMN(MomentumHmpid, momentumHmpid, float); DECLARE_SOA_COLUMN(MomentumTrack, momentumTrack, float); DECLARE_SOA_COLUMN(XTrack, xTrack, float); @@ -60,15 +58,12 @@ DECLARE_SOA_COLUMN(TpcNSigmaPr, tpcNSigmaPr, float); DECLARE_SOA_COLUMN(TofNSigmaPr, tofNSigmaPr, float); DECLARE_SOA_COLUMN(TpcNSigmaDe, tpcNSigmaDe, float); DECLARE_SOA_COLUMN(TofNSigmaDe, tofNSigmaDe, float); - DECLARE_SOA_COLUMN(Centrality, centrality, float); } // namespace variables_table DECLARE_SOA_TABLE(HmpidAnalysis, "AOD", "HMPIDANALYSIS", variables_table::ChAngle, - variables_table::Phi, - variables_table::Eta, variables_table::MomentumHmpid, variables_table::MomentumTrack, variables_table::XTrack, From cd15898f2f47288b3e05c80e0063e8803110c9e9 Mon Sep 17 00:00:00 2001 From: EmilGorm <50658075+EmilGorm@users.noreply.github.com> Date: Wed, 25 Feb 2026 20:53:32 +0100 Subject: [PATCH 083/347] =?UTF-8?q?[PWGCF]=20fixed=20subevent=20central=20?= =?UTF-8?q?moments=20skipping=20fills=20due=20to=20higher-orders=20no?= =?UTF-8?q?=E2=80=A6=20(#15159)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../GenericFramework/Core/FlowPtContainer.cxx | 127 +++++++++--------- 1 file changed, 67 insertions(+), 60 deletions(-) diff --git a/PWGCF/GenericFramework/Core/FlowPtContainer.cxx b/PWGCF/GenericFramework/Core/FlowPtContainer.cxx index b8189636987..f527b05d6af 100644 --- a/PWGCF/GenericFramework/Core/FlowPtContainer.cxx +++ b/PWGCF/GenericFramework/Core/FlowPtContainer.cxx @@ -699,8 +699,9 @@ void FlowPtContainer::fillSubeventPtProfiles(const double& centmult, const doubl } ++subIndex; } - if (valid) + if (valid) { dynamic_cast(fSubList->At(histCounter))->FillProfile(centmult, val, (fEventWeight == EventWeight::UnityWeight) ? 1.0 : dn, rn); + } ++histCounter; } return; @@ -907,16 +908,18 @@ void FlowPtContainer::fillCMSubeventProfiles(const double& centmult, const doubl for (int im = 1; im <= mpar; im++) { indOffset += im; } + + std::vector validMpar = {0, 0, 0}; // 0th order correlation cmDenSub[0].push_back(1.); cmValSub[0].push_back(1.); cmDenSub[nSubevents - 1].push_back(1.); cmValSub[nSubevents - 1].push_back(1.); - cmDenSub[0].push_back(insub[0][getVectorIndex(1, 0)]); - cmDenSub[0].push_back(insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] - insub[0][getVectorIndex(2, 0)]); - cmDenSub[0].push_back(insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] - 3 * insub[0][getVectorIndex(2, 0)] * insub[0][getVectorIndex(1, 0)] + 2 * insub[0][getVectorIndex(3, 0)]); - cmDenSub[0].push_back(insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] - 6 * insub[0][getVectorIndex(2, 0)] * insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] + 8 * insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(3, 0)] + 3 * insub[0][getVectorIndex(2, 0)] * insub[0][getVectorIndex(2, 0)] - 6 * insub[0][getVectorIndex(4, 0)]); + cmDenSub[0].push_back(insub[0][getVectorIndex(1, 0)]); // cmDensub[0][1] = sum w + cmDenSub[0].push_back(insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] - insub[0][getVectorIndex(2, 0)]); // cmDensub[0][2] = sum wi wj + cmDenSub[0].push_back(insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] - 3 * insub[0][getVectorIndex(2, 0)] * insub[0][getVectorIndex(1, 0)] + 2 * insub[0][getVectorIndex(3, 0)]); // cmDensub[0][3] = sum wi wj wk + cmDenSub[0].push_back(insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] - 6 * insub[0][getVectorIndex(2, 0)] * insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] + 8 * insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(3, 0)] + 3 * insub[0][getVectorIndex(2, 0)] * insub[0][getVectorIndex(2, 0)] - 6 * insub[0][getVectorIndex(4, 0)]); // cmDensub[0][4] = sum wi wj wk wl cmDenSub[nSubevents - 1].push_back(insub[nSubevents - 1][getVectorIndex(1, 0)]); cmDenSub[nSubevents - 1].push_back(insub[nSubevents - 1][getVectorIndex(1, 0)] * insub[nSubevents - 1][getVectorIndex(1, 0)] - insub[nSubevents - 1][getVectorIndex(2, 0)]); @@ -932,65 +935,68 @@ void FlowPtContainer::fillCMSubeventProfiles(const double& centmult, const doubl dynamic_cast(fSubCMList->At(indOffset + 0))->FillProfile(centmult, cmValSub[nSubevents - 1][1], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[nSubevents - 1][1], rn); } - if (mpar < 2) - return; - if (insub[0][getVectorIndex(2, 0)] != 0 && cmDenSub[0][2] != 0) { - cmValSub[0].push_back(1 / cmDenSub[0][2] * (insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] - insub[0][getVectorIndex(2, 2)])); - dynamic_cast(fSubCMList->At(1))->FillProfile(centmult, cmValSub[0][2], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[0][2], rn); - cmValSub[0].push_back(1 / cmDenSub[0][2] * (insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 1)] - insub[0][getVectorIndex(2, 1)])); - dynamic_cast(fSubCMList->At(2))->FillProfile(centmult, cmValSub[0][3], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[0][2], rn); - } - if (insub[nSubevents - 1][getVectorIndex(2, 0)] != 0 && cmDenSub[nSubevents - 1][2] != 0) { - cmValSub[nSubevents - 1].push_back(1 / cmDenSub[nSubevents - 1][2] * (insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] - insub[nSubevents - 1][getVectorIndex(2, 2)])); - dynamic_cast(fSubCMList->At(indOffset + 1))->FillProfile(centmult, cmValSub[nSubevents - 1][2], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[nSubevents - 1][2], rn); - cmValSub[nSubevents - 1].push_back(1 / cmDenSub[nSubevents - 1][2] * (insub[nSubevents - 1][getVectorIndex(1, 0)] * insub[nSubevents - 1][getVectorIndex(1, 1)] - insub[nSubevents - 1][getVectorIndex(2, 1)])); - dynamic_cast(fSubCMList->At(indOffset + 2))->FillProfile(centmult, cmValSub[nSubevents - 1][3], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[nSubevents - 1][2], rn); - } - - if (mpar < 3) - return; - if (insub[0][getVectorIndex(3, 0)] != 0 && cmDenSub[0][3] != 0) { - cmValSub[0].push_back(1 / cmDenSub[0][3] * (insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] - 3 * insub[0][getVectorIndex(2, 2)] * insub[0][getVectorIndex(1, 1)] + 2 * insub[0][getVectorIndex(3, 3)])); - dynamic_cast(fSubCMList->At(3))->FillProfile(centmult, cmValSub[0][4], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[0][3], rn); - cmValSub[0].push_back(1 / cmDenSub[0][3] * (insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 0)] - 2 * insub[0][getVectorIndex(2, 1)] * insub[0][getVectorIndex(1, 1)] + 2 * insub[0][getVectorIndex(3, 2)] - insub[0][getVectorIndex(2, 2)] * insub[0][getVectorIndex(1, 0)])); - dynamic_cast(fSubCMList->At(4))->FillProfile(centmult, cmValSub[0][5], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[0][3], rn); - cmValSub[0].push_back(1 / cmDenSub[0][3] * (insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] - 2 * insub[0][getVectorIndex(2, 1)] * insub[0][getVectorIndex(1, 0)] + 2 * insub[0][getVectorIndex(3, 1)] - insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(2, 0)])); - dynamic_cast(fSubCMList->At(5))->FillProfile(centmult, cmValSub[0][6], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[0][3], rn); - } - if (insub[nSubevents - 1][getVectorIndex(3, 0)] != 0 && cmDenSub[nSubevents - 1][3] != 0) { - cmValSub[nSubevents - 1].push_back(1 / cmDenSub[nSubevents - 1][3] * (insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] - 3 * insub[nSubevents - 1][getVectorIndex(2, 2)] * insub[nSubevents - 1][getVectorIndex(1, 1)] + 2 * insub[nSubevents - 1][getVectorIndex(3, 3)])); - dynamic_cast(fSubCMList->At(indOffset + 3))->FillProfile(centmult, cmValSub[nSubevents - 1][4], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[nSubevents - 1][3], rn); - cmValSub[nSubevents - 1].push_back(1 / cmDenSub[nSubevents - 1][3] * (insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 0)] - 2 * insub[nSubevents - 1][getVectorIndex(2, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] + 2 * insub[nSubevents - 1][getVectorIndex(3, 2)] - insub[nSubevents - 1][getVectorIndex(2, 2)] * insub[nSubevents - 1][getVectorIndex(1, 0)])); - dynamic_cast(fSubCMList->At(indOffset + 4))->FillProfile(centmult, cmValSub[nSubevents - 1][5], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[nSubevents - 1][3], rn); - cmValSub[nSubevents - 1].push_back(1 / cmDenSub[nSubevents - 1][3] * (insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 0)] * insub[nSubevents - 1][getVectorIndex(1, 0)] - 2 * insub[nSubevents - 1][getVectorIndex(2, 1)] * insub[nSubevents - 1][getVectorIndex(1, 0)] + 2 * insub[nSubevents - 1][getVectorIndex(3, 1)] - insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(2, 0)])); - dynamic_cast(fSubCMList->At(indOffset + 5))->FillProfile(centmult, cmValSub[nSubevents - 1][6], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[nSubevents - 1][3], rn); + if (mpar >= 2) { + if (insub[0][getVectorIndex(2, 0)] != 0 && cmDenSub[0][2] != 0) { + cmValSub[0].push_back(1 / cmDenSub[0][2] * (insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] - insub[0][getVectorIndex(2, 2)])); + dynamic_cast(fSubCMList->At(1))->FillProfile(centmult, cmValSub[0][2], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[0][2], rn); + cmValSub[0].push_back(1 / cmDenSub[0][2] * (insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 1)] - insub[0][getVectorIndex(2, 1)])); + dynamic_cast(fSubCMList->At(2))->FillProfile(centmult, cmValSub[0][3], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[0][2], rn); + } + if (insub[nSubevents - 1][getVectorIndex(2, 0)] != 0 && cmDenSub[nSubevents - 1][2] != 0) { + cmValSub[nSubevents - 1].push_back(1 / cmDenSub[nSubevents - 1][2] * (insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] - insub[nSubevents - 1][getVectorIndex(2, 2)])); + dynamic_cast(fSubCMList->At(indOffset + 1))->FillProfile(centmult, cmValSub[nSubevents - 1][2], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[nSubevents - 1][2], rn); + cmValSub[nSubevents - 1].push_back(1 / cmDenSub[nSubevents - 1][2] * (insub[nSubevents - 1][getVectorIndex(1, 0)] * insub[nSubevents - 1][getVectorIndex(1, 1)] - insub[nSubevents - 1][getVectorIndex(2, 1)])); + dynamic_cast(fSubCMList->At(indOffset + 2))->FillProfile(centmult, cmValSub[nSubevents - 1][3], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[nSubevents - 1][2], rn); + } + validMpar[0] = true; } - if (mpar < 4) - return; - if (insub[0][getVectorIndex(4, 0)] != 0 && cmDenSub[0][4] != 0) { - cmValSub[0].push_back(1 / cmDenSub[0][4] * (insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] - 6 * insub[0][getVectorIndex(2, 2)] * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] + 3 * insub[0][getVectorIndex(2, 2)] * insub[0][getVectorIndex(2, 2)] + 8 * insub[0][getVectorIndex(3, 3)] * insub[0][getVectorIndex(1, 1)] - 6 * insub[0][getVectorIndex(4, 4)])); - dynamic_cast(fSubCMList->At(6))->FillProfile(centmult, cmValSub[0][7], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[0][4], rn); - cmValSub[0].push_back(1 / cmDenSub[0][4] * (insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 0)] - 3 * insub[0][getVectorIndex(2, 2)] * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 0)] - 3 * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(2, 1)] + 3 * insub[0][getVectorIndex(2, 2)] * insub[0][getVectorIndex(2, 1)] + 6 * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(3, 2)] - 6 * insub[0][getVectorIndex(4, 3)])); - dynamic_cast(fSubCMList->At(7))->FillProfile(centmult, cmValSub[0][8], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[0][4], rn); - cmValSub[0].push_back(1 / cmDenSub[0][4] * (insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] - insub[0][getVectorIndex(2, 2)] * insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] - insub[0][getVectorIndex(2, 0)] * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] + insub[0][getVectorIndex(2, 0)] * insub[0][getVectorIndex(2, 2)] - 4 * insub[0][getVectorIndex(2, 1)] * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 0)] + 4 * insub[0][getVectorIndex(3, 2)] * insub[0][getVectorIndex(1, 0)] + 4 * insub[0][getVectorIndex(3, 1)] * insub[0][getVectorIndex(1, 1)] + 2 * insub[0][getVectorIndex(2, 1)] * insub[0][getVectorIndex(2, 1)] - 6 * insub[0][getVectorIndex(4, 2)])); - dynamic_cast(fSubCMList->At(8))->FillProfile(centmult, cmValSub[0][9], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[0][4], rn); - cmValSub[0].push_back(1 / cmDenSub[0][4] * (insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] - 3 * insub[0][getVectorIndex(2, 1)] * insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] - 3 * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(2, 0)] * insub[0][getVectorIndex(1, 0)] + 3 * insub[0][getVectorIndex(2, 1)] * insub[0][getVectorIndex(2, 0)] + 2 * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(3, 0)] + 6 * insub[0][getVectorIndex(3, 1)] * insub[0][getVectorIndex(1, 0)] - 6 * insub[0][getVectorIndex(4, 1)])); - dynamic_cast(fSubCMList->At(9))->FillProfile(centmult, cmValSub[0][10], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[0][4], rn); - } - if (insub[nSubevents - 1][getVectorIndex(4, 0)] != 0 && cmDenSub[nSubevents - 1][4] != 0) { - cmValSub[nSubevents - 1].push_back(1 / cmDenSub[nSubevents - 1][4] * (insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] - 6 * insub[nSubevents - 1][getVectorIndex(2, 2)] * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] + 3 * insub[nSubevents - 1][getVectorIndex(2, 2)] * insub[nSubevents - 1][getVectorIndex(2, 2)] + 8 * insub[nSubevents - 1][getVectorIndex(3, 3)] * insub[nSubevents - 1][getVectorIndex(1, 1)] - 6 * insub[nSubevents - 1][getVectorIndex(4, 4)])); - dynamic_cast(fSubCMList->At(indOffset + 6))->FillProfile(centmult, cmValSub[nSubevents - 1][7], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[nSubevents - 1][4], rn); - cmValSub[nSubevents - 1].push_back(1 / cmDenSub[nSubevents - 1][4] * (insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 0)] - 3 * insub[nSubevents - 1][getVectorIndex(2, 2)] * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 0)] - 3 * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(2, 1)] + 3 * insub[nSubevents - 1][getVectorIndex(2, 2)] * insub[nSubevents - 1][getVectorIndex(2, 1)] + 6 * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(3, 2)] - 6 * insub[nSubevents - 1][getVectorIndex(4, 3)])); - dynamic_cast(fSubCMList->At(indOffset + 7))->FillProfile(centmult, cmValSub[nSubevents - 1][8], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[nSubevents - 1][4], rn); - cmValSub[nSubevents - 1].push_back(1 / cmDenSub[nSubevents - 1][4] * (insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 0)] * insub[nSubevents - 1][getVectorIndex(1, 0)] - insub[nSubevents - 1][getVectorIndex(2, 2)] * insub[nSubevents - 1][getVectorIndex(1, 0)] * insub[nSubevents - 1][getVectorIndex(1, 0)] - insub[nSubevents - 1][getVectorIndex(2, 0)] * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] + insub[nSubevents - 1][getVectorIndex(2, 0)] * insub[nSubevents - 1][getVectorIndex(2, 2)] - 4 * insub[nSubevents - 1][getVectorIndex(2, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 0)] + 4 * insub[nSubevents - 1][getVectorIndex(3, 2)] * insub[nSubevents - 1][getVectorIndex(1, 0)] + 4 * insub[nSubevents - 1][getVectorIndex(3, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] + 2 * insub[nSubevents - 1][getVectorIndex(2, 1)] * insub[nSubevents - 1][getVectorIndex(2, 1)] - 6 * insub[nSubevents - 1][getVectorIndex(4, 2)])); - dynamic_cast(fSubCMList->At(indOffset + 8))->FillProfile(centmult, cmValSub[nSubevents - 1][9], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[nSubevents - 1][4], rn); - cmValSub[nSubevents - 1].push_back(1 / cmDenSub[nSubevents - 1][4] * (insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 0)] * insub[nSubevents - 1][getVectorIndex(1, 0)] * insub[nSubevents - 1][getVectorIndex(1, 0)] - 3 * insub[nSubevents - 1][getVectorIndex(2, 1)] * insub[nSubevents - 1][getVectorIndex(1, 0)] * insub[nSubevents - 1][getVectorIndex(1, 0)] - 3 * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(2, 0)] * insub[nSubevents - 1][getVectorIndex(1, 0)] + 3 * insub[nSubevents - 1][getVectorIndex(2, 1)] * insub[nSubevents - 1][getVectorIndex(2, 0)] + 2 * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(3, 0)] + 6 * insub[nSubevents - 1][getVectorIndex(3, 1)] * insub[nSubevents - 1][getVectorIndex(1, 0)] - 6 * insub[nSubevents - 1][getVectorIndex(4, 1)])); - dynamic_cast(fSubCMList->At(indOffset + 9))->FillProfile(centmult, cmValSub[nSubevents - 1][10], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[nSubevents - 1][4], rn); + if (mpar >= 3) { + if (insub[0][getVectorIndex(3, 0)] != 0 && cmDenSub[0][3] != 0) { + cmValSub[0].push_back(1 / cmDenSub[0][3] * (insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] - 3 * insub[0][getVectorIndex(2, 2)] * insub[0][getVectorIndex(1, 1)] + 2 * insub[0][getVectorIndex(3, 3)])); + dynamic_cast(fSubCMList->At(3))->FillProfile(centmult, cmValSub[0][4], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[0][3], rn); + cmValSub[0].push_back(1 / cmDenSub[0][3] * (insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 0)] - 2 * insub[0][getVectorIndex(2, 1)] * insub[0][getVectorIndex(1, 1)] + 2 * insub[0][getVectorIndex(3, 2)] - insub[0][getVectorIndex(2, 2)] * insub[0][getVectorIndex(1, 0)])); + dynamic_cast(fSubCMList->At(4))->FillProfile(centmult, cmValSub[0][5], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[0][3], rn); + cmValSub[0].push_back(1 / cmDenSub[0][3] * (insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] - 2 * insub[0][getVectorIndex(2, 1)] * insub[0][getVectorIndex(1, 0)] + 2 * insub[0][getVectorIndex(3, 1)] - insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(2, 0)])); + dynamic_cast(fSubCMList->At(5))->FillProfile(centmult, cmValSub[0][6], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[0][3], rn); + } + if (insub[nSubevents - 1][getVectorIndex(3, 0)] != 0 && cmDenSub[nSubevents - 1][3] != 0) { + cmValSub[nSubevents - 1].push_back(1 / cmDenSub[nSubevents - 1][3] * (insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] - 3 * insub[nSubevents - 1][getVectorIndex(2, 2)] * insub[nSubevents - 1][getVectorIndex(1, 1)] + 2 * insub[nSubevents - 1][getVectorIndex(3, 3)])); + dynamic_cast(fSubCMList->At(indOffset + 3))->FillProfile(centmult, cmValSub[nSubevents - 1][4], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[nSubevents - 1][3], rn); + cmValSub[nSubevents - 1].push_back(1 / cmDenSub[nSubevents - 1][3] * (insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 0)] - 2 * insub[nSubevents - 1][getVectorIndex(2, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] + 2 * insub[nSubevents - 1][getVectorIndex(3, 2)] - insub[nSubevents - 1][getVectorIndex(2, 2)] * insub[nSubevents - 1][getVectorIndex(1, 0)])); + dynamic_cast(fSubCMList->At(indOffset + 4))->FillProfile(centmult, cmValSub[nSubevents - 1][5], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[nSubevents - 1][3], rn); + cmValSub[nSubevents - 1].push_back(1 / cmDenSub[nSubevents - 1][3] * (insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 0)] * insub[nSubevents - 1][getVectorIndex(1, 0)] - 2 * insub[nSubevents - 1][getVectorIndex(2, 1)] * insub[nSubevents - 1][getVectorIndex(1, 0)] + 2 * insub[nSubevents - 1][getVectorIndex(3, 1)] - insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(2, 0)])); + dynamic_cast(fSubCMList->At(indOffset + 5))->FillProfile(centmult, cmValSub[nSubevents - 1][6], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[nSubevents - 1][3], rn); + } + validMpar[1] = true; + } + if (mpar >= 4) { + if (insub[0][getVectorIndex(4, 0)] != 0 && cmDenSub[0][4] != 0) { + cmValSub[0].push_back(1 / cmDenSub[0][4] * (insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] - 6 * insub[0][getVectorIndex(2, 2)] * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] + 3 * insub[0][getVectorIndex(2, 2)] * insub[0][getVectorIndex(2, 2)] + 8 * insub[0][getVectorIndex(3, 3)] * insub[0][getVectorIndex(1, 1)] - 6 * insub[0][getVectorIndex(4, 4)])); + dynamic_cast(fSubCMList->At(6))->FillProfile(centmult, cmValSub[0][7], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[0][4], rn); + cmValSub[0].push_back(1 / cmDenSub[0][4] * (insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 0)] - 3 * insub[0][getVectorIndex(2, 2)] * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 0)] - 3 * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(2, 1)] + 3 * insub[0][getVectorIndex(2, 2)] * insub[0][getVectorIndex(2, 1)] + 6 * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(3, 2)] - 6 * insub[0][getVectorIndex(4, 3)])); + dynamic_cast(fSubCMList->At(7))->FillProfile(centmult, cmValSub[0][8], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[0][4], rn); + cmValSub[0].push_back(1 / cmDenSub[0][4] * (insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] - insub[0][getVectorIndex(2, 2)] * insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] - insub[0][getVectorIndex(2, 0)] * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] + insub[0][getVectorIndex(2, 0)] * insub[0][getVectorIndex(2, 2)] - 4 * insub[0][getVectorIndex(2, 1)] * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 0)] + 4 * insub[0][getVectorIndex(3, 2)] * insub[0][getVectorIndex(1, 0)] + 4 * insub[0][getVectorIndex(3, 1)] * insub[0][getVectorIndex(1, 1)] + 2 * insub[0][getVectorIndex(2, 1)] * insub[0][getVectorIndex(2, 1)] - 6 * insub[0][getVectorIndex(4, 2)])); + dynamic_cast(fSubCMList->At(8))->FillProfile(centmult, cmValSub[0][9], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[0][4], rn); + cmValSub[0].push_back(1 / cmDenSub[0][4] * (insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] - 3 * insub[0][getVectorIndex(2, 1)] * insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] - 3 * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(2, 0)] * insub[0][getVectorIndex(1, 0)] + 3 * insub[0][getVectorIndex(2, 1)] * insub[0][getVectorIndex(2, 0)] + 2 * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(3, 0)] + 6 * insub[0][getVectorIndex(3, 1)] * insub[0][getVectorIndex(1, 0)] - 6 * insub[0][getVectorIndex(4, 1)])); + dynamic_cast(fSubCMList->At(9))->FillProfile(centmult, cmValSub[0][10], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[0][4], rn); + } + if (insub[nSubevents - 1][getVectorIndex(4, 0)] != 0 && cmDenSub[nSubevents - 1][4] != 0) { + cmValSub[nSubevents - 1].push_back(1 / cmDenSub[nSubevents - 1][4] * (insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] - 6 * insub[nSubevents - 1][getVectorIndex(2, 2)] * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] + 3 * insub[nSubevents - 1][getVectorIndex(2, 2)] * insub[nSubevents - 1][getVectorIndex(2, 2)] + 8 * insub[nSubevents - 1][getVectorIndex(3, 3)] * insub[nSubevents - 1][getVectorIndex(1, 1)] - 6 * insub[nSubevents - 1][getVectorIndex(4, 4)])); + dynamic_cast(fSubCMList->At(indOffset + 6))->FillProfile(centmult, cmValSub[nSubevents - 1][7], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[nSubevents - 1][4], rn); + cmValSub[nSubevents - 1].push_back(1 / cmDenSub[nSubevents - 1][4] * (insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 0)] - 3 * insub[nSubevents - 1][getVectorIndex(2, 2)] * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 0)] - 3 * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(2, 1)] + 3 * insub[nSubevents - 1][getVectorIndex(2, 2)] * insub[nSubevents - 1][getVectorIndex(2, 1)] + 6 * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(3, 2)] - 6 * insub[nSubevents - 1][getVectorIndex(4, 3)])); + dynamic_cast(fSubCMList->At(indOffset + 7))->FillProfile(centmult, cmValSub[nSubevents - 1][8], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[nSubevents - 1][4], rn); + cmValSub[nSubevents - 1].push_back(1 / cmDenSub[nSubevents - 1][4] * (insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 0)] * insub[nSubevents - 1][getVectorIndex(1, 0)] - insub[nSubevents - 1][getVectorIndex(2, 2)] * insub[nSubevents - 1][getVectorIndex(1, 0)] * insub[nSubevents - 1][getVectorIndex(1, 0)] - insub[nSubevents - 1][getVectorIndex(2, 0)] * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] + insub[nSubevents - 1][getVectorIndex(2, 0)] * insub[nSubevents - 1][getVectorIndex(2, 2)] - 4 * insub[nSubevents - 1][getVectorIndex(2, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 0)] + 4 * insub[nSubevents - 1][getVectorIndex(3, 2)] * insub[nSubevents - 1][getVectorIndex(1, 0)] + 4 * insub[nSubevents - 1][getVectorIndex(3, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] + 2 * insub[nSubevents - 1][getVectorIndex(2, 1)] * insub[nSubevents - 1][getVectorIndex(2, 1)] - 6 * insub[nSubevents - 1][getVectorIndex(4, 2)])); + dynamic_cast(fSubCMList->At(indOffset + 8))->FillProfile(centmult, cmValSub[nSubevents - 1][9], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[nSubevents - 1][4], rn); + cmValSub[nSubevents - 1].push_back(1 / cmDenSub[nSubevents - 1][4] * (insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 0)] * insub[nSubevents - 1][getVectorIndex(1, 0)] * insub[nSubevents - 1][getVectorIndex(1, 0)] - 3 * insub[nSubevents - 1][getVectorIndex(2, 1)] * insub[nSubevents - 1][getVectorIndex(1, 0)] * insub[nSubevents - 1][getVectorIndex(1, 0)] - 3 * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(2, 0)] * insub[nSubevents - 1][getVectorIndex(1, 0)] + 3 * insub[nSubevents - 1][getVectorIndex(2, 1)] * insub[nSubevents - 1][getVectorIndex(2, 0)] + 2 * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(3, 0)] + 6 * insub[nSubevents - 1][getVectorIndex(3, 1)] * insub[nSubevents - 1][getVectorIndex(1, 0)] - 6 * insub[nSubevents - 1][getVectorIndex(4, 1)])); + dynamic_cast(fSubCMList->At(indOffset + 9))->FillProfile(centmult, cmValSub[nSubevents - 1][10], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[nSubevents - 1][4], rn); + } + validMpar[2] = true; } - // Fill cross terms for (int m = 2; m <= 4; ++m) { + if (!validMpar[m - 2]) + continue; for (int first = 1; first < m; ++first) { for (int second = first; second < m; ++second) { if (first > second) @@ -999,8 +1005,9 @@ void FlowPtContainer::fillCMSubeventProfiles(const double& centmult, const doubl for (int third = 1; third < m; ++third) { if (third > fourth) continue; - if (insub[0][getVectorIndex(m, 0)] != 0 && insub[nSubevents - 1][getVectorIndex(m, 0)] != 0 && cmDenSub[0][m] * cmDenSub[nSubevents - 1][m] != 0) + if (insub[0][getVectorIndex(m, 0)] != 0 && insub[nSubevents - 1][getVectorIndex(m, 0)] != 0 && cmDenSub[0][m] * cmDenSub[nSubevents - 1][m] != 0) { dynamic_cast(fSubCMList->FindObject(Form("cm%i_%i%isub1_%i%isub2", m, first, second, third, fourth)))->FillProfile(centmult, cmValSub[0][second * (second - 1) / 2 + second - first + 1] * cmValSub[nSubevents - 1][fourth * (fourth - 1) / 2 + fourth - third + 1], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[0][m] * cmDenSub[nSubevents - 1][m], rn); + } } } } From acaa6cc69ea0e8fa9c3542e1d3f82d12cc0c6e68 Mon Sep 17 00:00:00 2001 From: Zhiyong <71517277+Luzhiyongg@users.noreply.github.com> Date: Wed, 25 Feb 2026 20:54:13 +0100 Subject: [PATCH 084/347] [PWGCF] Add 3D histogram for eta, pT, and Centrality (#15166) --- PWGCF/Flow/Tasks/flowTask.cxx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/PWGCF/Flow/Tasks/flowTask.cxx b/PWGCF/Flow/Tasks/flowTask.cxx index 3e3fbb181dc..5403fb99ad4 100644 --- a/PWGCF/Flow/Tasks/flowTask.cxx +++ b/PWGCF/Flow/Tasks/flowTask.cxx @@ -361,6 +361,7 @@ struct FlowTask { registry.add("centFT0CVar_centFT0C", "after cut;Centrality T0C;Centrality T0C Var", {HistType::kTH2D, {axisCentForQA, axisCentForQA}}); registry.add("centFT0M_centFT0C", "after cut;Centrality T0C;Centrality T0M", {HistType::kTH2D, {axisCentForQA, axisCentForQA}}); registry.add("centFV0A_centFT0C", "after cut;Centrality T0C;Centrality V0A", {HistType::kTH2D, {axisCentForQA, axisCentForQA}}); + registry.add("hEtaPtCent", "after cut;#eta;p_{T};Centrality;", {HistType::kTH3D, {{16, -0.8, 0.8}, axisPt, {10, 0, 100}}}); } // Track QA registry.add("hPhi", "#phi distribution", {HistType::kTH1D, {axisPhi}}); @@ -1295,6 +1296,9 @@ struct FlowTask { registry.fill(HIST("hPt"), track.pt()); if (cfgAdditionObs.cfgDptDisEnable) ptVec.push_back(track.pt()); + if (!cfgUserIO.cfgUseSmallMemory) { + registry.fill(HIST("hEtaPtCent"), track.eta(), track.pt(), cent); + } if (cfgAdditionObs.cfgV02Enabled && track.eta() >= cfgAdditionObs.cfgV02FracEtaMin && track.eta() <= cfgAdditionObs.cfgV02FracEtaMax) { cfgAdditionObs.listPtX[0]->Fill(independent, track.pt(), weff); cfgAdditionObs.listPtX[sampleIndex + 1]->Fill(independent, track.pt(), weff); From 944d59713f9738ca0e89ff631ede1f7c6e0b71d6 Mon Sep 17 00:00:00 2001 From: abilandz Date: Wed, 25 Feb 2026 21:48:59 +0100 Subject: [PATCH 085/347] [PWGCF] further clean up and additions for w. (#15161) --- .../Core/MuPa-Configurables.h | 8 +- .../Core/MuPa-DataMembers.h | 2 +- .../Core/MuPa-Enums.h | 4 +- .../Core/MuPa-MemberFunctions.h | 453 ++++++++++++------ 4 files changed, 321 insertions(+), 146 deletions(-) diff --git a/PWGCF/MultiparticleCorrelations/Core/MuPa-Configurables.h b/PWGCF/MultiparticleCorrelations/Core/MuPa-Configurables.h index 4b5cf165b44..1e5839de465 100644 --- a/PWGCF/MultiparticleCorrelations/Core/MuPa-Configurables.h +++ b/PWGCF/MultiparticleCorrelations/Core/MuPa-Configurables.h @@ -143,7 +143,7 @@ struct : ConfigurableGroup { Configurable> cfBookParticleHistograms{"cfBookParticleHistograms", {"1-Phi", "1-Pt", "1-Eta", "1-Charge", "1-tpcNClsFindable", "1-tpcNClsShared", "1-itsChi2NCl", "1-tpcNClsFound", "1-tpcNClsCrossedRows", "1-itsNCls", "1-itsNClsInnerBarrel", "1-tpcCrossedRowsOverFindableCls", "1-tpcFoundOverFindableCls", "1-tpcFractionSharedCls", "1-tpcChi2NCl", "1-dcaXY", "1-dcaZ", "0-PDG"}, "Book (1) or do not book (0) particle histogram"}; Configurable cfFillParticleHistograms2D{"cfFillParticleHistograms2D", false, "if false, all 2D particle histograms are not filled. if kTRUE, the ones for which fBookParticleHistograms2D[...] is kTRUE, are filled"}; Configurable> cfBookParticleHistograms2D{"cfBookParticleHistograms2D", {"1-Phi_vs_Pt", "1-Phi_vs_Eta"}, "Book (1) or do not book (0) 2D particle histograms"}; - Configurable cfRebinSparse{"cfRebinSparse", 1, "used only for all fixed-length bins which are implemented directly for sparse histograms (i.e. not inherited from results histograms)"}; + Configurable> cfRebinSparse{"cfRebinSparse", {1., 1., 1., 1., 1., 1.}, "Ordering is the same as in eDiffPhiWeights. To make bins factor 2 finer use 0.5, to make bins factor 5 coarser use 5."}; Configurable> cfBookParticleSparseHistograms{"cfBookParticleSparseHistograms", {"0-DWPhi", "0-DWPt", "0-DWEta"}, "Book (1) or do not book (0) particular category of sparse histograms"}; Configurable cfFillParticleSparseHistogramsBeforeCuts{"cfFillParticleSparseHistogramsBeforeCuts", false, "I need sparse histograms before cuts only when testing pt and eta weights, in internal validation"}; // TBI 20250223 add eventually configurable for FillParticleSparseHistogramsDimension @@ -157,7 +157,7 @@ struct : ConfigurableGroup { Configurable> cfPhi{"cfPhi", {0.0, o2::constants::math::TwoPI}, "phi range: {min, max}[rad], with convention: min <= phi < max"}; Configurable> cfPt{"cfPt", {0.2, 5.0}, "pt range: {min, max}[GeV], with convention: min <= pt < max"}; Configurable> cfEta{"cfEta", {-0.8, 0.8}, "eta range: {min, max}, with convention: min <= eta < max"}; - Configurable> cfCharge{"cfCharge", {-1.5, 1.5}, "particle charge. {-1.5,0} = only negative, {0,1.5} = only positive"}; + Configurable> cfCharge{"cfCharge", {-2.0, 2.0}, "particle charge. {-2.0,0} = only negative, {0,2.0} = only positive (keep in sync with res.fResultsProBinEdges[AFO_CHARGE])"}; Configurable> cftpcNClsFindable{"cftpcNClsFindable", {-1000., 1000.}, "tpcNClsFindable range: {min, max}, with convention: min <= cftpcNClsFindable < max"}; Configurable> cftpcNClsShared{"cftpcNClsShared", {-1000., 1000.}, "tpcNClsShared range: {min, max}, with convention: min <= cftpcNClsShared < max"}; Configurable> cfitsChi2NCl{"cfitsChi2NCl", {-1000., 36.}, "itsChi2NCl range: {min, max}, with convention: min <= cfitsChi2NCl < max"}; @@ -231,8 +231,8 @@ struct : ConfigurableGroup { Configurable cfUseDiffPhiPtWeights{"cfUseDiffPhiPtWeights", false, "use or not differential phi(pt) weights"}; Configurable cfUseDiffPhiEtaWeights{"cfUseDiffPhiEtaWeights", false, "use or not differential phi(eta) weights"}; Configurable> cfWhichDiffPhiWeights{"cfWhichDiffPhiWeights", {"1-wPhi", "1-wPt", "1-wEta", "1-wCharge", "1-wCentrality", "1-wVertexZ"}, "use (1) or do not use (0) differential phi weight for particular dimension. If only phi is set to 1, integrated phi weights are used. If phi is set to 0, ALL dimensions are switched off (yes!)"}; - Configurable> cfWhichDiffPtWeights{"cfWhichDiffPtWeights", {"0-wPt", "0-wCharge", "0-wCentrality"}, "use (1) or do not use (0) differential pt weight for particular dimension. If only pt is set to 1, integrated pt weights are used. If pt is set to 0, ALL dimensions are switched off (yes!)"}; - Configurable> cfWhichDiffEtaWeights{"cfWhichDiffEtaWeights", {"0-wEta", "0-wCharge", "0-wCentrality"}, "use (1) or do not use (0) differential eta weight for particular dimension. If only eta is set to 1, integrated eta weights are used. If eta is set to 0, ALL dimensions are switched off (yes!)"}; + Configurable> cfWhichDiffPtWeights{"cfWhichDiffPtWeights", {"0-wPt", "0-wEta", "0-wCharge", "0-wCentrality"}, "use (1) or do not use (0) differential pt weight for particular dimension. If only pt is set to 1, integrated pt weights are used. If pt is set to 0, ALL dimensions are switched off (yes!)"}; + Configurable> cfWhichDiffEtaWeights{"cfWhichDiffEtaWeights", {"0-wEta", "0-wPt", "0-wCharge", "0-wCentrality"}, "use (1) or do not use (0) differential eta weight for particular dimension. If only eta is set to 1, integrated eta weights are used. If eta is set to 0, ALL dimensions are switched off (yes!)"}; Configurable cfFileWithWeights{"cfFileWithWeights", "/home/abilandz/DatasetsO2/weights.root", "path to external ROOT file which holds all particle weights in O2 format"}; // for AliEn file prepend "/alice/cern.ch/", for CCDB prepend "/alice-ccdb.cern.ch" } cf_pw; diff --git a/PWGCF/MultiparticleCorrelations/Core/MuPa-DataMembers.h b/PWGCF/MultiparticleCorrelations/Core/MuPa-DataMembers.h index 79a383076a7..45efee2c74b 100644 --- a/PWGCF/MultiparticleCorrelations/Core/MuPa-DataMembers.h +++ b/PWGCF/MultiparticleCorrelations/Core/MuPa-DataMembers.h @@ -262,7 +262,7 @@ struct ParticleHistograms { int fParticleSparseHistogramsNBins[eDiffWeightCategory_N][gMaxNumberSparseDimensions] = {{0}}; // number of bins. I do not have min and max, because for sparse I use BinEdges, see below TArrayD* fParticleSparseHistogramsBinEdges[eDiffWeightCategory_N][gMaxNumberSparseDimensions] = {{NULL}}; // arrays holding bin edges, see the usage of SetBinEdges for sparse histograms TString fParticleSparseHistogramsAxisTitle[eDiffWeightCategory_N][gMaxNumberSparseDimensions] = {{""}}; // axis title - int fRebinSparse = 1; // used only for all fixed-length bins which are implemented directly for sparse histograms (i.e. not inherited from results histograms) + float fRebinSparse[eDiffWeightCategory_N][gMaxNumberSparseDimensions] = {{1.}}; // used only for all fixed-length bins which are implemented directly for sparse histograms (i.e. not inherited from results histograms) } ph; // "ph" labels an instance of group of histograms "ParticleHistograms" // *) Particle cuts: diff --git a/PWGCF/MultiparticleCorrelations/Core/MuPa-Enums.h b/PWGCF/MultiparticleCorrelations/Core/MuPa-Enums.h index fd2bc36920f..a4becda5ffe 100644 --- a/PWGCF/MultiparticleCorrelations/Core/MuPa-Enums.h +++ b/PWGCF/MultiparticleCorrelations/Core/MuPa-Enums.h @@ -121,8 +121,9 @@ enum eDiffPhiWeights { eDiffPhiWeights_N }; -enum eDiffPtWeights { +enum eDiffPtWeights { // if i add new entry here, or in eDiffPhiWeights and eDiffEtaWeights, I need to update also GetParticleWeights() wPtPtAxis = 0, + wPtEtaAxis, wPtChargeAxis, wPtCentralityAxis, eDiffPtWeights_N @@ -130,6 +131,7 @@ enum eDiffPtWeights { enum eDiffEtaWeights { wEtaEtaAxis = 0, + wEtaPtAxis, wEtaChargeAxis, wEtaCentralityAxis, eDiffEtaWeights_N diff --git a/PWGCF/MultiparticleCorrelations/Core/MuPa-MemberFunctions.h b/PWGCF/MultiparticleCorrelations/Core/MuPa-MemberFunctions.h index 4635f8f9c7d..6b169302955 100644 --- a/PWGCF/MultiparticleCorrelations/Core/MuPa-MemberFunctions.h +++ b/PWGCF/MultiparticleCorrelations/Core/MuPa-MemberFunctions.h @@ -667,6 +667,8 @@ void defaultConfiguration() for (int dpw = 0; dpw < eDiffPtWeights_N; dpw++) { // "differential pt weight" if (TString(lWhichDiffPtWeights[dpw]).Contains("wPt")) { pw.fUseDiffPtWeights[wPtPtAxis] = Alright(lWhichDiffPtWeights[dpw]); // if I pass "1-Pt" => true, "0-Pt" => false + } else if (TString(lWhichDiffPtWeights[dpw]).Contains("wEta")) { + pw.fUseDiffPtWeights[wPtEtaAxis] = Alright(lWhichDiffPtWeights[dpw]) && pw.fUseDiffPtWeights[wPtPtAxis]; } else if (TString(lWhichDiffPtWeights[dpw]).Contains("wCharge")) { pw.fUseDiffPtWeights[wPtChargeAxis] = Alright(lWhichDiffPtWeights[dpw]) && pw.fUseDiffPtWeights[wPtPtAxis]; } else if (TString(lWhichDiffPtWeights[dpw]).Contains("wCentrality")) { @@ -686,6 +688,8 @@ void defaultConfiguration() for (int dpw = 0; dpw < eDiffEtaWeights_N; dpw++) { // "differential eta weight" if (TString(lWhichDiffEtaWeights[dpw]).Contains("wEta")) { pw.fUseDiffEtaWeights[wEtaEtaAxis] = Alright(lWhichDiffEtaWeights[dpw]); // if I pass "1-Eta" => true, "0-Eta" => false + } else if (TString(lWhichDiffEtaWeights[dpw]).Contains("wPt")) { + pw.fUseDiffEtaWeights[wEtaPtAxis] = Alright(lWhichDiffEtaWeights[dpw]) && pw.fUseDiffEtaWeights[wEtaEtaAxis]; } else if (TString(lWhichDiffEtaWeights[dpw]).Contains("wCharge")) { pw.fUseDiffEtaWeights[wEtaChargeAxis] = Alright(lWhichDiffEtaWeights[dpw]) && pw.fUseDiffEtaWeights[wEtaEtaAxis]; } else if (TString(lWhichDiffEtaWeights[dpw]).Contains("wCentrality")) { @@ -1310,7 +1314,27 @@ void defaultBooking() ph.fBookParticleHistograms2D[ePhiEta] = Alright(lBookParticleHistograms2D[ePhiEta]) && ph.fFillParticleHistograms2D; // e) Particle sparse histograms: - ph.fRebinSparse = cf_ph.cfRebinSparse; + auto lRebinSparse = (std::vector)cf_ph.cfRebinSparse; + + ph.fRebinSparse[eDWPhi][wPhiPhiAxis] = lRebinSparse[wPhiPhiAxis]; + ph.fRebinSparse[eDWPhi][wPhiPtAxis] = lRebinSparse[wPhiPtAxis]; + ph.fRebinSparse[eDWPhi][wPhiEtaAxis] = lRebinSparse[wPhiEtaAxis]; + ph.fRebinSparse[eDWPhi][wPhiChargeAxis] = lRebinSparse[wPhiChargeAxis]; + ph.fRebinSparse[eDWPhi][wPhiCentralityAxis] = lRebinSparse[wPhiCentralityAxis]; + ph.fRebinSparse[eDWPhi][wPhiVertexZAxis] = lRebinSparse[wPhiVertexZAxis]; + // ... + + ph.fRebinSparse[eDWPt][wPtPtAxis] = lRebinSparse[wPhiPtAxis]; // yes, wPhiPtAxis is on the RHS, becase I defined ordering of cfRebinSparse by using oredring in eDiffPhiWeights + ph.fRebinSparse[eDWPt][wPtEtaAxis] = lRebinSparse[wPhiEtaAxis]; + ph.fRebinSparse[eDWPt][wPtChargeAxis] = lRebinSparse[wPhiChargeAxis]; + ph.fRebinSparse[eDWPt][wPtCentralityAxis] = lRebinSparse[wPhiCentralityAxis]; + // ... + + ph.fRebinSparse[eDWEta][wEtaEtaAxis] = lRebinSparse[wPhiEtaAxis]; // yes, wPhiEtaAxis is on the RHS, becase I defined ordering of cfRebinSparse by using oredring in eDiffPhiWeights + ph.fRebinSparse[eDWEta][wEtaPtAxis] = lRebinSparse[wPhiPtAxis]; + ph.fRebinSparse[eDWEta][wEtaChargeAxis] = lRebinSparse[wPhiChargeAxis]; + ph.fRebinSparse[eDWEta][wEtaCentralityAxis] = lRebinSparse[wPhiCentralityAxis]; + // ... // *) Categories of sparse histograms: auto lBookParticleSparseHistograms = cf_ph.cfBookParticleSparseHistograms.value; // fill or not particulat category of sparse histograms @@ -1571,8 +1595,11 @@ void defaultBinning() // Default binning for all histograms. // TBI 20240114 If some of these values are going to change frequently, add support for them in MuPa-Configurables.h, - // in the same way I did it for defaultCuts(). - // At the moment, I added to configurables support only for binning of sparse histograms, because there memory managment is critical. + // in the same way I did it for defaultCuts(). + // TBI 20260223 If ever I will add also support for variable-length binning for control histograms, re-think first what I did in the + // booking of sparse histograms, because the code there hinges on the usage of fixed-length binning and the usage of + // configurable cfRebinSparse. But I doubt I will even need here variable-length binning, I have always rebin in such a way + // all control histograms in offline postprocessing. // a) Default binning for event histograms; // b) Default binning for particle histograms 1D; @@ -1648,11 +1675,11 @@ void defaultBinning() ph.fParticleHistogramsBins[ePt][0] = 2000; ph.fParticleHistogramsBins[ePt][1] = 0.; - ph.fParticleHistogramsBins[ePt][2] = 200.; + ph.fParticleHistogramsBins[ePt][2] = 20.; - ph.fParticleHistogramsBins[eEta][0] = 500; - ph.fParticleHistogramsBins[eEta][1] = -5.; - ph.fParticleHistogramsBins[eEta][2] = 5.; + ph.fParticleHistogramsBins[eEta][0] = 400; + ph.fParticleHistogramsBins[eEta][1] = -2.; + ph.fParticleHistogramsBins[eEta][2] = 2.; ph.fParticleHistogramsBins[eCharge][0] = 7; ph.fParticleHistogramsBins[eCharge][1] = -3.5; // anticipating I might be storing charge of Delta++, etc. @@ -1797,6 +1824,7 @@ void defaultBinning() // *) Binning vs. particle charge => binning is always the same nBins = 2 in (-2.,2), so that the center of bins is at +/- 1: // Therefore, I shall never initialize or set for ill-defined cases the charge to 0., because when filling, that one will go to bin for +1 charge ("lower boundary included"). + // Keep in sync with Configurable> cfCharge{ ... res.fResultsProBinEdges[AFO_CHARGE] = new TArrayD(3); res.fResultsProBinEdges[AFO_CHARGE]->AddAt(-2., 0); res.fResultsProBinEdges[AFO_CHARGE]->AddAt(0., 1); @@ -3243,6 +3271,18 @@ void insanityChecksBeforeBooking() LOGF(fatal, "\033[1;31m%s at line %d : in IV eMultiplicityEstimator cannot be set to \"ReferenceMultiplicity\" (yet) \033[0m", __FUNCTION__, __LINE__); } + if (!tc.fCalculateAsFunctionOf[AFO_PT] && pc.fUseParticleCuts[ePt]) { + LOGF(fatal, "\033[1;31m%s at line %d : in IV you do not calculate vs pt, but the cut on pt is on in IV\033[0m", __FUNCTION__, __LINE__); + } + + if (!tc.fCalculateAsFunctionOf[AFO_ETA] && pc.fUseParticleCuts[eEta]) { + LOGF(fatal, "\033[1;31m%s at line %d : in IV you do not calculate vs eta, but the cut on eta is on in IV\033[0m", __FUNCTION__, __LINE__); + } + + if (!tc.fCalculateAsFunctionOf[AFO_CHARGE] && pc.fUseParticleCuts[eCharge]) { + LOGF(fatal, "\033[1;31m%s at line %d : in IV you do not calculate vs charge, but the cut on charge is on in IV\033[0m", __FUNCTION__, __LINE__); + } + } // if (iv.fUseInternalValidation) { // h) Insanity checks on results histograms: @@ -4998,8 +5038,8 @@ void bookParticleHistograms() // a) Book the profile holding flags; // b) Book specific particle histograms 1D; // c) Book specific particle histograms 2D; - // e) Default binning for particle sparse histograms (yes, here, see comments below); - // d) Book specific particle sparse histograms (n-dimensions). + // d) Default binning for particle sparse histograms (yes, here, see comments below); + // e) Book specific particle sparse histograms (n-dimensions). if (tc.fVerbose) { StartFunction(__FUNCTION__); @@ -5153,28 +5193,31 @@ void bookParticleHistograms() // eParticleHistograms // d) Default binning for particle sparse histograms: - // Remark 0: This requires the special treatment, because I re-use in some cases bins from results histograns. - // Therefore, I can do all this only after bookResultsHistograms() was already called. + // Remark 0: I am using binning from particle or event control histograms, and I can optionally make it coarser or finer via configurable array fRebinSparse. + // It is important to vary fRebinSparse as a part of systematics. Note that I can do additional rebinning offline when making weights, so keep it here + // as fine as possible. // Remark 1: I anticipate I will need them only when I need to calculate differential weights, therefore I couple them intentionally // with enum's for differential weights from very beginning. - // Remark 2: Whenever possible, I re-use binning from results histograms. + // Remark 2: Do NOT re-use binning from results histograms, here the bin widths cannot be varied as a part of systematics (see Remark 0 above); // Remark 3: For variable-length binning, for each dimension of THnSparse, I have to call SetBinEdges (see below). // Therefore, to facilitate the whole procedure, fixed-length bins which I implemented directly (e.g. for phi dimension, which I do not have in results histograms), // I convert also in arrays. For fixed-length bins in results histograms I do NOT have to do that, because for that case I call GetArray() in any case, which is // doing such conversion automatically. + // TBI 20260223 I didn't really check variable-length binning for sparse extensively, use only fixed-length binning for the time being. // Remark 4: If I do not need particular dimension in sparse histogram, e.g. pt, in the config simply set // "cfFixedLengthPtBins": {"values": ["1", "0.2", "5.0"]}, // where lower and upper pt boundary must be the same as in the pt cut, defined via // "cfPt": {"values": ["0.2","5.0"]}, // Keep this convention in sync with what I am doing in the macro MakeWeightsFromSparse(...) + // Remark 5: Do not mix below eh.fEventHistograms and ph.fParticleHistograms // **) eDiffWeightCategory = eDWPhi: TAxis* lAxis = NULL; // local helper TAxis, to convert in one line the booking of fixed-length array into array of corresponding bin edges - // ***) phi-axis for diff phi weights: at the moment I support only fixed-length binning, which optionally can be made finer or coarser with ph.fRebinSparse configurable: - ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiPhiAxis] = static_cast(180. / ph.fRebinSparse); - lAxis = new TAxis(ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiPhiAxis], 0., o2::constants::math::TwoPI); + // ***) phi-axis for diff phi weights - at the moment I support only fixed-length binning from control histograms, which optionally can be made finer or coarser with cfRebinSparse configurable: + ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiPhiAxis] = static_cast(ph.fParticleHistogramsBins[ePhi][0] / ph.fRebinSparse[eDWPhi][wPhiPhiAxis]); + lAxis = new TAxis(ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiPhiAxis], ph.fParticleHistogramsBins[ePhi][1], ph.fParticleHistogramsBins[ePhi][2]); ph.fParticleSparseHistogramsBinEdges[eDWPhi][wPhiPhiAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiPhiAxis]); for (int bin = 1; bin <= lAxis->GetNbins(); bin++) { ph.fParticleSparseHistogramsBinEdges[eDWPhi][wPhiPhiAxis]->AddAt(lAxis->GetBinLowEdge(bin), bin - 1); @@ -5183,166 +5226,155 @@ void bookParticleHistograms() delete lAxis; ph.fParticleSparseHistogramsAxisTitle[eDWPhi][wPhiPhiAxis] = FancyFormatting("Phi"); - // ***) pt-axis for diff phi weights - I re-use binning from results histograms: - if (!res.fResultsPro[AFO_PT]) { - LOGF(fatal, "\033[1;31m%s at line %d : res.fResultsPro[AFO_PT] is NULL \033[0m", __FUNCTION__, __LINE__); - } - ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiPtAxis] = res.fResultsPro[AFO_PT]->GetNbinsX(); // :55 - lAxis = res.fResultsPro[AFO_PT]->GetXaxis(); + // ***) pt-axis for diff phi weights - at the moment I support only fixed-length binning from control histograms, which optionally can be made finer or coarser with cfRebinSparse configurable: + ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiPtAxis] = static_cast(ph.fParticleHistogramsBins[ePt][0] / ph.fRebinSparse[eDWPhi][wPhiPtAxis]); + lAxis = new TAxis(ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiPtAxis], ph.fParticleHistogramsBins[ePt][1], ph.fParticleHistogramsBins[ePt][2]); ph.fParticleSparseHistogramsBinEdges[eDWPhi][wPhiPtAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiPtAxis]); for (int bin = 1; bin <= lAxis->GetNbins(); bin++) { ph.fParticleSparseHistogramsBinEdges[eDWPhi][wPhiPtAxis]->AddAt(lAxis->GetBinLowEdge(bin), bin - 1); } ph.fParticleSparseHistogramsBinEdges[eDWPhi][wPhiPtAxis]->AddAt(lAxis->GetBinLowEdge(1 + lAxis->GetNbins()), lAxis->GetNbins()); // special treatment for last bin - // delete lAxis; // I do not need to delete here, only when new TAxis(...) + delete lAxis; ph.fParticleSparseHistogramsAxisTitle[eDWPhi][wPhiPtAxis] = FancyFormatting("Pt"); - // ***) eta-axis for diff phi weights - I re-use binning from results histograms: - if (!res.fResultsPro[AFO_ETA]) { - LOGF(fatal, "\033[1;31m%s at line %d : res.fResultsPro[AFO_ETA] is NULL \033[0m", __FUNCTION__, __LINE__); - } - ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiEtaAxis] = res.fResultsPro[AFO_ETA]->GetNbinsX(); - lAxis = res.fResultsPro[AFO_ETA]->GetXaxis(); + // ***) eta-axis for diff phi weights - at the moment I support only fixed-length binning from control histograms, which optionally can be made finer or coarser with cfRebinSparse configurable: + ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiEtaAxis] = static_cast(ph.fParticleHistogramsBins[eEta][0] / ph.fRebinSparse[eDWPhi][wPhiEtaAxis]); + lAxis = new TAxis(ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiEtaAxis], ph.fParticleHistogramsBins[eEta][1], ph.fParticleHistogramsBins[eEta][2]); ph.fParticleSparseHistogramsBinEdges[eDWPhi][wPhiEtaAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiEtaAxis]); for (int bin = 1; bin <= lAxis->GetNbins(); bin++) { ph.fParticleSparseHistogramsBinEdges[eDWPhi][wPhiEtaAxis]->AddAt(lAxis->GetBinLowEdge(bin), bin - 1); } ph.fParticleSparseHistogramsBinEdges[eDWPhi][wPhiEtaAxis]->AddAt(lAxis->GetBinLowEdge(1 + lAxis->GetNbins()), lAxis->GetNbins()); // special treatment for last bin - // delete lAxis; // I do not need to delete here, only when new TAxis(...) + delete lAxis; ph.fParticleSparseHistogramsAxisTitle[eDWPhi][wPhiEtaAxis] = FancyFormatting("Eta"); - // ***) charge-axis for diff phi weights - I re-use binning from results histograms: - if (!res.fResultsPro[AFO_CHARGE]) { - LOGF(fatal, "\033[1;31m%s at line %d : res.fResultsPro[AFO_CHARGE] is NULL \033[0m", __FUNCTION__, __LINE__); - } - ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiChargeAxis] = res.fResultsPro[AFO_CHARGE]->GetNbinsX(); - lAxis = res.fResultsPro[AFO_CHARGE]->GetXaxis(); + // ***) charge-axis for diff phi weights - at the moment I support only fixed-length binning from control histograms, which optionally can be made finer or coarser with cfRebinSparse configurable: + ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiChargeAxis] = static_cast(ph.fParticleHistogramsBins[eCharge][0] / ph.fRebinSparse[eDWPhi][wPhiChargeAxis]); + lAxis = new TAxis(ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiChargeAxis], ph.fParticleHistogramsBins[eCharge][1], ph.fParticleHistogramsBins[eCharge][2]); ph.fParticleSparseHistogramsBinEdges[eDWPhi][wPhiChargeAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiChargeAxis]); for (int bin = 1; bin <= lAxis->GetNbins(); bin++) { ph.fParticleSparseHistogramsBinEdges[eDWPhi][wPhiChargeAxis]->AddAt(lAxis->GetBinLowEdge(bin), bin - 1); } ph.fParticleSparseHistogramsBinEdges[eDWPhi][wPhiChargeAxis]->AddAt(lAxis->GetBinLowEdge(1 + lAxis->GetNbins()), lAxis->GetNbins()); // special treatment for last bin - // delete lAxis; // I do not need to delete here, only when new TAxis(...) + delete lAxis; ph.fParticleSparseHistogramsAxisTitle[eDWPhi][wPhiChargeAxis] = FancyFormatting("Charge"); - // ***) centrality-axis for diff phi weights - I re-use binning from results histograms: - if (!res.fResultsPro[AFO_CENTRALITY]) { - LOGF(fatal, "\033[1;31m%s at line %d : res.fResultsPro[AFO_CENTRALITY] is NULL \033[0m", __FUNCTION__, __LINE__); - } - ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiCentralityAxis] = res.fResultsPro[AFO_CENTRALITY]->GetNbinsX(); - lAxis = res.fResultsPro[AFO_CENTRALITY]->GetXaxis(); + // ***) centrality-axis for diff phi weights - at the moment I support only fixed-length binning from control histograms, which optionally can be made finer or coarser with cfRebinSparse configurable: + ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiCentralityAxis] = static_cast(eh.fEventHistogramsBins[eCentrality][0] / ph.fRebinSparse[eDWPhi][wPhiCentralityAxis]); + lAxis = new TAxis(ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiCentralityAxis], eh.fEventHistogramsBins[eCentrality][1], eh.fEventHistogramsBins[eCentrality][2]); ph.fParticleSparseHistogramsBinEdges[eDWPhi][wPhiCentralityAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiCentralityAxis]); for (int bin = 1; bin <= lAxis->GetNbins(); bin++) { ph.fParticleSparseHistogramsBinEdges[eDWPhi][wPhiCentralityAxis]->AddAt(lAxis->GetBinLowEdge(bin), bin - 1); } ph.fParticleSparseHistogramsBinEdges[eDWPhi][wPhiCentralityAxis]->AddAt(lAxis->GetBinLowEdge(1 + lAxis->GetNbins()), lAxis->GetNbins()); // special treatment for last bin - // delete lAxis; // I do not need to delete here, only when new TAxis(...) + delete lAxis; ph.fParticleSparseHistogramsAxisTitle[eDWPhi][wPhiCentralityAxis] = "Centrality"; // TBI 20250222 I cannot call here FancyFormatting for "Centrality", because ec.fsEventCuts[eCentralityEstimator] is still not fetched and set from configurable. Re-think how to proceed for this specific case. - // ***) VertexZ-axis for diff phi weights - I re-use binning from results histograms: - if (!res.fResultsPro[AFO_VZ]) { - LOGF(fatal, "\033[1;31m%s at line %d : res.fResultsPro[AFO_VZ] is NULL \033[0m", __FUNCTION__, __LINE__); - } - ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiVertexZAxis] = res.fResultsPro[AFO_VZ]->GetNbinsX(); - lAxis = res.fResultsPro[AFO_VZ]->GetXaxis(); + // ***) VertexZ-axis for diff phi weights - at the moment I support only fixed-length binning from control histograms, which optionally can be made finer or coarser with cfRebinSparse configurable: + ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiVertexZAxis] = static_cast(eh.fEventHistogramsBins[eVertexZ][0] / ph.fRebinSparse[eDWPhi][wPhiVertexZAxis]); + lAxis = new TAxis(ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiVertexZAxis], eh.fEventHistogramsBins[eVertexZ][1], eh.fEventHistogramsBins[eVertexZ][2]); ph.fParticleSparseHistogramsBinEdges[eDWPhi][wPhiVertexZAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiVertexZAxis]); for (int bin = 1; bin <= lAxis->GetNbins(); bin++) { ph.fParticleSparseHistogramsBinEdges[eDWPhi][wPhiVertexZAxis]->AddAt(lAxis->GetBinLowEdge(bin), bin - 1); } ph.fParticleSparseHistogramsBinEdges[eDWPhi][wPhiVertexZAxis]->AddAt(lAxis->GetBinLowEdge(1 + lAxis->GetNbins()), lAxis->GetNbins()); // special treatment for last bin - // delete lAxis; // I do not need to delete here, only when new TAxis(...) - ph.fParticleSparseHistogramsAxisTitle[eDWPhi][wPhiVertexZAxis] = "VertexZ"; // TBI 20250222 I cannot call here FancyFormatting for "Centrality", because ec.fsEventCuts[eCentralityEstimator] + delete lAxis; + ph.fParticleSparseHistogramsAxisTitle[eDWPhi][wPhiVertexZAxis] = "VertexZ"; // ... // **) eDiffWeightCategory = eDWPt: - // ***) pt-axis for diff pt weights - I re-use binning from results histograms: - if (!res.fResultsPro[AFO_PT]) { - LOGF(fatal, "\033[1;31m%s at line %d : res.fResultsPro[AFO_PT] is NULL \033[0m", __FUNCTION__, __LINE__); - } - ph.fParticleSparseHistogramsNBins[eDWPt][wPtPtAxis] = res.fResultsPro[AFO_PT]->GetNbinsX(); - lAxis = res.fResultsPro[AFO_PT]->GetXaxis(); + // ***) pt-axis for diff pt weights - at the moment I support only fixed-length binning from control histograms, which optionally can be made finer or coarser with cfRebinSparse configurable: + ph.fParticleSparseHistogramsNBins[eDWPt][wPtPtAxis] = static_cast(ph.fParticleHistogramsBins[ePt][0] / ph.fRebinSparse[eDWPt][wPtPtAxis]); + lAxis = new TAxis(ph.fParticleSparseHistogramsNBins[eDWPt][wPtPtAxis], ph.fParticleHistogramsBins[ePt][1], ph.fParticleHistogramsBins[ePt][2]); ph.fParticleSparseHistogramsBinEdges[eDWPt][wPtPtAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWPt][wPtPtAxis]); for (int bin = 1; bin <= lAxis->GetNbins(); bin++) { ph.fParticleSparseHistogramsBinEdges[eDWPt][wPtPtAxis]->AddAt(lAxis->GetBinLowEdge(bin), bin - 1); } ph.fParticleSparseHistogramsBinEdges[eDWPt][wPtPtAxis]->AddAt(lAxis->GetBinLowEdge(1 + lAxis->GetNbins()), lAxis->GetNbins()); // special treatment for last bin - // delete lAxis; // I do not need to delete here, only when new TAxis(...) + delete lAxis; ph.fParticleSparseHistogramsAxisTitle[eDWPt][wPtPtAxis] = FancyFormatting("Pt"); - // ***) charge-axis for diff pt weights - I re-use binning from results histograms: - if (!res.fResultsPro[AFO_CHARGE]) { - LOGF(fatal, "\033[1;31m%s at line %d : res.fResultsPro[AFO_CHARGE] is NULL \033[0m", __FUNCTION__, __LINE__); + // ***) eta-axis for diff pt weights - at the moment I support only fixed-length binning from control histograms, which optionally can be made finer or coarser with cfRebinSparse configurable: + ph.fParticleSparseHistogramsNBins[eDWPt][wPtEtaAxis] = static_cast(ph.fParticleHistogramsBins[eEta][0] / ph.fRebinSparse[eDWPt][wPtEtaAxis]); + lAxis = new TAxis(ph.fParticleSparseHistogramsNBins[eDWPt][wPtEtaAxis], ph.fParticleHistogramsBins[eEta][1], ph.fParticleHistogramsBins[eEta][2]); + ph.fParticleSparseHistogramsBinEdges[eDWPt][wPtEtaAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWPt][wPtEtaAxis]); + for (int bin = 1; bin <= lAxis->GetNbins(); bin++) { + ph.fParticleSparseHistogramsBinEdges[eDWPt][wPtEtaAxis]->AddAt(lAxis->GetBinLowEdge(bin), bin - 1); } - ph.fParticleSparseHistogramsNBins[eDWPt][wPtChargeAxis] = res.fResultsPro[AFO_CHARGE]->GetNbinsX(); - lAxis = res.fResultsPro[AFO_CHARGE]->GetXaxis(); + ph.fParticleSparseHistogramsBinEdges[eDWPt][wPtEtaAxis]->AddAt(lAxis->GetBinLowEdge(1 + lAxis->GetNbins()), lAxis->GetNbins()); // special treatment for last bin + delete lAxis; + ph.fParticleSparseHistogramsAxisTitle[eDWPt][wPtEtaAxis] = FancyFormatting("Eta"); + + // ***) charge-axis for diff pt weights - at the moment I support only fixed-length binning from control histograms, which optionally can be made finer or coarser with cfRebinSparse configurable: + ph.fParticleSparseHistogramsNBins[eDWPt][wPtChargeAxis] = static_cast(ph.fParticleHistogramsBins[eCharge][0] / ph.fRebinSparse[eDWPt][wPtChargeAxis]); + lAxis = new TAxis(ph.fParticleSparseHistogramsNBins[eDWPt][wPtChargeAxis], ph.fParticleHistogramsBins[eCharge][1], ph.fParticleHistogramsBins[eCharge][2]); ph.fParticleSparseHistogramsBinEdges[eDWPt][wPtChargeAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWPt][wPtChargeAxis]); for (int bin = 1; bin <= lAxis->GetNbins(); bin++) { ph.fParticleSparseHistogramsBinEdges[eDWPt][wPtChargeAxis]->AddAt(lAxis->GetBinLowEdge(bin), bin - 1); } ph.fParticleSparseHistogramsBinEdges[eDWPt][wPtChargeAxis]->AddAt(lAxis->GetBinLowEdge(1 + lAxis->GetNbins()), lAxis->GetNbins()); // special treatment for last bin - // delete lAxis; // I do not need to delete here, only when new TAxis(...) + delete lAxis; ph.fParticleSparseHistogramsAxisTitle[eDWPt][wPtChargeAxis] = FancyFormatting("Charge"); - // ***) centrality-axis for diff pt weights - I re-use binning from results histograms: - if (!res.fResultsPro[AFO_CENTRALITY]) { - LOGF(fatal, "\033[1;31m%s at line %d : res.fResultsPro[AFO_CENTRALITY] is NULL \033[0m", __FUNCTION__, __LINE__); - } - ph.fParticleSparseHistogramsNBins[eDWPt][wPtCentralityAxis] = res.fResultsPro[AFO_CENTRALITY]->GetNbinsX(); - lAxis = res.fResultsPro[AFO_CENTRALITY]->GetXaxis(); + // ***) centrality-axis for diff pt weights - at the moment I support only fixed-length binning from control histograms, which optionally can be made finer or coarser with cfRebinSparse configurable: + ph.fParticleSparseHistogramsNBins[eDWPt][wPtCentralityAxis] = static_cast(eh.fEventHistogramsBins[eCentrality][0] / ph.fRebinSparse[eDWPt][wPtCentralityAxis]); + lAxis = new TAxis(ph.fParticleSparseHistogramsNBins[eDWPt][wPtCentralityAxis], eh.fEventHistogramsBins[eCentrality][1], eh.fEventHistogramsBins[eCentrality][2]); ph.fParticleSparseHistogramsBinEdges[eDWPt][wPtCentralityAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWPt][wPtCentralityAxis]); for (int bin = 1; bin <= lAxis->GetNbins(); bin++) { ph.fParticleSparseHistogramsBinEdges[eDWPt][wPtCentralityAxis]->AddAt(lAxis->GetBinLowEdge(bin), bin - 1); } ph.fParticleSparseHistogramsBinEdges[eDWPt][wPtCentralityAxis]->AddAt(lAxis->GetBinLowEdge(1 + lAxis->GetNbins()), lAxis->GetNbins()); // special treatment for last bin - // delete lAxis; // I do not need to delete here, only when new TAxis(...) + delete lAxis; ph.fParticleSparseHistogramsAxisTitle[eDWPt][wPtCentralityAxis] = "Centrality"; // TBI 20250222 I cannot call here FancyFormatting for "Centrality", because ec.fsEventCuts[eCentralityEstimator] is still not fetched and set from configurable. Re-think how to proceed for this specific case. // ... // **) eDiffWeightCategory = eDWEta: - // ***) eta-axis for diff eta weights - I re-use binning from results histograms: - if (!res.fResultsPro[AFO_ETA]) { - LOGF(fatal, "\033[1;31m%s at line %d : res.fResultsPro[AFO_ETA] is NULL \033[0m", __FUNCTION__, __LINE__); - } - ph.fParticleSparseHistogramsNBins[eDWEta][wEtaEtaAxis] = res.fResultsPro[AFO_ETA]->GetNbinsX(); - lAxis = res.fResultsPro[AFO_ETA]->GetXaxis(); + // ***) eta-axis for diff eta weights - at the moment I support only fixed-length binning from control histograms, which optionally can be made finer or coarser with cfRebinSparse configurable: + ph.fParticleSparseHistogramsNBins[eDWEta][wEtaEtaAxis] = static_cast(ph.fParticleHistogramsBins[eEta][0] / ph.fRebinSparse[eDWEta][wEtaEtaAxis]); + lAxis = new TAxis(ph.fParticleSparseHistogramsNBins[eDWEta][wEtaEtaAxis], ph.fParticleHistogramsBins[eEta][1], ph.fParticleHistogramsBins[eEta][2]); ph.fParticleSparseHistogramsBinEdges[eDWEta][wEtaEtaAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWEta][wEtaEtaAxis]); for (int bin = 1; bin <= lAxis->GetNbins(); bin++) { ph.fParticleSparseHistogramsBinEdges[eDWEta][wEtaEtaAxis]->AddAt(lAxis->GetBinLowEdge(bin), bin - 1); } ph.fParticleSparseHistogramsBinEdges[eDWEta][wEtaEtaAxis]->AddAt(lAxis->GetBinLowEdge(1 + lAxis->GetNbins()), lAxis->GetNbins()); // special treatment for last bin - // delete lAxis; // I do not need to delete here, only when new TAxis(...) + delete lAxis; ph.fParticleSparseHistogramsAxisTitle[eDWEta][wEtaEtaAxis] = FancyFormatting("Eta"); - // ***) charge-axis for diff eta weights - I re-use binning from results histograms: - if (!res.fResultsPro[AFO_CHARGE]) { - LOGF(fatal, "\033[1;31m%s at line %d : res.fResultsPro[AFO_CHARGE] is NULL \033[0m", __FUNCTION__, __LINE__); + // ***) pt-axis for diff eta weights - at the moment I support only fixed-length binning from control histograms, which optionally can be made finer or coarser with cfRebinSparse configurable: + ph.fParticleSparseHistogramsNBins[eDWEta][wEtaPtAxis] = static_cast(ph.fParticleHistogramsBins[ePt][0] / ph.fRebinSparse[eDWEta][wEtaPtAxis]); + lAxis = new TAxis(ph.fParticleSparseHistogramsNBins[eDWEta][wEtaPtAxis], ph.fParticleHistogramsBins[ePt][1], ph.fParticleHistogramsBins[ePt][2]); + ph.fParticleSparseHistogramsBinEdges[eDWEta][wEtaPtAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWEta][wEtaPtAxis]); + for (int bin = 1; bin <= lAxis->GetNbins(); bin++) { + ph.fParticleSparseHistogramsBinEdges[eDWEta][wEtaPtAxis]->AddAt(lAxis->GetBinLowEdge(bin), bin - 1); } - ph.fParticleSparseHistogramsNBins[eDWEta][wEtaChargeAxis] = res.fResultsPro[AFO_CHARGE]->GetNbinsX(); - lAxis = res.fResultsPro[AFO_CHARGE]->GetXaxis(); + ph.fParticleSparseHistogramsBinEdges[eDWEta][wEtaPtAxis]->AddAt(lAxis->GetBinLowEdge(1 + lAxis->GetNbins()), lAxis->GetNbins()); // special treatment for last bin + delete lAxis; + ph.fParticleSparseHistogramsAxisTitle[eDWEta][wEtaPtAxis] = FancyFormatting("Pt"); + + // ***) charge-axis for diff eta weights - at the moment I support only fixed-length binning from control histograms, which optionally can be made finer or coarser with cfRebinSparse configurable: + ph.fParticleSparseHistogramsNBins[eDWEta][wEtaChargeAxis] = static_cast(ph.fParticleHistogramsBins[eCharge][0] / ph.fRebinSparse[eDWEta][wEtaChargeAxis]); + lAxis = new TAxis(ph.fParticleSparseHistogramsNBins[eDWEta][wEtaChargeAxis], ph.fParticleHistogramsBins[eCharge][1], ph.fParticleHistogramsBins[eCharge][2]); ph.fParticleSparseHistogramsBinEdges[eDWEta][wEtaChargeAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWEta][wEtaChargeAxis]); for (int bin = 1; bin <= lAxis->GetNbins(); bin++) { ph.fParticleSparseHistogramsBinEdges[eDWEta][wEtaChargeAxis]->AddAt(lAxis->GetBinLowEdge(bin), bin - 1); } ph.fParticleSparseHistogramsBinEdges[eDWEta][wEtaChargeAxis]->AddAt(lAxis->GetBinLowEdge(1 + lAxis->GetNbins()), lAxis->GetNbins()); // special treatment for last bin - // delete lAxis; // I do not need to delete here, only when new TAxis(...) + delete lAxis; ph.fParticleSparseHistogramsAxisTitle[eDWEta][wEtaChargeAxis] = FancyFormatting("Charge"); - // ***) centrality-axis for diff eta weights - I re-use binning from results histograms: - if (!res.fResultsPro[AFO_CENTRALITY]) { - LOGF(fatal, "\033[1;31m%s at line %d : res.fResultsPro[AFO_CENTRALITY] is NULL \033[0m", __FUNCTION__, __LINE__); - } - ph.fParticleSparseHistogramsNBins[eDWEta][wEtaCentralityAxis] = res.fResultsPro[AFO_CENTRALITY]->GetNbinsX(); - lAxis = res.fResultsPro[AFO_CENTRALITY]->GetXaxis(); + // ***) centrality-axis for diff eta weights - at the moment I support only fixed-length binning from control histograms, which optionally can be made finer or coarser with cfRebinSparse configurable: + ph.fParticleSparseHistogramsNBins[eDWEta][wEtaCentralityAxis] = static_cast(eh.fEventHistogramsBins[eCentrality][0] / ph.fRebinSparse[eDWEta][wEtaCentralityAxis]); + lAxis = new TAxis(ph.fParticleSparseHistogramsNBins[eDWEta][wEtaCentralityAxis], eh.fEventHistogramsBins[eCentrality][1], eh.fEventHistogramsBins[eCentrality][2]); ph.fParticleSparseHistogramsBinEdges[eDWEta][wEtaCentralityAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWEta][wEtaCentralityAxis]); for (int bin = 1; bin <= lAxis->GetNbins(); bin++) { ph.fParticleSparseHistogramsBinEdges[eDWEta][wEtaCentralityAxis]->AddAt(lAxis->GetBinLowEdge(bin), bin - 1); } ph.fParticleSparseHistogramsBinEdges[eDWEta][wEtaCentralityAxis]->AddAt(lAxis->GetBinLowEdge(1 + lAxis->GetNbins()), lAxis->GetNbins()); // special treatment for last bin - // delete lAxis; // I do not need to delete here, only when new TAxis(...) + delete lAxis; ph.fParticleSparseHistogramsAxisTitle[eDWEta][wEtaCentralityAxis] = "Centrality"; // TBI 20250222 I cannot call here FancyFormatting for "Centrality", because ec.fsEventCuts[eCentralityEstimator] is still not fetched and set from configurable. Re-think how to proceed for this specific case. // ... @@ -6516,7 +6548,7 @@ void bookNUAHistograms() continue; } // Define default detector acceptance in pseudorapidity: One sectors, with probability < 1. - double dSector[2] = {0.2, 0.5}; // sector is defined as 0.2 < eta < 0.5 + double dSector[2] = {0.2, 0.6}; // sector is defined as 0.2 < eta < 0.6 double dProbability = 0.2; // probability, so after being set this way, only 20% of particles in that sector are reconstructed nua.fDefaultNUAPDF[eEtaNUAPDF] = new TF1(TString::Format("fDefaultNUAPDF[%d]", eEtaNUAPDF), "1.-(x>=[0])*(1.-[2]) + (x>=[1])*(1.-[2])", ph.fParticleHistogramsBins[eEta][1], ph.fParticleHistogramsBins[eEta][2]); @@ -6723,7 +6755,7 @@ void InternalValidation() // :iv - // Last update: 20251126 + // Last update: 20260220 // To do: // 20250121 At the moment, I do not support here differential phi weights. If I decide to add that feature, basically I need to generalize Accept() for 2D case, @@ -7078,13 +7110,13 @@ void InternalValidation() // **) eDWPt : here the fundamental 0-th axis never to be projected out is "pt" if (ph.fBookParticleSparseHistograms[eDWPt]) { // Remark: It is mandatory that ordering in initialization here resembles the ordering in enum eDiffPtWeights - double vector[eDiffPtWeights_N] = {pbyp.fPt, pbyp.fCharge, ebye.fCentrality}; + double vector[eDiffPtWeights_N] = {pbyp.fPt, pbyp.fEta, pbyp.fCharge, ebye.fCentrality}; ph.fParticleSparseHistograms[eDWPt][eSim][eBefore]->Fill(vector); } // **) eDWEta : here the fundamental 0-th axis never to be projected out is "eta" if (ph.fBookParticleSparseHistograms[eDWEta]) { // Remark: It is mandatory that ordering in initialization here resembles the ordering in enum eDiffEtaWeights - double vector[eDiffEtaWeights_N] = {pbyp.fEta, pbyp.fCharge, ebye.fCentrality}; + double vector[eDiffEtaWeights_N] = {pbyp.fEta, pbyp.fPt, pbyp.fCharge, ebye.fCentrality}; ph.fParticleSparseHistograms[eDWEta][eSim][eBefore]->Fill(vector); } } // ph.fFillParticleSparseHistogramsBeforeCuts @@ -7146,13 +7178,13 @@ void InternalValidation() // **) eDWPt : here the fundamental 0-th axis never to be projected out is "pt" if (ph.fBookParticleSparseHistograms[eDWPt]) { // Remark: It is mandatory that ordering in initialization here resembles the ordering in enum eDiffPtWeights - double vector[eDiffPtWeights_N] = {pbyp.fPt, pbyp.fCharge, ebye.fCentrality}; + double vector[eDiffPtWeights_N] = {pbyp.fPt, pbyp.fEta, pbyp.fCharge, ebye.fCentrality}; ph.fParticleSparseHistograms[eDWPt][eSim][eAfter]->Fill(vector); } // **) eDWEta : here the fundamental 0-th axis never to be projected out is "eta" if (ph.fBookParticleSparseHistograms[eDWEta]) { // Remark: It is mandatory that ordering in initialization here resembles the ordering in enum eDiffEtaWeights - double vector[eDiffEtaWeights_N] = {pbyp.fEta, pbyp.fCharge, ebye.fCentrality}; + double vector[eDiffEtaWeights_N] = {pbyp.fEta, pbyp.fPt, pbyp.fCharge, ebye.fCentrality}; ph.fParticleSparseHistograms[eDWEta][eSim][eAfter]->Fill(vector); } } // if (ph.fFillParticleHistograms || ph.fFillParticleHistograms2D) @@ -11254,13 +11286,13 @@ void FillParticleHistograms(T const& track, eBeforeAfter ba, int weight = 1) // **) eDWPt : here the fundamental 0-th axis never to be projected out is "pt" if (ph.fBookParticleSparseHistograms[eDWPt]) { // Remark: It is mandatory that ordering in initialization here resembles the ordering in enum eDiffPtWeights - double vector[eDiffPtWeights_N] = {track.pt(), static_cast(track.sign()), ebye.fCentrality}; + double vector[eDiffPtWeights_N] = {track.pt(), track.eta(), static_cast(track.sign()), ebye.fCentrality}; ph.fParticleSparseHistograms[eDWPt][eRec][ba]->Fill(vector, weight); } // **) eDWEta : here the fundamental 0-th axis never to be projected out is "eta" if (ph.fBookParticleSparseHistograms[eDWEta]) { // Remark: It is mandatory that ordering in initialization here resembles the ordering in enum eDiffEtaWeights - double vector[eDiffEtaWeights_N] = {track.eta(), static_cast(track.sign()), ebye.fCentrality}; + double vector[eDiffEtaWeights_N] = {track.eta(), track.pt(), static_cast(track.sign()), ebye.fCentrality}; ph.fParticleSparseHistograms[eDWEta][eRec][ba]->Fill(vector, weight); } } // if (ba == eAfter ... ) { @@ -11411,7 +11443,7 @@ void FillParticleHistograms(T const& track, eBeforeAfter ba, int weight = 1) // Yes, I have to check the 2nd condition, because e.g. for PDG code 1000010020 (deuteron), GetParticle(...) returns NULL charge = tc.fDatabasePDG->GetParticle(mcParticle.pdgCode())->Charge() / 3.; // yes, divided by 3. Fundamental unit of charge is associated with quarks } - double vector[eDiffPtWeights_N] = {mcParticle.pt(), charge, ebye.fCentralitySim}; + double vector[eDiffPtWeights_N] = {mcParticle.pt(), mcParticle.eta(), charge, ebye.fCentralitySim}; ph.fParticleSparseHistograms[eDWPt][eSim][ba]->Fill(vector, weight); } // **) eDWEta : here the fundamental 0-th axis never to be projected out is "eta" @@ -11424,7 +11456,7 @@ void FillParticleHistograms(T const& track, eBeforeAfter ba, int weight = 1) // Yes, I have to check the 2nd condition, because e.g. for PDG code 1000010020 (deuteron), GetParticle(...) returns NULL charge = tc.fDatabasePDG->GetParticle(mcParticle.pdgCode())->Charge() / 3.; // yes, divided by 3. Fundamental unit of charge is associated with quarks } - double vector[eDiffEtaWeights_N] = {mcParticle.eta(), charge, ebye.fCentralitySim}; + double vector[eDiffEtaWeights_N] = {mcParticle.eta(), mcParticle.pt(), charge, ebye.fCentralitySim}; ph.fParticleSparseHistograms[eDWEta][eSim][ba]->Fill(vector, weight); } } // if (ba == eAfter ... ) { @@ -13231,15 +13263,31 @@ void FillNestedLoopsContainers(const int& particleIndex) double wPhi = 1.; double wPt = 1.; double wEta = 1.; - if (pw.fUseWeights[wPHI]) { + + if (pw.fUseDiffPhiWeights[wPhiPhiAxis]) { // yes, 0th axis serves as a common boolean for this category + wPhi = WeightFromSparse(eDWPhi); + } + + if (pw.fUseDiffPtWeights[wPtPtAxis]) { // yes, 0th axis serves as a common boolean for this category + wPt = WeightFromSparse(eDWPt); + } + + if (pw.fUseDiffEtaWeights[wEtaEtaAxis]) { // yes, 0th axis serves as a common boolean for this category + wEta = WeightFromSparse(eDWEta); + } + + if (pw.fUseWeights[wPHI]) { // TBI 20260216 obsolete, remove eventually wPhi = Weight(pbyp.fPhi, wPHI); } - if (pw.fUseWeights[wPT]) { + + if (pw.fUseWeights[wPT]) { // TBI 20260216 obsolete, remove eventually wPt = Weight(pbyp.fPt, wPT); } - if (pw.fUseWeights[wETA]) { + + if (pw.fUseWeights[wETA]) { // TBI 20260216 obsolete, remove eventually wEta = Weight(pbyp.fEta, wETA); } + nl.ftaNestedLoops[1]->AddAt(wPhi * wPt * wEta, particleIndex); // remember that the 2nd argument here must start from 0 } @@ -13989,30 +14037,126 @@ void SetDiffWeightsSparse(THnSparseF* const sparse, eDiffWeightCategory dwc) // Finally, add to corresponding TList: pw.fWeightsList->Add(pw.fDiffWeightsSparse[dwc]); - // TBI 20250530 check this code snippet - do I need it? - // // Cosmetics: TBI 20240216 do I really want to overwrite initial cosmetics, perhaps this shall go better into MakeWeights.C ? - // // Or I could move all this to GetHistogramWithWeights, where in any case I am setting e.g. histogram title, etc. - // TString sVariable[eDiffWeights_N] = {"#varphi", "#varphi"}; // yes, for the time being, x-axis is always phi - // TString sWeights[eDiffWeights_N] = {"(w_{#varphi})_{| p_{T}}", "(w_{#varphi})_{| #eta}"}; - // pw.fDiffWeightsSparse[whichDiffWeight][bin]->SetStats(false); - // pw.fDiffWeightsSparse[whichDiffWeight][bin]->GetXaxis()->SetTitle(sVariable[whichDiffWeight].Data()); - // pw.fDiffWeightsSparse[whichDiffWeight][bin]->GetYaxis()->SetTitle(sWeights[whichDiffWeight].Data()); - // pw.fDiffWeightsSparse[whichDiffWeight][bin]->SetFillColor(eFillColor); - // pw.fDiffWeightsSparse[whichDiffWeight][bin]->SetLineColor(eColor); - // pw.fWeightsList->Add(pw.fDiffWeightsSparse[whichDiffWeight][bin]); // This is working at the moment, because I am fetching all weights in Preprocess(), which is called after init() - // // But if eventually it will be possible to fetch run number programatically in init(), I will have to re-think this line. - - // // Flag: - // if (!pw.fUseDiffWeights[whichDiffWeight]) // yes, set it only once to true, for all bins - // { - // pw.fUseDiffWeights[whichDiffWeight] = true; - // } + if (tc.fVerbose) { + ExitFunction(__FUNCTION__); + } - // if (tc.fVerbose) { - // ExitFunction(__FUNCTION__); - // } +} // void SetDiffWeightsSparse(THnSparseF* const sparse, eDiffWeightCategory dwc) + +//============================================================ + +void insanitizeDiffWeightsSparse(THnSparseF* const sparse) +{ + // Check if particle weights are avaiable for the phase window I have selected for each dimension with cuts. + // Basically, I check whether range of each axis in sparse histograms is compatible with the cuts i used for variable on that axis. + + // TBI 20260223 : I am doing one unnecessary extra check in each if statement below to prevent rounding problem - check this further -} // void SetDiffWeightsSparse(THnSparseF* const sparse) + if (tc.fVerbose) { + StartFunction(__FUNCTION__); + } + + if (!sparse) { + LOGF(fatal, "\033[1;31m%s at line %d\033[0m", __FUNCTION__, __LINE__); + } + + int nDim = sparse->GetNdimensions(); + for (int d = 0; d < nDim; d++) { + + // get title for this axis: + std::string axisTitle = sparse->GetAxis(d)->GetTitle(); + + // insanity check on the title: + if (axisTitle.empty()) { + LOGF(fatal, "\033[1;31m%s at line %d : axis %d of sparse %s has an empty title \033[0m", __FUNCTION__, __LINE__, d, sparse->GetName()); + } + + // check all supported observables: + if (!axisTitle.compare("#varphi")) { // I have to negate, becase compare() returns 0 if strings are equal + keep in sync hardwired string here with what i have in FancyFormatting(...) + + // check lower boundary: + if ((pc.fdParticleCuts[ePhi][eMin] < sparse->GetAxis(d)->GetBinLowEdge(1)) && (std::abs(sparse->GetAxis(d)->GetBinLowEdge(1) - pc.fdParticleCuts[ePhi][eMin]) > tc.fFloatingPointPrecision)) { + LOGF(fatal, "\033[1;31m%s at line %d : axis %d (#varphi) of sparse %s has lower boundary %f, while lower cut on that variable is %f. This means that for some particles I won't be able to fetch weights from this sparse. \033[0m", __FUNCTION__, __LINE__, d, sparse->GetName(), sparse->GetAxis(d)->GetBinLowEdge(1), pc.fdParticleCuts[ePhi][eMin]); + } + + // check upper boundary: + if ((pc.fdParticleCuts[ePhi][eMax] > sparse->GetAxis(d)->GetBinUpEdge(sparse->GetAxis(d)->GetNbins())) && (std::abs(sparse->GetAxis(d)->GetBinUpEdge(sparse->GetAxis(d)->GetNbins()) - pc.fdParticleCuts[ePhi][eMax]) > tc.fFloatingPointPrecision)) { + LOGF(fatal, "\033[1;31m%s at line %d : axis %d (#varphi) of sparse %s has upper boundary %f, while upper cut on that variable is %f. This means that for some particles I won't be able to fetch weights from this sparse. \033[0m", __FUNCTION__, __LINE__, d, sparse->GetName(), sparse->GetAxis(d)->GetBinUpEdge(sparse->GetAxis(d)->GetNbins()), pc.fdParticleCuts[ePhi][eMax]); + } + + } else if (!axisTitle.compare("p_{T}")) { + + // check lower boundary: + if ((pc.fdParticleCuts[ePt][eMin] < sparse->GetAxis(d)->GetBinLowEdge(1)) && (std::abs(sparse->GetAxis(d)->GetBinLowEdge(1) - pc.fdParticleCuts[ePt][eMin]) > tc.fFloatingPointPrecision)) { + LOGF(fatal, "\033[1;31m%s at line %d : axis %d (p_{T}) of sparse %s has lower boundary %f, while lower cut on that variable is %f. This means that for some particles I won't be able to fetch weights from this sparse. \033[0m", __FUNCTION__, __LINE__, d, sparse->GetName(), sparse->GetAxis(d)->GetBinLowEdge(1), pc.fdParticleCuts[ePt][eMin]); + } + + // check upper boundary: + if ((pc.fdParticleCuts[ePt][eMax] > sparse->GetAxis(d)->GetBinUpEdge(sparse->GetAxis(d)->GetNbins())) && (std::abs(sparse->GetAxis(d)->GetBinUpEdge(sparse->GetAxis(d)->GetNbins()) - pc.fdParticleCuts[ePt][eMax]) > tc.fFloatingPointPrecision)) { + LOGF(fatal, "\033[1;31m%s at line %d : axis %d (p_{T}) of sparse %s has upper boundary %f, while upper cut on that variable is %f. This means that for some particles I won't be able to fetch weights from this sparse. \033[0m", __FUNCTION__, __LINE__, d, sparse->GetName(), sparse->GetAxis(d)->GetBinUpEdge(sparse->GetAxis(d)->GetNbins()), pc.fdParticleCuts[ePt][eMax]); + } + + } else if (!axisTitle.compare("#eta")) { + + // check lower boundary: + if ((pc.fdParticleCuts[eEta][eMin] < sparse->GetAxis(d)->GetBinLowEdge(1)) && (std::abs(sparse->GetAxis(d)->GetBinLowEdge(1) - pc.fdParticleCuts[eEta][eMin]) > tc.fFloatingPointPrecision)) { + LOGF(fatal, "\033[1;31m%s at line %d : axis %d (#eta) of sparse %s has lower boundary %f, while lower cut on that variable is %f. This means that for some particles I won't be able to fetch weights from this sparse. \033[0m", __FUNCTION__, __LINE__, d, sparse->GetName(), sparse->GetAxis(d)->GetBinLowEdge(1), pc.fdParticleCuts[eEta][eMin]); + } + + // check upper boundary: + if ((pc.fdParticleCuts[eEta][eMax] > sparse->GetAxis(d)->GetBinUpEdge(sparse->GetAxis(d)->GetNbins())) && (std::abs(sparse->GetAxis(d)->GetBinUpEdge(sparse->GetAxis(d)->GetNbins()) - pc.fdParticleCuts[eEta][eMax]) > tc.fFloatingPointPrecision)) { + LOGF(fatal, "\033[1;31m%s at line %d : axis %d (#eta) of sparse %s has upper boundary %f, while upper cut on that variable is %f. This means that for some particles I won't be able to fetch weights from this sparse. \033[0m", __FUNCTION__, __LINE__, d, sparse->GetName(), sparse->GetAxis(d)->GetBinUpEdge(sparse->GetAxis(d)->GetNbins()), pc.fdParticleCuts[eEta][eMax]); + } + + } else if (!axisTitle.compare("Charge")) { + + // check lower boundary: + if ((pc.fdParticleCuts[eCharge][eMin] < sparse->GetAxis(d)->GetBinLowEdge(1)) && (std::abs(sparse->GetAxis(d)->GetBinLowEdge(1) - pc.fdParticleCuts[eCharge][eMin]) > tc.fFloatingPointPrecision)) { + LOGF(fatal, "\033[1;31m%s at line %d : axis %d (Charge) of sparse %s has lower boundary %f, while lower cut on that variable is %f. This means that for some particles I won't be able to fetch weights from this sparse. \033[0m", __FUNCTION__, __LINE__, d, sparse->GetName(), sparse->GetAxis(d)->GetBinLowEdge(1), pc.fdParticleCuts[eCharge][eMin]); + } + + // check upper boundary: + if ((pc.fdParticleCuts[eCharge][eMax] > sparse->GetAxis(d)->GetBinUpEdge(sparse->GetAxis(d)->GetNbins())) && (std::abs(sparse->GetAxis(d)->GetBinUpEdge(sparse->GetAxis(d)->GetNbins()) - pc.fdParticleCuts[eCharge][eMax]) > tc.fFloatingPointPrecision)) { + LOGF(fatal, "\033[1;31m%s at line %d : axis %d (Charge) of sparse %s has upper boundary %f, while upper cut on that variable is %f. This means that for some particles I won't be able to fetch weights from this sparse. \033[0m", __FUNCTION__, __LINE__, d, sparse->GetName(), sparse->GetAxis(d)->GetBinUpEdge(sparse->GetAxis(d)->GetNbins()), pc.fdParticleCuts[eCharge][eMax]); + } + + } else if (!axisTitle.find("Centrality")) { // I have to use here find() instead, because title also contains centrality estimator name, e.g. "Centality (FT0C)" + + // check lower boundary: + if ((ec.fdEventCuts[eCentrality][eMin] < sparse->GetAxis(d)->GetBinLowEdge(1)) && (std::abs(sparse->GetAxis(d)->GetBinLowEdge(1) - ec.fdEventCuts[eCentrality][eMin]) > tc.fFloatingPointPrecision)) { + LOGF(fatal, "\033[1;31m%s at line %d : axis %d (Centrality) of sparse %s has lower boundary %f, while lower cut on that variable is %f. This means that for some events I won't be able to fetch particle weights from this sparse. \033[0m", __FUNCTION__, __LINE__, d, sparse->GetName(), sparse->GetAxis(d)->GetBinLowEdge(1), ec.fdEventCuts[eCentrality][eMin]); + } + + // check upper boundary: + if ((ec.fdEventCuts[eCentrality][eMax] > sparse->GetAxis(d)->GetBinUpEdge(sparse->GetAxis(d)->GetNbins())) && (std::abs(sparse->GetAxis(d)->GetBinUpEdge(sparse->GetAxis(d)->GetNbins()) - ec.fdEventCuts[eCentrality][eMax]) > tc.fFloatingPointPrecision)) { + LOGF(fatal, "\033[1;31m%s at line %d : axis %d (Centrality) of sparse %s has upper boundary %f, while upper cut on that variable is %f. This means that for some events I won't be able to fetch particles weights from this sparse. \033[0m", __FUNCTION__, __LINE__, d, sparse->GetName(), sparse->GetAxis(d)->GetBinUpEdge(sparse->GetAxis(d)->GetNbins()), ec.fdEventCuts[eCentrality][eMax]); + } + + } else if (!(axisTitle.compare("V_{z}")) || !(axisTitle.compare("VertexZ"))) { // TBI 20260217 I use indeed "VertexZ" for the time being, not sure why I didn't use here also FancyFormatting. But it doesn't hurt to add check for both + + // check lower boundary: + if ((ec.fdEventCuts[eVertexZ][eMin] < sparse->GetAxis(d)->GetBinLowEdge(1)) && (std::abs(sparse->GetAxis(d)->GetBinLowEdge(1) - ec.fdEventCuts[eVertexZ][eMin]) > tc.fFloatingPointPrecision)) { + LOGF(fatal, "\033[1;31m%s at line %d : axis %d (V_{z} or VertexZ) of sparse %s has lower boundary %f, while lower cut on that variable is %f. This means that for some events I won't be able to fetch particle weights from this sparse. \033[0m", __FUNCTION__, __LINE__, d, sparse->GetName(), sparse->GetAxis(d)->GetBinLowEdge(1), ec.fdEventCuts[eVertexZ][eMin]); + } + + // check upper boundary: + if ((ec.fdEventCuts[eVertexZ][eMax] > sparse->GetAxis(d)->GetBinUpEdge(sparse->GetAxis(d)->GetNbins())) && (std::abs(sparse->GetAxis(d)->GetBinUpEdge(sparse->GetAxis(d)->GetNbins()) - ec.fdEventCuts[eVertexZ][eMax]) > tc.fFloatingPointPrecision)) { + LOGF(fatal, "\033[1;31m%s at line %d : axis %d (V_{z} or VertexZ) of sparse %s has upper boundary %f, while upper cut on that variable is %f. This means that for some events I won't be able to fetch particles weights from this sparse. \033[0m", __FUNCTION__, __LINE__, d, sparse->GetName(), sparse->GetAxis(d)->GetBinUpEdge(sparse->GetAxis(d)->GetNbins()), ec.fdEventCuts[eVertexZ][eMax]); + } + + // ... add in the same way check for any other variable + + } else { + LOGF(fatal, "\033[1;31m%s at line %d : axisTitle = %s of sparse = %s is not supported yet in this function \033[0m", __FUNCTION__, __LINE__, axisTitle.data(), sparse->GetName()); + } + + } // for(int d = 0; d < nDim; d++) { + + if (tc.fVerbose) { + ExitFunction(__FUNCTION__); + } + +} // void insanitizeDiffWeightsSparse(THnSparseF* const sparse) //============================================================ @@ -15864,7 +16008,7 @@ void GetParticleWeights() // b) Differential weights: // differential phi(pt) weights: - if (pw.fUseDiffWeights[wPHIPT]) { + if (pw.fUseDiffWeights[wPHIPT]) { // TBI 20260217 obsolete branch, remove eventually TH1D* phiptWeights = NULL; int nPtBins = res.fResultsPro[AFO_PT]->GetXaxis()->GetNbins(); for (int b = 0; b < nPtBins; b++) { @@ -15893,7 +16037,7 @@ void GetParticleWeights() } // if (pw.fUseDiffWeights[wPHIPT]) { // differential phi(eta) weights: - if (pw.fUseDiffWeights[wPHIETA]) { + if (pw.fUseDiffWeights[wPHIETA]) { // TBI 20260217 obsolete branch, remove eventually TH1D* phietaWeights = NULL; int nEtaBins = res.fResultsPro[AFO_ETA]->GetXaxis()->GetNbins(); for (int b = 0; b < nEtaBins; b++) { @@ -15945,14 +16089,17 @@ void GetParticleWeights() } // ... - // TBI-today ... check if particle weights are avaiable for the phase window I have selected for each dimension with cuts - THnSparseF* diffWeightsSparse = GetSparseHistogramWithWeights(pw.fFileWithWeights.Data(), tc.fRunNumber.Data(), whichCategory.Data(), whichDimensions.Data()); if (!diffWeightsSparse) { LOGF(fatal, "\033[1;31m%s at line %d : diffWeightsSparse for category \"phi\" is NULL. Check the external file %s with particle weights\033[0m", __FUNCTION__, __LINE__, pw.fFileWithWeights.Data()); } - // okay, just use this sparse histogram with weights: + // Check if particle weights are avaiable for the phase window I have selected for each dimension with cuts. + // Basically, I check whether range of each axis is compatible with the cuts i used for variable on that axis. + // Since GetParticleWeights() is called only once, this check is also performed only once. + insanitizeDiffWeightsSparse(diffWeightsSparse); + + // Okay, just use this sparse histogram with weights: SetDiffWeightsSparse(diffWeightsSparse, eDWPhi); } // if (pw.fUseDiffPhiWeights[wPhiPhiAxis]) { @@ -15963,7 +16110,10 @@ void GetParticleWeights() TString whichCategory = "pt"; // differential pt weights TString whichDimensions = ""; // differential pt weights as a function of particular dimension - // Remark: the naming convention hardwired here for axes dimensions have to be in sync with what I have in the macro to make these weights + // Remark: the naming convention hardwired here for axes dimensions have to be in sync with what I have in the macro to make these weights. + if (pw.fUseDiffPtWeights[wPtEtaAxis]) { + whichDimensions += "_eta"; + } if (pw.fUseDiffPtWeights[wPtChargeAxis]) { whichDimensions += "_charge"; } @@ -15972,13 +16122,16 @@ void GetParticleWeights() } // ... - // TBI-today ... check if particles weights are avaiable for the phase window I have selected for each dimension with cuts - THnSparseF* diffWeightsSparse = GetSparseHistogramWithWeights(pw.fFileWithWeights.Data(), tc.fRunNumber.Data(), whichCategory.Data(), whichDimensions.Data()); if (!diffWeightsSparse) { LOGF(fatal, "\033[1;31m%s at line %d : diffWeightsSparse for category \"pt\" is NULL. Check the external file %s with particle weights\033[0m", __FUNCTION__, __LINE__, pw.fFileWithWeights.Data()); } + // Check if particle weights are avaiable for the phase window I have selected for each dimension with cuts. + // Basically, I check whether range of each axis is compatible with the cuts i used for variable on that axis. + // Since GetParticleWeights() is called only once, this check is also performed only once. + insanitizeDiffWeightsSparse(diffWeightsSparse); + // okay, just use this sparse histogram with weights: SetDiffWeightsSparse(diffWeightsSparse, eDWPt); @@ -15990,8 +16143,10 @@ void GetParticleWeights() TString whichCategory = "eta"; // differential eta weights TString whichDimensions = ""; // differential eta weights as a function of particular dimension - // Remark: the naming convention hardwired here for axes dimensions have to be in sync with what I have in the macro to make these weights - + // Remark: the naming convention hardwired here for axes dimensions have to be in sync with what I have in the macro to make these weights. + if (pw.fUseDiffEtaWeights[wEtaPtAxis]) { + whichDimensions += "_pt"; + } if (pw.fUseDiffEtaWeights[wEtaChargeAxis]) { whichDimensions += "_charge"; } @@ -16000,13 +16155,16 @@ void GetParticleWeights() } // ... - // TBI-today ... check if particles weights are avaiable for the phase window I have selected for each dimension with cuts - THnSparseF* diffWeightsSparse = GetSparseHistogramWithWeights(pw.fFileWithWeights.Data(), tc.fRunNumber.Data(), whichCategory.Data(), whichDimensions.Data()); if (!diffWeightsSparse) { LOGF(fatal, "\033[1;31m%s at line %d : diffWeightsSparse for category \"eta\" is NULL. Check the external file %s with particle weights\033[0m", __FUNCTION__, __LINE__, pw.fFileWithWeights.Data()); } + // Check if particle weights are avaiable for the phase window I have selected for each dimension with cuts. + // Basically, I check whether range of each axis is compatible with the cuts i used for variable on that axis. + // Since GetParticleWeights() is called only once, this check is also performed only once. + insanitizeDiffWeightsSparse(diffWeightsSparse); + // okay, just use this sparse histogram with weights: SetDiffWeightsSparse(diffWeightsSparse, eDWEta); @@ -16240,6 +16398,9 @@ void EventCounterForDryRun(eEventCounterForDryRun eVar) const char* FancyFormatting(const char* name) { // Simple utility function to convert ordinary name into fancier formatting. + // If I change something in the formatting here, check if that fancy formatting was hardwired elsewhere, e.g. in void insanitizeDiffWeightsSparse(...) + + // :ff // Examples: // 1. use LaTeX syntax (as supported by ROOT!), for the case when it's possible (e.g. "Phi" => "#{varphi}"); @@ -19230,7 +19391,7 @@ void MainLoopOverParticles(T const& tracks) // *) Fill nested loops containers (integrated => I fill kine containers for nested loops in FillqvectorNdim(...)): if (nl.fCalculateNestedLoops || nl.fCalculateCustomNestedLoops) { - this->FillNestedLoopsContainers(ebye.fSelectedTracks); // all 4 arguments are passed by reference + this->FillNestedLoopsContainers(ebye.fSelectedTracks); // all 4 arguments are passed by reference => not true any longer, I have now 4 pbyp data members } // *) Counter of selected tracks in the current event: @@ -19431,7 +19592,19 @@ void Steer(T1 const& collision, T2 const& bcs, T3 const& tracks) ExitFunction(__FUNCTION__); } - // memStatus (summary): Last update: 20250602 + // memStatus (summary): Status at 20260218 (wf-13.sh + file 2023/LHC23zzh/544116/apass5/0140/o2_ctf_run00544116_orbit0034437888_tf0000000601_epn103/008/AO2D.root) + // Remark: disable sequential bailout before doing this test (yes!) + all of UseSetBinLabel, ... UseDatabasetPDG + // ~47K (dry run with 1D objects booked) + // ~61K (all object declaration besides kine objects (diff. q-vectors and eta separations) + all calculus and 1D histograms filled, trivial labels) + // ~61K (all object declaration + 1D kine objects (diff. q-vectors in coarse kine bins: 2 bins in pt and 2 in eta) + all calculus and 1D histograms filled, standard labels) + // ~61K (all object declaration + 1D kine objects (diff. q-vectors in fine kine bins: 16 bins in pt and 10 in eta) + all calculus and 1D histograms filled, standard labels) + // ~62K (all object declaration + 1D kine objects (diff. q-vectors in fine kine bins: 16 bins in pt and 10 in eta) + all calculus and 1D histograms filled, Set_0 labels + // + all 3 sparse histograms only after the cuts) + // ~80K (all object declaration + 1D kine objects (diff. q-vectors in fine kine bins: 16 bins in pt and 10 in eta) + all calculus and 1D histograms filled, Set_0 labels + // + all 3 sparse histograms before and after the cuts) + // ~102K (all object declaration + 1D + 2D + 3D kine objects (diff. q-vectors in fine kine bins: same as above) + all calculus and 1D histograms filled, Set_0 labels) + + // memStatus (summary): Status at 20250602 // Remark: disable sequential bailout before doing this test (yes!) + all of UseSetBinLabel, ... UseDatabasetPDG // ~46K (skeleton - literally) // ~50K (dry run with 1D objects booked) From c04e8e7c5dd0bd1b807841d6b81a8d3ce7cc7d2c Mon Sep 17 00:00:00 2001 From: dyx-11 <1260971129@qq.com> Date: Thu, 26 Feb 2026 05:03:53 +0800 Subject: [PATCH 086/347] [PWGUD] add Nch_vs_zVtx (#15167) --- PWGUD/Tasks/flowCorrelationsUpc.cxx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/PWGUD/Tasks/flowCorrelationsUpc.cxx b/PWGUD/Tasks/flowCorrelationsUpc.cxx index 9dcb3cac9bd..26c4e7cfc09 100644 --- a/PWGUD/Tasks/flowCorrelationsUpc.cxx +++ b/PWGUD/Tasks/flowCorrelationsUpc.cxx @@ -83,6 +83,7 @@ struct CalcNchUpc { registry.add("Ncharge", "N_{charge}", {HistType::kTH1D, {axisNch}}); registry.add("zVtx_all", "zVtx_all", {HistType::kTH1D, {axisVrtx}}); + registry.add("Nch_vs_zVtx", "Nch vs zVtx", {HistType::kTH2D, {axisVrtx, axisNch}}); } void process(UDCollisionsFull::iterator const& collision, UdTracksFull const& tracks) @@ -90,6 +91,7 @@ struct CalcNchUpc { multiplicityNch(tracks.size()); registry.fill(HIST("Ncharge"), tracks.size()); registry.fill(HIST("zVtx_all"), collision.posZ()); + registry.fill(HIST("Nch_vs_zVtx"), collision.posZ(), tracks.size()); } }; @@ -169,6 +171,7 @@ struct FlowCorrelationsUpc { registry.add("pT", "pT", {HistType::kTH1D, {axisPtTrigger}}); registry.add("Nch", "N_{ch}", {HistType::kTH1D, {axisMultiplicity}}); registry.add("zVtx", "zVtx", {HistType::kTH1D, {axisVertex}}); + registry.add("Nch_vs_zVtx", "Nch vs zVtx", {HistType::kTH2D, {axisVertex, axisMultiplicity}}); registry.add("Trig_hist", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisPtTrigger}}}); @@ -380,6 +383,7 @@ struct FlowCorrelationsUpc { int runIndex = collision.runNumber(); registry.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin + registry.fill(HIST("Nch_vs_zVtx"), collision.posZ(), tracks.size()); fillYield(collision, tracks); fillCorrelations(tracks, tracks, collision.posZ(), SameEvent, runIndex); // fill the SE histogram and Sparse } From 890987287b664a3437ddd1cfff56ccfa52ae49f8 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Wed, 25 Feb 2026 22:27:09 +0100 Subject: [PATCH 087/347] [PWGLF,PWGMM] Implement both BL definitions and move from mu to number of inspected BCs (#15165) Co-authored-by: ALICE Action Bot --- PWGMM/Lumi/Tasks/lumiStabilityPP.cxx | 258 ++++++++++++++++----------- 1 file changed, 153 insertions(+), 105 deletions(-) diff --git a/PWGMM/Lumi/Tasks/lumiStabilityPP.cxx b/PWGMM/Lumi/Tasks/lumiStabilityPP.cxx index 9143f524ff3..85c66f376c1 100644 --- a/PWGMM/Lumi/Tasks/lumiStabilityPP.cxx +++ b/PWGMM/Lumi/Tasks/lumiStabilityPP.cxx @@ -49,16 +49,20 @@ enum TriggerAliases { AllBCs = 0, FT0CE = 2, FDD = 3, NTriggerAliases }; -enum BCCategories { BCA = 0, // A side BCs (bunch-crossings that had beam only from A side) - BCB = 1, // B type BCs (bunch-crossings that had beam from both sides) - BCC = 2, // C side BCs (bunch-crossings that had beam only from C side) - BCE = 3, // empty BCs (bunch-crossings that did not have beam from either side) - BCL = 4, // leading BCs (bunch-crossings that did not have interacting bunches for a configurable number of preceding BCs) - BCSLFDD = 5, // super-leading BCs for FDD (bunch-crossings that had beam from both sides but did not have FDD activity for a configurable number of preceding BCs) - BCSLFT0 = 6, // super-leading BCs for FT0 (bunch-crossings that had beam from both sides but did not have FT0 activity for a configurable number of preceding BCs) - BCNL = 7, // non-leading BCs of type B (bunch-crossings that come after a BCL and are of type B) - BCNSLFDD = 8, // non-super-leading BCs for FDD of type B (bunch-crossings that had beam from both sides but are not SL for FDD activity for a configurable number of preceding BCs) - BCNSLFT0 = 9, // non-super-leading BCs for FT0 of type B (bunch-crossings that had beam from both sides but are not SL for FT0 activity for a configurable number of preceding BCs) + +// SL types must be after all the others +enum BCCategories { BCA = 0, // A side BCs (bunch-crossings that had beam only from A side) + BCB, // B type BCs (bunch-crossings that had beam from both sides) + BCC, // C side BCs (bunch-crossings that had beam only from C side) + BCE, // empty BCs (bunch-crossings that did not have beam from either side) + BCL, // leading BCs (bunch-crossings that have not-B BCs for a configurable number of preceding BCs) + BCLE, // leading BCs (bunch-crossings that did not have interacting bunches for a configurable number of preceding BCs) + BCNL, // non-leading BCs of type B (bunch-crossings that come after a BCL and are of type B) + BCNLE, // non-leading BCs of type B (bunch-crossings that come after a BCLE and are of type B) + BCSLFDD, // super-leading BCs for FDD (bunch-crossings that had beam from both sides but did not have FDD activity for a configurable number of preceding BCs) + BCSLFT0, // super-leading BCs for FT0 (bunch-crossings that had beam from both sides but did not have FT0 activity for a configurable number of preceding BCs) + BCNSLFDD, // non-super-leading BCs for FDD of type B (bunch-crossings that had beam from both sides but are not SL for FDD activity for a configurable number of preceding BCs) + BCNSLFT0, // non-super-leading BCs for FT0 of type B (bunch-crossings that had beam from both sides but are not SL for FT0 activity for a configurable number of preceding BCs) NBCCategories }; } // namespace lumi } // namespace o2 @@ -72,14 +76,15 @@ using BCsWithTimeStamps = soa::Join; struct LumiStabilityPP { - static constexpr int defaulFlags[1][NBCCategories] = {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}; - Configurable> doTypeBC{"doTypeBC", {defaulFlags[0], NBCCategories, {"BCA", "BCB", "BCC", "BCE", "BCL", "BCSLFDD", "BCSLFT0", "BCNL", "BCNSLFDD", "BCNSLFT0"}}, "Create and fill histograms for different BC types"}; + static constexpr int defaulFlags[1][NBCCategories] = {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}; + Configurable> doTypeBC{"doTypeBC", {defaulFlags[0], NBCCategories, {"BCA", "BCB", "BCC", "BCE", "BCL", "BCLE", "BCSLFDD", "BCSLFT0", "BCNL", "BCNLE", "BCNSLFDD", "BCNSLFT0"}}, "Create and fill histograms for different BC types"}; - Configurable numEmptyBCsBeforeLeadingBC{"numEmptyBCsBeforeLeadingBC", 5, "Number of (empty) non-B BCs before a (super)leading BC"}; + static constexpr int defaulNumBCsBeforeLeadingBC[1][3] = {{5, 5, 5}}; + Configurable> numEmptyBCsBeforeLeadingBC{"numEmptyBCsBeforeLeadingBC", {defaulNumBCsBeforeLeadingBC[0], 3, {"BCL", "BCLE", "BCSL"}}, "Create and fill histograms for different BC types"}; Configurable bcShiftFDDForData2023{"bcShiftFDDForData2023", 7, "Number of bc to shift for FDD to be applied for 2023 data only"}; std::bitset beamPatternA, beamPatternC; - std::bitset bcPatternA, bcPatternC, bcPatternB, bcPatternE, bcPatternL; + std::bitset bcPatternA, bcPatternC, bcPatternB, bcPatternE, bcPatternL, bcPatternLE; const int nBCsPerOrbit = o2::constants::lhc::LHCMaxBunches; o2::framework::Service ccdb; @@ -93,8 +98,8 @@ struct LumiStabilityPP { std::array>, NBCCategories>, NTriggerAliases> histBcVsTime; std::array>, NBCCategories>, NTriggerAliases> histBcVsBcId; - std::array>, NBCCategories>, NTriggerAliases> histMu; - std::array>, NBCCategories>, NTriggerAliases> histMuPerBcId; + std::array>, NBCCategories>, NTriggerAliases> histBcInspectVsBcId; + std::array>, BCSLFDD> histBcPattern; // undefined for BC(N)SL std::map> histNBcsVsTime; std::map> histNBcsVsBcId; std::map> histTfPerMin; @@ -103,22 +108,24 @@ struct LumiStabilityPP { std::map> histInteractionRate; static constexpr std::string_view NBCsVsTimeHistNames[NTriggerAliases][NBCCategories] = - {{"AllBCs/BC_A/nBCsVsTime", "AllBCs/BC_B/nBCsVsTime", "AllBCs/BC_C/nBCsVsTime", "AllBCs/BC_E/nBCsVsTime", "AllBCs/BC_L/nBCsVsTime", "AllBCs/BC_SL_FDD/nBCsVsTime", "AllBCs/BC_SL_FT0/nBCsVsTime", "AllBCs/BC_NL/nBCsVsTime", "AllBCs/BC_NSL_FT0/nBCsVsTime", "AllBCs/BC_NSL_FDD/nBCsVsTime"}, - {"FT0VTx/BC_A/nBCsVsTime", "FT0VTx/BC_B/nBCsVsTime", "FT0VTx/BC_C/nBCsVsTime", "FT0VTx/BC_E/nBCsVsTime", "FT0VTx/BC_L/nBCsVsTime", "FT0VTx/BC_SL_FDD/nBCsVsTime", "FT0VTx/BC_SL_FT0/nBCsVsTime", "FT0VTx/BC_NL/nBCsVsTime", "FT0VTx/BC_NSL_FT0/nBCsVsTime", "FT0VTx/BC_NSL_FDD/nBCsVsTime"}, - {"FT0CE/BC_A/nBCsVsTime", "FT0CE/BC_B/nBCsVsTime", "FT0CE/BC_C/nBCsVsTime", "FT0CE/BC_E/nBCsVsTime", "FT0CE/BC_L/nBCsVsTime", "FT0CE/BC_SL_FDD/nBCsVsTime", "FT0CE/BC_SL_FT0/nBCsVsTime", "FT0CE/BC_NL/nBCsVsTime", "FT0CE/BC_NSL_FT0/nBCsVsTime", "FT0CE/BC_NSL_FDD/nBCsVsTime"}, - {"FDD/BC_A/nBCsVsTime", "FDD/BC_B/nBCsVsTime", "FDD/BC_C/nBCsVsTime", "FDD/BC_E/nBCsVsTime", "FDD/BC_L/nBCsVsTime", "FDD/BC_SL_FDD/nBCsVsTime", "FDD/BC_SL_FT0/nBCsVsTime", "FDD/BC_NL/nBCsVsTime", "FDD/BC_NSL_FT0/nBCsVsTime", "FDD/BC_NSL_FDD/nBCsVsTime"}}; + {{"AllBCs/BC_A/nBCsVsTime", "AllBCs/BC_B/nBCsVsTime", "AllBCs/BC_C/nBCsVsTime", "AllBCs/BC_E/nBCsVsTime", "AllBCs/BC_L/nBCsVsTime", "AllBCs/BC_LE/nBCsVsTime", "AllBCs/BC_NL/nBCsVsTime", "AllBCs/BC_NLE/nBCsVsTime", "AllBCs/BC_SL_FDD/nBCsVsTime", "AllBCs/BC_SL_FT0/nBCsVsTime", "AllBCs/BC_NSL_FT0/nBCsVsTime", "AllBCs/BC_NSL_FDD/nBCsVsTime"}, + {"FT0VTx/BC_A/nBCsVsTime", "FT0VTx/BC_B/nBCsVsTime", "FT0VTx/BC_C/nBCsVsTime", "FT0VTx/BC_E/nBCsVsTime", "FT0VTx/BC_L/nBCsVsTime", "FT0VTx/BC_LE/nBCsVsTime", "FT0VTx/BC_NL/nBCsVsTime", "FT0VTx/BC_NLE/nBCsVsTime", "FT0VTx/BC_SL_FDD/nBCsVsTime", "FT0VTx/BC_SL_FT0/nBCsVsTime", "FT0VTx/BC_NSL_FT0/nBCsVsTime", "FT0VTx/BC_NSL_FDD/nBCsVsTime"}, + {"FT0CE/BC_A/nBCsVsTime", "FT0CE/BC_B/nBCsVsTime", "FT0CE/BC_C/nBCsVsTime", "FT0CE/BC_E/nBCsVsTime", "FT0CE/BC_L/nBCsVsTime", "FT0CE/BC_LE/nBCsVsTime", "FT0CE/BC_NL/nBCsVsTime", "FT0CE/BC_NLE/nBCsVsTime", "FT0CE/BC_SL_FDD/nBCsVsTime", "FT0CE/BC_SL_FT0/nBCsVsTime", "FT0CE/BC_NSL_FT0/nBCsVsTime", "FT0CE/BC_NSL_FDD/nBCsVsTime"}, + {"FDD/BC_A/nBCsVsTime", "FDD/BC_B/nBCsVsTime", "FDD/BC_C/nBCsVsTime", "FDD/BC_E/nBCsVsTime", "FDD/BC_L/nBCsVsTime", "FDD/BC_LE/nBCsVsTime", "FDD/BC_NL/nBCsVsTime", "FDD/BC_NLE/nBCsVsTime", "FDD/BC_SL_FDD/nBCsVsTime", "FDD/BC_SL_FT0/nBCsVsTime", "FDD/BC_NSL_FT0/nBCsVsTime", "FDD/BC_NSL_FDD/nBCsVsTime"}}; static constexpr std::string_view NBCsVsBCIDHistNames[NTriggerAliases][NBCCategories] = - {{"AllBCs/BC_A/nBCsVsBCID", "AllBCs/BC_B/nBCsVsBCID", "AllBCs/BC_C/nBCsVsBCID", "AllBCs/BC_E/nBCsVsBCID", "AllBCs/BC_L/nBCsVsBCID", "AllBCs/BC_SL_FDD/nBCsVsBCID", "AllBCs/BC_SL_FT0/nBCsVsBCID", "AllBCs/BC_NL/nBCsVsBCID", "AllBCs/BC_NSL_FT0/nBCsVsBCID", "AllBCs/BC_NSL_FDD/nBCsVsBCID"}, - {"FT0VTx/BC_A/nBCsVsBCID", "FT0VTx/BC_B/nBCsVsBCID", "FT0VTx/BC_C/nBCsVsBCID", "FT0VTx/BC_E/nBCsVsBCID", "FT0VTx/BC_L/nBCsVsBCID", "FT0VTx/BC_SL_FDD/nBCsVsBCID", "FT0VTx/BC_SL_FT0/nBCsVsBCID", "FT0VTx/BC_NL/nBCsVsBCID", "FT0VTx/BC_NSL_FT0/nBCsVsBCID", "FT0VTx/BC_NSL_FDD/nBCsVsBCID"}, - {"FT0CE/BC_A/nBCsVsBCID", "FT0CE/BC_B/nBCsVsBCID", "FT0CE/BC_C/nBCsVsBCID", "FT0CE/BC_E/nBCsVsBCID", "FT0CE/BC_L/nBCsVsBCID", "FT0CE/BC_SL_FDD/nBCsVsBCID", "FT0CE/BC_SL_FT0/nBCsVsBCID", "FT0CE/BC_NL/nBCsVsBCID", "FT0CE/BC_NSL_FT0/nBCsVsBCID", "FT0CE/BC_NSL_FDD/nBCsVsBCID"}, - {"FDD/BC_A/nBCsVsBCID", "FDD/BC_B/nBCsVsBCID", "FDD/BC_C/nBCsVsBCID", "FDD/BC_E/nBCsVsBCID", "FDD/BC_L/nBCsVsBCID", "FDD/BC_SL_FDD/nBCsVsBCID", "FDD/BC_SL_FT0/nBCsVsBCID", "FDD/BC_NL/nBCsVsBCID", "FDD/BC_NSL_FT0/nBCsVsBCID", "FDD/BC_NSL_FDD/nBCsVsBCID"}}; + {{"AllBCs/BC_A/nBCsVsBCID", "AllBCs/BC_B/nBCsVsBCID", "AllBCs/BC_C/nBCsVsBCID", "AllBCs/BC_E/nBCsVsBCID", "AllBCs/BC_L/nBCsVsBCID", "AllBCs/BC_LE/nBCsVsBCID", "AllBCs/BC_NL/nBCsVsBCID", "AllBCs/BC_NLE/nBCsVsBCID", "AllBCs/BC_SL_FDD/nBCsVsBCID", "AllBCs/BC_SL_FT0/nBCsVsBCID", "AllBCs/BC_NSL_FT0/nBCsVsBCID", "AllBCs/BC_NSL_FDD/nBCsVsBCID"}, + {"FT0VTx/BC_A/nBCsVsBCID", "FT0VTx/BC_B/nBCsVsBCID", "FT0VTx/BC_C/nBCsVsBCID", "FT0VTx/BC_E/nBCsVsBCID", "FT0VTx/BC_L/nBCsVsBCID", "FT0VTx/BC_LE/nBCsVsBCID", "FT0VTx/BC_NL/nBCsVsBCID", "FT0VTx/BC_NLE/nBCsVsBCID", "FT0VTx/BC_SL_FDD/nBCsVsBCID", "FT0VTx/BC_SL_FT0/nBCsVsBCID", "FT0VTx/BC_NSL_FT0/nBCsVsBCID", "FT0VTx/BC_NSL_FDD/nBCsVsBCID"}, + {"FT0CE/BC_A/nBCsVsBCID", "FT0CE/BC_B/nBCsVsBCID", "FT0CE/BC_C/nBCsVsBCID", "FT0CE/BC_E/nBCsVsBCID", "FT0CE/BC_L/nBCsVsBCID", "FT0CE/BC_LE/nBCsVsBCID", "FT0CE/BC_NL/nBCsVsBCID", "FT0CE/BC_NLE/nBCsVsBCID", "FT0CE/BC_SL_FDD/nBCsVsBCID", "FT0CE/BC_SL_FT0/nBCsVsBCID", "FT0CE/BC_NSL_FT0/nBCsVsBCID", "FT0CE/BC_NSL_FDD/nBCsVsBCID"}, + {"FDD/BC_A/nBCsVsBCID", "FDD/BC_B/nBCsVsBCID", "FDD/BC_C/nBCsVsBCID", "FDD/BC_E/nBCsVsBCID", "FDD/BC_L/nBCsVsBCID", "FDD/BC_LE/nBCsVsBCID", "FDD/BC_NL/nBCsVsBCID", "FDD/BC_NLE/nBCsVsBCID", "FDD/BC_SL_FDD/nBCsVsBCID", "FDD/BC_SL_FT0/nBCsVsBCID", "FDD/BC_NSL_FT0/nBCsVsBCID", "FDD/BC_NSL_FDD/nBCsVsBCID"}}; + + static constexpr std::string_view NBCsInspectVsBCIDHistNames[NTriggerAliases][NBCCategories] = + {{"AllBCs/BC_A/nBCsInspectedVsBCID", "AllBCs/BC_B/nBCsInspectedVsBCID", "AllBCs/BC_C/nBCsInspectedVsBCID", "AllBCs/BC_E/nBCsInspectedVsBCID", "AllBCs/BC_L/nBCsInspectedVsBCID", "AllBCs/BC_LE/nBCsInspectedVsBCID", "AllBCs/BC_NL/nBCsInspectedVsBCID", "AllBCs/BC_NLE/nBCsInspectedVsBCID", "AllBCs/BC_SL_FDD/nBCsInspectedVsBCID", "AllBCs/BC_SL_FT0/nBCsInspectedVsBCID", "AllBCs/BC_NSL_FT0/nBCsInspectedVsBCID", "AllBCs/BC_NSL_FDD/nBCsInspectedVsBCID"}, + {"FT0VTx/BC_A/nBCsInspectedVsBCID", "FT0VTx/BC_B/nBCsInspectedVsBCID", "FT0VTx/BC_C/nBCsInspectedVsBCID", "FT0VTx/BC_E/nBCsInspectedVsBCID", "FT0VTx/BC_L/nBCsInspectedVsBCID", "FT0VTx/BC_LE/nBCsInspectedVsBCID", "FT0VTx/BC_NL/nBCsInspectedVsBCID", "FT0VTx/BC_NLE/nBCsInspectedVsBCID", "FT0VTx/BC_SL_FDD/nBCsInspectedVsBCID", "FT0VTx/BC_SL_FT0/nBCsInspectedVsBCID", "FT0VTx/BC_NSL_FT0/nBCsInspectedVsBCID", "FT0VTx/BC_NSL_FDD/nBCsInspectedVsBCID"}, + {"FT0CE/BC_A/nBCsInspectedVsBCID", "FT0CE/BC_B/nBCsInspectedVsBCID", "FT0CE/BC_C/nBCsInspectedVsBCID", "FT0CE/BC_E/nBCsInspectedVsBCID", "FT0CE/BC_L/nBCsInspectedVsBCID", "FT0CE/BC_LE/nBCsInspectedVsBCID", "FT0CE/BC_NL/nBCsInspectedVsBCID", "FT0CE/BC_NLE/nBCsInspectedVsBCID", "FT0CE/BC_SL_FDD/nBCsInspectedVsBCID", "FT0CE/BC_SL_FT0/nBCsInspectedVsBCID", "FT0CE/BC_NSL_FT0/nBCsInspectedVsBCID", "FT0CE/BC_NSL_FDD/nBCsInspectedVsBCID"}, + {"FDD/BC_A/nBCsInspectedVsBCID", "FDD/BC_B/nBCsInspectedVsBCID", "FDD/BC_C/nBCsInspectedVsBCID", "FDD/BC_E/nBCsInspectedVsBCID", "FDD/BC_L/nBCsInspectedVsBCID", "FDD/BC_LE/nBCsInspectedVsBCID", "FDD/BC_NL/nBCsInspectedVsBCID", "FDD/BC_NLE/nBCsInspectedVsBCID", "FDD/BC_SL_FDD/nBCsInspectedVsBCID", "FDD/BC_SL_FT0/nBCsInspectedVsBCID", "FDD/BC_NSL_FT0/nBCsInspectedVsBCID", "FDD/BC_NSL_FDD/nBCsInspectedVsBCID"}}; - static constexpr std::string_view MuHistNames[NTriggerAliases][NBCCategories] = - {{"AllBCs/BC_A/Mu", "AllBCs/BC_B/Mu", "AllBCs/BC_C/Mu", "AllBCs/BC_E/Mu", "AllBCs/BC_L/Mu", "AllBCs/BC_SL_FDD/Mu", "AllBCs/BC_SL_FT0/Mu", "AllBCs/BC_NL/Mu", "AllBCs/BC_NSL_FT0/Mu", "AllBCs/BC_NSL_FDD/Mu"}, - {"FT0VTx/BC_A/Mu", "FT0VTx/BC_B/Mu", "FT0VTx/BC_C/Mu", "FT0VTx/BC_E/Mu", "FT0VTx/BC_L/Mu", "FT0VTx/BC_SL_FDD/Mu", "FT0VTx/BC_SL_FT0/Mu", "FT0VTx/BC_NL/Mu", "FT0VTx/BC_NSL_FT0/Mu", "FT0VTx/BC_NSL_FDD/Mu"}, - {"FT0CE/BC_A/Mu", "FT0CE/BC_B/Mu", "FT0CE/BC_C/Mu", "FT0CE/BC_E/Mu", "FT0CE/BC_L/Mu", "FT0CE/BC_SL_FDD/Mu", "FT0CE/BC_SL_FT0/Mu", "FT0CE/BC_NL/Mu", "FT0CE/BC_NSL_FT0/Mu", "FT0CE/BC_NSL_FDD/Mu"}, - {"FDD/BC_A/Mu", "FDD/BC_B/Mu", "FDD/BC_C/Mu", "FDD/BC_E/Mu", "FDD/BC_L/Mu", "FDD/BC_SL_FDD/Mu", "FDD/BC_SL_FT0/Mu", "FDD/BC_NL/Mu", "FDD/BC_NSL_FT0/Mu", "FDD/BC_NSL_FDD/Mu"}}; + static constexpr std::string_view PatternHistNames[BCSLFDD] = {"BC_A/BcPattern", "BC_B/BcPattern", "BC_C/BcPattern", "BC_E/BcPattern", "BC_L/BcPattern", "BC_LE/BcPattern", "BC_NL/BcPattern", "BC_NLE/BcPattern"}; const AxisSpec timeAxis{2880, 0., 2880., "#bf{t-t_{SOF} (min)}"}, bcIDAxis{nBCsPerOrbit, -0.5, static_cast(nBCsPerOrbit) - 0.5, "#bf{BC ID in orbit}"}; @@ -146,11 +153,14 @@ struct LumiStabilityPP { if (doTypeBC->get(0u, iBCCategory)) { histBcVsTime[iTrigger][iBCCategory][runNumber] = registry.add(Form("%d/%s", runNumber, std::string(NBCsVsTimeHistNames[iTrigger][iBCCategory]).c_str()), "Time of triggered BCs since the start of fill;#bf{t-t_{SOF} (min)};#bf{#it{N}_{BC}}", HistType::kTH1D, {timeAxis}); histBcVsBcId[iTrigger][iBCCategory][runNumber] = registry.add(Form("%d/%s", runNumber, std::string(NBCsVsBCIDHistNames[iTrigger][iBCCategory]).c_str()), "BC ID of triggered BCs;#bf{BC ID in orbit};#bf{#it{N}_{BC}}", HistType::kTH1D, {bcIDAxis}); - histMu[iTrigger][iBCCategory][runNumber] = registry.add(Form("%d/%s", runNumber, std::string(MuHistNames[iTrigger][iBCCategory]).c_str()), "pile-up #mu of different triggers;#mu;counts", HistType::kTH1D, {{400, 0., 0.2}}); - histMuPerBcId[iTrigger][iBCCategory][runNumber] = registry.add(Form("%d/%sVsBcId", runNumber, std::string(MuHistNames[iTrigger][iBCCategory]).c_str()), "pile-up #mu of different triggers per BCId;#mu;counts", HistType::kTH2D, {{bcIDAxis}, {400, 0., 0.2}}); + histBcInspectVsBcId[iTrigger][iBCCategory][runNumber] = registry.add(Form("%d/%s", runNumber, std::string(NBCsInspectVsBCIDHistNames[iTrigger][iBCCategory]).c_str()), "BC ID of inspecred BCs;#bf{BC ID in orbit};#bf{#it{N}_{BC}}", HistType::kTH1D, {bcIDAxis}); } } } + + for (int iBCCategory{0}; iBCCategory < BCSLFDD; ++iBCCategory) { + histBcPattern[iBCCategory][runNumber] = registry.add(Form("%d/%s", runNumber, std::string(PatternHistNames[iBCCategory]).c_str()), "BC Pattern;#bf{BC ID in orbit};", HistType::kTH1D, {bcIDAxis}); + } } void setLHCIFData(const auto& bc) @@ -197,14 +207,15 @@ struct LumiStabilityPP { // Create bcPatternL: leading BCs of type B that follow at least "numEmptyBCsBeforeLeadingBC" non-B BCs bcPatternL.reset(); // Initialize all bits to false + bcPatternLE.reset(); LOG(info) << "Starting to create bcPatternL from bcPatternB"; LOG(info) << "Total number of BCs to check: " << o2::constants::lhc::LHCMaxBunches; - int totalLeadingBCs = 0; + std::array totalLeadingBCs = {0, 0}; for (int iBC = 0; iBC < o2::constants::lhc::LHCMaxBunches; iBC++) { if (bcPatternB[iBC]) { // Check if current BC is of type B - int nonBtypeBCsBefore = 0; // Count how many consecutive BCs before this one are non-B - for (int j = 1; j <= numEmptyBCsBeforeLeadingBC; j++) { + int nonBtypeBCsBefore{0}, emptyBCsBefore{0}; // Count how many consecutive BCs before this one are non-B + for (int j = 1; j <= numEmptyBCsBeforeLeadingBC->get(0u, 0u); j++) { int prevBC = (iBC - j + o2::constants::lhc::LHCMaxBunches) % o2::constants::lhc::LHCMaxBunches; // Protection for BCs at small indices to check the end of the orbit if (!bcPatternB[prevBC]) { nonBtypeBCsBefore++; @@ -212,13 +223,50 @@ struct LumiStabilityPP { break; // Stop counting if we hit a BCB } } - if (nonBtypeBCsBefore >= numEmptyBCsBeforeLeadingBC) { // If we found at least numEmptyBCsBeforeLeadingBC non-B BCs before this one, mark it as leading + for (int j = 1; j <= numEmptyBCsBeforeLeadingBC->get(0u, 1u); j++) { + int prevBC = (iBC - j + o2::constants::lhc::LHCMaxBunches) % o2::constants::lhc::LHCMaxBunches; // Protection for BCs at small indices to check the end of the orbit + if (bcPatternE[prevBC]) { + emptyBCsBefore++; + } else { + break; // Stop counting if we hit a non BCE + } + } + if (nonBtypeBCsBefore >= numEmptyBCsBeforeLeadingBC->get(0u, 0u)) { // If we found at least numEmptyBCsBeforeLeadingBC[0] non-B BCs before this one, mark it as leading bcPatternL[iBC] = true; - totalLeadingBCs++; + totalLeadingBCs[0]++; + } + if (emptyBCsBefore >= numEmptyBCsBeforeLeadingBC->get(0u, 1u)) { // If we found at least numEmptyBCsBeforeLeadingBC[1] empty BCs before this one, mark it as leading + bcPatternLE[iBC] = true; + totalLeadingBCs[1]++; + } + } + if (bcPatternA[iBC]) { + histBcPattern[BCA][runNumber]->Fill(iBC); + } + if (bcPatternB[iBC]) { + histBcPattern[BCB][runNumber]->Fill(iBC); + if (!bcPatternL[iBC]) { + histBcPattern[BCNL][runNumber]->Fill(iBC); } + if (!bcPatternLE[iBC]) { + histBcPattern[BCNLE][runNumber]->Fill(iBC); + } + } + if (bcPatternC[iBC]) { + histBcPattern[BCC][runNumber]->Fill(iBC); + } + if (bcPatternE[iBC]) { + histBcPattern[BCE][runNumber]->Fill(iBC); + } + if (bcPatternL[iBC]) { + histBcPattern[BCL][runNumber]->Fill(iBC); + } + if (bcPatternLE[iBC]) { + histBcPattern[BCLE][runNumber]->Fill(iBC); } } - LOG(info) << "bcPatternL creation complete. Total leading BCs found: " << totalLeadingBCs; + LOG(info) << "bcPatternL creation complete. Total leading BCs found: " << totalLeadingBCs[0]; + LOG(info) << "bcPatternLE creation complete. Total leading BCs found: " << totalLeadingBCs[1]; auto runInfo = o2::parameters::AggregatedRunInfo::buildAggregatedRunInfo(o2::ccdb::BasicCCDBManager::instance(), runNumber, metadataInfo.get("LPMProductionTag")); bcSOR = runInfo.orbitSOR * nBCsPerOrbit; // first bc of the first orbit @@ -233,18 +281,9 @@ struct LumiStabilityPP { return (bc.timestamp() - mLHCIFdata->getFillNumberTime()) / 1e3 / 60; // Convert to minutes } - float getMu(double ntriggers, int nbc) - { - if (nbc == 0) { - return 0.; - } - return -std::log(1.f - ntriggers / nbc); - } - template - void fillHistograms(float timeSinceSOF, int64_t localBC, int& nTriggers) + void fillHistograms(float timeSinceSOF, int64_t localBC) { - nTriggers += 1; histBcVsTime[iTrigger][iBCCategory][runNumber]->Fill(timeSinceSOF); histBcVsBcId[iTrigger][iBCCategory][runNumber]->Fill(localBC); } @@ -257,12 +296,6 @@ struct LumiStabilityPP { std::vector> nBCsPerBcId; nBCsPerBcId.resize(nBCsPerOrbit); std::fill(&nBCsPerBcId[0][0], &nBCsPerBcId[0][0] + (static_cast(nBCsPerOrbit) * static_cast(NBCCategories)), 0); // Initialize to 0 - std::vector, NTriggerAliases>> nTriggersPerBcId; - nTriggersPerBcId.resize(nBCsPerOrbit); - std::fill(&nTriggersPerBcId[0][0][0], &nTriggersPerBcId[0][0][0] + (static_cast(nBCsPerOrbit) * static_cast(NTriggerAliases) * static_cast(NBCCategories)), 0); // Initialize to 0 - - int nTriggersPerDf[NTriggerAliases][NBCCategories]; - std::fill(&nTriggersPerDf[0][0], &nTriggersPerDf[0][0] + (static_cast(NTriggerAliases) * static_cast(NBCCategories)), 0); // Initialize to 0 double rate{-1.}; for (const auto& bc : bcs) { @@ -297,10 +330,10 @@ struct LumiStabilityPP { int localBCFDD = globalBCFDD % nBCsPerOrbit; bool isSuperLeadingBcFDD{true}, isSuperLeadingBcFT0{true}; - if (globalBCFDD - globalBCIdOfLastBCWithActivityFDD < numEmptyBCsBeforeLeadingBC) { + if (globalBCFDD - globalBCIdOfLastBCWithActivityFDD < numEmptyBCsBeforeLeadingBC->get(0u, 2u)) { isSuperLeadingBcFDD = false; // not a super-leading BC for FDD } - if (globalBC - globalBCIdOfLastBCWithActivityFT0 < numEmptyBCsBeforeLeadingBC) { + if (globalBC - globalBCIdOfLastBCWithActivityFT0 < numEmptyBCsBeforeLeadingBC->get(0u, 2u)) { isSuperLeadingBcFT0 = false; // not a super-leading BC for FT0 } @@ -330,12 +363,12 @@ struct LumiStabilityPP { } if (bcPatternB[iLocalBC]) { nBCsPerBcId[iLocalBC][BCB]++; - if (iGlobalBC - globalBCIdOfLastBCWithActivityFDD > numEmptyBCsBeforeLeadingBC) { + if (iGlobalBC - globalBCIdOfLastBCWithActivityFDD > numEmptyBCsBeforeLeadingBC->get(0u, 2u)) { nBCsPerBcId[iLocalBC][BCSLFDD]++; } else { nBCsPerBcId[iLocalBC][BCNSLFDD]++; } - if (iGlobalBC - globalBCIdOfLastBCWithActivityFT0 > numEmptyBCsBeforeLeadingBC) { + if (iGlobalBC - globalBCIdOfLastBCWithActivityFT0 > numEmptyBCsBeforeLeadingBC->get(0u, 2u)) { nBCsPerBcId[iLocalBC][BCSLFT0]++; } else { nBCsPerBcId[iLocalBC][BCNSLFT0]++; @@ -343,6 +376,9 @@ struct LumiStabilityPP { if (!bcPatternL[iLocalBC]) { nBCsPerBcId[iLocalBC][BCNL]++; } + if (!bcPatternLE[iLocalBC]) { + nBCsPerBcId[iLocalBC][BCNLE]++; + } } if (bcPatternC[iLocalBC]) { nBCsPerBcId[iLocalBC][BCC]++; @@ -353,6 +389,9 @@ struct LumiStabilityPP { if (bcPatternL[iLocalBC]) { nBCsPerBcId[iLocalBC][BCL]++; } + if (bcPatternLE[iLocalBC]) { + nBCsPerBcId[iLocalBC][BCLE]++; + } } int64_t thisTFid = (globalBC - bcSOR) / nBCsPerTF; @@ -367,91 +406,107 @@ struct LumiStabilityPP { if (doTypeBC->get(0u, iBCCategory)) { if (iTrigger == AllBCs) { if (iBCCategory == BCA && bcPatternA[localBC]) - fillHistograms(timeSinceSOF, localBC, nTriggersPerBcId[localBC][iTrigger][iBCCategory]); + fillHistograms(timeSinceSOF, localBC); if (iBCCategory == BCB && bcPatternB[localBC]) - fillHistograms(timeSinceSOF, localBC, nTriggersPerBcId[localBC][iTrigger][iBCCategory]); + fillHistograms(timeSinceSOF, localBC); if (iBCCategory == BCC && bcPatternC[localBC]) - fillHistograms(timeSinceSOF, localBC, nTriggersPerBcId[localBC][iTrigger][iBCCategory]); + fillHistograms(timeSinceSOF, localBC); if (iBCCategory == BCE && bcPatternE[localBC]) - fillHistograms(timeSinceSOF, localBC, nTriggersPerBcId[localBC][iTrigger][iBCCategory]); + fillHistograms(timeSinceSOF, localBC); if (iBCCategory == BCL && bcPatternL[localBC]) - fillHistograms(timeSinceSOF, localBC, nTriggersPerBcId[localBC][iTrigger][iBCCategory]); + fillHistograms(timeSinceSOF, localBC); + if (iBCCategory == BCLE && bcPatternLE[localBC]) + fillHistograms(timeSinceSOF, localBC); if (iBCCategory == BCSLFDD && isSuperLeadingBcFDD) - fillHistograms(timeSinceSOF, localBC, nTriggersPerBcId[localBC][iTrigger][iBCCategory]); + fillHistograms(timeSinceSOF, localBC); if (iBCCategory == BCSLFT0 && isSuperLeadingBcFT0) - fillHistograms(timeSinceSOF, localBC, nTriggersPerBcId[localBC][iTrigger][iBCCategory]); + fillHistograms(timeSinceSOF, localBC); if (iBCCategory == BCNL && !bcPatternL[localBC] && bcPatternB[localBC]) - fillHistograms(timeSinceSOF, localBC, nTriggersPerBcId[localBC][iTrigger][iBCCategory]); + fillHistograms(timeSinceSOF, localBC); + if (iBCCategory == BCNLE && !bcPatternLE[localBC] && bcPatternB[localBC]) + fillHistograms(timeSinceSOF, localBC); if (iBCCategory == BCNSLFDD && !isSuperLeadingBcFDD && bcPatternB[localBC]) - fillHistograms(timeSinceSOF, localBC, nTriggersPerBcId[localBC][iTrigger][iBCCategory]); + fillHistograms(timeSinceSOF, localBC); if (iBCCategory == BCNSLFT0 && !isSuperLeadingBcFT0 && bcPatternB[localBC]) - fillHistograms(timeSinceSOF, localBC, nTriggersPerBcId[localBC][iTrigger][iBCCategory]); + fillHistograms(timeSinceSOF, localBC); } if (iTrigger == FT0Vtx && ctpInputMask.test(2)) { if (iBCCategory == BCA && bcPatternA[localBC]) - fillHistograms(timeSinceSOF, localBC, nTriggersPerBcId[localBC][iTrigger][iBCCategory]); + fillHistograms(timeSinceSOF, localBC); if (iBCCategory == BCB && bcPatternB[localBC]) - fillHistograms(timeSinceSOF, localBC, nTriggersPerBcId[localBC][iTrigger][iBCCategory]); + fillHistograms(timeSinceSOF, localBC); if (iBCCategory == BCC && bcPatternC[localBC]) - fillHistograms(timeSinceSOF, localBC, nTriggersPerBcId[localBC][iTrigger][iBCCategory]); + fillHistograms(timeSinceSOF, localBC); if (iBCCategory == BCE && bcPatternE[localBC]) - fillHistograms(timeSinceSOF, localBC, nTriggersPerBcId[localBC][iTrigger][iBCCategory]); + fillHistograms(timeSinceSOF, localBC); if (iBCCategory == BCL && bcPatternL[localBC]) - fillHistograms(timeSinceSOF, localBC, nTriggersPerBcId[localBC][iTrigger][iBCCategory]); + fillHistograms(timeSinceSOF, localBC); + if (iBCCategory == BCLE && bcPatternLE[localBC]) + fillHistograms(timeSinceSOF, localBC); if (iBCCategory == BCSLFDD && isSuperLeadingBcFDD) - fillHistograms(timeSinceSOF, localBC, nTriggersPerBcId[localBC][iTrigger][iBCCategory]); + fillHistograms(timeSinceSOF, localBC); if (iBCCategory == BCSLFT0 && isSuperLeadingBcFT0) - fillHistograms(timeSinceSOF, localBC, nTriggersPerBcId[localBC][iTrigger][iBCCategory]); + fillHistograms(timeSinceSOF, localBC); if (iBCCategory == BCNL && !bcPatternL[localBC] && bcPatternB[localBC]) - fillHistograms(timeSinceSOF, localBC, nTriggersPerBcId[localBC][iTrigger][iBCCategory]); + fillHistograms(timeSinceSOF, localBC); + if (iBCCategory == BCNLE && !bcPatternLE[localBC] && bcPatternB[localBC]) + fillHistograms(timeSinceSOF, localBC); if (iBCCategory == BCNSLFDD && !isSuperLeadingBcFDD && bcPatternB[localBC]) - fillHistograms(timeSinceSOF, localBC, nTriggersPerBcId[localBC][iTrigger][iBCCategory]); + fillHistograms(timeSinceSOF, localBC); if (iBCCategory == BCNSLFT0 && !isSuperLeadingBcFT0 && bcPatternB[localBC]) - fillHistograms(timeSinceSOF, localBC, nTriggersPerBcId[localBC][iTrigger][iBCCategory]); + fillHistograms(timeSinceSOF, localBC); } if (iTrigger == FT0CE && ctpInputMask.test(4)) { if (iBCCategory == BCA && bcPatternA[localBC]) - fillHistograms(timeSinceSOF, localBC, nTriggersPerBcId[localBC][iTrigger][iBCCategory]); + fillHistograms(timeSinceSOF, localBC); if (iBCCategory == BCB && bcPatternB[localBC]) - fillHistograms(timeSinceSOF, localBC, nTriggersPerBcId[localBC][iTrigger][iBCCategory]); + fillHistograms(timeSinceSOF, localBC); if (iBCCategory == BCC && bcPatternC[localBC]) - fillHistograms(timeSinceSOF, localBC, nTriggersPerBcId[localBC][iTrigger][iBCCategory]); + fillHistograms(timeSinceSOF, localBC); if (iBCCategory == BCE && bcPatternE[localBC]) - fillHistograms(timeSinceSOF, localBC, nTriggersPerBcId[localBC][iTrigger][iBCCategory]); + fillHistograms(timeSinceSOF, localBC); if (iBCCategory == BCL && bcPatternL[localBC]) - fillHistograms(timeSinceSOF, localBC, nTriggersPerBcId[localBC][iTrigger][iBCCategory]); + fillHistograms(timeSinceSOF, localBC); + if (iBCCategory == BCLE && bcPatternLE[localBC]) + fillHistograms(timeSinceSOF, localBC); if (iBCCategory == BCSLFDD && isSuperLeadingBcFDD) - fillHistograms(timeSinceSOF, localBC, nTriggersPerBcId[localBC][iTrigger][iBCCategory]); + fillHistograms(timeSinceSOF, localBC); if (iBCCategory == BCSLFT0 && isSuperLeadingBcFT0) - fillHistograms(timeSinceSOF, localBC, nTriggersPerBcId[localBC][iTrigger][iBCCategory]); + fillHistograms(timeSinceSOF, localBC); if (iBCCategory == BCNL && !bcPatternL[localBC] && bcPatternB[localBC]) - fillHistograms(timeSinceSOF, localBC, nTriggersPerBcId[localBC][iTrigger][iBCCategory]); + fillHistograms(timeSinceSOF, localBC); + if (iBCCategory == BCNLE && !bcPatternLE[localBC] && bcPatternB[localBC]) + fillHistograms(timeSinceSOF, localBC); if (iBCCategory == BCNSLFDD && !isSuperLeadingBcFDD && bcPatternB[localBC]) - fillHistograms(timeSinceSOF, localBC, nTriggersPerBcId[localBC][iTrigger][iBCCategory]); + fillHistograms(timeSinceSOF, localBC); if (iBCCategory == BCNSLFT0 && !isSuperLeadingBcFT0 && bcPatternB[localBC]) - fillHistograms(timeSinceSOF, localBC, nTriggersPerBcId[localBC][iTrigger][iBCCategory]); + fillHistograms(timeSinceSOF, localBC); } if (iTrigger == FDD && ctpInputMask.test(15)) { if (iBCCategory == BCA && bcPatternA[localBCFDD]) - fillHistograms(timeSinceSOF, localBCFDD, nTriggersPerBcId[localBCFDD][iTrigger][iBCCategory]); + fillHistograms(timeSinceSOF, localBCFDD); if (iBCCategory == BCB && bcPatternB[localBCFDD]) - fillHistograms(timeSinceSOF, localBCFDD, nTriggersPerBcId[localBCFDD][iTrigger][iBCCategory]); + fillHistograms(timeSinceSOF, localBCFDD); if (iBCCategory == BCC && bcPatternC[localBCFDD]) - fillHistograms(timeSinceSOF, localBCFDD, nTriggersPerBcId[localBCFDD][iTrigger][iBCCategory]); + fillHistograms(timeSinceSOF, localBCFDD); if (iBCCategory == BCE && bcPatternE[localBCFDD]) - fillHistograms(timeSinceSOF, localBCFDD, nTriggersPerBcId[localBCFDD][iTrigger][iBCCategory]); + fillHistograms(timeSinceSOF, localBCFDD); if (iBCCategory == BCL && bcPatternL[localBCFDD]) - fillHistograms(timeSinceSOF, localBCFDD, nTriggersPerBcId[localBCFDD][iTrigger][iBCCategory]); + fillHistograms(timeSinceSOF, localBCFDD); + if (iBCCategory == BCLE && bcPatternLE[localBCFDD]) + fillHistograms(timeSinceSOF, localBCFDD); if (iBCCategory == BCSLFDD && isSuperLeadingBcFDD) - fillHistograms(timeSinceSOF, localBCFDD, nTriggersPerBcId[localBCFDD][iTrigger][iBCCategory]); + fillHistograms(timeSinceSOF, localBCFDD); if (iBCCategory == BCSLFT0 && isSuperLeadingBcFT0) - fillHistograms(timeSinceSOF, localBCFDD, nTriggersPerBcId[localBCFDD][iTrigger][iBCCategory]); + fillHistograms(timeSinceSOF, localBCFDD); if (iBCCategory == BCNL && !bcPatternL[localBCFDD] && bcPatternB[localBCFDD]) - fillHistograms(timeSinceSOF, localBCFDD, nTriggersPerBcId[localBCFDD][iTrigger][iBCCategory]); + fillHistograms(timeSinceSOF, localBCFDD); + if (iBCCategory == BCNLE && !bcPatternLE[localBCFDD] && bcPatternB[localBCFDD]) + fillHistograms(timeSinceSOF, localBCFDD); if (iBCCategory == BCNSLFDD && !isSuperLeadingBcFDD && bcPatternB[localBCFDD]) - fillHistograms(timeSinceSOF, localBCFDD, nTriggersPerBcId[localBCFDD][iTrigger][iBCCategory]); + fillHistograms(timeSinceSOF, localBCFDD); if (iBCCategory == BCNSLFT0 && !isSuperLeadingBcFT0 && bcPatternB[localBCFDD]) - fillHistograms(timeSinceSOF, localBCFDD, nTriggersPerBcId[localBCFDD][iTrigger][iBCCategory]); + fillHistograms(timeSinceSOF, localBCFDD); } } } @@ -467,16 +522,9 @@ struct LumiStabilityPP { for (int iTrigger{0}; iTrigger < NTriggerAliases; ++iTrigger) { for (int iBCCategory{0}; iBCCategory < NBCCategories; ++iBCCategory) { if (doTypeBC->get(0u, iBCCategory)) { - int nTotBCs{0}; - int nTotTriggers{0}; for (int iBcId{0}; iBcId < nBCsPerOrbit; ++iBcId) { - float muPerBcId = getMu(nTriggersPerBcId[iBcId][iTrigger][iBCCategory], nBCsPerBcId[iBcId][iBCCategory]); - histMuPerBcId[iTrigger][iBCCategory][runNumber]->Fill(iBcId, muPerBcId); - nTotBCs += nBCsPerBcId[iBcId][iBCCategory]; - nTotTriggers += nTriggersPerBcId[iBcId][iTrigger][iBCCategory]; + histBcInspectVsBcId[iTrigger][iBCCategory][runNumber]->Fill(iBcId, nBCsPerBcId[iBcId][iBCCategory]); } - float mu = getMu(nTotTriggers, nTotBCs); - histMu[iTrigger][iBCCategory][runNumber]->Fill(mu); } } } From 8bcf4a3b76d2f45519c83a24b67d4d74f859c973 Mon Sep 17 00:00:00 2001 From: ddobrigk Date: Wed, 25 Feb 2026 23:07:33 +0100 Subject: [PATCH 088/347] [Common] add deconvolution of b, nancestor (#15130) Co-authored-by: ALICE Builder --- .../Multiplicity/multGlauberNBDFitter.cxx | 59 ++++++++++++++++--- .../Tools/Multiplicity/multGlauberNBDFitter.h | 3 +- 2 files changed, 53 insertions(+), 9 deletions(-) diff --git a/Common/Tools/Multiplicity/multGlauberNBDFitter.cxx b/Common/Tools/Multiplicity/multGlauberNBDFitter.cxx index c7a669f816b..44d7cbe79de 100644 --- a/Common/Tools/Multiplicity/multGlauberNBDFitter.cxx +++ b/Common/Tools/Multiplicity/multGlauberNBDFitter.cxx @@ -384,7 +384,7 @@ Double_t multGlauberNBDFitter::ContinuousNBD(Double_t n, Double_t mu, Double_t k return F; } -void multGlauberNBDFitter::CalculateAvNpNc(TProfile* lNPartProf, TProfile* lNCollProf, TH2F* lNPart2DPlot, TH2F* lNColl2DPlot, TH1F* hPercentileMap, Double_t lLoRange, Double_t lHiRange, TH3D* lNpNcEcc, TH2F* lEcc2DPlot) +void multGlauberNBDFitter::CalculateAvNpNc(TProfile* lNPartProf, TProfile* lNCollProf, TH2F* lNPart2DPlot, TH2F* lNColl2DPlot, TH1F* hPercentileMap, Double_t lLoRange, Double_t lHiRange, TH3D* lNpNcEcc, TH2F* lEcc2DPlot, TH3D* lNpNcB, TH2F* lB2DPlot, TH2F* lNancestor2DPlot, Double_t fProbabilityCutoff) { cout << "Calculating , in centrality bins..." << endl; cout << "Range to calculate: " << lLoRange << " to " << lHiRange << endl; @@ -415,28 +415,56 @@ void multGlauberNBDFitter::CalculateAvNpNc(TProfile* lNPartProf, TProfile* lNCol } // bypass to zero for (int ibin = 0; ibin < fNNpNcPairs; ibin++) { - if (ibin % 2000 == 0) + if (ibin % 200 == 0) cout << "At NpNc pair #" << ibin << " of " << fNNpNcPairs << "..." << endl; Double_t lNAncestors0 = (Int_t)(fNpart[ibin] * ff + fNcoll[ibin] * (1.0 - ff)); Double_t lNAncestors1 = TMath::Floor(fNpart[ibin] * ff + fNcoll[ibin] * (1.0 - ff) + 0.5); Double_t lNAncestors2 = (fNpart[ibin] * ff + fNcoll[ibin] * (1.0 - ff)); - TH1D* hEccentricity = 0x0; + // define ancestors officially + Double_t lNancestors = lNAncestors0; + if (fAncestorMode == 1) + lNancestors = lNAncestors1; + if (fAncestorMode == 2) + lNancestors = lNAncestors2; + // eccentricity handling + TH1D* hEccentricity = 0x0; if (lNpNcEcc) { // locate the histogram that corresponds to the eccentricity distribution in this NpNc pair lNpNcEcc->GetXaxis()->SetRange(lNpNcEcc->GetXaxis()->FindBin(fNpart[ibin]), lNpNcEcc->GetXaxis()->FindBin(fNpart[ibin])); lNpNcEcc->GetYaxis()->SetRange(lNpNcEcc->GetYaxis()->FindBin(fNcoll[ibin]), lNpNcEcc->GetYaxis()->FindBin(fNcoll[ibin])); hEccentricity = reinterpret_cast(lNpNcEcc->Project3D("z")); hEccentricity->SetName(Form("hEccentricity_%i", ibin)); + + // normalize into unitary fractions + Double_t eccIntegral = hEccentricity->Integral(1, hEccentricity->GetNbinsX() + 1); + if (eccIntegral > 1e-6) { // no counts + hEccentricity->Scale(1. / eccIntegral); + } else { + hEccentricity->Scale(0.0); + } + } + + // impact parameter handling + TH1D* hImpactParameter = 0x0; + if (lNpNcB) { + // locate the histogram that corresponds to the eccentricity distribution in this NpNc pair + lNpNcB->GetXaxis()->SetRange(lNpNcB->GetXaxis()->FindBin(fNpart[ibin]), lNpNcB->GetXaxis()->FindBin(fNpart[ibin])); + lNpNcB->GetYaxis()->SetRange(lNpNcB->GetYaxis()->FindBin(fNcoll[ibin]), lNpNcB->GetYaxis()->FindBin(fNcoll[ibin])); + hImpactParameter = reinterpret_cast(lNpNcB->Project3D("z")); + hImpactParameter->SetName(Form("hImpactParameter_%i", ibin)); + + // normalize into unitary fractions + Double_t bIntegral = hImpactParameter->Integral(1, hImpactParameter->GetNbinsX() + 1); + if (bIntegral > 1e-6) { // no counts + hImpactParameter->Scale(1. / bIntegral); + } else { + hImpactParameter->Scale(0.0); + } } for (Long_t lMultValue = 1; lMultValue < lHiRange; lMultValue++) { - Double_t lNancestors = lNAncestors0; - if (fAncestorMode == 1) - lNancestors = lNAncestors1; - if (fAncestorMode == 2) - lNancestors = lNAncestors2; Double_t lNancestorCount = fContent[ibin]; Double_t lThisMu = (((Double_t)lNancestors)) * fMu; Double_t lThisk = (((Double_t)lNancestors)) * fk; @@ -447,11 +475,20 @@ void multGlauberNBDFitter::CalculateAvNpNc(TProfile* lNPartProf, TProfile* lNCol if (lMultValue > 1e-6) lMult = fAncestorMode != 2 ? fNBD->Eval(lMultValue) : ContinuousNBD(lMultValue, lThisMu, lThisk); Double_t lProbability = lNancestorCount * lMult; + + if (lProbability < fProbabilityCutoff) { + continue; // skip if probability of contributing too small + } + Double_t lMultValueToFill = lMultValue; if (hPercentileMap) lMultValueToFill = hPercentileMap->GetBinContent(hPercentileMap->FindBin(lMultValue)); lNPartProf->Fill(lMultValueToFill, fNpart[ibin], lProbability); lNCollProf->Fill(lMultValueToFill, fNcoll[ibin], lProbability); + if (lNancestor2DPlot) { + // fill cross-check histogram with lNancestorCount at lNancestors value + lNancestor2DPlot->Fill(lMultValueToFill, lNancestors, lProbability); + } if (lNPart2DPlot) lNPart2DPlot->Fill(lMultValueToFill, fNpart[ibin], lProbability); if (lNColl2DPlot) @@ -462,6 +499,12 @@ void multGlauberNBDFitter::CalculateAvNpNc(TProfile* lNPartProf, TProfile* lNCol lEcc2DPlot->Fill(lMultValueToFill, hEccentricity->GetBinCenter(ib), lProbability * hEccentricity->GetBinContent(ib)); } } + if (lNpNcB) { + // collapse the entire impact parameter distribution for this combo + for (int ib = 1; ib < hImpactParameter->GetNbinsX() + 1; ib++) { + lB2DPlot->Fill(lMultValueToFill, hImpactParameter->GetBinCenter(ib), lProbability * hImpactParameter->GetBinContent(ib)); + } + } } } } diff --git a/Common/Tools/Multiplicity/multGlauberNBDFitter.h b/Common/Tools/Multiplicity/multGlauberNBDFitter.h index 889398fad1a..598ef312ce9 100644 --- a/Common/Tools/Multiplicity/multGlauberNBDFitter.h +++ b/Common/Tools/Multiplicity/multGlauberNBDFitter.h @@ -78,7 +78,8 @@ class multGlauberNBDFitter : public TNamed Double_t ContinuousNBD(Double_t n, Double_t mu, Double_t k); // For estimating Npart, Ncoll in multiplicity bins - void CalculateAvNpNc(TProfile* lNPartProf, TProfile* lNCollProf, TH2F* lNPart2DPlot, TH2F* lNColl2DPlot, TH1F* hPercentileMap, Double_t lLoRange = -1, Double_t lHiRange = -1, TH3D* lNpNcEcc = 0x0, TH2F* lEcc2DPlot = 0x0); + // also viable: eccentricity, impact parameter, ancestor cross-check plot + void CalculateAvNpNc(TProfile* lNPartProf, TProfile* lNCollProf, TH2F* lNPart2DPlot, TH2F* lNColl2DPlot, TH1F* hPercentileMap, Double_t lLoRange = -1, Double_t lHiRange = -1, TH3D* lNpNcEcc = 0x0, TH2F* lEcc2DPlot = 0x0, TH3D* lNpNcB = 0x0, TH2F* lB2DPlot = 0x0, TH2F* lNancestor2DPlot = 0x0, Double_t fProbabilityCutoff = -1); // void Print(Option_t *option="") const; From cadea3ec691041605f251aa19d4dd3fc2c420f05 Mon Sep 17 00:00:00 2001 From: Gyula Bencedi Date: Wed, 25 Feb 2026 23:36:22 +0100 Subject: [PATCH 089/347] [PWGLF,PWGMM] Remove redundant process functions (#15171) --- PWGMM/Mult/Tasks/dndetaMFTPbPb.cxx | 436 +++++++++-------------------- 1 file changed, 135 insertions(+), 301 deletions(-) diff --git a/PWGMM/Mult/Tasks/dndetaMFTPbPb.cxx b/PWGMM/Mult/Tasks/dndetaMFTPbPb.cxx index 4380a7471c6..3b060924ad7 100644 --- a/PWGMM/Mult/Tasks/dndetaMFTPbPb.cxx +++ b/PWGMM/Mult/Tasks/dndetaMFTPbPb.cxx @@ -120,7 +120,7 @@ struct DndetaMFTPbPb { std::array, 4> hCollAssoc; std::array, 4> hReAssoc; - std::array, 6> hDCAMc; + std::array, 8> hDCAMc; enum OccupancyEst { TrkITS = 1, Ft0C }; @@ -147,6 +147,7 @@ struct DndetaMFTPbPb { Configurable cfgIRSource{"cfgIRSource", "ZNC hadronic", "Estimator of the interaction rate (Pb-Pb: ZNC hadronic)"}; Configurable cfgUseTrackSel{"cfgUseTrackSel", false, "Flag to apply track selection"}; Configurable cfgUseParticleSel{"cfgUseParticleSel", false, "Flag to apply particle selection"}; + Configurable cfgRemoveTrivialAssoc{"cfgRemoveTrivialAssoc", false, "Skip trivial associations"}; Configurable cfgRemoveReassigned{"cfgRemoveReassigned", false, "Remove reassgined tracks"}; Configurable cfgUseTrackParExtra{"cfgUseTrackParExtra", false, "Use table with refitted track parameters"}; Configurable cfgUseInelgt0{"cfgUseInelgt0", false, "Use INEL > 0 condition"}; @@ -921,6 +922,9 @@ struct DndetaMFTPbPb { } if (doprocessCollAssocMC) { + + registry.add("Events/hNAssocColls", "Number of times generated collisions are reconstructed; N; Counts", HistType::kTH1F, {{10, -0.5, 9.5}}); + // tracks not associated to any collision hCollAssoc[0] = qaregistry.add("TrackToColl/hNonAssocTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); // tracks associasted to a collision @@ -929,17 +933,47 @@ struct DndetaMFTPbPb { hCollAssoc[2] = qaregistry.add("TrackToColl/hGoodAssocTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); // tracks associated to the correct collision considering all ambiguous reco collisions (based on the MC collision index) hCollAssoc[3] = qaregistry.add("TrackToColl/hGoodAssocTracksAmb", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); + qaregistry.add("TrackToColl/histFracTracksFakeMcColl", "Fraction of tracks originating from fake collision; fraction; entries", {HistType::kTH1F, {{101, 0., 1.01}}}); qaregistry.add("TrackToColl/histFracGoodTracks", "Fraction of tracks originating from the correct collision; fraction; entries", {HistType::kTH1F, {{101, 0., 1.01}}}); qaregistry.add("TrackToColl/histAmbTrackNumColls", "Number of collisions associated to an ambiguous track; no. collisions; entries", {HistType::kTH1F, {{30, -0.5, 29.5}}}); + qaregistry.add("TrackToColl/histTrackNumColls", "Number of collisions associated to track; no. collisions; entries", {HistType::kTH1F, {{30, -0.5, 29.5}}}); + qaregistry.add("TrackToColl/histNonAmbTrackNumColls", "Number of collisions associated to non-ambiguous track; no. collisions; entries", {HistType::kTH1F, {{30, -0.5, 29.5}}}); qaregistry.add("TrackToColl/histAmbTrackZvtxRMS", "RMS of #it{Z}^{reco} of collisions associated to a track; RMS(#it{Z}^{reco}) (cm); entries", {HistType::kTH1F, {{100, 0., 0.5}}}); } if (doprocessReAssocMC) { + + registry.add("Events/hNReAssocColls", "Number of times generated collisions are reconstructed; N; Counts", HistType::kTH1F, {{10, -0.5, 9.5}}); + + registry.add("Events/ReAssocMCStatus", ";status", {HistType::kTH1F, {{12, 0.5, 12.5}}}); + auto hstat = registry.get(HIST("Events/ReAssocMCStatus")); + hstat->GetXaxis()->SetBinLabel(1, "All compatible"); + hstat->GetXaxis()->SetBinLabel(2, "Selected"); + hstat->GetXaxis()->SetBinLabel(3, "Has collision"); + hstat->GetXaxis()->SetBinLabel(4, "Reassigned"); + hstat->GetXaxis()->SetBinLabel(5, "Has particle"); + hstat->GetXaxis()->SetBinLabel(6, "Pos z MC cut"); + hstat->GetXaxis()->SetBinLabel(7, "Associated"); + hstat->GetXaxis()->SetBinLabel(8, "Associated true"); + hstat->GetXaxis()->SetBinLabel(9, "Associated wrong"); + hstat->GetXaxis()->SetBinLabel(10, "Reassociated"); + hstat->GetXaxis()->SetBinLabel(11, "Reassociated true"); + hstat->GetXaxis()->SetBinLabel(12, "Reassociated wrong"); + hReAssoc[0] = qaregistry.add("ReAssoc/hAssocBestTrue", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); hReAssoc[1] = qaregistry.add("ReAssoc/hAssocBestWrong", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); hReAssoc[2] = qaregistry.add("ReAssoc/hReAssocBestTrue", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); hReAssoc[3] = qaregistry.add("ReAssoc/hReAssocBestWrong", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); + + hDCAMc[0] = qaregistry.add("ReAssoc/hAssocBestTrueDCAPrim", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); + hDCAMc[1] = qaregistry.add("ReAssoc/hAssocBestTrueDCASec", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); + hDCAMc[2] = qaregistry.add("ReAssoc/hAssocBestWrongDCAPrim", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); + hDCAMc[3] = qaregistry.add("ReAssoc/hAssocBestWrongDCASec", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); + hDCAMc[4] = qaregistry.add("ReAssoc/hReAssocBestTrueDCAPrim", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); + hDCAMc[5] = qaregistry.add("ReAssoc/hReAssocBestTrueDCASec", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); + hDCAMc[6] = qaregistry.add("ReAssoc/hReAssocBestWrongDCAPrim", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); + hDCAMc[7] = qaregistry.add("ReAssoc/hReAssocBestWrongDCASec", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); } if (doprocessEfficiencyInclusive) { @@ -1018,63 +1052,6 @@ struct DndetaMFTPbPb { } } - if (doprocessDCAReassocMcInclusive || doprocessDCAReassocMcCentFT0C) { - auto hNevt = registry.add("Events/hNGenRecCollsReassoc", "Number of generated and reconstructed MC collisions", HistType::kTH1F, {{3, 0.5, 3.5}}); - hNevt->GetXaxis()->SetBinLabel(1, "Reconstructed collisions"); - hNevt->GetXaxis()->SetBinLabel(2, "Generated collisions"); - if (doprocessDCAReassocMcInclusive) { - registry.add({"Events/EvtGenRecReassoc", ";status", {HistType::kTH2F, {{3, 0.5, 3.5}, occupancyAxis}}}); - auto heff = registry.get(HIST("Events/EvtGenRecReassoc")); - auto* h = heff->GetXaxis(); - h->SetBinLabel(1, "All generated"); - h->SetBinLabel(2, "All reconstructed"); - h->SetBinLabel(3, "Selected reconstructed"); - registry.add({"Tracks/THnDCAxyBestRec", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm)", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis}}}); - registry.add({"Tracks/THnDCAxyBestRecFake", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm)", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis}}}); - registry.add({"Tracks/THnDCAxyBestGenPrim", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm)", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis}}}); - registry.add({"Tracks/THnDCAxyBestGenTruthPrim", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm)", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis}}}); - registry.add({"Tracks/THnDCAxyBestGenPrimWrongColl", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm)", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis}}}); - registry.add({"Tracks/THnDCAxyBestGenTruthPrimWrongColl", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm)", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis}}}); - - registry.add({"Tracks/BestGenPrimDeltaX", ";#Delta X (cm)", {HistType::kTH1F, {deltaZAxis}}}); - registry.add({"Tracks/BestGenSecDeltaX", ";#Delta X (cm)", {HistType::kTH1F, {deltaZAxis}}}); - registry.add({"Tracks/BestGenPrimWrongCollDeltaX", ";#Delta X (cm)", {HistType::kTH1F, {deltaZAxis}}}); - registry.add({"Tracks/BestGenSecWrongCollDeltaX", ";#Delta X (cm)", {HistType::kTH1F, {deltaZAxis}}}); - - registry.add({"Tracks/THnDCAxyBestGenSec", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm)", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis}}}); - registry.add({"Tracks/THnDCAxyBestGenTruthSec", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm)", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis}}}); - registry.add({"Tracks/THnDCAxyBestGenSecWrongColl", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm)", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis}}}); - registry.add({"Tracks/THnDCAxyBestGenTruthSecWrongColl", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm)", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis}}}); - registry.add({"Tracks/THnDCAxyBestGenSecWeak", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm)", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis}}}); - registry.add({"Tracks/THnDCAxyBestGenSecMat", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm)", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis}}}); - } - if (doprocessDCAReassocMcCentFT0C) { - registry.add({"Events/Centrality/EvtGenRecReassoc", ";status;centrality", {HistType::kTHnSparseF, {{3, 0.5, 3.5}, centralityAxis, occupancyAxis}}}); - auto heff = registry.get(HIST("Events/Centrality/EvtGenRecReassoc")); - heff->GetAxis(0)->SetBinLabel(1, "All generated"); - heff->GetAxis(0)->SetBinLabel(2, "All reconstructed"); - heff->GetAxis(0)->SetBinLabel(3, "Selected reconstructed"); - registry.add({"Tracks/Centrality/THnDCAxyBestRec", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm); centrality", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis, centralityAxis}}}); - registry.add({"Tracks/Centrality/THnDCAxyBestRecFake", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm); centrality", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis, centralityAxis}}}); - registry.add({"Tracks/Centrality/THnDCAxyBestGenPrim", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm); centrality", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis, centralityAxis}}}); - registry.add({"Tracks/Centrality/THnDCAxyBestGenTruthPrim", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm); centrality", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis, centralityAxis}}}); - registry.add({"Tracks/Centrality/THnDCAxyBestGenPrimWrongColl", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm); centrality", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis, centralityAxis}}}); - registry.add({"Tracks/Centrality/THnDCAxyBestGenTruthPrimWrongColl", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm); centrality", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis, centralityAxis}}}); - - registry.add({"Tracks/Centrality/BestGenPrimDeltaX", ";#Delta X (cm)", {HistType::kTH2F, {deltaZAxis, centralityAxis}}}); - registry.add({"Tracks/Centrality/BestGenSecDeltaX", ";#Delta X (cm)", {HistType::kTH2F, {deltaZAxis, centralityAxis}}}); - registry.add({"Tracks/Centrality/BestGenPrimWrongCollDeltaX", ";#Delta X (cm)", {HistType::kTH2F, {deltaZAxis, centralityAxis}}}); - registry.add({"Tracks/Centrality/BestGenSecWrongCollDeltaX", ";#Delta X (cm)", {HistType::kTH2F, {deltaZAxis, centralityAxis}}}); - - registry.add({"Tracks/Centrality/THnDCAxyBestGenSec", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm); centrality", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis, centralityAxis}}}); - registry.add({"Tracks/Centrality/THnDCAxyBestGenTruthSec", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm); centrality", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis, centralityAxis}}}); - registry.add({"Tracks/Centrality/THnDCAxyBestGenSecWrongColl", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm); centrality", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis, centralityAxis}}}); - registry.add({"Tracks/Centrality/THnDCAxyBestGenTruthSecWrongColl", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm); centrality", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis, centralityAxis}}}); - registry.add({"Tracks/Centrality/THnDCAxyBestGenSecWeak", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm); centrality", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis, centralityAxis}}}); - registry.add({"Tracks/Centrality/THnDCAxyBestGenSecMat", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm); centrality", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis, centralityAxis}}}); - } - } - if (doprocessAlignmentInclusive) { for (size_t j = 0; j < mftQuadrant.size(); j++) { const auto& quadrant = mftQuadrant[j]; @@ -1101,7 +1078,6 @@ struct DndetaMFTPbPb { hstat->GetXaxis()->SetBinLabel(9, "Correctly assigned true"); registry.add({"AmbTracks/hVtxzMCrec", " ; Z_{vtx} (cm)", {HistType::kTH1F, {zAxis}}}); - registry.add({"AmbTracks/DCAXY", " ; DCA_{XY} (cm)", {HistType::kTH1F, {dcaxyAxis}}}); registry.add({"AmbTracks/DCAZ", " ; DCA_{Z} (cm)", {HistType::kTH1F, {dcazAxis}}}); registry.add({"AmbTracks/DCAXYBest", " ; DCA_{XY} (cm)", {HistType::kTH1F, {dcaxyAxis}}}); @@ -2996,32 +2972,59 @@ struct DndetaMFTPbPb { aod::McCollisions const& /*mccollisions*/ ) { - for (const auto& collision : collisions) { - if (!collision.has_mcCollision()) { - continue; - } - // auto mcCollision = collision.template mcCollision_as(); - auto tracksInColl = tracksInAcc->sliceByCached(aod::fwdtrack::collisionId, collision.globalIndex(), cache); - int nTrk = 0, nFakeTrk = 0, nGoodTrk = 0; - for (const auto& track : tracksInColl) { - if (!track.has_mcParticle()) { + const auto& nRecoColls = collisions.size(); + registry.fill(HIST("Events/hNAssocColls"), 1.f, nRecoColls); + // Generated evets with >= 1 reco collisions + if (nRecoColls > CintZero) { + auto maxNcontributors = -1; + auto bestCollIndex = -1; + for (const auto& collision : collisions) { + if (!isGoodEvent(collision)) { continue; } - nTrk++; - auto particle = track.mcParticle(); + if (!collision.has_mcCollision()) { + continue; + } + if (maxNcontributors < collision.numContrib()) { + maxNcontributors = collision.numContrib(); + bestCollIndex = collision.globalIndex(); + } + } - if ((particle.mcCollisionId() != collision.mcCollision().globalIndex())) { - nFakeTrk++; + for (const auto& collision : collisions) { + if (!isGoodEvent(collision)) { + continue; + } + if (!collision.has_mcCollision()) { continue; } - if (collision.mcCollisionId() == particle.mcCollisionId()) { - nGoodTrk++; + // Select collisions with the largest number of contributors + if (bestCollIndex != collision.globalIndex()) { + continue; + } + // auto mcCollision = collision.template mcCollision_as(); + auto tracksInColl = tracksInAcc->sliceByCached(aod::fwdtrack::collisionId, collision.globalIndex(), cache); + int nTrk = 0, nFakeTrk = 0, nGoodTrk = 0; + for (const auto& track : tracksInColl) { + if (!track.has_mcParticle()) { + continue; + } + nTrk++; + auto particle = track.mcParticle(); + + if ((particle.mcCollisionId() != collision.mcCollision().globalIndex())) { + nFakeTrk++; + continue; + } + if (collision.mcCollisionId() == particle.mcCollisionId()) { + nGoodTrk++; + } } + float frac = (nTrk > 0) ? static_cast(nGoodTrk) / nTrk : -1.; + qaregistry.fill(HIST("TrackToColl/histFracGoodTracks"), frac); + float fracFake = (nTrk > 0) ? static_cast(nFakeTrk) / nTrk : -1.; + qaregistry.fill(HIST("TrackToColl/histFracTracksFakeMcColl"), fracFake); } - float frac = (nTrk > 0) ? static_cast(nGoodTrk) / nTrk : -1.; - qaregistry.fill(HIST("TrackToColl/histFracGoodTracks"), frac); - float fracFake = (nTrk > 0) ? static_cast(nFakeTrk) / nTrk : -1.; - qaregistry.fill(HIST("TrackToColl/histFracTracksFakeMcColl"), fracFake); } for (const auto& track : tracks) { @@ -3029,10 +3032,19 @@ struct DndetaMFTPbPb { if (track.has_mcParticle()) { // auto particle = track.mcParticle_as(); const auto& particle = track.mcParticle(); + + qaregistry.fill(HIST("TrackToColl/histTrackNumColls"), track.compatibleCollIds().size()); + + if (gConf.cfgRemoveTrivialAssoc) { + if (track.compatibleCollIds().empty() || (track.compatibleCollIds().size() == 1 && track.collisionId() == track.compatibleCollIds()[0])) { + qaregistry.fill(HIST("TrackToColl/histNonAmbTrackNumColls"), track.compatibleCollIds().size()); + continue; + } + } + bool isAmbiguous = (track.compatibleCollIds().size() > 1); if (isAmbiguous) { qaregistry.fill(HIST("TrackToColl/histAmbTrackNumColls"), track.compatibleCollIds().size()); - std::vector ambVtxZ{}; for (const auto& collIdx : track.compatibleCollIds()) { const auto& ambColl = collisions.rawIteratorAt(collIdx); @@ -3042,6 +3054,7 @@ struct DndetaMFTPbPb { qaregistry.fill(HIST("TrackToColl/histAmbTrackZvtxRMS"), computeRMS(ambVtxZ)); } } + float deltaX = -999.f; float deltaY = -999.f; float deltaZ = -999.f; @@ -3091,6 +3104,7 @@ struct DndetaMFTPbPb { ) { const auto& nRecoColls = collisions.size(); + registry.fill(HIST("Events/hNReAssocColls"), 1.f, nRecoColls); // Generated evets with >= 1 reco collisions if (nRecoColls > CintZero) { @@ -3119,8 +3133,6 @@ struct DndetaMFTPbPb { mapVtxYrec.emplace(collision.globalIndex(), collision.posY()); mapVtxZrec.emplace(collision.globalIndex(), collision.posZ()); mapMcCollIdPerRecColl.emplace(collision.globalIndex(), collision.mcCollisionId()); - } else { - continue; } } @@ -3138,9 +3150,11 @@ struct DndetaMFTPbPb { auto perCollisionASample = besttracks.sliceBy(perColU, collision.globalIndex()); for (auto const& atrack : perCollisionASample) { + registry.fill(HIST("Events/ReAssocMCStatus"), 1); if (!isBestTrackSelected(atrack)) { continue; } + registry.fill(HIST("Events/ReAssocMCStatus"), 2); auto itrack = atrack.template mfttrack_as(); if (!isTrackSelected(itrack)) { continue; @@ -3153,12 +3167,15 @@ struct DndetaMFTPbPb { if (!itrack.has_collision()) { continue; } + registry.fill(HIST("Events/ReAssocMCStatus"), 3); if (gConf.cfgRemoveReassigned) { if (itrack.collisionId() != atrack.bestCollisionId()) { continue; } + registry.fill(HIST("Events/ReAssocMCStatus"), 4); } if (itrack.has_mcParticle()) { + registry.fill(HIST("Events/ReAssocMCStatus"), 5); auto particle = itrack.template mcParticle_as(); auto collision = itrack.template collision_as(); auto mcCollision = particle.template mcCollision_as(); @@ -3167,6 +3184,8 @@ struct DndetaMFTPbPb { continue; } + registry.fill(HIST("Events/ReAssocMCStatus"), 6); + float deltaX = -999.f; float deltaY = -999.f; float deltaZ = -999.f; @@ -3193,17 +3212,48 @@ struct DndetaMFTPbPb { deltaY = vtxYbest - mcCollision.posY(); deltaZ = vtxZbest - mcCollision.posZ(); + const auto dcaXtruth(particle.vx() - particle.mcCollision().posX()); + const auto dcaYtruth(particle.vy() - particle.mcCollision().posY()); + const auto dcaZtruth(particle.vz() - particle.mcCollision().posZ()); + auto dcaXYtruth = std::sqrt(dcaXtruth * dcaXtruth + dcaYtruth * dcaYtruth); + if (itrack.collisionId() == atrack.bestCollisionId()) { // associated + registry.fill(HIST("Events/ReAssocMCStatus"), 7); if (collision.has_mcCollision() && mcCollIdRec == particle.mcCollisionId()) { - hReAssoc[0]->Fill(itrack.pt(), itrack.eta(), deltaX, deltaY, deltaZ); + registry.fill(HIST("Events/ReAssocMCStatus"), 8); + hReAssoc[0]->Fill(particle.pt(), particle.eta(), deltaX, deltaY, deltaZ); + if (!particle.isPhysicalPrimary()) { + hDCAMc[1]->Fill(particle.pt(), particle.eta(), atrack.bestDCAXY(), atrack.bestDCAZ(), dcaXYtruth, dcaZtruth); + } else { // Primaries + hDCAMc[0]->Fill(particle.pt(), particle.eta(), atrack.bestDCAXY(), atrack.bestDCAZ(), dcaXYtruth, dcaZtruth); + } } else { - hReAssoc[1]->Fill(itrack.pt(), itrack.eta(), deltaX, deltaY, deltaZ); + registry.fill(HIST("Events/ReAssocMCStatus"), 9); + hReAssoc[1]->Fill(particle.pt(), particle.eta(), deltaX, deltaY, deltaZ); + if (!particle.isPhysicalPrimary()) { + hDCAMc[3]->Fill(particle.pt(), particle.eta(), atrack.bestDCAXY(), atrack.bestDCAZ(), dcaXYtruth, dcaZtruth); + } else { // Primaries + hDCAMc[2]->Fill(particle.pt(), particle.eta(), atrack.bestDCAXY(), atrack.bestDCAZ(), dcaXYtruth, dcaZtruth); + } } } else { + registry.fill(HIST("Events/ReAssocMCStatus"), 10); if (collision.has_mcCollision() && mcCollIdRec == particle.mcCollisionId()) { - hReAssoc[2]->Fill(itrack.pt(), itrack.eta(), deltaX, deltaY, deltaZ); + registry.fill(HIST("Events/ReAssocMCStatus"), 11); + hReAssoc[2]->Fill(particle.pt(), particle.eta(), deltaX, deltaY, deltaZ); + if (!particle.isPhysicalPrimary()) { + hDCAMc[5]->Fill(particle.pt(), particle.eta(), atrack.bestDCAXY(), atrack.bestDCAZ(), dcaXYtruth, dcaZtruth); + } else { // Primaries + hDCAMc[4]->Fill(particle.pt(), particle.eta(), atrack.bestDCAXY(), atrack.bestDCAZ(), dcaXYtruth, dcaZtruth); + } } else { - hReAssoc[3]->Fill(itrack.pt(), itrack.eta(), deltaX, deltaY, deltaZ); + registry.fill(HIST("Events/ReAssocMCStatus"), 12); + hReAssoc[3]->Fill(particle.pt(), particle.eta(), deltaX, deltaY, deltaZ); + if (!particle.isPhysicalPrimary()) { + hDCAMc[7]->Fill(particle.pt(), particle.eta(), atrack.bestDCAXY(), atrack.bestDCAZ(), dcaXYtruth, dcaZtruth); + } else { // Primaries + hDCAMc[6]->Fill(particle.pt(), particle.eta(), atrack.bestDCAXY(), atrack.bestDCAZ(), dcaXYtruth, dcaZtruth); + } } } } @@ -3514,218 +3564,6 @@ struct DndetaMFTPbPb { PROCESS_SWITCH(DndetaMFTPbPb, processSecondariesMCCentFT0C, "Process secondaries checks (in FT0C centrality bins)", false); - template - void processDCAReassocMc(typename soa::Join const& collisions, - MC const& mcCollisions, - aod::McParticles const& /*particles*/, - BestTracksMC const& besttracks, - FiltMcMftTracks const& /*tracks*/ - ) - { - registry.fill(HIST("Events/hNGenRecCollsReassoc"), 1.f, collisions.size()); - registry.fill(HIST("Events/hNGenRecCollsReassoc"), 2.f, mcCollisions.size()); - - float cGen = -1; - if constexpr (has_reco_cent) { - float crecMin = 105.f; - for (const auto& collision : collisions) { - if (isGoodEvent(collision)) { - float c = getRecoCent(collision); - if (c < crecMin) { - crecMin = c; - } - } - } - if (cGen < 0) - cGen = crecMin; - } - float occGen = -1.; - for (const auto& collision : collisions) { - if (isGoodEvent(collision)) { - float o = getOccupancy(collision, eventCuts.occupancyEstimator); - if (o > occGen) { - occGen = o; - } - } - } - - if constexpr (has_reco_cent) { - registry.fill(HIST("Events/Centrality/EvtGenRecReassoc"), 1., cGen, occGen); - } else { - registry.fill(HIST("Events/EvtGenRecReassoc"), 1., occGen); - } - - for (const auto& collision : collisions) { - auto occ = getOccupancy(collision, eventCuts.occupancyEstimator); - float crec = getRecoCent(collision); - - if constexpr (has_reco_cent) { - registry.fill(HIST("Events/Centrality/EvtGenRecReassoc"), 2., crec, occ); - } else { - registry.fill(HIST("Events/EvtGenRecReassoc"), 2., occ); - } - - if (!isGoodEvent(collision)) { - continue; - } - - if constexpr (has_reco_cent) { - registry.fill(HIST("Events/Centrality/EvtGenRecReassoc"), 3., crec, occ); - } else { - registry.fill(HIST("Events/EvtGenRecReassoc"), 3., occ); - } - - if (!collision.has_mcCollision()) { - continue; - } - - auto perCollisionASample = besttracks.sliceBy(perColU, collision.globalIndex()); - for (auto const& atrack : perCollisionASample) { - if (!isBestTrackSelected(atrack)) { - continue; - } - auto itrack = atrack.template mfttrack_as(); - - if (!isTrackSelected(itrack)) { - continue; - } - float phi = itrack.phi(); - o2::math_utils::bringTo02Pi(phi); - if (phi < Czero || TwoPI < phi) { - continue; - } - - if (!itrack.has_collision()) { - continue; - } - if (gConf.cfgRemoveReassigned) { - if (itrack.collisionId() != atrack.bestCollisionId()) { - continue; - } - } - - if constexpr (has_reco_cent) { - registry.fill(HIST("Tracks/Centrality/THnDCAxyBestRec"), itrack.pt(), itrack.eta(), collision.posZ(), atrack.bestDCAXY(), atrack.bestDCAZ(), crec); - } else { - registry.fill(HIST("Tracks/THnDCAxyBestRec"), itrack.pt(), itrack.eta(), collision.posZ(), atrack.bestDCAXY(), atrack.bestDCAZ()); - } - - if (itrack.has_mcParticle()) { - auto particle = itrack.template mcParticle_as(); - if (!isChrgParticle(particle.pdgCode())) { - continue; - } - if (particle.eta() <= trackCuts.minEta || particle.eta() >= trackCuts.maxEta) { - continue; - } - if (gConf.cfgUseParticleSel && !isParticleSelected(particle)) { - continue; - } - - const auto dcaXtruth(particle.vx() - particle.mcCollision().posX()); - const auto dcaYtruth(particle.vy() - particle.mcCollision().posY()); - const auto dcaZtruth(particle.vz() - particle.mcCollision().posZ()); - auto dcaXYtruth = std::sqrt(dcaXtruth * dcaXtruth + dcaYtruth * dcaYtruth); - auto mcCollision = particle.template mcCollision_as(); - - if (eventCuts.useZDiffCut) { - if (std::abs(collision.posZ() - mcCollision.posZ()) > eventCuts.maxZvtxDiff) { - continue; - } - } - - if (collision.has_mcCollision() && collision.mcCollisionId() == particle.mcCollisionId()) { - if (!particle.isPhysicalPrimary()) { // Secondaries (weak decays and material) - if constexpr (has_reco_cent) { - registry.fill(HIST("Tracks/Centrality/BestGenSecDeltaX"), collision.posZ() - particle.mcCollision().posZ(), crec); - registry.fill(HIST("Tracks/Centrality/THnDCAxyBestGenSec"), particle.pt(), particle.eta(), mcCollision.posZ(), atrack.bestDCAXY(), atrack.bestDCAZ(), crec); - registry.fill(HIST("Tracks/Centrality/THnDCAxyBestGenTruthSec"), particle.pt(), particle.eta(), mcCollision.posZ(), dcaXYtruth, dcaZtruth, crec); - } else { - registry.fill(HIST("Tracks/BestGenSecDeltaX"), collision.posZ() - particle.mcCollision().posZ()); - registry.fill(HIST("Tracks/THnDCAxyBestGenSec"), particle.pt(), particle.eta(), mcCollision.posZ(), atrack.bestDCAXY(), atrack.bestDCAZ()); - registry.fill(HIST("Tracks/THnDCAxyBestGenTruthSec"), particle.pt(), particle.eta(), mcCollision.posZ(), dcaXYtruth, dcaZtruth); - } - if (particle.getProcess() == TMCProcess::kPDecay) { // Particles from decay - if constexpr (has_reco_cent) { - registry.fill(HIST("Tracks/Centrality/THnDCAxyBestGenSecWeak"), particle.pt(), particle.eta(), mcCollision.posZ(), atrack.bestDCAXY(), atrack.bestDCAZ(), crec); - } else { - registry.fill(HIST("Tracks/THnDCAxyBestGenSecWeak"), particle.pt(), particle.eta(), mcCollision.posZ(), atrack.bestDCAXY(), atrack.bestDCAZ()); - } - } else { // Particles from the material - if constexpr (has_reco_cent) { - registry.fill(HIST("Tracks/Centrality/THnDCAxyBestGenSecMat"), particle.pt(), particle.eta(), mcCollision.posZ(), atrack.bestDCAXY(), atrack.bestDCAZ(), crec); - } else { - registry.fill(HIST("Tracks/THnDCAxyBestGenSecMat"), particle.pt(), particle.eta(), mcCollision.posZ(), atrack.bestDCAXY(), atrack.bestDCAZ()); - } - } - } else { // Primaries - if constexpr (has_reco_cent) { - registry.fill(HIST("Tracks/Centrality/BestGenPrimDeltaX"), collision.posZ() - particle.mcCollision().posZ(), crec); - registry.fill(HIST("Tracks/Centrality/THnDCAxyBestGenPrim"), particle.pt(), particle.eta(), mcCollision.posZ(), atrack.bestDCAXY(), atrack.bestDCAZ(), crec); - registry.fill(HIST("Tracks/Centrality/THnDCAxyBestGenTruthPrim"), particle.pt(), particle.eta(), mcCollision.posZ(), dcaXYtruth, dcaZtruth, crec); - } else { - registry.fill(HIST("Tracks/BestGenPrimDeltaX"), collision.posZ() - particle.mcCollision().posZ()); - registry.fill(HIST("Tracks/THnDCAxyBestGenPrim"), particle.pt(), particle.eta(), mcCollision.posZ(), atrack.bestDCAXY(), atrack.bestDCAZ()); - registry.fill(HIST("Tracks/THnDCAxyBestGenTruthPrim"), particle.pt(), particle.eta(), mcCollision.posZ(), dcaXYtruth, dcaZtruth); - } - } - } else { // Wrong collision - if (!particle.isPhysicalPrimary()) { // Secondaries (weak decays and material) - if constexpr (has_reco_cent) { - registry.fill(HIST("Tracks/Centrality/BestGenSecWrongCollDeltaX"), collision.posZ() - particle.mcCollision().posZ(), crec); - registry.fill(HIST("Tracks/Centrality/THnDCAxyBestGenSecWrongColl"), particle.pt(), particle.eta(), mcCollision.posZ(), atrack.bestDCAXY(), atrack.bestDCAZ(), crec); - registry.fill(HIST("Tracks/Centrality/THnDCAxyBestGenTruthSecWrongColl"), particle.pt(), particle.eta(), mcCollision.posZ(), dcaXYtruth, dcaZtruth, crec); - } else { - registry.fill(HIST("Tracks/BestGenSecWrongCollDeltaX"), collision.posZ() - particle.mcCollision().posZ()); - registry.fill(HIST("Tracks/THnDCAxyBestGenSecWrongColl"), particle.pt(), particle.eta(), mcCollision.posZ(), atrack.bestDCAXY(), atrack.bestDCAZ()); - registry.fill(HIST("Tracks/THnDCAxyBestGenTruthSecWrongColl"), particle.pt(), particle.eta(), mcCollision.posZ(), dcaXYtruth, dcaZtruth); - } - } else { // Primaries - if constexpr (has_reco_cent) { - registry.fill(HIST("Tracks/Centrality/BestGenPrimWrongCollDeltaX"), collision.posZ() - particle.mcCollision().posZ(), crec); - registry.fill(HIST("Tracks/Centrality/THnDCAxyBestGenPrimWrongColl"), particle.pt(), particle.eta(), mcCollision.posZ(), atrack.bestDCAXY(), atrack.bestDCAZ(), crec); - registry.fill(HIST("Tracks/Centrality/THnDCAxyBestGenTruthPrimWrongColl"), particle.pt(), particle.eta(), mcCollision.posZ(), dcaXYtruth, dcaZtruth, crec); - } else { - registry.fill(HIST("Tracks/BestGenPrimWrongCollDeltaX"), collision.posZ() - particle.mcCollision().posZ()); - registry.fill(HIST("Tracks/THnDCAxyBestGenPrimWrongColl"), particle.pt(), particle.eta(), mcCollision.posZ(), atrack.bestDCAXY(), atrack.bestDCAZ()); - registry.fill(HIST("Tracks/THnDCAxyBestGenTruthPrimWrongColl"), particle.pt(), particle.eta(), mcCollision.posZ(), dcaXYtruth, dcaZtruth); - } - } - } - } else { - LOGP(debug, "No MC particle for ambiguous itrack, skip..."); - if constexpr (has_reco_cent) { - registry.fill(HIST("Tracks/Centrality/THnDCAxyBestRecFake"), itrack.pt(), itrack.eta(), collision.posZ(), atrack.bestDCAXY(), atrack.bestDCAZ(), crec); - } else { - registry.fill(HIST("Tracks/THnDCAxyBestRecFake"), itrack.pt(), itrack.eta(), collision.posZ(), atrack.bestDCAXY(), atrack.bestDCAZ()); - } - } - } - } - } - - void processDCAReassocMcInclusive(soa::Join const& collisions, - aod::McCollisions const& mccollisions, - aod::McParticles const& particles, - BestTracksMC const& besttracks, - FiltMcMftTracks const& tracks) - { - processDCAReassocMc(collisions, mccollisions, particles, besttracks, tracks); - } - - PROCESS_SWITCH(DndetaMFTPbPb, processDCAReassocMcInclusive, "Process MC DCA checks using re-association information based on BestCollisionsFwd3d table (Inclusive)", false); - - void processDCAReassocMcCentFT0C(soa::Join const& collisions, - aod::McCollisions const& mccollisions, - aod::McParticles const& particles, - BestTracksMC const& besttracks, - FiltMcMftTracks const& tracks) - { - processDCAReassocMc(collisions, mccollisions, particles, besttracks, tracks); - } - - PROCESS_SWITCH(DndetaMFTPbPb, processDCAReassocMcCentFT0C, "Process MC DCA checks using re-association information based on BestCollisionsFwd3d table (in FT0C centrality bins)", false); - template void processCorrelationwBestTracks(typename C::iterator const& collision, FiltMftTracks const& /*tracks*/, soa::SmallGroups const& besttracks) { @@ -3876,8 +3714,6 @@ struct DndetaMFTPbPb { maxNcontributors = collision.numContrib(); bestCollIndex = collision.globalIndex(); crec = getRecoCent(collision); - } else { - continue; } } @@ -4085,8 +3921,6 @@ struct DndetaMFTPbPb { if (maxNcontributors < collision.numContrib()) { maxNcontributors = collision.numContrib(); centrality = getRecoCent(collision); - } else { - continue; } gtZeroColl = true; } From 66829f3ac661c3f72989086189680eccd24a7cfb Mon Sep 17 00:00:00 2001 From: Pritam Chakraborty <47203359+prchakra@users.noreply.github.com> Date: Thu, 26 Feb 2026 00:08:59 +0100 Subject: [PATCH 090/347] [PWGCF] FemtoUniverse: Fine binning for centrality based event mixing (#15172) --- .../femtoUniversePairTaskTrackTrackSpherHarMultKtExtended.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackSpherHarMultKtExtended.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackSpherHarMultKtExtended.cxx index c046f9f0ff9..f5a4409a2e7 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackSpherHarMultKtExtended.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackSpherHarMultKtExtended.cxx @@ -191,7 +191,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { ConfigurableAxis confTempFitVarpTBins{"confTempFitVarpTBins", {20, 0.5, 4.05}, "pT binning of the pT vs. TempFitVar plot"}; /// Correlation part - ConfigurableAxis confMultBinsCent{"confMultBinsCent", {VARIABLE_WIDTH, 0.0f, 4.0f, 8.0f, 12.0f, 16.0f, 20.0f, 24.0f, 28.0f, 32.0f, 36.0f, 40.0f, 44.0f, 48.0f, 52.0f, 56.0f, 60.0f, 64.0f, 68.0f, 72.0f, 76.0f, 80.0f, 84.0f, 88.0f, 92.0f, 96.0f, 100.0f, 200.0f, 99999.f}, "Mixing bins - centrality"}; // \todo to be obtained from the hash task + ConfigurableAxis confMultBinsCent{"confMultBinsCent", {VARIABLE_WIDTH, 0.0f, 2.5f, 5.0f, 7.5f, 10.0f, 12.5f, 15.0f, 17.5f, 20.0f, 22.5f, 25.0f, 27.5f, 30.0f, 32.5f, 35.0f, 37.5f, 40.0f, 42.5f, 45.0f, 47.5f, 50.0f, 52.5f, 55.0f, 57.5f, 60.0f, 62.5f, 65.0f, 67.5f, 70.5f, 75.0f, 80.0f, 90.0f, 100.0f, 99999.f}, "Mixing bins - centrality"}; ConfigurableAxis confMultBinsMult{"confMultBinsMult", {VARIABLE_WIDTH, 0.0f, 400.0f, 800.0f, 1200.0f, 1600.0f, 2000.0f, 2500.0f, 3000.0f, 3500.0f, 4000.0f, 4500.0f, 5000.0f, 6000.0f, 7000.0f, 8000.0f, 9000.0f, 10000.0f, 11000.0f, 12000.0f, 13000.0f, 14000.0f, 15000.0f, 16000.0f, 17000.0f, 18000.0f, 99999.f}, "Mixing bins - centrality"}; ConfigurableAxis confMultKstarBins{"confMultKstarBins", {VARIABLE_WIDTH, 0.0f, 200.0f}, "Bins for kstar analysis in multiplicity or centrality bins (10 is maximum)"}; ConfigurableAxis confKtKstarBins{"confKtKstarBins", {VARIABLE_WIDTH, 0.1f, 0.2f, 0.3f, 0.4f}, "Bins for kstar analysis in kT bins"}; From a3469081b158a27fcc331748ecd0319459f9af20 Mon Sep 17 00:00:00 2001 From: SCHOTTER Romain <47983209+romainschotter@users.noreply.github.com> Date: Thu, 26 Feb 2026 03:10:36 +0100 Subject: [PATCH 091/347] [PWGLF] Add requirement "at least one track has TOF" (#15175) --- .../derivedlambdakzeroanalysis.cxx | 93 ++++++++++++++----- 1 file changed, 71 insertions(+), 22 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/derivedlambdakzeroanalysis.cxx b/PWGLF/Tasks/Strangeness/derivedlambdakzeroanalysis.cxx index 8700b91bfd0..75d73541798 100644 --- a/PWGLF/Tasks/Strangeness/derivedlambdakzeroanalysis.cxx +++ b/PWGLF/Tasks/Strangeness/derivedlambdakzeroanalysis.cxx @@ -215,6 +215,7 @@ struct derivedlambdakzeroanalysis { Configurable rejectNegITSafterburner{"rejectNegITSafterburner", false, "reject negative track formed out of afterburner ITS tracks"}; Configurable requirePosITSafterburnerOnly{"requirePosITSafterburnerOnly", false, "require positive track formed out of afterburner ITS tracks"}; Configurable requireNegITSafterburnerOnly{"requireNegITSafterburnerOnly", false, "require negative track formed out of afterburner ITS tracks"}; + Configurable requireAtLeastOneHasTOF{"requireAtLeastOneHasTOF", false, "require that at least one of daughter tracks has an associated TOF signal"}; Configurable requirePosHasTOF{"requirePosHasTOF", false, "require that positive track has an associated TOF signal. On false, TOF requirement (if any) is only applied IF the track has an associated TOF signal."}; Configurable requireNegHasTOF{"requireNegHasTOF", false, "require that negative track has an associated TOF signal. On false, TOF requirement (if any) is only applied IF the track has an associated TOF signal."}; Configurable rejectTPCsectorBoundary{"rejectTPCsectorBoundary", false, "reject tracks close to the TPC sector boundaries"}; @@ -529,15 +530,15 @@ struct derivedlambdakzeroanalysis { BITSET(maskAntiLambdaSpecific, selTPCPIDPositivePion); } // TOF PID - if (v0Selections.requirePosHasTOF || v0Selections.tofPidNsigmaCutK0Pi < 1e+5 || v0Selections.maxDeltaTimePion < 1e+6) { // safeguard for no cut + if (v0Selections.requireAtLeastOneHasTOF || v0Selections.requirePosHasTOF || v0Selections.tofPidNsigmaCutK0Pi < 1e+5 || v0Selections.maxDeltaTimePion < 1e+6) { // safeguard for no cut BITSET(maskK0ShortSpecific, selTOFNSigmaPositivePionK0Short); BITSET(maskK0ShortSpecific, selTOFDeltaTPositivePionK0Short); } - if (v0Selections.requirePosHasTOF || v0Selections.tofPidNsigmaCutLaPr < 1e+5 || v0Selections.maxDeltaTimeProton < 1e+6) { // safeguard for no cut + if (v0Selections.requireAtLeastOneHasTOF || v0Selections.requirePosHasTOF || v0Selections.tofPidNsigmaCutLaPr < 1e+5 || v0Selections.maxDeltaTimeProton < 1e+6) { // safeguard for no cut BITSET(maskLambdaSpecific, selTOFNSigmaPositiveProtonLambda); BITSET(maskLambdaSpecific, selTOFDeltaTPositiveProtonLambda); } - if (v0Selections.requirePosHasTOF || v0Selections.tofPidNsigmaCutLaPi < 1e+5 || v0Selections.maxDeltaTimePion < 1e+6) { // safeguard for no cut + if (v0Selections.requireAtLeastOneHasTOF || v0Selections.requirePosHasTOF || v0Selections.tofPidNsigmaCutLaPi < 1e+5 || v0Selections.maxDeltaTimePion < 1e+6) { // safeguard for no cut BITSET(maskAntiLambdaSpecific, selTOFNSigmaPositivePionLambda); BITSET(maskAntiLambdaSpecific, selTOFDeltaTPositivePionLambda); } @@ -555,15 +556,15 @@ struct derivedlambdakzeroanalysis { BITSET(maskAntiLambdaSpecific, selTPCPIDNegativeProton); } // TOF PID - if (v0Selections.requireNegHasTOF || v0Selections.tofPidNsigmaCutK0Pi < 1e+5 || v0Selections.maxDeltaTimePion < 1e+6) { // safeguard for no cut + if (v0Selections.requireAtLeastOneHasTOF || v0Selections.requireNegHasTOF || v0Selections.tofPidNsigmaCutK0Pi < 1e+5 || v0Selections.maxDeltaTimePion < 1e+6) { // safeguard for no cut BITSET(maskK0ShortSpecific, selTOFNSigmaNegativePionK0Short); BITSET(maskK0ShortSpecific, selTOFDeltaTNegativePionK0Short); } - if (v0Selections.requireNegHasTOF || v0Selections.tofPidNsigmaCutLaPi < 1e+5 || v0Selections.maxDeltaTimePion < 1e+6) { // safeguard for no cut + if (v0Selections.requireAtLeastOneHasTOF || v0Selections.requireNegHasTOF || v0Selections.tofPidNsigmaCutLaPi < 1e+5 || v0Selections.maxDeltaTimePion < 1e+6) { // safeguard for no cut BITSET(maskLambdaSpecific, selTOFNSigmaNegativePionLambda); BITSET(maskLambdaSpecific, selTOFDeltaTNegativePionLambda); } - if (v0Selections.requireNegHasTOF || v0Selections.tofPidNsigmaCutLaPr < 1e+5 || v0Selections.maxDeltaTimeProton < 1e+6) { // safeguard for no cut + if (v0Selections.requireAtLeastOneHasTOF || v0Selections.requireNegHasTOF || v0Selections.tofPidNsigmaCutLaPr < 1e+5 || v0Selections.maxDeltaTimeProton < 1e+6) { // safeguard for no cut BITSET(maskAntiLambdaSpecific, selTOFNSigmaNegativeProtonLambda); BITSET(maskAntiLambdaSpecific, selTOFDeltaTNegativeProtonLambda); } @@ -1314,13 +1315,25 @@ struct derivedlambdakzeroanalysis { // TOF PID in DeltaT // Positive track - if (v0Selections.requirePosHasTOF) { - if (v0.positiveHasTOF() && std::fabs(v0.posTOFDeltaTLaPr()) < v0Selections.maxDeltaTimeProton) + if (v0Selections.requirePosHasTOF || v0Selections.requireAtLeastOneHasTOF) { + if (v0.positiveHasTOF() && std::fabs(v0.posTOFDeltaTLaPr()) < v0Selections.maxDeltaTimeProton) { BITSET(bitMap, selTOFDeltaTPositiveProtonLambda); - if (v0.positiveHasTOF() && std::fabs(v0.posTOFDeltaTLaPi()) < v0Selections.maxDeltaTimePion) + if (v0Selections.requireAtLeastOneHasTOF) { // positive has a TOF hit --> no need to check for negative + BITSET(bitMap, selTOFDeltaTNegativePionLambda); + } + } + if (v0.positiveHasTOF() && std::fabs(v0.posTOFDeltaTLaPi()) < v0Selections.maxDeltaTimePion) { BITSET(bitMap, selTOFDeltaTPositivePionLambda); - if (v0.positiveHasTOF() && std::fabs(v0.posTOFDeltaTK0Pi()) < v0Selections.maxDeltaTimePion) + if (v0Selections.requireAtLeastOneHasTOF) { // positive has a TOF hit --> no need to check for negative + BITSET(bitMap, selTOFDeltaTNegativeProtonLambda); + } + } + if (v0.positiveHasTOF() && std::fabs(v0.posTOFDeltaTK0Pi()) < v0Selections.maxDeltaTimePion) { BITSET(bitMap, selTOFDeltaTPositivePionK0Short); + if (v0Selections.requireAtLeastOneHasTOF) { // positive has a TOF hit --> no need to check for negative + BITSET(bitMap, selTOFDeltaTNegativePionK0Short); + } + } } else { // only apply TOF requirement if available if (!v0.positiveHasTOF() || std::fabs(v0.posTOFDeltaTLaPr()) < v0Selections.maxDeltaTimeProton) BITSET(bitMap, selTOFDeltaTPositiveProtonLambda); @@ -1330,13 +1343,25 @@ struct derivedlambdakzeroanalysis { BITSET(bitMap, selTOFDeltaTPositivePionK0Short); } // Negative track - if (v0Selections.requireNegHasTOF) { - if (v0.negativeHasTOF() && std::fabs(v0.negTOFDeltaTLaPr()) < v0Selections.maxDeltaTimeProton) + if (v0Selections.requireNegHasTOF || v0Selections.requireAtLeastOneHasTOF) { + if (v0.negativeHasTOF() && std::fabs(v0.negTOFDeltaTLaPr()) < v0Selections.maxDeltaTimeProton) { BITSET(bitMap, selTOFDeltaTNegativeProtonLambda); - if (v0.negativeHasTOF() && std::fabs(v0.negTOFDeltaTLaPi()) < v0Selections.maxDeltaTimePion) + if (v0Selections.requireAtLeastOneHasTOF) { // negative has a TOF hit --> no need to check for positive + BITSET(bitMap, selTOFDeltaTPositivePionLambda); + } + } + if (v0.negativeHasTOF() && std::fabs(v0.negTOFDeltaTLaPi()) < v0Selections.maxDeltaTimePion) { BITSET(bitMap, selTOFDeltaTNegativePionLambda); - if (v0.negativeHasTOF() && std::fabs(v0.negTOFDeltaTK0Pi()) < v0Selections.maxDeltaTimePion) + if (v0Selections.requireAtLeastOneHasTOF) { // negative has a TOF hit --> no need to check for positive + BITSET(bitMap, selTOFDeltaTPositiveProtonLambda); + } + } + if (v0.negativeHasTOF() && std::fabs(v0.negTOFDeltaTK0Pi()) < v0Selections.maxDeltaTimePion) { BITSET(bitMap, selTOFDeltaTNegativePionK0Short); + if (v0Selections.requireAtLeastOneHasTOF) { // negative has a TOF hit --> no need to check for positive + BITSET(bitMap, selTOFDeltaTPositivePionK0Short); + } + } } else { // only apply TOF requirement if available if (!v0.negativeHasTOF() || std::fabs(v0.negTOFDeltaTLaPr()) < v0Selections.maxDeltaTimeProton) BITSET(bitMap, selTOFDeltaTNegativeProtonLambda); @@ -1348,13 +1373,25 @@ struct derivedlambdakzeroanalysis { // TOF PID in NSigma // Positive track - if (v0Selections.requirePosHasTOF) { - if (v0.positiveHasTOF() && std::fabs(v0.tofNSigmaLaPr()) < v0Selections.tofPidNsigmaCutLaPr) + if (v0Selections.requirePosHasTOF || v0Selections.requireAtLeastOneHasTOF) { + if (v0.positiveHasTOF() && std::fabs(v0.tofNSigmaLaPr()) < v0Selections.tofPidNsigmaCutLaPr) { BITSET(bitMap, selTOFNSigmaPositiveProtonLambda); - if (v0.positiveHasTOF() && std::fabs(v0.tofNSigmaALaPi()) < v0Selections.tofPidNsigmaCutLaPi) + if (v0Selections.requireAtLeastOneHasTOF) { // positive has a TOF hit --> no need to check for negative + BITSET(bitMap, selTOFNSigmaNegativePionLambda); + } + } + if (v0.positiveHasTOF() && std::fabs(v0.tofNSigmaALaPi()) < v0Selections.tofPidNsigmaCutLaPi) { BITSET(bitMap, selTOFNSigmaPositivePionLambda); - if (v0.positiveHasTOF() && std::fabs(v0.tofNSigmaK0PiPlus()) < v0Selections.tofPidNsigmaCutK0Pi) + if (v0Selections.requireAtLeastOneHasTOF) { // positive has a TOF hit --> no need to check for negative + BITSET(bitMap, selTOFNSigmaNegativeProtonLambda); + } + } + if (v0.positiveHasTOF() && std::fabs(v0.tofNSigmaK0PiPlus()) < v0Selections.tofPidNsigmaCutK0Pi) { BITSET(bitMap, selTOFNSigmaPositivePionK0Short); + if (v0Selections.requireAtLeastOneHasTOF) { // positive has a TOF hit --> no need to check for negative + BITSET(bitMap, selTOFNSigmaNegativePionK0Short); + } + } } else { // only apply TOF requirement if available if (!v0.positiveHasTOF() || std::fabs(v0.tofNSigmaLaPr()) < v0Selections.tofPidNsigmaCutLaPr) BITSET(bitMap, selTOFNSigmaPositiveProtonLambda); @@ -1364,13 +1401,25 @@ struct derivedlambdakzeroanalysis { BITSET(bitMap, selTOFNSigmaPositivePionK0Short); } // Negative track - if (v0Selections.requireNegHasTOF) { - if (v0.negativeHasTOF() && std::fabs(v0.tofNSigmaALaPr()) < v0Selections.tofPidNsigmaCutLaPr) + if (v0Selections.requireNegHasTOF || v0Selections.requireAtLeastOneHasTOF) { + if (v0.negativeHasTOF() && std::fabs(v0.tofNSigmaALaPr()) < v0Selections.tofPidNsigmaCutLaPr) { BITSET(bitMap, selTOFNSigmaNegativeProtonLambda); - if (v0.negativeHasTOF() && std::fabs(v0.tofNSigmaLaPi()) < v0Selections.tofPidNsigmaCutLaPi) + if (v0Selections.requireAtLeastOneHasTOF) { // negative has a TOF hit --> no need to check for positive + BITSET(bitMap, selTOFNSigmaPositivePionLambda); + } + } + if (v0.negativeHasTOF() && std::fabs(v0.tofNSigmaLaPi()) < v0Selections.tofPidNsigmaCutLaPi) { BITSET(bitMap, selTOFNSigmaNegativePionLambda); - if (v0.negativeHasTOF() && std::fabs(v0.tofNSigmaK0PiMinus()) < v0Selections.tofPidNsigmaCutK0Pi) + if (v0Selections.requireAtLeastOneHasTOF) { // negative has a TOF hit --> no need to check for positive + BITSET(bitMap, selTOFNSigmaPositiveProtonLambda); + } + } + if (v0.negativeHasTOF() && std::fabs(v0.tofNSigmaK0PiMinus()) < v0Selections.tofPidNsigmaCutK0Pi) { BITSET(bitMap, selTOFNSigmaNegativePionK0Short); + if (v0Selections.requireAtLeastOneHasTOF) { // negative has a TOF hit --> no need to check for positive + BITSET(bitMap, selTOFNSigmaPositivePionK0Short); + } + } } else { // only apply TOF requirement if available if (!v0.negativeHasTOF() || std::fabs(v0.tofNSigmaALaPr()) < v0Selections.tofPidNsigmaCutLaPr) BITSET(bitMap, selTOFNSigmaNegativeProtonLambda); From 10974357fccf78a0449a683f624d30c0a68a0881 Mon Sep 17 00:00:00 2001 From: mj525 <99000728+mjkim525@users.noreply.github.com> Date: Thu, 26 Feb 2026 15:54:07 +0900 Subject: [PATCH 092/347] [PWGLF] Update on Xi1820 Analysis and add the Armenteros-Qt, Alpha info. on the ResoV0s table (#15140) Co-authored-by: ALICE Action Bot --- PWGLF/DataModel/LFResonanceTables.h | 4 + .../Resonances/resonanceInitializer.cxx | 7 +- .../Resonances/resonanceModuleInitializer.cxx | 3 +- PWGLF/Tasks/Resonances/xi1820Analysis.cxx | 1035 ++++++++++------- 4 files changed, 629 insertions(+), 420 deletions(-) diff --git a/PWGLF/DataModel/LFResonanceTables.h b/PWGLF/DataModel/LFResonanceTables.h index 8a04eb4ffdd..e5d9662b89e 100644 --- a/PWGLF/DataModel/LFResonanceTables.h +++ b/PWGLF/DataModel/LFResonanceTables.h @@ -210,6 +210,8 @@ DECLARE_SOA_COLUMN(CascTransRadius, cascTransRadius, float); DECLARE_SOA_COLUMN(DecayVtxX, decayVtxX, float); //! X position of the decay vertex DECLARE_SOA_COLUMN(DecayVtxY, decayVtxY, float); //! Y position of the decay vertex DECLARE_SOA_COLUMN(DecayVtxZ, decayVtxZ, float); //! Z position of the decay vertex +DECLARE_SOA_COLUMN(Alpha, alpha, float); //! Alpha of the decay vertex +DECLARE_SOA_COLUMN(QtArm, qtarm, float); //! Armenteros Qt of the decay vertex DECLARE_SOA_COLUMN(TpcSignal10, tpcSignal10, int8_t); //! TPC signal of the track x10 DECLARE_SOA_COLUMN(DaughterTPCNSigmaPosPi10, daughterTPCNSigmaPosPi10, int8_t); //! TPC PID x10 of the positive daughter as Pion DECLARE_SOA_COLUMN(DaughterTPCNSigmaPosKa10, daughterTPCNSigmaPosKa10, int8_t); //! TPC PID x10 of the positive daughter as Kaon @@ -648,6 +650,8 @@ DECLARE_SOA_TABLE(ResoV0s, "AOD", "RESOV0", resodaughter::DecayVtxX, resodaughter::DecayVtxY, resodaughter::DecayVtxZ, + resodaughter::Alpha, + resodaughter::QtArm, // resodaughter::Pt, resodaughter::Eta, resodaughter::Phi, diff --git a/PWGLF/TableProducer/Resonances/resonanceInitializer.cxx b/PWGLF/TableProducer/Resonances/resonanceInitializer.cxx index e1c4b3cc5d8..d401153f9b6 100644 --- a/PWGLF/TableProducer/Resonances/resonanceInitializer.cxx +++ b/PWGLF/TableProducer/Resonances/resonanceInitializer.cxx @@ -793,7 +793,8 @@ struct ResonanceInitializer { v0.mLambda(), v0.mAntiLambda(), v0.mK0Short(), - v0.v0radius(), v0.x(), v0.y(), v0.z()); + v0.v0radius(), v0.x(), v0.y(), v0.z(), + v0.alpha(), v0.qtarm()); if (!cfgBypassTrackIndexFill) { resoV0V0s(v0.globalIndex()); } @@ -1016,7 +1017,7 @@ struct ResonanceInitializer { daughterPDGs = getDaughtersPDGCodes(v0mc); } while (daughters.size() > 2) { - LOGF(info, "daughters.size() is larger than 2"); + // LOGF(info, "daughters.size() is larger than 2"); daughters.pop_back(); daughterPDGs.pop_back(); } @@ -1127,7 +1128,7 @@ struct ResonanceInitializer { daughterPDGs = getDaughtersPDGCodes(cascmc); } while (daughters.size() > 2) { - LOGF(info, "daughters.size() is larger than 2"); + // LOGF(info, "daughters.size() is larger than 2"); daughters.pop_back(); daughterPDGs.pop_back(); } diff --git a/PWGLF/TableProducer/Resonances/resonanceModuleInitializer.cxx b/PWGLF/TableProducer/Resonances/resonanceModuleInitializer.cxx index 5a4bc9f2be1..358703eaf13 100644 --- a/PWGLF/TableProducer/Resonances/resonanceModuleInitializer.cxx +++ b/PWGLF/TableProducer/Resonances/resonanceModuleInitializer.cxx @@ -1037,7 +1037,8 @@ struct ResonanceDaughterInitializer { v0.mLambda(), v0.mAntiLambda(), v0.mK0Short(), - v0.v0radius(), v0.x(), v0.y(), v0.z()); + v0.v0radius(), v0.x(), v0.y(), v0.z(), + v0.alpha(), v0.qtarm()); if (!cfgBypassTrackIndexFill) { resoV0V0s(v0.globalIndex()); } diff --git a/PWGLF/Tasks/Resonances/xi1820Analysis.cxx b/PWGLF/Tasks/Resonances/xi1820Analysis.cxx index 997c68a5015..1528ac712b5 100644 --- a/PWGLF/Tasks/Resonances/xi1820Analysis.cxx +++ b/PWGLF/Tasks/Resonances/xi1820Analysis.cxx @@ -11,7 +11,8 @@ /// \file xi1820Analysis.cxx /// \brief Invariant Mass Reconstruction of Xi(1820) Resonance -/// \author Bong-Hwi Lim +/// +/// \author Bong-Hwi Lim , Minjae Kim #include "PWGLF/DataModel/LFResonanceTables.h" @@ -40,11 +41,12 @@ struct Xi1820Analysis { Preslice perResoCollisionTrack = aod::resodaughter::resoCollisionId; Preslice perResoCollisionMicroTrack = aod::resodaughter::resoCollisionId; HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + using ResoMCCols = soa::Join; // Constants static constexpr float kSmallMomentumDenominator = 1e-10f; // Small value to avoid division by zero - static constexpr float kMaxDcaToPv = 1.0f; // Maximum DCA to primary vertex - static constexpr int kPdgXi1820 = 123314; // o2-linter: disable=pdg/explicit-code (Xi(1820) PDG code not available in PDG_t or o2::constants::physics::Pdg) + static constexpr int kPdgChagedXi1820 = 123314; // o2-linter: disable=pdg/explicit-code (Xi(1820) PDG code not available in PDG_t or o2::constants::physics::Pdg) + static constexpr int kPdgXi1820Zero = 123324; // o2-linter: disable=pdg/explicit-code (Xi(1820) PDG code not available in PDG_t or o2::constants::physics::Pdg) static constexpr int kExpectedDaughters = 2; // Expected number of daughters for two-body decay // Axes @@ -52,7 +54,7 @@ struct Xi1820Analysis { ConfigurableAxis binsPtQA{"binsPtQA", {VARIABLE_WIDTH, 0.0, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0}, "pT (QA)"}; ConfigurableAxis binsCent{"binsCent", {VARIABLE_WIDTH, 0., 1., 5., 10., 30., 50., 70., 100., 110.}, "Centrality"}; - // Invariant mass range for Xi(1820) → Λ + K + // Invariant mass range for Xi(1820) to Λ + K Configurable cInvMassStart{"cInvMassStart", 1.6, "Invariant mass start (GeV/c^2)"}; Configurable cInvMassEnd{"cInvMassEnd", 2.2, "Invariant mass end (GeV/c^2)"}; Configurable cInvMassBins{"cInvMassBins", 600, "Invariant mass bins"}; @@ -72,48 +74,64 @@ struct Xi1820Analysis { Configurable cKaonITSNClusMin{"cKaonITSNClusMin", 2, "Minimum ITS clusters for kaon"}; // Kaon PID selections - Configurable cKaonTPCNSigmaMax{"cKaonTPCNSigmaMax", 3.0, "Maximum TPC NSigma for kaon (if not using pT-dependent)"}; - Configurable cKaonTOFNSigmaMax{"cKaonTOFNSigmaMax", 3.0, "Maximum TOF NSigma for kaon (if not using pT-dependent)"}; + Configurable cKaonTPCNSigmaMax{"cKaonTPCNSigmaMax", 3.5, "Maximum TPC NSigma for kaon (if not using pT-dependent)"}; + Configurable cKaonTOFNSigmaMax{"cKaonTOFNSigmaMax", 999., "Maximum TOF NSigma for kaon (if not using pT-dependent)"}; Configurable cKaonUsePtDepPID{"cKaonUsePtDepPID", false, "Use pT-dependent PID cuts"}; Configurable> cKaonPIDPtBins{"cKaonPIDPtBins", {0.0f, 0.5f, 0.8f, 2.0f, 999.0f}, "pT bin edges for PID cuts (N+1 values for N bins)"}; Configurable> cKaonTPCNSigmaCuts{"cKaonTPCNSigmaCuts", {3.0f, 3.0f, 2.0f, 2.0f}, "TPC NSigma cuts per pT bin (N values)"}; Configurable> cKaonTOFNSigmaCuts{"cKaonTOFNSigmaCuts", {3.0f, 3.0f, 3.0f, 3.0f}, "TOF NSigma cuts per pT bin (N values)"}; - Configurable> cKaonTOFRequired{"cKaonTOFRequired", {0, 0, 1, 1}, "Require TOF per pT bin (N values, 0=false, 1=true)"}; + Configurable> cKaonTOFRequired{"cKaonTOFRequired", {0, 0, 0, 0}, "Require TOF per pT bin (N values, 0=false, 1=true)"}; // V0 (Lambda) selections Configurable cV0MinCosPA{"cV0MinCosPA", 0.995, "V0 minimum pointing angle cosine"}; - Configurable cV0MaxDaughDCA{"cV0MaxDaughDCA", 1.0, "V0 daughter DCA Maximum"}; - Configurable cV0MassWindow{"cV0MassWindow", 0.005, "Mass window for Lambda selection"}; + Configurable cV0MaxDaughDCA{"cV0MaxDaughDCA", 0.5, "V0 daughter DCA Maximum"}; + Configurable cV0MassWindow{"cV0MassWindow", 0.01, "Mass window for Lambda selection (GeV/c^2)"}; Configurable cMaxV0Etacut{"cMaxV0Etacut", 0.8, "V0 maximum eta cut"}; Configurable cV0RadiusMin{"cV0RadiusMin", 0.5, "V0 decay radius min"}; Configurable cV0RadiusMax{"cV0RadiusMax", 200.0, "V0 decay radius max"}; Configurable cV0DauPosDCAtoPVMin{"cV0DauPosDCAtoPVMin", 0.05, "V0 positive daughter DCA to PV min"}; Configurable cV0DauNegDCAtoPVMin{"cV0DauNegDCAtoPVMin", 0.05, "V0 negative daughter DCA to PV min"}; Configurable cV0ProperLifetimeMax{"cV0ProperLifetimeMax", 30.0, "Lambda proper lifetime max (cm/c)"}; + Configurable cV0sCrossMassRejection{"cV0sCrossMassRejection", true, "Enable K0s mass rejection for Lambda"}; + Configurable cV0sCrossMassRejectionWindow{"cV0sCrossMassRejectionWindow", 0.005, "K0s mass rejection window for Lambda (GeV/c^2)"}; // K0s selections - Configurable cK0sMinCosPA{"cK0sMinCosPA", 0.97, "K0s minimum pointing angle cosine"}; - Configurable cK0sMaxDaughDCA{"cK0sMaxDaughDCA", 1.0, "K0s daughter DCA Maximum"}; - Configurable cK0sMassWindow{"cK0sMassWindow", 0.0043, "Mass window for K0s selection"}; + Configurable cK0sMinCosPA{"cK0sMinCosPA", 0.98, "K0s minimum pointing angle cosine"}; + Configurable cK0sMaxDaughDCA{"cK0sMaxDaughDCA", 0.5, "K0s daughter DCA Maximum"}; + Configurable cK0sMassWindow{"cK0sMassWindow", 0.025, "Mass window for K0s selection (GeV/c^2)"}; Configurable cK0sProperLifetimeMax{"cK0sProperLifetimeMax", 20.0, "K0s proper lifetime max (cm/c)"}; Configurable cK0sArmenterosQtMin{"cK0sArmenterosQtMin", 0.0, "K0s Armenteros qt min"}; - Configurable cK0sArmenterosAlphaMax{"cK0sArmenterosAlphaMax", 0.8, "K0s Armenteros alpha max"}; - Configurable cK0sDauPosDCAtoPVMin{"cK0sDauPosDCAtoPVMin", 0.1, "K0s positive daughter DCA to PV min"}; - Configurable cK0sDauNegDCAtoPVMin{"cK0sDauNegDCAtoPVMin", 0.1, "K0s negative daughter DCA to PV min"}; + Configurable cK0sArmenterosAlphaCoeff{"cK0sArmenterosAlphaCoeff", 0.2, "K0s Armenteros alpha max"}; + Configurable cK0sDauPosDCAtoPVMin{"cK0sDauPosDCAtoPVMin", 0.05, "K0s positive daughter DCA to PV min"}; + Configurable cK0sDauNegDCAtoPVMin{"cK0sDauNegDCAtoPVMin", 0.05, "K0s negative daughter DCA to PV min"}; Configurable cK0sRadiusMin{"cK0sRadiusMin", 0.5, "K0s decay radius min"}; - Configurable cK0sRadiusMax{"cK0sRadiusMax", 100.0, "K0s decay radius max"}; + Configurable cK0sRadiusMax{"cK0sRadiusMax", 200.0, "K0s decay radius max"}; Configurable cK0sCrossMassRejection{"cK0sCrossMassRejection", true, "Enable Lambda mass rejection for K0s"}; + Configurable cK0sCrossMassRejectionWindow{"cK0sCrossMassRejectionWindow", 0.01, "Lambda mass rejection window for K0s (GeV/c^2)"}; // Event Mixing Configurable nEvtMixing{"nEvtMixing", 10, "Number of events to mix"}; ConfigurableAxis cfgVtxBins{"cfgVtxBins", {VARIABLE_WIDTH, -10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}, "Mixing bins - z-vertex"}; ConfigurableAxis cfgMultBins{"cfgMultBins", {VARIABLE_WIDTH, 0.0f, 1.0f, 5.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f, 100.0f, 110.0f}, "Mixing bins - centrality"}; - // Track type selection - Configurable cUseMicroTracks{"cUseMicroTracks", false, "Use ResoMicroTracks instead of ResoTracks"}; + // Additional QA and configurations + struct : ConfigurableGroup { + Configurable cRecoINELgt0{"cRecoINELgt0", false, "Apply Reco INEL>0 event selection"}; + Configurable cConsiderPairOnly{"cConsiderPairOnly", true, "Consider only the pair of tracks for the charged K + Lambda analysis"}; + Configurable cConsiderHasV0s{"cConsiderHasV0s", true, "Consider only the pair of tracks for the K0s + Lambda analysis"}; + Configurable cUseTruthRapidity{"cUseTruthRapidity", false, "Use truth rapidity for MC generated target"}; + + Configurable cUsePtDepDCAForKaons{"cUsePtDepDCAForKaons", true, "Use pT dependent DCA cuts for kaon tracks"}; + Configurable cDCAToPVByPtFirstP0{"cDCAToPVByPtFirstP0", 0.004, "pT dependent DCA cut first parameter (cm)"}; + Configurable cDCAToPVByPtFirstExp{"cDCAToPVByPtFirstExp", 0.013, "pT dependent DCA cut second parameter (exponent)"}; + Configurable cMaxDcaToPVV0{"cMaxDcaToPVV0", 1.0, "Maximum DCA to PV for V0 candidates (cm)"}; + + Configurable cfgRapidityCut{"cfgRapidityCut", 0.5, "Rapidity cut"}; + ConfigurableAxis multNTracksAxis{"multNTracksAxis", {500, 0, 500}, "N_{tracks}"}; + + } additionalConfig; using BinningTypeVertexContributor = ColumnBinningPolicy; - BinningTypeVertexContributor colBinning{{cfgVtxBins, cfgMultBins}, true}; void init(InitContext&) { @@ -123,137 +141,181 @@ struct Xi1820Analysis { AxisSpec invMassAxis = {cInvMassBins, cInvMassStart, cInvMassEnd, "Invariant Mass (GeV/#it{c}^{2})"}; AxisSpec lambdaMassAxis = {200, 1.08, 1.16, "#Lambda mass (GeV/#it{c}^{2})"}; AxisSpec dcaAxis = {200, 0., 2.0, "DCA (cm)"}; - AxisSpec dcaxyAxis = {200, -1.0, 1.0, "DCA_{xy} (cm)"}; - AxisSpec dcazAxis = {200, -2.0, 2.0, "DCA_{z} (cm)"}; + AxisSpec dcaxyAxis = {400, -0.2, 0.2, "DCA_{xy} (cm)"}; + AxisSpec dcazAxis = {400, -0.2, 0.2, "DCA_{z} (cm)"}; AxisSpec cosPAAxis = {1000, 0.95, 1.0, "cos(PA)"}; AxisSpec radiusAxis = {200, 0, 200, "Radius (cm)"}; AxisSpec lifetimeAxis = {200, 0, 50, "Proper lifetime (cm/c)"}; AxisSpec nsigmaAxis = {100, -5.0, 5.0, "N#sigma"}; + AxisSpec armenterosAlphaAxis = {200, -1.0, 1.0, "Armenteros alpha"}; + AxisSpec armenterosQtAxis = {500, 0.0, 0.5, "Armenteros qt (GeV/c)"}; // Event QA histograms histos.add("Event/posZ", "Event vertex Z position", kTH1F, {{200, -20., 20., "V_{z} (cm)"}}); - histos.add("Event/centrality", "Event centrality distribution", kTH1F, {centAxis}); + histos.add("Event/centrality", "Event centrality distribution", kTH1D, {centAxis}); histos.add("Event/posZvsCent", "Vertex Z vs Centrality", kTH2F, {{200, -20., 20., "V_{z} (cm)"}, centAxis}); histos.add("Event/nV0s", "Number of V0s per event", kTH1F, {{200, 0., 200., "N_{V0s}"}}); - histos.add("Event/nKaons", "Number of kaons per event", kTH1F, {{200, 0., 200., "N_{kaons}"}}); - histos.add("Event/nV0sAfterCuts", "Number of V0s per event after cuts", kTH1F, {{100, 0., 100., "N_{V0s}"}}); - histos.add("Event/nKaonsAfterCuts", "Number of kaons per event after cuts", kTH1F, {{100, 0., 100., "N_{kaons}"}}); - - // Lambda QA histograms - histos.add("QAbefore/lambdaMass", "Lambda mass before cuts", kTH1F, {lambdaMassAxis}); - histos.add("QAbefore/lambdaPt", "Lambda pT before cuts", kTH1F, {ptAxisQA}); - histos.add("QAbefore/lambdaEta", "Lambda eta before cuts", kTH1F, {{100, -2.0, 2.0, "#eta"}}); - histos.add("QAbefore/lambdaCosPA", "Lambda CosPA before cuts", kTH2F, {ptAxisQA, cosPAAxis}); - histos.add("QAbefore/lambdaRadius", "Lambda radius before cuts", kTH2F, {ptAxisQA, radiusAxis}); - histos.add("QAbefore/lambdaDauDCA", "Lambda daughter DCA before cuts", kTH2F, {ptAxisQA, dcaAxis}); - histos.add("QAbefore/lambdaProperLifetime", "Lambda proper lifetime before cuts", kTH2F, {ptAxisQA, lifetimeAxis}); - histos.add("QAbefore/lambdaDauPosDCA", "Lambda positive daughter DCA before cuts", kTH2F, {ptAxisQA, dcaAxis}); - histos.add("QAbefore/lambdaDauNegDCA", "Lambda negative daughter DCA before cuts", kTH2F, {ptAxisQA, dcaAxis}); - - histos.add("QAafter/lambdaMass", "Lambda mass after cuts", kTH1F, {lambdaMassAxis}); - histos.add("QAafter/lambdaPt", "Lambda pT after cuts", kTH1F, {ptAxisQA}); - histos.add("QAafter/lambdaEta", "Lambda eta after cuts", kTH1F, {{100, -2.0, 2.0, "#eta"}}); - histos.add("QAafter/lambdaCosPA", "Lambda CosPA after cuts", kTH2F, {ptAxisQA, cosPAAxis}); - histos.add("QAafter/lambdaRadius", "Lambda radius after cuts", kTH2F, {ptAxisQA, radiusAxis}); - histos.add("QAafter/lambdaDauDCA", "Lambda daughter DCA after cuts", kTH2F, {ptAxisQA, dcaAxis}); - histos.add("QAafter/lambdaProperLifetime", "Lambda proper lifetime after cuts", kTH2F, {ptAxisQA, lifetimeAxis}); - histos.add("QAafter/lambdaDauPosDCA", "Lambda positive daughter DCA after cuts", kTH2F, {ptAxisQA, dcaAxis}); - histos.add("QAafter/lambdaDauNegDCA", "Lambda negative daughter DCA after cuts", kTH2F, {ptAxisQA, dcaAxis}); - - // Kaon QA histograms - histos.add("QAbefore/kaonPt", "Kaon pT before cuts", kTH1F, {ptAxisQA}); - histos.add("QAbefore/kaonEta", "Kaon eta before cuts", kTH1F, {{100, -2.0, 2.0, "#eta"}}); - histos.add("QAbefore/kaonDCAxy", "Kaon DCAxy before cuts", kTH2F, {ptAxisQA, dcaxyAxis}); - histos.add("QAbefore/kaonDCAz", "Kaon DCAz before cuts", kTH2F, {ptAxisQA, dcazAxis}); - histos.add("QAbefore/kaonTPCNcls", "Kaon TPC clusters before cuts", kTH1F, {{160, 0, 160, "N_{TPC clusters}"}}); - histos.add("QAbefore/kaonITSNcls", "Kaon ITS clusters before cuts", kTH1F, {{10, 0, 10, "N_{ITS clusters}"}}); - histos.add("QAbefore/kaonTPCNSigma", "Kaon TPC NSigma before cuts", kTH2F, {ptAxisQA, nsigmaAxis}); - histos.add("QAbefore/kaonTOFNSigma", "Kaon TOF NSigma before cuts", kTH2F, {ptAxisQA, nsigmaAxis}); - - histos.add("QAafter/kaonPt", "Kaon pT after cuts", kTH1F, {ptAxisQA}); - histos.add("QAafter/kaonEta", "Kaon eta after cuts", kTH1F, {{100, -2.0, 2.0, "#eta"}}); - histos.add("QAafter/kaonDCAxy", "Kaon DCAxy after cuts", kTH2F, {ptAxisQA, dcaxyAxis}); - histos.add("QAafter/kaonDCAz", "Kaon DCAz after cuts", kTH2F, {ptAxisQA, dcazAxis}); - histos.add("QAafter/kaonTPCNcls", "Kaon TPC clusters after cuts", kTH1F, {{160, 0, 160, "N_{TPC clusters}"}}); - histos.add("QAafter/kaonITSNcls", "Kaon ITS clusters after cuts", kTH1F, {{10, 0, 10, "N_{ITS clusters}"}}); - histos.add("QAafter/kaonTPCNSigma", "Kaon TPC NSigma after cuts", kTH2F, {ptAxisQA, nsigmaAxis}); - histos.add("QAafter/kaonTOFNSigma", "Kaon TOF NSigma after cuts", kTH2F, {ptAxisQA, nsigmaAxis}); + histos.add("Event/nKaons", "Number of kaons per event", kTH1F, {{200, 0., 200., "N_{kaon}"}}); + histos.add("Event/nLambdasAfterCuts", "Number of Lambdas per event after cuts", kTH1F, {{100, 0., 100., "N_{Lambda}"}}); + histos.add("Event/nKaonsAfterCuts", "Number of kaons (or K0s) per event after cuts", kTH1F, {{100, 0., 100., "N_{Kaon}"}}); + + if (doprocessDataWithTracks || doprocessDataWithMicroTracks || doprocessMCWithTracks || doprocessK0sLambda || doprocessMCK0sLambda) { + // Lambda QA histograms + histos.add("QAbefore/lambdaMass", "Lambda mass before cuts", kTH1F, {lambdaMassAxis}); + histos.add("QAbefore/lambdaMassAnti", "Anti-Lambda mass before cuts", kTH1F, {lambdaMassAxis}); + histos.add("QAbefore/lambdaPt", "Lambda pT before cuts", kTH1F, {ptAxisQA}); + histos.add("QAbefore/lambdaEta", "Lambda eta before cuts", kTH1F, {{100, -2.0, 2.0, "#eta"}}); + histos.add("QAbefore/lambdaCosPA", "Lambda CosPA before cuts", kTH2F, {ptAxisQA, cosPAAxis}); + histos.add("QAbefore/lambdaRadius", "Lambda radius before cuts", kTH2F, {ptAxisQA, radiusAxis}); + histos.add("QAbefore/lambdaDauDCA", "Lambda daughter DCA before cuts", kTH2F, {ptAxisQA, dcaAxis}); + histos.add("QAbefore/lambdaProperLifetime", "Lambda proper lifetime before cuts", kTH2F, {ptAxisQA, lifetimeAxis}); + histos.add("QAbefore/lambdaDauPosDCA", "Lambda positive daughter DCA before cuts", kTH2F, {ptAxisQA, dcaAxis}); + histos.add("QAbefore/lambdaDauNegDCA", "Lambda negative daughter DCA before cuts", kTH2F, {ptAxisQA, dcaAxis}); + histos.add("QAbefore/lambdaArmenterosPodolanski", "Lambda candidate Armenteros-Podolanski before cuts", kTH3F, {armenterosAlphaAxis, armenterosQtAxis, ptAxisQA}); + + histos.add("QAafter/lambdaMass", "Lambda mass after cuts", kTH1F, {lambdaMassAxis}); + histos.add("QAafter/lambdaMassAnti", "Anti-Lambda mass after cuts", kTH1F, {lambdaMassAxis}); + histos.add("QAafter/lambdaPt", "Lambda pT after cuts", kTH1F, {ptAxisQA}); + histos.add("QAafter/lambdaEta", "Lambda eta after cuts", kTH1F, {{100, -2.0, 2.0, "#eta"}}); + histos.add("QAafter/lambdaCosPA", "Lambda CosPA after cuts", kTH2F, {ptAxisQA, cosPAAxis}); + histos.add("QAafter/lambdaRadius", "Lambda radius after cuts", kTH2F, {ptAxisQA, radiusAxis}); + histos.add("QAafter/lambdaDauDCA", "Lambda daughter DCA after cuts", kTH2F, {ptAxisQA, dcaAxis}); + histos.add("QAafter/lambdaProperLifetime", "Lambda proper lifetime after cuts", kTH2F, {ptAxisQA, lifetimeAxis}); + histos.add("QAafter/lambdaDauPosDCA", "Lambda positive daughter DCA after cuts", kTH2F, {ptAxisQA, dcaAxis}); + histos.add("QAafter/lambdaDauNegDCA", "Lambda negative daughter DCA after cuts", kTH2F, {ptAxisQA, dcaAxis}); + histos.add("QAafter/lambdaArmenterosPodolanski", "Lambda candidate Armenteros-Podolanski after cuts", kTH3F, {armenterosAlphaAxis, armenterosQtAxis, ptAxisQA}); + } + + if (doprocessDataWithTracks || doprocessDataWithMicroTracks || doprocessMCWithTracks) { + // Kaon QA histograms + histos.add("QAbefore/kaonPt", "Kaon pT before cuts", kTH1F, {ptAxisQA}); + histos.add("QAbefore/kaonEta", "Kaon eta before cuts", kTH1F, {{100, -2.0, 2.0, "#eta"}}); + histos.add("QAbefore/kaonDCAxy", "Kaon DCAxy before cuts", kTH2F, {ptAxisQA, dcaxyAxis}); + histos.add("QAbefore/kaonDCAz", "Kaon DCAz before cuts", kTH2F, {ptAxisQA, dcazAxis}); + histos.add("QAbefore/kaonTPCNcls", "Kaon TPC clusters before cuts", kTH1F, {{160, 0, 160, "N_{TPC clusters}"}}); + histos.add("QAbefore/kaonITSNcls", "Kaon ITS clusters before cuts", kTH1F, {{10, 0, 10, "N_{ITS clusters}"}}); + histos.add("QAbefore/kaonTPCNSigma", "Kaon TPC NSigma before cuts", kTH2F, {ptAxisQA, nsigmaAxis}); + histos.add("QAbefore/kaonTOFNSigma", "Kaon TOF NSigma before cuts", kTH2F, {ptAxisQA, nsigmaAxis}); + + histos.add("QAafter/kaonPt", "Kaon pT after cuts", kTH1F, {ptAxisQA}); + histos.add("QAafter/kaonEta", "Kaon eta after cuts", kTH1F, {{100, -2.0, 2.0, "#eta"}}); + histos.add("QAafter/kaonDCAxy", "Kaon DCAxy after cuts", kTH2F, {ptAxisQA, dcaxyAxis}); + histos.add("QAafter/kaonDCAz", "Kaon DCAz after cuts", kTH2F, {ptAxisQA, dcazAxis}); + histos.add("QAafter/kaonTPCNcls", "Kaon TPC clusters after cuts", kTH1F, {{160, 0, 160, "N_{TPC clusters}"}}); + histos.add("QAafter/kaonITSNcls", "Kaon ITS clusters after cuts", kTH1F, {{10, 0, 10, "N_{ITS clusters}"}}); + histos.add("QAafter/kaonTPCNSigma", "Kaon TPC NSigma after cuts", kTH2F, {ptAxisQA, nsigmaAxis}); + histos.add("QAafter/kaonTOFNSigma", "Kaon TOF NSigma after cuts", kTH2F, {ptAxisQA, nsigmaAxis}); + } // Resonance histograms - 4 combinations // K+ Lambda - histos.add("xi1820/kplus_lambda/hInvMassKplusLambda", "Invariant mass of Xi(1820) → K^{+} + #Lambda", kTH1F, {invMassAxis}); - histos.add("xi1820/kplus_lambda/hInvMassKplusLambda_Mix", "Mixed event Invariant mass of Xi(1820) → K^{+} + #Lambda", kTH1F, {invMassAxis}); - histos.add("xi1820/kplus_lambda/hMassPtCentKplusLambda", "Xi(1820) mass vs pT vs cent (K^{+}#Lambda)", kTH3F, {invMassAxis, ptAxis, centAxis}); - histos.add("xi1820/kplus_lambda/hMassPtCentKplusLambda_Mix", "Mixed event Xi(1820) mass vs pT vs cent (K^{+}#Lambda)", kTH3F, {invMassAxis, ptAxis, centAxis}); - - // K+ Anti-Lambda - histos.add("xi1820/kplus_antilambda/hInvMassKplusAntiLambda", "Invariant mass of Xi(1820) → K^{+} + #bar{#Lambda}", kTH1F, {invMassAxis}); - histos.add("xi1820/kplus_antilambda/hInvMassKplusAntiLambda_Mix", "Mixed event Invariant mass of Xi(1820) → K^{+} + #bar{#Lambda}", kTH1F, {invMassAxis}); - histos.add("xi1820/kplus_antilambda/hMassPtCentKplusAntiLambda", "Xi(1820) mass vs pT vs cent (K^{+}#bar{#Lambda})", kTH3F, {invMassAxis, ptAxis, centAxis}); - histos.add("xi1820/kplus_antilambda/hMassPtCentKplusAntiLambda_Mix", "Mixed event Xi(1820) mass vs pT vs cent (K^{+}#bar{#Lambda})", kTH3F, {invMassAxis, ptAxis, centAxis}); - - // K- Lambda - histos.add("xi1820/kminus_lambda/hInvMassKminusLambda", "Invariant mass of Xi(1820) → K^{-} + #Lambda", kTH1F, {invMassAxis}); - histos.add("xi1820/kminus_lambda/hInvMassKminusLambda_Mix", "Mixed event Invariant mass of Xi(1820) → K^{-} + #Lambda", kTH1F, {invMassAxis}); - histos.add("xi1820/kminus_lambda/hMassPtCentKminusLambda", "Xi(1820) mass vs pT vs cent (K^{-}#Lambda)", kTH3F, {invMassAxis, ptAxis, centAxis}); - histos.add("xi1820/kminus_lambda/hMassPtCentKminusLambda_Mix", "Mixed event Xi(1820) mass vs pT vs cent (K^{-}#Lambda)", kTH3F, {invMassAxis, ptAxis, centAxis}); - - // K- Anti-Lambda - histos.add("xi1820/kminus_antilambda/hInvMassKminusAntiLambda", "Invariant mass of Xi(1820) → K^{-} + #bar{#Lambda}", kTH1F, {invMassAxis}); - histos.add("xi1820/kminus_antilambda/hInvMassKminusAntiLambda_Mix", "Mixed event Invariant mass of Xi(1820) → K^{-} + #bar{#Lambda}", kTH1F, {invMassAxis}); - histos.add("xi1820/kminus_antilambda/hMassPtCentKminusAntiLambda", "Xi(1820) mass vs pT vs cent (K^{-}#bar{#Lambda})", kTH3F, {invMassAxis, ptAxis, centAxis}); - histos.add("xi1820/kminus_antilambda/hMassPtCentKminusAntiLambda_Mix", "Mixed event Xi(1820) mass vs pT vs cent (K^{-}#bar{#Lambda})", kTH3F, {invMassAxis, ptAxis, centAxis}); + if (doprocessDataWithTracks || doprocessDataWithMicroTracks || doprocessMixedEventWithTracks || doprocessMixedEventWithMicroTracks || doprocessMCWithTracks) { + histos.add("xi1820/kplus_lambda/hInvMassKplusLambda", "Invariant mass of K^{+} + #Lambda", kTH1F, {invMassAxis}); + histos.add("xi1820/kplus_lambda/hInvMassKplusLambda_Mix", "Mixed event Invariant mass of K^{+} + #Lambda", kTH1F, {invMassAxis}); + histos.add("xi1820/kplus_lambda/hMassPtCentKplusLambda", "K^{+} + #Lambda mass vs pT vs cent", kTH3D, {invMassAxis, ptAxis, centAxis}); + histos.add("xi1820/kplus_lambda/hMassPtCentKplusLambda_Mix", "Mixed event K^{+} + #Lambda mass vs pT vs cent", kTH3D, {invMassAxis, ptAxis, centAxis}); + + // K+ Anti-Lambda + histos.add("xi1820/kplus_antilambda/hInvMassKplusAntiLambda", "Invariant mass of K^{+} + #bar{#Lambda}", kTH1F, {invMassAxis}); + histos.add("xi1820/kplus_antilambda/hInvMassKplusAntiLambda_Mix", "Mixed event Invariant mass of K^{+} + #bar{#Lambda}", kTH1F, {invMassAxis}); + histos.add("xi1820/kplus_antilambda/hMassPtCentKplusAntiLambda", "K^{+} + #bar{#Lambda} mass vs pT vs cent", kTH3D, {invMassAxis, ptAxis, centAxis}); + histos.add("xi1820/kplus_antilambda/hMassPtCentKplusAntiLambda_Mix", "Mixed event K^{+} + #bar{#Lambda} mass vs pT vs cent", kTH3D, {invMassAxis, ptAxis, centAxis}); + + // K- Lambda + histos.add("xi1820/kminus_lambda/hInvMassKminusLambda", "Invariant mass of K^{-} + #Lambda", kTH1F, {invMassAxis}); + histos.add("xi1820/kminus_lambda/hInvMassKminusLambda_Mix", "Mixed event Invariant mass of K^{-} + #Lambda", kTH1F, {invMassAxis}); + histos.add("xi1820/kminus_lambda/hMassPtCentKminusLambda", "K^{-} + #Lambda mass vs pT vs cent", kTH3D, {invMassAxis, ptAxis, centAxis}); + histos.add("xi1820/kminus_lambda/hMassPtCentKminusLambda_Mix", "Mixed event K^{-} + #Lambda mass vs pT vs cent", kTH3D, {invMassAxis, ptAxis, centAxis}); + + // K- Anti-Lambda + histos.add("xi1820/kminus_antilambda/hInvMassKminusAntiLambda", "Invariant mass of K^{-} + #bar{#Lambda}", kTH1F, {invMassAxis}); + histos.add("xi1820/kminus_antilambda/hInvMassKminusAntiLambda_Mix", "Mixed event Invariant mass of K^{-} + #bar{#Lambda}", kTH1F, {invMassAxis}); + histos.add("xi1820/kminus_antilambda/hMassPtCentKminusAntiLambda", "K^{-} + #bar{#Lambda} mass vs pT vs cent", kTH3D, {invMassAxis, ptAxis, centAxis}); + histos.add("xi1820/kminus_antilambda/hMassPtCentKminusAntiLambda_Mix", "Mixed event K^{-} + #bar{#Lambda} mass vs pT vs cent", kTH3D, {invMassAxis, ptAxis, centAxis}); + } + + // MC Reco histograms for charged K + Lambda channel + if (doprocessMCWithTracks) { + histos.add("MC/kplus_antilambda/hMCRecoInvMassKplusAntiLambda", "Invariant mass of Xi(1820) to K^{-} + #Lambda (MC Reco)", kTH1F, {invMassAxis}); + histos.add("MC/kplus_antilambda/hMCRecoMassPtCentKplusAntiLambda", "Xi(1820) mass vs pT vs cent (K^{-} + #Lambda) (MC Reco)", kTHnSparseD, {invMassAxis, ptAxis, centAxis, ptAxis}); + + histos.add("MC/kminus_antilambda/hMCRecoInvMassKminusAntiLambda", "Invariant mass of Xi(1820) to K^{+} + #bar{#Lambda} (MC Reco)", kTH1F, {invMassAxis}); + histos.add("MC/kminus_antilambda/hMCRecoMassPtCentKminusAntiLambda", "Xi(1820) mass vs pT vs cent (K^{+} + #bar{#Lambda}) (MC Reco)", kTHnSparseD, {invMassAxis, ptAxis, centAxis, ptAxis}); + } + + // K0s QA histograms + if (doprocessK0sLambda || doprocessMCK0sLambda) { + histos.add("QAbefore/k0sMass", "K0s mass before cuts", kTH1F, {{100, 0.4, 0.6, "K^{0}_{S} mass (GeV/#it{c}^{2})"}}); + histos.add("QAbefore/k0sPt", "K0s pT before cuts", kTH1F, {ptAxisQA}); + histos.add("QAbefore/k0sEta", "K0s eta before cuts", kTH1F, {{100, -2.0, 2.0, "#eta"}}); + histos.add("QAbefore/k0sCosPA", "K0s CosPA before cuts", kTH2F, {ptAxisQA, cosPAAxis}); + histos.add("QAbefore/k0sRadius", "K0s radius before cuts", kTH2F, {ptAxisQA, radiusAxis}); + histos.add("QAbefore/k0sDauDCA", "K0s daughter DCA before cuts", kTH2F, {ptAxisQA, dcaAxis}); + histos.add("QAbefore/k0sProperLifetime", "K0s proper lifetime before cuts", kTH2F, {ptAxisQA, lifetimeAxis}); + histos.add("QAbefore/k0sArmenterosPodolanski", "K0s candidate Armenteros-Podolanski before cuts", kTH3F, {armenterosAlphaAxis, armenterosQtAxis, ptAxisQA}); + + histos.add("QAafter/k0sMass", "K0s mass after cuts", kTH1F, {{100, 0.4, 0.6, "K^{0}_{S} mass (GeV/#it{c}^{2})"}}); + histos.add("QAafter/k0sPt", "K0s pT after cuts", kTH1F, {ptAxisQA}); + histos.add("QAafter/k0sEta", "K0s eta after cuts", kTH1F, {{100, -2.0, 2.0, "#eta"}}); + histos.add("QAafter/k0sCosPA", "K0s CosPA after cuts", kTH2F, {ptAxisQA, cosPAAxis}); + histos.add("QAafter/k0sRadius", "K0s radius after cuts", kTH2F, {ptAxisQA, radiusAxis}); + histos.add("QAafter/k0sDauDCA", "K0s daughter DCA after cuts", kTH2F, {ptAxisQA, dcaAxis}); + histos.add("QAafter/k0sProperLifetime", "K0s proper lifetime after cuts", kTH2F, {ptAxisQA, lifetimeAxis}); + histos.add("QAafter/k0sArmenterosPodolanski", "K0s candidate Armenteros-Podolanski after cuts", kTH3F, {armenterosAlphaAxis, armenterosQtAxis, ptAxisQA}); + } // K0s + Lambda - histos.add("xi1820/k0s_lambda/hInvMassK0sLambda", "Invariant mass of Xi(1820) → K^{0}_{S} + #Lambda", kTH1F, {invMassAxis}); - histos.add("xi1820/k0s_lambda/hInvMassK0sLambda_Mix", "Mixed event Invariant mass of Xi(1820) → K^{0}_{S} + #Lambda", kTH1F, {invMassAxis}); - histos.add("xi1820/k0s_lambda/hMassPtCentK0sLambda", "Xi(1820) mass vs pT vs cent (K^{0}_{S}#Lambda)", kTH3F, {invMassAxis, ptAxis, centAxis}); - histos.add("xi1820/k0s_lambda/hMassPtCentK0sLambda_Mix", "Mixed event Xi(1820) mass vs pT vs cent (K^{0}_{S}#Lambda)", kTH3F, {invMassAxis, ptAxis, centAxis}); + if (doprocessK0sLambda || doprocessK0sLambdaMixedEvent || doprocessMCK0sLambda) { + histos.add("xi1820/k0s_lambda/hInvMassK0sLambda", "Invariant mass of Xi(1820) to K^{0}_{S} + #Lambda", kTH1F, {invMassAxis}); + histos.add("xi1820/k0s_lambda/hInvMassK0sLambda_Mix", "Mixed event Invariant mass of Xi(1820) to K^{0}_{S} + #Lambda", kTH1F, {invMassAxis}); + histos.add("xi1820/k0s_lambda/hMassPtCentK0sLambda", "Xi(1820) mass vs pT vs cent (K^{0}_{S}#Lambda)", kTH3D, {invMassAxis, ptAxis, centAxis}); + histos.add("xi1820/k0s_lambda/hMassPtCentK0sLambda_Mix", "Mixed event Xi(1820) mass vs pT vs cent (K^{0}_{S}#Lambda)", kTH3D, {invMassAxis, ptAxis, centAxis}); + + // K0s + Anti-Lambda + histos.add("xi1820/k0s_antilambda/hInvMassK0sAntiLambda", "Invariant mass of Xi(1820) to K^{0}_{S} + #bar{#Lambda}", kTH1F, {invMassAxis}); + histos.add("xi1820/k0s_antilambda/hInvMassK0sAntiLambda_Mix", "Mixed event Invariant mass of Xi(1820) to K^{0}_{S} + #bar{#Lambda}", kTH1F, {invMassAxis}); + histos.add("xi1820/k0s_antilambda/hMassPtCentK0sAntiLambda", "Xi(1820) mass vs pT vs cent (K^{0}_{S}#bar{#Lambda})", kTH3D, {invMassAxis, ptAxis, centAxis}); + histos.add("xi1820/k0s_antilambda/hMassPtCentK0sAntiLambda_Mix", "Mixed event Xi(1820) mass vs pT vs cent (K^{0}_{S}#bar{#Lambda})", kTH3D, {invMassAxis, ptAxis, centAxis}); + } + + if (doprocessMCK0sLambda) { + histos.add("MC/k0s_lambda/hMCRecoInvMassK0sLambda", "Invariant mass of Xi(1820) to K^{0}_{S} + #Lambda (MC Reco)", kTH1F, {invMassAxis}); + histos.add("MC/k0s_lambda/hMCRecoMassPtCentK0sLambda", "Xi(1820) mass vs pT vs cent (K^{0}_{S}#Lambda) (MC Reco)", kTHnSparseD, {invMassAxis, ptAxis, centAxis, ptAxis}); + + histos.add("MC/k0s_antilambda/hMCRecoInvMassK0sAntiLambda", "Invariant mass of Xi(1820) to K^{0}_{S} + #bar{#Lambda} (MC Reco)", kTH1F, {invMassAxis}); + histos.add("MC/k0s_antilambda/hMCRecoMassPtCentK0sAntiLambda", "Xi(1820) mass vs pT vs cent (K^{0}_{S}#bar{#Lambda}) (MC Reco)", kTHnSparseD, {invMassAxis, ptAxis, centAxis, ptAxis}); + } - // K0s + Anti-Lambda - histos.add("xi1820/k0s_antilambda/hInvMassK0sAntiLambda", "Invariant mass of Xi(1820) → K^{0}_{S} + #bar{#Lambda}", kTH1F, {invMassAxis}); - histos.add("xi1820/k0s_antilambda/hInvMassK0sAntiLambda_Mix", "Mixed event Invariant mass of Xi(1820) → K^{0}_{S} + #bar{#Lambda}", kTH1F, {invMassAxis}); - histos.add("xi1820/k0s_antilambda/hMassPtCentK0sAntiLambda", "Xi(1820) mass vs pT vs cent (K^{0}_{S}#bar{#Lambda})", kTH3F, {invMassAxis, ptAxis, centAxis}); - histos.add("xi1820/k0s_antilambda/hMassPtCentK0sAntiLambda_Mix", "Mixed event Xi(1820) mass vs pT vs cent (K^{0}_{S}#bar{#Lambda})", kTH3F, {invMassAxis, ptAxis, centAxis}); + if (doprocessMCGen) { + histos.add("multQA/h2MultCentMC", "Multiplicity vs Centrality MC", HistType::kTH2D, {centAxis, additionalConfig.multNTracksAxis}); + // MC truth invariant mass vs pT (2D) + histos.add("MC/hMCGenPtCentMultKminusLambda", "MC Truth Mass vs pT K^{-}#Lambda", kTH3D, {ptAxis, centAxis, additionalConfig.multNTracksAxis}); + histos.add("MC/hMCGenPtCentMultKplusAntiLambda", "MC Truth Mass vs pT K^{+}#bar{#Lambda}", kTH3D, {ptAxis, centAxis, additionalConfig.multNTracksAxis}); + histos.add("MC/hMCGenPtCentMultK0sLambda", "MC Truth Mass vs pT K^{0}_{S}#Lambda", kTH3D, {ptAxis, centAxis, additionalConfig.multNTracksAxis}); + histos.add("MC/hMCGenPtCentMultK0sAntiLambda", "MC Truth Mass vs pT K^{0}_{S}#bar{#Lambda}", kTH3D, {ptAxis, centAxis, additionalConfig.multNTracksAxis}); + } // MC truth histograms AxisSpec etaAxis = {100, -2.0, 2.0, "#eta"}; AxisSpec rapidityAxis = {100, -2.0, 2.0, "y"}; - histos.add("MC/hMCGenXi1820Pt", "MC Generated Xi(1820) pT", kTH1F, {ptAxis}); - histos.add("MC/hMCGenXi1820PtEta", "MC Generated Xi(1820) pT vs eta", kTH2F, {ptAxis, etaAxis}); - histos.add("MC/hMCGenXi1820Y", "MC Generated Xi(1820) rapidity", kTH1F, {rapidityAxis}); - histos.add("MC/hMCRecXi1820Pt", "MC Reconstructed Xi(1820) pT", kTH1F, {ptAxis}); - histos.add("MC/hMCRecXi1820PtEta", "MC Reconstructed Xi(1820) pT vs eta", kTH2F, {ptAxis, etaAxis}); - - // MC truth invariant mass (from MC particles) - histos.add("MC/hMCTruthInvMassKplusLambda", "MC Truth Inv Mass K^{+}#Lambda", kTH1F, {invMassAxis}); - histos.add("MC/hMCTruthInvMassKminusAntiLambda", "MC Truth Inv Mass K^{-}#bar{#Lambda}", kTH1F, {invMassAxis}); - histos.add("MC/hMCTruthInvMassK0sLambda", "MC Truth Inv Mass K^{0}_{S}#Lambda", kTH1F, {invMassAxis}); - histos.add("MC/hMCTruthInvMassK0sAntiLambda", "MC Truth Inv Mass K^{0}_{S}#bar{#Lambda}", kTH1F, {invMassAxis}); - - // MC truth invariant mass vs pT (2D) - histos.add("MC/hMCTruthMassPtKplusLambda", "MC Truth Mass vs pT K^{+}#Lambda", kTH2F, {invMassAxis, ptAxis}); - histos.add("MC/hMCTruthMassPtKminusAntiLambda", "MC Truth Mass vs pT K^{-}#bar{#Lambda}", kTH2F, {invMassAxis, ptAxis}); - histos.add("MC/hMCTruthMassPtK0sLambda", "MC Truth Mass vs pT K^{0}_{S}#Lambda", kTH2F, {invMassAxis, ptAxis}); - histos.add("MC/hMCTruthMassPtK0sAntiLambda", "MC Truth Mass vs pT K^{0}_{S}#bar{#Lambda}", kTH2F, {invMassAxis, ptAxis}); - - // K0s QA histograms - histos.add("QAbefore/k0sMass", "K0s mass before cuts", kTH1F, {{100, 0.4, 0.6, "K^{0}_{S} mass (GeV/#it{c}^{2})"}}); - histos.add("QAbefore/k0sPt", "K0s pT before cuts", kTH1F, {ptAxisQA}); - histos.add("QAbefore/k0sEta", "K0s eta before cuts", kTH1F, {{100, -2.0, 2.0, "#eta"}}); - histos.add("QAbefore/k0sCosPA", "K0s CosPA before cuts", kTH2F, {ptAxisQA, cosPAAxis}); - histos.add("QAbefore/k0sRadius", "K0s radius before cuts", kTH2F, {ptAxisQA, radiusAxis}); - histos.add("QAbefore/k0sDauDCA", "K0s daughter DCA before cuts", kTH2F, {ptAxisQA, dcaAxis}); - histos.add("QAbefore/k0sProperLifetime", "K0s proper lifetime before cuts", kTH2F, {ptAxisQA, lifetimeAxis}); - - histos.add("QAafter/k0sMass", "K0s mass after cuts", kTH1F, {{100, 0.4, 0.6, "K^{0}_{S} mass (GeV/#it{c}^{2})"}}); - histos.add("QAafter/k0sPt", "K0s pT after cuts", kTH1F, {ptAxisQA}); - histos.add("QAafter/k0sEta", "K0s eta after cuts", kTH1F, {{100, -2.0, 2.0, "#eta"}}); - histos.add("QAafter/k0sCosPA", "K0s CosPA after cuts", kTH2F, {ptAxisQA, cosPAAxis}); - histos.add("QAafter/k0sRadius", "K0s radius after cuts", kTH2F, {ptAxisQA, radiusAxis}); - histos.add("QAafter/k0sDauDCA", "K0s daughter DCA after cuts", kTH2F, {ptAxisQA, dcaAxis}); - histos.add("QAafter/k0sProperLifetime", "K0s proper lifetime after cuts", kTH2F, {ptAxisQA, lifetimeAxis}); + if (doprocessMCTruth) { + histos.add("MC/hMCTruthXi1820Pt", "MC Generated Xi(1820) pT", kTH1F, {ptAxis}); + histos.add("MC/hMCTruthXi1820PtEta", "MC Generated Xi(1820) pT vs eta", kTH2F, {ptAxis, etaAxis}); + histos.add("MC/hMCTruthXi1820Y", "MC Generated Xi(1820) rapidity", kTH1F, {rapidityAxis}); + + // MC truth invariant mass (from MC particles) + histos.add("MC/hMCTruthInvMassKminusLambda", "MC Truth Inv Mass K^{-}#Lambda", kTH1F, {invMassAxis}); + histos.add("MC/hMCTruthInvMassKplusAntiLambda", "MC Truth Inv Mass K^{+}#bar{#Lambda}", kTH1F, {invMassAxis}); + histos.add("MC/hMCTruthInvMassK0sLambda", "MC Truth Inv Mass K^{0}_{S}#Lambda", kTH1F, {invMassAxis}); + histos.add("MC/hMCTruthInvMassK0sAntiLambda", "MC Truth Inv Mass K^{0}_{S}#bar{#Lambda}", kTH1F, {invMassAxis}); + + // MC truth invariant mass vs pT (2D) + histos.add("MC/hMCTruthMassPtKminusLambda", "MC Truth Mass vs pT K^{-}#Lambda", kTH2F, {invMassAxis, ptAxis}); + histos.add("MC/hMCTruthMassPtKplusAntiLambda", "MC Truth Mass vs pT K^{+}#bar{#Lambda}", kTH2F, {invMassAxis, ptAxis}); + histos.add("MC/hMCTruthMassPtK0sLambda", "MC Truth Mass vs pT K^{0}_{S}#Lambda", kTH2F, {invMassAxis, ptAxis}); + histos.add("MC/hMCTruthMassPtK0sAntiLambda", "MC Truth Mass vs pT K^{0}_{S}#bar{#Lambda}", kTH2F, {invMassAxis, ptAxis}); + } } // Lambda/Anti-Lambda selection @@ -279,7 +341,7 @@ struct Xi1820Analysis { return false; // Radius cuts - auto radius = v0.transRadius(); + float radius = v0.transRadius(); if (radius < cV0RadiusMin || radius > cV0RadiusMax) return false; @@ -302,6 +364,14 @@ struct Xi1820Analysis { return false; } + if (cV0sCrossMassRejection) { + if (std::abs(v0.mK0Short() - MassK0Short) < cV0sCrossMassRejectionWindow) + return false; + } + + if (v0.qtarm() > cK0sArmenterosAlphaCoeff * std::fabs(v0.alpha())) + return false; + return true; } @@ -328,12 +398,12 @@ struct Xi1820Analysis { return false; // Radius cuts - auto radius = v0.transRadius(); + float radius = v0.transRadius(); if (radius < cK0sRadiusMin || radius > cK0sRadiusMax) return false; // DCA to PV - if (std::abs(v0.dcav0topv()) > kMaxDcaToPv) + if (std::abs(v0.dcav0topv()) > additionalConfig.cMaxDcaToPVV0) return false; // Proper lifetime cut @@ -352,12 +422,15 @@ struct Xi1820Analysis { // Competing V0 rejection: remove (Anti)Λ if (cK0sCrossMassRejection) { - if (std::abs(v0.mLambda() - MassLambda) < cK0sMassWindow) + if (std::abs(v0.mLambda() - MassLambda) < cK0sCrossMassRejectionWindow) return false; - if (std::abs(v0.mAntiLambda() - MassLambda) < cK0sMassWindow) + if (std::abs(v0.mAntiLambda() - MassLambda) < cK0sCrossMassRejectionWindow) return false; } + if (v0.qtarm() < cK0sArmenterosAlphaCoeff * std::fabs(v0.alpha())) + return false; + return true; } @@ -476,23 +549,44 @@ struct Xi1820Analysis { template bool kaonCut(const TrackType& track) { + float candPt = track.pt(); // Basic kinematic cuts - if (track.pt() < cKaonPtMin) + if (candPt < cKaonPtMin) return false; if (std::abs(track.eta()) > cKaonEtaMax) return false; + float dcaXY = -999.f; + float dcaZ = -999.f; + // DCA cuts - different access for ResoMicroTracks if constexpr (IsResoMicrotrack) { - if (o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAxy(track.trackSelectionFlags()) > cKaonDCAxyMax) - return false; - if (o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAz(track.trackSelectionFlags()) > cKaonDCAzMax) - return false; + dcaXY = o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAxy(track.trackSelectionFlags()); + dcaZ = o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAz(track.trackSelectionFlags()); + + if (additionalConfig.cUsePtDepDCAForKaons) { // Insert pT dependent DCAxy,z cut (tighter than global-track w DCA cut) + if (std::abs(dcaXY) > (additionalConfig.cDCAToPVByPtFirstP0 + additionalConfig.cDCAToPVByPtFirstExp * std::pow(candPt, -1.))) + return false; + if (std::abs(dcaZ) > (additionalConfig.cDCAToPVByPtFirstP0 + additionalConfig.cDCAToPVByPtFirstExp * std::pow(candPt, -1.))) + return false; + } else { + if (std::abs(dcaXY) > cKaonDCAxyMax) + return false; + if (std::abs(dcaZ) > cKaonDCAzMax) + return false; + } } else { - if (std::abs(track.dcaXY()) > cKaonDCAxyMax) - return false; - if (std::abs(track.dcaZ()) > cKaonDCAzMax) - return false; + if (additionalConfig.cUsePtDepDCAForKaons) { // Insert pT dependent DCAxy,z cut (tighter than global-track w DCA cut) + if (std::abs(track.dcaXY()) > (additionalConfig.cDCAToPVByPtFirstP0 + additionalConfig.cDCAToPVByPtFirstExp * std::pow(candPt, -1.))) + return false; + if (std::abs(track.dcaZ()) > (additionalConfig.cDCAToPVByPtFirstP0 + additionalConfig.cDCAToPVByPtFirstExp * std::pow(candPt, -1.))) + return false; + } else { + if (std::abs(track.dcaXY()) > cKaonDCAxyMax) + return false; + if (std::abs(track.dcaZ()) > cKaonDCAzMax) + return false; + } } // Track quality cuts - check if fields are available (only for ResoTracks) @@ -514,8 +608,8 @@ struct Xi1820Analysis { return true; } - template - void fill(const CollisionT& collision, const V0sT& v0s, const TracksT& tracks) + template + void fillChargedKLambda(const CollisionT& collision, const V0sT& v0s, const TracksT& tracks) // Xi(1820) analysis: charged K + Lambda channel { auto cent = collision.cent(); @@ -528,10 +622,16 @@ struct Xi1820Analysis { histos.fill(HIST("Event/nKaons"), tracks.size()); } + if (additionalConfig.cConsiderPairOnly && (v0s.size() < 1 || tracks.size() < 1)) + return; // skip events that cannot form pairs if the option is enabled (for increasing processing speed when only pairs are of interest) + // Count candidates after cuts int nV0sAfterCuts = 0; int nKaonsAfterCuts = 0; + // Build 4 combinations + ROOT::Math::PxPyPzEVector pKaon, pLambda, pRes; + // Loop over kaon candidates for (const auto& kaon : tracks) { // QA before cuts @@ -599,6 +699,7 @@ struct Xi1820Analysis { // Lambda QA before cuts if constexpr (!IsMix) { histos.fill(HIST("QAbefore/lambdaMass"), v0.mLambda()); + histos.fill(HIST("QAbefore/lambdaMassAnti"), v0.mAntiLambda()); histos.fill(HIST("QAbefore/lambdaPt"), v0.pt()); histos.fill(HIST("QAbefore/lambdaEta"), v0.eta()); histos.fill(HIST("QAbefore/lambdaCosPA"), v0.pt(), v0.v0CosPA()); @@ -615,6 +716,7 @@ struct Xi1820Analysis { float p = std::sqrt(v0.px() * v0.px() + v0.py() * v0.py() + v0.pz() * v0.pz()); auto properLifetime = (l / (p + kSmallMomentumDenominator)) * MassLambda; histos.fill(HIST("QAbefore/lambdaProperLifetime"), v0.pt(), properLifetime); + histos.fill(HIST("QAbefore/lambdaArmenterosPodolanski"), v0.alpha(), v0.qtarm(), v0.pt()); } // Try Lambda @@ -632,7 +734,7 @@ struct Xi1820Analysis { histos.fill(HIST("QAafter/lambdaMass"), v0.mLambda()); } if (isAntiLambda) { - histos.fill(HIST("QAafter/lambdaMass"), v0.mAntiLambda()); + histos.fill(HIST("QAafter/lambdaMassAnti"), v0.mAntiLambda()); } histos.fill(HIST("QAafter/lambdaPt"), v0.pt()); histos.fill(HIST("QAafter/lambdaEta"), v0.eta()); @@ -649,55 +751,97 @@ struct Xi1820Analysis { float p = std::sqrt(v0.px() * v0.px() + v0.py() * v0.py() + v0.pz() * v0.pz()); auto properLifetime = (l / (p + kSmallMomentumDenominator)) * MassLambda; histos.fill(HIST("QAafter/lambdaProperLifetime"), v0.pt(), properLifetime); + histos.fill(HIST("QAafter/lambdaArmenterosPodolanski"), v0.alpha(), v0.qtarm(), v0.pt()); } - // Build 4 combinations - ROOT::Math::PxPyPzEVector pKaon, pLambda, pRes; pKaon = ROOT::Math::PxPyPzEVector(ROOT::Math::PtEtaPhiMVector(kaon.pt(), kaon.eta(), kaon.phi(), MassKaonCharged)); - // K+ Lambda + // K+ + Lambda -> Bkg channel for charged Xi(1820) if (kaonCharge > 0 && isLambda) { pLambda = ROOT::Math::PxPyPzEVector(ROOT::Math::PtEtaPhiMVector(v0.pt(), v0.eta(), v0.phi(), v0.mLambda())); pRes = pKaon + pLambda; + auto pCandRapidity = pRes.Rapidity(); + if (std::abs(pCandRapidity) >= additionalConfig.cfgRapidityCut) // skip candidate if reconstructed rapidity is outside of cut + continue; if constexpr (!IsMix) { histos.fill(HIST("xi1820/kplus_lambda/hInvMassKplusLambda"), pRes.M()); histos.fill(HIST("xi1820/kplus_lambda/hMassPtCentKplusLambda"), pRes.M(), pRes.Pt(), cent); + } else { histos.fill(HIST("xi1820/kplus_lambda/hInvMassKplusLambda_Mix"), pRes.M()); histos.fill(HIST("xi1820/kplus_lambda/hMassPtCentKplusLambda_Mix"), pRes.M(), pRes.Pt(), cent); } } - // K+ Anti-Lambda + // K+ + Anti-Lambda -> Signal channel for Anti-charged Xi(1820) if (kaonCharge > 0 && isAntiLambda) { pLambda = ROOT::Math::PxPyPzEVector(ROOT::Math::PtEtaPhiMVector(v0.pt(), v0.eta(), v0.phi(), v0.mAntiLambda())); pRes = pKaon + pLambda; + auto pCandRapidity = pRes.Rapidity(); + if (std::abs(pCandRapidity) >= additionalConfig.cfgRapidityCut) // skip candidate if reconstructed rapidity is outside of cut + continue; if constexpr (!IsMix) { histos.fill(HIST("xi1820/kplus_antilambda/hInvMassKplusAntiLambda"), pRes.M()); histos.fill(HIST("xi1820/kplus_antilambda/hMassPtCentKplusAntiLambda"), pRes.M(), pRes.Pt(), cent); + if constexpr (IsMC) { // Calculate Acceptance x efficiency for "the particle" channel + if (std::abs(v0.motherPDG()) != kPdgChagedXi1820) + continue; + if (kaon.pdgCode() != PDG_t::kKPlus || v0.pdgCode() != PDG_t::kLambda0Bar) + continue; + if (kaon.motherId() != v0.motherId()) + continue; + auto pMCPt = v0.motherPt(); // Check particle's pT resolution + if (additionalConfig.cUseTruthRapidity && std::abs(v0.motherRap()) >= additionalConfig.cfgRapidityCut) // skip candidate if True rapidity of mother particle is outside of cut + continue; + histos.fill(HIST("MC/kplus_antilambda/hMCRecoInvMassKplusAntiLambda"), pRes.M()); + histos.fill(HIST("MC/kplus_antilambda/hMCRecoMassPtCentKplusAntiLambda"), pRes.M(), pRes.Pt(), cent, pMCPt); + + // Detail QA histograms for truth particle -> Will be updated + } } else { histos.fill(HIST("xi1820/kplus_antilambda/hInvMassKplusAntiLambda_Mix"), pRes.M()); histos.fill(HIST("xi1820/kplus_antilambda/hMassPtCentKplusAntiLambda_Mix"), pRes.M(), pRes.Pt(), cent); } } - // K- Lambda + // K- + Lambda -> Signal channel for Xi(1820)- if (kaonCharge < 0 && isLambda) { pLambda = ROOT::Math::PxPyPzEVector(ROOT::Math::PtEtaPhiMVector(v0.pt(), v0.eta(), v0.phi(), v0.mLambda())); pRes = pKaon + pLambda; + auto pCandRapidity = pRes.Rapidity(); + if (std::abs(pCandRapidity) >= additionalConfig.cfgRapidityCut) // skip candidate if reconstructed rapidity is outside of cut + continue; if constexpr (!IsMix) { histos.fill(HIST("xi1820/kminus_lambda/hInvMassKminusLambda"), pRes.M()); histos.fill(HIST("xi1820/kminus_lambda/hMassPtCentKminusLambda"), pRes.M(), pRes.Pt(), cent); + if constexpr (IsMC) { // Calculate Acceptance x efficiency for "the particle" channel + if (std::abs(v0.motherPDG()) != kPdgChagedXi1820) + continue; + if (kaon.pdgCode() != PDG_t::kKMinus || v0.pdgCode() != PDG_t::kLambda0) + continue; + if (kaon.motherId() != v0.motherId()) + continue; + auto pMCPt = v0.motherPt(); // Check particle's pT resolution + if (additionalConfig.cUseTruthRapidity && std::abs(v0.motherRap()) >= additionalConfig.cfgRapidityCut) // skip candidate if True rapidity of mother particle is outside of cut + continue; + histos.fill(HIST("MC/kminus_lambda/hMCRecoInvMassKminusLambda"), pRes.M()); + histos.fill(HIST("MC/kminus_lambda/hMCRecoMassPtCentKminusLambda"), pRes.M(), pRes.Pt(), cent, pMCPt); + + // Detail QA histograms for the truth particle -> Will be updated + } } else { histos.fill(HIST("xi1820/kminus_lambda/hInvMassKminusLambda_Mix"), pRes.M()); histos.fill(HIST("xi1820/kminus_lambda/hMassPtCentKminusLambda_Mix"), pRes.M(), pRes.Pt(), cent); } } - // K- Anti-Lambda + // K- + Anti-Lambda -> Bkg channel for charged Xi(1820) if (kaonCharge < 0 && isAntiLambda) { pLambda = ROOT::Math::PxPyPzEVector(ROOT::Math::PtEtaPhiMVector(v0.pt(), v0.eta(), v0.phi(), v0.mAntiLambda())); pRes = pKaon + pLambda; + auto pCandRapidity = pRes.Rapidity(); + if (std::abs(pCandRapidity) >= additionalConfig.cfgRapidityCut) // skip candidate if reconstructed rapidity is outside of cut + continue; if constexpr (!IsMix) { histos.fill(HIST("xi1820/kminus_antilambda/hInvMassKminusAntiLambda"), pRes.M()); histos.fill(HIST("xi1820/kminus_antilambda/hMassPtCentKminusAntiLambda"), pRes.M(), pRes.Pt(), cent); @@ -711,203 +855,105 @@ struct Xi1820Analysis { // Fill event QA for after-cuts counters (only for same-event) if constexpr (!IsMix) { - histos.fill(HIST("Event/nV0sAfterCuts"), nV0sAfterCuts); + histos.fill(HIST("Event/nLambdasAfterCuts"), nV0sAfterCuts); histos.fill(HIST("Event/nKaonsAfterCuts"), nKaonsAfterCuts); } } - void processDummy(const aod::ResoCollision& /*collision*/) - { - // Dummy function to satisfy the compiler - } - PROCESS_SWITCH(Xi1820Analysis, processDummy, "Process Dummy", true); - - void processDataWithTracks(const aod::ResoCollision& collision, - aod::ResoV0s const& resov0s, - aod::ResoTracks const& resotracks) - { - fill(collision, resov0s, resotracks); - } - PROCESS_SWITCH(Xi1820Analysis, processDataWithTracks, "Process Event with ResoTracks", false); - - void processDataWithMicroTracks(const aod::ResoCollision& collision, - aod::ResoV0s const& resov0s, - aod::ResoMicroTracks const& resomicrotracks) + template + void fillK0sLambda(const CollisionT& collision, const V0sT& k0sCands, const V0sT& lambdaCands) // Xi(1820) analysis: K0s + Lambda channel, No need to MicroTrack! { - fill(collision, resov0s, resomicrotracks); - } - PROCESS_SWITCH(Xi1820Analysis, processDataWithMicroTracks, "Process Event with ResoMicroTracks", false); - - void processMixedEventWithTracks(const aod::ResoCollisions& collisions, - aod::ResoV0s const& resov0s, - aod::ResoTracks const& resotracks) - { - - auto v0sTracksTuple = std::make_tuple(resov0s, resotracks); - Pair pairs{colBinning, nEvtMixing, -1, collisions, v0sTracksTuple, &cache}; - - for (auto& [collision1, v0s1, collision2, tracks2] : pairs) { // o2-linter: disable=const-ref-in-for-loop (structured bindings from Pair iterator cannot be const) - auto cent = collision1.cent(); - - for (const auto& kaon : tracks2) { - if (!kaonCut(kaon)) - continue; - int kaonCharge = kaon.sign(); - - for (const auto& v0 : v0s1) { - bool isLambda = v0Cut(collision1, v0, true); - bool isAntiLambda = v0Cut(collision1, v0, false); - - if (!isLambda && !isAntiLambda) - continue; - - ROOT::Math::PxPyPzEVector pKaon, pLambda, pRes; - pKaon = ROOT::Math::PxPyPzEVector(ROOT::Math::PtEtaPhiMVector(kaon.pt(), kaon.eta(), kaon.phi(), MassKaonCharged)); + auto cent = collision.cent(); - // K+ Lambda - if (kaonCharge > 0 && isLambda) { - pLambda = ROOT::Math::PxPyPzEVector(ROOT::Math::PtEtaPhiMVector(v0.pt(), v0.eta(), v0.phi(), v0.mLambda())); - pRes = pKaon + pLambda; - histos.fill(HIST("xi1820/kplus_lambda/hInvMassKplusLambda_Mix"), pRes.M()); - histos.fill(HIST("xi1820/kplus_lambda/hMassPtCentKplusLambda_Mix"), pRes.M(), pRes.Pt(), cent); - } + // Fill event QA histograms + if constexpr (!IsMix) { + histos.fill(HIST("Event/posZ"), collision.posZ()); + histos.fill(HIST("Event/centrality"), cent); + histos.fill(HIST("Event/posZvsCent"), collision.posZ(), cent); + histos.fill(HIST("Event/nV0s"), lambdaCands.size()); + histos.fill(HIST("Event/nKaons"), k0sCands.size()); + } - // K+ Anti-Lambda - if (kaonCharge > 0 && isAntiLambda) { - pLambda = ROOT::Math::PxPyPzEVector(ROOT::Math::PtEtaPhiMVector(v0.pt(), v0.eta(), v0.phi(), v0.mAntiLambda())); - pRes = pKaon + pLambda; - histos.fill(HIST("xi1820/kplus_antilambda/hInvMassKplusAntiLambda_Mix"), pRes.M()); - histos.fill(HIST("xi1820/kplus_antilambda/hMassPtCentKplusAntiLambda_Mix"), pRes.M(), pRes.Pt(), cent); - } + if (additionalConfig.cConsiderHasV0s && (lambdaCands.size() < 1)) + return; // skip events that do not have V0s if the option is enabled - // K- Lambda - if (kaonCharge < 0 && isLambda) { - pLambda = ROOT::Math::PxPyPzEVector(ROOT::Math::PtEtaPhiMVector(v0.pt(), v0.eta(), v0.phi(), v0.mLambda())); - pRes = pKaon + pLambda; - histos.fill(HIST("xi1820/kminus_lambda/hInvMassKminusLambda_Mix"), pRes.M()); - histos.fill(HIST("xi1820/kminus_lambda/hMassPtCentKminusLambda_Mix"), pRes.M(), pRes.Pt(), cent); - } + int nV0sAfterCuts = 0; + int nKaonsAfterCuts = 0; - // K- Anti-Lambda - if (kaonCharge < 0 && isAntiLambda) { - pLambda = ROOT::Math::PxPyPzEVector(ROOT::Math::PtEtaPhiMVector(v0.pt(), v0.eta(), v0.phi(), v0.mAntiLambda())); - pRes = pKaon + pLambda; - histos.fill(HIST("xi1820/kminus_antilambda/hInvMassKminusAntiLambda_Mix"), pRes.M()); - histos.fill(HIST("xi1820/kminus_antilambda/hMassPtCentKminusAntiLambda_Mix"), pRes.M(), pRes.Pt(), cent); - } - } + // Loop over V0s for K0s + for (const auto& k0s : k0sCands) { + // K0s QA before cuts + if constexpr (!IsMix) { + histos.fill(HIST("QAbefore/k0sMass"), k0s.mK0Short()); + histos.fill(HIST("QAbefore/k0sPt"), k0s.pt()); + histos.fill(HIST("QAbefore/k0sEta"), k0s.eta()); + histos.fill(HIST("QAbefore/k0sCosPA"), k0s.pt(), k0s.v0CosPA()); + histos.fill(HIST("QAbefore/k0sRadius"), k0s.pt(), k0s.transRadius()); + histos.fill(HIST("QAbefore/k0sDauDCA"), k0s.pt(), k0s.daughDCA()); + + float dx = k0s.decayVtxX() - collision.posX(); + float dy = k0s.decayVtxY() - collision.posY(); + float dz = k0s.decayVtxZ() - collision.posZ(); + float l = std::sqrt(dx * dx + dy * dy + dz * dz); + float p = std::sqrt(k0s.px() * k0s.px() + k0s.py() * k0s.py() + k0s.pz() * k0s.pz()); + auto k0sProperLifetime = (l / (p + 1e-10)) * MassK0Short; + histos.fill(HIST("QAbefore/k0sProperLifetime"), k0s.pt(), k0sProperLifetime); + histos.fill(HIST("QAbefore/k0sArmenterosPodolanski"), k0s.alpha(), k0s.qtarm(), k0s.pt()); } - } - } - PROCESS_SWITCH(Xi1820Analysis, processMixedEventWithTracks, "Process Mixed Event with ResoTracks", false); - - void processMixedEventWithMicroTracks(const aod::ResoCollisions& collisions, - aod::ResoV0s const& resov0s, - aod::ResoMicroTracks const& resomicrotracks) - { - auto v0sTracksTuple = std::make_tuple(resov0s, resomicrotracks); - Pair pairs{colBinning, nEvtMixing, -1, collisions, v0sTracksTuple, &cache}; + if (!k0sCut(collision, k0s)) + continue; + auto indexK0s = k0s.index(); - for (auto& [collision1, v0s1, collision2, tracks2] : pairs) { // o2-linter: disable=const-ref-in-for-loop (structured bindings from Pair iterator cannot be const) - auto cent = collision1.cent(); + if constexpr (!IsMix) { + nKaonsAfterCuts++; + // K0s QA after cuts + histos.fill(HIST("QAafter/k0sMass"), k0s.mK0Short()); + histos.fill(HIST("QAafter/k0sPt"), k0s.pt()); + histos.fill(HIST("QAafter/k0sEta"), k0s.eta()); + histos.fill(HIST("QAafter/k0sCosPA"), k0s.pt(), k0s.v0CosPA()); + histos.fill(HIST("QAafter/k0sRadius"), k0s.pt(), k0s.transRadius()); + histos.fill(HIST("QAafter/k0sDauDCA"), k0s.pt(), k0s.daughDCA()); + + float dx = k0s.decayVtxX() - collision.posX(); + float dy = k0s.decayVtxY() - collision.posY(); + float dz = k0s.decayVtxZ() - collision.posZ(); + float l = std::sqrt(dx * dx + dy * dy + dz * dz); + float p = std::sqrt(k0s.px() * k0s.px() + k0s.py() * k0s.py() + k0s.pz() * k0s.pz()); + auto k0sProperLifetime = (l / (p + 1e-10)) * MassK0Short; + histos.fill(HIST("QAafter/k0sProperLifetime"), k0s.pt(), k0sProperLifetime); + histos.fill(HIST("QAafter/k0sArmenterosPodolanski"), k0s.alpha(), k0s.qtarm(), k0s.pt()); + } - for (const auto& kaon : tracks2) { - if (!kaonCut(kaon)) - continue; - int kaonCharge = kaon.sign(); + // Loop over V0s for Lambda + for (const auto& lambda : lambdaCands) { - for (const auto& v0 : v0s1) { - bool isLambda = v0Cut(collision1, v0, true); - bool isAntiLambda = v0Cut(collision1, v0, false); + auto indexLambda = lambda.index(); - if (!isLambda && !isAntiLambda) + if constexpr (!IsMix) { + if (indexLambda == indexK0s) // Avoid self-combination continue; + histos.fill(HIST("QAbefore/lambdaMass"), lambda.mLambda()); + histos.fill(HIST("QAbefore/lambdaMassAnti"), lambda.mAntiLambda()); + histos.fill(HIST("QAbefore/lambdaPt"), lambda.pt()); + histos.fill(HIST("QAbefore/lambdaEta"), lambda.eta()); + histos.fill(HIST("QAbefore/lambdaCosPA"), lambda.pt(), lambda.v0CosPA()); + histos.fill(HIST("QAbefore/lambdaRadius"), lambda.pt(), lambda.transRadius()); + histos.fill(HIST("QAbefore/lambdaDauDCA"), lambda.pt(), lambda.daughDCA()); + histos.fill(HIST("QAbefore/lambdaDauPosDCA"), lambda.pt(), std::abs(lambda.dcapostopv())); + histos.fill(HIST("QAbefore/lambdaDauNegDCA"), lambda.pt(), std::abs(lambda.dcanegtopv())); - ROOT::Math::PxPyPzEVector pKaon, pLambda, pRes; - pKaon = ROOT::Math::PxPyPzEVector(ROOT::Math::PtEtaPhiMVector(kaon.pt(), kaon.eta(), kaon.phi(), MassKaonCharged)); - - // K+ Lambda - if (kaonCharge > 0 && isLambda) { - pLambda = ROOT::Math::PxPyPzEVector(ROOT::Math::PtEtaPhiMVector(v0.pt(), v0.eta(), v0.phi(), v0.mLambda())); - pRes = pKaon + pLambda; - histos.fill(HIST("xi1820/kplus_lambda/hInvMassKplusLambda_Mix"), pRes.M()); - histos.fill(HIST("xi1820/kplus_lambda/hMassPtCentKplusLambda_Mix"), pRes.M(), pRes.Pt(), cent); - } - - // K+ Anti-Lambda - if (kaonCharge > 0 && isAntiLambda) { - pLambda = ROOT::Math::PxPyPzEVector(ROOT::Math::PtEtaPhiMVector(v0.pt(), v0.eta(), v0.phi(), v0.mAntiLambda())); - pRes = pKaon + pLambda; - histos.fill(HIST("xi1820/kplus_antilambda/hInvMassKplusAntiLambda_Mix"), pRes.M()); - histos.fill(HIST("xi1820/kplus_antilambda/hMassPtCentKplusAntiLambda_Mix"), pRes.M(), pRes.Pt(), cent); - } - - // K- Lambda - if (kaonCharge < 0 && isLambda) { - pLambda = ROOT::Math::PxPyPzEVector(ROOT::Math::PtEtaPhiMVector(v0.pt(), v0.eta(), v0.phi(), v0.mLambda())); - pRes = pKaon + pLambda; - histos.fill(HIST("xi1820/kminus_lambda/hInvMassKminusLambda_Mix"), pRes.M()); - histos.fill(HIST("xi1820/kminus_lambda/hMassPtCentKminusLambda_Mix"), pRes.M(), pRes.Pt(), cent); - } - - // K- Anti-Lambda - if (kaonCharge < 0 && isAntiLambda) { - pLambda = ROOT::Math::PxPyPzEVector(ROOT::Math::PtEtaPhiMVector(v0.pt(), v0.eta(), v0.phi(), v0.mAntiLambda())); - pRes = pKaon + pLambda; - histos.fill(HIST("xi1820/kminus_antilambda/hInvMassKminusAntiLambda_Mix"), pRes.M()); - histos.fill(HIST("xi1820/kminus_antilambda/hMassPtCentKminusAntiLambda_Mix"), pRes.M(), pRes.Pt(), cent); - } + // Calculate proper lifetime manually + float dx = lambda.decayVtxX() - collision.posX(); + float dy = lambda.decayVtxY() - collision.posY(); + float dz = lambda.decayVtxZ() - collision.posZ(); + float l = std::sqrt(dx * dx + dy * dy + dz * dz); + float p = std::sqrt(lambda.px() * lambda.px() + lambda.py() * lambda.py() + lambda.pz() * lambda.pz()); + auto properLifetime = (l / (p + kSmallMomentumDenominator)) * MassLambda; + histos.fill(HIST("QAbefore/lambdaProperLifetime"), lambda.pt(), properLifetime); + histos.fill(HIST("QAbefore/lambdaArmenterosPodolanski"), lambda.alpha(), lambda.qtarm(), lambda.pt()); } - } - } - } - PROCESS_SWITCH(Xi1820Analysis, processMixedEventWithMicroTracks, "Process Mixed Event with ResoMicroTracks", false); - - // K0s + Lambda analysis - void processK0sLambda(const aod::ResoCollision& collision, - aod::ResoV0s const& resov0s) - { - auto cent = collision.cent(); - - // Fill event QA histograms - histos.fill(HIST("Event/posZ"), collision.posZ()); - histos.fill(HIST("Event/centrality"), cent); - histos.fill(HIST("Event/posZvsCent"), collision.posZ(), cent); - histos.fill(HIST("Event/nV0s"), resov0s.size()); - - // Loop over V0s for K0s - for (const auto& k0s : resov0s) { - // K0s QA before cuts - histos.fill(HIST("QAbefore/k0sMass"), k0s.mK0Short()); - histos.fill(HIST("QAbefore/k0sPt"), k0s.pt()); - histos.fill(HIST("QAbefore/k0sEta"), k0s.eta()); - histos.fill(HIST("QAbefore/k0sCosPA"), k0s.pt(), k0s.v0CosPA()); - histos.fill(HIST("QAbefore/k0sRadius"), k0s.pt(), k0s.transRadius()); - histos.fill(HIST("QAbefore/k0sDauDCA"), k0s.pt(), k0s.daughDCA()); - - float dx = k0s.decayVtxX() - collision.posX(); - float dy = k0s.decayVtxY() - collision.posY(); - float dz = k0s.decayVtxZ() - collision.posZ(); - float l = std::sqrt(dx * dx + dy * dy + dz * dz); - float p = std::sqrt(k0s.px() * k0s.px() + k0s.py() * k0s.py() + k0s.pz() * k0s.pz()); - auto k0sProperLifetime = (l / (p + 1e-10)) * MassK0Short; - histos.fill(HIST("QAbefore/k0sProperLifetime"), k0s.pt(), k0sProperLifetime); - - if (!k0sCut(collision, k0s)) - continue; - // K0s QA after cuts - histos.fill(HIST("QAafter/k0sMass"), k0s.mK0Short()); - histos.fill(HIST("QAafter/k0sPt"), k0s.pt()); - histos.fill(HIST("QAafter/k0sEta"), k0s.eta()); - histos.fill(HIST("QAafter/k0sCosPA"), k0s.pt(), k0s.v0CosPA()); - histos.fill(HIST("QAafter/k0sRadius"), k0s.pt(), k0s.transRadius()); - histos.fill(HIST("QAafter/k0sDauDCA"), k0s.pt(), k0s.daughDCA()); - histos.fill(HIST("QAafter/k0sProperLifetime"), k0s.pt(), k0sProperLifetime); - - // Loop over V0s for Lambda - for (const auto& lambda : resov0s) { // Try Lambda bool isLambda = v0Cut(collision, lambda, true); // Try Anti-Lambda @@ -916,112 +962,270 @@ struct Xi1820Analysis { if (!isLambda && !isAntiLambda) continue; + if constexpr (!IsMix) { + nV0sAfterCuts++; + // QA after cuts (fill for whichever passes) + if (isLambda) { + histos.fill(HIST("QAafter/lambdaMass"), lambda.mLambda()); + } + if (isAntiLambda) { + histos.fill(HIST("QAafter/lambdaMassAnti"), lambda.mAntiLambda()); + } + histos.fill(HIST("QAafter/lambdaPt"), lambda.pt()); + histos.fill(HIST("QAafter/lambdaEta"), lambda.eta()); + histos.fill(HIST("QAafter/lambdaCosPA"), lambda.pt(), lambda.v0CosPA()); + histos.fill(HIST("QAafter/lambdaRadius"), lambda.pt(), lambda.transRadius()); + histos.fill(HIST("QAafter/lambdaDauDCA"), lambda.pt(), lambda.daughDCA()); + histos.fill(HIST("QAafter/lambdaDauPosDCA"), lambda.pt(), std::abs(lambda.dcapostopv())); + histos.fill(HIST("QAafter/lambdaDauNegDCA"), lambda.pt(), std::abs(lambda.dcanegtopv())); + + float dx = lambda.decayVtxX() - collision.posX(); + float dy = lambda.decayVtxY() - collision.posY(); + float dz = lambda.decayVtxZ() - collision.posZ(); + float l = std::sqrt(dx * dx + dy * dy + dz * dz); + float p = std::sqrt(lambda.px() * lambda.px() + lambda.py() * lambda.py() + lambda.pz() * lambda.pz()); + auto properLifetime = (l / (p + kSmallMomentumDenominator)) * MassLambda; + histos.fill(HIST("QAafter/lambdaProperLifetime"), lambda.pt(), properLifetime); + histos.fill(HIST("QAafter/lambdaArmenterosPodolanski"), lambda.alpha(), lambda.qtarm(), lambda.pt()); + } + // 4-vectors ROOT::Math::PxPyPzEVector pK0s, pLambda, pRes; pK0s = ROOT::Math::PxPyPzEVector(ROOT::Math::PtEtaPhiMVector(k0s.pt(), k0s.eta(), k0s.phi(), MassK0Short)); - // K0s + Lambda if (isLambda) { pLambda = ROOT::Math::PxPyPzEVector(ROOT::Math::PtEtaPhiMVector(lambda.pt(), lambda.eta(), lambda.phi(), lambda.mLambda())); pRes = pK0s + pLambda; - histos.fill(HIST("xi1820/k0s_lambda/hInvMassK0sLambda"), pRes.M()); - histos.fill(HIST("xi1820/k0s_lambda/hMassPtCentK0sLambda"), pRes.M(), pRes.Pt(), cent); + auto pCandRapidity = pRes.Rapidity(); + if (std::abs(pCandRapidity) >= additionalConfig.cfgRapidityCut) // skip candidate if reconstructed rapidity is outside of cut + continue; + if constexpr (!IsMix) { + histos.fill(HIST("xi1820/k0s_lambda/hInvMassK0sLambda"), pRes.M()); + histos.fill(HIST("xi1820/k0s_lambda/hMassPtCentK0sLambda"), pRes.M(), pRes.Pt(), cent); + if constexpr (IsMC) { // Calculate Acceptance x efficiency + if (std::abs(lambda.motherPDG()) != kPdgXi1820Zero) + continue; + if (std::abs(k0s.pdgCode()) != PDG_t::kK0Short || lambda.pdgCode() != PDG_t::kLambda0) + continue; + if (k0s.motherId() != lambda.motherId()) + continue; + auto pMCPt = lambda.motherPt(); // Check particle's pT resolution + if (additionalConfig.cUseTruthRapidity && std::abs(lambda.motherRap()) >= additionalConfig.cfgRapidityCut) // skip candidate if True rapidity of mother particle is outside of cut + continue; + histos.fill(HIST("MC/k0s_lambda/hMCRecoInvMassK0sLambda"), pRes.M()); + histos.fill(HIST("MC/k0s_lambda/hMCRecoMassPtCentK0sLambda"), pRes.M(), pRes.Pt(), cent, pMCPt); + // Detail QA histograms for truth particle -> Will be updated + } + } else { + histos.fill(HIST("xi1820/k0s_lambda/hInvMassK0sLambda_Mix"), pRes.M()); + histos.fill(HIST("xi1820/k0s_lambda/hMassPtCentK0sLambda_Mix"), pRes.M(), pRes.Pt(), cent); + } } - // K0s + Anti-Lambda if (isAntiLambda) { pLambda = ROOT::Math::PxPyPzEVector(ROOT::Math::PtEtaPhiMVector(lambda.pt(), lambda.eta(), lambda.phi(), lambda.mAntiLambda())); pRes = pK0s + pLambda; - histos.fill(HIST("xi1820/k0s_antilambda/hInvMassK0sAntiLambda"), pRes.M()); - histos.fill(HIST("xi1820/k0s_antilambda/hMassPtCentK0sAntiLambda"), pRes.M(), pRes.Pt(), cent); + auto pCandRapidity = pRes.Rapidity(); + if (std::abs(pCandRapidity) >= additionalConfig.cfgRapidityCut) // skip candidate if reconstructed rapidity is outside of cut + continue; + if constexpr (!IsMix) { + histos.fill(HIST("xi1820/k0s_antilambda/hInvMassK0sAntiLambda"), pRes.M()); + histos.fill(HIST("xi1820/k0s_antilambda/hMassPtCentK0sAntiLambda"), pRes.M(), pRes.Pt(), cent); + + if constexpr (IsMC) { // Calculate Acceptance x efficiency + if (std::abs(lambda.motherPDG()) != kPdgXi1820Zero) + continue; + if (std::abs(k0s.pdgCode()) != PDG_t::kK0Short || lambda.pdgCode() != PDG_t::kLambda0Bar) + continue; + if (k0s.motherId() != lambda.motherId()) + continue; + auto pMCPt = lambda.motherPt(); // Check particle's pT resolution + if (additionalConfig.cUseTruthRapidity && std::abs(lambda.motherRap()) >= additionalConfig.cfgRapidityCut) // skip candidate if True rapidity of mother particle is outside of cut + continue; + histos.fill(HIST("MC/k0s_antilambda/hMCRecoInvMassK0sAntiLambda"), pRes.M()); + histos.fill(HIST("MC/k0s_antilambda/hMCRecoMassPtCentK0sAntiLambda"), pRes.M(), pRes.Pt(), cent, pMCPt); + // Detail QA histograms for truth particle -> Will be updated + } + } else { + histos.fill(HIST("xi1820/k0s_antilambda/hInvMassK0sAntiLambda_Mix"), pRes.M()); + histos.fill(HIST("xi1820/k0s_antilambda/hMassPtCentK0sAntiLambda_Mix"), pRes.M(), pRes.Pt(), cent); + } } - } + } // End of loop over Lambda candidates + } // End of loop over K0s candidates + + // Fill event QA for after-cuts counters (only for same-event) + if constexpr (!IsMix) { + histos.fill(HIST("Event/nLambdasAfterCuts"), nV0sAfterCuts); + histos.fill(HIST("Event/nKaonsAfterCuts"), nKaonsAfterCuts); } } - PROCESS_SWITCH(Xi1820Analysis, processK0sLambda, "Process K0s + Lambda", false); - // K0s + Lambda mixed event analysis - void processK0sLambdaMixedEvent(const aod::ResoCollisions& collisions, - aod::ResoV0s const& resov0s) + void processDummy(const aod::ResoCollision& /*collision*/) { + // Dummy function to satisfy the compiler + } + PROCESS_SWITCH(Xi1820Analysis, processDummy, "Process Dummy", true); - auto v0sV0sTuple = std::make_tuple(resov0s, resov0s); - Pair pairs{colBinning, nEvtMixing, -1, collisions, v0sV0sTuple, &cache}; + void processDataWithTracks(const aod::ResoCollision& resoCollision, + aod::ResoV0s const& resoV0s, + aod::ResoTracks const& resoTracks) + { + if (additionalConfig.cRecoINELgt0 && !resoCollision.isRecINELgt0()) + return; // skip event if RecoINEL>0 selection is enabled and event does not pass it + fillChargedKLambda(resoCollision, resoV0s, resoTracks); + } + PROCESS_SWITCH(Xi1820Analysis, processDataWithTracks, "Process Event with ResoTracks", false); - for (auto& [collision1, k0s1, collision2, lambda2] : pairs) { // o2-linter: disable=const-ref-in-for-loop (structured bindings from Pair iterator cannot be const) - auto cent = collision1.cent(); + void processDataWithMicroTracks(const aod::ResoCollision& resoCollision, + aod::ResoV0s const& resoV0s, + aod::ResoMicroTracks const& resoMicroTracks) + { + if (additionalConfig.cRecoINELgt0 && !resoCollision.isRecINELgt0()) + return; // skip event if RecoINEL>0 selection is enabled and event does not pass it + fillChargedKLambda(resoCollision, resoV0s, resoMicroTracks); + } + PROCESS_SWITCH(Xi1820Analysis, processDataWithMicroTracks, "Process Event with ResoMicroTracks", false); - for (const auto& k0s : k0s1) { - if (!k0sCut(collision1, k0s)) - continue; + void processMixedEventWithTracks(const aod::ResoCollisions& resoCollisions, + aod::ResoV0s const& resoV0s, + aod::ResoTracks const& resoTracks) + { - for (const auto& lambda : lambda2) { - bool isLambda = v0Cut(collision2, lambda, true); - bool isAntiLambda = v0Cut(collision2, lambda, false); + auto v0sTracksTuple = std::make_tuple(resoTracks, resoV0s); + BinningTypeVertexContributor colBinning{{cfgVtxBins, cfgMultBins}, true}; + Pair pairs{colBinning, nEvtMixing, -1, resoCollisions, v0sTracksTuple, &cache}; - if (!isLambda && !isAntiLambda) - continue; + for (auto& [collision1, tracks1, collision2, v0s2] : pairs) { // o2-linter: disable=const-ref-in-for-loop (structured bindings from Pair iterator cannot be const) + if (additionalConfig.cRecoINELgt0 && !collision1.isRecINELgt0()) + continue; // skip event if RecoINEL>0 selection is enabled and event does not pass it + fillChargedKLambda(collision1, v0s2, tracks1); + } + } + PROCESS_SWITCH(Xi1820Analysis, processMixedEventWithTracks, "Process Mixed Event with ResoTracks", false); - ROOT::Math::PxPyPzEVector pK0s, pLambda, pRes; - pK0s = ROOT::Math::PxPyPzEVector(ROOT::Math::PtEtaPhiMVector(k0s.pt(), k0s.eta(), k0s.phi(), MassK0Short)); + void processMixedEventWithMicroTracks(const aod::ResoCollisions& resoCollisions, + aod::ResoV0s const& resoV0s, + aod::ResoMicroTracks const& resoMicroTracks) + { - // K0s + Lambda - if (isLambda) { - pLambda = ROOT::Math::PxPyPzEVector(ROOT::Math::PtEtaPhiMVector(lambda.pt(), lambda.eta(), lambda.phi(), lambda.mLambda())); - pRes = pK0s + pLambda; - histos.fill(HIST("xi1820/k0s_lambda/hInvMassK0sLambda_Mix"), pRes.M()); - histos.fill(HIST("xi1820/k0s_lambda/hMassPtCentK0sLambda_Mix"), pRes.M(), pRes.Pt(), cent); - } + auto v0sTracksTuple = std::make_tuple(resoV0s, resoMicroTracks); + BinningTypeVertexContributor colBinning{{cfgVtxBins, cfgMultBins}, true}; + Pair pairs{colBinning, nEvtMixing, -1, resoCollisions, v0sTracksTuple, &cache}; - // K0s + Anti-Lambda - if (isAntiLambda) { - pLambda = ROOT::Math::PxPyPzEVector(ROOT::Math::PtEtaPhiMVector(lambda.pt(), lambda.eta(), lambda.phi(), lambda.mAntiLambda())); - pRes = pK0s + pLambda; - histos.fill(HIST("xi1820/k0s_antilambda/hInvMassK0sAntiLambda_Mix"), pRes.M()); - histos.fill(HIST("xi1820/k0s_antilambda/hMassPtCentK0sAntiLambda_Mix"), pRes.M(), pRes.Pt(), cent); - } - } - } + for (auto& [collision1, v0s1, collision2, tracks2] : pairs) { // o2-linter: disable=const-ref-in-for-loop (structured bindings from Pair iterator cannot be const) + if (additionalConfig.cRecoINELgt0 && !collision2.isRecINELgt0()) + continue; // skip event if RecoINEL>0 selection is enabled and event does not pass it + fillChargedKLambda(collision2, v0s1, tracks2); + } + } + PROCESS_SWITCH(Xi1820Analysis, processMixedEventWithMicroTracks, "Process Mixed Event with ResoMicroTracks", false); + + // K0s + Lambda analysis + void processK0sLambda(const aod::ResoCollision& resoCollision, + aod::ResoV0s const& resoV0s) + { + if (additionalConfig.cRecoINELgt0 && !resoCollision.isRecINELgt0()) + return; // skip event if RecoINEL>0 selection is enabled and event does not pass it + fillK0sLambda(resoCollision, resoV0s, resoV0s); + } + PROCESS_SWITCH(Xi1820Analysis, processK0sLambda, "Process K0s + Lambda", false); + + // K0s + Lambda mixed event analysis + void processK0sLambdaMixedEvent(const aod::ResoCollisions& resoCollisions, + aod::ResoV0s const& resoV0s) + { + + auto v0sV0sTuple = std::make_tuple(resoV0s, resoV0s); + BinningTypeVertexContributor colBinning{{cfgVtxBins, cfgMultBins}, true}; + Pair pairs{colBinning, nEvtMixing, -1, resoCollisions, v0sV0sTuple, &cache}; + + for (auto& [collision1, k0s1, collision2, lambda2] : pairs) { // o2-linter: disable=const-ref-in-for-loop (structured bindings from Pair iterator cannot be const) + if (additionalConfig.cRecoINELgt0 && !collision1.isRecINELgt0()) + continue; // skip event if RecoINEL>0 selection is enabled and event does not pass it + fillK0sLambda(collision1, k0s1, lambda2); } } PROCESS_SWITCH(Xi1820Analysis, processK0sLambdaMixedEvent, "Process K0s + Lambda Mixed Event", false); - // MC processes - placeholder for future implementation - void processMCWithTracks(const aod::ResoCollision& /*collision*/, - aod::ResoV0s const& /*resov0s*/, - aod::ResoTracks const& /*resotracks*/, - aod::McParticles const& /*mcParticles*/) + // MC processes for charged K + Lambda analysis + void processMCWithTracks(ResoMCCols::iterator const& resoMCcollision, + soa::Join const& resoMCV0s, + soa::Join const& resoMCTracks) + { + if (additionalConfig.cRecoINELgt0 && !resoMCcollision.isRecINELgt0()) + return; // skip event if RecoINEL>0 selection is enabled and event does not pass it + if (!resoMCcollision.isInAfterAllCuts()) // MC event selection + return; + fillChargedKLambda(resoMCcollision, resoMCV0s, resoMCTracks); + } + PROCESS_SWITCH(Xi1820Analysis, processMCWithTracks, "Process MC for charged K + Lambda", false); + + void processMCK0sLambda(ResoMCCols::iterator const& resoMCCollision, + soa::Join const& resoMCV0s) { - // TODO: Implement MC truth matching for K± + Lambda - // - Match reconstructed kaons to MC kaons - // - Match reconstructed Lambdas to MC Lambdas - // - Fill MC truth histograms - // - Fill reconstruction efficiency histograms + if (additionalConfig.cRecoINELgt0 && !resoMCCollision.isRecINELgt0()) + return; // skip event if RecoINEL>0 selection is enabled and event does not pass it + if (!resoMCCollision.isInAfterAllCuts()) // MC event selection + return; + fillK0sLambda(resoMCCollision, resoMCV0s, resoMCV0s); } - PROCESS_SWITCH(Xi1820Analysis, processMCWithTracks, "Process MC with ResoTracks (placeholder)", false); + PROCESS_SWITCH(Xi1820Analysis, processMCK0sLambda, "Process MC K0s + Lambda", false); - void processMCWithMicroTracks(const aod::ResoCollision& /*collision*/, - aod::ResoV0s const& /*resov0s*/, - aod::ResoMicroTracks const& /*resomicrotracks*/, + void processMCWithMicroTracks(const aod::ResoCollision& /*resoCollision*/, + aod::ResoV0s const& /*resoV0s*/, + aod::ResoMicroTracks const& /*resoMicroTracks*/, aod::McParticles const& /*mcParticles*/) { // TODO: Implement MC truth matching for K± + Lambda with MicroTracks + // But is this really necessary? -> Most of the injected MC sizes are already within small-train limit. } PROCESS_SWITCH(Xi1820Analysis, processMCWithMicroTracks, "Process MC with ResoMicroTracks (placeholder)", false); - void processMCK0sLambda(const aod::ResoCollision& /*collision*/, - aod::ResoV0s const& /*resov0s*/, - aod::McParticles const& /*mcParticles*/) + void processMCGen(ResoMCCols::iterator const& resoCollision, // Calculate denominator for the acceptance x efficiency and a part of Event-factor (for selected evennts) + aod::ResoMCParents const& resoParents) { - // TODO: Implement MC truth matching for K0s + Lambda - // - Match reconstructed K0s to MC K0s - // - Match reconstructed Lambdas to MC Lambdas - // - Fill MC truth histograms - // - Fill reconstruction efficiency histograms + auto multiplicity = resoCollision.mcMultiplicity(); + auto inCent = resoCollision.cent(); + if (additionalConfig.cRecoINELgt0 && !resoCollision.isRecINELgt0()) // Check reco INELgt0 + return; + if (!resoCollision.isInAfterAllCuts()) + return; + histos.fill(HIST("multQA/h2MultCentMC"), inCent, multiplicity); + for (const auto& part : resoParents) { // loop over all pre-filtered Gen particle on selected events + auto pdgMother = part.pdgCode(); + if (std::abs(pdgMother) != kPdgChagedXi1820 && std::abs(pdgMother) != kPdgXi1820Zero) + continue; + if (std::abs(part.y()) >= additionalConfig.cfgRapidityCut) + continue; // skip if rapidity of the particle is outside of cut + auto motherPt = part.pt(); + auto daughter1PDG = part.daughterPDG1(); + auto daughter2PDG = part.daughterPDG2(); + + if (std::abs(pdgMother) == kPdgChagedXi1820) { // Explicity check for the safety. + // K- + Anti-Lambda, K+ + Anti-Lambda + if ((daughter1PDG == PDG_t::kKMinus && daughter2PDG == PDG_t::kLambda0) || + (daughter1PDG == PDG_t::kLambda0 && daughter2PDG == PDG_t::kKMinus)) { + histos.fill(HIST("MC/hMCGenPtCentMultKminusLambda"), motherPt, inCent, multiplicity); + } else if ((daughter1PDG == PDG_t::kKPlus && daughter2PDG == PDG_t::kLambda0Bar) || + (daughter1PDG == PDG_t::kLambda0Bar && daughter2PDG == PDG_t::kKPlus)) { + histos.fill(HIST("MC/hMCGenPtCentMultKplusAntiLambda"), motherPt, inCent, multiplicity); + } + } else { + // K0s + Lambda, K0s + Anti-Lambda + if ((std::abs(daughter1PDG) == PDG_t::kK0Short && daughter2PDG == PDG_t::kLambda0) || + (daughter1PDG == PDG_t::kLambda0 && std::abs(daughter2PDG) == PDG_t::kK0Short)) { + histos.fill(HIST("MC/hMCGenPtCentMultK0sLambda"), motherPt, inCent, multiplicity); + } else if ((std::abs(daughter1PDG) == PDG_t::kK0Short && daughter2PDG == PDG_t::kLambda0Bar) || + (daughter1PDG == PDG_t::kLambda0Bar && std::abs(daughter2PDG) == PDG_t::kK0Short)) { + histos.fill(HIST("MC/hMCGenPtCentMultK0sAntiLambda"), motherPt, inCent, multiplicity); + } + } + } } - PROCESS_SWITCH(Xi1820Analysis, processMCK0sLambda, "Process MC K0s + Lambda (placeholder)", false); + PROCESS_SWITCH(Xi1820Analysis, processMCGen, "Process Event for MC (Generated at selected events)", false); - void processMCGenerated(aod::McParticles const& mcParticles) + void processMCTruth(aod::McParticles const& mcParticles) // ->Let's keep it and use for injected MC QA...! { // Process MC generated particles (no reconstruction requirement) // Xi(1820)0 PDG code: 123314 (neutral, decays to K+ Lambda or K0s Lambda) @@ -1033,7 +1237,7 @@ struct Xi1820Analysis { // Xi(1820)0: PDG 123314 // Check if it's Xi(1820) or similar resonance - if (std::abs(pdg) != kPdgXi1820) + if (std::abs(pdg) != kPdgChagedXi1820 && std::abs(pdg) != kPdgXi1820Zero) continue; // Fill generated level histograms @@ -1041,9 +1245,9 @@ struct Xi1820Analysis { auto eta = mcParticle.eta(); auto y = mcParticle.y(); - histos.fill(HIST("MC/hMCGenXi1820Pt"), pt); - histos.fill(HIST("MC/hMCGenXi1820PtEta"), pt, eta); - histos.fill(HIST("MC/hMCGenXi1820Y"), y); + histos.fill(HIST("MC/hMCTruthXi1820Pt"), pt); + histos.fill(HIST("MC/hMCTruthXi1820PtEta"), pt, eta); + histos.fill(HIST("MC/hMCTruthXi1820Y"), y); // Get daughters auto daughters = mcParticle.daughters_as(); @@ -1064,43 +1268,42 @@ struct Xi1820Analysis { } iDaughter++; } - pMother = p1 + p2; // Check decay channels auto motherPt = pMother.Pt(); auto motherM = pMother.M(); - // K+ + Lambda - if ((daughter1PDG == PDG_t::kKPlus && daughter2PDG == PDG_t::kLambda0) || - (daughter1PDG == PDG_t::kLambda0 && daughter2PDG == PDG_t::kKPlus)) { - histos.fill(HIST("MC/hMCTruthInvMassKplusLambda"), motherM); - histos.fill(HIST("MC/hMCTruthMassPtKplusLambda"), motherM, motherPt); + // K- + Lambda + if ((daughter1PDG == PDG_t::kKMinus && daughter2PDG == PDG_t::kLambda0) || + (daughter1PDG == PDG_t::kLambda0 && daughter2PDG == PDG_t::kKMinus)) { + histos.fill(HIST("MC/hMCTruthInvMassKminusLambda"), motherM); + histos.fill(HIST("MC/hMCTruthMassPtKminusLambda"), motherM, motherPt); } - // K- + Anti-Lambda - if ((daughter1PDG == PDG_t::kKMinus && daughter2PDG == PDG_t::kLambda0Bar) || - (daughter1PDG == PDG_t::kLambda0Bar && daughter2PDG == PDG_t::kKMinus)) { - histos.fill(HIST("MC/hMCTruthInvMassKminusAntiLambda"), motherM); - histos.fill(HIST("MC/hMCTruthMassPtKminusAntiLambda"), motherM, motherPt); + // K+ + Anti-Lambda + if ((daughter1PDG == PDG_t::kKPlus && daughter2PDG == PDG_t::kLambda0Bar) || + (daughter1PDG == PDG_t::kLambda0Bar && daughter2PDG == PDG_t::kKPlus)) { + histos.fill(HIST("MC/hMCTruthInvMassKplusAntiLambda"), motherM); + histos.fill(HIST("MC/hMCTruthMassPtKplusAntiLambda"), motherM, motherPt); } // K0s + Lambda - if ((daughter1PDG == PDG_t::kK0Short && daughter2PDG == PDG_t::kLambda0) || - (daughter1PDG == PDG_t::kLambda0 && daughter2PDG == PDG_t::kK0Short)) { + if ((std::abs(daughter1PDG) == PDG_t::kK0Short && daughter2PDG == PDG_t::kLambda0) || + (daughter1PDG == PDG_t::kLambda0 && std::abs(daughter2PDG) == PDG_t::kK0Short)) { histos.fill(HIST("MC/hMCTruthInvMassK0sLambda"), motherM); histos.fill(HIST("MC/hMCTruthMassPtK0sLambda"), motherM, motherPt); } // K0s + Anti-Lambda - if ((daughter1PDG == PDG_t::kK0Short && daughter2PDG == PDG_t::kLambda0Bar) || - (daughter1PDG == PDG_t::kLambda0Bar && daughter2PDG == PDG_t::kK0Short)) { + if ((std::abs(daughter1PDG) == PDG_t::kK0Short && daughter2PDG == PDG_t::kLambda0Bar) || + (daughter1PDG == PDG_t::kLambda0Bar && std::abs(daughter2PDG) == PDG_t::kK0Short)) { histos.fill(HIST("MC/hMCTruthInvMassK0sAntiLambda"), motherM); histos.fill(HIST("MC/hMCTruthMassPtK0sAntiLambda"), motherM, motherPt); } } } - PROCESS_SWITCH(Xi1820Analysis, processMCGenerated, "Process MC generated particles", false); + PROCESS_SWITCH(Xi1820Analysis, processMCTruth, "Process MC Truth particles", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) From cadaa099c062ce14f28b114e4ec0f06931ca72a8 Mon Sep 17 00:00:00 2001 From: Mattia Faggin Date: Thu, 26 Feb 2026 09:17:14 +0100 Subject: [PATCH 093/347] [Common] TrackTuner: autodetect pp ref 2024 calibrations. (#15169) --- Common/Tools/TrackTuner.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Common/Tools/TrackTuner.h b/Common/Tools/TrackTuner.h index 665fd395b24..9a04b51be04 100644 --- a/Common/Tools/TrackTuner.h +++ b/Common/Tools/TrackTuner.h @@ -189,6 +189,10 @@ struct TrackTuner : o2::framework::ConfigurableGroup { LOG(info) << "[TrackTuner::getPathInputFileAutomaticFromCCDB]: +++ Run list: 564356 <= runNumber && runNumber <= 564445 +++"; LOG(info) << "[TrackTuner::getPathInputFileAutomaticFromCCDB]: +++ [CASE 5]: OO, 5.36 TeV 2025, period LHC25af: CCDB path Users/m/mfaggin/test/inputsTrackTuner/OO/LHC25af +++"; LOG(info) << "[TrackTuner::getPathInputFileAutomaticFromCCDB]: +++ Run list: 564468 <= runNumber && runNumber <= 564472 +++"; + LOG(info) << "[TrackTuner::getPathInputFileAutomaticFromCCDB]: +++ [CASE 6]: pp, 5.36 TeV 2024, period LHC24ap: CCDB path Users/m/mfaggin/test/inputsTrackTuner/pp2024/ppRef/polarity_positive +++"; + LOG(info) << "[TrackTuner::getPathInputFileAutomaticFromCCDB]: +++ Run list: 559348 <= runNumber && runNumber <= 559387 +++"; + LOG(info) << "[TrackTuner::getPathInputFileAutomaticFromCCDB]: +++ [CASE 7]: pp, 5.36 TeV 2024, period LHC24aq: CCDB path Users/m/mfaggin/test/inputsTrackTuner/pp2024/ppRef/polarity_negative +++"; + LOG(info) << "[TrackTuner::getPathInputFileAutomaticFromCCDB]: +++ Run list: 559408 <= runNumber && runNumber <= 559456 +++"; LOG(info) << "[TrackTuner::getPathInputFileAutomaticFromCCDB]: +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"; LOG(info) << ""; @@ -234,6 +238,22 @@ struct TrackTuner : o2::framework::ConfigurableGroup { pathInputFile = "Users/m/mfaggin/test/inputsTrackTuner/OO/LHC25af"; LOG(info) << "[TrackTuner::getPathInputFileAutomaticFromCCDB]: >>> OO, 5.36 TeV 2025, period LHC25af: CCDB path " << pathInputFile; LOG(info) << " >>> Run list: 564468 <= runNumber && runNumber <= 564472"; + } else if (559348 <= runNumber && runNumber <= 559387) { + /// + /// [CASE 6]: pp, 5.36 TeV 2024, period LHC24ap: CCDB path Users/m/mfaggin/test/inputsTrackTuner/pp2024/ppRef/polarity_positive + /// Run list: 559348 <= runNumber && runNumber <= 559387 + /// + pathInputFile = "Users/m/mfaggin/test/inputsTrackTuner/pp2024/ppRef/polarity_positive"; + LOG(info) << "[TrackTuner::getPathInputFileAutomaticFromCCDB]: >>> pp, 5.36 TeV 2024, period LHC24ap: CCDB path " << pathInputFile; + LOG(info) << " >>> Run list: 559348 <= runNumber && runNumber <= 559387"; + } else if (559408 <= runNumber && runNumber <= 559456) { + /// + /// [CASE 7]: pp, 5.36 TeV 2024, period LHC24aq: CCDB path Users/m/mfaggin/test/inputsTrackTuner/pp2024/ppRef/polarity_negative + /// Run list: 559408 <= runNumber && runNumber <= 559456 + /// + pathInputFile = "Users/m/mfaggin/test/inputsTrackTuner/pp2024/ppRef/polarity_negative"; + LOG(info) << "[TrackTuner::getPathInputFileAutomaticFromCCDB]: >>> pp, 5.36 TeV 2024, period LHC24aq: CCDB path " << pathInputFile; + LOG(info) << " >>> Run list: 559408 <= runNumber && runNumber <= 559456"; } else { LOG(fatal) << "runNumber " << runNumber << " not supported for the autodetection. Please switch to manual configuration of the TrackTuner object. Aborting..."; } From efc65c9e1313b795146791a7dc524f6a49410afb Mon Sep 17 00:00:00 2001 From: creetz16 <79141119+creetz16@users.noreply.github.com> Date: Thu, 26 Feb 2026 12:25:18 +0100 Subject: [PATCH 094/347] [PWGLF] Update MC matching in decay3bodybuilder to include MC bkg in MC output table (#15143) Co-authored-by: Francesco Mazzaschi --- .../Nuspex/decay3bodybuilder.cxx | 162 +++++++++++------- 1 file changed, 99 insertions(+), 63 deletions(-) diff --git a/PWGLF/TableProducer/Nuspex/decay3bodybuilder.cxx b/PWGLF/TableProducer/Nuspex/decay3bodybuilder.cxx index cae41a2bd67..8e1e0431010 100644 --- a/PWGLF/TableProducer/Nuspex/decay3bodybuilder.cxx +++ b/PWGLF/TableProducer/Nuspex/decay3bodybuilder.cxx @@ -123,6 +123,9 @@ struct decay3bodyBuilder { Configurable doVertexQA{"doVertexQA", false, "Flag to fill QA histograms for PV of (selected) events."}; Configurable disableITSROFCut{"disableITSROFCut", false, "Disable ITS ROF border cut"}; + // MC processing options + Configurable doStoreMcBkg{"doStoreMcBkg", false, "Flag to store candidates which were not matched to true H3L/Anti-H3L decaying via three-body decay in MC (i.e. MC background) in the output table"}; + // data processing options Configurable doSkimmedProcessing{"doSkimmedProcessing", false, "Apply Zoroo counting in case of skimmed data input"}; Configurable triggerList{"triggerList", "fTriggerEventF1Proton, fTrackedOmega, fTrackedXi, fOmegaLargeRadius, fDoubleOmega, fOmegaHighMult, fSingleXiYN, fQuadrupleXi, fDoubleXi, fhadronOmega, fOmegaXi, fTripleXi, fOmega, fGammaVeryLowPtEMCAL, fGammaVeryLowPtDCAL, fGammaHighPtEMCAL, fGammaLowPtEMCAL, fGammaVeryHighPtDCAL, fGammaVeryHighPtEMCAL, fGammaLowPtDCAL, fJetNeutralLowPt, fJetNeutralHighPt, fGammaHighPtDCAL, fJetFullLowPt, fJetFullHighPt, fEMCALReadout, fPCMandEE, fPHOSnbar, fPCMHighPtPhoton, fPHOSPhoton, fLD, fPPPHI, fPD, fLLL, fPLL, fPPL, fPPP, fLeadingPtTrack, fHighFt0cFv0Flat, fHighFt0cFv0Mult, fHighFt0Flat, fHighFt0Mult, fHighMultFv0, fHighTrackMult, fHfSingleNonPromptCharm3P, fHfSingleNonPromptCharm2P, fHfSingleCharm3P, fHfPhotonCharm3P, fHfHighPt2P, fHfSigmaC0K0, fHfDoubleCharm2P, fHfBeauty3P, fHfFemto3P, fHfFemto2P, fHfHighPt3P, fHfSigmaCPPK, fHfDoubleCharm3P, fHfDoubleCharmMix, fHfPhotonCharm2P, fHfV0Charm2P, fHfBeauty4P, fHfV0Charm3P, fHfSingleCharm2P, fHfCharmBarToXiBach, fSingleMuHigh, fSingleMuLow, fLMeeHMR, fDiMuon, fDiElectron, fLMeeIMR, fSingleE, fTrackHighPt, fTrackLowPt, fJetChHighPt, fJetChLowPt, fUDdiffLarge, fUDdiffSmall, fITSextremeIonisation, fITSmildIonisation, fH3L3Body, fHe, fH2", "List of triggers used to select events"}; @@ -794,47 +797,56 @@ struct decay3bodyBuilder { // check if daughters have MC particle if (!trackProton.has_mcParticle() || !trackPion.has_mcParticle() || !trackDeuteron.has_mcParticle()) { - continue; - } + if (!doStoreMcBkg) { + continue; // if not storing MC background, skip candidates where at least one daughter is not matched to MC particle + } else { + this3BodyMCInfo.label = -5; // at least one non-matched daughter + // fill analysis table (only McVtx3BodyDatas is filled here) + fillAnalysisTables(); + } + } else { // all daughters are matched to MC particles, get their MC info + // get MC daughter particles + auto mcTrackProton = trackProton.template mcParticle_as(); + auto mcTrackPion = trackPion.template mcParticle_as(); + auto mcTrackDeuteron = trackDeuteron.template mcParticle_as(); + + // set daughter MC info (also for non-matched mothers) + this3BodyMCInfo.daughterPrPdgCode = mcTrackProton.pdgCode(); + this3BodyMCInfo.daughterPiPdgCode = mcTrackPion.pdgCode(); + this3BodyMCInfo.daughterDePdgCode = mcTrackDeuteron.pdgCode(); + this3BodyMCInfo.isDeuteronPrimary = mcTrackDeuteron.isPhysicalPrimary(); + this3BodyMCInfo.genMomProton = mcTrackProton.p(); + this3BodyMCInfo.genMomPion = mcTrackPion.p(); + this3BodyMCInfo.genMomDeuteron = mcTrackDeuteron.p(); + this3BodyMCInfo.genPtProton = mcTrackProton.pt(); + this3BodyMCInfo.genPtPion = mcTrackPion.pt(); + this3BodyMCInfo.genPtDeuteron = mcTrackDeuteron.pt(); + + // daughters are matched to MC, now we check if reco mother is true H3L/Anti-H3l and decayed via three-body decay + this3BodyMCInfo.label = checkH3LTruth(mcTrackProton, mcTrackPion, mcTrackDeuteron); // returns global index of mother if true H3L/Anti-H3L mother decaying via three-body decay, otherwise negative value + + // if not storing MC background, skip candidates where mother is not true H3L/Anti-H3L decaying via three-body decay + if (!doStoreMcBkg && this3BodyMCInfo.label <= 0) { + continue; + } - // get MC daughter particles - auto mcTrackProton = trackProton.template mcParticle_as(); - auto mcTrackPion = trackPion.template mcParticle_as(); - auto mcTrackDeuteron = trackDeuteron.template mcParticle_as(); - - // set daughter MC info (also for non-matched candidates) - this3BodyMCInfo.daughterPrPdgCode = mcTrackProton.pdgCode(); - this3BodyMCInfo.daughterPiPdgCode = mcTrackPion.pdgCode(); - this3BodyMCInfo.daughterDePdgCode = mcTrackDeuteron.pdgCode(); - this3BodyMCInfo.isDeuteronPrimary = mcTrackDeuteron.isPhysicalPrimary(); - this3BodyMCInfo.genMomProton = mcTrackProton.p(); - this3BodyMCInfo.genMomPion = mcTrackPion.p(); - this3BodyMCInfo.genMomDeuteron = mcTrackDeuteron.p(); - this3BodyMCInfo.genPtProton = mcTrackProton.pt(); - this3BodyMCInfo.genPtPion = mcTrackPion.pt(); - this3BodyMCInfo.genPtDeuteron = mcTrackDeuteron.pt(); - - // check if reco mother is true H3L/Anti-H3l - bool isMuonReco; - int motherID = checkH3LTruth(mcTrackProton, mcTrackPion, mcTrackDeuteron, isMuonReco); - - // get generated mother MC info - if (motherID > 0) { - auto mcTrackH3L = mcParticles.rawIteratorAt(motherID); - this3BodyMCInfo.motherPdgCode = mcTrackH3L.pdgCode(); - this3BodyMCInfo.label = motherID; - this3BodyMCInfo.genMomentum = {mcTrackH3L.px(), mcTrackH3L.py(), mcTrackH3L.pz()}; - this3BodyMCInfo.genDecVtx = {mcTrackProton.vx(), mcTrackProton.vy(), mcTrackProton.vz()}; - this3BodyMCInfo.genCt = RecoDecay::sqrtSumOfSquares(mcTrackProton.vx() - mcTrackH3L.vx(), mcTrackProton.vy() - mcTrackH3L.vy(), mcTrackProton.vz() - mcTrackH3L.vz()) * o2::constants::physics::MassHyperTriton / mcTrackH3L.p(); - this3BodyMCInfo.genPhi = mcTrackH3L.phi(); - this3BodyMCInfo.genEta = mcTrackH3L.eta(); - this3BodyMCInfo.genRapidity = mcTrackH3L.y(); - this3BodyMCInfo.isTrueH3L = this3BodyMCInfo.motherPdgCode > 0 ? true : false; - this3BodyMCInfo.isTrueAntiH3L = this3BodyMCInfo.motherPdgCode < 0 ? true : false; - } + // get generated mother MC info for matched candidates + if (this3BodyMCInfo.label > -1) { + auto mcTrackH3L = mcParticles.rawIteratorAt(this3BodyMCInfo.label); + this3BodyMCInfo.motherPdgCode = mcTrackH3L.pdgCode(); + this3BodyMCInfo.genMomentum = {mcTrackH3L.px(), mcTrackH3L.py(), mcTrackH3L.pz()}; + this3BodyMCInfo.genDecVtx = {mcTrackProton.vx(), mcTrackProton.vy(), mcTrackProton.vz()}; + this3BodyMCInfo.genCt = RecoDecay::sqrtSumOfSquares(mcTrackProton.vx() - mcTrackH3L.vx(), mcTrackProton.vy() - mcTrackH3L.vy(), mcTrackProton.vz() - mcTrackH3L.vz()) * o2::constants::physics::MassHyperTriton / mcTrackH3L.p(); + this3BodyMCInfo.genPhi = mcTrackH3L.phi(); + this3BodyMCInfo.genEta = mcTrackH3L.eta(); + this3BodyMCInfo.genRapidity = mcTrackH3L.y(); + this3BodyMCInfo.isTrueH3L = this3BodyMCInfo.motherPdgCode > 0 ? true : false; + this3BodyMCInfo.isTrueAntiH3L = this3BodyMCInfo.motherPdgCode < 0 ? true : false; + } - // fill analysis tables (only McVtx3BodyDatas is filled here) - fillAnalysisTables(); + // fill analysis tables (only McVtx3BodyDatas is filled here) + fillAnalysisTables(); + } // end of check if daughters have MC particle // mark mcParticle as reconstructed if (this3BodyMCInfo.label > -1) { @@ -1179,30 +1191,23 @@ struct decay3bodyBuilder { // ______________________________________________________________ // function to check if a reconstructed mother is a true H3L/Anti-H3L (returns -1 if not) template - int checkH3LTruth(MCTrack3B const& mcParticlePr, MCTrack3B const& mcParticlePi, MCTrack3B const& mcParticleDe, bool& isMuonReco) + int checkH3LTruth(MCTrack3B const& mcParticlePr, MCTrack3B const& mcParticlePi, MCTrack3B const& mcParticleDe) { - if (std::abs(mcParticlePr.pdgCode()) != PDG_t::kProton || std::abs(mcParticleDe.pdgCode()) != o2::constants::physics::Pdg::kDeuteron) { - return -1; - } - // check proton and deuteron mother - int prDeMomID = -1; - for (const auto& motherPr : mcParticlePr.template mothers_as()) { - for (const auto& motherDe : mcParticleDe.template mothers_as()) { - if (motherPr.globalIndex() == motherDe.globalIndex() && std::abs(motherPr.pdgCode()) == o2::constants::physics::Pdg::kHyperTriton) { - prDeMomID = motherPr.globalIndex(); - break; - } - } - } - if (prDeMomID == -1) { - return -1; - } - if (std::abs(mcParticlePi.pdgCode()) != PDG_t::kPiPlus && std::abs(mcParticlePi.pdgCode()) != PDG_t::kMuonMinus) { - return -1; + // return legend + // -4: proton, pion, or deuteron have wrong identity + // -3: proton and pion have a common mother which is a Lambda (i.e., not a direct daughter of hypertriton) + // -2: proton, pion, and deuteron don't have a common mother + // -1: proton, pion, and deuteron have common mother but it's NOT a hypertriton + // global mother ID: proton, pion, and deuteron have common mother and it's a hypertriton + + // first, check identity of MC daughters + if (std::abs(mcParticlePr.pdgCode()) != PDG_t::kProton || std::abs(mcParticleDe.pdgCode()) != o2::constants::physics::Pdg::kDeuteron || (std::abs(mcParticlePi.pdgCode()) != PDG_t::kPiPlus && std::abs(mcParticlePi.pdgCode()) != PDG_t::kMuonMinus)) { + return -4; } // check if the pion track is a muon coming from a pi -> mu + vu decay, if yes, take the mother pi auto mcParticlePiTmp = mcParticlePi; if (std::abs(mcParticlePiTmp.pdgCode()) == PDG_t::kMuonMinus) { + bool isMuonReco = false; for (const auto& motherPi : mcParticlePiTmp.template mothers_as()) { if (std::abs(motherPi.pdgCode()) == PDG_t::kPiPlus) { mcParticlePiTmp = motherPi; @@ -1210,14 +1215,45 @@ struct decay3bodyBuilder { break; } } + // If the track is a muon but none of its mothers is a pi+, treat as wrong identity + if (!isMuonReco) { + return -4; + } + } + + // now first check if the proton and pion have the same mother and it is a Lambda + for (const auto& motherPr : mcParticlePr.template mothers_as()) { + for (const auto& motherPi : mcParticlePiTmp.template mothers_as()) { + if (motherPr.globalIndex() == motherPi.globalIndex() && std::abs(motherPr.pdgCode()) == PDG_t::kLambda0) { + return -3; + } + } } - // now loop over the pion mother - for (const auto& motherPi : mcParticlePiTmp.template mothers_as()) { - if (motherPi.globalIndex() == prDeMomID) { - return motherPi.globalIndex(); + + // now check if all three daughters have the same mother + int momID = -1; + int momPdgCode = 0; + for (const auto& motherPr : mcParticlePr.template mothers_as()) { + for (const auto& motherDe : mcParticleDe.template mothers_as()) { + for (const auto& motherPi : mcParticlePiTmp.template mothers_as()) { + if (motherPr.globalIndex() == motherDe.globalIndex() && motherPr.globalIndex() == motherPi.globalIndex()) { + momID = motherPr.globalIndex(); + momPdgCode = motherPr.pdgCode(); + break; + } + } } } - return -1; + if (momID == -1) { + return -2; + } + + // check if the common mother is a hypertriton + if (std::abs(momPdgCode) == o2::constants::physics::Pdg::kHyperTriton) { + return momID; + } else { + return -1; // common mother found but not a hypertriton + } } // ______________________________________________________________ From e4012a09b123160b95100127f7db94802ed54ddd Mon Sep 17 00:00:00 2001 From: Swati <69241911+SwatiSaha-1997@users.noreply.github.com> Date: Thu, 26 Feb 2026 20:06:08 +0530 Subject: [PATCH 095/347] [PWGCF] Added pT dependent DCA cuts (#15176) --- .../Tasks/MeanptFluctuations.cxx | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/PWGCF/EbyEFluctuations/Tasks/MeanptFluctuations.cxx b/PWGCF/EbyEFluctuations/Tasks/MeanptFluctuations.cxx index a517e00f62a..2040a7127a7 100644 --- a/PWGCF/EbyEFluctuations/Tasks/MeanptFluctuations.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/MeanptFluctuations.cxx @@ -87,6 +87,14 @@ struct MeanptFluctuationsAnalysis { Configurable cfgEvSelUseGoodZvtxFT0vsPV{"cfgEvSelUseGoodZvtxFT0vsPV", true, "GoodZvertex and FT0 vs PV cut"}; Configurable cfgCentralityEstimator{"cfgCentralityEstimator", 1, "Centrlaity estimatore choice: 1-->FT0C, 2-->FT0A; 3-->FT0M, 4-->FV0A"}; + // pT dep DCAxy and DCAz cuts + Configurable cfgUsePtDepDCAxy{"cfgUsePtDepDCAxy", true, "Use pt-dependent DCAxy cut"}; + Configurable cfgUsePtDepDCAz{"cfgUsePtDepDCAz", true, "Use pt-dependent DCAz cut"}; + O2_DEFINE_CONFIGURABLE(cfgDCAxyFunc, std::string, "(0.0026+0.005/(x^1.01))", "Functional form of pt-dependent DCAxy cut"); + O2_DEFINE_CONFIGURABLE(cfgDCAzFunc, std::string, "(0.0026+0.005/(x^1.01))", "Functional form of pt-dependent DCAz cut"); + TF1* fPtDepDCAxy = nullptr; + TF1* fPtDepDCAz = nullptr; + O2_DEFINE_CONFIGURABLE(cfgEvSelMultCorrelation, bool, true, "Multiplicity correlation cut") O2_DEFINE_CONFIGURABLE(cfgEvSelV0AT0ACut, bool, true, "V0A T0A 5 sigma cut") struct : ConfigurableGroup { @@ -183,6 +191,8 @@ struct MeanptFluctuationsAnalysis { histos.add("hDcaZ", ";#it{dca}_{Z}", kTH1F, {{1000, -5, 5}}); histos.add("his2DdcaXYvsPt", "", {HistType::kTH2D, {ptAxis, {1000, -1, 1}}}); histos.add("his2DdcaZvsPt", "", {HistType::kTH2D, {ptAxis, {1000, -1, 1}}}); + histos.add("his2DdcaXYvsPtPtBeforePtDepSel", "", {HistType::kTH2D, {ptAxis, {1000, -1, 1}}}); + histos.add("his2DdcaZvsPtPtBeforePtDepSel", "", {HistType::kTH2D, {ptAxis, {1000, -1, 1}}}); histos.add("hMeanPt", "", kTProfile, {centAxis}); histos.add("Hist2D_globalTracks_PVTracks", "", {HistType::kTH2D, {nchAxis, nchAxis}}); histos.add("Hist2D_cent_nch", "", {HistType::kTH2D, {nchAxis, centAxis}}); @@ -300,6 +310,13 @@ struct MeanptFluctuationsAnalysis { cfgFuncParas.fT0AV0ASigma->SetParameters(463.4144, 6.796509e-02, -9.097136e-07, 7.971088e-12, -2.600581e-17); } + if (cfgUsePtDepDCAxy) { + fPtDepDCAxy = new TF1("ptDepDCAxy", Form("%s", cfgDCAxyFunc->c_str()), 0.001, 1000); + } + if (cfgUsePtDepDCAz) { + fPtDepDCAz = new TF1("ptDepDCAz", Form("%s", cfgDCAzFunc->c_str()), 0.001, 1000); + } + } //! end init function template @@ -649,6 +666,16 @@ struct MeanptFluctuationsAnalysis { continue; } + histos.fill(HIST("his2DdcaXYvsPtBeforePtDepSel"), track.pt(), track.dcaXY()); + histos.fill(HIST("his2DdcaZvsPtPtBeforePtDepSel"), track.pt(), track.dcaZ()); + + if (cfgUsePtDepDCAxy && !(std::abs(track.dcaXY()) < fPtDepDCAxy->Eval(track.pt()))) { + continue; + } + if (cfgUsePtDepDCAz && !(std::abs(track.dcaZ()) < fPtDepDCAz->Eval(track.pt()))) { + continue; + } + if (particle.isPhysicalPrimary()) { if ((particle.pt() > cfgCutPtLower) && (particle.pt() < cfgCutPreSelPt) && (std::abs(particle.eta()) < cfgCutPreSelEta)) { histos.fill(HIST("hP"), track.p()); @@ -776,6 +803,16 @@ struct MeanptFluctuationsAnalysis { continue; } + histos.fill(HIST("his2DdcaXYvsPtBeforePtDepSel"), track.pt(), track.dcaXY()); + histos.fill(HIST("his2DdcaZvsPtPtBeforePtDepSel"), track.pt(), track.dcaZ()); + + if (cfgUsePtDepDCAxy && !(std::abs(track.dcaXY()) < fPtDepDCAxy->Eval(track.pt()))) { + continue; + } + if (cfgUsePtDepDCAz && !(std::abs(track.dcaZ()) < fPtDepDCAz->Eval(track.pt()))) { + continue; + } + histos.fill(HIST("hP"), track.p()); histos.fill(HIST("hPt"), track.pt()); histos.fill(HIST("hEta"), track.eta()); From 3ec94ecfba72f7fe3824329fb790f2cc9db8551f Mon Sep 17 00:00:00 2001 From: Jesper Karlsson Gumprecht <113693781+jesgum@users.noreply.github.com> Date: Thu, 26 Feb 2026 16:18:34 +0100 Subject: [PATCH 096/347] [ALICE3] Add DCAFitterN QA (#15164) --- .../TableProducer/alice3MulticharmFinder.cxx | 48 +++++++++++++++++++ .../TableProducer/alice3strangenessFinder.cxx | 25 ++++++++++ 2 files changed, 73 insertions(+) diff --git a/ALICE3/TableProducer/alice3MulticharmFinder.cxx b/ALICE3/TableProducer/alice3MulticharmFinder.cxx index e66708bd911..79437c2a1a2 100644 --- a/ALICE3/TableProducer/alice3MulticharmFinder.cxx +++ b/ALICE3/TableProducer/alice3MulticharmFinder.cxx @@ -227,6 +227,9 @@ struct Alice3MulticharmFinder { if (nCand == 0) { return false; } + + const u_int8_t fitterStatusCode = fitter.getFitStatus(); + histos.fill(HIST("hFitterStatusCode"), fitterStatusCode); //}-{}-{}-{}-{}-{}-{}-{}-{}-{} o2::track::TrackParCov t0new = fitter.getTrack(0); @@ -298,6 +301,9 @@ struct Alice3MulticharmFinder { if (nCand == 0) { return false; } + + const u_int8_t fitter3StatusCode = fitter3.getFitStatus(); + histos.fill(HIST("hFitter3StatusCode"), fitter3StatusCode); //}-{}-{}-{}-{}-{}-{}-{}-{}-{} t0 = fitter3.getTrack(0); @@ -433,6 +439,48 @@ struct Alice3MulticharmFinder { fitter3.setBz(magneticField); fitter3.setMatCorrType(o2::base::Propagator::MatCorrType::USEMatCorrNONE); + auto hFitterStatusCode = histos.add("hFitterStatusCode", "hFitterStatusCode", kTH1D, {{15, -0.5, 14.5}}); + hFitterStatusCode->GetXaxis()->SetBinLabel(1, "None"); // no status set (should not be possible!) + + /* Good Conditions */ + hFitterStatusCode->GetXaxis()->SetBinLabel(2, "Converged"); // fit converged + hFitterStatusCode->GetXaxis()->SetBinLabel(3, "MaxIter"); // max iterations reached before fit convergence + + /* Error Conditions */ + hFitterStatusCode->GetXaxis()->SetBinLabel(4, "NoCrossing"); // no reasaonable crossing was found + hFitterStatusCode->GetXaxis()->SetBinLabel(5, "RejRadius"); // radius of crossing was not acceptable + hFitterStatusCode->GetXaxis()->SetBinLabel(6, "RejTrackX"); // one candidate track x was below the mimimum required radius + hFitterStatusCode->GetXaxis()->SetBinLabel(7, "RejTrackRoughZ"); // rejected by rough cut on tracks Z difference + hFitterStatusCode->GetXaxis()->SetBinLabel(8, "RejChi2Max"); // rejected by maximum chi2 cut + hFitterStatusCode->GetXaxis()->SetBinLabel(9, "FailProp"); // propagation of at least prong to PCA failed + hFitterStatusCode->GetXaxis()->SetBinLabel(10, "FailInvCov"); // inversion of cov.-matrix failed + hFitterStatusCode->GetXaxis()->SetBinLabel(11, "FailInvWeight"); // inversion of Ti weight matrix failed + hFitterStatusCode->GetXaxis()->SetBinLabel(12, "FailInv2ndDeriv"); // inversion of 2nd derivatives failed + hFitterStatusCode->GetXaxis()->SetBinLabel(13, "FailCorrTracks"); // correction of tracks to updated x failed + hFitterStatusCode->GetXaxis()->SetBinLabel(14, "FailCloserAlt"); // alternative PCA is closer + hFitterStatusCode->GetXaxis()->SetBinLabel(15, "NStatusesDefined"); + + auto hFitter3StatusCode = histos.add("hFitter3StatusCode", "hFitter3StatusCode", kTH1D, {{15, -0.5, 14.5}}); + hFitter3StatusCode->GetXaxis()->SetBinLabel(1, "None"); // no status set (should not be possible!) + + /* Good Conditions */ + hFitter3StatusCode->GetXaxis()->SetBinLabel(2, "Converged"); // fit converged + hFitter3StatusCode->GetXaxis()->SetBinLabel(3, "MaxIter"); // max iterations reached before fit convergence + + /* Error Conditions */ + hFitter3StatusCode->GetXaxis()->SetBinLabel(4, "NoCrossing"); // no reasaonable crossing was found + hFitter3StatusCode->GetXaxis()->SetBinLabel(5, "RejRadius"); // radius of crossing was not acceptable + hFitter3StatusCode->GetXaxis()->SetBinLabel(6, "RejTrackX"); // one candidate track x was below the mimimum required radius + hFitter3StatusCode->GetXaxis()->SetBinLabel(7, "RejTrackRoughZ"); // rejected by rough cut on tracks Z difference + hFitter3StatusCode->GetXaxis()->SetBinLabel(8, "RejChi2Max"); // rejected by maximum chi2 cut + hFitter3StatusCode->GetXaxis()->SetBinLabel(9, "FailProp"); // propagation of at least prong to PCA failed + hFitter3StatusCode->GetXaxis()->SetBinLabel(10, "FailInvCov"); // inversion of cov.-matrix failed + hFitter3StatusCode->GetXaxis()->SetBinLabel(11, "FailInvWeight"); // inversion of Ti weight matrix failed + hFitter3StatusCode->GetXaxis()->SetBinLabel(12, "FailInv2ndDeriv"); // inversion of 2nd derivatives failed + hFitter3StatusCode->GetXaxis()->SetBinLabel(13, "FailCorrTracks"); // correction of tracks to updated x failed + hFitter3StatusCode->GetXaxis()->SetBinLabel(14, "FailCloserAlt"); // alternative PCA is closer + hFitter3StatusCode->GetXaxis()->SetBinLabel(15, "NStatusesDefined"); + INSERT_HIST(std::string("h2dGenXi"), "h2dGenXi", {kTH2D, {{axisPt, axisEta}}}); INSERT_HIST(std::string("h2dGenXiC"), "h2dGenXiC", {kTH2D, {{axisPt, axisEta}}}); INSERT_HIST(std::string("h2dGenXiCC"), "h2dGenXiCC", {kTH2D, {{axisPt, axisEta}}}); diff --git a/ALICE3/TableProducer/alice3strangenessFinder.cxx b/ALICE3/TableProducer/alice3strangenessFinder.cxx index 2d36590ede0..f2a60b5ab8c 100644 --- a/ALICE3/TableProducer/alice3strangenessFinder.cxx +++ b/ALICE3/TableProducer/alice3strangenessFinder.cxx @@ -44,6 +44,7 @@ #include #include +#include using namespace o2; // using namespace o2::analysis; @@ -153,6 +154,27 @@ struct Alice3strangenessFinder { fitter.setMatCorrType(o2::base::Propagator::MatCorrType::USEMatCorrNONE); histos.add("hFitterQA", "", kTH1D, {{10, 0, 10}}); // For QA reasons, counting found candidates at different stages + auto hFitterStatusCode = histos.add("hFitterStatusCode", "hFitterStatusCode", kTH1D, {{15, -0.5, 14.5}}); + hFitterStatusCode->GetXaxis()->SetBinLabel(1, "None"); // no status set (should not be possible!) + + /* Good Conditions */ + hFitterStatusCode->GetXaxis()->SetBinLabel(2, "Converged"); // fit converged + hFitterStatusCode->GetXaxis()->SetBinLabel(3, "MaxIter"); // max iterations reached before fit convergence + + /* Error Conditions */ + hFitterStatusCode->GetXaxis()->SetBinLabel(4, "NoCrossing"); // no reasaonable crossing was found + hFitterStatusCode->GetXaxis()->SetBinLabel(5, "RejRadius"); // radius of crossing was not acceptable + hFitterStatusCode->GetXaxis()->SetBinLabel(6, "RejTrackX"); // one candidate track x was below the mimimum required radius + hFitterStatusCode->GetXaxis()->SetBinLabel(7, "RejTrackRoughZ"); // rejected by rough cut on tracks Z difference + hFitterStatusCode->GetXaxis()->SetBinLabel(8, "RejChi2Max"); // rejected by maximum chi2 cut + hFitterStatusCode->GetXaxis()->SetBinLabel(9, "FailProp"); // propagation of at least prong to PCA failed + hFitterStatusCode->GetXaxis()->SetBinLabel(10, "FailInvCov"); // inversion of cov.-matrix failed + hFitterStatusCode->GetXaxis()->SetBinLabel(11, "FailInvWeight"); // inversion of Ti weight matrix failed + hFitterStatusCode->GetXaxis()->SetBinLabel(12, "FailInv2ndDeriv"); // inversion of 2nd derivatives failed + hFitterStatusCode->GetXaxis()->SetBinLabel(13, "FailCorrTracks"); // correction of tracks to updated x failed + hFitterStatusCode->GetXaxis()->SetBinLabel(14, "FailCloserAlt"); // alternative PCA is closer + hFitterStatusCode->GetXaxis()->SetBinLabel(15, "NStatusesDefined"); + histos.add("hPtPosDau", "", kTH1D, {axisPt}); histos.add("hPtNegDau", "", kTH1D, {axisPt}); histos.add("hPtPosDauAfterV0Finding", "", kTH2D, {axisPt, axisPt}); @@ -220,6 +242,9 @@ struct Alice3strangenessFinder { } catch (...) { return false; } + + const u_int8_t fitterStatusCode = fitter.getFitStatus(); + histos.fill(HIST("hFitterStatusCode"), fitterStatusCode); histos.fill(HIST("hFitterQA"), 1.5); if (nCand == 0) { LOG(info) << "0 candidates found by fitter"; From 013877fbbe407f2a8c8b1272b6234ddae8da3feb Mon Sep 17 00:00:00 2001 From: rbailhac Date: Thu, 26 Feb 2026 16:18:50 +0100 Subject: [PATCH 097/347] [ALICE3] Fix name of histogram in dilepton task (#15150) --- ALICE3/Tasks/alice3-dilepton.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ALICE3/Tasks/alice3-dilepton.cxx b/ALICE3/Tasks/alice3-dilepton.cxx index bb142b11834..4ed9ee35a87 100644 --- a/ALICE3/Tasks/alice3-dilepton.cxx +++ b/ALICE3/Tasks/alice3-dilepton.cxx @@ -642,7 +642,7 @@ struct Alice3Dilepton { } // end of mc particle loop registry.fill(HIST("Generated/Particle/ParticlesPerEvent"), nParticlesInEvent); - registry.fill(HIST("Generated/Particle/ParticlesFIT"), nParticlesFIT); + registry.fill(HIST("Generated/Particle/ParticlesFit"), nParticlesFIT); auto neg_mcParticles_coll = neg_mcParticles->sliceByCached(o2::aod::mcparticle::mcCollisionId, mccollision.globalIndex(), cache_mc); auto pos_mcParticles_coll = pos_mcParticles->sliceByCached(o2::aod::mcparticle::mcCollisionId, mccollision.globalIndex(), cache_mc); From 507f0118b6fa7a3772077e16e76ae82cd1a90755 Mon Sep 17 00:00:00 2001 From: nzardosh Date: Thu, 26 Feb 2026 17:02:04 +0100 Subject: [PATCH 098/347] =?UTF-8?q?[PWGJE]=20add=20particle=20selection=20?= =?UTF-8?q?to=20trigger=20track=20selections=20at=20MC=20level=20for=20se?= =?UTF-8?q?=E2=80=A6=20(#15179)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- PWGJE/TableProducer/derivedDataSelector.cxx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/PWGJE/TableProducer/derivedDataSelector.cxx b/PWGJE/TableProducer/derivedDataSelector.cxx index fcd4c3f5ffe..5fae719fe60 100644 --- a/PWGJE/TableProducer/derivedDataSelector.cxx +++ b/PWGJE/TableProducer/derivedDataSelector.cxx @@ -369,6 +369,14 @@ struct JetDerivedDataSelector { continue; } } + if constexpr (std::is_same_v, aod::JMcParticles>) { + if (!selectionObject.isPhysicalPrimary()) { + continue; + } + if (selectionObject.pt() < config.trackPtSelectionMin || std::abs(selectionObject.eta()) > config.trackEtaSelectionMax) { + continue; + } + } if (selectionObject.pt() >= selectionObjectPtMin) { isTriggerObject = true; } From 26e161569dcbd996bbf7752902f98af01f62f1c9 Mon Sep 17 00:00:00 2001 From: Fan Si <147278151+fsii@users.noreply.github.com> Date: Thu, 26 Feb 2026 18:41:52 +0100 Subject: [PATCH 099/347] [PWGCF] Add QA for pos./neg. tracks in task partNumFluc.cxx (#15182) --- PWGCF/EbyEFluctuations/Tasks/partNumFluc.cxx | 253 +++++++++++-------- 1 file changed, 153 insertions(+), 100 deletions(-) diff --git a/PWGCF/EbyEFluctuations/Tasks/partNumFluc.cxx b/PWGCF/EbyEFluctuations/Tasks/partNumFluc.cxx index d339999e23e..314f3dcd5ec 100644 --- a/PWGCF/EbyEFluctuations/Tasks/partNumFluc.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/partNumFluc.cxx @@ -548,13 +548,20 @@ struct HolderEvent { std::int32_t runIndex = 0; std::int32_t runGroupIndex = 0; double vz = 0.; - std::int32_t nGlobalTracks = 0; - std::int32_t nPvContributors = 0; - double meanDcaXy = 0.; - double meanSquareDcaXy = 0.; - double meanDcaZ = 0.; - double meanSquareDcaZ = 0.; - std::int32_t nTofBeta = 0; + std::int32_t nGlobalTracksP = 0; + std::int32_t nGlobalTracksM = 0; + std::int32_t nPvContributorsP = 0; + std::int32_t nPvContributorsM = 0; + double meanDcaXyP = 0.; + double meanDcaXyM = 0.; + double meanSquareDcaXyP = 0.; + double meanSquareDcaXyM = 0.; + double meanDcaZP = 0.; + double meanDcaZM = 0.; + double meanSquareDcaZP = 0.; + double meanSquareDcaZM = 0.; + std::int32_t nTofBetaP = 0; + std::int32_t nTofBetaM = 0; double centrality = 0.; std::int32_t subgroupIndex = 0; std::int32_t nChPMc = 0; @@ -576,13 +583,20 @@ struct HolderEvent { runIndex = 0; runGroupIndex = 0; vz = 0.; - nGlobalTracks = 0; - nPvContributors = 0; - meanDcaXy = 0.; - meanSquareDcaXy = 0.; - meanDcaZ = 0.; - meanSquareDcaZ = 0.; - nTofBeta = 0; + nGlobalTracksP = 0; + nGlobalTracksM = 0; + nPvContributorsP = 0; + nPvContributorsM = 0; + meanDcaXyP = 0.; + meanDcaXyM = 0.; + meanSquareDcaXyP = 0.; + meanSquareDcaXyM = 0.; + meanDcaZP = 0.; + meanDcaZM = 0.; + meanSquareDcaZP = 0.; + meanSquareDcaZM = 0.; + nTofBetaP = 0; + nTofBetaM = 0; centrality = 0.; subgroupIndex = 0; nChPMc = 0; @@ -719,7 +733,7 @@ struct PartNumFluc { struct : ConfigurableGroup { Configurable cfgFlagRejectionRunBad{"cfgFlagRejectionRunBad", true, "Bad run rejection flag"}; - Configurable cfgFlagRejectionRunBadMc{"cfgFlagRejectionRunBadMc", true, "MC bad run rejection flag"}; + Configurable cfgFlagRejectionRunBadMc{"cfgFlagRejectionRunBadMc", false, "MC bad run rejection flag"}; Configurable cfgLabelFlagsRct{"cfgLabelFlagsRct", "CBT_hadronPID", "RCT flags label"}; Configurable cfgBitsSelectionEvent{"cfgBitsSelectionEvent", 0b10000000001101110100000000000000000000000000000000ULL, "Event selection bits"}; Configurable cfgFlagInelEvent{"cfgFlagInelEvent", true, "Flag of requiring inelastic event"}; @@ -1060,25 +1074,34 @@ struct PartNumFluc { } hrCounter.add("hNEvents", ";;No. of Events", {HistType::kTH1D, {{10 + aod::evsel::EventSelectionFlags::kNsel, -0.5, 9.5 + static_cast(aod::evsel::EventSelectionFlags::kNsel), "Selection"}}}); - hrCounter.add("hNMcEvents", ";;No. of MC Events", {HistType::kTH1D, {{10, -0.5, 9.5, "Selection"}}}); + if (doprocessMc.value) { + hrCounter.add("hNMcEvents", ";;No. of MC Events", {HistType::kTH1D, {{10, -0.5, 9.5, "Selection"}}}); + } if (groupAnalysis.cfgFlagQaRun.value) { LOG(info) << "Enabling run QA."; - HistogramConfigSpec hcsQaRun(HistType::kTProfile, {{static_cast(holderCcdb.runNumbersIndicesGroupIndices.size()), -0.5, holderCcdb.runNumbersIndicesGroupIndices.size() - 0.5, "Run Index"}}); + const HistogramConfigSpec hcsQaRun(HistType::kTProfile, {{static_cast(holderCcdb.runNumbersIndicesGroupIndices.size()), -0.5, holderCcdb.runNumbersIndicesGroupIndices.size() - 0.5, "Run Index"}}); hrQaRun.add("QaRun/pRunIndexVx", ";;#LT#it{V}_{#it{x}}#GT (cm)", hcsQaRun); hrQaRun.add("QaRun/pRunIndexVy", ";;#LT#it{V}_{#it{y}}#GT (cm)", hcsQaRun); hrQaRun.add("QaRun/pRunIndexVz", ";;#LT#it{V}_{#it{z}}#GT (cm)", hcsQaRun); hrQaRun.add("QaRun/pRunIndexMultFt0a", ";;FT0A #LTMultiplicity#GT", hcsQaRun); hrQaRun.add("QaRun/pRunIndexMultFt0c", ";;FT0C #LTMultiplicity#GT", hcsQaRun); - hrQaRun.add("QaRun/pRunIndexNGlobalTracks", ";;#LTnGlobalTracks#GT", hcsQaRun); - hrQaRun.add("QaRun/pRunIndexNPvContributors", ";;#LTnPvContributors#GT", hcsQaRun); - hrQaRun.add("QaRun/pRunIndexMeanDcaXy", ";;#LT#LTDCA_{#it{xy}}#GT_{event}#GT (cm)", hcsQaRun); - hrQaRun.add("QaRun/pRunIndexSigmaDcaXy", ";;#LT#it{#sigma}(DCA_{#it{xy}})_{event}#GT (cm)", hcsQaRun); - hrQaRun.add("QaRun/pRunIndexMeanDcaZ", ";;#LT#LTDCA_{#it{z}}#GT_{event}#GT (cm)", hcsQaRun); - hrQaRun.add("QaRun/pRunIndexSigmaDcaZ", ";;#LT#it{#sigma}(DCA_{#it{z}})_{event}#GT (cm)", hcsQaRun); - hrQaRun.add("QaRun/pRunIndexNTofBeta", ";;#LTnTofBeta#GT", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexNGlobalTracks_p", ";;#LTnGlobalTracks#GT (#it{q}>0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexNGlobalTracks_m", ";;#LTnGlobalTracks#GT (#it{q}<0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexNPvContributors_p", ";;#LTnPvContributors#GT (#it{q}>0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexNPvContributors_m", ";;#LTnPvContributors#GT (#it{q}<0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexMeanDcaXy_p", ";;#LT#LTDCA_{#it{xy}}#GT_{event}#GT (cm) (#it{q}>0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexMeanDcaXy_m", ";;#LT#LTDCA_{#it{xy}}#GT_{event}#GT (cm) (#it{q}<0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexSigmaDcaXy_p", ";;#LT#it{#sigma}(DCA_{#it{xy}})_{event}#GT (cm) (#it{q}>0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexSigmaDcaXy_m", ";;#LT#it{#sigma}(DCA_{#it{xy}})_{event}#GT (cm) (#it{q}<0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexMeanDcaZ_p", ";;#LT#LTDCA_{#it{z}}#GT_{event}#GT (cm) (#it{q}>0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexMeanDcaZ_m", ";;#LT#LTDCA_{#it{z}}#GT_{event}#GT (cm) (#it{q}<0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexSigmaDcaZ_p", ";;#LT#it{#sigma}(DCA_{#it{z}})_{event}#GT (cm) (#it{q}>0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexSigmaDcaZ_m", ";;#LT#it{#sigma}(DCA_{#it{z}})_{event}#GT (cm) (#it{q}<0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexNTofBeta_p", ";;#LTnTofBeta#GT (#it{q}>0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexNTofBeta_m", ";;#LTnTofBeta#GT (#it{q}<0)", hcsQaRun); hrQaRun.add("QaRun/pRunIndexItsNCls_p", ";;ITS #LTnClusters#GT (#it{q}>0)", hcsQaRun); hrQaRun.add("QaRun/pRunIndexItsNCls_m", ";;ITS #LTnClusters#GT (#it{q}<0)", hcsQaRun); hrQaRun.add("QaRun/pRunIndexItsChi2NCls_p", ";;ITS #LT#it{#chi}^{2}/nClusters#GT (#it{q}>0)", hcsQaRun); @@ -1124,24 +1147,23 @@ struct PartNumFluc { if (groupAnalysis.cfgFlagQaEvent.value) { LOG(info) << "Enabling event QA."; - AxisSpec asRunIndex(static_cast(holderCcdb.runNumbersIndicesGroupIndices.size()), -0.5, holderCcdb.runNumbersIndicesGroupIndices.size() - 0.5, "Run Index"); - AxisSpec asNGlobalTracks(180, -0.5, 179.5, "nGlobalTracks"); + const AxisSpec asNGlobalTracks(200, -0.5, 199.5, "nGlobalTracks"); - hrQaEvent.add("QaEvent/hRunIndexVxVy", "", {HistType::kTHnSparseF, {asRunIndex, {150, -0.15, 0.15, "#it{V}_{#it{x}} (cm)"}, {150, -0.15, 0.15, "#it{V}_{#it{y}} (cm)"}}}); - hrQaEvent.add("QaEvent/hRunIndexVz", "", {HistType::kTH2F, {asRunIndex, {300, -15., 15., "#it{V}_{#it{z}} (cm)"}}}); - hrQaEvent.add("QaEvent/hRunIndexNPvContributorsNGlobalTracks", "", {HistType::kTHnSparseF, {asRunIndex, {180, -0.5, 179.5, "nPvContributors"}, asNGlobalTracks}}); - hrQaEvent.add("QaEvent/hRunIndexNGlobalTracksMeanDcaXy", "", {HistType::kTHnSparseF, {asRunIndex, asNGlobalTracks, {200, -0.5, 0.5, "#LTDCA_{#it{xy}}#GT_{event} (cm)"}}}); - hrQaEvent.add("QaEvent/hRunIndexNGlobalTracksMeanDcaXy_nPvContributorsCut", "", {HistType::kTHnSparseF, {asRunIndex, asNGlobalTracks, {200, -2., 2., "#LTDCA_{#it{z}}#GT_{event} (cm)"}}}); - hrQaEvent.add("QaEvent/hRunIndexNGlobalTracksMeanDcaZ", "", {HistType::kTHnSparseF, {asRunIndex, asNGlobalTracks, {200, -2., 2., "#LTDCA_{#it{z}}#GT_{event} (cm)"}}}); - hrQaEvent.add("QaEvent/hRunIndexNGlobalTracksMeanDcaZ_nPvContributorsCut", "", {HistType::kTHnSparseF, {asRunIndex, asNGlobalTracks, {200, -2., 2., "#LTDCA_{#it{z}}#GT_{event} (cm)"}}}); - hrQaEvent.add("QaEvent/hRunIndexNTofBetaNGlobalTracks", "", {HistType::kTHnSparseF, {asRunIndex, {60, -0.5, 59.5, "nTofBeta"}, asNGlobalTracks}}); - hrQaEvent.add("QaEvent/hRunIndexNTofBetaNGlobalTracks_nPvContributorsCut", "", {HistType::kTHnSparseF, {asRunIndex, {60, -0.5, 59.5, "nTofBeta"}, asNGlobalTracks}}); + hrQaEvent.add("QaEvent/hVxVy", "", {HistType::kTHnSparseD, {{150, -0.15, 0.15, "#it{V}_{#it{x}} (cm)"}, {150, -0.15, 0.15, "#it{V}_{#it{y}} (cm)"}}}); + hrQaEvent.add("QaEvent/hVz", "", {HistType::kTH1D, {{300, -15., 15., "#it{V}_{#it{z}} (cm)"}}}); + hrQaEvent.add("QaEvent/hNPvContributorsNGlobalTracks", "", {HistType::kTHnSparseF, {{200, -0.5, 199.5, "nPvContributors"}, asNGlobalTracks}}); + hrQaEvent.add("QaEvent/hNGlobalTracksMeanDcaXy", "", {HistType::kTHnSparseF, {asNGlobalTracks, {200, -0.5, 0.5, "#LTDCA_{#it{xy}}#GT_{event} (cm)"}}}); + hrQaEvent.add("QaEvent/hNGlobalTracksMeanDcaXy_nPvContributorsCut", "", {HistType::kTHnSparseF, {asNGlobalTracks, {200, -2., 2., "#LTDCA_{#it{z}}#GT_{event} (cm)"}}}); + hrQaEvent.add("QaEvent/hNGlobalTracksMeanDcaZ", "", {HistType::kTHnSparseF, {asNGlobalTracks, {200, -2., 2., "#LTDCA_{#it{z}}#GT_{event} (cm)"}}}); + hrQaEvent.add("QaEvent/hNGlobalTracksMeanDcaZ_nPvContributorsCut", "", {HistType::kTHnSparseF, {asNGlobalTracks, {200, -2., 2., "#LTDCA_{#it{z}}#GT_{event} (cm)"}}}); + hrQaEvent.add("QaEvent/hNTofBetaNGlobalTracks", "", {HistType::kTHnSparseF, {{200, -0.5, 199.5, "nTofBeta"}, asNGlobalTracks}}); + hrQaEvent.add("QaEvent/hNTofBetaNGlobalTracks_nPvContributorsCut", "", {HistType::kTHnSparseF, {{200, -0.5, 199.5, "nTofBeta"}, asNGlobalTracks}}); } if (groupAnalysis.cfgFlagQaCentrality.value) { LOG(info) << "Enabling centrality QA."; - AxisSpec asCentrality(20, 0., 100., "Centrality (%)"); + const AxisSpec asCentrality(20, 0., 100., "Centrality (%)"); hrQaCentrality.add("QaCentrality/hCentralityFt0a", "", {HistType::kTHnSparseF, {asCentrality, {1600, 0., 8000., "FT0A Multiplicity"}}}); hrQaCentrality.add("QaCentrality/hCentralityFt0c", "", {HistType::kTHnSparseF, {asCentrality, {400, 0., 2000., "FT0C Multiplicity"}}}); @@ -1155,37 +1177,37 @@ struct PartNumFluc { hrQaTrack.add("QaTrack/hItsNCls_m", "", {HistType::kTH1D, {{10, -0.5, 9.5, "ITS nClusters"}}}); hrQaTrack.add("QaTrack/hItsChi2NCls_p", "", {HistType::kTH1D, {{80, 0., 40., "ITS #it{#chi}^{2}/nClusters"}}}); hrQaTrack.add("QaTrack/hItsChi2NCls_m", "", {HistType::kTH1D, {{80, 0., 40., "ITS #it{#chi}^{2}/nClusters"}}}); - hrQaTrack.add("QaTrack/hTpcNClsNClsShared_p", "", {HistType::kTH2D, {{180, -0.5, 179.5, "TPC nClusters"}, {180, -0.5, 179.5, "TPC nSharedClusters"}}}); - hrQaTrack.add("QaTrack/hTpcNClsNClsShared_m", "", {HistType::kTH2D, {{180, -0.5, 179.5, "TPC nClusters"}, {180, -0.5, 179.5, "TPC nSharedClusters"}}}); + hrQaTrack.add("QaTrack/hTpcNClsNClsShared_p", "", {HistType::kTHnSparseD, {{180, -0.5, 179.5, "TPC nClusters"}, {180, -0.5, 179.5, "TPC nSharedClusters"}}}); + hrQaTrack.add("QaTrack/hTpcNClsNClsShared_m", "", {HistType::kTHnSparseD, {{180, -0.5, 179.5, "TPC nClusters"}, {180, -0.5, 179.5, "TPC nSharedClusters"}}}); hrQaTrack.add("QaTrack/hTpcChi2NCls_p", "", {HistType::kTH1D, {{100, 0., 5., "TPC #it{#chi}^{2}/nClusters"}}}); hrQaTrack.add("QaTrack/hTpcChi2NCls_m", "", {HistType::kTH1D, {{100, 0., 5., "TPC #it{#chi}^{2}/nClusters"}}}); - hrQaTrack.add("QaTrack/hTpcNClsFindableNCrossedRows_p", "", {HistType::kTH2D, {{180, -0.5, 179.5, "TPC nFindableClusters"}, {180, -0.5, 179.5, "TPC nCrossedRows"}}}); - hrQaTrack.add("QaTrack/hTpcNClsFindableNCrossedRows_m", "", {HistType::kTH2D, {{180, -0.5, 179.5, "TPC nFindableClusters"}, {180, -0.5, 179.5, "TPC nCrossedRows"}}}); + hrQaTrack.add("QaTrack/hTpcNClsFindableNCrossedRows_p", "", {HistType::kTHnSparseD, {{180, -0.5, 179.5, "TPC nFindableClusters"}, {180, -0.5, 179.5, "TPC nCrossedRows"}}}); + hrQaTrack.add("QaTrack/hTpcNClsFindableNCrossedRows_m", "", {HistType::kTHnSparseD, {{180, -0.5, 179.5, "TPC nFindableClusters"}, {180, -0.5, 179.5, "TPC nCrossedRows"}}}); } if (groupAnalysis.cfgFlagQaDca.value) { LOG(info) << "Enabling DCA QA."; - AxisSpec asPt(200, 0., 2., "#it{p}_{T} (GeV/#it{c})"); - AxisSpec asDca(400, -1., 1.); + const AxisSpec asPt(200, 0., 2., "#it{p}_{T} (GeV/#it{c})"); + const AxisSpec asDca(400, -1., 1.); - hrQaDca.add("QaDca/hPtDcaXy_p", ";;DCA_{#it{xy}} (cm)", {HistType::kTH2D, {asPt, asDca}}); - hrQaDca.add("QaDca/hPtDcaXy_m", ";;DCA_{#it{xy}} (cm)", {HistType::kTH2D, {asPt, asDca}}); + hrQaDca.add("QaDca/hPtDcaXy_p", ";;DCA_{#it{xy}} (cm)", {HistType::kTHnSparseD, {asPt, asDca}}); + hrQaDca.add("QaDca/hPtDcaXy_m", ";;DCA_{#it{xy}} (cm)", {HistType::kTHnSparseD, {asPt, asDca}}); hrQaDca.add("QaDca/pPtDcaXy_p", ";;#LTDCA_{#it{xy}}#GT (cm)", {HistType::kTProfile, {asPt}}); hrQaDca.add("QaDca/pPtDcaXy_m", ";;#LTDCA_{#it{xy}}#GT (cm)", {HistType::kTProfile, {asPt}}); - hrQaDca.add("QaDca/hPtDcaZ_p", ";;DCA_{#it{z}} (cm)", {HistType::kTH2D, {asPt, asDca}}); - hrQaDca.add("QaDca/hPtDcaZ_m", ";;DCA_{#it{z}} (cm)", {HistType::kTH2D, {asPt, asDca}}); + hrQaDca.add("QaDca/hPtDcaZ_p", ";;DCA_{#it{z}} (cm)", {HistType::kTHnSparseD, {asPt, asDca}}); + hrQaDca.add("QaDca/hPtDcaZ_m", ";;DCA_{#it{z}} (cm)", {HistType::kTHnSparseD, {asPt, asDca}}); hrQaDca.add("QaDca/pPtDcaZ_p", ";;#LTDCA_{#it{z}}#GT (cm)", {HistType::kTProfile, {asPt}}); hrQaDca.add("QaDca/pPtDcaZ_m", ";;#LTDCA_{#it{z}}#GT (cm)", {HistType::kTProfile, {asPt}}); } if (groupAnalysis.cfgFlagQaAcceptance.value || groupAnalysis.cfgFlagQaAcceptancePi.value || groupAnalysis.cfgFlagQaAcceptanceKa.value || groupAnalysis.cfgFlagQaAcceptancePr.value) { - AxisSpec asPt(250, 0., 2.5, "#it{p}_{T} (GeV/#it{c})"); + const AxisSpec asPt(250, 0., 2.5, "#it{p}_{T} (GeV/#it{c})"); if (groupAnalysis.cfgFlagQaAcceptance.value) { LOG(info) << "Enabling acceptance QA."; - HistogramConfigSpec hcsQaAcceptance(HistType::kTHnSparseF, {{300, -1.5, 1.5, "#it{#eta}"}, asPt}); + const HistogramConfigSpec hcsQaAcceptance(HistType::kTHnSparseD, {{300, -1.5, 1.5, "#it{#eta}"}, asPt}); hrQaAcceptance.add("QaAcceptance/hEtaPt_tpcEdgeP", "", hcsQaAcceptance); hrQaAcceptance.add("QaAcceptance/hEtaPt_tpcEdgeM", "", hcsQaAcceptance); @@ -1194,7 +1216,7 @@ struct PartNumFluc { } if (groupAnalysis.cfgFlagQaAcceptancePi.value || groupAnalysis.cfgFlagQaAcceptanceKa.value || groupAnalysis.cfgFlagQaAcceptancePr.value) { - HistogramConfigSpec hcsQaAcceptance(HistType::kTH2D, {{300, -1.5, 1.5, "#it{y}"}, asPt}); + const HistogramConfigSpec hcsQaAcceptance(HistType::kTHnSparseD, {{300, -1.5, 1.5, "#it{y}"}, asPt}); if (groupAnalysis.cfgFlagQaAcceptancePi.value) { LOG(info) << "Enabling pion acceptance QA."; @@ -1226,7 +1248,7 @@ struct PartNumFluc { } if (groupAnalysis.cfgFlagQaPhi.value || groupAnalysis.cfgFlagQaPhiPi.value || groupAnalysis.cfgFlagQaPhiKa.value || groupAnalysis.cfgFlagQaPhiPr.value) { - HistogramConfigSpec hcsQaPhi(HistType::kTHnSparseF, {{{0., 5., 10., 20., 30., 40., 50., 60., 70., 80., 90.}, "Centrality (%)"}, {20, 0., 2., "#it{p}_{T} (GeV/#it{c})"}, {16, -0.8, 0.8, "#it{#eta}"}, {360, 0., constants::math::TwoPI, "#it{#varphi} (rad)"}}); + const HistogramConfigSpec hcsQaPhi(HistType::kTHnSparseF, {{{0., 5., 10., 20., 30., 40., 50., 60., 70., 80., 90.}, "Centrality (%)"}, {20, 0., 2., "#it{p}_{T} (GeV/#it{c})"}, {16, -0.8, 0.8, "#it{#eta}"}, {360, 0., constants::math::TwoPI, "#it{#varphi} (rad)"}}); if (groupAnalysis.cfgFlagQaPhi.value) { LOG(info) << "Enabling phi QA."; @@ -1318,21 +1340,21 @@ struct PartNumFluc { } if (groupAnalysis.cfgFlagQaPid.value || groupAnalysis.cfgFlagQaPidPi.value || groupAnalysis.cfgFlagQaPidKa.value || groupAnalysis.cfgFlagQaPidPr.value) { - AxisSpec asCentrality({0., 5., 10., 20., 30., 40., 50., 60., 70., 80., 90.}, "Centrality (%)"); + const AxisSpec asCentrality({0., 5., 10., 20., 30., 40., 50., 60., 70., 80., 90.}, "Centrality (%)"); if (groupAnalysis.cfgFlagQaPid.value) { LOG(info) << "Enabling PID QA."; - AxisSpec asPOverQ(350, -3.5, 3.5, "#it{p}/#it{q} (GeV/#it{c})"); - AxisSpec asEta(48, -1.2, 1.2, "#it{#eta}"); + const AxisSpec asPOverQ(350, -3.5, 3.5, "#it{p}/#it{q} (GeV/#it{c})"); + const AxisSpec asEta(48, -1.2, 1.2, "#it{#eta}"); hrQaPid.add("QaPid/hCentralityPOverQEtaTpcLnDeDx", "", {HistType::kTHnSparseF, {asCentrality, asPOverQ, asEta, {240, 3., 9., "TPC ln(d#it{E}/d#it{x} (a.u.))"}}}); hrQaPid.add("QaPid/hCentralityPOverQEtaTofInverseBeta", "", {HistType::kTHnSparseF, {asCentrality, asPOverQ, asEta, {120, 0.5, 3.5, "TOF 1/#it{#beta}"}}}); } if (groupAnalysis.cfgFlagQaPidPi.value || groupAnalysis.cfgFlagQaPidKa.value || groupAnalysis.cfgFlagQaPidPr.value) { - AxisSpec asPt(40, 0., 2., "#it{p}_{T} (GeV/#it{c})"); - AxisSpec asEta(32, -0.8, 0.8, "#it{#eta}"); + const AxisSpec asPt(40, 0., 2., "#it{p}_{T} (GeV/#it{c})"); + const AxisSpec asEta(32, -0.8, 0.8, "#it{#eta}"); if (groupAnalysis.cfgFlagQaPidPi.value) { LOG(info) << "Enabling pion PID QA."; @@ -1400,16 +1422,16 @@ struct PartNumFluc { if (groupAnalysis.cfgFlagQaMc.value) { LOG(info) << "Enabling MC QA."; - AxisSpec asCentrality(20, 0., 100., "Centrality (%)"); + const AxisSpec asCentrality(20, 0., 100., "Centrality (%)"); - hrQaMc.add("QaMc/hCentralityVzVzMc", "", {HistType::kTH3F, {asCentrality, {200, -10., 10., "#it{V}_{#it{z}}^{Rec} (cm)"}, {200, -10., 10., "#it{V}_{#it{z}}^{Gen} (cm)"}}}); + hrQaMc.add("QaMc/hCentralityVzVzMc", "", {HistType::kTHnSparseF, {asCentrality, {200, -10., 10., "#it{V}_{#it{z}}^{Rec} (cm)"}, {200, -10., 10., "#it{V}_{#it{z}}^{Gen} (cm)"}}}); hrQaMc.add("QaMc/hCentralityPtEtaDeltaPt", "", {HistType::kTHnSparseF, {asCentrality, {100, 0., 2., "#it{p}_{T}^{Rec} (GeV/#it{c})"}, {120, -1.2, 1.2, "#it{#eta}_{Rec}"}, {100, -1., 1., "#it{p}_{T}^{Rec}#minus#it{p}_{T}^{Gen} (GeV/#it{c})"}}}); hrQaMc.add("QaMc/hCentralityPtEtaDeltaEta", "", {HistType::kTHnSparseF, {asCentrality, {100, 0., 2., "#it{p}_{T}^{Rec} (GeV/#it{c})"}, {120, -1.2, 1.2, "#it{#eta}_{Rec}"}, {100, -1., 1., "#it{#eta}_{Rec}#minus#it{#eta}_{Gen}"}}}); } } if (groupAnalysis.cfgFlagCalculationYieldPi.value || groupAnalysis.cfgFlagCalculationYieldKa.value || groupAnalysis.cfgFlagCalculationYieldPr.value) { - HistogramConfigSpec hcsCalculationYield(HistType::kTHnSparseF, {{static_cast(std::llrint(std::ceil(groupEvent.cfgCutMaxAbsVertexZ.value))) * 2, -std::ceil(groupEvent.cfgCutMaxAbsVertexZ.value), std::ceil(groupEvent.cfgCutMaxAbsVertexZ.value), "#it{V}_{#it{z}} (cm)"}, {{0., 5., 10., 20., 30., 40., 50., 60., 70., 80., 90.}, "Centrality (%)"}, {20, 0., 2., "#it{p}_{T} (GeV/#it{c})"}, {16, -0.8, 0.8, "#it{#eta}"}, {180, 0., constants::math::TwoPI, "#it{#varphi} (rad)"}}); + const HistogramConfigSpec hcsCalculationYield(HistType::kTHnSparseF, {{static_cast(std::llrint(std::ceil(groupEvent.cfgCutMaxAbsVertexZ.value))) * 2, -std::ceil(groupEvent.cfgCutMaxAbsVertexZ.value), std::ceil(groupEvent.cfgCutMaxAbsVertexZ.value), "#it{V}_{#it{z}} (cm)"}, {{0., 5., 10., 20., 30., 40., 50., 60., 70., 80., 90.}, "Centrality (%)"}, {40, 0., 2., "#it{p}_{T} (GeV/#it{c})"}, {32, -0.8, 0.8, "#it{#eta}"}}); if (groupAnalysis.cfgFlagCalculationYieldPi.value) { LOG(info) << "Enabling pion yield calculation."; @@ -1480,7 +1502,7 @@ struct PartNumFluc { if (doprocessMc.value) { if (groupAnalysis.cfgFlagCalculationPurityPi.value || groupAnalysis.cfgFlagCalculationPurityKa.value || groupAnalysis.cfgFlagCalculationPurityPr.value) { - HistogramConfigSpec hcsCalculationPurity(HistType::kTProfile3D, {{{0., 5., 10., 20., 30., 40., 50., 60., 70., 80., 90.}, "Centrality (%)"}, {20, 0., 2., "#it{p}_{T} (GeV/#it{c})"}, {16, -0.8, 0.8, "#it{#eta}"}}); + const HistogramConfigSpec hcsCalculationPurity(HistType::kTProfile3D, {{{0., 5., 10., 20., 30., 40., 50., 60., 70., 80., 90.}, "Centrality (%)"}, {20, 0., 2., "#it{p}_{T} (GeV/#it{c})"}, {16, -0.8, 0.8, "#it{#eta}"}}); if (groupAnalysis.cfgFlagCalculationPurityPi.value) { LOG(info) << "Enabling pion purity calculation."; @@ -1513,7 +1535,7 @@ struct PartNumFluc { if (doprocessMc.value) { if (groupAnalysis.cfgFlagCalculationFractionPrimaryPi.value || groupAnalysis.cfgFlagCalculationFractionPrimaryKa.value || groupAnalysis.cfgFlagCalculationFractionPrimaryPr.value) { - HistogramConfigSpec hcsCalculationFractionPrimary(HistType::kTProfile3D, {{{0., 5., 10., 20., 30., 40., 50., 60., 70., 80., 90.}, "Centrality (%)"}, {20, 0., 2., "#it{p}_{T} (GeV/#it{c})"}, {16, -0.8, 0.8, "#it{#eta}"}}); + const HistogramConfigSpec hcsCalculationFractionPrimary(HistType::kTProfile3D, {{{0., 5., 10., 20., 30., 40., 50., 60., 70., 80., 90.}, "Centrality (%)"}, {20, 0., 2., "#it{p}_{T} (GeV/#it{c})"}, {16, -0.8, 0.8, "#it{#eta}"}}); if (groupAnalysis.cfgFlagCalculationFractionPrimaryPi.value) { LOG(info) << "Enabling pion primary fraction calculation."; @@ -1547,9 +1569,9 @@ struct PartNumFluc { if (groupAnalysis.cfgFlagCalculationFluctuationCh.value || groupAnalysis.cfgFlagCalculationFluctuationKa.value || groupAnalysis.cfgFlagCalculationFluctuationPr.value) { static constexpr std::int32_t NDimensionsEfficiency = 4; - AxisSpec asCentrality(groupEvent.cfgAxisCentrality, "Centrality (%)"); - HistogramConfigSpec hcsCalculationFluctuation(HistType::kTH3D, {asCentrality, {40, -0.5, 39.5}, {40, -0.5, 39.5}}); - HistogramConfigSpec hcsFluctuationCalculator(HistType::kTH3D, {asCentrality, {groupEvent.cfgNSubgroups.value, -0.5, groupEvent.cfgNSubgroups.value - 0.5, "Subgroup Index"}, {fluctuation_calculator_base::NOrderVectors, -0.5, fluctuation_calculator_base::NOrderVectors - 0.5, "Order Vector Index"}}); + const AxisSpec asCentrality(groupEvent.cfgAxisCentrality, "Centrality (%)"); + const HistogramConfigSpec hcsCalculationFluctuation(HistType::kTHnSparseD, {asCentrality, {50, -0.5, 49.5}, {50, -0.5, 49.5}}); + const HistogramConfigSpec hcsFluctuationCalculator(HistType::kTH3D, {asCentrality, {groupEvent.cfgNSubgroups.value, -0.5, groupEvent.cfgNSubgroups.value - 0.5, "Subgroup Index"}, {fluctuation_calculator_base::NOrderVectors, -0.5, fluctuation_calculator_base::NOrderVectors - 0.5, "Order Vector Index"}}); if (groupAnalysis.cfgFlagCalculationFluctuationCh.value) { holderCcdb.hVzCentralityPtEtaEfficiencyTpcPiP.resize(nRunGroups); @@ -1928,17 +1950,33 @@ struct PartNumFluc { } if constexpr (doInitingEvent) { - if (track.isPrimaryTrack()) { - holderEvent.nGlobalTracks++; - if (track.isPVContributor()) { - holderEvent.nPvContributors++; - } - holderEvent.meanDcaXy += holderTrack.dcaXY; - holderEvent.meanSquareDcaXy += std::pow(holderTrack.dcaXY, 2.); - holderEvent.meanDcaZ += holderTrack.dcaZ; - holderEvent.meanSquareDcaZ += std::pow(holderTrack.dcaZ, 2.); - if (holderTrack.hasTofPid) { - holderEvent.nTofBeta++; + if (holderTrack.sign > 0) { + if (track.isPrimaryTrack()) { + holderEvent.nGlobalTracksP++; + if (track.isPVContributor()) { + holderEvent.nPvContributorsP++; + } + holderEvent.meanDcaXyP += holderTrack.dcaXY; + holderEvent.meanSquareDcaXyP += std::pow(holderTrack.dcaXY, 2.); + holderEvent.meanDcaZP += holderTrack.dcaZ; + holderEvent.meanSquareDcaZP += std::pow(holderTrack.dcaZ, 2.); + if (holderTrack.hasTofPid) { + holderEvent.nTofBetaP++; + } + } + } else if (holderTrack.sign < 0) { + if (track.isPrimaryTrack()) { + holderEvent.nGlobalTracksM++; + if (track.isPVContributor()) { + holderEvent.nPvContributorsM++; + } + holderEvent.meanDcaXyM += holderTrack.dcaXY; + holderEvent.meanSquareDcaXyM += std::pow(holderTrack.dcaXY, 2.); + holderEvent.meanDcaZM += holderTrack.dcaZ; + holderEvent.meanSquareDcaZM += std::pow(holderTrack.dcaZ, 2.); + if (holderTrack.hasTofPid) { + holderEvent.nTofBetaM++; + } } } } @@ -2243,8 +2281,8 @@ struct PartNumFluc { } if (groupAnalysis.cfgFlagQaEvent.value) { - hrQaEvent.fill(HIST("QaEvent/hRunIndexVxVy"), holderEvent.runIndex, collision.posX(), collision.posY()); - hrQaEvent.fill(HIST("QaEvent/hRunIndexVz"), holderEvent.runIndex, holderEvent.vz); + hrQaEvent.fill(HIST("QaEvent/hVxVy"), collision.posX(), collision.posY()); + hrQaEvent.fill(HIST("QaEvent/hVz"), holderEvent.vz); } if (!(std::fabs(holderEvent.vz) < groupEvent.cfgCutMaxAbsVertexZ.value)) { @@ -2267,35 +2305,50 @@ struct PartNumFluc { initTrack(track); } - if (holderEvent.nGlobalTracks > 0.) { - holderEvent.meanDcaXy /= holderEvent.nGlobalTracks; - holderEvent.meanSquareDcaXy /= holderEvent.nGlobalTracks; - holderEvent.meanDcaZ /= holderEvent.nGlobalTracks; - holderEvent.meanSquareDcaZ /= holderEvent.nGlobalTracks; + if (holderEvent.nGlobalTracksP > 0.) { + holderEvent.meanDcaXyP /= holderEvent.nGlobalTracksP; + holderEvent.meanSquareDcaXyP /= holderEvent.nGlobalTracksP; + holderEvent.meanDcaZP /= holderEvent.nGlobalTracksP; + holderEvent.meanSquareDcaZP /= holderEvent.nGlobalTracksP; + } + if (holderEvent.nGlobalTracksM > 0.) { + holderEvent.meanDcaXyM /= holderEvent.nGlobalTracksM; + holderEvent.meanSquareDcaXyM /= holderEvent.nGlobalTracksM; + holderEvent.meanDcaZM /= holderEvent.nGlobalTracksM; + holderEvent.meanSquareDcaZM /= holderEvent.nGlobalTracksM; } if (groupAnalysis.cfgFlagQaRun.value) { - hrQaRun.fill(HIST("QaRun/pRunIndexNGlobalTracks"), holderEvent.runIndex, holderEvent.nGlobalTracks); - hrQaRun.fill(HIST("QaRun/pRunIndexNPvContributors"), holderEvent.runIndex, holderEvent.nPvContributors); - if (holderEvent.nGlobalTracks > 0) { - hrQaRun.fill(HIST("QaRun/pRunIndexMeanDcaXy"), holderEvent.runIndex, holderEvent.meanDcaXy); - hrQaRun.fill(HIST("QaRun/pRunIndexSigmaDcaXy"), holderEvent.runIndex, std::sqrt(holderEvent.meanSquareDcaXy - std::pow(holderEvent.meanDcaXy, 2.))); - hrQaRun.fill(HIST("QaRun/pRunIndexMeanDcaZ"), holderEvent.runIndex, holderEvent.meanDcaZ); - hrQaRun.fill(HIST("QaRun/pRunIndexSigmaDcaZ"), holderEvent.runIndex, std::sqrt(holderEvent.meanSquareDcaZ - std::pow(holderEvent.meanDcaZ, 2.))); - } - hrQaRun.fill(HIST("QaRun/pRunIndexNTofBeta"), holderEvent.runIndex, holderEvent.nTofBeta); + hrQaRun.fill(HIST("QaRun/pRunIndexNGlobalTracks_p"), holderEvent.runIndex, holderEvent.nGlobalTracksP); + hrQaRun.fill(HIST("QaRun/pRunIndexNGlobalTracks_m"), holderEvent.runIndex, holderEvent.nGlobalTracksM); + hrQaRun.fill(HIST("QaRun/pRunIndexNPvContributors_p"), holderEvent.runIndex, holderEvent.nPvContributorsP); + hrQaRun.fill(HIST("QaRun/pRunIndexNPvContributors_m"), holderEvent.runIndex, holderEvent.nPvContributorsM); + if (holderEvent.nGlobalTracksP > 0) { + hrQaRun.fill(HIST("QaRun/pRunIndexMeanDcaXy_p"), holderEvent.runIndex, holderEvent.meanDcaXyP); + hrQaRun.fill(HIST("QaRun/pRunIndexSigmaDcaXy_p"), holderEvent.runIndex, std::sqrt(holderEvent.meanSquareDcaXyP - std::pow(holderEvent.meanDcaXyP, 2.))); + hrQaRun.fill(HIST("QaRun/pRunIndexMeanDcaZ_p"), holderEvent.runIndex, holderEvent.meanDcaZP); + hrQaRun.fill(HIST("QaRun/pRunIndexSigmaDcaZ_p"), holderEvent.runIndex, std::sqrt(holderEvent.meanSquareDcaZP - std::pow(holderEvent.meanDcaZP, 2.))); + } + if (holderEvent.nGlobalTracksM > 0) { + hrQaRun.fill(HIST("QaRun/pRunIndexMeanDcaXy_m"), holderEvent.runIndex, holderEvent.meanDcaXyM); + hrQaRun.fill(HIST("QaRun/pRunIndexSigmaDcaXy_m"), holderEvent.runIndex, std::sqrt(holderEvent.meanSquareDcaXyM - std::pow(holderEvent.meanDcaXyM, 2.))); + hrQaRun.fill(HIST("QaRun/pRunIndexMeanDcaZ_m"), holderEvent.runIndex, holderEvent.meanDcaZM); + hrQaRun.fill(HIST("QaRun/pRunIndexSigmaDcaZ_m"), holderEvent.runIndex, std::sqrt(holderEvent.meanSquareDcaZM - std::pow(holderEvent.meanDcaZM, 2.))); + } + hrQaRun.fill(HIST("QaRun/pRunIndexNTofBeta_p"), holderEvent.runIndex, holderEvent.nTofBetaP); + hrQaRun.fill(HIST("QaRun/pRunIndexNTofBeta_m"), holderEvent.runIndex, holderEvent.nTofBetaM); } if (groupAnalysis.cfgFlagQaEvent.value) { - hrQaEvent.fill(HIST("QaEvent/hRunIndexNPvContributorsNGlobalTracks"), holderEvent.runIndex, holderEvent.nPvContributors, holderEvent.nGlobalTracks); - if (holderEvent.nGlobalTracks > 0) { - hrQaEvent.fill(HIST("QaEvent/hRunIndexNGlobalTracksMeanDcaXy"), holderEvent.runIndex, holderEvent.nGlobalTracks, holderEvent.meanDcaXy); - hrQaEvent.fill(HIST("QaEvent/hRunIndexNGlobalTracksMeanDcaZ"), holderEvent.runIndex, holderEvent.nGlobalTracks, holderEvent.meanDcaZ); + hrQaEvent.fill(HIST("QaEvent/hNPvContributorsNGlobalTracks"), holderEvent.nPvContributorsP + holderEvent.nPvContributorsM, holderEvent.nGlobalTracksP + holderEvent.nGlobalTracksM); + if (holderEvent.nGlobalTracksP + holderEvent.nGlobalTracksM > 0) { + hrQaEvent.fill(HIST("QaEvent/hNGlobalTracksMeanDcaXy"), holderEvent.nGlobalTracksP + holderEvent.nGlobalTracksM, (holderEvent.meanDcaXyP * holderEvent.nGlobalTracksP + holderEvent.meanDcaXyM * holderEvent.nGlobalTracksM) / (holderEvent.nGlobalTracksP + holderEvent.nGlobalTracksM)); + hrQaEvent.fill(HIST("QaEvent/hNGlobalTracksMeanDcaZ"), holderEvent.nGlobalTracksP + holderEvent.nGlobalTracksM, (holderEvent.meanDcaZP * holderEvent.nGlobalTracksP + holderEvent.meanDcaZM * holderEvent.nGlobalTracksM) / (holderEvent.nGlobalTracksP + holderEvent.nGlobalTracksM)); } - hrQaEvent.fill(HIST("QaEvent/hRunIndexNTofBetaNGlobalTracks"), holderEvent.runIndex, holderEvent.nTofBeta, holderEvent.nGlobalTracks); + hrQaEvent.fill(HIST("QaEvent/hNTofBetaNGlobalTracks"), holderEvent.nTofBetaP + holderEvent.nTofBetaM, holderEvent.nGlobalTracksP + holderEvent.nGlobalTracksM); } - if (!(holderEvent.nPvContributors - holderEvent.nGlobalTracks > groupEvent.cfgCutMinDeviationNPvContributors.value)) { + if (!(holderEvent.nPvContributorsP + holderEvent.nPvContributorsM - holderEvent.nGlobalTracksP - holderEvent.nGlobalTracksM > groupEvent.cfgCutMinDeviationNPvContributors.value)) { hrCounter.fill(HIST("hNEvents"), 7.); return false; } @@ -2303,11 +2356,11 @@ struct PartNumFluc { hrCounter.fill(HIST("hNEvents"), 1.); if (groupAnalysis.cfgFlagQaEvent.value) { - if (holderEvent.nGlobalTracks > 0) { - hrQaEvent.fill(HIST("QaEvent/hRunIndexNGlobalTracksMeanDcaXy_nPvContributorsCut"), holderEvent.runIndex, holderEvent.nGlobalTracks, holderEvent.meanDcaXy); - hrQaEvent.fill(HIST("QaEvent/hRunIndexNGlobalTracksMeanDcaZ_nPvContributorsCut"), holderEvent.runIndex, holderEvent.nGlobalTracks, holderEvent.meanDcaZ); + if (holderEvent.nGlobalTracksP + holderEvent.nGlobalTracksM > 0) { + hrQaEvent.fill(HIST("QaEvent/hNGlobalTracksMeanDcaXy_nPvContributorsCut"), holderEvent.nGlobalTracksP + holderEvent.nGlobalTracksM, (holderEvent.meanDcaXyP * holderEvent.nGlobalTracksP + holderEvent.meanDcaXyM * holderEvent.nGlobalTracksM) / (holderEvent.nGlobalTracksP + holderEvent.nGlobalTracksM)); + hrQaEvent.fill(HIST("QaEvent/hNGlobalTracksMeanDcaZ_nPvContributorsCut"), holderEvent.nGlobalTracksP + holderEvent.nGlobalTracksM, (holderEvent.meanDcaZP * holderEvent.nGlobalTracksP + holderEvent.meanDcaZM * holderEvent.nGlobalTracksM) / (holderEvent.nGlobalTracksP + holderEvent.nGlobalTracksM)); } - hrQaEvent.fill(HIST("QaEvent/hRunIndexNTofBetaNGlobalTracks_nPvContributorsCut"), holderEvent.runIndex, holderEvent.nTofBeta, holderEvent.nGlobalTracks); + hrQaEvent.fill(HIST("QaEvent/hNTofBetaNGlobalTracks_nPvContributorsCut"), holderEvent.nTofBetaP + holderEvent.nTofBetaM, holderEvent.nGlobalTracksP + holderEvent.nGlobalTracksM); } if (groupAnalysis.cfgFlagQaCentrality.value) { From 92c026ad7b7724fb7f82209a359599d846e3308e Mon Sep 17 00:00:00 2001 From: prottayCMT <61418725+prottayCMT@users.noreply.github.com> Date: Thu, 26 Feb 2026 22:32:27 +0100 Subject: [PATCH 100/347] [PWGLF] updated data models and table producer for reducing deriveddata size (#15177) Co-authored-by: Prottay Das --- PWGLF/DataModel/ZDCCalTables.h | 28 ++++++--------------- PWGLF/TableProducer/Common/zdcvector.cxx | 27 ++++++++++++-------- PWGLF/Tasks/Strangeness/zdccalderived.cxx | 30 +++++++++++------------ 3 files changed, 39 insertions(+), 46 deletions(-) diff --git a/PWGLF/DataModel/ZDCCalTables.h b/PWGLF/DataModel/ZDCCalTables.h index 0e3a61d1e4d..fee4e89e309 100644 --- a/PWGLF/DataModel/ZDCCalTables.h +++ b/PWGLF/DataModel/ZDCCalTables.h @@ -34,16 +34,10 @@ DECLARE_SOA_COLUMN(Cent, cent, float); DECLARE_SOA_COLUMN(Vx, vx, float); DECLARE_SOA_COLUMN(Vy, vy, float); DECLARE_SOA_COLUMN(Vz, vz, float); -DECLARE_SOA_COLUMN(ZnaC, znaC, float); -DECLARE_SOA_COLUMN(ZncC, zncC, float); -DECLARE_SOA_COLUMN(ZnaE0, znaE0, float); -DECLARE_SOA_COLUMN(ZnaE1, znaE1, float); -DECLARE_SOA_COLUMN(ZnaE2, znaE2, float); -DECLARE_SOA_COLUMN(ZnaE3, znaE3, float); -DECLARE_SOA_COLUMN(ZncE0, zncE0, float); -DECLARE_SOA_COLUMN(ZncE1, zncE1, float); -DECLARE_SOA_COLUMN(ZncE2, zncE2, float); -DECLARE_SOA_COLUMN(ZncE3, zncE3, float); +DECLARE_SOA_COLUMN(QxA, qxA, float); +DECLARE_SOA_COLUMN(QxC, qxC, float); +DECLARE_SOA_COLUMN(QyA, qyA, float); +DECLARE_SOA_COLUMN(QyC, qyC, float); } // namespace zdccaltable DECLARE_SOA_TABLE(ZDCCalTables, "AOD", "ZDCCALTABLE", zdccaltable::TriggerEventZDC, @@ -52,16 +46,10 @@ DECLARE_SOA_TABLE(ZDCCalTables, "AOD", "ZDCCALTABLE", zdccaltable::Vx, zdccaltable::Vy, zdccaltable::Vz, - zdccaltable::ZnaC, - zdccaltable::ZncC, - zdccaltable::ZnaE0, - zdccaltable::ZnaE1, - zdccaltable::ZnaE2, - zdccaltable::ZnaE3, - zdccaltable::ZncE0, - zdccaltable::ZncE1, - zdccaltable::ZncE2, - zdccaltable::ZncE3); + zdccaltable::QxA, + zdccaltable::QxC, + zdccaltable::QyA, + zdccaltable::QyC); using ZDCCalTable = ZDCCalTables::iterator; } // namespace o2::aod #endif // PWGLF_DATAMODEL_ZDCCALTABLES_H_ diff --git a/PWGLF/TableProducer/Common/zdcvector.cxx b/PWGLF/TableProducer/Common/zdcvector.cxx index 995b0cc8448..19fc5e65393 100644 --- a/PWGLF/TableProducer/Common/zdcvector.cxx +++ b/PWGLF/TableProducer/Common/zdcvector.cxx @@ -176,7 +176,7 @@ struct zdcvector { if (!bc.has_zdc()) { triggerevent = false; - zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); + zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, 0.0, 0.0, 0.0, 0.0); return; } @@ -190,7 +190,8 @@ struct zdcvector { if (znaEnergycommon <= 0.0 || zncEnergycommon <= 0.0) { triggerevent = false; - zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, znaEnergycommon, zncEnergycommon, znaEnergy[0], znaEnergy[1], znaEnergy[2], znaEnergy[3], zncEnergy[0], zncEnergy[1], zncEnergy[2], zncEnergy[3]); + zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, 0.0, 0.0, 0.0, 0.0); + // zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, znaEnergycommon, zncEnergycommon, znaEnergy[0], znaEnergy[1], znaEnergy[2], znaEnergy[3], zncEnergy[0], zncEnergy[1], zncEnergy[2], zncEnergy[3]); return; } @@ -198,14 +199,16 @@ struct zdcvector { if (znaEnergy[0] <= 0.0 || znaEnergy[1] <= 0.0 || znaEnergy[2] <= 0.0 || znaEnergy[3] <= 0.0) { triggerevent = false; - zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, znaEnergycommon, zncEnergycommon, znaEnergy[0], znaEnergy[1], znaEnergy[2], znaEnergy[3], zncEnergy[0], zncEnergy[1], zncEnergy[2], zncEnergy[3]); + zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, 0.0, 0.0, 0.0, 0.0); + // zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, znaEnergycommon, zncEnergycommon, znaEnergy[0], znaEnergy[1], znaEnergy[2], znaEnergy[3], zncEnergy[0], zncEnergy[1], zncEnergy[2], zncEnergy[3]); return; } histos.fill(HIST("hEvtSelInfo"), 3.5); if (zncEnergy[0] <= 0.0 || zncEnergy[1] <= 0.0 || zncEnergy[2] <= 0.0 || zncEnergy[3] <= 0.0) { triggerevent = false; - zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, znaEnergycommon, zncEnergycommon, znaEnergy[0], znaEnergy[1], znaEnergy[2], znaEnergy[3], zncEnergy[0], zncEnergy[1], zncEnergy[2], zncEnergy[3]); + zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, 0.0, 0.0, 0.0, 0.0); + // zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, znaEnergycommon, zncEnergycommon, znaEnergy[0], znaEnergy[1], znaEnergy[2], znaEnergy[3], zncEnergy[0], zncEnergy[1], zncEnergy[2], zncEnergy[3]); return; } @@ -213,7 +216,8 @@ struct zdcvector { if (rctCut.requireRCTFlagChecker && !rctChecker(collision)) { triggerevent = false; - zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, znaEnergycommon, zncEnergycommon, znaEnergy[0], znaEnergy[1], znaEnergy[2], znaEnergy[3], zncEnergy[0], zncEnergy[1], zncEnergy[2], zncEnergy[3]); + zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, 0.0, 0.0, 0.0, 0.0); + // zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, znaEnergycommon, zncEnergycommon, znaEnergy[0], znaEnergy[1], znaEnergy[2], znaEnergy[3], zncEnergy[0], zncEnergy[1], zncEnergy[2], zncEnergy[3]); return; } @@ -221,7 +225,8 @@ struct zdcvector { if (additionalEvSel && (!collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV))) { triggerevent = false; - zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, znaEnergycommon, zncEnergycommon, znaEnergy[0], znaEnergy[1], znaEnergy[2], znaEnergy[3], zncEnergy[0], zncEnergy[1], zncEnergy[2], zncEnergy[3]); + zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, 0.0, 0.0, 0.0, 0.0); + // zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, znaEnergycommon, zncEnergycommon, znaEnergy[0], znaEnergy[1], znaEnergy[2], znaEnergy[3], zncEnergy[0], zncEnergy[1], zncEnergy[2], zncEnergy[3]); return; } @@ -255,7 +260,7 @@ struct zdcvector { if (znaEnergy[iChA] <= 0.0) { triggerevent = false; - zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, znaEnergycommon, zncEnergycommon, znaEnergy[0], znaEnergy[1], znaEnergy[2], znaEnergy[3], zncEnergy[0], zncEnergy[1], zncEnergy[2], zncEnergy[3]); + zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, 0.0, 0.0, 0.0, 0.0); return; } else { double ampl = gainequal * znaEnergy[iChA]; @@ -270,7 +275,8 @@ struct zdcvector { } else { if (zncEnergy[iChA - 4] <= 0.0) { triggerevent = false; - zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, znaEnergycommon, zncEnergycommon, znaEnergy[0], znaEnergy[1], znaEnergy[2], znaEnergy[3], zncEnergy[0], zncEnergy[1], zncEnergy[2], zncEnergy[3]); + zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, 0.0, 0.0, 0.0, 0.0); + // zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, znaEnergycommon, zncEnergycommon, znaEnergy[0], znaEnergy[1], znaEnergy[2], znaEnergy[3], zncEnergy[0], zncEnergy[1], zncEnergy[2], zncEnergy[3]); return; } else { double ampl = gainequal * zncEnergy[iChA - 4]; @@ -300,7 +306,8 @@ struct zdcvector { qyZDCA = 0.0; qyZDCC = 0.0; triggerevent = false; - zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, znaEnergycommon, zncEnergycommon, znaEnergy[0], znaEnergy[1], znaEnergy[2], znaEnergy[3], zncEnergy[0], zncEnergy[1], zncEnergy[2], zncEnergy[3]); + zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, 0.0, 0.0, 0.0, 0.0); + // zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, znaEnergycommon, zncEnergycommon, znaEnergy[0], znaEnergy[1], znaEnergy[2], znaEnergy[3], zncEnergy[0], zncEnergy[1], zncEnergy[2], zncEnergy[3]); return; } @@ -322,7 +329,7 @@ struct zdcvector { lastRunNumber = currentRunNumber; } - zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, znaEnergycommon, zncEnergycommon, znaEnergy[0], znaEnergy[1], znaEnergy[2], znaEnergy[3], zncEnergy[0], zncEnergy[1], zncEnergy[2], zncEnergy[3]); + zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, qxZDCA, qxZDCC, qyZDCA, qyZDCC); } }; diff --git a/PWGLF/Tasks/Strangeness/zdccalderived.cxx b/PWGLF/Tasks/Strangeness/zdccalderived.cxx index 5d8776345d1..f92540cca05 100644 --- a/PWGLF/Tasks/Strangeness/zdccalderived.cxx +++ b/PWGLF/Tasks/Strangeness/zdccalderived.cxx @@ -116,8 +116,8 @@ struct zdccalderived { Configurable useShift{"useShift", false, "shift histograms"}; Configurable ispolarization{"ispolarization", false, "Flag to check polarization"}; Configurable followpub{"followpub", true, "flag to use alphaZDC"}; - Configurable useGainCallib{"useGainCallib", false, "use gain calibration"}; - Configurable useCallibvertex{"useCallibvertex", false, "use calibration for vxy"}; + // Configurable useGainCallib{"useGainCallib", false, "use gain calibration"}; + // Configurable useCallibvertex{"useCallibvertex", false, "use calibration for vxy"}; Configurable coarse1{"coarse1", false, "RE1"}; Configurable fine1{"fine1", false, "REfine1"}; Configurable coarse2{"coarse2", false, "RE2"}; @@ -133,8 +133,6 @@ struct zdccalderived { Configurable useRecentereSp{"useRecentereSp", false, "use Recentering with Sparse or THn"}; Configurable useRecenterefineSp{"useRecenterefineSp", false, "use fine Recentering with THn"}; - Configurable confGainPath{"confGainPath", "Users/p/prottay/My/Object/NewPbPbpass4_10092024/gaincallib", "Path to gain calibration"}; - Configurable confGainPathVxy{"confGainPathVxy", "Users/p/prottay/My/Object/swapcoords/PbPbpass4_20112024/recentervert", "Path to gain calibration for vxy"}; Configurable confRecentereSp{"confRecentereSp", "Users/p/prottay/My/Object/Testingwithsparse/NewPbPbpass4_17092024/recenter", "Sparse or THn path for recentering"}; Configurable confRecentereSp2{"confRecentereSp2", "Users/p/prottay/My/Object/Testingwithsparse/NewPbPbpass4_17092024/recenter", "Sparse or THn path for recentering 2"}; Configurable confRecentereSp3{"confRecentereSp3", "Users/p/prottay/My/Object/Testingwithsparse/NewPbPbpass4_17092024/recenter", "Sparse or THn path for recentering 3"}; @@ -354,20 +352,20 @@ struct zdccalderived { auto vx = collision.vx(); auto vy = collision.vy(); - float psiZDCC = -99; - float psiZDCA = -99; - auto qxZDCA = 0.0; - auto qxZDCC = 0.0; - auto qyZDCA = 0.0; - auto qyZDCC = 0.0; - auto sumA = 0.0; - auto sumC = 0.0; + double psiZDCC = -99; + double psiZDCA = -99; + auto qxZDCA = collision.qxA(); + auto qxZDCC = collision.qxC(); + auto qyZDCA = collision.qyA(); + auto qyZDCC = collision.qyC(); + // auto sumA = 0.0; + // auto sumC = 0.0; auto timestamps = ccdb->getRunDuration(currentRunNumber, true); /// fatalise if timestamps are not found int64_t sorTimestamp = timestamps.first; // timestamp of the SOR/SOX/STF in ms int64_t eorTimestamp = timestamps.second; // timestamp of the EOR/EOX/ETF in ms int64_t ts = eorTimestamp / 2 + sorTimestamp / 2; // timestamp of the middle of the run - + /* std::array znaEnergy = { collision.znaE0(), collision.znaE1(), @@ -442,14 +440,14 @@ struct zdccalderived { qyZDCC = 0.0; return; } - + */ histos.fill(HIST("hEvtSelInfo"), 8.5); histos.fill(HIST("hCentrality"), centrality); histos.fill(HIST("Vz"), vz); histos.fill(HIST("AvgVxy"), 0.5, vx); histos.fill(HIST("AvgVxy"), 1.5, vy); - + /* if (useCallibvertex && (currentRunNumber != lastRunNumber)) { gainprofilevxy = ccdb->getForTimeStamp(confGainPathVxy.value, ts); } @@ -458,7 +456,7 @@ struct zdccalderived { vx = vx - gainprofilevxy->GetBinContent(1); vy = vy - gainprofilevxy->GetBinContent(2); } - + */ bool res = 0; bool resfine = 0; int check = 1; From ced54b5e51d698c0de70427dd4baa2f904f8dd7e Mon Sep 17 00:00:00 2001 From: nzardosh Date: Fri, 27 Feb 2026 03:24:14 +0100 Subject: [PATCH 101/347] [PWGJE] adding event splitting for trigger tracks (#15186) --- PWGJE/TableProducer/derivedDataSelector.cxx | 89 +++++++++++++++------ 1 file changed, 64 insertions(+), 25 deletions(-) diff --git a/PWGJE/TableProducer/derivedDataSelector.cxx b/PWGJE/TableProducer/derivedDataSelector.cxx index 5fae719fe60..371dbc73f34 100644 --- a/PWGJE/TableProducer/derivedDataSelector.cxx +++ b/PWGJE/TableProducer/derivedDataSelector.cxx @@ -50,8 +50,6 @@ struct JetDerivedDataSelector { Configurable thresholdChargedJetPtMin{"thresholdChargedJetPtMin", 0.0, "Minimum charged jet pt to accept event"}; Configurable thresholdChargedEventWiseSubtractedJetPtMin{"thresholdChargedEventWiseSubtractedJetPtMin", 0.0, "Minimum charged event-wise subtracted jet pt to accept event"}; Configurable thresholdChargedMCPJetPtMin{"thresholdChargedMCPJetPtMin", 0.0, "Minimum charged mcp jet pt to accept event"}; - Configurable thresholdNeutralJetPtMin{"thresholdNeutralJetPtMin", 0.0, "Minimum neutral jet pt to accept event"}; - Configurable thresholdNeutralMCPJetPtMin{"thresholdNeutralMCPJetPtMin", 0.0, "Minimum neutal mcp jet pt to accept event"}; Configurable thresholdFullJetPtMin{"thresholdFullJetPtMin", 0.0, "Minimum full jet pt to accept event"}; Configurable thresholdFullMCPJetPtMin{"thresholdFullMCPJetPtMin", 0.0, "Minimum full mcp jet pt to accept event"}; Configurable thresholdD0PtMin{"thresholdD0PtMin", 0.0, "Minimum D0 pt to accept event"}; @@ -100,7 +98,9 @@ struct JetDerivedDataSelector { Configurable thresholdChargedEventWiseSubtractedDielectronJetPtMin{"thresholdChargedEventWiseSubtractedDielectronJetPtMin", 0.0, "Minimum charged event-wise subtracted Dielectron jet pt to accept event"}; Configurable thresholdChargedDielectronMCPJetPtMin{"thresholdChargedDielectronMCPJetPtMin", 0.0, "Minimum charged Dielectron mcp jet pt to accept event"}; Configurable thresholdTriggerTrackPtMin{"thresholdTriggerTrackPtMin", 0.0, "Minimum trigger track pt to accept event"}; + Configurable thresholdTriggerTrackReferencePtMin{"thresholdTriggerTrackReferencePtMin", 0.0, "Minimum trigger track reference pt to accept event"}; Configurable thresholdTriggerParticlePtMin{"thresholdTriggerParticlePtMin", 0.0, "Minimum trigger particle pt to accept event"}; + Configurable thresholdTriggerParticleReferencePtMin{"thresholdTriggerParticleReferencePtMin", 0.0, "Minimum trigger particle reference pt to accept event"}; Configurable thresholdClusterEnergyMin{"thresholdClusterEnergyMin", 0.0, "Minimum cluster energy to accept event"}; Configurable downscaleFactor{"downscaleFactor", 1, "random downscale of selected events"}; @@ -116,12 +116,15 @@ struct JetDerivedDataSelector { Configurable performTrackSelection{"performTrackSelection", true, "only save tracks that pass one of the track selections"}; Configurable trackPtSelectionMin{"trackPtSelectionMin", 0.15, "only save tracks that have a pT larger than this pT"}; Configurable trackEtaSelectionMax{"trackEtaSelectionMax", 0.9, "only save tracks that have an eta smaller than this eta"}; + Configurable triggerTrackSignalFraction{"triggerTrackSignalFraction", 0.95, "fraction of events to scan for signal trigger track class"}; Configurable triggerMasks{"triggerMasks", "", "possible JE Trigger masks: fJetChLowPt,fJetChHighPt,fTrackLowPt,fTrackHighPt,fJetD0ChLowPt,fJetD0ChHighPt,fJetLcChLowPt,fJetLcChHighPt,fEMCALReadout,fJetFullHighPt,fJetFullLowPt,fJetNeutralHighPt,fJetNeutralLowPt,fGammaVeryHighPtEMCAL,fGammaVeryHighPtDCAL,fGammaHighPtEMCAL,fGammaHighPtDCAL,fGammaLowPtEMCAL,fGammaLowPtDCAL,fGammaVeryLowPtEMCAL,fGammaVeryLowPtDCAL"}; } config; std::vector collisionFlag; - std::vector McCollisionFlag; + std::vector mcCollisionFlag; + std::vector collisionSplitFlag; + std::vector mcCollisionSplitFlag; TRandom3 randomNumber; @@ -146,8 +149,8 @@ struct JetDerivedDataSelector { void processSetupMcCollisions(aod::JMcCollisions const& mcCollisions) { - McCollisionFlag.clear(); - McCollisionFlag.resize(mcCollisions.size(), false); + mcCollisionFlag.clear(); + mcCollisionFlag.resize(mcCollisions.size(), false); } void processSelectMcCollisionsPerCollision(aod::JMcCollisions const& mcCollisions, soa::Join const& collisions) @@ -156,7 +159,7 @@ struct JetDerivedDataSelector { const auto collisionsPerMcCollision = collisions.sliceBy(CollisionsPerMcCollision, mcCollision.globalIndex()); for (auto collision : collisionsPerMcCollision) { if (collisionFlag[collision.globalIndex()]) { - McCollisionFlag[mcCollision.globalIndex()] = true; + mcCollisionFlag[mcCollision.globalIndex()] = true; } } } @@ -165,7 +168,7 @@ struct JetDerivedDataSelector { void processSelectCollisionsPerMcCollision(soa::Join::iterator const& collision) { if (collision.has_mcCollision()) { - if (McCollisionFlag[collision.mcCollisionId()]) { + if (mcCollisionFlag[collision.mcCollisionId()]) { collisionFlag[collision.globalIndex()] = true; } } @@ -184,11 +187,11 @@ struct JetDerivedDataSelector { void processSetupAllMcCollisionsWithDownscaling(aod::JMcCollisions const& mcCollisions) { - McCollisionFlag.clear(); - McCollisionFlag.resize(mcCollisions.size(), false); + mcCollisionFlag.clear(); + mcCollisionFlag.resize(mcCollisions.size(), false); for (const auto& mcCollision : mcCollisions) { if (randomNumber.Integer(config.downscaleFactor) == 0) { - McCollisionFlag[mcCollision.globalIndex()] = true; + mcCollisionFlag[mcCollision.globalIndex()] = true; } } } @@ -203,8 +206,8 @@ struct JetDerivedDataSelector { } } if constexpr (std::is_same_v, aod::JMcCollisions>) { - if (McCollisionFlag[collision.globalIndex()] && randomNumber.Integer(config.downscaleFactor) != 0) { - McCollisionFlag[collision.globalIndex()] = false; + if (mcCollisionFlag[collision.globalIndex()] && randomNumber.Integer(config.downscaleFactor) != 0) { + mcCollisionFlag[collision.globalIndex()] = false; } } } @@ -227,7 +230,7 @@ struct JetDerivedDataSelector { if (jetderiveddatautilities::selectCollision(collision, eventSelectionBitsCharged, config.skipMBGapEvents, config.applyRCTSelectionsCharged)) { barrelRCTFlagSelection = true; } - if (doprocessSelectingNeutralJets || doprocessSelectingNeutralMCDJets || doprocessSelectingNeutralMCPJets || doprocessSelectingFullJets || doprocessSelectingFullMCDJets || doprocessSelectingFullMCPJets || doprocessSelectingClusters) { + if (doprocessSelectingFullJets || doprocessSelectingFullMCDJets || doprocessSelectingFullMCPJets || doprocessSelectingClusters) { if (jetderiveddatautilities::selectCollision(collision, eventSelectionBitsFull, config.skipMBGapEvents, config.applyRCTSelectionsFull, "CBT_calo")) { emcalRCTFlagSelection = true; } @@ -237,6 +240,33 @@ struct JetDerivedDataSelector { } } + void processCollisionSplitting(aod::JCollisions const& collisions) + { + collisionSplitFlag.clear(); + collisionSplitFlag.resize(collisions.size(), true); + for (auto const& collision : collisions) { + if (randomNumber.Rndm() > config.triggerTrackSignalFraction) { + collisionSplitFlag[collision.globalIndex()] = false; + } + } + } + + void processCollisionSplittingMC(aod::JMcCollisions const& mcCollisions, soa::Join const& collisions) + { + mcCollisionSplitFlag.clear(); + mcCollisionSplitFlag.resize(mcCollisions.size(), true); + collisionSplitFlag.clear(); + collisionSplitFlag.resize(collisions.size(), true); + for (auto const& mcCollision : mcCollisions) { + if (randomNumber.Rndm() > config.triggerTrackSignalFraction) { + mcCollisionSplitFlag[mcCollision.globalIndex()] = false; + for (auto const& collision : collisions.sliceBy(CollisionsPerMcCollision, mcCollision.globalIndex())) { + collisionSplitFlag[collision.globalIndex()] = false; + } + } + } + } + template void processSelectionObjects(T const& selectionObjects) { @@ -247,10 +277,6 @@ struct JetDerivedDataSelector { selectionObjectPtMin = config.thresholdChargedEventWiseSubtractedJetPtMin; } else if constexpr (std::is_same_v, aod::ChargedMCParticleLevelJets>) { selectionObjectPtMin = config.thresholdChargedMCPJetPtMin; - } else if constexpr (std::is_same_v, aod::NeutralJets> || std::is_same_v, aod::NeutralMCDetectorLevelJets>) { - selectionObjectPtMin = config.thresholdNeutralJetPtMin; - } else if constexpr (std::is_same_v, aod::NeutralMCParticleLevelJets>) { - selectionObjectPtMin = config.thresholdNeutralMCPJetPtMin; } else if constexpr (std::is_same_v, aod::FullJets> || std::is_same_v, aod::FullMCDetectorLevelJets>) { selectionObjectPtMin = config.thresholdFullJetPtMin; } else if constexpr (std::is_same_v, aod::FullMCParticleLevelJets>) { @@ -368,6 +394,13 @@ struct JetDerivedDataSelector { if (selectionObject.pt() < config.trackPtSelectionMin || std::abs(selectionObject.eta()) > config.trackEtaSelectionMax) { continue; } + if (doprocessCollisionSplitting || doprocessCollisionSplittingMC) { + if (collisionSplitFlag[selectionObject.collisionId()]) { + selectionObjectPtMin = config.thresholdTriggerTrackPtMin; + } else { + selectionObjectPtMin = config.thresholdTriggerTrackReferencePtMin; + } + } } if constexpr (std::is_same_v, aod::JMcParticles>) { if (!selectionObject.isPhysicalPrimary()) { @@ -376,15 +409,22 @@ struct JetDerivedDataSelector { if (selectionObject.pt() < config.trackPtSelectionMin || std::abs(selectionObject.eta()) > config.trackEtaSelectionMax) { continue; } + if (doprocessCollisionSplittingMC) { + if (mcCollisionSplitFlag[selectionObject.mcCollisionId()]) { + selectionObjectPtMin = config.thresholdTriggerParticlePtMin; + } else { + selectionObjectPtMin = config.thresholdTriggerParticleReferencePtMin; + } + } } if (selectionObject.pt() >= selectionObjectPtMin) { isTriggerObject = true; } } if (isTriggerObject) { - if constexpr (std::is_same_v, aod::ChargedMCParticleLevelJets> || std::is_same_v, aod::NeutralMCParticleLevelJets> || std::is_same_v, aod::FullMCParticleLevelJets> || std::is_same_v, aod::CandidatesD0MCP> || std::is_same_v, aod::D0ChargedMCParticleLevelJets> || std::is_same_v, aod::CandidatesDplusMCP> || std::is_same_v, aod::DplusChargedMCParticleLevelJets> || std::is_same_v, aod::CandidatesDsMCP> || std::is_same_v, aod::DsChargedMCParticleLevelJets> || std::is_same_v, aod::CandidatesDstarMCP> || std::is_same_v, aod::DstarChargedMCParticleLevelJets> || std::is_same_v, aod::CandidatesLcMCP> || std::is_same_v, aod::LcChargedMCParticleLevelJets> || std::is_same_v, aod::CandidatesB0MCP> || std::is_same_v, aod::B0ChargedMCParticleLevelJets> || std::is_same_v, aod::CandidatesBplusMCP> || std::is_same_v, aod::BplusChargedMCParticleLevelJets> || std::is_same_v, aod::CandidatesXicToXiPiPiMCP> || std::is_same_v, aod::XicToXiPiPiChargedMCParticleLevelJets> || std::is_same_v, aod::CandidatesDielectronMCP> || std::is_same_v, aod::DielectronChargedMCParticleLevelJets> || std::is_same_v, aod::JMcParticles>) { + if constexpr (std::is_same_v, aod::ChargedMCParticleLevelJets> || std::is_same_v, aod::FullMCParticleLevelJets> || std::is_same_v, aod::CandidatesD0MCP> || std::is_same_v, aod::D0ChargedMCParticleLevelJets> || std::is_same_v, aod::CandidatesDplusMCP> || std::is_same_v, aod::DplusChargedMCParticleLevelJets> || std::is_same_v, aod::CandidatesDsMCP> || std::is_same_v, aod::DsChargedMCParticleLevelJets> || std::is_same_v, aod::CandidatesDstarMCP> || std::is_same_v, aod::DstarChargedMCParticleLevelJets> || std::is_same_v, aod::CandidatesLcMCP> || std::is_same_v, aod::LcChargedMCParticleLevelJets> || std::is_same_v, aod::CandidatesB0MCP> || std::is_same_v, aod::B0ChargedMCParticleLevelJets> || std::is_same_v, aod::CandidatesBplusMCP> || std::is_same_v, aod::BplusChargedMCParticleLevelJets> || std::is_same_v, aod::CandidatesXicToXiPiPiMCP> || std::is_same_v, aod::XicToXiPiPiChargedMCParticleLevelJets> || std::is_same_v, aod::CandidatesDielectronMCP> || std::is_same_v, aod::DielectronChargedMCParticleLevelJets> || std::is_same_v, aod::JMcParticles>) { if (selectionObject.mcCollisionId() >= 0) { - McCollisionFlag[selectionObject.mcCollisionId()] = true; + mcCollisionFlag[selectionObject.mcCollisionId()] = true; } } else { if (selectionObject.collisionId() >= 0) { @@ -400,14 +440,13 @@ struct JetDerivedDataSelector { PROCESS_SWITCH(JetDerivedDataSelector, processSetupAllCollisionsWithDownscaling, "setup the writing of untriggered collisions with downscaling", false); PROCESS_SWITCH(JetDerivedDataSelector, processSetupAllMcCollisionsWithDownscaling, "setup the writing of untriggered mccollisions with downscaling", false); PROCESS_SWITCH(JetDerivedDataSelector, processSetupEventTriggering, "process software triggers", false); + PROCESS_SWITCH(JetDerivedDataSelector, processCollisionSplitting, "process collision splitting for trigger tracks", false); + PROCESS_SWITCH(JetDerivedDataSelector, processCollisionSplittingMC, "process mcCollision and collision splitting for trigger tracks", false); PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingChargedJets, "process charged jets", false); PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingChargedEventWiseSubtractedJets, "process charged event-wise subtracted jets", false); PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingChargedMCDJets, "process charged mcd jets", false); PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingChargedMCDetectorLevelEventWiseSubtractedJets, "process charged event-wise subtracted mcd jets", false); PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingChargedMCPJets, "process charged mcp jets", false); - PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingNeutralJets, "process neutral jets", false); - PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingNeutralMCDJets, "process neutral mcd jets", false); - PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingNeutralMCPJets, "process neutral mcp jets", false); PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingFullJets, "process full jets", false); PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingFullMCDJets, "process full mcd jets", false); PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingFullMCPJets, "process full mcp jets", false); @@ -460,8 +499,8 @@ struct JetDerivedDataSelector { PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingBplusChargedMCDJets, "process Bplus charged mcd jets", false); PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingBplusChargedMCDetectorLevelEventWiseSubtractedJets, "process Bplus event-wise subtracted charged mcd jets", false); PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingBplusChargedMCPJets, "process Bplus charged mcp jets", false); - PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingXicToXiPiPiCandidates, "process XicToXiPiPi candidates", false); - PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingXicToXiPiPiCandidatesMCP, "process XicToXiPiPi particles", false); + // PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingXicToXiPiPiCandidates, "process XicToXiPiPi candidates", false); + // PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingXicToXiPiPiCandidatesMCP, "process XicToXiPiPi particles", false); PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingXicToXiPiPiChargedJets, "process XicToXiPiPi charged jets", false); PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingXicToXiPiPiChargedEventWiseSubtractedJets, "process XicToXiPiPi event-wise subtracted charged jets", false); PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingXicToXiPiPiChargedMCDJets, "process XicToXiPiPi charged mcd jets", false); @@ -495,7 +534,7 @@ struct JetDerivedDataSelector { void processStoreMcCollisionDecision(aod::JMcCollision const& mcCollision) { - if (McCollisionFlag[mcCollision.globalIndex()]) { + if (mcCollisionFlag[mcCollision.globalIndex()]) { mcCollisionSelectionsTable(true); } else { mcCollisionSelectionsTable(false); From 3c9bb5350c81004ad01c52a6d5d5142ea05dc529 Mon Sep 17 00:00:00 2001 From: Roman Lietava Date: Fri, 27 Feb 2026 10:09:04 +0100 Subject: [PATCH 102/347] [PWGLF] fixes: runnumber and downscaling (#15170) --- PWGLF/Tasks/Strangeness/nonPromptCascade.cxx | 22 +++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/nonPromptCascade.cxx b/PWGLF/Tasks/Strangeness/nonPromptCascade.cxx index 59a460d0324..7bb2b93ea4a 100644 --- a/PWGLF/Tasks/Strangeness/nonPromptCascade.cxx +++ b/PWGLF/Tasks/Strangeness/nonPromptCascade.cxx @@ -216,6 +216,7 @@ struct NonPromptCascadeTask { Configurable cfgMaxMult{"cfgMaxMult", 8000.f, "Upper range of multiplicty histo"}; Configurable cfgMaxMultFV0{"cfgMaxMultFV0", 10000.f, "Upper range of multiplicty FV0 histo"}; Configurable cfgPtEdgesdNdeta{"ptEdges", "0,0.2,0.4,0.6,0.8,1,1.2,1.6,2.0,2.4,2.8,3.2,3.6,4,4.5,5,5.5,6,7,8,10", "Pt bin edges (comma-separated)"}; + Configurable cfgDownscaleMB{"cfgDownscaleMB", 1, "Downscaling for pile up study sample"}; Zorro mZorro; OutputObj mZorroSummary{"ZorroSummary"}; @@ -978,14 +979,21 @@ struct NonPromptCascadeTask { void processPileUp(CollisionCandidatesRun3 const& collisions, aod::BCsWithTimestamps const&) { - std::cout << "Processing pile up" << std::endl; + // std::cout << "Processing pile up" << std::endl; + int ds = 1; for (const auto& coll : collisions) { - float centFT0M = coll.centFT0M(); - float multFT0M = coll.multFT0M(); - auto bc = coll.template bc_as(); - uint64_t globalBC = bc.globalBC(); - NPPUTable(mRunNumber, globalBC, coll.numContrib(), coll.multNTracksGlobal(), centFT0M, multFT0M); - // NPPileUpTable(mRunNumber, globalBC, multNTracks, centFT0M, multFT0M); + if (ds == cfgDownscaleMB) { + auto bc = coll.template bc_as(); + if (mRunNumber != bc.runNumber()) { + mRunNumber = bc.runNumber(); + } + float centFT0M = coll.centFT0M(); + float multFT0M = coll.multFT0M(); + uint64_t globalBC = bc.globalBC(); + NPPUTable(mRunNumber, globalBC, coll.numContrib(), coll.multNTracksGlobal(), centFT0M, multFT0M); + ds = 0; + } + ds++; } }; PROCESS_SWITCH(NonPromptCascadeTask, processPileUp, "pile up studies", true); From 9db255feebd9fdbf3346751b01d3bddb8dc7e0c7 Mon Sep 17 00:00:00 2001 From: Hirak Koley Date: Fri, 27 Feb 2026 14:47:09 +0530 Subject: [PATCH 103/347] [PWGLF] Refactor event selection and processing logic (#15185) --- .../Resonances/lambda1520analysisinpp.cxx | 140 +++++++++++------- PWGLF/Utils/EventSelectionFlagsMapping.def | 2 +- PWGLF/Utils/collisionCuts.h | 24 ++- 3 files changed, 104 insertions(+), 62 deletions(-) diff --git a/PWGLF/Tasks/Resonances/lambda1520analysisinpp.cxx b/PWGLF/Tasks/Resonances/lambda1520analysisinpp.cxx index 3d3aac5b773..6758d7ba9ca 100644 --- a/PWGLF/Tasks/Resonances/lambda1520analysisinpp.cxx +++ b/PWGLF/Tasks/Resonances/lambda1520analysisinpp.cxx @@ -14,6 +14,7 @@ /// \author Hirak Kumar Koley #include "PWGLF/Utils/collisionCuts.h" +#include "PWGLF/Utils/inelGt.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/Multiplicity.h" @@ -92,15 +93,15 @@ struct Lambda1520analysisinpp { Configurable cfgEvtZvtx{"cfgEvtZvtx", 10.0f, "Evt sel: Max. z-Vertex (cm)"}; Configurable cfgEvtOccupancyInTimeRangeMax{"cfgEvtOccupancyInTimeRangeMax", -1, "Evt sel: maximum track occupancy"}; Configurable cfgEvtOccupancyInTimeRangeMin{"cfgEvtOccupancyInTimeRangeMin", -1, "Evt sel: minimum track occupancy"}; - Configurable cfgEvtTriggerCheck{"cfgEvtTriggerCheck", false, "Evt sel: check for trigger"}; - Configurable cfgEvtOfflineCheck{"cfgEvtOfflineCheck", true, "Evt sel: check for offline selection"}; - Configurable cfgEvtTriggerTVXSel{"cfgEvtTriggerTVXSel", false, "Evt sel: triggerTVX selection (MB)"}; - Configurable cfgEvtTFBorderCut{"cfgEvtTFBorderCut", false, "Evt sel: apply TF border cut"}; - Configurable cfgEvtUseITSTPCvertex{"cfgEvtUseITSTPCvertex", false, "Evt sel: use at lease on ITS-TPC track for vertexing"}; - Configurable cfgEvtZvertexTimedifference{"cfgEvtZvertexTimedifference", false, "Evt sel: apply Z-vertex time difference"}; - Configurable cfgEvtPileupRejection{"cfgEvtPileupRejection", false, "Evt sel: apply pileup rejection"}; - Configurable cfgEvtNoITSROBorderCut{"cfgEvtNoITSROBorderCut", false, "Evt sel: apply NoITSRO border cut"}; - Configurable cfgEvtCollInTimeRangeStandard{"cfgEvtCollInTimeRangeStandard", false, "Evt sel: apply NoCollInTimeRangeStandard"}; + Configurable cfgEvtSel8{"cfgEvtSel8", false, "Evt Sel 8 check for offline selection"}; + Configurable cfgEvtTriggerTVXSel{"cfgEvtTriggerTVXSel", true, "Evt sel: triggerTVX selection (MB)"}; + Configurable cfgEvtNoTFBorderCut{"cfgEvtNoTFBorderCut", true, "Evt sel: apply TF border cut"}; + Configurable cfgEvtIsVertexITSTPC{"cfgEvtIsVertexITSTPC", false, "Evt sel: use at lease on ITS-TPC track for vertexing"}; + Configurable cfgEvtIsGoodZvtxFT0vsPV{"cfgEvtIsGoodZvtxFT0vsPV", true, "Evt sel: apply Z-vertex time difference"}; + Configurable cfgEvtNoSameBunchPileup{"cfgEvtNoSameBunchPileup", false, "Evt sel: apply pileup rejection"}; + Configurable cfgEvtNoITSROFrameBorderCut{"cfgEvtNoITSROFrameBorderCut", false, "Evt sel: apply NoITSRO border cut"}; + Configurable cfgEvtNoCollInTimeRangeStandard{"cfgEvtNoCollInTimeRangeStandard", false, "Evt sel: apply NoNoCollInTimeRangeStandard"}; + Configurable cfgEvtIsVertexTOFmatched{"cfgEvtIsVertexTOFmatched", true, "kIsVertexTOFmatched: apply vertex TOF matched"}; } configEvents; struct : ConfigurableGroup { @@ -157,7 +158,7 @@ struct Lambda1520analysisinpp { /// Event Mixing Configurable nEvtMixing{"nEvtMixing", 10, "Number of events to mix"}; ConfigurableAxis cfgVtxBins{"cfgVtxBins", {VARIABLE_WIDTH, -10.0f, -8.0f, -6.0f, -4.0f, -2.0f, 0.0f, 2.0f, 4.0f, 6.0f, 8.0f, 10.0f}, "Mixing bins - z-vertex"}; - ConfigurableAxis cfgMultBins{"cfgMultBins", {VARIABLE_WIDTH, 0.0f, 5.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f, 100.0f, 110.0f}, "Mixing bins - multiplicity"}; + ConfigurableAxis cfgMultPercentileBins{"cfgMultPercentileBins", {VARIABLE_WIDTH, 0.0f, 5.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f, 100.0f, 110.0f}, "Mixing bins - multiplicity"}; // Rotational background Configurable rotationalcut{"rotationalcut", 10, "Cut value (Rotation angle pi - pi/cut and pi + pi/cut)"}; @@ -174,7 +175,6 @@ struct Lambda1520analysisinpp { Configurable cfgUseDaughterEtaCutMC{"cfgUseDaughterEtaCutMC", false, "Switch to turn on/off eta cuts for daughters in MC"}; // MC selection cut - Configurable cZvertCutMC{"cZvertCutMC", 10.0f, "MC Z-vertex cut"}; Configurable cEtacutMC{"cEtacutMC", 0.5f, "MC eta cut"}; Configurable cUseRapcutMC{"cUseRapcutMC", true, "MC eta cut"}; Configurable cUseEtacutMC{"cUseEtacutMC", true, "MC eta cut"}; @@ -237,16 +237,17 @@ struct Lambda1520analysisinpp { void init(framework::InitContext&) { - colCuts.setCuts(configEvents.cfgEvtZvtx, configEvents.cfgEvtTriggerCheck, configEvents.cfgEvtOfflineCheck, /*checkRun3*/ true, /*triggerTVXsel*/ false, configEvents.cfgEvtOccupancyInTimeRangeMax, configEvents.cfgEvtOccupancyInTimeRangeMin); + colCuts.setCuts(configEvents.cfgEvtZvtx, /* configEvents.cfgEvtTriggerCheck */ false, configEvents.cfgEvtSel8, /*checkRun3*/ true, /*triggerTVXsel*/ false, configEvents.cfgEvtOccupancyInTimeRangeMax, configEvents.cfgEvtOccupancyInTimeRangeMin); colCuts.init(&histos); colCuts.setTriggerTVX(configEvents.cfgEvtTriggerTVXSel); - colCuts.setApplyTFBorderCut(configEvents.cfgEvtTFBorderCut); - colCuts.setApplyITSTPCvertex(configEvents.cfgEvtUseITSTPCvertex); - colCuts.setApplyZvertexTimedifference(configEvents.cfgEvtZvertexTimedifference); - colCuts.setApplyPileupRejection(configEvents.cfgEvtPileupRejection); - colCuts.setApplyNoITSROBorderCut(configEvents.cfgEvtNoITSROBorderCut); - colCuts.setApplyCollInTimeRangeStandard(configEvents.cfgEvtCollInTimeRangeStandard); + colCuts.setApplyTFBorderCut(configEvents.cfgEvtNoTFBorderCut); + colCuts.setApplyITSTPCvertex(configEvents.cfgEvtIsVertexITSTPC); + colCuts.setApplyZvertexTimedifference(configEvents.cfgEvtIsGoodZvtxFT0vsPV); + colCuts.setApplyPileupRejection(configEvents.cfgEvtNoSameBunchPileup); + colCuts.setApplyNoITSROBorderCut(configEvents.cfgEvtNoITSROFrameBorderCut); + colCuts.setApplyCollInTimeRangeStandard(configEvents.cfgEvtNoCollInTimeRangeStandard); + colCuts.setApplyVertexTOFmatched(configEvents.cfgEvtIsVertexTOFmatched); colCuts.printCuts(); // axes @@ -255,22 +256,23 @@ struct Lambda1520analysisinpp { AxisSpec axisEta{binsEta, "#eta"}; AxisSpec axisRap{binsEta, "#it{y}"}; AxisSpec axisMassLambda1520{binsMass, "Invariant Mass (GeV/#it{c}^2)"}; - AxisSpec axisMult{binsMult, "mult_{V0M}"}; + AxisSpec axisMult{binsMult, "mult_{FT0M}"}; AxisSpec axisDCAz{binsDCAz, "DCA_{z}"}; AxisSpec axisDCAxy{binsDCAxy, "DCA_{XY}"}; AxisSpec axisTPCXrow{binsTPCXrows, "#Xrows_{TPC}"}; AxisSpec axisPIDQA{binsnSigma, "#sigma"}; AxisSpec axisTPCSignal{binsnTPCSignal, ""}; - AxisSpec axisMClabel{6, -1.5f, 5.5f, "MC Label"}; + AxisSpec axisMClabel{6, -1.5f, 6.5f, "MC Label"}; AxisSpec axisEtaPhi{binsEtaPhi, ""}; AxisSpec axisPhi{350, 0, 7, "#Phi"}; - AxisSpec axisMultMix{configBkg.cfgMultBins, "Multiplicity"}; + AxisSpec axisMultMix{configBkg.cfgMultPercentileBins, "Multiplicity Percentile"}; AxisSpec axisVtxMix{configBkg.cfgVtxBins, "Vertex Z (cm)"}; AxisSpec idxMCAxis = {26, -0.5f, 25.5f, "Index"}; if (cFilladditionalQAeventPlots) { // event histograms if (doprocessData) { + histos.add("QAevent/hEvents", "INEL>0 Events", HistType::kTH1F, {{2, 0.5f, 2.5f}}); histos.add("QAevent/hPairsCounterSameE", "total valid no. of pairs sameE", HistType::kTH1F, {{1, 0.5f, 1.5f}}); histos.add("QAevent/hnTrksSameE", "n tracks per event SameE", HistType::kTH1F, {{1000, 0.0, 1000.0}}); } @@ -287,6 +289,9 @@ struct Lambda1520analysisinpp { histos.add("QAevent/hMultiplicityPercentMixedE", "Multiplicity percentile of collision", HistType::kTH1F, {{120, 0.0f, 120.0f}}); histos.add("QAevent/hnTrksMixedE", "n tracks per event MixedE", HistType::kTH1F, {{1000, 0.0f, 1000.0f}}); } + if (doprocessMCRec) { + histos.add("QAevent/hEventsMC", "INEL>0 Events MC", HistType::kTH1F, {{2, 0.5f, 2.5f}}); + } } if (doprocessData) { @@ -395,7 +400,7 @@ struct Lambda1520analysisinpp { // MC QA histos.add("Event/hMCEventIndices", "hMCEventIndices", kTH2D, {axisMult, idxMCAxis}); - if (doprocessMCTrue) { + if (doprocessMCGen) { histos.add("QA/MC/h2GenEtaPt_beforeanycut", " #eta-#it{p}_{T} distribution of Generated #Lambda(1520); #eta; #it{p}_{T}; Counts;", HistType::kTHnSparseF, {axisEta, axisPtQA}); histos.add("QA/MC/h2GenPhiRapidity_beforeanycut", " #phi-y distribution of Generated #Lambda(1520); #phi; y; Counts;", HistType::kTHnSparseF, {axisPhi, axisRap}); histos.add("QA/MC/h2GenEtaPt_afterEtaRapCut", " #eta-#it{p}_{T} distribution of Generated #Lambda(1520); #eta; #it{p}_{T}; Counts;", HistType::kTHnSparseF, {axisEta, axisPtQA}); @@ -406,7 +411,7 @@ struct Lambda1520analysisinpp { histos.add("Result/MC/Genlambda1520pt", "pT distribution of True MC #Lambda(1520)0", kTH3F, {axisMClabel, axisPt, axisMult}); histos.add("Result/MC/Genantilambda1520pt", "pT distribution of True MC Anti-#Lambda(1520)0", kTH3F, {axisMClabel, axisPt, axisMult}); } - if (doprocessMC) { + if (doprocessMCRec) { histos.add("QA/MC/h2RecoEtaPt_after", " #eta-#it{p}_{T} distribution of Reconstructed #Lambda(1520); #eta; #it{p}_{T}; Counts;", HistType::kTHnSparseF, {axisEta, axisPt}); histos.add("QA/MC/h2RecoPhiRapidity_after", " #phi-y distribution of Reconstructed #Lambda(1520); #phi; y; Counts;", HistType::kTHnSparseF, {axisPhi, axisRap}); @@ -453,26 +458,6 @@ struct Lambda1520analysisinpp { return returnValue; } - auto static constexpr TripleCharge = 3.0f; - - // Check if the collision is INEL>0 - template - bool isTrueINEL0(MCColl const& /*mccoll*/, MCPart const& mcparts) - { - for (auto const& mcparticle : mcparts) { - if (!mcparticle.isPhysicalPrimary()) - continue; - auto p = pdg->GetParticle(mcparticle.pdgCode()); - if (p != nullptr) { - if (std::abs(p->Charge()) >= TripleCharge) { // check if the particle is charged - if (std::abs(mcparticle.eta()) < 1.0f) - return true; - } - } - } - return false; - } - template bool trackCut(const TrackType track) { @@ -1039,6 +1024,17 @@ struct Lambda1520analysisinpp { if (!colCuts.isSelected(collision)) // Default event selection return; + if (cFilladditionalQAeventPlots) { + histos.fill(HIST("QAevent/hEvents"), 1); + } + + if (!collision.isInelGt0()) // <-- + return; + + if (cFilladditionalQAeventPlots) { + histos.fill(HIST("QAevent/hEvents"), 2); + } + colCuts.fillQA(collision); fillHistograms(collision, tracks, tracks); @@ -1050,32 +1046,49 @@ struct Lambda1520analysisinpp { if (!colCuts.isSelected(collision, false)) // Default event selection return; + if (!collision.isInelGt0()) // <-- + return; + fillHistograms(collision, tracks, tracks); } PROCESS_SWITCH(Lambda1520analysisinpp, processRotational, "Process Rotational Background", false); - void processMC(MCEventCandidates::iterator const& collision, - aod::McCollisions const&, - MCTrackCandidates const& tracks, aod::McParticles const&) + void processMCRec(MCEventCandidates::iterator const& collision, + aod::McCollisions const&, + MCTrackCandidates const& tracks, aod::McParticles const&) { - colCuts.fillQA(collision); + if (!colCuts.isSelected(collision)) + return; + + if (cFilladditionalQAeventPlots) { + histos.fill(HIST("QAevent/hEventsMC"), 1); + } - if (std::abs(collision.posZ()) > cZvertCutMC) // Z-vertex cut + if (!collision.isInelGt0()) // <-- return; + if (cFilladditionalQAeventPlots) { + histos.fill(HIST("QAevent/hEventsMC"), 2); + } + fillHistograms(collision, tracks, tracks); } - PROCESS_SWITCH(Lambda1520analysisinpp, processMC, "Process Event for MC Light without partition", false); + PROCESS_SWITCH(Lambda1520analysisinpp, processMCRec, "Process Event for MC Rec without partition", false); Partition selectedMCParticles = (nabs(aod::mcparticle::pdgCode) == static_cast(Pdg::kLambda1520_Py)); // Lambda(1520) - void processMCTrue(MCEventCandidates::iterator const& collision, aod::McCollisions const&, aod::McParticles const& mcParticles) + void processMCGen(MCEventCandidates::iterator const& collision, aod::McCollisions const&, aod::McParticles const& mcParticles) { - bool isInAfterAllCuts = colCuts.isSelected(collision); + bool isInAfterAllCuts = colCuts.isSelected(collision, false); bool inVtx10 = (std::abs(collision.mcCollision().posZ()) > configEvents.cfgEvtZvtx) ? false : true; bool isTriggerTVX = collision.selection_bit(aod::evsel::kIsTriggerTVX); bool isSel8 = collision.sel8(); - bool isTrueINELgt0 = isTrueINEL0(collision, mcParticles); + + auto mcPartsAll = mcParticles.sliceBy(perMcCollision, collision.mcCollision().globalIndex()); + + bool isTrueINELgt0 = pwglf::isINELgt0mc(mcPartsAll, pdg); + // bool isTrueINELgt0 = collision.isInelGt0(); + auto centrality = centEst(collision); auto mcParts = selectedMCParticles->sliceBy(perMcCollision, collision.mcCollision().globalIndex()); @@ -1157,6 +1170,13 @@ struct Lambda1520analysisinpp { else histos.fill(HIST("Result/MC/Genantilambda1520pt"), 4, part.pt(), centrality); } + if (isInAfterAllCuts && isTrueINELgt0) // after all event selection + { + if (part.pdgCode() > 0) + histos.fill(HIST("Result/MC/Genlambda1520pt"), 5, part.pt(), centrality); + else + histos.fill(HIST("Result/MC/Genantilambda1520pt"), 5, part.pt(), centrality); + } } // QA for Trigger efficiency @@ -1198,7 +1218,7 @@ struct Lambda1520analysisinpp { if (isInAfterAllCuts && isTrueINELgt0 && inVtx10) histos.fill(HIST("Event/hMCEventIndices"), centrality, AllCutsINELg010); } - PROCESS_SWITCH(Lambda1520analysisinpp, processMCTrue, "Process Event for MC only", false); + PROCESS_SWITCH(Lambda1520analysisinpp, processMCGen, "Process Event for MC only", false); // Processing Event Mixing using BinningTypeVtxZT0M = ColumnBinningPolicy; @@ -1208,7 +1228,7 @@ struct Lambda1520analysisinpp { { auto tracksTuple = std::make_tuple(tracks); - BinningTypeVtxZT0M colBinning{{configBkg.cfgVtxBins, configBkg.cfgMultBins}, true}; + BinningTypeVtxZT0M colBinning{{configBkg.cfgVtxBins, configBkg.cfgMultPercentileBins}, true}; SameKindPair pairs{colBinning, configBkg.nEvtMixing, -1, collision, tracksTuple, &cache}; // -1 is the number of the bin to skip for (const auto& [collision1, tracks1, collision2, tracks2] : pairs) { @@ -1218,6 +1238,18 @@ struct Lambda1520analysisinpp { // LOGF(info, "Mixed event tracks pair: (%d, %d) from events (%d, %d)", t1.index(), t2.index(), collision1.index(), collision2.index()); // } + if (!colCuts.isSelected(collision1, false)) // Default event selection + return; + + if (!colCuts.isSelected(collision2, false)) // Default event selection + return; + + if (!collision1.isInelGt0()) // <-- + return; + + if (!collision2.isInelGt0()) // <-- + return; + if (cFilladditionalQAeventPlots) { // Fill histograms for the characteristics of the *mixed* events (collision1 and collision2) // This will show the distribution of events that are actually being mixed. diff --git a/PWGLF/Utils/EventSelectionFlagsMapping.def b/PWGLF/Utils/EventSelectionFlagsMapping.def index 3e23ba89cdd..06b4cb5c03a 100644 --- a/PWGLF/Utils/EventSelectionFlagsMapping.def +++ b/PWGLF/Utils/EventSelectionFlagsMapping.def @@ -49,6 +49,7 @@ EVSEL_FLAG(kNoITSROFrameBorder, applyNoITSROBorderCut, false, kFlagITSROFrameBor // Vertex quality EVSEL_FLAG(kIsVertexITSTPC, applyITSTPCvertex, false, kFlagVertexITSTPC, setApplyITSTPCvertex, ApplyITSTPCvertex, "IsVertexITSTPC", "Apply ITS-TPC vertex") EVSEL_FLAG(kIsGoodZvtxFT0vsPV, applyZvertexTimedifference, false, kFlagZvtxFT0vsPV, setApplyZvertexTimedifference, ApplyZvertexTimedifference, "IsGoodZvtxFT0vsPV", "Apply Z-vertex time difference") +EVSEL_FLAG(kIsVertexTOFmatched, applyVertexTOFmatched, false, kFlagVertexTOFmatched, setApplyVertexTOFmatched, ApplyVertexTOFmatched, "IsVertexTOFmatched", "Vertex has TOF-matched track") EVSEL_FLAG(kIsVertexTRDmatched, applyVertexTRDmatched, false, kFlagVertexTRDmatched, setApplyVertexTRDmatched, ApplyVertexTRDmatched, "IsVertexTRDmatched", "Vertex has TRD-matched track") // Pileup rejection @@ -74,5 +75,4 @@ EVSEL_FLAG(kIsBBT0A, applyBBT0A, false, kFlagBBT0A, setApplyBBT0A, ApplyBBT0A, " EVSEL_FLAG(kIsBBT0C, applyBBT0C, false, kFlagBBT0C, setApplyBBT0C, ApplyBBT0C, "IsBBT0C", "T0C in beam-beam window") // Future flags can be easily added here, for example: -// EVSEL_FLAG(kIsVertexTOFmatched, applyVertexTOFmatched, false, kFlagVertexTOFmatched, setApplyVertexTOFmatched, ApplyVertexTOFmatched, "IsVertexTOFmatched", "Apply vertex TOF matched") // EVSEL_FLAG(kNoCollInTimeRangeStrict, applyCollInTimeRangeStrict, false, kNoCollInTimeRangeStrict, setApplyCollInTimeRangeStrict, ApplyCollInTimeRangeStrict, "NoCollInTimeRangeStrict", "Apply NoCollInTimeRangeStrict") diff --git a/PWGLF/Utils/collisionCuts.h b/PWGLF/Utils/collisionCuts.h index 7b23620ee64..ebb6fd34436 100644 --- a/PWGLF/Utils/collisionCuts.h +++ b/PWGLF/Utils/collisionCuts.h @@ -46,11 +46,11 @@ class CollisonCuts kFlagTrigerTVX, kFlagTimeFrameBorder, kFlagITSROFrameBorder, - kFlagSel8, kFlagVertexITSTPC, - kFlagBunchPileup, kFlagZvtxFT0vsPV, - kFlagOccupancy, + kFlagVertexTOFmatched, + kFlagVertexTRDmatched, + kFlagBunchPileup, kNoCollInTimeRangeStandard, kNoCollInTimeRangeNarrow, kNoCollInTimeRangeStrict, @@ -60,9 +60,10 @@ class CollisonCuts kIsGoodITSLayersAll, kIsGoodITSLayer3, kIsGoodITSLayer0123, - kFlagVertexTRDmatched, kFlagBBT0A, kFlagBBT0C, + kFlagSel8, + kFlagOccupancy, kAllpassed }; @@ -111,9 +112,9 @@ class CollisonCuts mHistogramRegistry->add("Event/posZ", "; vtx_{z} (cm); Entries", o2::framework::kTH1F, {{250, -12.5, 12.5}}); // z-vertex histogram after event selections mHistogramRegistry->add("Event/posZ_noCut", "; vtx_{z} (cm); Entries", o2::framework::kTH1F, {{250, -12.5, 12.5}}); // z-vertex histogram before all selections if (mCheckIsRun3) { - mHistogramRegistry->add("Event/CentFT0M", "; vCentT0M; Entries", o2::framework::kTH1F, {{110, 0, 110}}); - mHistogramRegistry->add("Event/CentFT0C", "; vCentT0C; Entries", o2::framework::kTH1F, {{110, 0, 110}}); - mHistogramRegistry->add("Event/CentFT0A", "; vCentT0A; Entries", o2::framework::kTH1F, {{110, 0, 110}}); + mHistogramRegistry->add("Event/CentFT0M", "; FT0M Percentile; Entries", o2::framework::kTH1F, {{110, 0, 110}}); + mHistogramRegistry->add("Event/CentFT0C", "; FT0C Percentile; Entries", o2::framework::kTH1F, {{110, 0, 110}}); + mHistogramRegistry->add("Event/CentFT0A", "; FT0A Percentile; Entries", o2::framework::kTH1F, {{110, 0, 110}}); mHistogramRegistry->add("Event/posZ_ITSOnly", "; vtx_{z} (cm); Entries", o2::framework::kTH1F, {{250, -12.5, 12.5}}); mHistogramRegistry->add("Event/posZ_ITSTPC", "; vtx_{z} (cm); Entries", o2::framework::kTH1F, {{250, -12.5, 12.5}}); mHistogramRegistry->add("Event/trackOccupancyInTimeRange_noCut", "; Occupancy; Entries", o2::framework::kTH1F, {{500, 0., 20000.}}); @@ -131,6 +132,7 @@ class CollisonCuts mHistogramRegistry->get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(binLabel(EvtSel::kFlagSel8), "sel8"); mHistogramRegistry->get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(binLabel(EvtSel::kFlagOccupancy), "LowOccupancy"); + mHistogramRegistry->get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(binLabel(EvtSel::kFlagVertexTOFmatched), "VertexTOFmatched"); mHistogramRegistry->get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(binLabel(EvtSel::kAllpassed), "Allpassed"); } @@ -268,6 +270,13 @@ class CollisonCuts setSelection(EvtSel::kNoHighMultCollInPrevRof, apply); } + /// Set the VertexTOFmatched cut + void setApplyVertexTOFmatched(bool apply) + { + mApplyVertexTOFmatched = apply; + setSelection(EvtSel::kFlagVertexTOFmatched, apply); + } + /// Set the VertexTRDmatched cut void setApplyVertexTRDmatched(bool apply) { @@ -531,6 +540,7 @@ class CollisonCuts bool mApplyCollInRofStandard = false; ///< Apply NoCollInRofStandard selection bool mApplyCollInRofStrict = false; ///< Apply NoCollInRofStrict selection bool mApplyHighMultCollInPrevRof = false; ///< Apply NoHighMultCollInPrevRof selection + bool mApplyVertexTOFmatched = false; ///< Apply vertex TOF matched selection bool mApplyVertexTRDmatched = false; ///< Apply vertex TRD matched selection bool mApplyBBT0A = false; ///< Apply T0A beam-beam timing selection bool mApplyBBT0C = false; ///< Apply T0C beam-beam timing selection From 74c4d16d554927e9e39723426b72b620ee5cd0fa Mon Sep 17 00:00:00 2001 From: Lorenzo Bernardinis <95907752+lorber98@users.noreply.github.com> Date: Fri, 27 Feb 2026 10:48:25 +0100 Subject: [PATCH 104/347] [PWGLF] Bug fix: replace return with continue statement in processMCgenerated (#15168) --- PWGLF/Tasks/Strangeness/strangenessInJetsIons.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWGLF/Tasks/Strangeness/strangenessInJetsIons.cxx b/PWGLF/Tasks/Strangeness/strangenessInJetsIons.cxx index 1b25bf8e442..4cbec3a9a01 100644 --- a/PWGLF/Tasks/Strangeness/strangenessInJetsIons.cxx +++ b/PWGLF/Tasks/Strangeness/strangenessInJetsIons.cxx @@ -1408,7 +1408,7 @@ struct StrangenessInJetsIons { // Require vertex position within the allowed z range if (std::fabs(collision.posZ()) > zVtx) - return; + continue; // Fill event counter after selection on z-vertex registryMC.fill(HIST("number_of_events_mc_gen"), 1.5); From fbec99bcaa85275ba85421dff4928b065bbbfd01 Mon Sep 17 00:00:00 2001 From: JBae <110481228+joonsukbae@users.noreply.github.com> Date: Fri, 27 Feb 2026 11:02:59 +0100 Subject: [PATCH 105/347] [Common] Fix stale Q/Pt values in TrackTuner graph-based smearing (#15174) --- Common/Tools/TrackTuner.h | 65 +++++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 30 deletions(-) diff --git a/Common/Tools/TrackTuner.h b/Common/Tools/TrackTuner.h index 9a04b51be04..01ca6930d89 100644 --- a/Common/Tools/TrackTuner.h +++ b/Common/Tools/TrackTuner.h @@ -755,19 +755,24 @@ struct TrackTuner : o2::framework::ConfigurableGroup { dcaZResMC = evalGraph(ptMC, grDcaZResVsPtPionMC[phiBin].get()); dcaZResData = evalGraph(ptMC, grDcaZResVsPtPionData[phiBin].get()); - // For Q/Pt corrections, files on CCDB will be used if both qOverPtMC and qOverPtData are null + // Local Q/Pt resolution: either the constant configurable value, or evaluated per-track from graphs + double smearQOverPtMC = qOverPtMC; + double smearQOverPtData = qOverPtData; if (updateCurvature || updateCurvatureIU) { - if ((qOverPtMC < 0) || (qOverPtData < 0)) { - if (debugInfo) { - LOG(info) << "### q/pt smearing: qOverPtMC=" << qOverPtMC << ", qOverPtData=" << qOverPtData << ". One of them is negative. Retrieving then values from graphs from input .root file"; - } + if ((smearQOverPtMC < 0) || (smearQOverPtData < 0)) { /// check that input graphs for q/pt smearing are correctly retrieved if (!grOneOverPtPionData.get() || !grOneOverPtPionMC.get()) { LOG(fatal) << "### q/pt smearing: input graphs not correctly retrieved. Aborting."; } - qOverPtMC = std::max(0.0, evalGraph(ptMC, grOneOverPtPionMC.get())); - qOverPtData = std::max(0.0, evalGraph(ptMC, grOneOverPtPionData.get())); - } // qOverPtMC, qOverPtData block ends here + smearQOverPtMC = std::max(0.0, evalGraph(ptMC, grOneOverPtPionMC.get())); + smearQOverPtData = std::max(0.0, evalGraph(ptMC, grOneOverPtPionData.get())); + if (debugInfo) { + LOG(info) << "### q/pt graph-based smearing: pT=" << ptMC + << " sigma(1/pT)_MC=" << smearQOverPtMC + << " sigma(1/pT)_Data=" << smearQOverPtData + << " ratio(Data/MC)=" << (smearQOverPtMC > 0. ? smearQOverPtData / smearQOverPtMC : -1.); + } + } // smearQOverPtMC, smearQOverPtData block ends here } // updateCurvature, updateCurvatureIU block ends here if (updateTrackDCAs) { @@ -836,7 +841,7 @@ struct TrackTuner : o2::framework::ConfigurableGroup { // double dpt1o =pt1o-pt1mc; deltaQpt = trackParQPtMCRec - trackParQPtMC; // double dpt1n =dpt1o *(spt1o >0. ? (spt1n /spt1o ) : 1.); - deltaQptTuned = deltaQpt * (qOverPtMC > 0. ? (qOverPtData / qOverPtMC) : 1.); + deltaQptTuned = deltaQpt * (smearQOverPtMC > 0. ? (smearQOverPtData / smearQOverPtMC) : 1.); // double pt1n = pt1mc+dpt1n; trackParQPtTuned = trackParQPtMC + deltaQptTuned; trackParCov.setQ2Pt(trackParQPtTuned); @@ -844,36 +849,36 @@ struct TrackTuner : o2::framework::ConfigurableGroup { // updating track cov matrix elements for 1/Pt at innermost update point // if(sd0rpo>0. && spt1o>0.)covar[10]*=(sd0rpn/sd0rpo)*(spt1n/spt1o);//ypt sigma1PtY = trackParCov.getSigma1PtY(); - if (dcaXYResMC > 0. && qOverPtMC > 0.) { - sigma1PtY *= ((dcaXYResData / dcaXYResMC) * (qOverPtData / qOverPtMC)); + if (dcaXYResMC > 0. && smearQOverPtMC > 0.) { + sigma1PtY *= ((dcaXYResData / dcaXYResMC) * (smearQOverPtData / smearQOverPtMC)); trackParCov.setCov(sigma1PtY, 10); } // if(sd0zo>0. && spt1o>0.) covar[11]*=(sd0zn/sd0zo)*(spt1n/spt1o);//zpt sigma1PtZ = trackParCov.getSigma1PtZ(); - if (dcaZResMC > 0. && qOverPtMC > 0.) { - sigma1PtZ *= ((dcaZResData / dcaZResMC) * (qOverPtData / qOverPtMC)); + if (dcaZResMC > 0. && smearQOverPtMC > 0.) { + sigma1PtZ *= ((dcaZResData / dcaZResMC) * (smearQOverPtData / smearQOverPtMC)); trackParCov.setCov(sigma1PtZ, 11); } // if(spt1o>0.) covar[12]*=(spt1n/spt1o);//sinPhipt sigma1PtSnp = trackParCov.getSigma1PtSnp(); - if (qOverPtMC > 0.) { - sigma1PtSnp *= (qOverPtData / qOverPtMC); + if (smearQOverPtMC > 0.) { + sigma1PtSnp *= (smearQOverPtData / smearQOverPtMC); trackParCov.setCov(sigma1PtSnp, 12); } // if(spt1o>0.) covar[13]*=(spt1n/spt1o);//tanTpt sigma1PtTgl = trackParCov.getSigma1PtTgl(); - if (qOverPtMC > 0.) { - sigma1PtTgl *= (qOverPtData / qOverPtMC); + if (smearQOverPtMC > 0.) { + sigma1PtTgl *= (smearQOverPtData / smearQOverPtMC); trackParCov.setCov(sigma1PtTgl, 13); } // if(spt1o>0.) covar[14]*=(spt1n/spt1o)*(spt1n/spt1o);//ptpt sigma1Pt2 = trackParCov.getSigma1Pt2(); - if (qOverPtMC > 0.) { - sigma1Pt2 *= (qOverPtData / qOverPtMC) * (qOverPtData / qOverPtMC); + if (smearQOverPtMC > 0.) { + sigma1Pt2 *= (smearQOverPtData / smearQOverPtMC) * (smearQOverPtData / smearQOverPtMC); trackParCov.setCov(sigma1Pt2, 14); } } // updateCurvatureIU block ends here @@ -969,7 +974,7 @@ struct TrackTuner : o2::framework::ConfigurableGroup { } deltaQpt = trackParQPtMCRec - trackParQPtMC; // double dpt1n =dpt1o *(spt1o >0. ? (spt1n /spt1o ) : 1.); - deltaQptTuned = deltaQpt * (qOverPtMC > 0. ? (qOverPtData / qOverPtMC) : 1.); + deltaQptTuned = deltaQpt * (smearQOverPtMC > 0. ? (smearQOverPtData / smearQOverPtMC) : 1.); // double pt1n = pt1mc+dpt1n; trackParQPtTuned = trackParQPtMC + deltaQptTuned; trackParCov.setQ2Pt(trackParQPtTuned); @@ -1030,36 +1035,36 @@ struct TrackTuner : o2::framework::ConfigurableGroup { if ((updateCurvature) && (!updateCurvatureIU)) { // if(sd0rpo>0. && spt1o>0.)covar[10]*=(sd0rpn/sd0rpo)*(spt1n/spt1o);//ypt sigma1PtY = trackParCov.getSigma1PtY(); - if (dcaXYResMC > 0. && qOverPtMC > 0.) { - sigma1PtY *= ((dcaXYResData / dcaXYResMC) * (qOverPtData / qOverPtMC)); + if (dcaXYResMC > 0. && smearQOverPtMC > 0.) { + sigma1PtY *= ((dcaXYResData / dcaXYResMC) * (smearQOverPtData / smearQOverPtMC)); trackParCov.setCov(sigma1PtY, 10); } // if(sd0zo>0. && spt1o>0.) covar[11]*=(sd0zn/sd0zo)*(spt1n/spt1o);//zpt sigma1PtZ = trackParCov.getSigma1PtZ(); - if (dcaZResMC > 0. && qOverPtMC > 0.) { - sigma1PtZ *= ((dcaZResData / dcaZResMC) * (qOverPtData / qOverPtMC)); + if (dcaZResMC > 0. && smearQOverPtMC > 0.) { + sigma1PtZ *= ((dcaZResData / dcaZResMC) * (smearQOverPtData / smearQOverPtMC)); trackParCov.setCov(sigma1PtZ, 11); } // if(spt1o>0.) covar[12]*=(spt1n/spt1o);//sinPhipt sigma1PtSnp = trackParCov.getSigma1PtSnp(); - if (qOverPtMC > 0.) { - sigma1PtSnp *= (qOverPtData / qOverPtMC); + if (smearQOverPtMC > 0.) { + sigma1PtSnp *= (smearQOverPtData / smearQOverPtMC); trackParCov.setCov(sigma1PtSnp, 12); } // if(spt1o>0.) covar[13]*=(spt1n/spt1o);//tanTpt sigma1PtTgl = trackParCov.getSigma1PtTgl(); - if (qOverPtMC > 0.) { - sigma1PtTgl *= (qOverPtData / qOverPtMC); + if (smearQOverPtMC > 0.) { + sigma1PtTgl *= (smearQOverPtData / smearQOverPtMC); trackParCov.setCov(sigma1PtTgl, 13); } // if(spt1o>0.) covar[14]*=(spt1n/spt1o)*(spt1n/spt1o);//ptpt sigma1Pt2 = trackParCov.getSigma1Pt2(); - if (qOverPtMC > 0.) { - sigma1Pt2 *= (qOverPtData / qOverPtMC) * (qOverPtData / qOverPtMC); + if (smearQOverPtMC > 0.) { + sigma1Pt2 *= (smearQOverPtData / smearQOverPtMC) * (smearQOverPtData / smearQOverPtMC); trackParCov.setCov(sigma1Pt2, 14); } } // ---> track cov matrix elements for 1/Pt ends here From cf90826d4b82a81bf172a459c4e8a4a430ff84da Mon Sep 17 00:00:00 2001 From: Tonmoy Sharma Date: Fri, 27 Feb 2026 16:44:38 +0530 Subject: [PATCH 106/347] [PWGLF] Fix: Revert struct name to 'tofSpectra' for script compatibility (#15188) --- PWGLF/Tasks/Nuspex/spectraTOF.cxx | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/PWGLF/Tasks/Nuspex/spectraTOF.cxx b/PWGLF/Tasks/Nuspex/spectraTOF.cxx index b2ff348c7a7..8c49a9595dd 100644 --- a/PWGLF/Tasks/Nuspex/spectraTOF.cxx +++ b/PWGLF/Tasks/Nuspex/spectraTOF.cxx @@ -96,7 +96,7 @@ static constexpr float DcaPhiPtMax = 1.1f; static constexpr int kD0 = 421; // Spectra task -struct SpectraTOF { +struct tofSpectra { struct : ConfigurableGroup { Configurable cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted z-vertex range"}; Configurable cfgINELCut{"cfgINELCut", 0, "INEL event selection: 0 no sel, 1 INEL>0, 2 INEL>1"}; @@ -877,7 +877,7 @@ struct SpectraTOF { histos.fill(HIST("Mult/PerBC/sel8/FT0AvsFT0C"), ft0.sumAmpA(), ft0.sumAmpC()); } // end of the process function - PROCESS_SWITCH(SpectraTOF, processBC, "Processor of BCs for the FT0 calibration", true); + PROCESS_SWITCH(tofSpectra, processBC, "Processor of BCs for the FT0 calibration", true); template void fillParticleHistos(const T& track, const C& collision) @@ -1619,7 +1619,7 @@ struct SpectraTOF { } } } - PROCESS_SWITCH(SpectraTOF, processMCclosure, "MC closure test", false); + PROCESS_SWITCH(tofSpectra, processMCclosure, "MC closure test", false); void processOccupancy(CollisionCandidates::iterator const& collision, soa::Join spPerCol = aod::spectra::collisionId; SliceCache cacheTrk; @@ -1759,7 +1759,7 @@ struct SpectraTOF { } } } // end of the process function - PROCESS_SWITCH(SpectraTOF, processDerived, "Derived data processor", false); + PROCESS_SWITCH(tofSpectra, processDerived, "Derived data processor", false); #define MAKE_PROCESS_FUNCTION(processorName, inputPid, particleId, isFull, tofTable, tpcTable) \ void process##processorName##inputPid(CollisionCandidates::iterator const& collision, \ @@ -1777,7 +1777,7 @@ struct SpectraTOF { fillParticleHistos(track, collision); \ } \ } \ - PROCESS_SWITCH(SpectraTOF, process##processorName##inputPid, Form("Process for the %s hypothesis from %s tables", #particleId, #processorName), false); + PROCESS_SWITCH(tofSpectra, process##processorName##inputPid, Form("Process for the %s hypothesis from %s tables", #particleId, #processorName), false); // Full tables #define MAKE_PROCESS_FUNCTION_FULL(inputPid, particleId) MAKE_PROCESS_FUNCTION(Full, inputPid, particleId, true, TOFFull, TPCFull) @@ -2700,7 +2700,7 @@ struct SpectraTOF { } } } - PROCESS_SWITCH(SpectraTOF, processMC, "Process MC", false); + PROCESS_SWITCH(tofSpectra, processMC, "Process MC", false); void processMCgen(aod::McCollision const& mcCollision, aod::McParticles const& mcParticles) { @@ -2732,7 +2732,7 @@ struct SpectraTOF { } } } - PROCESS_SWITCH(SpectraTOF, processMCgen, "process generated MC", false); + PROCESS_SWITCH(tofSpectra, processMCgen, "process generated MC", false); void processMCgenRecoEvs(soa::Join const& tracks, @@ -2831,7 +2831,7 @@ struct SpectraTOF { } } } - PROCESS_SWITCH(SpectraTOF, processMCgenRecoEvs, "process generated MC (reconstructed events)", false); + PROCESS_SWITCH(tofSpectra, processMCgenRecoEvs, "process generated MC (reconstructed events)", false); void processTrackMCLabels(CollisionCandidates::iterator const& collisions, soa::Join(cfgc)}; } +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask(cfgc)}; } From fe4c5174ba0c62c4ae3be28cd8180918e9e9c3e5 Mon Sep 17 00:00:00 2001 From: Swati <69241911+SwatiSaha-1997@users.noreply.github.com> Date: Fri, 27 Feb 2026 17:05:51 +0530 Subject: [PATCH 107/347] [PWGCF] Correction in histname to fill DCA dist before selection (#15189) --- PWGCF/EbyEFluctuations/Tasks/MeanptFluctuations.cxx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/PWGCF/EbyEFluctuations/Tasks/MeanptFluctuations.cxx b/PWGCF/EbyEFluctuations/Tasks/MeanptFluctuations.cxx index 2040a7127a7..21ed21ad9de 100644 --- a/PWGCF/EbyEFluctuations/Tasks/MeanptFluctuations.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/MeanptFluctuations.cxx @@ -191,8 +191,8 @@ struct MeanptFluctuationsAnalysis { histos.add("hDcaZ", ";#it{dca}_{Z}", kTH1F, {{1000, -5, 5}}); histos.add("his2DdcaXYvsPt", "", {HistType::kTH2D, {ptAxis, {1000, -1, 1}}}); histos.add("his2DdcaZvsPt", "", {HistType::kTH2D, {ptAxis, {1000, -1, 1}}}); - histos.add("his2DdcaXYvsPtPtBeforePtDepSel", "", {HistType::kTH2D, {ptAxis, {1000, -1, 1}}}); - histos.add("his2DdcaZvsPtPtBeforePtDepSel", "", {HistType::kTH2D, {ptAxis, {1000, -1, 1}}}); + histos.add("his2DdcaXYvsPtBeforePtDepSel", "", {HistType::kTH2D, {ptAxis, {1000, -1, 1}}}); + histos.add("his2DdcaZvsPtBeforePtDepSel", "", {HistType::kTH2D, {ptAxis, {1000, -1, 1}}}); histos.add("hMeanPt", "", kTProfile, {centAxis}); histos.add("Hist2D_globalTracks_PVTracks", "", {HistType::kTH2D, {nchAxis, nchAxis}}); histos.add("Hist2D_cent_nch", "", {HistType::kTH2D, {nchAxis, centAxis}}); @@ -667,7 +667,7 @@ struct MeanptFluctuationsAnalysis { } histos.fill(HIST("his2DdcaXYvsPtBeforePtDepSel"), track.pt(), track.dcaXY()); - histos.fill(HIST("his2DdcaZvsPtPtBeforePtDepSel"), track.pt(), track.dcaZ()); + histos.fill(HIST("his2DdcaZvsPtBeforePtDepSel"), track.pt(), track.dcaZ()); if (cfgUsePtDepDCAxy && !(std::abs(track.dcaXY()) < fPtDepDCAxy->Eval(track.pt()))) { continue; @@ -804,7 +804,7 @@ struct MeanptFluctuationsAnalysis { } histos.fill(HIST("his2DdcaXYvsPtBeforePtDepSel"), track.pt(), track.dcaXY()); - histos.fill(HIST("his2DdcaZvsPtPtBeforePtDepSel"), track.pt(), track.dcaZ()); + histos.fill(HIST("his2DdcaZvsPtBeforePtDepSel"), track.pt(), track.dcaZ()); if (cfgUsePtDepDCAxy && !(std::abs(track.dcaXY()) < fPtDepDCAxy->Eval(track.pt()))) { continue; From be8e55bab19c4a2ee454ce8e1cf0d0de6c9ef492 Mon Sep 17 00:00:00 2001 From: rbailhac Date: Fri, 27 Feb 2026 14:55:29 +0100 Subject: [PATCH 108/347] [PWGEM] Add the possibility to select electrons with a given PID hypothesis in tracking (#15193) --- PWGEM/Dilepton/Tasks/createResolutionMap.cxx | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/PWGEM/Dilepton/Tasks/createResolutionMap.cxx b/PWGEM/Dilepton/Tasks/createResolutionMap.cxx index 891667627a1..003b1b6bfa4 100644 --- a/PWGEM/Dilepton/Tasks/createResolutionMap.cxx +++ b/PWGEM/Dilepton/Tasks/createResolutionMap.cxx @@ -146,6 +146,8 @@ struct CreateResolutionMap { Configurable includeITSsa{"includeITSsa", false, "Flag to include ITSsa tracks"}; Configurable maxpt_itssa{"maxpt_itssa", 0.15, "max pt for ITSsa track"}; Configurable maxMeanITSClusterSize{"maxMeanITSClusterSize", 16, "max x cos(lambda)"}; + Configurable checkPIDforTracking{"checkPIDforTracking", false, "check for PID in tracking"}; + Configurable PartIdentifier{"PartIdentifier", 2, "Particle identifier for selected particle; 0: electron, 1: muon, 2: pion, 3: kaon, 4: proton, 5: deuteron, 6: triton, 7: helium3, 8: alpha"}; } electroncuts; struct : ConfigurableGroup { @@ -498,6 +500,10 @@ struct CreateResolutionMap { } } + if (electroncuts.checkPIDforTracking && track.pidForTracking() != static_cast(std::abs(electroncuts.PartIdentifier))) { + return false; + } + return true; } @@ -628,8 +634,8 @@ struct CreateResolutionMap { if constexpr (withMFTCov) { auto mfttrackcov = mftCovs.rawIteratorAt(map_mfttrackcovs[mfttrack.globalIndex()]); auto muonAtMP = propagateMuon(mchtrack, mchtrack, collision, propagationPoint::kToMatchingPlane, muoncuts.matchingZ, mBzMFT, 0.0); // propagated to matching plane - o2::track::TrackParCovFwd mftsaAtMP = getTrackParCovFwd(mfttrack, mfttrackcov); // values at innermost update - mftsaAtMP.propagateToZhelix(muoncuts.matchingZ, mBzMFT); // propagated to matching plane + o2::track::TrackParCovFwd mftsaAtMP = getTrackParCovFwd(mfttrack, mfttrackcov); // values at innermost update + mftsaAtMP.propagateToZhelix(muoncuts.matchingZ, mBzMFT); // propagated to matching plane etaMatchedMFTatMP = mftsaAtMP.getEta(); phiMatchedMFTatMP = mftsaAtMP.getPhi(); etaMatchedMCHMIDatMP = muonAtMP.getEta(); From 839159f0e3a7c7bfaa315ff25ede80172fbd572d Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Fri, 27 Feb 2026 15:22:08 +0100 Subject: [PATCH 109/347] [PWGLF,PWGMM] Properly account for -1 shift between CTPinput and test bit function (#15195) --- PWGMM/Lumi/Tasks/lumiStabilityPP.cxx | 32 ++++++++++++++-------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/PWGMM/Lumi/Tasks/lumiStabilityPP.cxx b/PWGMM/Lumi/Tasks/lumiStabilityPP.cxx index 85c66f376c1..b1bca3040ed 100644 --- a/PWGMM/Lumi/Tasks/lumiStabilityPP.cxx +++ b/PWGMM/Lumi/Tasks/lumiStabilityPP.cxx @@ -108,22 +108,22 @@ struct LumiStabilityPP { std::map> histInteractionRate; static constexpr std::string_view NBCsVsTimeHistNames[NTriggerAliases][NBCCategories] = - {{"AllBCs/BC_A/nBCsVsTime", "AllBCs/BC_B/nBCsVsTime", "AllBCs/BC_C/nBCsVsTime", "AllBCs/BC_E/nBCsVsTime", "AllBCs/BC_L/nBCsVsTime", "AllBCs/BC_LE/nBCsVsTime", "AllBCs/BC_NL/nBCsVsTime", "AllBCs/BC_NLE/nBCsVsTime", "AllBCs/BC_SL_FDD/nBCsVsTime", "AllBCs/BC_SL_FT0/nBCsVsTime", "AllBCs/BC_NSL_FT0/nBCsVsTime", "AllBCs/BC_NSL_FDD/nBCsVsTime"}, - {"FT0VTx/BC_A/nBCsVsTime", "FT0VTx/BC_B/nBCsVsTime", "FT0VTx/BC_C/nBCsVsTime", "FT0VTx/BC_E/nBCsVsTime", "FT0VTx/BC_L/nBCsVsTime", "FT0VTx/BC_LE/nBCsVsTime", "FT0VTx/BC_NL/nBCsVsTime", "FT0VTx/BC_NLE/nBCsVsTime", "FT0VTx/BC_SL_FDD/nBCsVsTime", "FT0VTx/BC_SL_FT0/nBCsVsTime", "FT0VTx/BC_NSL_FT0/nBCsVsTime", "FT0VTx/BC_NSL_FDD/nBCsVsTime"}, - {"FT0CE/BC_A/nBCsVsTime", "FT0CE/BC_B/nBCsVsTime", "FT0CE/BC_C/nBCsVsTime", "FT0CE/BC_E/nBCsVsTime", "FT0CE/BC_L/nBCsVsTime", "FT0CE/BC_LE/nBCsVsTime", "FT0CE/BC_NL/nBCsVsTime", "FT0CE/BC_NLE/nBCsVsTime", "FT0CE/BC_SL_FDD/nBCsVsTime", "FT0CE/BC_SL_FT0/nBCsVsTime", "FT0CE/BC_NSL_FT0/nBCsVsTime", "FT0CE/BC_NSL_FDD/nBCsVsTime"}, - {"FDD/BC_A/nBCsVsTime", "FDD/BC_B/nBCsVsTime", "FDD/BC_C/nBCsVsTime", "FDD/BC_E/nBCsVsTime", "FDD/BC_L/nBCsVsTime", "FDD/BC_LE/nBCsVsTime", "FDD/BC_NL/nBCsVsTime", "FDD/BC_NLE/nBCsVsTime", "FDD/BC_SL_FDD/nBCsVsTime", "FDD/BC_SL_FT0/nBCsVsTime", "FDD/BC_NSL_FT0/nBCsVsTime", "FDD/BC_NSL_FDD/nBCsVsTime"}}; + {{"AllBCs/BC_A/nBCsVsTime", "AllBCs/BC_B/nBCsVsTime", "AllBCs/BC_C/nBCsVsTime", "AllBCs/BC_E/nBCsVsTime", "AllBCs/BC_L/nBCsVsTime", "AllBCs/BC_LE/nBCsVsTime", "AllBCs/BC_NL/nBCsVsTime", "AllBCs/BC_NLE/nBCsVsTime", "AllBCs/BC_SL_FDD/nBCsVsTime", "AllBCs/BC_SL_FT0/nBCsVsTime", "AllBCs/BC_NSL_FDD/nBCsVsTime", "AllBCs/BC_NSL_FT0/nBCsVsTime"}, + {"FT0VTx/BC_A/nBCsVsTime", "FT0VTx/BC_B/nBCsVsTime", "FT0VTx/BC_C/nBCsVsTime", "FT0VTx/BC_E/nBCsVsTime", "FT0VTx/BC_L/nBCsVsTime", "FT0VTx/BC_LE/nBCsVsTime", "FT0VTx/BC_NL/nBCsVsTime", "FT0VTx/BC_NLE/nBCsVsTime", "FT0VTx/BC_SL_FDD/nBCsVsTime", "FT0VTx/BC_SL_FT0/nBCsVsTime", "FT0VTx/BC_NSL_FDD/nBCsVsTime", "FT0VTx/BC_NSL_FT0/nBCsVsTime"}, + {"FT0CE/BC_A/nBCsVsTime", "FT0CE/BC_B/nBCsVsTime", "FT0CE/BC_C/nBCsVsTime", "FT0CE/BC_E/nBCsVsTime", "FT0CE/BC_L/nBCsVsTime", "FT0CE/BC_LE/nBCsVsTime", "FT0CE/BC_NL/nBCsVsTime", "FT0CE/BC_NLE/nBCsVsTime", "FT0CE/BC_SL_FDD/nBCsVsTime", "FT0CE/BC_SL_FT0/nBCsVsTime", "FT0CE/BC_NSL_FDD/nBCsVsTime", "FT0CE/BC_NSL_FT0/nBCsVsTime"}, + {"FDD/BC_A/nBCsVsTime", "FDD/BC_B/nBCsVsTime", "FDD/BC_C/nBCsVsTime", "FDD/BC_E/nBCsVsTime", "FDD/BC_L/nBCsVsTime", "FDD/BC_LE/nBCsVsTime", "FDD/BC_NL/nBCsVsTime", "FDD/BC_NLE/nBCsVsTime", "FDD/BC_SL_FDD/nBCsVsTime", "FDD/BC_SL_FT0/nBCsVsTime", "FDD/BC_NSL_FDD/nBCsVsTime", "FDD/BC_NSL_FT0/nBCsVsTime"}}; static constexpr std::string_view NBCsVsBCIDHistNames[NTriggerAliases][NBCCategories] = - {{"AllBCs/BC_A/nBCsVsBCID", "AllBCs/BC_B/nBCsVsBCID", "AllBCs/BC_C/nBCsVsBCID", "AllBCs/BC_E/nBCsVsBCID", "AllBCs/BC_L/nBCsVsBCID", "AllBCs/BC_LE/nBCsVsBCID", "AllBCs/BC_NL/nBCsVsBCID", "AllBCs/BC_NLE/nBCsVsBCID", "AllBCs/BC_SL_FDD/nBCsVsBCID", "AllBCs/BC_SL_FT0/nBCsVsBCID", "AllBCs/BC_NSL_FT0/nBCsVsBCID", "AllBCs/BC_NSL_FDD/nBCsVsBCID"}, - {"FT0VTx/BC_A/nBCsVsBCID", "FT0VTx/BC_B/nBCsVsBCID", "FT0VTx/BC_C/nBCsVsBCID", "FT0VTx/BC_E/nBCsVsBCID", "FT0VTx/BC_L/nBCsVsBCID", "FT0VTx/BC_LE/nBCsVsBCID", "FT0VTx/BC_NL/nBCsVsBCID", "FT0VTx/BC_NLE/nBCsVsBCID", "FT0VTx/BC_SL_FDD/nBCsVsBCID", "FT0VTx/BC_SL_FT0/nBCsVsBCID", "FT0VTx/BC_NSL_FT0/nBCsVsBCID", "FT0VTx/BC_NSL_FDD/nBCsVsBCID"}, - {"FT0CE/BC_A/nBCsVsBCID", "FT0CE/BC_B/nBCsVsBCID", "FT0CE/BC_C/nBCsVsBCID", "FT0CE/BC_E/nBCsVsBCID", "FT0CE/BC_L/nBCsVsBCID", "FT0CE/BC_LE/nBCsVsBCID", "FT0CE/BC_NL/nBCsVsBCID", "FT0CE/BC_NLE/nBCsVsBCID", "FT0CE/BC_SL_FDD/nBCsVsBCID", "FT0CE/BC_SL_FT0/nBCsVsBCID", "FT0CE/BC_NSL_FT0/nBCsVsBCID", "FT0CE/BC_NSL_FDD/nBCsVsBCID"}, - {"FDD/BC_A/nBCsVsBCID", "FDD/BC_B/nBCsVsBCID", "FDD/BC_C/nBCsVsBCID", "FDD/BC_E/nBCsVsBCID", "FDD/BC_L/nBCsVsBCID", "FDD/BC_LE/nBCsVsBCID", "FDD/BC_NL/nBCsVsBCID", "FDD/BC_NLE/nBCsVsBCID", "FDD/BC_SL_FDD/nBCsVsBCID", "FDD/BC_SL_FT0/nBCsVsBCID", "FDD/BC_NSL_FT0/nBCsVsBCID", "FDD/BC_NSL_FDD/nBCsVsBCID"}}; + {{"AllBCs/BC_A/nBCsVsBCID", "AllBCs/BC_B/nBCsVsBCID", "AllBCs/BC_C/nBCsVsBCID", "AllBCs/BC_E/nBCsVsBCID", "AllBCs/BC_L/nBCsVsBCID", "AllBCs/BC_LE/nBCsVsBCID", "AllBCs/BC_NL/nBCsVsBCID", "AllBCs/BC_NLE/nBCsVsBCID", "AllBCs/BC_SL_FDD/nBCsVsBCID", "AllBCs/BC_SL_FT0/nBCsVsBCID", "AllBCs/BC_NSL_FDD/nBCsVsBCID", "AllBCs/BC_NSL_FT0/nBCsVsBCID"}, + {"FT0VTx/BC_A/nBCsVsBCID", "FT0VTx/BC_B/nBCsVsBCID", "FT0VTx/BC_C/nBCsVsBCID", "FT0VTx/BC_E/nBCsVsBCID", "FT0VTx/BC_L/nBCsVsBCID", "FT0VTx/BC_LE/nBCsVsBCID", "FT0VTx/BC_NL/nBCsVsBCID", "FT0VTx/BC_NLE/nBCsVsBCID", "FT0VTx/BC_SL_FDD/nBCsVsBCID", "FT0VTx/BC_SL_FT0/nBCsVsBCID", "FT0VTx/BC_NSL_FDD/nBCsVsBCID", "FT0VTx/BC_NSL_FT0/nBCsVsBCID"}, + {"FT0CE/BC_A/nBCsVsBCID", "FT0CE/BC_B/nBCsVsBCID", "FT0CE/BC_C/nBCsVsBCID", "FT0CE/BC_E/nBCsVsBCID", "FT0CE/BC_L/nBCsVsBCID", "FT0CE/BC_LE/nBCsVsBCID", "FT0CE/BC_NL/nBCsVsBCID", "FT0CE/BC_NLE/nBCsVsBCID", "FT0CE/BC_SL_FDD/nBCsVsBCID", "FT0CE/BC_SL_FT0/nBCsVsBCID", "FT0CE/BC_NSL_FDD/nBCsVsBCID", "FT0CE/BC_NSL_FT0/nBCsVsBCID"}, + {"FDD/BC_A/nBCsVsBCID", "FDD/BC_B/nBCsVsBCID", "FDD/BC_C/nBCsVsBCID", "FDD/BC_E/nBCsVsBCID", "FDD/BC_L/nBCsVsBCID", "FDD/BC_LE/nBCsVsBCID", "FDD/BC_NL/nBCsVsBCID", "FDD/BC_NLE/nBCsVsBCID", "FDD/BC_SL_FDD/nBCsVsBCID", "FDD/BC_SL_FT0/nBCsVsBCID", "FDD/BC_NSL_FDD/nBCsVsBCID", "FDD/BC_NSL_FT0/nBCsVsBCID"}}; static constexpr std::string_view NBCsInspectVsBCIDHistNames[NTriggerAliases][NBCCategories] = - {{"AllBCs/BC_A/nBCsInspectedVsBCID", "AllBCs/BC_B/nBCsInspectedVsBCID", "AllBCs/BC_C/nBCsInspectedVsBCID", "AllBCs/BC_E/nBCsInspectedVsBCID", "AllBCs/BC_L/nBCsInspectedVsBCID", "AllBCs/BC_LE/nBCsInspectedVsBCID", "AllBCs/BC_NL/nBCsInspectedVsBCID", "AllBCs/BC_NLE/nBCsInspectedVsBCID", "AllBCs/BC_SL_FDD/nBCsInspectedVsBCID", "AllBCs/BC_SL_FT0/nBCsInspectedVsBCID", "AllBCs/BC_NSL_FT0/nBCsInspectedVsBCID", "AllBCs/BC_NSL_FDD/nBCsInspectedVsBCID"}, - {"FT0VTx/BC_A/nBCsInspectedVsBCID", "FT0VTx/BC_B/nBCsInspectedVsBCID", "FT0VTx/BC_C/nBCsInspectedVsBCID", "FT0VTx/BC_E/nBCsInspectedVsBCID", "FT0VTx/BC_L/nBCsInspectedVsBCID", "FT0VTx/BC_LE/nBCsInspectedVsBCID", "FT0VTx/BC_NL/nBCsInspectedVsBCID", "FT0VTx/BC_NLE/nBCsInspectedVsBCID", "FT0VTx/BC_SL_FDD/nBCsInspectedVsBCID", "FT0VTx/BC_SL_FT0/nBCsInspectedVsBCID", "FT0VTx/BC_NSL_FT0/nBCsInspectedVsBCID", "FT0VTx/BC_NSL_FDD/nBCsInspectedVsBCID"}, - {"FT0CE/BC_A/nBCsInspectedVsBCID", "FT0CE/BC_B/nBCsInspectedVsBCID", "FT0CE/BC_C/nBCsInspectedVsBCID", "FT0CE/BC_E/nBCsInspectedVsBCID", "FT0CE/BC_L/nBCsInspectedVsBCID", "FT0CE/BC_LE/nBCsInspectedVsBCID", "FT0CE/BC_NL/nBCsInspectedVsBCID", "FT0CE/BC_NLE/nBCsInspectedVsBCID", "FT0CE/BC_SL_FDD/nBCsInspectedVsBCID", "FT0CE/BC_SL_FT0/nBCsInspectedVsBCID", "FT0CE/BC_NSL_FT0/nBCsInspectedVsBCID", "FT0CE/BC_NSL_FDD/nBCsInspectedVsBCID"}, - {"FDD/BC_A/nBCsInspectedVsBCID", "FDD/BC_B/nBCsInspectedVsBCID", "FDD/BC_C/nBCsInspectedVsBCID", "FDD/BC_E/nBCsInspectedVsBCID", "FDD/BC_L/nBCsInspectedVsBCID", "FDD/BC_LE/nBCsInspectedVsBCID", "FDD/BC_NL/nBCsInspectedVsBCID", "FDD/BC_NLE/nBCsInspectedVsBCID", "FDD/BC_SL_FDD/nBCsInspectedVsBCID", "FDD/BC_SL_FT0/nBCsInspectedVsBCID", "FDD/BC_NSL_FT0/nBCsInspectedVsBCID", "FDD/BC_NSL_FDD/nBCsInspectedVsBCID"}}; + {{"AllBCs/BC_A/nBCsInspectedVsBCID", "AllBCs/BC_B/nBCsInspectedVsBCID", "AllBCs/BC_C/nBCsInspectedVsBCID", "AllBCs/BC_E/nBCsInspectedVsBCID", "AllBCs/BC_L/nBCsInspectedVsBCID", "AllBCs/BC_LE/nBCsInspectedVsBCID", "AllBCs/BC_NL/nBCsInspectedVsBCID", "AllBCs/BC_NLE/nBCsInspectedVsBCID", "AllBCs/BC_SL_FDD/nBCsInspectedVsBCID", "AllBCs/BC_SL_FT0/nBCsInspectedVsBCID", "AllBCs/BC_NSL_FDD/nBCsInspectedVsBCID", "AllBCs/BC_NSL_FT0/nBCsInspectedVsBCID"}, + {"FT0VTx/BC_A/nBCsInspectedVsBCID", "FT0VTx/BC_B/nBCsInspectedVsBCID", "FT0VTx/BC_C/nBCsInspectedVsBCID", "FT0VTx/BC_E/nBCsInspectedVsBCID", "FT0VTx/BC_L/nBCsInspectedVsBCID", "FT0VTx/BC_LE/nBCsInspectedVsBCID", "FT0VTx/BC_NL/nBCsInspectedVsBCID", "FT0VTx/BC_NLE/nBCsInspectedVsBCID", "FT0VTx/BC_SL_FDD/nBCsInspectedVsBCID", "FT0VTx/BC_SL_FT0/nBCsInspectedVsBCID", "FT0VTx/BC_NSL_FDD/nBCsInspectedVsBCID", "FT0VTx/BC_NSL_FT0/nBCsInspectedVsBCID"}, + {"FT0CE/BC_A/nBCsInspectedVsBCID", "FT0CE/BC_B/nBCsInspectedVsBCID", "FT0CE/BC_C/nBCsInspectedVsBCID", "FT0CE/BC_E/nBCsInspectedVsBCID", "FT0CE/BC_L/nBCsInspectedVsBCID", "FT0CE/BC_LE/nBCsInspectedVsBCID", "FT0CE/BC_NL/nBCsInspectedVsBCID", "FT0CE/BC_NLE/nBCsInspectedVsBCID", "FT0CE/BC_SL_FDD/nBCsInspectedVsBCID", "FT0CE/BC_SL_FT0/nBCsInspectedVsBCID", "FT0CE/BC_NSL_FDD/nBCsInspectedVsBCID", "FT0CE/BC_NSL_FT0/nBCsInspectedVsBCID"}, + {"FDD/BC_A/nBCsInspectedVsBCID", "FDD/BC_B/nBCsInspectedVsBCID", "FDD/BC_C/nBCsInspectedVsBCID", "FDD/BC_E/nBCsInspectedVsBCID", "FDD/BC_L/nBCsInspectedVsBCID", "FDD/BC_LE/nBCsInspectedVsBCID", "FDD/BC_NL/nBCsInspectedVsBCID", "FDD/BC_NLE/nBCsInspectedVsBCID", "FDD/BC_SL_FDD/nBCsInspectedVsBCID", "FDD/BC_SL_FT0/nBCsInspectedVsBCID", "FDD/BC_NSL_FDD/nBCsInspectedVsBCID", "FDD/BC_NSL_FT0/nBCsInspectedVsBCID"}}; static constexpr std::string_view PatternHistNames[BCSLFDD] = {"BC_A/BcPattern", "BC_B/BcPattern", "BC_C/BcPattern", "BC_E/BcPattern", "BC_L/BcPattern", "BC_LE/BcPattern", "BC_NL/BcPattern", "BC_NLE/BcPattern"}; @@ -337,11 +337,11 @@ struct LumiStabilityPP { isSuperLeadingBcFT0 = false; // not a super-leading BC for FT0 } - if (ctpInputMask.test(13) || ctpInputMask.test(15) || ctpInputMask.test(16) || ctpInputMask.test(17) || ctpInputMask.test(18)) { // 5 FDD triggers - globalBCIdOfLastBCWithActivityFDD = globalBC; + if (ctpInputMask.test(12) || ctpInputMask.test(14) || ctpInputMask.test(15) || ctpInputMask.test(16) || ctpInputMask.test(17)) { // 5 FDD triggers + globalBCIdOfLastBCWithActivityFDD = globalBCFDD; } - if (ctpInputMask.test(1) || ctpInputMask.test(2) || ctpInputMask.test(3) || ctpInputMask.test(4) || ctpInputMask.test(5)) { // 5 FT0 triggers - globalBCIdOfLastBCWithActivityFT0 = globalBCFDD; + if (ctpInputMask.test(0) || ctpInputMask.test(1) || ctpInputMask.test(2) || ctpInputMask.test(3) || ctpInputMask.test(4)) { // 5 FT0 triggers + globalBCIdOfLastBCWithActivityFT0 = globalBC; } if (!bcPatternB[localBC]) { From 1eb465552a08fbf255710404bb1d6d379695fe07 Mon Sep 17 00:00:00 2001 From: nkaratze Date: Fri, 27 Feb 2026 16:18:51 +0100 Subject: [PATCH 110/347] [PWGLF] Minor Table Subscription Change (#15192) --- PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx b/PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx index 976e0f3a4bf..e3587cec700 100644 --- a/PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx +++ b/PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx @@ -697,7 +697,7 @@ struct V0PtInvMassPlots { // This is the process for Generated Particles void genMCProcess(soa::Join::iterator const& mcCollision, - soa::SmallGroups> const& collisions, + soa::SmallGroups> const& collisions, aod::McParticles const& mcParticles) { // Event Efficiency, Event Split and V0 Signal Loss Corrections From a0208840a9e11484c02f80e96a4cf424adfe4ab1 Mon Sep 17 00:00:00 2001 From: Giorgio Alberto Lucia <87222843+GiorgioAlbertoLucia@users.noreply.github.com> Date: Fri, 27 Feb 2026 17:30:27 +0100 Subject: [PATCH 111/347] [PWGLF] Fixed calculation in correctPtHe3TrackedAsTriton function (#15181) --- PWGLF/TableProducer/Nuspex/he3HadronFemto.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PWGLF/TableProducer/Nuspex/he3HadronFemto.cxx b/PWGLF/TableProducer/Nuspex/he3HadronFemto.cxx index 029b8e95b89..41e5a177282 100644 --- a/PWGLF/TableProducer/Nuspex/he3HadronFemto.cxx +++ b/PWGLF/TableProducer/Nuspex/he3HadronFemto.cxx @@ -514,9 +514,9 @@ struct he3HadronFemto { float correctPtHe3TrackedAsTriton(const float pt, const uint32_t pidForTracking) { if (pt < 2.5 && pidForTracking == o2::track::PID::Triton) - return pt * 2. * (1. - kHePidTrkParams[0] - kHePidTrkParams[1] * pt * 2.); + return pt * (1. - kHePidTrkParams[0] - kHePidTrkParams[1] * pt); - return pt * 2.; + return pt; } float computeNsigmaDCA(const float pt, const float dca, const int iSpecies, const char* dcaType = "xy") From 05873aaffc3207776dc322cf63ce4891a8af3ad1 Mon Sep 17 00:00:00 2001 From: Hirak Koley Date: Sat, 28 Feb 2026 03:42:50 +0530 Subject: [PATCH 112/347] [PWGLF] Added centrality estimator for phitask and new separate kstar task (#15197) Co-authored-by: ALICE Action Bot --- PWGLF/Tasks/Resonances/CMakeLists.txt | 18 +- PWGLF/Tasks/Resonances/kstar0analysis.cxx | 947 ++++++++++++++++++ .../{phiOO.cxx => phi1020analysis.cxx} | 62 +- 3 files changed, 1005 insertions(+), 22 deletions(-) create mode 100644 PWGLF/Tasks/Resonances/kstar0analysis.cxx rename PWGLF/Tasks/Resonances/{phiOO.cxx => phi1020analysis.cxx} (94%) diff --git a/PWGLF/Tasks/Resonances/CMakeLists.txt b/PWGLF/Tasks/Resonances/CMakeLists.txt index e4bc31fc311..e129ce85dcf 100644 --- a/PWGLF/Tasks/Resonances/CMakeLists.txt +++ b/PWGLF/Tasks/Resonances/CMakeLists.txt @@ -254,8 +254,13 @@ o2physics_add_dpl_workflow(kstarinoo PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(phioo - SOURCES phiOO.cxx +o2physics_add_dpl_workflow(kstar0analysis + SOURCES kstar0analysis.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(phi1020analysis + SOURCES phi1020analysis.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) @@ -268,30 +273,37 @@ o2physics_add_dpl_workflow(phispectrapbpbqa SOURCES phispectrapbpbqa.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(phi-1020-spherocity-analysis SOURCES phi1020SpherocityAnalysis.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(phitutorial SOURCES phitutorial.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) - o2physics_add_dpl_workflow(phitutorial-step0 + +o2physics_add_dpl_workflow(phitutorial-step0 SOURCES phitutorial_step0.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(phitutorial-step1 SOURCES phitutorial_step1.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(phitutorial-step2 SOURCES phitutorial_step2.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(phitutorial-step3 SOURCES phitutorial_step3.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(k892hadronphoton SOURCES k892hadronphoton.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::AnalysisCCDB diff --git a/PWGLF/Tasks/Resonances/kstar0analysis.cxx b/PWGLF/Tasks/Resonances/kstar0analysis.cxx new file mode 100644 index 00000000000..6fa7b2b21aa --- /dev/null +++ b/PWGLF/Tasks/Resonances/kstar0analysis.cxx @@ -0,0 +1,947 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +/// \file kstar0analysis.cxx +/// \brief the reconstruction of k*0(892) resonance analysis using K\pi decay channel +/// \author Hirak Kumar Koley + +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "CommonConstants/PhysicsConstants.h" +#include "DataFormatsParameters/GRPObject.h" +#include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "ReconstructionDataFormats/Track.h" +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct kstar0analysis { + SliceCache cache; + Preslice perCollision = aod::track::collisionId; + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + //================================== + //|| + //|| Selection + //|| + //================================== + + // Event Selection + Configurable cfgEventSelections{"cfgEventSelections", "sel8", "Set event selection"}; + Configurable cfgEventVtxCut{"cfgEventVtxCut", 10.0, "V_z cut selection"}; + ConfigurableAxis cfgCentAxis{"cfgCentAxis", {VARIABLE_WIDTH, 0.0, 1.0, 5.0, 10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0}, "Binning of the centrality axis"}; + Configurable cfgOccupancySel{"cfgOccupancySel", false, "Occupancy selection"}; + Configurable cfgOccupancyMax{"cfgOccupancyMax", 999999., "maximum occupancy of tracks in neighbouring collisions in a given time range"}; + Configurable cfgOccupancyMin{"cfgOccupancyMin", -100., "minimum occupancy of tracks in neighbouring collisions in a given time range"}; + + // Track Selection + // General + Configurable cfgTrackMinPt{"cfgTrackMinPt", 0.15, "set track min pT"}; + Configurable cfgTrackMaxEta{"cfgTrackMaxEta", 0.8, "set track max Eta"}; + Configurable cfgTrackMaxDCArToPVcut{"cfgTrackMaxDCArToPVcut", 0.5, "Track DCAr cut to PV Maximum"}; + Configurable cfgTrackMaxDCAzToPVcut{"cfgTrackMaxDCAzToPVcut", 2.0, "Track DCAz cut to PV Maximum"}; + Configurable cfgTrackGlobalSel{"cfgTrackGlobalSel", true, "Global track selection"}; + Configurable cfgTrackPrimaryTrack{"cfgTrackPrimaryTrack", true, "Primary track selection"}; // kGoldenChi2 | kDCAxy | kDCAz + Configurable cfgTrackConnectedToPV{"cfgTrackConnectedToPV", true, "PV contributor track selection"}; // PV Contriuibutor + Configurable cfgTrackGlobalWoDCATrack{"cfgTrackGlobalWoDCATrack", true, "Global track selection without DCA"}; // kQualityTracks (kTrackType | kTPCNCls | kTPCCrossedRows | kTPCCrossedRowsOverNCls | kTPCChi2NDF | kTPCRefit | kITSNCls | kITSChi2NDF | kITSRefit | kITSHits) | kInAcceptanceTracks (kPtRange | kEtaRange) + + // TPC + Configurable cfgTrackFindableTPCClusters{"cfgTrackFindableTPCClusters", 50, "nFindable TPC Clusters"}; + Configurable cfgTrackTPCCrossedRows{"cfgTrackTPCCrossedRows", 70, "nCrossed TPC Rows"}; + Configurable cfgTrackRowsOverFindable{"cfgTrackRowsOverFindable", 1.2, "nRowsOverFindable TPC CLusters"}; + Configurable cfgTrackTPCChi2{"cfgTrackTPCChi2", 4.0, "nTPC Chi2 per Cluster"}; + + // ITS + Configurable cfgTrackITSChi2{"cfgTrackITSChi2", 36.0, "nITS Chi2 per Cluster"}; + + // PID + Configurable cfgTrackTPCPID{"cfgTrackTPCPID", true, "Enables TPC PID"}; + Configurable cfgTrackTOFPID{"cfgTrackTOFPID", true, "Enables TOF PID"}; + Configurable cfgTrackSquarePIDCut{"cfgTrackSqurePIDCut", true, "Enables PID cut shape square switch"}; + Configurable cfgTrackCirclePIDCut{"cfgTrackCirclePIDCut", true, "Enables PID cut shape circle switch"}; + Configurable cfgTrackCircleValue{"cfgTrackCircleValue", 2, "Enables TOF TPC PID circle cut value"}; + Configurable cfgTrackTOFHard{"cfgTrackTOFHard", false, "Enables TOF Hard"}; + + Configurable cfgTrackTPCPIDnSig{"cfgTrackTPCPIDnSig", 4.0, "nTPC PID sigma"}; + Configurable cfgTrackTOFPIDnSig{"cfgTrackTOFPIDnSig", 4.0, "nTOF PID sigma"}; + Configurable cDebugLevel{"cDebugLevel", 0, "Resolution of Debug"}; + + // Mixing + ConfigurableAxis cfgBinsMixMult{"cfgBinsCent", {VARIABLE_WIDTH, 0.0, 1.0, 5.0, 10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0, 110.0}, "Binning of the centrality axis"}; + ConfigurableAxis cfgBinsMixVtx{"cfgBinsMixVtx", {VARIABLE_WIDTH, -10.0f, -5.f, 0.f, 5.f, 10.f}, "Mixing bins - z-vertex"}; + Configurable cfgMixNMixedEvents{"cfgMixNMixedEvents", 10, "Number of mixed events per event"}; + Configurable cfgVtxMixCut{"cfgVtxMixCut", 10, "Vertex Mix Cut"}; + + // MCGen + Configurable cfgForceGenReco{"cfgForceGenReco", false, "Only consider events which are reconstructed (neglect event-loss)"}; + Configurable cfgReqMcEffPID{"cfgReqMcEffPID", false, "Request McEfficiency PID"}; + + // Pair + Configurable cfgMinvNBins{"cfgMinvNBins", 300, "Number of bins for Minv axis"}; + Configurable cfgMinvMin{"cfgMinvMin", 0.60, "Minimum Minv value"}; + Configurable cfgMinvMax{"cfgMinvMax", 1.20, "Maximum Minv value"}; + + // Histogram + ConfigurableAxis binsDCAz{"binsDCAz", {40, -0.2, 0.2}, ""}; + ConfigurableAxis binsDCAxy{"binsDCAxy", {40, -0.2, 0.2}, ""}; + Configurable cfgEventCutQA{"cfgEventCutsQA", false, "Enable Event QA Hists"}; + Configurable cfgTrackCutQA{"cfgTrackCutQA", false, "Enable Track QA Hists"}; + + Configurable cfgMCHistos{"cfgMCHistos", false, "Enable MC Hists"}; + Configurable cfgMixedHistos{"cfgMixedHistos", false, "Enable Mixed Histos"}; + Configurable cfgManualEvSel{"cfgManualEvSel", false, "Enable Manual EvSel"}; + + // Main + void init(o2::framework::InitContext&) + { + // HISTOGRAMS + const AxisSpec axisEta{30, -1.5, +1.5, "#eta"}; + const AxisSpec axisPhi{200, -1, +7, "#phi"}; + const AxisSpec ptAxis = {200, 0, 20.0}; + const AxisSpec pidAxis = {120, -6, 6}; + const AxisSpec minvAxis = {cfgMinvNBins, cfgMinvMin, cfgMinvMax}; + const AxisSpec axisDCAz{binsDCAz, "DCA_{z}"}; + const AxisSpec axisDCAxy{binsDCAxy, "DCA_{XY}"}; + + if (cfgEventCutQA) { + histos.add("hEvent_Cut", "Number of event after cuts", kTH1D, {{13, -0.5, 12.5}}); + histos.add("hPosZ_BC", "hPosZ_BC", kTH1F, {{300, -15.0, 15.0}}); + histos.add("hPosZ_AC", "hPosZ_AC", kTH1F, {{300, -15.0, 15.0}}); + histos.add("hcentFT0C_BC", "centFT0C_BC", kTH1F, {{110, 0.0, 110.0}}); + histos.add("hcentFT0C_AC", "centFT0C_AC", kTH1F, {{110, 0.0, 110.0}}); + } + if (cfgTrackCutQA) { + histos.add("hDCArToPv_BC", "DCArToPv_BC", kTH1F, {axisDCAxy}); + histos.add("hDCAzToPv_BC", "DCAzToPv_BC", kTH1F, {axisDCAz}); + histos.add("hIsPrim_BC", "hIsPrim_BC", kTH1F, {{2, -0.5, 1.5}}); + histos.add("hIsGood_BC", "hIsGood_BC", kTH1F, {{2, -0.5, 1.5}}); + histos.add("hIsPrimCont_BC", "hIsPrimCont_BC", kTH1F, {{2, -0.5, 1.5}}); + histos.add("hFindableTPCClusters_BC", "hFindableTPCClusters_BC", kTH1F, {{200, 0, 200}}); + histos.add("hFindableTPCRows_BC", "hFindableTPCRows_BC", kTH1F, {{200, 0, 200}}); + histos.add("hClustersVsRows_BC", "hClustersVsRows_BC", kTH1F, {{200, 0, 2}}); + histos.add("hTPCChi2_BC", "hTPCChi2_BC", kTH1F, {{200, 0, 100}}); + histos.add("hITSChi2_BC", "hITSChi2_BC", kTH1F, {{200, 0, 100}}); + histos.add("QA_nSigma_pion_TPC_BC", "QA_nSigma_pion_TPC_BC", {HistType::kTH2F, {ptAxis, pidAxis}}); + histos.add("QA_nSigma_pion_TOF_BC", "QA_nSigma_pion_TOF_BC", {HistType::kTH2F, {ptAxis, pidAxis}}); + histos.add("QA_pion_TPC_TOF_BC", "QA_pion_TPC_TOF_BC", {HistType::kTH2F, {pidAxis, pidAxis}}); + histos.add("QA_nSigma_kaon_TPC_BC", "QA_nSigma_kaon_TPC_BC", {HistType::kTH2F, {ptAxis, pidAxis}}); + histos.add("QA_nSigma_kaon_TOF_BC", "QA_nSigma_kaon_TOF_BC", {HistType::kTH2F, {ptAxis, pidAxis}}); + histos.add("QA_kaon_TPC_TOF_BC", "QA_kaon_TPC_TOF_BC", {HistType::kTH2F, {pidAxis, pidAxis}}); + histos.add("QA_track_pT_BC", "QA_track_pT_BC", kTH1F, {{13, 0.0, 13.0}}); + + histos.add("hDCArToPv_AC", "DCArToPv_AC", kTH1F, {axisDCAxy}); + histos.add("hDCAzToPv_AC", "DCAzToPv_AC", kTH1F, {axisDCAz}); + histos.add("hIsPrim_AC", "hIsPrim_AC", kTH1F, {{2, -0.5, 1.5}}); + histos.add("hIsGood_AC", "hIsGood_AC", kTH1F, {{2, -0.5, 1.5}}); + histos.add("hIsPrimCont_AC", "hIsPrimCont_AC", kTH1F, {{2, -0.5, 1.5}}); + histos.add("hFindableTPCClusters_AC", "hFindableTPCClusters_AC", kTH1F, {{200, 0, 200}}); + histos.add("hFindableTPCRows_AC", "hFindableTPCRows_AC", kTH1F, {{200, 0, 200}}); + histos.add("hClustersVsRows_AC", "hClustersVsRows_AC", kTH1F, {{200, 0, 2}}); + histos.add("hTPCChi2_AC", "hTPCChi2_AC", kTH1F, {{200, 0, 100}}); + histos.add("hITSChi2_AC", "hITSChi2_AC", kTH1F, {{200, 0, 100}}); + histos.add("QA_nSigma_pion_TPC_AC", "QA_nSigma_pion_TPC_AC", {HistType::kTH2F, {ptAxis, pidAxis}}); + histos.add("QA_nSigma_pion_TOF_AC", "QA_nSigma_pion_TOF_AC", {HistType::kTH2F, {ptAxis, pidAxis}}); + histos.add("QA_pion_TPC_TOF_AC", "QA_pion_TPC_TOF_AC", {HistType::kTH2F, {pidAxis, pidAxis}}); + histos.add("QA_nSigma_kaon_TPC_AC", "QA_nSigma_kaon_TPC_AC", {HistType::kTH2F, {ptAxis, pidAxis}}); + histos.add("QA_nSigma_kaon_TOF_AC", "QA_nSigma_kaon_TOF_AC", {HistType::kTH2F, {ptAxis, pidAxis}}); + histos.add("QA_kaon_TPC_TOF_AC", "QA_kaon_TPC_TOF_AC", {HistType::kTH2F, {pidAxis, pidAxis}}); + histos.add("QA_track_pT_AC", "QA_track_pT_AC", kTH1F, {{13, 0.0, 13.0}}); + } + + //////////////////////////////////// + histos.add("nEvents", "nEvents", kTH1F, {{7, 0.0, 7.0}}); + histos.add("hUSS_KPi", "hUSS_KPi", kTHnSparseF, {cfgCentAxis, ptAxis, minvAxis}); + histos.add("hUSS_PiK", "hUSS_PiK", kTHnSparseF, {cfgCentAxis, ptAxis, minvAxis}); + histos.add("hLSS_KPi", "hLSS_KPi", kTHnSparseF, {cfgCentAxis, ptAxis, minvAxis}); + histos.add("hLSS_PiK", "hLSS_PiK", kTHnSparseF, {cfgCentAxis, ptAxis, minvAxis}); + + if (cfgMixedHistos) { + histos.add("hUSS_KPi_Mix", "hUSS_KPi_Mix", kTHnSparseF, {cfgCentAxis, ptAxis, minvAxis}); + histos.add("hUSS_PiK_Mix", "hUSS_PiK_Mix", kTHnSparseF, {cfgCentAxis, ptAxis, minvAxis}); + } + if (cfgMCHistos) { + histos.add("nEvents_Gen", "nEvents_Gen", kTH1F, {{4, 0.0, 4.0}}); + histos.add("hUSS_TrueRec", "hUSS_TrueRec", kTHnSparseF, {cfgCentAxis, ptAxis, minvAxis}); + histos.add("hGen_pT_Raw", "Gen_pT_Raw (GeV/c)", kTH1F, {{800, 0., 40.}}); + histos.add("hGen_pT_GoodEv", "hGen_pT_GoodEv", kTHnSparseF, {cfgCentAxis, ptAxis}); + } + + if (cfgEventCutQA) { + std::shared_ptr hCutFlow = histos.get(HIST("hEvent_Cut")); + std::vector eventCutLabels = { + "All Events", + "sel8", + Form("|Vz| < %.1f", cfgEventVtxCut.value), + "kIsGoodZvtxFT0vsPV", + "kNoSameBunchPileup", + "kNoTimeFrameBorder", + "kNoITSROFrameBorder", + "kNoCollInTimeRangeStandard", + "kIsGoodITSLayersAll", + Form("Occupancy < %.0f", cfgOccupancyMax.value), + "All passed events"}; + + for (size_t i = 0; i < eventCutLabels.size(); ++i) { + hCutFlow->GetXaxis()->SetBinLabel(i + 1, eventCutLabels[i].c_str()); + } + } + } // end of init + + //====================== + //|| For LF Analysis + //====================== + using EventCandidates = soa::Join; //, aod::CentFT0Ms, aod::CentFT0As + using EventCandidatesTrue = aod::McCollisions; + using TrackCandidates = soa::Join; + using TrackCandidatesMC = soa::Join; + + // For Mixed Event + using BinningType = ColumnBinningPolicy; + + Partition kaon = !cfgTrackTPCPID || (nabs(aod::pidtpc::tpcNSigmaKa) <= cfgTrackTPCPIDnSig); + Partition pion = !cfgTrackTPCPID || (nabs(aod::pidtpc::tpcNSigmaPi) <= cfgTrackTPCPIDnSig); + Partition kaonMC = !cfgTrackTPCPID || (nabs(aod::pidtpc::tpcNSigmaKa) <= cfgTrackTPCPIDnSig); + Partition pionMC = !cfgTrackTPCPID || (nabs(aod::pidtpc::tpcNSigmaPi) <= cfgTrackTPCPIDnSig); + + double massKa = o2::constants::physics::MassKPlus; + double massPi = o2::constants::physics::MassPiMinus; + + //================================== + //|| + //|| Helper Templates + //|| + //================================== + template + void fillQA(const bool pass, const objType& obj, const int objecttype = 0) + { + if (objecttype == 1) { + if constexpr (requires { obj.posZ(); }) { + if (!pass) { + histos.fill(HIST("hPosZ_BC"), obj.posZ()); + histos.fill(HIST("hcentFT0C_BC"), obj.centFT0C()); + } else { + histos.fill(HIST("hPosZ_AC"), obj.posZ()); + histos.fill(HIST("hcentFT0C_AC"), obj.centFT0C()); + } + } + } // eventSelection histogram + + if constexpr (requires { obj.tpcCrossedRowsOverFindableCls(); }) { + if (objecttype == 3) { + if (!pass) { + histos.fill(HIST("hDCArToPv_BC"), obj.dcaXY()); + histos.fill(HIST("hDCAzToPv_BC"), obj.dcaZ()); + histos.fill(HIST("hIsPrim_BC"), obj.isPrimaryTrack()); + histos.fill(HIST("hIsGood_BC"), obj.isGlobalTrackWoDCA()); + histos.fill(HIST("hIsPrimCont_BC"), obj.isPVContributor()); + histos.fill(HIST("hFindableTPCClusters_BC"), obj.tpcNClsFindable()); + histos.fill(HIST("hFindableTPCRows_BC"), obj.tpcNClsCrossedRows()); + histos.fill(HIST("hClustersVsRows_BC"), obj.tpcCrossedRowsOverFindableCls()); + histos.fill(HIST("hTPCChi2_BC"), obj.tpcChi2NCl()); + histos.fill(HIST("hITSChi2_BC"), obj.itsChi2NCl()); + histos.fill(HIST("QA_track_pT_BC"), obj.pt()); + } else { + histos.fill(HIST("hDCArToPv_AC"), obj.dcaXY()); + histos.fill(HIST("hDCAzToPv_AC"), obj.dcaZ()); + histos.fill(HIST("hIsPrim_AC"), obj.isPrimaryTrack()); + histos.fill(HIST("hIsGood_AC"), obj.isGlobalTrackWoDCA()); + histos.fill(HIST("hIsPrimCont_AC"), obj.isPVContributor()); + histos.fill(HIST("hFindableTPCClusters_AC"), obj.tpcNClsFindable()); + histos.fill(HIST("hFindableTPCRows_AC"), obj.tpcNClsCrossedRows()); + histos.fill(HIST("hClustersVsRows_AC"), obj.tpcCrossedRowsOverFindableCls()); + histos.fill(HIST("hTPCChi2_AC"), obj.tpcChi2NCl()); + histos.fill(HIST("hITSChi2_AC"), obj.itsChi2NCl()); + histos.fill(HIST("QA_track_pT_AC"), obj.pt()); + } + } + } // trackSelection + if (objecttype == 4) { + if constexpr (requires { obj.pt(); }) { + if (!pass) { + histos.fill(HIST("QA_nSigma_kaon_TPC_BC"), obj.pt(), obj.tpcNSigmaKa()); + histos.fill(HIST("QA_nSigma_kaon_TOF_BC"), obj.pt(), obj.tofNSigmaKa()); + histos.fill(HIST("QA_kaon_TPC_TOF_BC"), obj.tpcNSigmaKa(), obj.tofNSigmaKa()); + } else { + histos.fill(HIST("QA_nSigma_kaon_TPC_AC"), obj.pt(), obj.tpcNSigmaKa()); + histos.fill(HIST("QA_nSigma_kaon_TOF_AC"), obj.pt(), obj.tofNSigmaKa()); + histos.fill(HIST("QA_kaon_TPC_TOF_AC"), obj.tpcNSigmaKa(), obj.tofNSigmaKa()); + } + } + } // kaon pid Selection + if (objecttype == 5) { + if constexpr (requires { obj.pt(); }) { + if (!pass) { + histos.fill(HIST("QA_nSigma_pion_TPC_BC"), obj.pt(), obj.tpcNSigmaPi()); + histos.fill(HIST("QA_nSigma_pion_TOF_BC"), obj.pt(), obj.tofNSigmaPi()); + histos.fill(HIST("QA_pion_TPC_TOF_BC"), obj.tpcNSigmaPi(), obj.tofNSigmaPi()); + } else { + histos.fill(HIST("QA_nSigma_pion_TPC_AC"), obj.pt(), obj.tpcNSigmaPi()); + histos.fill(HIST("QA_nSigma_pion_TOF_AC"), obj.pt(), obj.tofNSigmaPi()); + histos.fill(HIST("QA_pion_TPC_TOF_AC"), obj.tpcNSigmaPi(), obj.tofNSigmaPi()); + } + } + } // pion pid Selection + } // fill QA + + enum class objectType { MB, + MBRecParticle }; + + template + void fillMinv(objectType type, const TrackType& trk1, const TrackType& trk2, const ROOT::Math::PxPyPzMVector& lReso, double centrality, bool IsMix, bool flip) + { + double conjugate = trk1.sign() * trk2.sign(); + switch (type) { + case objectType::MB: + if (IsMix && cfgMixedHistos) { + if (conjugate < 0) { + if (!flip) + histos.fill(HIST("hUSS_KPi_Mix"), centrality, lReso.Pt(), lReso.M()); + else + histos.fill(HIST("hUSS_PiK_Mix"), centrality, lReso.Pt(), lReso.M()); + } + } else { + if (conjugate < 0) { + if (!flip) + histos.fill(HIST("hUSS_KPi"), centrality, lReso.Pt(), lReso.M()); + else + histos.fill(HIST("hUSS_PiK"), centrality, lReso.Pt(), lReso.M()); + } else if (conjugate > 0) { + if (!flip) + histos.fill(HIST("hLSS_KPi"), centrality, lReso.Pt(), lReso.M()); + else + histos.fill(HIST("hLSS_PiK"), centrality, lReso.Pt(), lReso.M()); + } + } + break; + + case objectType::MBRecParticle: + if (cfgMCHistos) { + if (conjugate < 0) { + histos.fill(HIST("hUSS_TrueRec"), centrality, lReso.Pt(), lReso.M()); + } + } + break; + } // switch + } // fillMinv + //====================================================================== + + template + std::pair eventSelection(const EventType event, const bool QA) + { + if (cfgEventCutQA && QA) { + fillQA(false, event, 1); + histos.fill(HIST("hEvent_Cut"), 0); + } + + if (!event.sel8()) + return {false, 1}; + if (cfgEventCutQA && QA) { + histos.fill(HIST("hEvent_Cut"), 1); + } + if (std::abs(event.posZ()) > cfgEventVtxCut) + return {false, 2}; + if (cfgEventCutQA && QA) { + histos.fill(HIST("hEvent_Cut"), 2); + } + if (!event.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) + return {false, 3}; + if (cfgEventCutQA && QA) { + histos.fill(HIST("hEvent_Cut"), 3); + } + if (!event.selection_bit(aod::evsel::kNoSameBunchPileup)) + return {false, 4}; + if (cfgEventCutQA && QA) { + histos.fill(HIST("hEvent_Cut"), 4); + } + if (!event.selection_bit(aod::evsel::kNoTimeFrameBorder)) + return {false, 5}; + if (cfgEventCutQA && QA) { + histos.fill(HIST("hEvent_Cut"), 5); + } + if (!event.selection_bit(aod::evsel::kNoITSROFrameBorder)) + return {false, 6}; + if (cfgEventCutQA && QA) { + histos.fill(HIST("hEvent_Cut"), 6); + } + if (!event.selection_bit(aod::evsel::kNoCollInTimeRangeStandard)) + return {false, 7}; + if (cfgEventCutQA && QA) { + histos.fill(HIST("hEvent_Cut"), 7); + } + if (!event.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) + return {false, 8}; + if (cfgEventCutQA && QA) { + histos.fill(HIST("hEvent_Cut"), 8); + } + if (cfgOccupancySel && (event.trackOccupancyInTimeRange() > cfgOccupancyMax || event.trackOccupancyInTimeRange() < cfgOccupancyMin)) + return {false, 9}; + if (cfgEventCutQA && QA) { + histos.fill(HIST("hEvent_Cut"), 9); + } + + if (cfgEventCutQA && QA) { + fillQA(true, event, 1); + histos.fill(HIST("hEvent_Cut"), 10); + } + return {true, 11}; + }; + + template + bool trackSelection(const TracksType track, const bool QA) + { + if (cfgTrackCutQA && QA) { + fillQA(false, track, 3); + } + + if (cfgTrackGlobalSel && !track.isGlobalTrack()) + return false; + if (track.pt() < cfgTrackMinPt) + return false; + if (std::abs(track.eta()) > cfgTrackMaxEta) + return false; + if (std::abs(track.dcaXY()) > cfgTrackMaxDCArToPVcut) + return false; + if (std::abs(track.dcaZ()) > cfgTrackMaxDCAzToPVcut) + return false; + if (cfgTrackPrimaryTrack && !track.isPrimaryTrack()) + return false; + if (cfgTrackGlobalWoDCATrack && !track.isGlobalTrackWoDCA()) + return false; + if (cfgTrackFindableTPCClusters > 0 && track.tpcNClsFindable() < cfgTrackFindableTPCClusters) + return false; + if (track.tpcNClsCrossedRows() < cfgTrackTPCCrossedRows) + return false; + if (cfgTrackRowsOverFindable > 0 && track.tpcCrossedRowsOverFindableCls() > cfgTrackRowsOverFindable) + return false; + if (track.tpcChi2NCl() > cfgTrackTPCChi2) + return false; + if (track.itsChi2NCl() > cfgTrackITSChi2) + return false; + if (cfgTrackConnectedToPV && !track.isPVContributor()) + return false; + + if (cfgTrackCutQA && QA) { + fillQA(true, track, 3); + } + return true; + }; + + template + bool trackPIDKaon(const TrackPID& candidate, const bool QA) + { + double tpcpid = 0; + double tofpid = 0; + bool tpcPIDPassed{false}, tofPIDPassed{false}; + + if (cfgTrackCutQA && QA) { + fillQA(false, candidate, 4); + } + + // TPC + if (cfgTrackSquarePIDCut) { + if (std::abs(candidate.tpcNSigmaKa()) < cfgTrackTPCPIDnSig) + tpcPIDPassed = true; + if (candidate.hasTOF()) { + if (std::abs(candidate.tofNSigmaKa()) < cfgTrackTOFPIDnSig) { + tofPIDPassed = true; + } + } else { + if (!cfgTrackTOFHard) { + tofPIDPassed = true; + } else { + tofPIDPassed = false; + } + } + } // end of square cut + if (cfgTrackCirclePIDCut) { + if (std::abs(candidate.tpcNSigmaKa()) < cfgTrackTPCPIDnSig) + tpcpid = std::abs(candidate.tpcNSigmaKa()); + tofpid = 0; + + if (candidate.hasTOF()) { + tofpid = std::abs(candidate.tofNSigmaKa()); + } else { + if (cfgTrackTOFHard) { + tofpid = 999; + } + } + if (tpcpid * tpcpid + tofpid * tofpid < cfgTrackCircleValue) { + tpcPIDPassed = true; + tofPIDPassed = true; + } + } // circular cut + + // TPC & TOF + if (tpcPIDPassed && tofPIDPassed) { + if (cfgTrackCutQA && QA) { + fillQA(true, candidate, 4); + } + return true; + } + return false; + } + + template + bool trackPIDPion(const TrackPID& candidate, const bool QA) + { + double tpcpid = 0; + double tofpid = 0; + bool tpcPIDPassed{false}, tofPIDPassed{false}; + + if (cfgTrackCutQA && QA) { + fillQA(false, candidate, 5); + } + + // TPC + if (cfgTrackSquarePIDCut) { + if (std::abs(candidate.tpcNSigmaPi()) < cfgTrackTPCPIDnSig) + tpcPIDPassed = true; + if (candidate.hasTOF()) { + if (std::abs(candidate.tofNSigmaPi()) < cfgTrackTOFPIDnSig) { + tofPIDPassed = true; + } + } else { + if (!cfgTrackTOFHard) { + tofPIDPassed = true; + } else { + tofPIDPassed = false; + } + } + } // end of square cut + if (cfgTrackCirclePIDCut) { + if (std::abs(candidate.tpcNSigmaPi()) < cfgTrackTPCPIDnSig) + tpcpid = std::abs(candidate.tpcNSigmaPi()); + tofpid = 0; + + if (candidate.hasTOF()) { + tofpid = std::abs(candidate.tofNSigmaPi()); + } else { + if (cfgTrackTOFHard) { + tofpid = 999; + } + } + if (tpcpid * tpcpid + tofpid * tofpid < cfgTrackCircleValue) { + tpcPIDPassed = true; + tofPIDPassed = true; + } + } // circular cut + + // TPC & TOF + if (tpcPIDPassed && tofPIDPassed) { + if (cfgTrackCutQA && QA) { + fillQA(true, candidate, 5); + } + return true; + } + return false; + } + + template + ROOT::Math::PxPyPzMVector minvReconstruction(const TracksType& trk1, const TracksType& trk2, const bool QA, const bool flip) + { + if (!trackSelection(trk1, false) || !trackSelection(trk2, false)) + return {}; + + if (!trackPIDKaon(trk1, QA) || !trackPIDPion(trk2, QA)) + return {}; + + if (trk1.globalIndex() >= trk2.globalIndex()) + return {}; + + ROOT::Math::PxPyPzMVector lDecayDaughter1, lDecayDaughter2, lResonance; + if (!flip) { + lDecayDaughter1 = ROOT::Math::PxPyPzMVector(trk1.px(), trk1.py(), trk1.pz(), massKa); + lDecayDaughter2 = ROOT::Math::PxPyPzMVector(trk2.px(), trk2.py(), trk2.pz(), massPi); + } else { + lDecayDaughter1 = ROOT::Math::PxPyPzMVector(trk1.px(), trk1.py(), trk1.pz(), massPi); + lDecayDaughter2 = ROOT::Math::PxPyPzMVector(trk2.px(), trk2.py(), trk2.pz(), massKa); + } + lResonance = lDecayDaughter1 + lDecayDaughter2; + + if (std::abs(lResonance.Eta()) > cfgTrackMaxEta) + return {}; + return {lResonance}; + } + + template + ROOT::Math::PxPyPzMVector TrueReconstruction(const TracksType& trk1, const TracksType& trk2) + { + double conjugate = trk1.sign() * trk2.sign(); + if (conjugate > 0) + return {}; + + auto particle1 = trk1.mcParticle(); + auto particle2 = trk2.mcParticle(); + + if (!particle1.has_mothers() || !particle2.has_mothers()) { + return {}; + } + + std::vector mothers1{}; + std::vector mothers1PDG{}; + for (auto& particle1_mom : particle1.template mothers_as()) { + mothers1.push_back(particle1_mom.globalIndex()); + mothers1PDG.push_back(particle1_mom.pdgCode()); + } + + std::vector mothers2{}; + std::vector mothers2PDG{}; + for (auto& particle2_mom : particle2.template mothers_as()) { + mothers2.push_back(particle2_mom.globalIndex()); + mothers2PDG.push_back(particle2_mom.pdgCode()); + } + + if (mothers1PDG[0] != 313) + return {}; // mother not K*0 + if (mothers2PDG[0] != 313) + return {}; // mothers not K*0 + + if (mothers1[0] != mothers2[0]) + return {}; // Kaon and pion not from the same K*0 + + if (std::fabs(particle1.pdgCode()) != 211 && std::fabs(particle1.pdgCode()) != 321) + return {}; + if (std::fabs(particle2.pdgCode()) != 211 && std::fabs(particle2.pdgCode()) != 321) + return {}; + + double track1_mass, track2_mass; + if (std::fabs(particle1.pdgCode()) == 211) { + track1_mass = massPi; + } else { + track1_mass = massKa; + } + + if (std::fabs(particle2.pdgCode()) == 211) { + track2_mass = massPi; + } else { + track2_mass = massKa; + } + + if (track1_mass == track2_mass) { + return {}; + } + + ROOT::Math::PxPyPzMVector lTrueDaughter1, lTrueDaughter2, lTrueReso; + lTrueDaughter1 = ROOT::Math::PxPyPzMVector(trk1.px(), trk1.py(), trk1.pz(), track1_mass); + lTrueDaughter2 = ROOT::Math::PxPyPzMVector(trk2.px(), trk2.py(), trk2.pz(), track2_mass); + lTrueReso = lTrueDaughter1 + lTrueDaughter2; + + if (lTrueReso.M() < 0) + return {}; + + return {lTrueReso}; + } + + template + void TrackSlicing(const CollisionType& collision1, const TracksType&, const CollisionType& collision2, const TracksType&, const bool IsMix, const bool QA) + { + auto tracks1 = kaon->sliceByCached(aod::track::collisionId, collision1.globalIndex(), cache); + auto tracks2 = pion->sliceByCached(aod::track::collisionId, collision2.globalIndex(), cache); + auto centrality = collision1.centFT0C(); + + for (const auto& [trk1, trk2] : combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { + for (bool flip : {false, true}) { + auto lReso = minvReconstruction(trk1, trk2, QA, flip); + if (lReso.M() < 0) + continue; + + fillMinv(objectType::MB, trk1, trk2, lReso, centrality, IsMix, flip); + } // flip + } // for + } // TrackSlicing + + template + void TrackSlicingMC(const CollisionType& collision1, const TracksType&, const CollisionType& collision2, const TracksType&, const bool IsMix, const bool QA) + { + auto tracks1 = kaonMC->sliceByCached(aod::track::collisionId, collision1.globalIndex(), cache); + auto tracks2 = pionMC->sliceByCached(aod::track::collisionId, collision2.globalIndex(), cache); + auto centrality = collision1.centFT0C(); + + for (const auto& [trk1, trk2] : combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { + if (!trk1.has_mcParticle() || !trk2.has_mcParticle()) + continue; + + for (bool flip : {false, true}) { + auto lReso = minvReconstruction(trk1, trk2, QA, flip); + if (lReso.M() < 0) + continue; + + fillMinv(objectType::MB, trk1, trk2, lReso, centrality, IsMix, flip); + } // flip + + //============================ + //| True Reconstruction + //============================ + auto lTrueReso = TrueReconstruction(trk1, trk2); + fillMinv(objectType::MBRecParticle, trk1, trk2, lTrueReso, centrality, IsMix, false); + } // tracks + } // TrackSlicingMC + + //======================================================= + //| + //| DATA STUFF (SE) + //| + //======================================================= + int nEvents = 0; + void processDataSameEvent(EventCandidates::iterator const& collision, TrackCandidates const& tracks) + { + if (cDebugLevel > 0) { + nEvents++; + if ((nEvents + 1) % 10000 == 0) { + std::cout << "Processed Data Events: " << nEvents << std::endl; + } + } + + auto [goodEv, code] = eventSelection(collision, true); + histos.fill(HIST("nEvents"), 0.5); + + if (!goodEv) + return; + + bool INELgt0 = false; + for (const auto& track : tracks) { + if (!trackSelection(track, true)) + continue; + if (std::fabs(track.eta()) < cfgTrackMaxEta) { + INELgt0 = true; + } + } + if (!INELgt0) + return; + histos.fill(HIST("nEvents"), 1.5); + + TrackSlicing(collision, tracks, collision, tracks, false, true); + + } // processSameEvents + PROCESS_SWITCH(kstar0analysis, processDataSameEvent, "process Data Same Event", false); + + //======================================================= + //| + //| DATA STUFF (ME) + //| + //======================================================= + int nEventsMix = 0; + void processDataMixedEvent(EventCandidates const& collisions, TrackCandidates const& tracks) + { + auto tracksTuple = std::make_tuple(tracks); + BinningType colBinning{{cfgBinsMixVtx, cfgBinsMixMult}, true}; // true is for 'ignore overflows' (true by default) + SameKindPair pairs{colBinning, cfgMixNMixedEvents, -1, collisions, tracksTuple, &cache}; + for (const auto& [collision1, tracks1, collision2, tracks2] : pairs) { + if (cDebugLevel > 0) { + nEventsMix++; + if ((nEventsMix + 1) % 10000 == 0) { + std::cout << "Processed DATA Mixed Events : " << nEventsMix << std::endl; + } + } + auto [goodEv1, code1] = eventSelection(collision1, false); + auto [goodEv2, code2] = eventSelection(collision2, false); + bool VtxMixFlag = false; + bool CentMixFlag = false; + // bool OccupanacyMixFlag = false; + if (std::fabs(collision1.posZ() - collision2.posZ()) <= cfgVtxMixCut) // set default to maybe 10 + VtxMixFlag = true; + if (std::fabs(collision1.centFT0C() - collision2.centFT0C()) <= cfgVtxMixCut) // set default to maybe 10 + CentMixFlag = true; + + if (!goodEv1 || !goodEv2) + continue; + if (!CentMixFlag) + continue; + if (!VtxMixFlag) + continue; + + TrackSlicing(collision1, tracks1, collision2, tracks2, true, false); + } + } + PROCESS_SWITCH(kstar0analysis, processDataMixedEvent, "process DATA Mixed Event", false); + + //======================================================= + //| + //| MC STUFF (SE) + //| + //========================================================= + int nEventsMC = 0; + void processSameEventMC(EventCandidates::iterator const& collision, TrackCandidatesMC const& tracks, aod::McParticles const&) + { + if (cDebugLevel > 0) { + nEventsMC++; + if ((nEventsMC + 1) % 10000 == 0) { + double histmem = histos.getSize(); + std::cout << histmem << std::endl; + std::cout << "process_SameEvent_MC: " << nEventsMC << std::endl; + } + } + auto [goodEv, code] = eventSelection(collision, true); + + histos.fill(HIST("nEvents"), 0.5); + + if (!goodEv) + return; + + bool INELgt0 = false; + for (const auto& track : tracks) { + if (!trackSelection(track, true)) + continue; + if (std::fabs(track.eta()) < cfgTrackMaxEta) { + INELgt0 = true; + } + } + if (!INELgt0) + return; + + histos.fill(HIST("nEvents"), 1.5); + + TrackSlicingMC(collision, tracks, collision, tracks, false, true); + } // processSameEvents_MC + PROCESS_SWITCH(kstar0analysis, processSameEventMC, "process Same Event MC", false); + + //======================================================= + //| + //| MC STUFF (ME) + //| + //======================================================= + int nEventsMCMix = 0; + void processMixedEventMC(EventCandidates const& collisions, TrackCandidatesMC const& tracks, aod::McParticles const&) + { + auto tracksTuple = std::make_tuple(tracks); + BinningType colBinning{{cfgBinsMixVtx, cfgBinsMixMult}, true}; // true is for 'ignore overflows' (true by default) + SameKindPair pairs{colBinning, cfgMixNMixedEvents, -1, collisions, tracksTuple, &cache}; + for (const auto& [collision1, tracks1, collision2, tracks2] : pairs) { + if (cDebugLevel > 0) { + nEventsMCMix++; + if ((nEventsMCMix + 1) % 10000 == 0) { + std::cout << "Processed Mixed Events: " << nEventsMCMix << std::endl; + } + } + auto [goodEv1, code1] = eventSelection(collision1, false); + auto [goodEv2, code2] = eventSelection(collision2, false); + if (!goodEv1 || !goodEv2) { + continue; + } + + TrackSlicingMC(collision1, tracks1, collision2, tracks2, true, false); + } // mixing + } // processMixedEvent_MC + PROCESS_SWITCH(kstar0analysis, processMixedEventMC, "process Mixed Event MC", false); + + //====================================== + //| + //| GENERATED STUFF + //| + //====================================== + int nEventsGen = 0; + void processGen(EventCandidatesTrue::iterator const& collision, soa::SmallGroups> const& recocolls, aod::McParticles const& mcParticles) + { + if (cDebugLevel > 0) { + ++nEventsGen; + if (nEventsGen % 10000 == 0) { + std::cout << "Processed MC (GEN) Events: " << nEventsGen << std::endl; + } + } + //======================= + //|| Event & Signal loss + //======================= + if (cfgMCHistos) { + histos.fill(HIST("nEvents_Gen"), 0.5); + } + + for (auto& particle : mcParticles) { + if (particle.pdgCode() != 313) + continue; + if (std::fabs(particle.eta()) > cfgTrackMaxEta) + continue; + if (fabs(collision.posZ()) > cfgEventVtxCut) + break; + + if (cfgMCHistos) { + histos.fill(HIST("hGen_pT_Raw"), particle.pt()); + } + } // Unreconstructed collisions(=Raw coll) for correction + + if (recocolls.size() <= 0) { // not reconstructed + if (cfgForceGenReco) { + return; + } + } + double centrality = -1; + for (auto& recocoll : recocolls) { + centrality = recocoll.centFT0C(); + auto [goodEv, code] = eventSelection(recocoll, true); + + if (cfgMCHistos) { + histos.fill(HIST("nEvents_Gen"), 1.5); + } + if (!goodEv) + continue; + } // recocolls (=reconstructed collisions) + + //================= + //|| Efficiency + //================= + for (auto& particle : mcParticles) { + if (particle.pdgCode() != 313) + continue; // Not K*0 + if (std::fabs(particle.eta()) > cfgTrackMaxEta) + continue; + + if (cfgMCHistos) { + histos.fill(HIST("nEvents_Gen"), 2.5); + histos.fill(HIST("hGen_pT_GoodEv"), centrality, particle.pt()); + } // cfgMCHistos + } // loop over particles + } // processMCTrue + PROCESS_SWITCH(kstar0analysis, processGen, "process Generated Particles", false); + + void processEventsDummy(EventCandidates::iterator const&, TrackCandidates const&) + { + return; + } + PROCESS_SWITCH(kstar0analysis, processEventsDummy, "dummy", false); +}; // kstar0analysis +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +}; diff --git a/PWGLF/Tasks/Resonances/phiOO.cxx b/PWGLF/Tasks/Resonances/phi1020analysis.cxx similarity index 94% rename from PWGLF/Tasks/Resonances/phiOO.cxx rename to PWGLF/Tasks/Resonances/phi1020analysis.cxx index 9c7e6005264..c56a71e68c4 100644 --- a/PWGLF/Tasks/Resonances/phiOO.cxx +++ b/PWGLF/Tasks/Resonances/phi1020analysis.cxx @@ -9,7 +9,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/// \file phiInJets.cxx +/// \file phi1020analysis.cxx /// \brief Reconstruction of Phi yield through track-track Minv correlations for resonance OO analysis /// /// @@ -61,7 +61,7 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -struct phiOO { +struct phi1020analysis { SliceCache cache; Preslice perCollision = aod::track::collisionId; @@ -77,6 +77,7 @@ struct phiOO { Configurable cfg_Event_Pileup{"cfg_Event_Pileup", true, "Pileup border cut"}; Configurable cfg_Event_OccupancyCut{"cfg_Event_OccupancyCut", true, "Occupancy border cut"}; Configurable cfg_Event_MaxOccupancy{"cfg_Event_MaxOccupancy", 1, "Max TPC Occupancy"}; + Configurable centEstimator{"centEstimator", 0, "Select centrality estimator: 0 - FT0M, 1 - FT0A, 2 - FT0C"}; // Track configurables Configurable cfg_Track_Sel{"cfg_Track_Sel", "globalTracks", "set track selections"}; @@ -136,10 +137,10 @@ struct phiOO { // Event QA if (cfg_Event_CutQA) { histos.add("hPosZ_BC", "PosZ_BC", kTH1F, {{240, -12.0, 12.0}}); - histos.add("hcentFT0C_BC", "centFT0C_BC", kTH1F, {{110, 0.0, 110.0}}); + histos.add("hcentFT0_BC", "centFT0_BC", kTH1F, {{110, 0.0, 110.0}}); histos.add("hOccupancy_BC", "Occupancy_BC", kTH1F, {{100, 0.0, 20000}}); // - histos.add("hcentFT0C_AC", "centFT0C_AC", kTH1F, {{110, 0.0, 110.0}}); + histos.add("hcentFT0_AC", "centFT0_AC", kTH1F, {{110, 0.0, 110.0}}); histos.add("hPosZ_AC", "PosZ_AC", kTH1F, {{240, -12.0, 12.0}}); histos.add("hOccupancy_AC", "Occupancy_AC", kTH1F, {{100, 0.0, 20000}}); } @@ -198,7 +199,7 @@ struct phiOO { Filter collisionFilter = nabs(aod::collision::posZ) <= cfg_Event_VtxCut; Filter collisionFilter_MC = nabs(aod::mccollision::posZ) <= cfg_Event_VtxCut; - Filter centralityFilter = nabs(aod::cent::centFT0C) <= cfg_Event_CentralityMax; + // Filter centralityFilter = nabs(aod::cent::centFT0C) <= cfg_Event_CentralityMax; Filter acceptanceFilter = (nabs(aod::track::eta) < cfg_Track_MaxEta && nabs(aod::track::pt) >= cfg_Track_MinPt); using EventCandidates = soa::Filtered>; using EventCandidates_True = soa::Filtered; @@ -208,7 +209,7 @@ struct phiOO { using TrackCandidates_MC = soa::Filtered>; - using BinningTypeVtxCent = ColumnBinningPolicy; + using BinningTypeVtxCent = ColumnBinningPolicy; Partition PosKaon_MC = (aod::track::signed1Pt > static_cast(0)) && @@ -224,6 +225,29 @@ struct phiOO { (!cfg_Track_TPCPID || (nabs(aod::pidtpc::tpcNSigmaKa) <= cfg_Track_TPCPID_nSig)); double massKa = o2::constants::physics::MassKPlus; + + // Centralicity estimator selection + template + float centEst(Coll collisions) + { + float returnValue = -999.0f; + switch (centEstimator) { + case 0: + returnValue = collisions.centFT0M(); + break; + case 1: + returnValue = collisions.centFT0A(); + break; + case 2: + returnValue = collisions.centFT0C(); + break; + default: + returnValue = collisions.centFT0M(); + break; + } + return returnValue; + } + //***********************************// // First, we declare some helper functions template @@ -234,10 +258,10 @@ struct phiOO { if constexpr (requires { obj.posZ(); }) { if (!pass) { histos.fill(HIST("hPosZ_BC"), obj.posZ()); - histos.fill(HIST("hcentFT0C_BC"), obj.centFT0C()); + histos.fill(HIST("hcentFT0_BC"), centEst(obj)); } else { histos.fill(HIST("hPosZ_AC"), obj.posZ()); - histos.fill(HIST("hcentFT0C_AC"), obj.centFT0C()); + histos.fill(HIST("hcentFT0_AC"), centEst(obj)); } } } @@ -300,7 +324,7 @@ struct phiOO { return {false, 4}; if (cfg_Event_Pileup && (!event.selection_bit(aod::evsel::kNoSameBunchPileup) || !event.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV))) return {false, 5}; - if (cfg_Event_Centrality && (event.centFT0C() > cfg_Event_CentralityMax)) + if (cfg_Event_Centrality && (centEst(event) > cfg_Event_CentralityMax)) return {false, 6}; if (cfg_Event_OccupancyCut && (event.trackOccupancyInTimeRange() > cfg_Event_MaxOccupancy)) return {false, 7}; @@ -375,7 +399,7 @@ struct phiOO { tofPIDPassed = true; } if (!candidate.hasTOF()) { - std::cout << candidate.tofNSigmaKa() << std::endl; + // std::cout << candidate.tofNSigmaKa() << std::endl; } } if (tpcPIDPassed && tofPIDPassed) { @@ -392,7 +416,7 @@ struct phiOO { { auto slicedtracks1 = PosKaon->sliceByCached(aod::track::collisionId, collision1.globalIndex(), cache); auto slicedtracks2 = NegKaon->sliceByCached(aod::track::collisionId, collision2.globalIndex(), cache); - auto centrality = collision1.centFT0C(); + auto centrality = centEst(collision1); for (auto& [track1, track2] : combinations(o2::soa::CombinationsFullIndexPolicy(slicedtracks1, slicedtracks2))) { auto [Minv, PhiPt] = minvReconstruction(track1, track2, QA); if (Minv < 0) @@ -419,7 +443,7 @@ struct phiOO { { auto slicedtracks1 = PosKaon_MC->sliceByCached(aod::track::collisionId, collision1.globalIndex(), cache); auto slicedtracks2 = NegKaon_MC->sliceByCached(aod::track::collisionId, collision2.globalIndex(), cache); - auto centrality = collision1.centFT0C(); + auto centrality = centEst(collision1); for (auto& [track1, track2] : combinations(o2::soa::CombinationsFullIndexPolicy(slicedtracks1, slicedtracks2))) { auto [Minv, PhiPt] = minvReconstruction(track1, track2, QA); if (Minv < 0) @@ -526,7 +550,7 @@ struct phiOO { } // end of process - PROCESS_SWITCH(phiOO, processSameEvent, "Process Same events", true); + PROCESS_SWITCH(phi1020analysis, processSameEvent, "Process Same events", true); //***************// // DATA (MIX) @@ -553,7 +577,7 @@ struct phiOO { TrackSlicing(collision1, tracks1, collision2, tracks2, false, true); } // mixing } // end of process - PROCESS_SWITCH(phiOO, processMixedEvent, "Process Mixed events", false); + PROCESS_SWITCH(phi1020analysis, processMixedEvent, "Process Mixed events", false); //***************// // RECONSTRUCTED MC @@ -576,7 +600,7 @@ struct phiOO { TrackSlicing_MC(collision, tracks, collision, tracks, true, false); } // end of process - PROCESS_SWITCH(phiOO, processSameEvent_MC, "Process Same events (MC)", true); + PROCESS_SWITCH(phi1020analysis, processSameEvent_MC, "Process Same events (MC)", true); //***************// // RECONSTRUCTED MC (MIX) @@ -602,7 +626,7 @@ struct phiOO { TrackSlicing_MC(collision1, tracks1, collision2, tracks2, false, true); } // mixing } // end of process - PROCESS_SWITCH(phiOO, processMixedEvent_MC, "Process Mixed events (MC)", false); + PROCESS_SWITCH(phi1020analysis, processMixedEvent_MC, "Process Mixed events (MC)", false); //***************// // GENERATED MC @@ -629,7 +653,7 @@ struct phiOO { double centrality = -1; for (auto& recocoll : recocolls) { // poorly reconstructed - centrality = recocoll.centFT0C(); + centrality = centEst(recocoll); auto [goodEv, code] = eventSelection(recocoll, false); histos.fill(HIST("hnEvents_MC_True"), code); if (!goodEv) @@ -665,11 +689,11 @@ struct phiOO { } // loop over particles } // end of process - PROCESS_SWITCH(phiOO, processParticles, "Process Particles", false); + PROCESS_SWITCH(phi1020analysis, processParticles, "Process Particles", false); }; // end of main struct WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - return WorkflowSpec{adaptAnalysisTask(cfgc)}; + return WorkflowSpec{adaptAnalysisTask(cfgc)}; }; From a0f219f0e680eb5aa42242dba875449a5f130e08 Mon Sep 17 00:00:00 2001 From: nkaratze Date: Sat, 28 Feb 2026 00:48:44 +0100 Subject: [PATCH 113/347] [PWGLF] Uncommented Event Selection (#15199) --- PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx b/PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx index e3587cec700..79fc64c1883 100644 --- a/PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx +++ b/PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx @@ -981,9 +981,9 @@ struct V0PtInvMassPlots { antilambdaptedgevalues[i] = std::stod(pthistos::antilambdaPtBins[i]); } - // if (!acceptEvent(collision)) { // Event Selection - // return; - // } + if (!acceptEvent(collision)) { // Event Selection + return; + } rPtAnalysis.fill(HIST("hNRecEvents"), 0.5, collision.centFT0M()); // Number of recorded events for (const auto& v0 : V0s) { // Checking that the V0 is a true K0s/Lambdas/Antilambdas and then filling the parameter histograms and the invariant mass plots for different cuts (which are taken from namespace) From 7a8f7ffb02df03ba3ac7f0b9d9eb2a583c8d055e Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Sat, 28 Feb 2026 09:04:23 +0100 Subject: [PATCH 114/347] [PWGLF,PWGMM] Fix position of update of last BC with activity for SL BCs (#15198) --- PWGMM/Lumi/Tasks/lumiStabilityPP.cxx | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/PWGMM/Lumi/Tasks/lumiStabilityPP.cxx b/PWGMM/Lumi/Tasks/lumiStabilityPP.cxx index b1bca3040ed..2962148c4dc 100644 --- a/PWGMM/Lumi/Tasks/lumiStabilityPP.cxx +++ b/PWGMM/Lumi/Tasks/lumiStabilityPP.cxx @@ -337,23 +337,16 @@ struct LumiStabilityPP { isSuperLeadingBcFT0 = false; // not a super-leading BC for FT0 } - if (ctpInputMask.test(12) || ctpInputMask.test(14) || ctpInputMask.test(15) || ctpInputMask.test(16) || ctpInputMask.test(17)) { // 5 FDD triggers - globalBCIdOfLastBCWithActivityFDD = globalBCFDD; - } - if (ctpInputMask.test(0) || ctpInputMask.test(1) || ctpInputMask.test(2) || ctpInputMask.test(3) || ctpInputMask.test(4)) { // 5 FT0 triggers - globalBCIdOfLastBCWithActivityFT0 = globalBC; + if (!bcPatternB[localBCFDD]) { + isSuperLeadingBcFDD = false; // not a super-leading BC for FDD } - if (!bcPatternB[localBC]) { - isSuperLeadingBcFT0 = false; // not a super-leading BC - } - if (!bcPatternB[localBCFDD]) { - isSuperLeadingBcFDD = false; // not a super-leading BC + isSuperLeadingBcFT0 = false; // not a super-leading BC for FT0 } int64_t globalBCStart = (globalBCLastInspectedBC >= 0 && globalBCLastInspectedBC < globalBC) ? globalBCLastInspectedBC + 1 : globalBC; - int64_t maxBcDiff = (rate > 0) ? 10 * static_cast(nBunchesFillingScheme * constants::lhc::LHCRevFreq / rate / 1.e3) : 1500; - if (globalBC - globalBCStart > maxBcDiff) { // we changed fill, we should not count all BCs between the current and the previous one + int64_t maxBcDiff = (rate > 0) ? 15 * static_cast(nBunchesFillingScheme * constants::lhc::LHCRevFreq / rate / 1.e3) : 1500; + if (globalBC - globalBCStart > maxBcDiff) { // we have a big jump in global BCs, we should not count all BCs between the current and the previous one globalBCStart = globalBC; } for (int64_t iGlobalBC{globalBCStart}; iGlobalBC <= globalBC; ++iGlobalBC) { // we count all BCs in between one and another stored in the AO2Ds @@ -363,12 +356,12 @@ struct LumiStabilityPP { } if (bcPatternB[iLocalBC]) { nBCsPerBcId[iLocalBC][BCB]++; - if (iGlobalBC - globalBCIdOfLastBCWithActivityFDD > numEmptyBCsBeforeLeadingBC->get(0u, 2u)) { + if (iGlobalBC - globalBCIdOfLastBCWithActivityFDD >= numEmptyBCsBeforeLeadingBC->get(0u, 2u)) { nBCsPerBcId[iLocalBC][BCSLFDD]++; } else { nBCsPerBcId[iLocalBC][BCNSLFDD]++; } - if (iGlobalBC - globalBCIdOfLastBCWithActivityFT0 > numEmptyBCsBeforeLeadingBC->get(0u, 2u)) { + if (iGlobalBC - globalBCIdOfLastBCWithActivityFT0 >= numEmptyBCsBeforeLeadingBC->get(0u, 2u)) { nBCsPerBcId[iLocalBC][BCSLFT0]++; } else { nBCsPerBcId[iLocalBC][BCNSLFT0]++; @@ -394,6 +387,13 @@ struct LumiStabilityPP { } } + if (ctpInputMask.test(12) || ctpInputMask.test(14) || ctpInputMask.test(15) || ctpInputMask.test(16) || ctpInputMask.test(17)) { // 5 FDD triggers + globalBCIdOfLastBCWithActivityFDD = globalBCFDD; + } + if (ctpInputMask.test(0) || ctpInputMask.test(1) || ctpInputMask.test(2) || ctpInputMask.test(3) || ctpInputMask.test(4)) { // 5 FT0 triggers + globalBCIdOfLastBCWithActivityFT0 = globalBC; + } + int64_t thisTFid = (globalBC - bcSOR) / nBCsPerTF; if (thisTFid != currentTFid) { From ccadab8eabdb1c97f6a961b893022fba39e44cff Mon Sep 17 00:00:00 2001 From: Paola Vargas Torres <88360333+PaolaVT@users.noreply.github.com> Date: Sat, 28 Feb 2026 04:40:10 -0600 Subject: [PATCH 115/347] [PWGLF] Track cuts were modified (#15200) Co-authored-by: Paola Vargas Torres --- PWGLF/Tasks/Nuspex/dedxPidAnalysis.cxx | 180 +++++++++++++++++-------- 1 file changed, 122 insertions(+), 58 deletions(-) diff --git a/PWGLF/Tasks/Nuspex/dedxPidAnalysis.cxx b/PWGLF/Tasks/Nuspex/dedxPidAnalysis.cxx index 5ff943f2348..a8ff711af76 100644 --- a/PWGLF/Tasks/Nuspex/dedxPidAnalysis.cxx +++ b/PWGLF/Tasks/Nuspex/dedxPidAnalysis.cxx @@ -134,27 +134,37 @@ struct DedxPidAnalysis { // Track secondary lebel enum TrkSecCutLabel { AllSec = 1, - V0Type, V0CosPA, V0DecayRadius, V0Daughters, - TPCRefit, PhiVarCutSec, NClTPCFoundCutSec, NClTPCPIDCutSec, AllK0s, + SingleTrackSelectionK0s, + V0TypeK0s, + DCAtoVtxK0s, + Armenteros, V0RapidityK0s, V0ProperLifetimeK0s, MassCutK0s, AllLambda, + SingleTrackSelectionLambda, + V0TypeLambda, + DCAtoVtxLambda, V0RapidityLambda, V0ProperLifetimeLambda, MassCutLambda, AllAntiLambda, + SingleTrackSelectionAntiLambda, + V0TypeAntiLambda, + DCAtoVtxAntiLambda, V0RapidityAntiLambda, V0ProperLifetimeAntiLambda, MassCutAntiLambda, AllGamma, + SingleTrackSelectionGamma, + V0TypeGamma, V0RapidityGamma, MassCutGamma }; @@ -176,20 +186,26 @@ struct DedxPidAnalysis { Configurable minNCrossedRowsOverFindableClustersTPC{"minNCrossedRowsOverFindableClustersTPC", 0.8f, "Additional cut on the minimum value of the ratio between crossed rows and findable clusters in the TPC"}; Configurable maxDCAz{"maxDCAz", 0.1f, "maxDCAz"}; // v0 cuts - Configurable v0cospaMin{"v0cospaMin", 0.998f, "Minimum V0 CosPA"}; - Configurable minimumV0Radius{"minimumV0Radius", 0.5f, + Configurable v0cospaMin{"v0cospaMin", 0.999f, "Minimum V0 CosPA"}; + Configurable minimumV0Radius{"minimumV0Radius", 1.2f, "Minimum V0 Radius"}; Configurable maximumV0Radius{"maximumV0Radius", 100.0f, "Maximum V0 Radius"}; Configurable dcaV0DaughtersMax{"dcaV0DaughtersMax", 0.5f, "Maximum DCA Daughters"}; + Configurable dcaProtonsFromLambda{"dcaProtonsFromLambda", 0.05f, + "Minimum DCA of protons to vtx for Lambda"}; + Configurable dcaPionsFromLambda{"dcaPionsFromLambda", 0.2f, + "Minimum DCA of pions to vtx for Lambda"}; + Configurable dcaPionsFromK0s{"dcaPionsFromK0s", 0.1f, + "Minimum DCA of pions to vtx for K0s"}; Configurable v0rapidityCut{"v0rapidityCut", 0.5f, "V0 rapidity cut"}; Configurable v0ProperLifetimeCutK0s{"v0ProperLifetimeCutK0s", 20.f, "V0 proper lifetime cut for K0s"}; Configurable v0ProperLifetimeCutLambda{"v0ProperLifetimeCutLambda", 30.f, "V0 proper lifetime cut for Lambda"}; Configurable nsigmaTOFmax{"nsigmaTOFmax", 3.0f, "Maximum nsigma TOF"}; - Configurable invMassCutK0s{"invMassCutK0s", 0.2f, "invariant Mass Cut for K0s"}; - Configurable invMassCutLambda{"invMassCutLambda", 0.1f, "invariant Mass Cut for Lambda"}; - Configurable invMassCutGamma{"invMassCutGamma", 0.1f, "invariant Mass Cut for Gamma"}; + Configurable invMassCutK0s{"invMassCutK0s", 0.015f, "invariant Mass Cut for K0s"}; + Configurable invMassCutLambda{"invMassCutLambda", 0.015f, "invariant Mass Cut for Lambda"}; + Configurable invMassCutGamma{"invMassCutGamma", 0.015f, "invariant Mass Cut for Gamma"}; Configurable calibrationMode{"calibrationMode", false, "calibration mode"}; Configurable phiVarCut{"phiVarCut", true, "phi var cut"}; Configurable nClTPCFoundCut{"nClTPCFoundCut", false, "number of found clusters in TPC cut"}; @@ -200,11 +216,13 @@ struct DedxPidAnalysis { Configurable v0SelectionMode{"v0SelectionMode", 3, "V0 Selection base on TPC: 1, TOF:2 ,Both:3"}; Configurable momentumMode{"momentumMode", 2, "1: TPC inner param, 2: Total momentum p"}; Configurable v0TypeSelection{"v0TypeSelection", 1, "select on a certain V0 type (leave negative if no selection desired)"}; + Configurable v0TypeSelectionGamma{"v0TypeSelectionGamma", 7, "select on a certain V0 type (leave negative if no selection desired)"}; Configurable multiplicityEstimator{"multiplicityEstimator", 9, "Flag to use a multiplicity estimator; No multiplicity: 0, MultFV0A: 1, MultFT0M: 2, MultFDDM: 3 ,MultTracklets: 4,MultTPC: 5,MultNTracksPV: 6 ,MultNTracksPVeta1: 7,CentralityFT0C: 8 ,CentralityFT0M: 9, CentralityFV0A: 10"}; Configurable lowParam1{"lowParam1", 0.119297, "First parameter for low phi cut"}; Configurable lowParam2{"lowParam2", 0.000379693, "Second parameter for low phi cut"}; Configurable highParam1{"highParam1", 0.16685, "First parameter for high phi cut"}; Configurable highParam2{"highParam2", 0.00981942, "Second parameter for high phi cut"}; + Configurable armPodCut{"armPodCut", 5.0f, "pT * (cut) > |alpha|"}; // Histograms names static constexpr std::string_view DedxvsMomentumPos[ParticlesType] = {"dEdx_vs_Momentum_all_Pos", "dEdx_vs_Momentum_Pi_v0_Pos", "dEdx_vs_Momentum_Pr_v0_Pos", "dEdx_vs_Momentum_El_v0_Pos"}; static constexpr std::string_view DedxvsMomentumNeg[ParticlesType] = {"dEdx_vs_Momentum_all_Neg", "dEdx_vs_Momentum_Pi_v0_Neg", "dEdx_vs_Momentum_Pr_v0_Neg", "dEdx_vs_Momentum_El_v0_Neg"}; @@ -648,34 +666,43 @@ struct DedxPidAnalysis { xAll->SetBinLabel(NClTPCPIDCutPri, "NClTPCPIDCutPri"); xAll->SetBinLabel(NClTPCFoundCutPri, "NClTPCFoundCutPri"); - registryDeDx.add("trackselSec", "track selected sec particles", HistType::kTH1F, {{24, 0.5, 24.5, ""}}); + registryDeDx.add("trackselSec", "track selected sec particles", HistType::kTH1F, {{34, 0.5, 34.5, ""}}); auto htrackSec = registryDeDx.get(HIST("trackselSec")); auto* xSec = htrackSec->GetXaxis(); xSec->SetBinLabel(AllSec, "AllSec"); - xSec->SetBinLabel(V0Type, "V0Type"); xSec->SetBinLabel(V0CosPA, "V0CosPA"); xSec->SetBinLabel(V0DecayRadius, "V0DecayRadius"); xSec->SetBinLabel(V0Daughters, "V0Daughters"); - xSec->SetBinLabel(TPCRefit, "TPCRefit"); xSec->SetBinLabel(PhiVarCutSec, "PhiVarCutSec"); xSec->SetBinLabel(NClTPCFoundCutSec, "NClTPCFoundCutSec"); xSec->SetBinLabel(NClTPCPIDCutSec, "NClTPCPIDCutSec"); xSec->SetBinLabel(AllK0s, "AllK0s"); + xSec->SetBinLabel(SingleTrackSelectionK0s, "SingleTrackSelectionK0s"); + xSec->SetBinLabel(V0TypeK0s, "V0TypeK0s"); + xSec->SetBinLabel(DCAtoVtxK0s, "DCAtoVtxK0s"); + xSec->SetBinLabel(Armenteros, "Armenteros"); xSec->SetBinLabel(V0RapidityK0s, "V0RapidityK0s"); xSec->SetBinLabel(V0ProperLifetimeK0s, "V0ProperLifetimeK0s"); xSec->SetBinLabel(MassCutK0s, "MassCutK0s"); xSec->SetBinLabel(AllLambda, "AllLambda"); + xSec->SetBinLabel(SingleTrackSelectionLambda, "SingleTrackSelectionLambda"); + xSec->SetBinLabel(V0TypeLambda, "V0TypeLambda"); + xSec->SetBinLabel(DCAtoVtxLambda, "DCAtoVtxLambda"); xSec->SetBinLabel(V0RapidityLambda, "V0RapidityLambda"); xSec->SetBinLabel(V0ProperLifetimeLambda, "V0ProperLifetimeLambda"); xSec->SetBinLabel(MassCutLambda, "MassCutLambda"); xSec->SetBinLabel(AllAntiLambda, "AllAntiLambda"); + xSec->SetBinLabel(SingleTrackSelectionAntiLambda, "SingleTrackSelectionAntiLambda"); + xSec->SetBinLabel(V0TypeAntiLambda, "V0TypeAntiLambda"); + xSec->SetBinLabel(DCAtoVtxAntiLambda, "DCAtoVtxAntiLambda"); xSec->SetBinLabel(V0RapidityAntiLambda, "V0RapidityAntiLambda"); xSec->SetBinLabel(V0ProperLifetimeAntiLambda, "V0ProperLifetimeAntiLambda"); xSec->SetBinLabel(MassCutAntiLambda, "MassCutAntiLambda"); xSec->SetBinLabel(AllGamma, "AllGamma"); + xSec->SetBinLabel(SingleTrackSelectionGamma, "SingleTrackSelectionGamma"); + xSec->SetBinLabel(V0TypeGamma, "V0TypeGamma"); xSec->SetBinLabel(V0RapidityGamma, "V0RapidityGamma"); xSec->SetBinLabel(MassCutGamma, "MassCutGamma"); - mySelectionPrim = myTrackSelection(); } @@ -684,12 +711,12 @@ struct DedxPidAnalysis { bool passedSingleTrackSelection(const T1& track, const C& /*collision*/) { // Single-Track Selections - if (!track.hasTPC()) - return false; + // if (!track.hasTPC()) + // return false; if (track.tpcNClsCrossedRows() < minNCrossedRowsTPC) return false; - if (track.tpcChi2NCl() > maxChi2TPC) - return false; + // if (track.tpcChi2NCl() > maxChi2TPC) + // return false; if (track.eta() < etaMin || track.eta() > etaMax) return false; @@ -727,12 +754,15 @@ struct DedxPidAnalysis { bool passedK0Selection(const T1& v0, const T2& ntrack, const T2& ptrack, const C& collision) { + + if (fillHist) + registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::AllK0s); // Single-Track Selections if (!passedSingleTrackSelection(ptrack, collision)) return false; if (!passedSingleTrackSelection(ntrack, collision)) return false; - double sigmap = 0.0; + /*double sigmap = 0.0; double sigman = 0.0; if (v0SelectionMode == V0TPC) { @@ -758,23 +788,37 @@ struct DedxPidAnalysis { return false; if (std::abs(sigman) > nsigmaTOFmax) return false; - } + }*/ if (fillHist) - registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::AllK0s); + registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::SingleTrackSelectionK0s); - if (std::abs(v0.yK0Short()) > v0rapidityCut) + if (v0.v0Type() != v0TypeSelection) // V0 type selection + return false; + if (fillHist) + registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::V0TypeK0s); + + if (std::fabs(v0.dcapostopv()) < dcaPionsFromK0s && std::fabs(v0.dcanegtopv()) < dcaPionsFromK0s) // DCA selection + return false; + if (fillHist) + registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::DCAtoVtxK0s); + + if (armPodCut * v0.qtarm() < std::abs(v0.alpha())) // Armenteros-Podolanski cut + return false; + if (fillHist) + registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::Armenteros); + + if (std::abs(v0.yK0Short()) > v0rapidityCut) // Rapidity selection return false; if (fillHist) registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::V0RapidityK0s); float properLifetime = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * MassK0Short; - - if (properLifetime > v0ProperLifetimeCutK0s) + if (properLifetime > v0ProperLifetimeCutK0s) // Proper lifetime return false; if (fillHist) registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::V0ProperLifetimeK0s); - if (std::abs(v0.mK0Short() - MassK0Short) > invMassCutK0s) + if (std::abs(v0.mK0Short() - MassK0Short) > invMassCutK0s) // Invarian mass return false; if (fillHist) registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::MassCutK0s); @@ -787,13 +831,16 @@ struct DedxPidAnalysis { bool passedLambdaSelection(const T1& v0, const T2& ntrack, const T2& ptrack, const C& collision) { + + if (fillHist) + registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::AllLambda); // Single-Track Selections if (!passedSingleTrackSelection(ptrack, collision)) return false; if (!passedSingleTrackSelection(ntrack, collision)) return false; - double sigmap = 0.0; + /*double sigmap = 0.0; double sigman = 0.0; if (v0SelectionMode == V0TPC) { @@ -819,26 +866,34 @@ struct DedxPidAnalysis { return false; if (std::abs(sigman) > nsigmaTOFmax) return false; - } + }*/ + if (fillHist) - registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::AllLambda); + registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::SingleTrackSelectionLambda); - if (std::abs(v0.yLambda()) > v0rapidityCut) + if (v0.v0Type() != v0TypeSelection) // V0 type selection return false; if (fillHist) - registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::V0RapidityLambda); + registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::V0TypeLambda); - float properLifetime = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * MassLambda; + if (std::fabs(v0.dcapostopv()) < dcaProtonsFromLambda && std::fabs(v0.dcanegtopv()) < dcaPionsFromLambda) // DCA selection + return false; + if (fillHist) + registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::DCAtoVtxLambda); - if (properLifetime > v0ProperLifetimeCutLambda) + if (std::abs(v0.yLambda()) > v0rapidityCut) // Rapidity selection return false; + if (fillHist) + registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::V0RapidityLambda); + float properLifetime = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * MassLambda; + if (properLifetime > v0ProperLifetimeCutLambda) // Proper lifetime + return false; if (fillHist) registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::V0ProperLifetimeLambda); - if (std::abs(v0.mLambda() - MassLambda) > invMassCutLambda) { + if (std::abs(v0.mLambda() - MassLambda) > invMassCutLambda) // Invarian mass return false; - } if (fillHist) registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::MassCutLambda); @@ -850,13 +905,15 @@ struct DedxPidAnalysis { bool passedAntiLambdaSelection(const T1& v0, const T2& ntrack, const T2& ptrack, const C& collision) { + if (fillHist) + registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::AllAntiLambda); // Single-Track Selections if (!passedSingleTrackSelection(ptrack, collision)) return false; if (!passedSingleTrackSelection(ntrack, collision)) return false; - double sigmap = 0.0; + /*double sigmap = 0.0; double sigman = 0.0; if (v0SelectionMode == V0TPC) { @@ -881,27 +938,35 @@ struct DedxPidAnalysis { return false; if (std::abs(sigman) > nsigmaTOFmax) return false; - } + }*/ + if (fillHist) - registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::AllAntiLambda); + registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::SingleTrackSelectionAntiLambda); - if (std::abs(v0.yLambda()) > v0rapidityCut) + // Select V0 type + if (v0.v0Type() != v0TypeSelection) // V0 type selection return false; + if (fillHist) + registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::V0TypeAntiLambda); + if (std::fabs(v0.dcapostopv()) < dcaPionsFromLambda && std::fabs(v0.dcanegtopv()) < dcaProtonsFromLambda) // DCA selection + return false; + if (fillHist) + registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::DCAtoVtxAntiLambda); + + if (std::abs(v0.yLambda()) > v0rapidityCut) // Rapidity selection + return false; if (fillHist) registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::V0RapidityAntiLambda); float properLifetime = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * MassLambda; - - if (properLifetime > v0ProperLifetimeCutLambda) + if (properLifetime > v0ProperLifetimeCutLambda) // Proper lifetime return false; - if (fillHist) registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::V0ProperLifetimeAntiLambda); - if (std::abs(v0.mAntiLambda() - MassLambda) > invMassCutLambda) + if (std::abs(v0.mAntiLambda() - MassLambda) > invMassCutLambda) // Invarian mass return false; - if (fillHist) registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::MassCutAntiLambda); @@ -913,13 +978,16 @@ struct DedxPidAnalysis { bool passedGammaSelection(const T1& v0, const T2& ntrack, const T2& ptrack, const C& collision) { + if (fillHist) + registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::AllGamma); + // Single-Track Selections if (!passedSingleTrackSelection(ptrack, collision)) return false; if (!passedSingleTrackSelection(ntrack, collision)) return false; - double sigmap = 0.0; + /*double sigmap = 0.0; double sigman = 0.0; if (v0SelectionMode == V0TPC) { @@ -945,23 +1013,25 @@ struct DedxPidAnalysis { return false; if (std::abs(sigman) > nsigmaTOFmax) return false; - } + }*/ const float gammaMass = 2 * MassElectron; // GeV/c^2 if (fillHist) - registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::AllGamma); - - const float yGamma = RecoDecay::y(std::array{v0.px(), v0.py(), v0.pz()}, MassGamma); + registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::SingleTrackSelectionGamma); - if (std::abs(yGamma) > v0rapidityCut) + if (v0.v0Type() != v0TypeSelectionGamma) // V0 type selection return false; + if (fillHist) + registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::V0TypeGamma); + const float yGamma = RecoDecay::y(std::array{v0.px(), v0.py(), v0.pz()}, MassGamma); + if (std::abs(yGamma) > v0rapidityCut) // Rapidity selection + return false; if (fillHist) registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::V0RapidityGamma); - if (std::abs(v0.mGamma() - gammaMass) > invMassCutGamma) + if (std::abs(v0.mGamma() - gammaMass) > invMassCutGamma) // Invarian mass return false; - if (fillHist) registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::MassCutGamma); @@ -1539,12 +1609,6 @@ struct DedxPidAnalysis { // Standard V0 Selections registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::AllSec); - // Select V0 type - if (v0.v0Type() != v0TypeSelection) - continue; - - registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::V0Type); - if (!passedV0Selection(v0, collision)) { continue; } @@ -1553,13 +1617,13 @@ struct DedxPidAnalysis { const auto& posTrack = v0.posTrack_as(); const auto& negTrack = v0.negTrack_as(); - if (!posTrack.passedTPCRefit()) + /*if (!posTrack.passedTPCRefit()) continue; if (!negTrack.passedTPCRefit()) - continue; + continue;*/ - registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::TPCRefit); - // phi and Ncl cut + // registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::TPCRefit); + // phi and Ncl cut if (phiVarCut) { if (!passedPhiCutSecondaries(posTrack, magField, *fphiCutLow, *fphiCutHigh)) continue; From 057099c7bbcf41ed3d0946324c8af4ed9795cab1 Mon Sep 17 00:00:00 2001 From: Jesper Karlsson Gumprecht <113693781+jesgum@users.noreply.github.com> Date: Sat, 28 Feb 2026 12:32:50 +0100 Subject: [PATCH 116/347] [ALICE3] Explicitly set ccdb manager in geometryContainer instances (#15196) --- ALICE3/Core/GeometryContainer.cxx | 8 ++++++++ ALICE3/Core/GeometryContainer.h | 2 +- ALICE3/TableProducer/OTF/onTheFlyRichPid.cxx | 1 + ALICE3/TableProducer/OTF/onTheFlyTofPid.cxx | 1 + ALICE3/TableProducer/OTF/onTheFlyTracker.cxx | 1 + 5 files changed, 12 insertions(+), 1 deletion(-) diff --git a/ALICE3/Core/GeometryContainer.cxx b/ALICE3/Core/GeometryContainer.cxx index 622e3d01757..f58c9b80926 100644 --- a/ALICE3/Core/GeometryContainer.cxx +++ b/ALICE3/Core/GeometryContainer.cxx @@ -101,6 +101,14 @@ void GeometryContainer::init(o2::framework::InitContext& initContext) } } +void GeometryContainer::addEntry(const std::string& filename) +{ + if (!mCcdb) { + LOG(fatal) << " --- ccdb is not set"; + } + mEntries.emplace_back(filename, mCcdb); +} + std::map GeometryEntry::getConfiguration(const std::string& layerName) const { auto it = mConfigurations.find(layerName); diff --git a/ALICE3/Core/GeometryContainer.h b/ALICE3/Core/GeometryContainer.h index 755fa57b87b..b3e9e23a538 100644 --- a/ALICE3/Core/GeometryContainer.h +++ b/ALICE3/Core/GeometryContainer.h @@ -91,7 +91,7 @@ class GeometryContainer void init(o2::framework::InitContext& initContext); // Add a geometry entry from a configuration file - void addEntry(const std::string& filename) { mEntries.emplace_back(filename, mCcdb); } + void addEntry(const std::string& filename); static void setLutCleanupSetting(const bool cleanLutWhenLoaded) { mCleanLutWhenLoaded = cleanLutWhenLoaded; } void setCcdbManager(o2::ccdb::BasicCCDBManager* mgr) { mCcdb = mgr; } diff --git a/ALICE3/TableProducer/OTF/onTheFlyRichPid.cxx b/ALICE3/TableProducer/OTF/onTheFlyRichPid.cxx index b2738c32c56..c11327e9f03 100644 --- a/ALICE3/TableProducer/OTF/onTheFlyRichPid.cxx +++ b/ALICE3/TableProducer/OTF/onTheFlyRichPid.cxx @@ -288,6 +288,7 @@ struct OnTheFlyRichPid { float mMagneticField = 0.0f; void init(o2::framework::InitContext& initContext) { + mGeoContainer.setCcdbManager(ccdb.operator->()); mGeoContainer.init(initContext); const int nGeometries = mGeoContainer.getNumberOfConfigurations(); diff --git a/ALICE3/TableProducer/OTF/onTheFlyTofPid.cxx b/ALICE3/TableProducer/OTF/onTheFlyTofPid.cxx index aecf7a85134..75e9d41d5c2 100644 --- a/ALICE3/TableProducer/OTF/onTheFlyTofPid.cxx +++ b/ALICE3/TableProducer/OTF/onTheFlyTofPid.cxx @@ -147,6 +147,7 @@ struct OnTheFlyTofPid { float mMagneticField = 0.0f; void init(o2::framework::InitContext& initContext) { + mGeoContainer.setCcdbManager(ccdb.operator->()); mGeoContainer.init(initContext); const int nGeometries = mGeoContainer.getNumberOfConfigurations(); diff --git a/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx b/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx index 4eb0cf81ea4..814b55623fe 100644 --- a/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx +++ b/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx @@ -317,6 +317,7 @@ struct OnTheFlyTracker { LOG(info) << "Initializing OnTheFlyTracker task"; ccdb->setURL("http://alice-ccdb.cern.ch"); ccdb->setTimestamp(-1); + mGeoContainer.setCcdbManager(ccdb.operator->()); mGeoContainer.init(initContext); const int nGeometries = mGeoContainer.getNumberOfConfigurations(); From ea101930c4f92d3aa9645944d4296e8447fad14d Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Sat, 28 Feb 2026 15:50:09 +0100 Subject: [PATCH 117/347] [PWGEM/Dilepton] reduce muon table size (#15201) Co-authored-by: ALICE Action Bot --- PWGEM/Dilepton/Core/Dilepton.h | 18 +- PWGEM/Dilepton/Core/DileptonHadronMPC.h | 29 ++- PWGEM/Dilepton/Core/DileptonMC.h | 10 +- PWGEM/Dilepton/Core/DileptonProducer.h | 13 +- PWGEM/Dilepton/Core/SingleTrackQC.h | 15 +- PWGEM/Dilepton/Core/SingleTrackQCMC.h | 15 +- PWGEM/Dilepton/DataModel/dileptonTables.h | 68 ++++-- .../TableProducer/Converters/CMakeLists.txt | 5 + .../Converters/muonConverter2.cxx | 52 +++++ .../Converters/trackConverter1.cxx | 13 +- .../TableProducer/associateMCinfoDilepton.cxx | 6 +- .../TableProducer/createEMEventDilepton.cxx | 5 +- .../TableProducer/skimmerPrimaryMFTTrack.cxx | 4 +- .../TableProducer/skimmerPrimaryMuon.cxx | 7 +- .../TableProducer/skimmerPrimaryTrack.cxx | 212 ++++++++---------- PWGEM/Dilepton/Utils/EMFwdTrack.h | 74 +++++- PWGEM/Dilepton/Utils/EMTrack.h | 4 +- PWGEM/Dilepton/Utils/EMTrackUtilities.h | 6 +- .../TableProducer/createEMEventPhoton.cxx | 4 +- 19 files changed, 344 insertions(+), 216 deletions(-) create mode 100644 PWGEM/Dilepton/TableProducer/Converters/muonConverter2.cxx diff --git a/PWGEM/Dilepton/Core/Dilepton.h b/PWGEM/Dilepton/Core/Dilepton.h index 9291314d00c..da847226252 100644 --- a/PWGEM/Dilepton/Core/Dilepton.h +++ b/PWGEM/Dilepton/Core/Dilepton.h @@ -186,7 +186,7 @@ struct Dilepton { Configurable cfg_min_dphi{"cfg_min_dphi", 0.2, "min dphi between 2 electrons (elliptic cut)"}; Configurable cfg_min_opang{"cfg_min_opang", 0.0, "min opening angle"}; Configurable cfg_max_opang{"cfg_max_opang", 6.4, "max opening angle"}; - Configurable cfg_require_diff_sides{"cfg_require_diff_sides", false, "flag to require 2 tracks are from different sides."}; + // Configurable cfg_require_diff_sides{"cfg_require_diff_sides", false, "flag to require 2 tracks are from different sides."}; Configurable cfg_apply_cuts_from_prefilter{"cfg_apply_cuts_from_prefilter", false, "flag to apply prefilter set when producing derived data"}; Configurable cfg_prefilter_bits{"cfg_prefilter_bits", 0, "prefilter bits [kNone : 0, kElFromPC : 1, kElFromPi0_20MeV : 2, kElFromPi0_40MeV : 4, kElFromPi0_60MeV : 8, kElFromPi0_80MeV : 16, kElFromPi0_100MeV : 32, kElFromPi0_120MeV : 64, kElFromPi0_140MeV : 128] Please consider logical-OR among them."}; // see PairUtilities.h @@ -215,8 +215,8 @@ struct Dilepton { Configurable cfg_require_itsib_1st{"cfg_require_itsib_1st", true, "flag to require ITS ib 1st hit"}; Configurable cfg_min_its_cluster_size{"cfg_min_its_cluster_size", 0.f, "min ITS cluster size"}; Configurable cfg_max_its_cluster_size{"cfg_max_its_cluster_size", 16.f, "max ITS cluster size"}; - Configurable cfg_min_rel_diff_pin{"cfg_min_rel_diff_pin", -1e+10, "min rel. diff. between pin and ppv"}; - Configurable cfg_max_rel_diff_pin{"cfg_max_rel_diff_pin", +1e+10, "max rel. diff. between pin and ppv"}; + // Configurable cfg_min_rel_diff_pin{"cfg_min_rel_diff_pin", -1e+10, "min rel. diff. between pin and ppv"}; + // Configurable cfg_max_rel_diff_pin{"cfg_max_rel_diff_pin", +1e+10, "max rel. diff. between pin and ppv"}; Configurable cfgRefR{"cfgRefR", 0.50, "ref. radius (m) for calculating phi position"}; // 0.50 +/- 0.06 can be syst. unc. Configurable cfg_min_phiposition_track{"cfg_min_phiposition_track", 0.f, "min phi position for single track at certain radius"}; Configurable cfg_max_phiposition_track{"cfg_max_phiposition_track", 6.3, "max phi position for single track at certain radius"}; @@ -708,7 +708,7 @@ struct Dilepton { fDielectronCut.ApplyPhiV(dielectroncuts.cfg_apply_phiv); fDielectronCut.SetMindEtadPhi(dielectroncuts.cfg_apply_detadphi, false, dielectroncuts.cfg_min_deta, dielectroncuts.cfg_min_dphi); fDielectronCut.SetPairOpAng(dielectroncuts.cfg_min_opang, dielectroncuts.cfg_max_opang); - fDielectronCut.SetRequireDifferentSides(dielectroncuts.cfg_require_diff_sides); + // fDielectronCut.SetRequireDifferentSides(dielectroncuts.cfg_require_diff_sides); // for track fDielectronCut.SetTrackPtRange(dielectroncuts.cfg_min_pt_track, dielectroncuts.cfg_max_pt_track); @@ -727,7 +727,7 @@ struct Dilepton { fDielectronCut.RequireITSibAny(dielectroncuts.cfg_require_itsib_any); fDielectronCut.RequireITSib1st(dielectroncuts.cfg_require_itsib_1st); fDielectronCut.SetChi2TOF(0, dielectroncuts.cfg_max_chi2tof); - fDielectronCut.SetRelDiffPin(dielectroncuts.cfg_min_rel_diff_pin, dielectroncuts.cfg_max_rel_diff_pin); + // fDielectronCut.SetRelDiffPin(dielectroncuts.cfg_min_rel_diff_pin, dielectroncuts.cfg_max_rel_diff_pin); // for eID fDielectronCut.SetPIDScheme(dielectroncuts.cfg_pid_scheme); @@ -1111,9 +1111,9 @@ struct Dilepton { used_trackIds_per_col.emplace_back(t1.globalIndex()); if (cfgDoMix) { if (t1.sign() > 0) { - emh_pos->AddTrackToEventPool(key_df_collision, EMFwdTrack(t1.pt(), t1.eta(), t1.phi(), leptonM1, t1.sign(), t1.fwdDcaX(), t1.fwdDcaY(), t1.cXXatDCA(), t1.cXYatDCA(), t1.cYYatDCA())); + emh_pos->AddTrackToEventPool(key_df_collision, EMFwdTrack(t1.pt(), t1.eta(), t1.phi(), leptonM1, t1.sign(), t1.fwdDcaX(), t1.fwdDcaY(), t1.cXX(), t1.cXY(), t1.cYY())); } else { - emh_neg->AddTrackToEventPool(key_df_collision, EMFwdTrack(t1.pt(), t1.eta(), t1.phi(), leptonM1, t1.sign(), t1.fwdDcaX(), t1.fwdDcaY(), t1.cXXatDCA(), t1.cXYatDCA(), t1.cYYatDCA())); + emh_neg->AddTrackToEventPool(key_df_collision, EMFwdTrack(t1.pt(), t1.eta(), t1.phi(), leptonM1, t1.sign(), t1.fwdDcaX(), t1.fwdDcaY(), t1.cXX(), t1.cXY(), t1.cYY())); } } } @@ -1121,9 +1121,9 @@ struct Dilepton { used_trackIds_per_col.emplace_back(t2.globalIndex()); if (cfgDoMix) { if (t2.sign() > 0) { - emh_pos->AddTrackToEventPool(key_df_collision, EMFwdTrack(t2.pt(), t2.eta(), t2.phi(), leptonM2, t2.sign(), t2.fwdDcaX(), t2.fwdDcaY(), t2.cXXatDCA(), t2.cXYatDCA(), t2.cYYatDCA())); + emh_pos->AddTrackToEventPool(key_df_collision, EMFwdTrack(t2.pt(), t2.eta(), t2.phi(), leptonM2, t2.sign(), t2.fwdDcaX(), t2.fwdDcaY(), t2.cXX(), t2.cXY(), t2.cYY())); } else { - emh_neg->AddTrackToEventPool(key_df_collision, EMFwdTrack(t2.pt(), t2.eta(), t2.phi(), leptonM2, t2.sign(), t2.fwdDcaX(), t2.fwdDcaY(), t2.cXXatDCA(), t2.cXYatDCA(), t2.cYYatDCA())); + emh_neg->AddTrackToEventPool(key_df_collision, EMFwdTrack(t2.pt(), t2.eta(), t2.phi(), leptonM2, t2.sign(), t2.fwdDcaX(), t2.fwdDcaY(), t2.cXX(), t2.cXY(), t2.cYY())); } } } diff --git a/PWGEM/Dilepton/Core/DileptonHadronMPC.h b/PWGEM/Dilepton/Core/DileptonHadronMPC.h index 77823486157..83797ce3e96 100644 --- a/PWGEM/Dilepton/Core/DileptonHadronMPC.h +++ b/PWGEM/Dilepton/Core/DileptonHadronMPC.h @@ -208,7 +208,7 @@ struct DileptonHadronMPC { Configurable cfg_max_dcaz{"cfg_max_dcaz", 1.0, "max dca Z for single track in cm"}; Configurable cfg_require_itsib_any{"cfg_require_itsib_any", false, "flag to require ITS ib any hits"}; Configurable cfg_require_itsib_1st{"cfg_require_itsib_1st", true, "flag to require ITS ib 1st hit"}; - Configurable cfgRefR{"cfgRefR", 1.2, "reference R (in m) for extrapolation"}; // https://cds.cern.ch/record/1419204 + Configurable cfgRefR{"cfgRefR", 0.5, "reference R (in m) for extrapolation"}; // https://cds.cern.ch/record/1419204 Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DielectronCut::PIDSchemes::kTPChadrejORTOFreq), "pid scheme [kTOFreq : 0, kTPChadrej : 1, kTPChadrejORTOFreq : 2, kTPConly : 3, kTOFif : 4, kPIDML : 5, kTPChadrejORTOFreq_woTOFif : 6]"}; Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -2.0, "min. TPC n sigma for electron inclusion"}; @@ -617,7 +617,6 @@ struct DileptonHadronMPC { fDielectronCut.RequireITSib1st(dielectroncuts.cfg_require_itsib_1st); fDielectronCut.SetChi2TOF(0, dielectroncuts.cfg_max_chi2tof); fDielectronCut.SetRelDiffPin(-1e+10, +1e+10); - fDielectronCut.IncludeITSsa(false, 0.15); // for eID fDielectronCut.SetPIDScheme(dielectroncuts.cfg_pid_scheme); @@ -807,9 +806,9 @@ struct DileptonHadronMPC { used_trackIds_per_col.emplace_back(t1.globalIndex()); if (cfgDoMix) { if (t1.sign() > 0) { - emh_pos->AddTrackToEventPool(key_df_collision, EMFwdTrack(t1.pt(), t1.eta(), t1.phi(), leptonM1, t1.sign(), t1.fwdDcaX(), t1.fwdDcaY(), t1.cXXatDCA(), t1.cXYatDCA(), t1.cYYatDCA())); + emh_pos->AddTrackToEventPool(key_df_collision, EMFwdTrack(t1.pt(), t1.eta(), t1.phi(), leptonM1, t1.sign(), t1.fwdDcaX(), t1.fwdDcaY(), t1.cXX(), t1.cXY(), t1.cYY())); } else { - emh_neg->AddTrackToEventPool(key_df_collision, EMFwdTrack(t1.pt(), t1.eta(), t1.phi(), leptonM1, t1.sign(), t1.fwdDcaX(), t1.fwdDcaY(), t1.cXXatDCA(), t1.cXYatDCA(), t1.cYYatDCA())); + emh_neg->AddTrackToEventPool(key_df_collision, EMFwdTrack(t1.pt(), t1.eta(), t1.phi(), leptonM1, t1.sign(), t1.fwdDcaX(), t1.fwdDcaY(), t1.cXX(), t1.cXY(), t1.cYY())); } } } @@ -817,9 +816,9 @@ struct DileptonHadronMPC { used_trackIds_per_col.emplace_back(t2.globalIndex()); if (cfgDoMix) { if (t2.sign() > 0) { - emh_pos->AddTrackToEventPool(key_df_collision, EMFwdTrack(t2.pt(), t2.eta(), t2.phi(), leptonM2, t2.sign(), t2.fwdDcaX(), t2.fwdDcaY(), t2.cXXatDCA(), t2.cXYatDCA(), t2.cYYatDCA())); + emh_pos->AddTrackToEventPool(key_df_collision, EMFwdTrack(t2.pt(), t2.eta(), t2.phi(), leptonM2, t2.sign(), t2.fwdDcaX(), t2.fwdDcaY(), t2.cXX(), t2.cXY(), t2.cYY())); } else { - emh_neg->AddTrackToEventPool(key_df_collision, EMFwdTrack(t2.pt(), t2.eta(), t2.phi(), leptonM2, t2.sign(), t2.fwdDcaX(), t2.fwdDcaY(), t2.cXXatDCA(), t2.cXYatDCA(), t2.cYYatDCA())); + emh_neg->AddTrackToEventPool(key_df_collision, EMFwdTrack(t2.pt(), t2.eta(), t2.phi(), leptonM2, t2.sign(), t2.fwdDcaX(), t2.fwdDcaY(), t2.cXX(), t2.cXY(), t2.cYY())); } } } @@ -844,9 +843,9 @@ struct DileptonHadronMPC { return false; } } - if (t1.trackId() == t3.trackId() || t2.trackId() == t3.trackId()) { - return false; - } + // if (t1.trackId() == t3.trackId() || t2.trackId() == t3.trackId()) { + // return false; + // } } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { if (!cut.template IsSelectedTrack(t1) || !cut.template IsSelectedTrack(t2)) { return false; @@ -947,9 +946,9 @@ struct DileptonHadronMPC { continue; } } - if (t1.trackId() == pos.trackId() || t2.trackId() == pos.trackId()) { - return false; - } + // if (t1.trackId() == pos.trackId() || t2.trackId() == pos.trackId()) { + // return false; + // } } // end of pos lepton loop for (const auto& neg : negLeptons) { // leptons per collision @@ -962,9 +961,9 @@ struct DileptonHadronMPC { continue; } } - if (t1.trackId() == neg.trackId() || t2.trackId() == neg.trackId()) { - return false; - } + // if (t1.trackId() == neg.trackId() || t2.trackId() == neg.trackId()) { + // return false; + // } } // end of neg lepton lopp } // end of if kDielectron diff --git a/PWGEM/Dilepton/Core/DileptonMC.h b/PWGEM/Dilepton/Core/DileptonMC.h index b20a9be3820..478695d906c 100644 --- a/PWGEM/Dilepton/Core/DileptonMC.h +++ b/PWGEM/Dilepton/Core/DileptonMC.h @@ -188,7 +188,7 @@ struct DileptonMC { Configurable cfg_min_dphi{"cfg_min_dphi", 0.2, "min dphi between 2 electrons (elliptic cut)"}; Configurable cfg_min_opang{"cfg_min_opang", 0.0, "min opening angle"}; Configurable cfg_max_opang{"cfg_max_opang", 6.4, "max opening angle"}; - Configurable cfg_require_diff_sides{"cfg_require_diff_sides", false, "flag to require 2 tracks are from different sides."}; + // Configurable cfg_require_diff_sides{"cfg_require_diff_sides", false, "flag to require 2 tracks are from different sides."}; Configurable cfg_apply_cuts_from_prefilter{"cfg_apply_cuts_from_prefilter", false, "flag to apply prefilter set when producing derived data"}; Configurable cfg_prefilter_bits{"cfg_prefilter_bits", 0, "prefilter bits [kNone : 0, kElFromPC : 1, kElFromPi0_20MeV : 2, kElFromPi0_40MeV : 4, kElFromPi0_60MeV : 8, kElFromPi0_80MeV : 16, kElFromPi0_100MeV : 32, kElFromPi0_120MeV : 64, kElFromPi0_140MeV : 128] Please consider logical-OR among them."}; // see PairUtilities.h @@ -217,8 +217,8 @@ struct DileptonMC { Configurable cfg_require_itsib_1st{"cfg_require_itsib_1st", true, "flag to require ITS ib 1st hit"}; Configurable cfg_min_its_cluster_size{"cfg_min_its_cluster_size", 0.f, "min ITS cluster size"}; Configurable cfg_max_its_cluster_size{"cfg_max_its_cluster_size", 16.f, "max ITS cluster size"}; - Configurable cfg_min_rel_diff_pin{"cfg_min_rel_diff_pin", -1e+10, "min rel. diff. between pin and ppv"}; - Configurable cfg_max_rel_diff_pin{"cfg_max_rel_diff_pin", +1e+10, "max rel. diff. between pin and ppv"}; + // Configurable cfg_min_rel_diff_pin{"cfg_min_rel_diff_pin", -1e+10, "min rel. diff. between pin and ppv"}; + // Configurable cfg_max_rel_diff_pin{"cfg_max_rel_diff_pin", +1e+10, "max rel. diff. between pin and ppv"}; Configurable cfgRefR{"cfgRefR", 0.50, "ref. radius (m) for calculating phi position"}; // 0.50 +/- 0.06 can be syst. unc. Configurable cfg_min_phiposition_track{"cfg_min_phiposition_track", 0.f, "min phi position for single track at certain radius"}; Configurable cfg_max_phiposition_track{"cfg_max_phiposition_track", 6.3, "max phi position for single track at certain radius"}; @@ -715,7 +715,7 @@ struct DileptonMC { fDielectronCut.ApplyPhiV(dielectroncuts.cfg_apply_phiv); fDielectronCut.SetMindEtadPhi(dielectroncuts.cfg_apply_detadphi, false, dielectroncuts.cfg_min_deta, dielectroncuts.cfg_min_dphi); fDielectronCut.SetPairOpAng(dielectroncuts.cfg_min_opang, dielectroncuts.cfg_max_opang); - fDielectronCut.SetRequireDifferentSides(dielectroncuts.cfg_require_diff_sides); + // fDielectronCut.SetRequireDifferentSides(dielectroncuts.cfg_require_diff_sides); // for track fDielectronCut.SetTrackPtRange(dielectroncuts.cfg_min_pt_track, dielectroncuts.cfg_max_pt_track); @@ -734,7 +734,7 @@ struct DileptonMC { fDielectronCut.RequireITSibAny(dielectroncuts.cfg_require_itsib_any); fDielectronCut.RequireITSib1st(dielectroncuts.cfg_require_itsib_1st); fDielectronCut.SetChi2TOF(0.0, dielectroncuts.cfg_max_chi2tof); - fDielectronCut.SetRelDiffPin(dielectroncuts.cfg_min_rel_diff_pin, dielectroncuts.cfg_max_rel_diff_pin); + // fDielectronCut.SetRelDiffPin(dielectroncuts.cfg_min_rel_diff_pin, dielectroncuts.cfg_max_rel_diff_pin); // for eID fDielectronCut.SetPIDScheme(dielectroncuts.cfg_pid_scheme); diff --git a/PWGEM/Dilepton/Core/DileptonProducer.h b/PWGEM/Dilepton/Core/DileptonProducer.h index 26b06061cb4..d28e616db13 100644 --- a/PWGEM/Dilepton/Core/DileptonProducer.h +++ b/PWGEM/Dilepton/Core/DileptonProducer.h @@ -162,7 +162,7 @@ struct DileptonProducer { Configurable cfg_min_dphi{"cfg_min_dphi", 0.2, "min dphi between 2 electrons (elliptic cut)"}; Configurable cfg_min_opang{"cfg_min_opang", 0.0, "min opening angle"}; Configurable cfg_max_opang{"cfg_max_opang", 6.4, "max opening angle"}; - Configurable cfg_require_diff_sides{"cfg_require_diff_sides", false, "flag to require 2 tracks are from different sides."}; + // Configurable cfg_require_diff_sides{"cfg_require_diff_sides", false, "flag to require 2 tracks are from different sides."}; Configurable cfg_apply_cuts_from_prefilter{"cfg_apply_cuts_from_prefilter", false, "flag to apply prefilter set when producing derived data"}; Configurable cfg_prefilter_bits{"cfg_prefilter_bits", 0, "prefilter bits [kNone : 0, kElFromPC : 1, kElFromPi0_20MeV : 2, kElFromPi0_40MeV : 4, kElFromPi0_60MeV : 8, kElFromPi0_80MeV : 16, kElFromPi0_100MeV : 32, kElFromPi0_120MeV : 64, kElFromPi0_140MeV : 128] Please consider logical-OR among them."}; // see PairUtilities.h @@ -191,8 +191,8 @@ struct DileptonProducer { Configurable cfg_require_itsib_1st{"cfg_require_itsib_1st", true, "flag to require ITS ib 1st hit"}; Configurable cfg_min_its_cluster_size{"cfg_min_its_cluster_size", 0.f, "min ITS cluster size"}; Configurable cfg_max_its_cluster_size{"cfg_max_its_cluster_size", 16.f, "max ITS cluster size"}; - Configurable cfg_min_rel_diff_pin{"cfg_min_rel_diff_pin", -1e+10, "min rel. diff. between pin and ppv"}; - Configurable cfg_max_rel_diff_pin{"cfg_max_rel_diff_pin", +1e+10, "max rel. diff. between pin and ppv"}; + // Configurable cfg_min_rel_diff_pin{"cfg_min_rel_diff_pin", -1e+10, "min rel. diff. between pin and ppv"}; + // Configurable cfg_max_rel_diff_pin{"cfg_max_rel_diff_pin", +1e+10, "max rel. diff. between pin and ppv"}; Configurable cfgRefR{"cfgRefR", 0.50, "ref. radius (m) for calculating phi position"}; // 0.50 +/- 0.06 can be syst. unc. Configurable cfg_min_phiposition_track{"cfg_min_phiposition_track", 0.f, "min phi position for single track at certain radius"}; Configurable cfg_max_phiposition_track{"cfg_max_phiposition_track", 6.3, "max phi position for single track at certain radius"}; @@ -213,8 +213,6 @@ struct DileptonProducer { Configurable cfg_min_pin_pirejTPC{"cfg_min_pin_pirejTPC", 0.f, "min. pin for pion rejection in TPC"}; Configurable cfg_max_pin_pirejTPC{"cfg_max_pin_pirejTPC", 1e+10, "max. pin for pion rejection in TPC"}; Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; - Configurable includeITSsa{"includeITSsa", false, "Flag to enable ITSsa tracks"}; - Configurable cfg_max_pt_track_ITSsa{"cfg_max_pt_track_ITSsa", 0.15, "max pt for ITSsa tracks"}; // configuration for PID ML Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; @@ -393,7 +391,7 @@ struct DileptonProducer { fDielectronCut.ApplyPhiV(dielectroncuts.cfg_apply_phiv); fDielectronCut.SetMindEtadPhi(dielectroncuts.cfg_apply_detadphi, false, dielectroncuts.cfg_min_deta, dielectroncuts.cfg_min_dphi); fDielectronCut.SetPairOpAng(dielectroncuts.cfg_min_opang, dielectroncuts.cfg_max_opang); - fDielectronCut.SetRequireDifferentSides(dielectroncuts.cfg_require_diff_sides); + // fDielectronCut.SetRequireDifferentSides(dielectroncuts.cfg_require_diff_sides); // for track fDielectronCut.SetTrackPtRange(dielectroncuts.cfg_min_pt_track, dielectroncuts.cfg_max_pt_track); @@ -412,8 +410,7 @@ struct DileptonProducer { fDielectronCut.RequireITSibAny(dielectroncuts.cfg_require_itsib_any); fDielectronCut.RequireITSib1st(dielectroncuts.cfg_require_itsib_1st); fDielectronCut.SetChi2TOF(0, dielectroncuts.cfg_max_chi2tof); - fDielectronCut.SetRelDiffPin(dielectroncuts.cfg_min_rel_diff_pin, dielectroncuts.cfg_max_rel_diff_pin); - fDielectronCut.IncludeITSsa(dielectroncuts.includeITSsa, dielectroncuts.cfg_max_pt_track_ITSsa); + // fDielectronCut.SetRelDiffPin(dielectroncuts.cfg_min_rel_diff_pin, dielectroncuts.cfg_max_rel_diff_pin); // for eID fDielectronCut.SetPIDScheme(dielectroncuts.cfg_pid_scheme); diff --git a/PWGEM/Dilepton/Core/SingleTrackQC.h b/PWGEM/Dilepton/Core/SingleTrackQC.h index 8b2d00019a3..9fb4d919e4d 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQC.h @@ -172,8 +172,6 @@ struct SingleTrackQC { Configurable cfg_min_pin_pirejTPC{"cfg_min_pin_pirejTPC", 0.f, "min. pin for pion rejection in TPC"}; Configurable cfg_max_pin_pirejTPC{"cfg_max_pin_pirejTPC", 1e+10, "max. pin for pion rejection in TPC"}; Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; - Configurable includeITSsa{"includeITSsa", false, "Flag to enable ITSsa tracks"}; - Configurable cfg_max_pt_track_ITSsa{"cfg_max_pt_track_ITSsa", 0.15, "max pt for ITSsa tracks"}; // configuration for PID ML Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; @@ -472,7 +470,6 @@ struct SingleTrackQC { fDielectronCut.RequireITSib1st(dielectroncuts.cfg_require_itsib_1st); fDielectronCut.SetChi2TOF(0.0, dielectroncuts.cfg_max_chi2tof); fDielectronCut.SetRelDiffPin(dielectroncuts.cfg_min_rel_diff_pin, dielectroncuts.cfg_max_rel_diff_pin); - fDielectronCut.IncludeITSsa(dielectroncuts.includeITSsa, dielectroncuts.cfg_max_pt_track_ITSsa); // for eID fDielectronCut.SetPIDScheme(dielectroncuts.cfg_pid_scheme); @@ -662,9 +659,9 @@ struct SingleTrackQC { fRegistry.fill(HIST("Track/positive/hQoverPt"), track.sign() / track.pt()); fRegistry.fill(HIST("Track/positive/hTrackType"), track.trackType()); fRegistry.fill(HIST("Track/positive/hDCAxy"), track.fwdDcaX(), track.fwdDcaY()); - fRegistry.fill(HIST("Track/positive/hDCAxySigma"), track.fwdDcaX() / std::sqrt(track.cXXatDCA()), track.fwdDcaY() / std::sqrt(track.cYYatDCA())); - fRegistry.fill(HIST("Track/positive/hDCAxRes_Pt"), track.pt(), std::sqrt(track.cXXatDCA()) * 1e+4); - fRegistry.fill(HIST("Track/positive/hDCAyRes_Pt"), track.pt(), std::sqrt(track.cYYatDCA()) * 1e+4); + fRegistry.fill(HIST("Track/positive/hDCAxySigma"), track.fwdDcaX() / std::sqrt(track.cXX()), track.fwdDcaY() / std::sqrt(track.cYY())); + fRegistry.fill(HIST("Track/positive/hDCAxRes_Pt"), track.pt(), std::sqrt(track.cXX()) * 1e+4); + fRegistry.fill(HIST("Track/positive/hDCAyRes_Pt"), track.pt(), std::sqrt(track.cYY()) * 1e+4); fRegistry.fill(HIST("Track/positive/hDCAxyRes_Pt"), track.pt(), sigmaFwdDcaXY(track) * 1e+4); fRegistry.fill(HIST("Track/positive/hDCAx_PosZ"), collision.posZ(), track.fwdDcaX()); fRegistry.fill(HIST("Track/positive/hDCAy_PosZ"), collision.posZ(), track.fwdDcaY()); @@ -686,9 +683,9 @@ struct SingleTrackQC { fRegistry.fill(HIST("Track/negative/hQoverPt"), track.sign() / track.pt()); fRegistry.fill(HIST("Track/negative/hTrackType"), track.trackType()); fRegistry.fill(HIST("Track/negative/hDCAxy"), track.fwdDcaX(), track.fwdDcaY()); - fRegistry.fill(HIST("Track/negative/hDCAxySigma"), track.fwdDcaX() / std::sqrt(track.cXXatDCA()), track.fwdDcaY() / std::sqrt(track.cYYatDCA())); - fRegistry.fill(HIST("Track/negative/hDCAxRes_Pt"), track.pt(), std::sqrt(track.cXXatDCA()) * 1e+4); - fRegistry.fill(HIST("Track/negative/hDCAyRes_Pt"), track.pt(), std::sqrt(track.cYYatDCA()) * 1e+4); + fRegistry.fill(HIST("Track/negative/hDCAxySigma"), track.fwdDcaX() / std::sqrt(track.cXX()), track.fwdDcaY() / std::sqrt(track.cYY())); + fRegistry.fill(HIST("Track/negative/hDCAxRes_Pt"), track.pt(), std::sqrt(track.cXX()) * 1e+4); + fRegistry.fill(HIST("Track/negative/hDCAyRes_Pt"), track.pt(), std::sqrt(track.cYY()) * 1e+4); fRegistry.fill(HIST("Track/negative/hDCAxyRes_Pt"), track.pt(), sigmaFwdDcaXY(track) * 1e+4); fRegistry.fill(HIST("Track/negative/hDCAx_PosZ"), collision.posZ(), track.fwdDcaX()); fRegistry.fill(HIST("Track/negative/hDCAy_PosZ"), collision.posZ(), track.fwdDcaY()); diff --git a/PWGEM/Dilepton/Core/SingleTrackQCMC.h b/PWGEM/Dilepton/Core/SingleTrackQCMC.h index 32169f6330f..d60e266da19 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQCMC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQCMC.h @@ -181,8 +181,6 @@ struct SingleTrackQCMC { Configurable cfg_min_pin_pirejTPC{"cfg_min_pin_pirejTPC", 0.f, "min. pin for pion rejection in TPC"}; Configurable cfg_max_pin_pirejTPC{"cfg_max_pin_pirejTPC", 1e+10, "max. pin for pion rejection in TPC"}; Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; - Configurable includeITSsa{"includeITSsa", false, "Flag to enable ITSsa tracks"}; - Configurable cfg_max_pt_track_ITSsa{"cfg_max_pt_track_ITSsa", 0.15, "max pt for ITSsa tracks"}; // configuration for PID ML Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; @@ -516,7 +514,6 @@ struct SingleTrackQCMC { fDielectronCut.RequireITSib1st(dielectroncuts.cfg_require_itsib_1st); fDielectronCut.SetChi2TOF(0.0, dielectroncuts.cfg_max_chi2tof); fDielectronCut.SetRelDiffPin(dielectroncuts.cfg_min_rel_diff_pin, dielectroncuts.cfg_max_rel_diff_pin); - fDielectronCut.IncludeITSsa(dielectroncuts.includeITSsa, dielectroncuts.cfg_max_pt_track_ITSsa); // for eID fDielectronCut.SetPIDScheme(dielectroncuts.cfg_pid_scheme); @@ -769,9 +766,9 @@ struct SingleTrackQCMC { fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hTrackType"), track.trackType()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hDCAxy"), std::sqrt(std::pow(track.fwdDcaX(), 2) + std::pow(track.fwdDcaY(), 2))); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hDCAxy2D"), track.fwdDcaX(), track.fwdDcaY()); - fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hDCAxy2DinSigma"), track.fwdDcaX() / std::sqrt(track.cXXatDCA()), track.fwdDcaY() / std::sqrt(track.cYYatDCA())); - fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hDCAxRes_Pt"), track.pt(), std::sqrt(track.cXXatDCA()) * 1e+4); - fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hDCAyRes_Pt"), track.pt(), std::sqrt(track.cYYatDCA()) * 1e+4); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hDCAxy2DinSigma"), track.fwdDcaX() / std::sqrt(track.cXX()), track.fwdDcaY() / std::sqrt(track.cYY())); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hDCAxRes_Pt"), track.pt(), std::sqrt(track.cXX()) * 1e+4); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hDCAyRes_Pt"), track.pt(), std::sqrt(track.cYY()) * 1e+4); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hDCAxyRes_Pt"), track.pt(), sigmaFwdDcaXY(track) * 1e+4); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hDCAx_PosZ"), collision.posZ(), track.fwdDcaX()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hDCAy_PosZ"), collision.posZ(), track.fwdDcaY()); @@ -802,9 +799,9 @@ struct SingleTrackQCMC { fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hTrackType"), track.trackType()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hDCAxy"), std::sqrt(std::pow(track.fwdDcaX(), 2) + std::pow(track.fwdDcaY(), 2))); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hDCAxy2D"), track.fwdDcaX(), track.fwdDcaY()); - fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hDCAxy2DinSigma"), track.fwdDcaX() / std::sqrt(track.cXXatDCA()), track.fwdDcaY() / std::sqrt(track.cYYatDCA())); - fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hDCAxRes_Pt"), track.pt(), std::sqrt(track.cXXatDCA()) * 1e+4); - fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hDCAyRes_Pt"), track.pt(), std::sqrt(track.cYYatDCA()) * 1e+4); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hDCAxy2DinSigma"), track.fwdDcaX() / std::sqrt(track.cXX()), track.fwdDcaY() / std::sqrt(track.cYY())); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hDCAxRes_Pt"), track.pt(), std::sqrt(track.cXX()) * 1e+4); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hDCAyRes_Pt"), track.pt(), std::sqrt(track.cYY()) * 1e+4); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hDCAxyRes_Pt"), track.pt(), sigmaFwdDcaXY(track) * 1e+4); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hDCAx_PosZ"), collision.posZ(), track.fwdDcaX()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hDCAy_PosZ"), collision.posZ(), track.fwdDcaY()); diff --git a/PWGEM/Dilepton/DataModel/dileptonTables.h b/PWGEM/Dilepton/DataModel/dileptonTables.h index e26f3ef9ab4..f6afb53f3e6 100644 --- a/PWGEM/Dilepton/DataModel/dileptonTables.h +++ b/PWGEM/Dilepton/DataModel/dileptonTables.h @@ -328,7 +328,7 @@ DECLARE_SOA_TABLE_VERSIONED(EMEventsAlias_000, "AOD", "EMEVENTALIAS", 0, evsel:: using EMEventsAlias = EMEventsAlias_000; using EMEventAlias = EMEventsAlias::iterator; -DECLARE_SOA_TABLE(EMEventsXY, "AOD", "EMEVENTXY", emevent::PosX, emevent::PosY); // joinable to EMEvents, only for treeCreatetorML.cxx +DECLARE_SOA_TABLE(EMEventsXY, "AOD", "EMEVENTXY", collision::PosX, collision::PosY); // joinable to EMEvents using EMEventXY = EMEventsXY::iterator; DECLARE_SOA_TABLE(EMEventsCov, "AOD", "EMEVENTCOV", //! joinable to EMEvents @@ -999,6 +999,7 @@ DECLARE_SOA_COLUMN(IsAmbiguous, isAmbiguous, bool); //! is am DECLARE_SOA_COLUMN(IsCorrectMatchMFTMCH, isCorrectMatchMFTMCH, bool); //! is correct match between MFT and MCH, only for MC DECLARE_SOA_COLUMN(Sign, sign, int8_t); //! DECLARE_SOA_COLUMN(Chi2MFT, chi2MFT, float); //! chi2 of MFT standalone track +DECLARE_SOA_DYNAMIC_COLUMN(Tgl, tgl, [](float eta) -> float { return std::tan(o2::constants::math::PIHalf - 2 * std::atan(std::exp(-eta))); }); DECLARE_SOA_DYNAMIC_COLUMN(Signed1Pt, signed1Pt, [](float pt, int8_t sign) -> float { return sign * 1. / pt; }); DECLARE_SOA_DYNAMIC_COLUMN(P, p, [](float pt, float eta) -> float { return pt * std::cosh(eta); }); DECLARE_SOA_DYNAMIC_COLUMN(Px, px, [](float pt, float phi) -> float { return pt * std::cos(phi); }); @@ -1071,26 +1072,53 @@ DECLARE_SOA_TABLE_VERSIONED(EMPrimaryMuons_001, "AOD", "EMPRIMARYMU", 1, //! emprimarymuon::Py, emprimarymuon::Pz); -using EMPrimaryMuons = EMPrimaryMuons_001; +DECLARE_SOA_TABLE_VERSIONED(EMPrimaryMuons_002, "AOD", "EMPRIMARYMU", 2, //! + o2::soa::Index<>, emprimarymuon::CollisionId, + emprimarymuon::FwdTrackId, emprimarymuon::MFTTrackId, emprimarymuon::MCHTrackId, fwdtrack::TrackType, + fwdtrack::Pt, fwdtrack::Eta, fwdtrack::Phi, emprimarymuon::Sign, + fwdtrack::FwdDcaX, fwdtrack::FwdDcaY, aod::fwdtrack::CXX, aod::fwdtrack::CYY, aod::fwdtrack::CXY, + emprimarymuon::PtMatchedMCHMID, emprimarymuon::EtaMatchedMCHMID, emprimarymuon::PhiMatchedMCHMID, + // emprimarymuon::EtaMatchedMCHMIDatMP, emprimarymuon::PhiMatchedMCHMIDatMP, + // emprimarymuon::EtaMatchedMFTatMP, emprimarymuon::PhiMatchedMFTatMP, + + fwdtrack::NClusters, fwdtrack::PDca, fwdtrack::RAtAbsorberEnd, + fwdtrack::Chi2, fwdtrack::Chi2MatchMCHMID, fwdtrack::Chi2MatchMCHMFT, + fwdtrack::MCHBitMap, fwdtrack::MIDBitMap, fwdtrack::MIDBoards, + fwdtrack::MFTClusterSizesAndTrackFlags, emprimarymuon::Chi2MFT, emprimarymuon::IsAssociatedToMPC, emprimarymuon::IsAmbiguous, + + // dynamic column + emprimarymuon::Signed1Pt, + emprimarymuon::Tgl, + emprimarymuon::NClustersMFT, + fwdtrack::IsCA, + emprimarymuon::MFTClusterMap, + emprimarymuon::P, + emprimarymuon::Px, + emprimarymuon::Py, + emprimarymuon::Pz); + +using EMPrimaryMuons = EMPrimaryMuons_002; // iterators using EMPrimaryMuon = EMPrimaryMuons::iterator; -DECLARE_SOA_TABLE(EMPrimaryMuonsCov, "AOD", "EMPRIMARYMUCOV", //! - aod::fwdtrack::CXX, - aod::fwdtrack::CXY, - aod::fwdtrack::CYY, - aod::fwdtrack::CPhiX, - aod::fwdtrack::CPhiY, - aod::fwdtrack::CPhiPhi, - aod::fwdtrack::CTglX, - aod::fwdtrack::CTglY, - aod::fwdtrack::CTglPhi, - aod::fwdtrack::CTglTgl, - aod::fwdtrack::C1PtX, - aod::fwdtrack::C1PtY, - aod::fwdtrack::C1PtPhi, - aod::fwdtrack::C1PtTgl, - aod::fwdtrack::C1Pt21Pt2); +DECLARE_SOA_TABLE_VERSIONED(EMPrimaryMuonsCov_002, "AOD", "EMPRIMARYMUCOV", 2, //! + fwdtrack::X, fwdtrack::Y, fwdtrack::Z, // at PV. Signed1Pt, Tgl and Phi are in EMPrimaryMuons table. + // aod::fwdtrack::CXX, + // aod::fwdtrack::CXY, + // aod::fwdtrack::CYY, + aod::fwdtrack::CPhiX, + aod::fwdtrack::CPhiY, + aod::fwdtrack::CPhiPhi, + aod::fwdtrack::CTglX, + aod::fwdtrack::CTglY, + aod::fwdtrack::CTglPhi, + aod::fwdtrack::CTglTgl, + aod::fwdtrack::C1PtX, + aod::fwdtrack::C1PtY, + aod::fwdtrack::C1PtPhi, + aod::fwdtrack::C1PtTgl, + aod::fwdtrack::C1Pt21Pt2); +using EMPrimaryMuonsCov = EMPrimaryMuonsCov_002; // iterators using EMPrimaryMuonCov = EMPrimaryMuonsCov::iterator; @@ -1131,8 +1159,8 @@ DECLARE_SOA_DYNAMIC_COLUMN(Sign, sign, [](float signed1Pt) -> short { return (si DECLARE_SOA_TABLE_VERSIONED(EMPrimaryTracks_000, "AOD", "EMPRIMARYTRACK", 0, //! primary charged track table for 2PC o2::soa::Index<>, emprimarytrack::CollisionId, emprimarytrack::TrackId, oldemprimarytrack::Sign, track::Pt, track::Eta, track::Phi, emprimarytrack::TrackBit); -DECLARE_SOA_TABLE_VERSIONED(EMPrimaryTracks_001, "AOD", "EMPRIMARYTRACK", 1, //! primary charged track table for 2PC - o2::soa::Index<>, emprimarytrack::CollisionId, emprimarytrack::TrackId, +DECLARE_SOA_TABLE_VERSIONED(EMPrimaryTracks_001, "AOD", "EMPRIMARYTRACK", 1, //! primary charged track table for 2PC + o2::soa::Index<>, /*emprimarytrack::CollisionId,*/ /*emprimarytrack::TrackId,*/ emprimarytrack::Signed1Pt, emprimarytrack::Eta, emprimarytrack::Phi, emprimarytrack::TrackBit, // dynamic column emprimarytrack::Sign, emprimarytrack::Pt); diff --git a/PWGEM/Dilepton/TableProducer/Converters/CMakeLists.txt b/PWGEM/Dilepton/TableProducer/Converters/CMakeLists.txt index 9d130209e72..748d953f900 100644 --- a/PWGEM/Dilepton/TableProducer/Converters/CMakeLists.txt +++ b/PWGEM/Dilepton/TableProducer/Converters/CMakeLists.txt @@ -60,6 +60,11 @@ o2physics_add_dpl_workflow(muon-converter1 PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(muon-converter2 + SOURCES muonConverter2.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(mcparticle-converter1 SOURCES mcParticleConverter1.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore diff --git a/PWGEM/Dilepton/TableProducer/Converters/muonConverter2.cxx b/PWGEM/Dilepton/TableProducer/Converters/muonConverter2.cxx new file mode 100644 index 00000000000..aea074131e3 --- /dev/null +++ b/PWGEM/Dilepton/TableProducer/Converters/muonConverter2.cxx @@ -0,0 +1,52 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +// +// ======================== +// +// This code produces muon table 001 from 000. +// Please write to: daiki.sekihata@cern.ch + +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" + +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +struct muonConverter2 { + Produces muon_002; + + void process(aod::EMPrimaryMuons_001 const& muons) + { + for (const auto& muon : muons) { + muon_002( + muon.collisionId(), + muon.fwdtrackId(), muon.mfttrackId(), muon.mchtrackId(), muon.trackType(), + muon.pt(), muon.eta(), muon.phi(), muon.sign(), + muon.fwdDcaX(), muon.fwdDcaY(), muon.cXXatDCA(), muon.cYYatDCA(), muon.cXYatDCA(), + muon.ptMatchedMCHMID(), muon.etaMatchedMCHMID(), muon.phiMatchedMCHMID(), + muon.nClusters(), muon.pDca(), muon.rAtAbsorberEnd(), + muon.chi2(), muon.chi2MatchMCHMID(), muon.chi2MatchMCHMFT(), + muon.mchBitMap(), muon.midBitMap(), muon.midBoards(), + muon.mftClusterSizesAndTrackFlags(), muon.chi2MFT(), muon.isAssociatedToMPC(), muon.isAmbiguous()); + } // end of muon loop + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"muon-converter2"})}; +} diff --git a/PWGEM/Dilepton/TableProducer/Converters/trackConverter1.cxx b/PWGEM/Dilepton/TableProducer/Converters/trackConverter1.cxx index c6f7bfce634..7ae8f3d47da 100644 --- a/PWGEM/Dilepton/TableProducer/Converters/trackConverter1.cxx +++ b/PWGEM/Dilepton/TableProducer/Converters/trackConverter1.cxx @@ -32,12 +32,13 @@ struct trackConverter1 { void process(aod::EMPrimaryTracks_000 const& tracks) { for (const auto& track : tracks) { - track_001(track.collisionId(), - track.trackId(), - track.sign() / track.pt(), - track.eta(), - track.phi(), - track.trackBit()); + track_001( + // track.collisionId(), + // track.trackId(), + track.sign() / track.pt(), + track.eta(), + track.phi(), + track.trackBit()); } // end of track loop } }; diff --git a/PWGEM/Dilepton/TableProducer/associateMCinfoDilepton.cxx b/PWGEM/Dilepton/TableProducer/associateMCinfoDilepton.cxx index e60f9b54365..a9147840f9e 100644 --- a/PWGEM/Dilepton/TableProducer/associateMCinfoDilepton.cxx +++ b/PWGEM/Dilepton/TableProducer/associateMCinfoDilepton.cxx @@ -11,7 +11,7 @@ // // ======================== // -// This code produces reduced events for photon analyses. +// This code produces reduced mc info for dilepton analyses. // Please write to: daiki.sekihata@cern.ch #include "PWGEM/Dilepton/DataModel/dileptonTables.h" @@ -58,8 +58,8 @@ struct AssociateMCInfoDilepton { Produces emdummydata; Configurable n_dummy_loop{"n_dummy_loop", 0, "for loop runs over n times"}; - Configurable down_scaling_omega{"down_scaling_omega", 1.1, "down scaling factor to store omega"}; - Configurable down_scaling_phi{"down_scaling_phi", 1.1, "down scaling factor to store phi"}; + Configurable down_scaling_omega{"down_scaling_omega", 1.0, "down scaling factor to store omega"}; + Configurable down_scaling_phi{"down_scaling_phi", 1.0, "down scaling factor to store phi"}; Configurable min_eta_gen_primary{"min_eta_gen_primary", -1.5, "min eta to store generated information"}; // smearing is applied at analysis stage. set wider value. Configurable max_eta_gen_primary{"max_eta_gen_primary", +1.5, "max eta to store generated information"}; // smearing is applied at analysis stage. set wider value. Configurable min_eta_gen_primary_fwd{"min_eta_gen_primary_fwd", -6.0, "min eta to store generated information"}; // smearing is applied at analysis stage. set wider value. diff --git a/PWGEM/Dilepton/TableProducer/createEMEventDilepton.cxx b/PWGEM/Dilepton/TableProducer/createEMEventDilepton.cxx index 4c92285441c..d35815b69f3 100644 --- a/PWGEM/Dilepton/TableProducer/createEMEventDilepton.cxx +++ b/PWGEM/Dilepton/TableProducer/createEMEventDilepton.cxx @@ -299,7 +299,8 @@ struct AssociateDileptonToEMEvent { PresliceUnsorted perCollision_el = aod::emprimaryelectron::collisionId; PresliceUnsorted perCollision_mu = aod::emprimarymuon::collisionId; - Preslice perCollision_track = aod::emprimarytrack::collisionId; + // Preslice perCollision_track = aod::emprimarytrack::collisionId; + Preslice perCollision_track = aod::track::collisionId; void init(o2::framework::InitContext&) {} @@ -329,7 +330,7 @@ struct AssociateDileptonToEMEvent { fillEventId(collisions, tracks, prmmueventid, perCollision_mu); } - void processChargedTrack(aod::EMEvents const& collisions, aod::EMPrimaryTracks const& tracks) + void processChargedTrack(aod::EMEvents const& collisions, soa::Join const& tracks) { fillEventId(collisions, tracks, prmtrackeventid, perCollision_track); } diff --git a/PWGEM/Dilepton/TableProducer/skimmerPrimaryMFTTrack.cxx b/PWGEM/Dilepton/TableProducer/skimmerPrimaryMFTTrack.cxx index 77f8d6b692c..28055a15057 100644 --- a/PWGEM/Dilepton/TableProducer/skimmerPrimaryMFTTrack.cxx +++ b/PWGEM/Dilepton/TableProducer/skimmerPrimaryMFTTrack.cxx @@ -59,6 +59,7 @@ struct skimmerPrimaryMFTTrack { SliceCache cache; Preslice perCol = o2::aod::fwdtrack::collisionId; Produces emprimarytracks; + Produces prmtrackeventidtmp; // Configurables Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; @@ -231,7 +232,8 @@ struct skimmerPrimaryMFTTrack { trackBit |= static_cast(RefMFTTrackBit::kDCAxy001cm); } - emprimarytracks(collision.globalIndex(), mfttrack.globalIndex(), mfttrack.sign() / pt, eta, phi, trackBit); + emprimarytracks(/*collision.globalIndex(),*/ /*mfttrack.globalIndex(),*/ mfttrack.sign() / pt, eta, phi, trackBit); + prmtrackeventidtmp(collision.globalIndex()); if (fillQAHistogram) { fRegistry.fill(HIST("MFT/hPt"), pt); diff --git a/PWGEM/Dilepton/TableProducer/skimmerPrimaryMuon.cxx b/PWGEM/Dilepton/TableProducer/skimmerPrimaryMuon.cxx index 1cc19c0ff76..e8175f9b870 100644 --- a/PWGEM/Dilepton/TableProducer/skimmerPrimaryMuon.cxx +++ b/PWGEM/Dilepton/TableProducer/skimmerPrimaryMuon.cxx @@ -456,14 +456,15 @@ struct skimmerPrimaryMuon { emprimarymuons(collision.globalIndex(), fwdtrack.globalIndex(), fwdtrack.matchMFTTrackId(), fwdtrack.matchMCHTrackId(), fwdtrack.trackType(), pt, eta, phi, fwdtrack.sign(), dcaX, dcaY, cXX, cYY, cXY, ptMatchedMCHMID, etaMatchedMCHMID, phiMatchedMCHMID, - etaMatchedMCHMIDatMP, phiMatchedMCHMIDatMP, etaMatchedMFTatMP, phiMatchedMFTatMP, + // etaMatchedMCHMIDatMP, phiMatchedMCHMIDatMP, etaMatchedMFTatMP, phiMatchedMFTatMP, fwdtrack.nClusters(), pDCA, rAtAbsorberEnd, fwdtrack.chi2(), fwdtrack.chi2MatchMCHMID(), fwdtrack.chi2MatchMCHMFT(), fwdtrack.mchBitMap(), fwdtrack.midBitMap(), fwdtrack.midBoards(), mftClusterSizesAndTrackFlags, chi2mft, isAssociatedToMPC, isAmbiguous); const auto& fwdcov = propmuonAtPV.getCovariances(); // covatiance matrix at PV emprimarymuonscov( - fwdcov(0, 0), - fwdcov(0, 1), fwdcov(1, 1), + propmuonAtPV.getX(), propmuonAtPV.getY(), propmuonAtPV.getZ(), + // fwdcov(0, 0), + // fwdcov(0, 1), fwdcov(1, 1), fwdcov(2, 0), fwdcov(2, 1), fwdcov(2, 2), fwdcov(3, 0), fwdcov(3, 1), fwdcov(3, 2), fwdcov(3, 3), fwdcov(4, 0), fwdcov(4, 1), fwdcov(4, 2), fwdcov(4, 3), fwdcov(4, 4)); diff --git a/PWGEM/Dilepton/TableProducer/skimmerPrimaryTrack.cxx b/PWGEM/Dilepton/TableProducer/skimmerPrimaryTrack.cxx index 7dba6b78b36..2460adf58d5 100644 --- a/PWGEM/Dilepton/TableProducer/skimmerPrimaryTrack.cxx +++ b/PWGEM/Dilepton/TableProducer/skimmerPrimaryTrack.cxx @@ -45,19 +45,19 @@ using namespace o2::framework::expressions; using namespace o2::constants::physics; using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; -using MyCollisions = soa::Join; -using MyCollisionsWithSWT = soa::Join; +struct skimmerPrimaryTrack { + using MyCollisions = soa::Join; + using MyCollisionsWithSWT = soa::Join; -using MyTracks = soa::Join; -using MyTrack = MyTracks::iterator; -using MyTracksMC = soa::Join; -using MyTrackMC = MyTracksMC::iterator; + using MyTracks = soa::Join; + using MyTrack = MyTracks::iterator; + using MyTracksMC = soa::Join; + using MyTrackMC = MyTracksMC::iterator; -struct skimmerPrimaryTrack { SliceCache cache; Preslice perCol = o2::aod::track::collisionId; Produces emprimarytracks; - // Produces prmtrackeventidtmp; + Produces prmtrackeventidtmp; // Configurables Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; @@ -258,107 +258,102 @@ struct skimmerPrimaryTrack { template void fillTrackTable(TCollision const& collision, TTrack const& track) { - if (std::find(stored_trackIds.begin(), stored_trackIds.end(), std::pair{collision.globalIndex(), track.globalIndex()}) == stored_trackIds.end()) { - o2::dataformats::DCA mDcaInfoCov; - mDcaInfoCov.set(999, 999, 999, 999, 999); - auto trackParCov = getTrackParCov(track); - trackParCov.setPID(track.pidForTracking()); - mVtx.setPos({collision.posX(), collision.posY(), collision.posZ()}); - mVtx.setCov(collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()); - o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, trackParCov, 2.f, matCorr, &mDcaInfoCov); - float dcaXY = mDcaInfoCov.getY(); - float dcaZ = mDcaInfoCov.getZ(); - - float pt = trackParCov.getPt(); - float eta = trackParCov.getEta(); - float phi = trackParCov.getPhi(); - o2::math_utils::bringTo02Pi(phi); - uint16_t trackBit = 0; - - // As minimal cuts, following cuts are applied. The cut values are hardcoded on the purpose for consistent bit operation. - // has info on ITS and TPC - // a hit on ITSib any - // Ncls ITS >= 4 - // chi2/Ncls ITS < 36 - // Ncr TPC >= 50 - // chi2/Ncls TPC < 5 - // Ncr/Nf ratio in TPC > 0.8 - - if (track.itsNCls() >= 5) { - trackBit |= static_cast(RefTrackBit::kNclsITS5); - } - if (track.itsNCls() >= 6) { - trackBit |= static_cast(RefTrackBit::kNclsITS6); - } + o2::dataformats::DCA mDcaInfoCov; + mDcaInfoCov.set(999, 999, 999, 999, 999); + auto trackParCov = getTrackParCov(track); + trackParCov.setPID(track.pidForTracking()); + mVtx.setPos({collision.posX(), collision.posY(), collision.posZ()}); + mVtx.setCov(collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()); + o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, trackParCov, 2.f, matCorr, &mDcaInfoCov); + float dcaXY = mDcaInfoCov.getY(); + float dcaZ = mDcaInfoCov.getZ(); - if (track.tpcNClsCrossedRows() >= 70) { - trackBit |= static_cast(RefTrackBit::kNcrTPC70); - } - if (track.tpcNClsCrossedRows() >= 90) { - trackBit |= static_cast(RefTrackBit::kNcrTPC90); - } - if (track.tpcNClsFound() >= 50) { - trackBit |= static_cast(RefTrackBit::kNclsTPC50); - } - if (track.tpcNClsFound() >= 70) { - trackBit |= static_cast(RefTrackBit::kNclsTPC70); - } - if (track.tpcNClsFound() >= 90) { - trackBit |= static_cast(RefTrackBit::kNclsTPC90); - } - if (track.tpcChi2NCl() < 4.f) { - trackBit |= static_cast(RefTrackBit::kChi2TPC4); - } - if (track.tpcChi2NCl() < 3.f) { - trackBit |= static_cast(RefTrackBit::kChi2TPC3); - } - if (track.tpcFractionSharedCls() < 0.7) { - trackBit |= static_cast(RefTrackBit::kFracSharedTPC07); - } + float pt = trackParCov.getPt(); + float eta = trackParCov.getEta(); + float phi = trackParCov.getPhi(); + o2::math_utils::bringTo02Pi(phi); + uint16_t trackBit = 0; + + // As minimal cuts, following cuts are applied. The cut values are hardcoded on the purpose for consistent bit operation. + // has info on ITS and TPC + // a hit on ITSib any + // Ncls ITS >= 4 + // chi2/Ncls ITS < 36 + // Ncr TPC >= 50 + // chi2/Ncls TPC < 5 + // Ncr/Nf ratio in TPC > 0.8 + + if (track.itsNCls() >= 5) { + trackBit |= static_cast(RefTrackBit::kNclsITS5); + } + if (track.itsNCls() >= 6) { + trackBit |= static_cast(RefTrackBit::kNclsITS6); + } - if (std::fabs(dcaZ) < 0.5) { - trackBit |= static_cast(RefTrackBit::kDCAz05cm); - } - if (std::fabs(dcaZ) < 0.3) { - trackBit |= static_cast(RefTrackBit::kDCAz03cm); - } + if (track.tpcNClsCrossedRows() >= 70) { + trackBit |= static_cast(RefTrackBit::kNcrTPC70); + } + if (track.tpcNClsCrossedRows() >= 90) { + trackBit |= static_cast(RefTrackBit::kNcrTPC90); + } + if (track.tpcNClsFound() >= 50) { + trackBit |= static_cast(RefTrackBit::kNclsTPC50); + } + if (track.tpcNClsFound() >= 70) { + trackBit |= static_cast(RefTrackBit::kNclsTPC70); + } + if (track.tpcNClsFound() >= 90) { + trackBit |= static_cast(RefTrackBit::kNclsTPC90); + } + if (track.tpcChi2NCl() < 4.f) { + trackBit |= static_cast(RefTrackBit::kChi2TPC4); + } + if (track.tpcChi2NCl() < 3.f) { + trackBit |= static_cast(RefTrackBit::kChi2TPC3); + } + if (track.tpcFractionSharedCls() < 0.7) { + trackBit |= static_cast(RefTrackBit::kFracSharedTPC07); + } - if (std::fabs(dcaXY) < 0.5) { - trackBit |= static_cast(RefTrackBit::kDCAxy05cm); - } - if (std::fabs(dcaXY) < 0.3) { - trackBit |= static_cast(RefTrackBit::kDCAxy03cm); - } + if (std::fabs(dcaZ) < 0.5) { + trackBit |= static_cast(RefTrackBit::kDCAz05cm); + } + if (std::fabs(dcaZ) < 0.3) { + trackBit |= static_cast(RefTrackBit::kDCAz03cm); + } - emprimarytracks(collision.globalIndex(), track.globalIndex(), track.sign() / pt, eta, phi, trackBit); - // prmtrackeventidtmp(collision.globalIndex()); - - stored_trackIds.emplace_back(std::pair{collision.globalIndex(), track.globalIndex()}); - - if (fillQAHistogram) { - fRegistry.fill(HIST("Track/hPt"), pt); - fRegistry.fill(HIST("Track/hQoverPt"), track.sign() / pt); - fRegistry.fill(HIST("Track/hEtaPhi"), phi, eta); - fRegistry.fill(HIST("Track/hDCAxyz"), dcaXY, dcaZ); - fRegistry.fill(HIST("Track/hDCAxyzSigma"), dcaXY / std::sqrt(trackParCov.getSigmaY2()), dcaZ / std::sqrt(trackParCov.getSigmaZ2())); - fRegistry.fill(HIST("Track/hDCAxyRes_Pt"), pt, std::sqrt(trackParCov.getSigmaY2()) * 1e+4); // convert cm to um - fRegistry.fill(HIST("Track/hDCAzRes_Pt"), pt, std::sqrt(trackParCov.getSigmaZ2()) * 1e+4); // convert cm to um - fRegistry.fill(HIST("Track/hNclsITS"), track.itsNCls()); - fRegistry.fill(HIST("Track/hNclsTPC"), track.tpcNClsFound()); - fRegistry.fill(HIST("Track/hNcrTPC"), track.tpcNClsCrossedRows()); - fRegistry.fill(HIST("Track/hTPCNcr2Nf"), track.tpcCrossedRowsOverFindableCls()); - fRegistry.fill(HIST("Track/hTPCNcls2Nf"), track.tpcFoundOverFindableCls()); - fRegistry.fill(HIST("Track/hTPCNclsShared"), track.pt(), track.tpcFractionSharedCls()); - fRegistry.fill(HIST("Track/hChi2TPC"), track.tpcChi2NCl()); - fRegistry.fill(HIST("Track/hChi2ITS"), track.itsChi2NCl()); - fRegistry.fill(HIST("Track/hITSClusterMap"), track.itsClusterMap()); - fRegistry.fill(HIST("Track/hTPCdEdx"), track.tpcInnerParam(), track.tpcSignal()); - } + if (std::fabs(dcaXY) < 0.5) { + trackBit |= static_cast(RefTrackBit::kDCAxy05cm); + } + if (std::fabs(dcaXY) < 0.3) { + trackBit |= static_cast(RefTrackBit::kDCAxy03cm); + } + + emprimarytracks(/*collision.globalIndex(),*/ /*track.globalIndex(),*/ track.sign() / pt, eta, phi, trackBit); + prmtrackeventidtmp(collision.globalIndex()); + + if (fillQAHistogram) { + fRegistry.fill(HIST("Track/hPt"), pt); + fRegistry.fill(HIST("Track/hQoverPt"), track.sign() / pt); + fRegistry.fill(HIST("Track/hEtaPhi"), phi, eta); + fRegistry.fill(HIST("Track/hDCAxyz"), dcaXY, dcaZ); + fRegistry.fill(HIST("Track/hDCAxyzSigma"), dcaXY / std::sqrt(trackParCov.getSigmaY2()), dcaZ / std::sqrt(trackParCov.getSigmaZ2())); + fRegistry.fill(HIST("Track/hDCAxyRes_Pt"), pt, std::sqrt(trackParCov.getSigmaY2()) * 1e+4); // convert cm to um + fRegistry.fill(HIST("Track/hDCAzRes_Pt"), pt, std::sqrt(trackParCov.getSigmaZ2()) * 1e+4); // convert cm to um + fRegistry.fill(HIST("Track/hNclsITS"), track.itsNCls()); + fRegistry.fill(HIST("Track/hNclsTPC"), track.tpcNClsFound()); + fRegistry.fill(HIST("Track/hNcrTPC"), track.tpcNClsCrossedRows()); + fRegistry.fill(HIST("Track/hTPCNcr2Nf"), track.tpcCrossedRowsOverFindableCls()); + fRegistry.fill(HIST("Track/hTPCNcls2Nf"), track.tpcFoundOverFindableCls()); + fRegistry.fill(HIST("Track/hTPCNclsShared"), track.pt(), track.tpcFractionSharedCls()); + fRegistry.fill(HIST("Track/hChi2TPC"), track.tpcChi2NCl()); + fRegistry.fill(HIST("Track/hChi2ITS"), track.itsChi2NCl()); + fRegistry.fill(HIST("Track/hITSClusterMap"), track.itsClusterMap()); + fRegistry.fill(HIST("Track/hTPCdEdx"), track.tpcInnerParam(), track.tpcSignal()); } } Preslice trackIndicesPerCollision = aod::track_association::collisionId; - std::vector> stored_trackIds; Filter trackFilter = o2::aod::track::itsChi2NCl < 36.f && o2::aod::track::tpcChi2NCl < 5.f && ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) == true && ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::TPC) == true; using MyFilteredTracks = soa::Filtered; @@ -366,8 +361,6 @@ struct skimmerPrimaryTrack { void processRec(MyCollisions const& collisions, aod::BCsWithTimestamps const&, MyFilteredTracks const& tracks) { - stored_trackIds.reserve(tracks.size()); - for (const auto& collision : collisions) { auto bc = collision.template foundBC_as(); initCCDB(bc); @@ -387,16 +380,11 @@ struct skimmerPrimaryTrack { } } // end of collision loop - - stored_trackIds.clear(); - stored_trackIds.shrink_to_fit(); } PROCESS_SWITCH(skimmerPrimaryTrack, processRec, "process reconstructed info only", true); // standalone void processRec_SWT(MyCollisionsWithSWT const& collisions, aod::BCsWithTimestamps const&, MyFilteredTracks const& tracks) { - stored_trackIds.reserve(tracks.size()); - for (const auto& collision : collisions) { auto bc = collision.template foundBC_as(); initCCDB(bc); @@ -420,9 +408,6 @@ struct skimmerPrimaryTrack { } } // end of collision loop - - stored_trackIds.clear(); - stored_trackIds.shrink_to_fit(); } PROCESS_SWITCH(skimmerPrimaryTrack, processRec_SWT, "process reconstructed info only", false); // standalone with swt @@ -431,8 +416,6 @@ struct skimmerPrimaryTrack { using MyFilteredTracksMC = soa::Filtered; void processMC(soa::Join const& collisions, aod::McCollisions const&, aod::BCsWithTimestamps const&, MyFilteredTracksMC const& tracks) { - stored_trackIds.reserve(tracks.size()); - for (const auto& collision : collisions) { if (!collision.has_mcCollision()) { continue; @@ -455,9 +438,6 @@ struct skimmerPrimaryTrack { fillTrackTable(collision, track); } } // end of collision loop - - stored_trackIds.clear(); - stored_trackIds.shrink_to_fit(); } PROCESS_SWITCH(skimmerPrimaryTrack, processMC, "process reconstructed and MC info ", false); }; diff --git a/PWGEM/Dilepton/Utils/EMFwdTrack.h b/PWGEM/Dilepton/Utils/EMFwdTrack.h index 7f59bb67a1d..510aa5f3533 100644 --- a/PWGEM/Dilepton/Utils/EMFwdTrack.h +++ b/PWGEM/Dilepton/Utils/EMFwdTrack.h @@ -51,9 +51,9 @@ class EMFwdTrack float e() const { return std::hypot(fPt * std::cosh(fEta), fMass); } // e2 = p2 + m2 float signed1Pt() const { return fCharge * 1.f / fPt; } - float cXXatDCA() const { return fCXX; } - float cXYatDCA() const { return fCXY; } - float cYYatDCA() const { return fCYY; } + float cXX() const { return fCXX; } + float cXY() const { return fCXY; } + float cYY() const { return fCYY; } protected: float fPt; @@ -68,5 +68,73 @@ class EMFwdTrack float fCYY; }; +class EMFwdTrackWithCov : public EMFwdTrack +{ + public: + EMFwdTrackWithCov(float pt, float eta, float phi, float mass, int8_t charge, float dcaX, float dcaY, float cXX, float cXY, float cYY, + float X = 0.f, float Y = 0.f, float Z = 0.f, float tgl = 0.f, + float cPhiX = 0.f, float cPhiY = 0.f, float cPhiPhi = 0.f, + float cTglX = 0.f, float cTglY = 0.f, float cTglPhi = 0.f, float cTglTgl = 0.f, + float c1PtX = 0.f, float c1PtY = 0.f, float c1PtPhi = 0.f, float c1PtTgl = 0.f, float c1Pt21Pt2 = 0.f, float chi2 = 0.f) : EMFwdTrack(pt, eta, phi, mass, charge, dcaX, dcaY, cXX, cXY, cYY) + { + fX = X; + fY = Y; + fZ = Z; + fTgl = tgl; + fCPhiX = cPhiX; + fCPhiY = cPhiY; + fCPhiPhi = cPhiPhi; + fCTglX = cTglX; + fCTglY = cTglY; + fCTglPhi = cTglPhi; + fCTglTgl = cTglTgl; + fC1PtX = c1PtX; + fC1PtY = c1PtY; + fC1PtPhi = c1PtPhi; + fC1PtTgl = c1PtTgl; + fC1Pt21Pt2 = c1Pt21Pt2; + fChi2 = chi2; + } + + ~EMFwdTrackWithCov() {} + + float x() const { return fX; } + float y() const { return fY; } + float z() const { return fZ; } + float tgl() const { return fTgl; } + float cPhiX() const { return fCPhiX; } + float cPhiY() const { return fCPhiY; } + float cPhiPhi() const { return fCPhiPhi; } + float cTglX() const { return fCTglX; } + float cTglY() const { return fCTglY; } + float cTglPhi() const { return fCTglPhi; } + float cTglTgl() const { return fCTglTgl; } + float c1PtX() const { return fC1PtX; } + float c1PtY() const { return fC1PtY; } + float c1PtPhi() const { return fC1PtPhi; } + float c1PtTgl() const { return fC1PtTgl; } + float c1Pt21Pt2() const { return fC1Pt21Pt2; } + float chi2() const { return fChi2; } + + protected: + float fX; + float fY; + float fZ; + float fTgl; + float fCPhiX; + float fCPhiY; + float fCPhiPhi; + float fCTglX; + float fCTglY; + float fCTglPhi; + float fCTglTgl; + float fC1PtX; + float fC1PtY; + float fC1PtPhi; + float fC1PtTgl; + float fC1Pt21Pt2; + float fChi2; // chi2 not chi2/ndf +}; + } // namespace o2::aod::pwgem::dilepton::utils #endif // PWGEM_DILEPTON_UTILS_EMFWDTRACK_H_ diff --git a/PWGEM/Dilepton/Utils/EMTrack.h b/PWGEM/Dilepton/Utils/EMTrack.h index d50e9d1fe2c..1ac2f442f7e 100644 --- a/PWGEM/Dilepton/Utils/EMTrack.h +++ b/PWGEM/Dilepton/Utils/EMTrack.h @@ -75,11 +75,11 @@ class EMTrackWithCov : public EMTrack { public: EMTrackWithCov(float pt, float eta, float phi, float mass, int8_t charge = 0, float dcaXY = 0.f, float dcaZ = 0.f, - float X = 0.f, float Y = 0.f, float Z = 0.f, float Alpha = 0.f, float Snp = 0.f, float Tgl = 0.f, float CYY = 0.f, float CZY = 0.f, float CZZ = 0.f, + float X = 0.f, float Y = 0.f, float Z = 0.f, float Alpha = 0.f, float Snp = 0.f, float Tgl = 0.f, float CSnpY = 0.f, float CSnpZ = 0.f, float CSnpSnp = 0.f, float CTglY = 0.f, float CTglZ = 0.f, float CTglSnp = 0.f, float CTglTgl = 0.f, - float C1PtY = 0.f, float C1PtZ = 0.f, float C1PtSnp = 0.f, float C1PtTgl = 0.f, float C1Pt21Pt2 = 0.f) : EMTrack(pt, eta, phi, mass, charge, dcaXY, dcaZ) + float C1PtY = 0.f, float C1PtZ = 0.f, float C1PtSnp = 0.f, float C1PtTgl = 0.f, float C1Pt21Pt2 = 0.f) : EMTrack(pt, eta, phi, mass, charge, dcaXY, dcaZ, CYY, CZY, CZZ) { fX = X; fY = Y; diff --git a/PWGEM/Dilepton/Utils/EMTrackUtilities.h b/PWGEM/Dilepton/Utils/EMTrackUtilities.h index 414a7735bd4..d5a42a1b4bf 100644 --- a/PWGEM/Dilepton/Utils/EMTrackUtilities.h +++ b/PWGEM/Dilepton/Utils/EMTrackUtilities.h @@ -97,9 +97,9 @@ float dcaZinSigma(T const& track) template float fwdDcaXYinSigma(T const& track) { - float cXX = track.cXXatDCA(); // in cm^2 - float cYY = track.cYYatDCA(); // in cm^2 - float cXY = track.cXYatDCA(); // in cm^2 + float cXX = track.cXX(); // in cm^2 + float cYY = track.cYY(); // in cm^2 + float cXY = track.cXY(); // in cm^2 float dcaX = track.fwdDcaX(); // in cm float dcaY = track.fwdDcaY(); // in cm float det = cXX * cYY - cXY * cXY; // determinant diff --git a/PWGEM/PhotonMeson/TableProducer/createEMEventPhoton.cxx b/PWGEM/PhotonMeson/TableProducer/createEMEventPhoton.cxx index 2c87cc3431d..0081bf67244 100644 --- a/PWGEM/PhotonMeson/TableProducer/createEMEventPhoton.cxx +++ b/PWGEM/PhotonMeson/TableProducer/createEMEventPhoton.cxx @@ -362,13 +362,13 @@ struct AssociatePhotonToEMEvent { Produces prmeleventid; Produces phoseventid; Produces emceventid; - Produces prmtrackeventid; + // Produces prmtrackeventid; Preslice perCollisionPCM = aod::v0photonkf::collisionId; PresliceUnsorted perCollisionEl = aod::emprimaryelectron::collisionId; Preslice perCollisionPHOS = aod::skimmedcluster::collisionId; Preslice perCollisionEMC = aod::skimmedcluster::collisionId; - Preslice perCollision_track = aod::emprimarytrack::collisionId; + // Preslice perCollision_track = aod::emprimarytrack::collisionId; void init(o2::framework::InitContext&) {} From cdb3dfdd12933a42487a84fa71f566f5740e21a9 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Sat, 28 Feb 2026 21:31:32 +0100 Subject: [PATCH 118/347] [PWGHF] Add D0+gamma in charm reso data creator (#15205) Co-authored-by: ALICE Action Bot --- PWGHF/D2H/Core/DataCreationCharmReso.h | 327 +++++++++++++++++- PWGHF/D2H/TableProducer/CMakeLists.txt | 6 +- .../dataCreatorCharmResoToD0Reduced.cxx | 64 +++- .../dataCreatorCharmResoToDplusReduced.cxx | 24 +- .../dataCreatorCharmResoToDstarReduced.cxx | 24 +- 5 files changed, 404 insertions(+), 41 deletions(-) diff --git a/PWGHF/D2H/Core/DataCreationCharmReso.h b/PWGHF/D2H/Core/DataCreationCharmReso.h index 3914b37c283..df88ca05069 100644 --- a/PWGHF/D2H/Core/DataCreationCharmReso.h +++ b/PWGHF/D2H/Core/DataCreationCharmReso.h @@ -18,6 +18,13 @@ #ifndef PWGHF_D2H_CORE_DATACREATIONCHARMRESO_H_ #define PWGHF_D2H_CORE_DATACREATIONCHARMRESO_H_ +#ifndef HomogeneousField +#define HomogeneousField // needed for KFParticle::SetField(magneticField); +#endif + +#include "PWGEM/Dilepton/Utils/PairUtilities.h" +#include "PWGEM/PhotonMeson/Utils/PCMUtilities.h" +#include "PWGEM/PhotonMeson/Utils/TrackSelection.h" #include "PWGHF/Core/CentralityEstimation.h" #include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" @@ -25,7 +32,9 @@ #include "PWGHF/Utils/utilsMcMatching.h" #include "Common/Core/RecoDecay.h" +#include "Common/Core/TPCVDriftManager.h" #include "Common/Core/trackUtilities.h" +#include "Tools/KFparticle/KFUtilities.h" #include #include @@ -39,6 +48,10 @@ #include #include +#include +#include +#include + #include #include @@ -69,6 +82,7 @@ enum BachelorType : uint8_t { Lambda, AntiLambda, Track, + Gamma, NBachelorTypes }; @@ -83,6 +97,7 @@ enum PairingType : uint8_t { V0Only, TrackOnly, V0AndTrack, + GammaOnly, NPairingType }; @@ -110,6 +125,7 @@ struct HfResoCandidateV0 { float dcaV0ToPv = 1000.f; float dcaDau = 1000.f; float alpha = -1.f; + float qt = -1.f; float eta = -999.f; float radius = 0.f; float mK0Short = 0.f; @@ -123,6 +139,7 @@ struct HfResoVarContainer { float invMassD0 = 0.f; float invMassD0Bar = 0.f; float invMassReso = 0.f; + float invMassResoBar = 0.f; float ptReso = -1.f; int8_t signD = 0; std::array pVectorProng0 = {0.f, 0.f, 0.f}; @@ -150,6 +167,31 @@ struct HfResoConfigV0Cuts : o2::framework::ConfigurableGroup { o2::framework::Configurable propagateV0toPV{"propagateV0toPV", false, "Enable or disable V0 propagation to V0"}; }; +struct HfResoConfigGammaCuts : o2::framework::ConfigurableGroup { + std::string prefix = "gammas"; // JSON group name + o2::framework::Configurable etaMax{"etaMax", 0.8f, "maximum eta"}; + o2::framework::Configurable ptMin{"ptMin", 0.1f, "minimum pT"}; + o2::framework::Configurable ptMaxItsOnly{"ptMaxItsOnly", 0.3f, "maximum pT for ITS-only gammas"}; + o2::framework::Configurable etaMaxDau{"etaMaxDau", 1.f, "maximum eta gamma daughters"}; + o2::framework::Configurable trackNclusItsCut{"trackNclusItsCut", 0, "Minimum number of ITS clusters for gamma daughter"}; + o2::framework::Configurable trackNCrossedRowsTpc{"trackNCrossedRowsTpc", 50, "Minimum TPC crossed rows"}; + o2::framework::Configurable trackNsharedClusTpc{"trackNsharedClusTpc", 1000, "Maximum number of shared TPC clusters for gamma daughter"}; + o2::framework::Configurable trackFracMaxindableTpcCls{"trackFracMaxindableTpcCls", 0.8f, "Maximum fraction of findable TPC clusters for gamma daughter"}; + o2::framework::Configurable dcaDauIts{"dcaDauIts", 0.5f, "maximum DCA gamma daughters (ITS)"}; + o2::framework::Configurable dcaDauItsIb{"dcaDauItsIb", 1.0f, "maximum DCA gamma daughters (ITS IB)"}; + o2::framework::Configurable dcaDauTpc{"dcaDauTpc", 0.5f, "maximum DCA gamma daughters (TPC)"}; + o2::framework::Configurable dcaDauTpcInner{"dcaDauTpcInner", 1.0f, "maximum DCA gamma daughters (TPC inner)"}; + o2::framework::Configurable dcaMaxDauToPv{"dcaMaxDauToPv", 0.1f, "Maximum gamma daughter's DCA to PV"}; + o2::framework::Configurable dcaPv{"dcaPv", 1.f, "DCA gamma to PV"}; + o2::framework::Configurable cosPa{"cosPa", 0.99f, "gamma CosPA"}; + o2::framework::Configurable radiusMin{"radiusMin", 1.0f, "Minimum gamma radius accepted"}; + o2::framework::Configurable radiusMax{"radiusMax", 90.f, "Maximum gamma radius accepted"}; + o2::framework::Configurable alphaApMax{"alphaApMax", 0.95f, "Maximum alpha AP"}; + o2::framework::Configurable qtApMax{"qtApMax", 0.01f, "Maximum qt AP"}; + o2::framework::Configurable nSigmaTpcEl{"nSigmaTpcEl", 4.f, "N sigma TPC for electrons"}; + o2::framework::Configurable propagateGammatoPV{"propagateGammatoPV", false, "Enable or disable V0 propagation to V0"}; +}; + struct HfResoConfigSingleTrackCuts : o2::framework::ConfigurableGroup { std::string prefix = "singleTracks"; // JSON group name o2::framework::Configurable setTrackSelections{"setTrackSelections", 2, "flag to apply track selections: 0=none; 1=global track w/o DCA selection; 2=global track; 3=only ITS quality"}; @@ -198,10 +240,16 @@ void addHistograms(o2::framework::HistogramRegistry& registry) const o2::framework::AxisSpec axisDeltaMassToPi{500, 0.13, 1.13, "inv. mass (GeV/#it{c}^{2})"}; const o2::framework::AxisSpec axisDeltaMassToPr{500, 0.93, 1.93, "inv. mass (GeV/#it{c}^{2})"}; const o2::framework::AxisSpec axisDeltaMassToLambda{500, 1.05, 2.05, "inv. mass (GeV/#it{c}^{2})"}; + const o2::framework::AxisSpec axisDeltaMassToGamma{500, 0., 0.25, "inv. mass (GeV/#it{c}^{2})"}; const o2::framework::AxisSpec axisMassDsj{400, 0.49f, 0.89f, ""}; // Ds1 and Ds2Star legacy + const o2::framework::AxisSpec axisAlpha{100, -1.f, 1.f}; + const o2::framework::AxisSpec axisQt{100, 0.f, 0.25f}; + const o2::framework::AxisSpec axisRadius{450, 0.f, 90.f}; registry.add("hMassVsPtK0s", "K0^{s} candidates;#it{p}_{T} (GeV/#it{c});inv. mass (#pi^{#plus}#pi^{#minus}) (GeV/#it{c}^{2});entries", {o2::framework::HistType::kTH2D, {axisPt, axisMassKzero}}); registry.add("hMassVsPtLambda", "Lambda candidates;#it{p}_{T} (GeV/#it{c});inv. mass (p #pi^{#minus}) (GeV/#it{c}^{2});entries", {o2::framework::HistType::kTH2D, {axisPt, axisMassLambda}}); + registry.add("hAP", "Aremnteros-Podolanski plot for V0 candidates;#it{#alpha};#it{q}_{T} (GeV/#it{c});entries", {o2::framework::HistType::kTH2D, {axisAlpha, axisQt}}); + registry.add("hRadius", "Radius of V0 candidates;#it{R} (cm);entries", {o2::framework::HistType::kTH1D, {axisRadius}}); registry.add("hdEdxVsP", "Tracks;#it{p} (GeV/#it{c});d#it{E}/d#it{x};entries", {o2::framework::HistType::kTH2D, {axisP, axisDeDx}}); if constexpr (DType == DMesonType::D0) { @@ -214,6 +262,7 @@ void addHistograms(o2::framework::HistogramRegistry& registry) registry.add("hMassD0K", "D0Kplus candidates; m_{D^{0}K^{+}} - m_{D^{0}} (GeV/#it{c}^{2});entries", {o2::framework::HistType::kTH2D, {axisPt, axisDeltaMassToK}}); registry.add("hMassD0Proton", "D0Proton candidates; m_{D^{0}p} - m_{D^{0}} (GeV/#it{c}^{2});entries", {o2::framework::HistType::kTH2D, {axisPt, axisDeltaMassToPr}}); registry.add("hMassD0Lambda", "D0Lambda candidates; m_{D^{0}#Lambda} - m_{D^{0}} (GeV/#it{c}^{2});entries", {o2::framework::HistType::kTH2D, {axisPt, axisDeltaMassToLambda}}); + registry.add("hMassD0Gamma", "D0Gamma candidates; m_{D^{0}#gamma} - m_{D^{0}} (GeV/#it{c}^{2});entries", {o2::framework::HistType::kTH2D, {axisPt, axisDeltaMassToGamma}}); } else if constexpr (DType == DMesonType::Dplus) { const o2::framework::AxisSpec axisMassDplus{200, 1.7f, 2.1f, "inv. mass (GeV/#it{c}^{2})"}; registry.add("hMassVsPtDplusAll", "Dplus candidates (all, regardless the pairing with V0s);#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {o2::framework::HistType::kTH2D, {axisPt, axisMassDplus}}); @@ -292,6 +341,18 @@ float alphaAP(std::array const& momV0, std::array const& mom return (lQlPos - lQlNeg) / (lQlPos + lQlNeg); } +/// Utility to compute qT +/// \param momDau0 is the momentum of first daughter +/// \param momDau1 is the momentum of second daughter +/// \return qtAP +//_______________________________________________________________________ +inline float qtAP(std::array const& momDau0, std::array const& momDau1) +{ + float momTot = RecoDecay::p2(momDau0[0] + momDau1[0], momDau0[1] + momDau1[1], momDau0[2] + momDau1[2]); + float dp = RecoDecay::dotProd(std::array{momDau1[0], momDau1[1], momDau1[2]}, std::array{momDau0[0] + momDau1[0], momDau0[1] + momDau1[1], momDau0[2] + momDau1[2]}); + return std::sqrt(RecoDecay::p2(momDau1[0], momDau1[1], momDau1[2]) - dp * dp / momTot); // qt of v0 +} + /// Utility to find DCA of V0 to Primary vertex /// \param x is the x-coordinate /// \param y is the y-coordinate @@ -397,6 +458,7 @@ bool buildAndSelectV0(const Coll& collision, const std::array& dDaughter v0.v0Type = {BIT(BachelorType::K0s) | BIT(BachelorType::Lambda) | BIT(BachelorType::AntiLambda)}; // for lambda hypotesys define if its lambda or anti-lambda v0.alpha = alphaAP(v0.mom, v0.momPos, v0.momNeg); + v0.qt = qtAP(v0.momPos, v0.momNeg); bool const matter = v0.alpha > 0; CLRBIT(v0.v0Type, matter ? BachelorType::AntiLambda : BachelorType::Lambda); auto massPos = matter ? o2::constants::physics::MassProton : o2::constants::physics::MassPionCharged; @@ -438,6 +500,195 @@ bool buildAndSelectV0(const Coll& collision, const std::array& dDaughter return true; } +/// Basic selection of V0 candidates +/// \param collision is the current collision +/// \param dauTracks are the v0 daughter tracks +/// \param dDaughtersIds are the IDs of the D meson daughter tracks +/// \param cfgV0Cuts are the cuts to be applied to the V0 +/// \param v0 is the V0 candidate +/// \param matCorr is the material correction type to be used in the track propagation +/// \param bz is the magnetic field +/// \param vDriftMgr is the TPC velocity drift manager +/// \param rejectPairsWithCommonDaughter is a flag to activate rejection of pairs sharing a daughter track +/// \return a bitmap with mass hypotesis if passes all cuts +template +bool buildAndSelectGamma(const Coll& collision, const std::array& dDaughtersIds, const std::array& dauTracks, const Cuts& cfgGammaCuts, HfResoCandidateV0& v0, o2::base::Propagator::MatCorrType const& matCorr, o2::aod::common::TPCVDriftManager* vDriftMgr, bool rejectPairsWithCommonDaughter) +{ + const auto& trackPos = dauTracks[0]; + const auto& trackNeg = dauTracks[1]; + if (trackPos.sign() * trackNeg.sign() > 0) { // reject same sign pair + return false; + } + if (trackPos.globalIndex() == trackNeg.globalIndex()) { + return false; + } + if (o2::pwgem::photonmeson::isITSonlyTrack(trackPos) && !trackNeg.hasITS()) { + return false; + } + if (o2::pwgem::photonmeson::isITSonlyTrack(trackNeg) && !trackPos.hasITS()) { + return false; + } + + // single-tracks selection + if (!selectV0Daughter(trackPos, dDaughtersIds, cfgGammaCuts, rejectPairsWithCommonDaughter) || !selectV0Daughter(trackNeg, dDaughtersIds, cfgGammaCuts, rejectPairsWithCommonDaughter)) { + return false; + } + if ((trackPos.hasTPC() && std::abs(trackPos.tpcNSigmaEl()) > cfgGammaCuts.nSigmaTpcEl.value) || (trackNeg.hasTPC() && std::abs(trackNeg.tpcNSigmaEl()) > cfgGammaCuts.nSigmaTpcEl.value)) { + return false; + } + + std::array dcaInfo; + auto trackParPos = getTrackParCov(trackPos); + if (o2::pwgem::photonmeson::isTPConlyTrack(trackPos) && !vDriftMgr->moveTPCTrack(collision, trackPos, trackParPos)) { + LOGP(error, "failed correction for positive tpc track"); + return false; + } + auto trackParPropPos = trackParPos; + trackParPropPos.setPID(o2::track::PID::Electron); + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, trackParPropPos, 2.f, matCorr, &dcaInfo); + auto trackPosDcaXY = dcaInfo[0]; + + auto trackParNeg = getTrackParCov(trackNeg); + if (o2::pwgem::photonmeson::isTPConlyTrack(trackNeg) && !vDriftMgr->moveTPCTrack(collision, trackNeg, trackParNeg)) { + LOGP(error, "failed correction for negative tpc track"); + return false; + } + auto trackParPropNeg = trackParNeg; + trackParPropNeg.setPID(o2::track::PID::Electron); + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, trackParPropNeg, 2.f, matCorr, &dcaInfo); + auto trackNegDcaXY = dcaInfo[0]; + + // daughters DCA to V0's collision primary vertex + if (std::fabs(trackPosDcaXY) < cfgGammaCuts.dcaMaxDauToPv.value || std::fabs(trackNegDcaXY) < cfgGammaCuts.dcaMaxDauToPv.value) { + return false; + } + + float gammaVtx[3] = {0.f, 0.f, 0.f}; + Vtx_recalculationParCov(o2::base::Propagator::Instance(), trackParPropPos, trackParPropNeg, gammaVtx, matCorr); + float radiusXy = std::hypot(gammaVtx[0], gammaVtx[1]); + const float maxX{83.1f}; // max X for track IU + const float marginTpc{7.f}; // margin for r cut in cm + if (radiusXy > maxX + marginTpc) { + return false; + } + if (radiusXy < std::fabs(gammaVtx[2]) * std::tan(2 * std::atan(std::exp(-cfgGammaCuts.etaMax.value))) - marginTpc) { + return false; // RZ line cut + } + + // vertex reconstruction + KFPTrack kfpTrackPos = createKFPTrackFromTrackParCov(trackParPropPos, trackPos.sign(), trackPos.tpcNClsFound(), trackPos.tpcChi2NCl()); + KFPTrack kfpTrackNeg = createKFPTrackFromTrackParCov(trackParPropNeg, trackNeg.sign(), trackNeg.tpcNClsFound(), trackNeg.tpcChi2NCl()); + KFParticle kfPartPos(kfpTrackPos, kPositron); + KFParticle kfPartNeg(kfpTrackNeg, kElectron); + const KFParticle* gammaDaughters[2] = {&kfPartPos, &kfPartNeg}; + + KFParticle gamma; + gamma.SetConstructMethod(2); + gamma.Construct(gammaDaughters, 2); + KFPVertex kfpVertex = createKFPVertexFromCollision(collision); + KFParticle KFPV(kfpVertex); + + // Transport the gamma to the recalculated decay vertex + KFParticle gammaDecayVtx = gamma; // with respect to (0,0,0) + gammaDecayVtx.TransportToPoint(gammaVtx); + v0.cosPA = cpaFromKF(gammaDecayVtx, KFPV); + if (v0.cosPA < cfgGammaCuts.cosPa.value) { + return false; + } + + v0.pos = {gammaDecayVtx.GetX(), gammaDecayVtx.GetY(), gammaDecayVtx.GetZ()}; + v0.radius = std::hypot(gammaDecayVtx.GetX(), gammaDecayVtx.GetY()); + if (v0.radius > maxX + marginTpc) { + return false; + } + if (v0.radius < std::fabs(gammaDecayVtx.GetZ()) * std::tan(2 * std::atan(std::exp(-cfgGammaCuts.etaMax.value))) - marginTpc) { + return false; // RZ line cut + } + if (v0.radius < cfgGammaCuts.radiusMin.value || cfgGammaCuts.radiusMax.value < v0.radius) { + return false; + } + + const float minRadTpcOnly{16.f}; + if ((!trackNeg.hasITS() && !trackNeg.hasITS()) && v0.radius < minRadTpcOnly) { // TPConly tracks can detect conversion points larger than minRadTpcOnly. + return false; + } + + // Apply a topological constraint of the gamma to the PV. Parameters will be given at the primary vertex. + KFParticle gammaPvConstr = gamma; + gammaPvConstr.SetProductionVertex(KFPV); + v0.mom = RecoDecay::pVec(std::array{gammaPvConstr.GetPx(), gammaPvConstr.GetPy(), gammaPvConstr.GetPz()}); + v0.pT = std::hypot(v0.mom[0], v0.mom[1]); + if (v0.pT < cfgGammaCuts.ptMin.value) { + return false; + } + if (o2::pwgem::photonmeson::isITSonlyTrack(trackNeg) && o2::pwgem::photonmeson::isITSonlyTrack(trackPos) && v0.pT > cfgGammaCuts.ptMaxItsOnly.value) { + return false; + } + v0.eta = RecoDecay::eta(v0.mom); + if (std::abs(v0.eta) > cfgGammaCuts.etaMax.value) { + return false; + } + + KFParticle kfPartDecayVtxPos = kfPartPos; // Don't set Primary Vertex + KFParticle kfPartDecayVtxNeg = kfPartNeg; // Don't set Primary Vertex + kfPartDecayVtxPos.TransportToPoint(gammaVtx); // Don't set Primary Vertex + kfPartDecayVtxNeg.TransportToPoint(gammaVtx); // Don't set Primary Vertex + v0.dcaDau = kfPartDecayVtxPos.GetDistanceFromParticle(kfPartDecayVtxNeg); + v0.momPos = RecoDecay::pVec(std::array{kfPartDecayVtxPos.GetPx(), kfPartDecayVtxPos.GetPy(), kfPartDecayVtxPos.GetPz()}); + v0.momNeg = RecoDecay::pVec(std::array{kfPartDecayVtxNeg.GetPx(), kfPartDecayVtxNeg.GetPy(), kfPartDecayVtxNeg.GetPz()}); + float ptItsOnlyMax{0.15f}; + if (o2::pwgem::photonmeson::isITSonlyTrack(trackPos) && std::hypot(v0.momPos[0], v0.momPos[1]) > ptItsOnlyMax) { + return false; + } + if (o2::pwgem::photonmeson::isITSonlyTrack(trackNeg) && std::hypot(v0.momNeg[0], v0.momNeg[1]) > ptItsOnlyMax) { + return false; + } + + const float maxRItsMft{66.f}; + if (!trackNeg.hasITS() && !trackPos.hasITS()) { // V0s with TPConly-TPConly + if (maxRItsMft < v0.radius && v0.radius < maxX + marginTpc) { + if (v0.dcaDau > cfgGammaCuts.dcaDauTpcInner.value) { + return false; + } + } else { + if (v0.dcaDau > cfgGammaCuts.dcaDauTpc.value) { + return false; + } + } + } else { // V0s with ITS hits + if (v0.radius < minRadTpcOnly) { + if (v0.dcaDau > cfgGammaCuts.dcaDauItsIb.value) { + return false; + } + } else { + if (v0.dcaDau > cfgGammaCuts.dcaDauIts.value) { + return false; + } + } + } + + // v0 DCA to primary vertex + v0.dcaV0ToPv = calculateDCAStraightToPV( + v0.pos[0], v0.pos[1], v0.pos[2], + v0.momPos[0] + v0.momNeg[0], + v0.momPos[1] + v0.momNeg[1], + v0.momPos[2] + v0.momNeg[2], + collision.posX(), collision.posY(), collision.posZ()); + if (std::abs(v0.dcaV0ToPv) > cfgGammaCuts.dcaPv.value) { + return false; + } + + // distinguish V0 hypotheses + v0.alpha = alphaAP(v0.mom, v0.momPos, v0.momNeg); + v0.qt = qtAP(v0.momPos, v0.momNeg); + ; + if (!checkAP(v0.alpha, v0.qt, cfgGammaCuts.alphaApMax.value, cfgGammaCuts.qtApMax.value)) { // store only photon conversions + return false; + } + v0.v0Type = BIT(BachelorType::Gamma); + return true; +} + /// Basic selection of tracks /// \param track is the track /// \param dDaughtersIds are the IDs of the D meson daughter tracks @@ -945,6 +1196,7 @@ void fillMcRecoInfoDTrack(PParticles const& particlesMc, /// \param tracksIU is the trackIU table /// \param particlesMc is the MC particle table /// \param hfRejMap is the event rejection map from the HF event selection util +/// \param bz is the magnetic field /// \param pdg is the O2DatabasePDG service /// \param registry is the histogram registry /// \param matCorr is the material correction type to be used in the track propagation @@ -957,7 +1209,8 @@ void fillMcRecoInfoDTrack(PParticles const& particlesMc, /// \param rowMcRecV0Reduced is the MC reco D-V0 reduced table to be filled /// \param rowMcRecTrkReduced is the MC reco D-track reduced table to be filled /// \param rowCandDmesMlReduced is the ML reduced table to be filled -template +/// \param vDriftMgr is the TPC velocity drift manager object +template void runDataCreation(Coll const& collision, CCands const& candsD, BBachV0s const& bachelorV0s, @@ -974,6 +1227,7 @@ void runDataCreation(Coll const& collision, DmesCuts const& cfgDmesCuts, TrkCuts const& cfgSingleTrackCuts, V0Cuts const& cfgV0Cuts, + GammaCuts const& cfgGammaCuts, QaConfig const& cfgQaPlots, bool rejectPairsWithCommonDaughter, TableCollRed& rowCollisionReduced, @@ -982,16 +1236,19 @@ void runDataCreation(Coll const& collision, TableTrkRed& rowTrkReduced, TableMcRecV0Red& rowMcRecV0Reduced, TableMcRecTrkRed& rowMcRecTrkReduced, - TableCandDMlRed& rowCandDmesMlReduced) + TableCandDMlRed& rowCandDmesMlReduced, + o2::aod::common::TPCVDriftManager* vDriftMgr = nullptr) { int const indexHfReducedCollision = rowCollisionReduced.lastIndex() + 1; // std::map where the key is the V0.globalIndex() and // the value is the V0 index in the table of the selected v0s std::map selectedV0s; std::map selectedTracks; + std::map selectedGammas; bool fillHfReducedCollision = false; constexpr bool DoTracks = PairType == PairingType::TrackOnly || PairType == PairingType::V0AndTrack; constexpr bool DoV0s = PairType == PairingType::V0Only || PairType == PairingType::V0AndTrack; + constexpr bool DoGammas = PairType == PairingType::GammaOnly; // loop on D candidates for (const auto& candD : candsD) { // initialize variables depending on D meson type @@ -1131,6 +1388,8 @@ void runDataCreation(Coll const& collision, getPxPyPz(trackParK0, candV0.mom); } // compute resonance invariant mass and filling of QA histograms + registry.fill(HIST("hAP"), candV0.alpha, candV0.qt); + registry.fill(HIST("hV0Radius"), candV0.radius); if (TESTBIT(candV0.v0Type, BachelorType::K0s)) { registry.fill(HIST("hMassVsPtK0s"), candV0.pT, candV0.mK0Short); if constexpr (DType == DMesonType::Dstar) { @@ -1416,6 +1675,70 @@ void runDataCreation(Coll const& collision, } } // end of loop on bachelor tracks } // end of do tracks + if constexpr (DoGammas) { + for (const auto& gamma : bachelorV0s) { + auto trackPos = tracksIU.rawIteratorAt(gamma.posTrackId()); + auto trackNeg = tracksIU.rawIteratorAt(gamma.negTrackId()); + // Apply selsection + auto gammaDauTracks = std::array{trackPos, trackNeg}; + HfResoCandidateV0 candGamma; + if (!buildAndSelectGamma(collision, prongIdsD, gammaDauTracks, cfgGammaCuts, candGamma, matCorr, vDriftMgr, rejectPairsWithCommonDaughter)) { + continue; + } + // Get single track variables + float chi2TpcDauGammaMax = -1.f; + int nItsClsDauGammaMin = 8, nTpcCrossRowsDauGammaMin = 200; + for (const auto& gammaTrack : gammaDauTracks) { + if (gammaTrack.itsNCls() < nItsClsDauGammaMin) { + nItsClsDauGammaMin = gammaTrack.itsNCls(); + } + if (gammaTrack.tpcNClsCrossedRows() < nTpcCrossRowsDauGammaMin) { + nTpcCrossRowsDauGammaMin = gammaTrack.tpcNClsCrossedRows(); + } + if (gammaTrack.tpcChi2NCl() > chi2TpcDauGammaMax) { + chi2TpcDauGammaMax = gammaTrack.tpcChi2NCl(); + } + } + // propagate gamma to primary vertex (if enabled) + if (cfgGammaCuts.propagateGammatoPV.value) { + std::array const pVecGammaOrig = {candGamma.mom[0], candGamma.mom[1], candGamma.mom[2]}; + std::array dcaInfo{}; + auto trackParGamma = o2::track::TrackPar(candGamma.pos, pVecGammaOrig, 0, true); + trackParGamma.setPID(o2::track::PID::Photon); + trackParGamma.setAbsCharge(0); + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, trackParGamma, 2.f, matCorr, &dcaInfo); + getPxPyPz(trackParGamma, candGamma.mom); + } + registry.fill(HIST("hAP"), candGamma.alpha, candGamma.qt); + registry.fill(HIST("hV0Radius"), candGamma.radius); + if constexpr (DType == DMesonType::D0) { + varUtils.invMassReso = RecoDecay::m(std::array{varUtils.pVectorProng0, varUtils.pVectorProng1, candGamma.mom}, std::array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassKPlus, o2::constants::physics::MassGamma}); + varUtils.invMassResoBar = RecoDecay::m(std::array{varUtils.pVectorProng0, varUtils.pVectorProng1, candGamma.mom}, std::array{o2::constants::physics::MassKPlus, o2::constants::physics::MassPionCharged, o2::constants::physics::MassGamma}); + varUtils.ptReso = RecoDecay::pt(RecoDecay::sumOfVec(varUtils.pVectorProng0, varUtils.pVectorProng1, candGamma.mom)); + if (!cfgQaPlots.applyCutsForQaHistograms.value || + ((varUtils.invMassD0 > cfgQaPlots.cutMassDMin.value && varUtils.invMassD0 < cfgQaPlots.cutMassDMax.value) || + (varUtils.invMassD0Bar > cfgQaPlots.cutMassDMin.value && varUtils.invMassD0Bar < cfgQaPlots.cutMassDMax.value))) { + registry.fill(HIST("hMassD0Gamma"), varUtils.ptReso, varUtils.invMassReso - varUtils.invMassD0); + registry.fill(HIST("hMassD0Gamma"), varUtils.ptReso, varUtils.invMassResoBar - varUtils.invMassD0Bar); + } + } + // fill V0 table --> use same for V0s and gammas + // if information on V0 already stored, go to next V0 + if (!selectedGammas.count(gamma.globalIndex())) { + rowCandV0Reduced(trackPos.globalIndex(), trackNeg.globalIndex(), + indexHfReducedCollision, + candGamma.pos[0], candGamma.pos[1], candGamma.pos[2], + candGamma.momPos[0], candGamma.momPos[1], candGamma.momPos[2], + candGamma.momNeg[0], candGamma.momNeg[1], candGamma.momNeg[2], + candGamma.cosPA, + candGamma.dcaV0ToPv, + nItsClsDauGammaMin, nTpcCrossRowsDauGammaMin, chi2TpcDauGammaMax, + candGamma.v0Type); + selectedGammas[gamma.globalIndex()] = rowCandV0Reduced.lastIndex(); + } + fillHfCandD = true; + } // end of loop on V0 candidates + } // end of do gammas // fill D candidate table if (fillHfCandD) { // fill candDplus table only once per D candidate, only if at least one V0 is found if constexpr (DType == DMesonType::Dplus) { diff --git a/PWGHF/D2H/TableProducer/CMakeLists.txt b/PWGHF/D2H/TableProducer/CMakeLists.txt index 19a4a7ae123..7ad2570bec7 100644 --- a/PWGHF/D2H/TableProducer/CMakeLists.txt +++ b/PWGHF/D2H/TableProducer/CMakeLists.txt @@ -72,17 +72,17 @@ o2physics_add_dpl_workflow(data-creator-charm-had-pi-reduced o2physics_add_dpl_workflow(data-creator-charm-reso-to-dstar-reduced SOURCES dataCreatorCharmResoToDstarReduced.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::EventFilteringUtils + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::EventFilteringUtils KFParticle::KFParticle COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(data-creator-charm-reso-to-dplus-reduced SOURCES dataCreatorCharmResoToDplusReduced.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::EventFilteringUtils + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::EventFilteringUtils KFParticle::KFParticle COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(data-creator-charm-reso-to-d0-reduced SOURCES dataCreatorCharmResoToD0Reduced.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::EventFilteringUtils + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::EventFilteringUtils KFParticle::KFParticle COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(data-creator-jpsi-had-reduced diff --git a/PWGHF/D2H/TableProducer/dataCreatorCharmResoToD0Reduced.cxx b/PWGHF/D2H/TableProducer/dataCreatorCharmResoToD0Reduced.cxx index b825a362cad..6526044e6d2 100644 --- a/PWGHF/D2H/TableProducer/dataCreatorCharmResoToD0Reduced.cxx +++ b/PWGHF/D2H/TableProducer/dataCreatorCharmResoToD0Reduced.cxx @@ -24,6 +24,7 @@ #include "PWGHF/Utils/utilsBfieldCCDB.h" #include "PWGHF/Utils/utilsEvSelHf.h" +#include "Common/Core/TPCVDriftManager.h" #include "Common/Core/ZorroSummary.h" #include "Common/DataModel/CollisionAssociationTables.h" #include "Common/DataModel/EventSelection.h" @@ -86,6 +87,8 @@ struct HfDataCreatorCharmResoToD0Reduced { } cfgDmesCuts; // selection V0 HfResoConfigV0Cuts cfgV0Cuts; + // selection Gamma + HfResoConfigGammaCuts cfgGammaCuts; // selection single tracks HfResoConfigSingleTrackCuts cfgSingleTrackCuts; // QA histograms @@ -109,6 +112,7 @@ struct HfDataCreatorCharmResoToD0Reduced { // material correction for track propagation o2::base::MatLayerCylSet* lut{}; o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; + o2::aod::common::TPCVDriftManager vDriftMgr; // O2DatabasePDG service Service pdg{}; @@ -125,6 +129,7 @@ struct HfDataCreatorCharmResoToD0Reduced { using TracksWithPID = soa::Join; using TracksWithPIDAndMC = soa::Join; using TracksIUWithPID = soa::Join; + using TracksIUWithElPID = soa::Join; using TracksIUWithPIDAndMC = soa::Join; // Collisions MC using BCsInfo = soa::Join; @@ -216,7 +221,7 @@ struct HfDataCreatorCharmResoToD0Reduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsD0.sliceBy(candsD0PerCollision, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, hfCandV0, dummyTable, dummyTable, dummyTable, dummyTable); + runDataCreation>(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgGammaCuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, hfCandV0, dummyTable, dummyTable, dummyTable, dummyTable); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); @@ -251,7 +256,7 @@ struct HfDataCreatorCharmResoToD0Reduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsD0.sliceBy(candsD0PerCollision, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, dummyTable, hfTrackNoParam, dummyTable, dummyTable, dummyTable); + runDataCreation>(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgGammaCuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, dummyTable, hfTrackNoParam, dummyTable, dummyTable, dummyTable); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); @@ -289,7 +294,7 @@ struct HfDataCreatorCharmResoToD0Reduced { auto candsDThisColl = candsD0.sliceBy(candsD0PerCollision, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, hfCandV0, hfTrackNoParam, dummyTable, dummyTable, dummyTable); + runDataCreation>(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgGammaCuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, hfCandV0, hfTrackNoParam, dummyTable, dummyTable, dummyTable); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); @@ -326,13 +331,48 @@ struct HfDataCreatorCharmResoToD0Reduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsD0.sliceBy(candsD0PerCollisionWithMl, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, hfCandV0, dummyTable, dummyTable, dummyTable, hfCandD2PrMl); + runDataCreation>(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgGammaCuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, hfCandV0, dummyTable, dummyTable, dummyTable, hfCandD2PrMl); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); } PROCESS_SWITCH(HfDataCreatorCharmResoToD0Reduced, processD0V0WithMl, "Process D0 candidates paired with V0s with ML info", false); + void processD0GammaWithMl(soa::Join const& collisions, + CandsD0FilteredWithMl const& candsD0, + aod::V0s const& v0s, + TracksIUWithElPID const& tracksIU, + aod::BCsWithTimestamps const&) + { + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + int dummyTable{0}; + for (const auto& collision : collisions) { + const auto hfRejMap = o2::hf_evsel::getEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + if (rejectCollisionsWithBadEvSel && hfRejMap != 0) { + continue; + } + auto bc = collision.template bc_as(); + if (runNumber != bc.runNumber()) { + LOG(info) << ">>>>>>>>>>>> Current run number: " << runNumber; + initCCDB(bc, runNumber, ccdb, ccdbPathGrpMag, lut, false); + bz = o2::base::Propagator::Instance()->getNominalBz(); + LOG(info) << ">>>>>>>>>>>> Magnetic field: " << bz; + } + fitter.setBz(bz); + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsD0.sliceBy(candsD0PerCollisionWithMl, thisCollId); + auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); + runDataCreation>(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgGammaCuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, hfCandV0, dummyTable, dummyTable, dummyTable, hfCandD2PrMl, &vDriftMgr); + } + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + } + PROCESS_SWITCH(HfDataCreatorCharmResoToD0Reduced, processD0GammaWithMl, "Process D0 candidates paired with gammas with ML info", false); + void processD0TrackWithMl(soa::Join const& collisions, CandsD0FilteredWithMl const& candsD0, aod::TrackAssoc const& trackIndices, @@ -361,7 +401,7 @@ struct HfDataCreatorCharmResoToD0Reduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsD0.sliceBy(candsD0PerCollisionWithMl, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, dummyTable, hfTrackNoParam, dummyTable, dummyTable, hfCandD2PrMl); + runDataCreation>(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgGammaCuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, dummyTable, hfTrackNoParam, dummyTable, dummyTable, hfCandD2PrMl); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); @@ -399,7 +439,7 @@ struct HfDataCreatorCharmResoToD0Reduced { auto candsDThisColl = candsD0.sliceBy(candsD0PerCollisionWithMl, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, hfCandV0, hfTrackNoParam, dummyTable, dummyTable, hfCandD2PrMl); + runDataCreation>(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgGammaCuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, hfCandV0, hfTrackNoParam, dummyTable, dummyTable, hfCandD2PrMl); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); @@ -439,7 +479,7 @@ struct HfDataCreatorCharmResoToD0Reduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsD0.sliceBy(candsD0PerCollision, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, hfCandV0, dummyTable, rowHf2PrV0McRecReduced, dummyTable, dummyTable); + runDataCreation>(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgGammaCuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, hfCandV0, dummyTable, rowHf2PrV0McRecReduced, dummyTable, dummyTable); } runMcGen(particlesMc, mcParticlesPerMcCollision, collInfos, colPerMcCollision, mcCollisions, hfEvSelMc, rejectCollisionsWithBadEvSel, registry, pdg, rowHfResoMcGenReduced, bcs); // handle normalization by the right number of collisions @@ -478,7 +518,7 @@ struct HfDataCreatorCharmResoToD0Reduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsD0.sliceBy(candsD0PerCollision, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, dummyTable, hfTrackNoParam, dummyTable, rowHf2PrTrkMcRecReduced, dummyTable); + runDataCreation>(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgGammaCuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, dummyTable, hfTrackNoParam, dummyTable, rowHf2PrTrkMcRecReduced, dummyTable); } runMcGen(particlesMc, mcParticlesPerMcCollision, collInfos, colPerMcCollision, mcCollisions, hfEvSelMc, rejectCollisionsWithBadEvSel, registry, pdg, rowHfResoMcGenReduced, bcs); // handle normalization by the right number of collisions @@ -520,7 +560,7 @@ struct HfDataCreatorCharmResoToD0Reduced { auto candsDThisColl = candsD0.sliceBy(candsD0PerCollision, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, hfCandV0, hfTrackNoParam, rowHf2PrV0McRecReduced, rowHf2PrTrkMcRecReduced, dummyTable); + runDataCreation>(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgGammaCuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, hfCandV0, hfTrackNoParam, rowHf2PrV0McRecReduced, rowHf2PrTrkMcRecReduced, dummyTable); } runMcGen(particlesMc, mcParticlesPerMcCollision, collInfos, colPerMcCollision, mcCollisions, hfEvSelMc, rejectCollisionsWithBadEvSel, registry, pdg, rowHfResoMcGenReduced, bcs); // handle normalization by the right number of collisions @@ -560,7 +600,7 @@ struct HfDataCreatorCharmResoToD0Reduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsD0.sliceBy(candsD0PerCollisionWithMl, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, hfCandV0, dummyTable, rowHf2PrV0McRecReduced, dummyTable, hfCandD2PrMl); + runDataCreation>(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgGammaCuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, hfCandV0, dummyTable, rowHf2PrV0McRecReduced, dummyTable, hfCandD2PrMl); } runMcGen(particlesMc, mcParticlesPerMcCollision, collInfos, colPerMcCollision, mcCollisions, hfEvSelMc, rejectCollisionsWithBadEvSel, registry, pdg, rowHfResoMcGenReduced, bcs); // handle normalization by the right number of collisions @@ -599,7 +639,7 @@ struct HfDataCreatorCharmResoToD0Reduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsD0.sliceBy(candsD0PerCollisionWithMl, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, dummyTable, hfTrackNoParam, dummyTable, rowHf2PrTrkMcRecReduced, hfCandD2PrMl); + runDataCreation>(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgGammaCuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, dummyTable, hfTrackNoParam, dummyTable, rowHf2PrTrkMcRecReduced, hfCandD2PrMl); } runMcGen(particlesMc, mcParticlesPerMcCollision, collInfos, colPerMcCollision, mcCollisions, hfEvSelMc, rejectCollisionsWithBadEvSel, registry, pdg, rowHfResoMcGenReduced, bcs); // handle normalization by the right number of collisions @@ -640,7 +680,7 @@ struct HfDataCreatorCharmResoToD0Reduced { auto candsDThisColl = candsD0.sliceBy(candsD0PerCollisionWithMl, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, hfCandV0, hfTrackNoParam, rowHf2PrV0McRecReduced, rowHf2PrTrkMcRecReduced, hfCandD2PrMl); + runDataCreation>(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgGammaCuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, hfCandV0, hfTrackNoParam, rowHf2PrV0McRecReduced, rowHf2PrTrkMcRecReduced, hfCandD2PrMl); } runMcGen(particlesMc, mcParticlesPerMcCollision, collInfos, colPerMcCollision, mcCollisions, hfEvSelMc, rejectCollisionsWithBadEvSel, registry, pdg, rowHfResoMcGenReduced, bcs); // handle normalization by the right number of collisions diff --git a/PWGHF/D2H/TableProducer/dataCreatorCharmResoToDplusReduced.cxx b/PWGHF/D2H/TableProducer/dataCreatorCharmResoToDplusReduced.cxx index d0f90836449..71c1f6b49cc 100644 --- a/PWGHF/D2H/TableProducer/dataCreatorCharmResoToDplusReduced.cxx +++ b/PWGHF/D2H/TableProducer/dataCreatorCharmResoToDplusReduced.cxx @@ -215,7 +215,7 @@ struct HfDataCreatorCharmResoToDplusReduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollision, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD3Pr, hfCandV0, dummyTable, dummyTable, dummyTable, dummyTable); + runDataCreation>(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD3Pr, hfCandV0, dummyTable, dummyTable, dummyTable, dummyTable); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); @@ -250,7 +250,7 @@ struct HfDataCreatorCharmResoToDplusReduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollision, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD3Pr, dummyTable, hfTrackNoParam, dummyTable, dummyTable, dummyTable); + runDataCreation>(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD3Pr, dummyTable, hfTrackNoParam, dummyTable, dummyTable, dummyTable); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); @@ -288,7 +288,7 @@ struct HfDataCreatorCharmResoToDplusReduced { auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollision, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD3Pr, hfCandV0, hfTrackNoParam, dummyTable, dummyTable, dummyTable); + runDataCreation>(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD3Pr, hfCandV0, hfTrackNoParam, dummyTable, dummyTable, dummyTable); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); @@ -325,7 +325,7 @@ struct HfDataCreatorCharmResoToDplusReduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollisionWithMl, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD3Pr, hfCandV0, dummyTable, dummyTable, dummyTable, hfCandD3PrMl); + runDataCreation>(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD3Pr, hfCandV0, dummyTable, dummyTable, dummyTable, hfCandD3PrMl); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); @@ -360,7 +360,7 @@ struct HfDataCreatorCharmResoToDplusReduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollisionWithMl, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD3Pr, dummyTable, hfTrackNoParam, dummyTable, dummyTable, hfCandD3PrMl); + runDataCreation>(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD3Pr, dummyTable, hfTrackNoParam, dummyTable, dummyTable, hfCandD3PrMl); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); @@ -398,7 +398,7 @@ struct HfDataCreatorCharmResoToDplusReduced { auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollisionWithMl, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD3Pr, hfCandV0, hfTrackNoParam, dummyTable, dummyTable, hfCandD3PrMl); + runDataCreation>(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD3Pr, hfCandV0, hfTrackNoParam, dummyTable, dummyTable, hfCandD3PrMl); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); @@ -437,7 +437,7 @@ struct HfDataCreatorCharmResoToDplusReduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollision, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD3Pr, hfCandV0, dummyTable, rowHf3PrV0McRecReduced, dummyTable, dummyTable); + runDataCreation>(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD3Pr, hfCandV0, dummyTable, rowHf3PrV0McRecReduced, dummyTable, dummyTable); } runMcGen(particlesMc, mcParticlesPerMcCollision, collInfos, colPerMcCollision, mcCollisions, hfEvSelMc, rejectCollisionsWithBadEvSel, registry, pdg, rowHfResoMcGenReduced, bcs); // handle normalization by the right number of collisions @@ -476,7 +476,7 @@ struct HfDataCreatorCharmResoToDplusReduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollision, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD3Pr, dummyTable, hfTrackNoParam, dummyTable, rowHf3PrTrkMcRecReduced, dummyTable); + runDataCreation>(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD3Pr, dummyTable, hfTrackNoParam, dummyTable, rowHf3PrTrkMcRecReduced, dummyTable); } runMcGen(particlesMc, mcParticlesPerMcCollision, collInfos, colPerMcCollision, mcCollisions, hfEvSelMc, rejectCollisionsWithBadEvSel, registry, pdg, rowHfResoMcGenReduced, bcs); // handle normalization by the right number of collisions @@ -518,7 +518,7 @@ struct HfDataCreatorCharmResoToDplusReduced { auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollision, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD3Pr, hfCandV0, hfTrackNoParam, rowHf3PrV0McRecReduced, rowHf3PrTrkMcRecReduced, dummyTable); + runDataCreation>(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD3Pr, hfCandV0, hfTrackNoParam, rowHf3PrV0McRecReduced, rowHf3PrTrkMcRecReduced, dummyTable); } runMcGen(particlesMc, mcParticlesPerMcCollision, collInfos, colPerMcCollision, mcCollisions, hfEvSelMc, rejectCollisionsWithBadEvSel, registry, pdg, rowHfResoMcGenReduced, bcs); // handle normalization by the right number of collisions @@ -558,7 +558,7 @@ struct HfDataCreatorCharmResoToDplusReduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollisionWithMl, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD3Pr, hfCandV0, dummyTable, rowHf3PrV0McRecReduced, dummyTable, hfCandD3PrMl); + runDataCreation>(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD3Pr, hfCandV0, dummyTable, rowHf3PrV0McRecReduced, dummyTable, hfCandD3PrMl); } runMcGen(particlesMc, mcParticlesPerMcCollision, collInfos, colPerMcCollision, mcCollisions, hfEvSelMc, rejectCollisionsWithBadEvSel, registry, pdg, rowHfResoMcGenReduced, bcs); // handle normalization by the right number of collisions @@ -597,7 +597,7 @@ struct HfDataCreatorCharmResoToDplusReduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollisionWithMl, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD3Pr, dummyTable, hfTrackNoParam, dummyTable, rowHf3PrTrkMcRecReduced, hfCandD3PrMl); + runDataCreation>(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD3Pr, dummyTable, hfTrackNoParam, dummyTable, rowHf3PrTrkMcRecReduced, hfCandD3PrMl); } runMcGen(particlesMc, mcParticlesPerMcCollision, collInfos, colPerMcCollision, mcCollisions, hfEvSelMc, rejectCollisionsWithBadEvSel, registry, pdg, rowHfResoMcGenReduced, bcs); // handle normalization by the right number of collisions @@ -638,7 +638,7 @@ struct HfDataCreatorCharmResoToDplusReduced { auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollisionWithMl, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD3Pr, hfCandV0, hfTrackNoParam, rowHf3PrV0McRecReduced, rowHf3PrTrkMcRecReduced, hfCandD3PrMl); + runDataCreation>(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD3Pr, hfCandV0, hfTrackNoParam, rowHf3PrV0McRecReduced, rowHf3PrTrkMcRecReduced, hfCandD3PrMl); } runMcGen(particlesMc, mcParticlesPerMcCollision, collInfos, colPerMcCollision, mcCollisions, hfEvSelMc, rejectCollisionsWithBadEvSel, registry, pdg, rowHfResoMcGenReduced, bcs); // handle normalization by the right number of collisions diff --git a/PWGHF/D2H/TableProducer/dataCreatorCharmResoToDstarReduced.cxx b/PWGHF/D2H/TableProducer/dataCreatorCharmResoToDstarReduced.cxx index 6a3829ec1b6..d8939b6a765 100644 --- a/PWGHF/D2H/TableProducer/dataCreatorCharmResoToDstarReduced.cxx +++ b/PWGHF/D2H/TableProducer/dataCreatorCharmResoToDstarReduced.cxx @@ -215,7 +215,7 @@ struct HfDataCreatorCharmResoToDstarReduced { auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollision, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandDstar, hfCandV0, dummyTable, dummyTable, dummyTable, dummyTable); + runDataCreation>(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandDstar, hfCandV0, dummyTable, dummyTable, dummyTable, dummyTable); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); @@ -251,7 +251,7 @@ struct HfDataCreatorCharmResoToDstarReduced { auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollision, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandDstar, dummyTable, hfTrackNoParam, dummyTable, dummyTable, dummyTable); + runDataCreation>(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandDstar, dummyTable, hfTrackNoParam, dummyTable, dummyTable, dummyTable); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); @@ -289,7 +289,7 @@ struct HfDataCreatorCharmResoToDstarReduced { auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollision, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandDstar, hfCandV0, hfTrackNoParam, dummyTable, dummyTable, dummyTable); + runDataCreation>(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandDstar, hfCandV0, hfTrackNoParam, dummyTable, dummyTable, dummyTable); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); @@ -326,7 +326,7 @@ struct HfDataCreatorCharmResoToDstarReduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollisionWithMl, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandDstar, hfCandV0, dummyTable, dummyTable, dummyTable, hfCandD3PrMl); + runDataCreation>(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandDstar, hfCandV0, dummyTable, dummyTable, dummyTable, hfCandD3PrMl); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); @@ -361,7 +361,7 @@ struct HfDataCreatorCharmResoToDstarReduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollisionWithMl, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandDstar, dummyTable, hfTrackNoParam, dummyTable, dummyTable, hfCandD3PrMl); + runDataCreation>(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandDstar, dummyTable, hfTrackNoParam, dummyTable, dummyTable, hfCandD3PrMl); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); @@ -399,7 +399,7 @@ struct HfDataCreatorCharmResoToDstarReduced { auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollisionWithMl, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandDstar, hfCandV0, hfTrackNoParam, dummyTable, dummyTable, hfCandD3PrMl); + runDataCreation>(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandDstar, hfCandV0, hfTrackNoParam, dummyTable, dummyTable, hfCandD3PrMl); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); @@ -439,7 +439,7 @@ struct HfDataCreatorCharmResoToDstarReduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollision, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandDstar, hfCandV0, dummyTable, rowHfDstarV0McRecReduced, dummyTable, dummyTable); + runDataCreation>(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandDstar, hfCandV0, dummyTable, rowHfDstarV0McRecReduced, dummyTable, dummyTable); } runMcGen(particlesMc, mcParticlesPerMcCollision, collInfos, colPerMcCollision, mcCollisions, hfEvSelMc, rejectCollisionsWithBadEvSel, registry, pdg, rowHfResoMcGenReduced, bcs); // handle normalization by the right number of collisions @@ -478,7 +478,7 @@ struct HfDataCreatorCharmResoToDstarReduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollision, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandDstar, dummyTable, hfTrackNoParam, dummyTable, rowHfDstarTrkMcRecReduced, dummyTable); + runDataCreation>(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandDstar, dummyTable, hfTrackNoParam, dummyTable, rowHfDstarTrkMcRecReduced, dummyTable); } runMcGen(particlesMc, mcParticlesPerMcCollision, collInfos, colPerMcCollision, mcCollisions, hfEvSelMc, rejectCollisionsWithBadEvSel, registry, pdg, rowHfResoMcGenReduced, bcs); // handle normalization by the right number of collisions @@ -520,7 +520,7 @@ struct HfDataCreatorCharmResoToDstarReduced { auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollision, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandDstar, hfCandV0, hfTrackNoParam, rowHfDstarV0McRecReduced, rowHfDstarTrkMcRecReduced, dummyTable); + runDataCreation>(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandDstar, hfCandV0, hfTrackNoParam, rowHfDstarV0McRecReduced, rowHfDstarTrkMcRecReduced, dummyTable); } runMcGen(particlesMc, mcParticlesPerMcCollision, collInfos, colPerMcCollision, mcCollisions, hfEvSelMc, rejectCollisionsWithBadEvSel, registry, pdg, rowHfResoMcGenReduced, bcs); // handle normalization by the right number of collisions @@ -560,7 +560,7 @@ struct HfDataCreatorCharmResoToDstarReduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollisionWithMl, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandDstar, hfCandV0, dummyTable, rowHfDstarV0McRecReduced, dummyTable, hfCandD3PrMl); + runDataCreation>(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandDstar, hfCandV0, dummyTable, rowHfDstarV0McRecReduced, dummyTable, hfCandD3PrMl); } runMcGen(particlesMc, mcParticlesPerMcCollision, collInfos, colPerMcCollision, mcCollisions, hfEvSelMc, rejectCollisionsWithBadEvSel, registry, pdg, rowHfResoMcGenReduced, bcs); // handle normalization by the right number of collisions @@ -599,7 +599,7 @@ struct HfDataCreatorCharmResoToDstarReduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollisionWithMl, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandDstar, dummyTable, hfTrackNoParam, dummyTable, rowHfDstarTrkMcRecReduced, hfCandD3PrMl); + runDataCreation>(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandDstar, dummyTable, hfTrackNoParam, dummyTable, rowHfDstarTrkMcRecReduced, hfCandD3PrMl); } runMcGen(particlesMc, mcParticlesPerMcCollision, collInfos, colPerMcCollision, mcCollisions, hfEvSelMc, rejectCollisionsWithBadEvSel, registry, pdg, rowHfResoMcGenReduced, bcs); // handle normalization by the right number of collisions @@ -640,7 +640,7 @@ struct HfDataCreatorCharmResoToDstarReduced { auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollisionWithMl, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandDstar, hfCandV0, hfTrackNoParam, rowHfDstarV0McRecReduced, rowHfDstarTrkMcRecReduced, hfCandD3PrMl); + runDataCreation>(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandDstar, hfCandV0, hfTrackNoParam, rowHfDstarV0McRecReduced, rowHfDstarTrkMcRecReduced, hfCandD3PrMl); } runMcGen(particlesMc, mcParticlesPerMcCollision, collInfos, colPerMcCollision, mcCollisions, hfEvSelMc, rejectCollisionsWithBadEvSel, registry, pdg, rowHfResoMcGenReduced, bcs); // handle normalization by the right number of collisions From 58c20be8a88371173984110473da9b2ed51aeb9d Mon Sep 17 00:00:00 2001 From: sawan <124118453+sawankumawat@users.noreply.github.com> Date: Sun, 1 Mar 2026 03:26:14 +0530 Subject: [PATCH 119/347] [PWGLF] Added condition for all generated events in MC for signal loss calcualtions (#15206) --- PWGLF/Tasks/Resonances/kstarqa.cxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/PWGLF/Tasks/Resonances/kstarqa.cxx b/PWGLF/Tasks/Resonances/kstarqa.cxx index 325139e0304..26a9c5aed59 100644 --- a/PWGLF/Tasks/Resonances/kstarqa.cxx +++ b/PWGLF/Tasks/Resonances/kstarqa.cxx @@ -91,6 +91,7 @@ struct Kstarqa { Configurable isapplypTdepPIDTOF{"isapplypTdepPIDTOF", false, "Apply pT dependent PID for TOF"}; Configurable isApplyParticleMID{"isApplyParticleMID", false, "Apply particle misidentification"}; Configurable isApplyParticleMIDPtDep{"isApplyParticleMIDPtDep", false, "Apply pT dependent MID selection"}; + Configurable AllGenEvents{"AllGenEvents", false, "Fill all generated events in MC for signal loss calculations"}; Configurable checkVzEvSigLoss{"checkVzEvSigLoss", false, "Check Vz event signal loss"}; Configurable isApplyDeepAngle{"isApplyDeepAngle", false, "Deep Angle cut"}; @@ -2761,7 +2762,7 @@ struct Kstarqa { const auto evtReconstructedAndSelected = std::find(selectedEvents.begin(), selectedEvents.end(), mcCollision.globalIndex()) != selectedEvents.end(); hInvMass.fill(HIST("hAllGenCollisions"), multiplicity); - if (!evtReconstructedAndSelected) { // Check that the event is reconstructed and that the reconstructed events pass the selection + if (!selectionConfig.AllGenEvents && !evtReconstructedAndSelected) { // Check that the event is reconstructed and that the reconstructed events pass the selection return; } double genMultiplicity = mcCollision.centFT0M(); From fd9fdef2de2a519a49193e8b139cc463abc6f521 Mon Sep 17 00:00:00 2001 From: Junlee Kim Date: Sun, 1 Mar 2026 16:58:36 +0800 Subject: [PATCH 120/347] [PWGLF] adding pointing angle selection (#14855) Co-authored-by: ALICE Action Bot --- PWGLF/Tasks/Resonances/heptaquark.cxx | 66 +++++++++++++++++++-------- 1 file changed, 47 insertions(+), 19 deletions(-) diff --git a/PWGLF/Tasks/Resonances/heptaquark.cxx b/PWGLF/Tasks/Resonances/heptaquark.cxx index f7c30a46ddf..824c39601ac 100644 --- a/PWGLF/Tasks/Resonances/heptaquark.cxx +++ b/PWGLF/Tasks/Resonances/heptaquark.cxx @@ -68,6 +68,7 @@ struct heptaquark { Configurable cfgSoftFraction{"cfgSoftFraction", 0.01, "Minimum allowed softest fraction"}; Configurable cfgCollinear{"cfgCollinear", 0.98, "Maximum allowed collinear selection"}; + Configurable cfgCosPoint{"cfgCosPoint", 0.95, "Minimum pointing angle selection"}; ConfigurableAxis massAxis{"massAxis", {600, 2.8, 3.4}, "Invariant mass axis"}; ConfigurableAxis ptAxis{"ptAxis", {VARIABLE_WIDTH, 0.2, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 4.0, 5.0, 6.5, 8.0, 10.0, 100.0}, "Transverse momentum bins"}; @@ -97,6 +98,18 @@ struct heptaquark { histos.add("hDalitzRot", "hDalitzRot", {HistType::kTHnSparseF, {massPPAxis, massPLAxis, massAxis, ptAxis, {2, -0.5f, 1.5f}, centAxis}}); } + template + static inline TLorentzVector makeP4FromHQRow(HQRow const& hq) + { + const double px = hq.hqPx(); + const double py = hq.hqPy(); + const double pz = hq.hqPz(); + const double m = hq.hqMass(); + TLorentzVector v; + v.SetXYZM(px, py, pz, m); + return v; + } + double massLambda = o2::constants::physics::MassLambda; double massPr = o2::constants::physics::MassProton; double massPi = o2::constants::physics::MassPionCharged; @@ -185,37 +198,52 @@ struct heptaquark { return false; } - template - int selectHQ(HQ1 const& hq1, HQ2 const& hq2, HQ3 const& hq3) + template + int selectHQ(HQRow1 const& hq1r, HQRow2 const& hq2r, HQRow3 const& hq3r, ColRow const& col) { int selection = 0; - if (hq1.Pt() < cfgMinPhiPt || hq2.Pt() < cfgMinPhiPt || hq3.Pt() < cfgMinLambdaPt) + + auto hq1 = makeP4FromHQRow(hq1r); + auto hq2 = makeP4FromHQRow(hq2r); + auto hq3 = makeP4FromHQRow(hq3r); + + if (hq1.Pt() < cfgMinPhiPt || hq2.Pt() < cfgMinPhiPt || hq3.Pt() < cfgMinLambdaPt) { selection += 1; + } - double sumE = hq1.E() + hq2.E() + hq3.E(); - double emin = std::min({hq1.E(), hq2.E(), hq3.E()}); - double fmin = emin / std::max(1e-9, sumE); - if (fmin < cfgSoftFraction) + const double sumE = hq1.E() + hq2.E() + hq3.E(); + const double emin = std::min({hq1.E(), hq2.E(), hq3.E()}); + const double fmin = emin / std::max(1e-9, sumE); + if (fmin < cfgSoftFraction) { selection += 2; + } auto ex = hq1 + hq2 + hq3; TVector3 boost = -ex.BoostVector(); + auto hqphipair_boost = hq1 + hq2; auto hqlambda_boost = hq3; hqphipair_boost.Boost(boost); hqlambda_boost.Boost(boost); - double cosHel = hqlambda_boost.Vect().Dot(hqphipair_boost.Vect()) / (hqlambda_boost.Vect().Mag() * hqphipair_boost.Vect().Mag()); - if (std::abs(cosHel) > cfgCollinear) + + const double denom = (hqlambda_boost.Vect().Mag() * hqphipair_boost.Vect().Mag()); + const double cosHel = (denom > 0.) ? (hqlambda_boost.Vect().Dot(hqphipair_boost.Vect()) / denom) : 1.0; + if (std::abs(cosHel) > cfgCollinear) { selection += 4; - /* - ROOT::Math::XYZVector rPV(col.posX(), col.posY(), col.posZ()); - ROOT::Math::XYZVector rSV(hq3.hqx(), hq3.hqy(), hq3.hqz()); - ROOT::Math::XYZVector L = rSV - rPV; - ROOT::Math::XYZVector exMom(ex.Px(), ex.Py(), ex.Pz()); - double cosPoint = L.Dot(exMom) / (L.R() * pEx.R() + 1e-9); - if (cosPoint < cfgCosPoint) - return 8; - */ + } + + ROOT::Math::XYZVector rPV(col.posX(), col.posY(), col.posZ()); + ROOT::Math::XYZVector rSV(hq3r.hqx(), hq3r.hqy(), hq3r.hqz()); + + ROOT::Math::XYZVector L = rSV - rPV; + ROOT::Math::XYZVector exMom(ex.Px(), ex.Py(), ex.Pz()); + + const double denom2 = (L.R() * exMom.R() + 1e-9); + const double cosPoint = L.Dot(exMom) / denom2; + if (cosPoint < cfgCosPoint) { + selection += 8; + } + return selection; } @@ -344,7 +372,7 @@ struct heptaquark { HQ12 = HQ1 + HQ2; HQ13 = HQ1 + HQ3; - if (cfgSelectHQ && selectHQ(HQ1, HQ2, HQ3)) + if (cfgSelectHQ && selectHQ(hqtrackd1, hqtrackd2, hqtrackd3, collision)) continue; histos.fill(HIST("h_InvMass_same"), exotic.M(), exotic.Pt(), collision.centrality()); From b2cd3823a3629f2d2dcaad42485b159946fa297d Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Sun, 1 Mar 2026 16:27:33 +0100 Subject: [PATCH 121/347] [PWGEM/Dilepton] update muon analyses (#15207) Co-authored-by: ALICE Action Bot --- PWGEM/Dilepton/DataModel/dileptonTables.h | 5 +- .../TableProducer/Converters/CMakeLists.txt | 5 + .../Converters/muonSelfIdConverter1.cxx | 43 ++++++ .../TableProducer/skimmerPrimaryMuon.cxx | 126 ++++++++++-------- PWGEM/Dilepton/Utils/EMTrackUtilities.h | 40 ++++-- 5 files changed, 157 insertions(+), 62 deletions(-) create mode 100644 PWGEM/Dilepton/TableProducer/Converters/muonSelfIdConverter1.cxx diff --git a/PWGEM/Dilepton/DataModel/dileptonTables.h b/PWGEM/Dilepton/DataModel/dileptonTables.h index f6afb53f3e6..5d051a9705a 100644 --- a/PWGEM/Dilepton/DataModel/dileptonTables.h +++ b/PWGEM/Dilepton/DataModel/dileptonTables.h @@ -982,6 +982,7 @@ DECLARE_SOA_COLUMN(CollisionId, collisionId, int); DECLARE_SOA_COLUMN(FwdTrackId, fwdtrackId, int); //! DECLARE_SOA_COLUMN(MFTTrackId, mfttrackId, int); //! DECLARE_SOA_COLUMN(MCHTrackId, mchtrackId, int); //! +DECLARE_SOA_SELF_ARRAY_INDEX_COLUMN(GlobalMuonsWithSameMCHMID, globalMuonsWithSameMCHMID); //! self indices to global muons that have the same MCHTrackId DECLARE_SOA_SELF_ARRAY_INDEX_COLUMN(GlobalMuonsWithSameMFT, globalMuonsWithSameMFT); //! self indices to global muons that have the same MFTTrackId DECLARE_SOA_SELF_ARRAY_INDEX_COLUMN(AmbiguousMuons, ambiguousMuons); DECLARE_SOA_COLUMN(CXXatDCA, cXXatDCA, float); //! DCAx resolution squared at DCA @@ -1130,7 +1131,9 @@ DECLARE_SOA_TABLE(EMAmbiguousMuonSelfIds, "AOD", "EMAMBMUSELFID", emprimarymuon: // iterators using EMAmbiguousMuonSelfId = EMAmbiguousMuonSelfIds::iterator; -DECLARE_SOA_TABLE(EMGlobalMuonSelfIds, "AOD", "EMGLMUSELFID", emprimarymuon::GlobalMuonsWithSameMFTIds); // To be joined with EMPrimaryMuons table at analysis level. +DECLARE_SOA_TABLE(EMGlobalMuonSelfIds_000, "AOD", "EMGLMUSELFID", emprimarymuon::GlobalMuonsWithSameMFTIds); // To be joined with EMPrimaryMuons table at analysis level. +DECLARE_SOA_TABLE_VERSIONED(EMGlobalMuonSelfIds_001, "AOD", "EMGLMUSELFID", 1, emprimarymuon::GlobalMuonsWithSameMCHMIDIds, emprimarymuon::GlobalMuonsWithSameMFTIds); // To be joined with EMPrimaryMuons table at analysis level. +using EMGlobalMuonSelfIds = EMGlobalMuonSelfIds_001; // iterators using EMGlobalMuonSelfId = EMGlobalMuonSelfIds::iterator; diff --git a/PWGEM/Dilepton/TableProducer/Converters/CMakeLists.txt b/PWGEM/Dilepton/TableProducer/Converters/CMakeLists.txt index 748d953f900..b2fb9161bd4 100644 --- a/PWGEM/Dilepton/TableProducer/Converters/CMakeLists.txt +++ b/PWGEM/Dilepton/TableProducer/Converters/CMakeLists.txt @@ -65,6 +65,11 @@ o2physics_add_dpl_workflow(muon-converter2 PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(muon-selfid-converter1 + SOURCES muonSelfIdConverter1.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(mcparticle-converter1 SOURCES mcParticleConverter1.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore diff --git a/PWGEM/Dilepton/TableProducer/Converters/muonSelfIdConverter1.cxx b/PWGEM/Dilepton/TableProducer/Converters/muonSelfIdConverter1.cxx new file mode 100644 index 00000000000..fbfdcf5cd6f --- /dev/null +++ b/PWGEM/Dilepton/TableProducer/Converters/muonSelfIdConverter1.cxx @@ -0,0 +1,43 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +// +// ======================== +// +// This code produces muon table 001 from 000. +// Please write to: daiki.sekihata@cern.ch + +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" + +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +struct muonSelfIdConverter1 { + Produces muon_001; + + void process(aod::EMGlobalMuonSelfIds_000 const& muons) + { + for (const auto& muon : muons) { + muon_001(std::vector{}, muon.globalMuonsWithSameMFTIds()); + } // end of muon loop + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"muon-selfif-converter1"})}; +} diff --git a/PWGEM/Dilepton/TableProducer/skimmerPrimaryMuon.cxx b/PWGEM/Dilepton/TableProducer/skimmerPrimaryMuon.cxx index e8175f9b870..80747036f22 100644 --- a/PWGEM/Dilepton/TableProducer/skimmerPrimaryMuon.cxx +++ b/PWGEM/Dilepton/TableProducer/skimmerPrimaryMuon.cxx @@ -177,8 +177,6 @@ struct skimmerPrimaryMuon { fRegistry.add("MFTMCHMID/hDeltaPt_Pt", "#Deltap_{T}/p_{T} vs. p_{T};p_{T}^{gl} (GeV/c);(p_{T}^{sa} - p_{T}^{gl})/p_{T}^{gl}", kTH2F, {{100, 0, 10}, {200, -0.5, +0.5}}, false); fRegistry.add("MFTMCHMID/hDeltaEta_Pt", "#Delta#eta vs. p_{T};p_{T}^{gl} (GeV/c);#Delta#eta", kTH2F, {{100, 0, 10}, {200, -0.5, +0.5}}, false); fRegistry.add("MFTMCHMID/hDeltaPhi_Pt", "#Delta#varphi vs. p_{T};p_{T}^{gl} (GeV/c);#Delta#varphi (rad.)", kTH2F, {{100, 0, 10}, {200, -0.5, +0.5}}, false); - fRegistry.add("MFTMCHMID/hDeltaEtaAtMP_Pt", "#Delta#eta vs. p_{T} at MP;p_{T}^{gl} (GeV/c);#Delta#eta", kTH2F, {{100, 0, 10}, {200, -0.5, +0.5}}, false); - fRegistry.add("MFTMCHMID/hDeltaPhiAtMP_Pt", "#Delta#varphi vs. p_{T} at MP;p_{T}^{gl} (GeV/c);#Delta#varphi (rad.)", kTH2F, {{100, 0, 10}, {200, -0.5, +0.5}}, false); fRegistry.add("MFTMCHMID/hSign", "sign;sign", kTH1F, {{3, -1.5, +1.5}}, false); fRegistry.add("MFTMCHMID/hNclusters", "Nclusters;Nclusters", kTH1F, {{21, -0.5f, 20.5}}, false); fRegistry.add("MFTMCHMID/hNclustersMFT", "NclustersMFT;Nclusters MFT", kTH1F, {{11, -0.5f, 10.5}}, false); @@ -300,9 +298,9 @@ struct skimmerPrimaryMuon { int ndf_mchmft = 1; int ndf_mft = 1; - float etaMatchedMCHMIDatMP = 999.f; + // float etaMatchedMCHMIDatMP = 999.f; float phiMatchedMCHMIDatMP = 999.f; - float etaMatchedMFTatMP = 999.f; + // float etaMatchedMFTatMP = 999.f; float phiMatchedMFTatMP = 999.f; float deta = 999.f; @@ -369,9 +367,9 @@ struct skimmerPrimaryMuon { auto muonAtMP = propagateMuon(mchtrack, mchtrack, collision, propagationPoint::kToMatchingPlane, matchingZ, mBz, mZShift); // propagated to matching plane o2::track::TrackParCovFwd mftsaAtMP = getTrackParCovFwdShift(mfttrack, mZShift, mfttrackcov); // values at innermost update mftsaAtMP.propagateToZhelix(matchingZ, mBz); // propagated to matching plane - etaMatchedMFTatMP = mftsaAtMP.getEta(); + // etaMatchedMFTatMP = mftsaAtMP.getEta(); phiMatchedMFTatMP = mftsaAtMP.getPhi(); - etaMatchedMCHMIDatMP = muonAtMP.getEta(); + // etaMatchedMCHMIDatMP = muonAtMP.getEta(); phiMatchedMCHMIDatMP = muonAtMP.getPhi(); o2::math_utils::bringTo02Pi(phiMatchedMCHMIDatMP); o2::math_utils::bringTo02Pi(phiMatchedMFTatMP); @@ -447,9 +445,9 @@ struct skimmerPrimaryMuon { if constexpr (fillTable) { float dpt = (ptMatchedMCHMID - pt) / pt; - float detaMP = etaMatchedMCHMIDatMP - etaMatchedMFTatMP; - float dphiMP = phiMatchedMCHMIDatMP - phiMatchedMFTatMP; - o2::math_utils::bringToPMPi(dphiMP); + // float detaMP = etaMatchedMCHMIDatMP - etaMatchedMFTatMP; + // float dphiMP = phiMatchedMCHMIDatMP - phiMatchedMFTatMP; + // o2::math_utils::bringToPMPi(dphiMP); bool isAssociatedToMPC = fwdtrack.collisionId() == collision.globalIndex(); // LOGF(info, "isAmbiguous = %d, isAssociatedToMPC = %d, fwdtrack.globalIndex() = %d, fwdtrack.collisionId() = %d, collision.globalIndex() = %d", isAmbiguous, isAssociatedToMPC, fwdtrack.globalIndex(), fwdtrack.collisionId(), collision.globalIndex()); @@ -488,8 +486,6 @@ struct skimmerPrimaryMuon { fRegistry.fill(HIST("MFTMCHMID/hDeltaPt_Pt"), pt, dpt); fRegistry.fill(HIST("MFTMCHMID/hDeltaEta_Pt"), pt, deta); fRegistry.fill(HIST("MFTMCHMID/hDeltaPhi_Pt"), pt, dphi); - fRegistry.fill(HIST("MFTMCHMID/hDeltaEtaAtMP_Pt"), pt, detaMP); - fRegistry.fill(HIST("MFTMCHMID/hDeltaPhiAtMP_Pt"), pt, dphiMP); fRegistry.fill(HIST("MFTMCHMID/hSign"), fwdtrack.sign()); fRegistry.fill(HIST("MFTMCHMID/hNclusters"), fwdtrack.nClusters()); fRegistry.fill(HIST("MFTMCHMID/hNclustersMFT"), nClustersMFT); @@ -518,8 +514,6 @@ struct skimmerPrimaryMuon { fRegistry.fill(HIST("MCHMID/hDeltaPt_Pt"), pt, dpt); fRegistry.fill(HIST("MCHMID/hDeltaEta_Pt"), pt, deta); fRegistry.fill(HIST("MCHMID/hDeltaPhi_Pt"), pt, dphi); - fRegistry.fill(HIST("MCHMID/hDeltaEtaAtMP_Pt"), pt, detaMP); - fRegistry.fill(HIST("MCHMID/hDeltaPhiAtMP_Pt"), pt, dphiMP); fRegistry.fill(HIST("MCHMID/hSign"), fwdtrack.sign()); fRegistry.fill(HIST("MCHMID/hNclusters"), fwdtrack.nClusters()); fRegistry.fill(HIST("MCHMID/hNclustersMFT"), nClustersMFT); @@ -695,9 +689,9 @@ struct skimmerPrimaryMuon { continue; } - if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { - continue; - } + // if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { + // continue; + // } // if (!isBestMatch(fwdtrack, fwdtracks, mfttracks)) { // continue; @@ -785,9 +779,10 @@ struct skimmerPrimaryMuon { continue; } - if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { - continue; - } + // if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { + // continue; + // } + // if (!isBestMatch(fwdtrack, fwdtracks, mfttracks)) { // continue; // } @@ -876,9 +871,11 @@ struct skimmerPrimaryMuon { if (fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { continue; } - if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { - continue; - } + + // if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { + // continue; + // } + // if (!isBestMatch(fwdtrack, fwdtracks, mfttracks)) { // continue; // } @@ -958,9 +955,10 @@ struct skimmerPrimaryMuon { if (fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { continue; } - if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { - continue; - } + // if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { + // continue; + // } + // if (!isBestMatch(fwdtrack, fwdtracks, mfttracks)) { // continue; // } @@ -1046,9 +1044,10 @@ struct skimmerPrimaryMuon { if (fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { continue; } - if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { - continue; - } + // if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { + // continue; + // } + // if (!isBestMatch(fwdtrack, fwdtracks, mfttracks)) { // continue; // } @@ -1138,9 +1137,9 @@ struct skimmerPrimaryMuon { if (fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { continue; } - if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { - continue; - } + // if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { + // continue; + // } // if (!isBestMatch(fwdtrack, fwdtracks, mfttracks)) { // continue; // } @@ -1221,9 +1220,9 @@ struct skimmerPrimaryMuon { if (fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { continue; } - if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { - continue; - } + // if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { + // continue; + // } // if (!isBestMatch(fwdtrack, fwdtracks, mfttracks)) { // continue; // } @@ -1312,9 +1311,9 @@ struct skimmerPrimaryMuon { if (fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { continue; } - if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { - continue; - } + // if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { + // continue; + // } // if (!isBestMatch(fwdtrack, fwdtracks, mfttracks)) { // continue; // } @@ -1407,9 +1406,9 @@ struct skimmerPrimaryMuon { if (fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { continue; } - if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { - continue; - } + // if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { + // continue; + // } // if (!isBestMatch(fwdtrack, fwdtracks, mfttracks)) { // continue; // } @@ -1487,12 +1486,15 @@ struct associateAmbiguousMuon { } } }; -struct associateSameMFT { - Produces em_same_mft_ids; + +struct associateSameMuonElement { + Produces glmuon_same_ids; SliceCache cache; PresliceUnsorted perMFTTrack = o2::aod::emprimarymuon::mfttrackId; - std::vector self_Ids; + PresliceUnsorted perMCHTrack = o2::aod::emprimarymuon::mchtrackId; + std::vector selfIds_per_MFT; + std::vector selfIds_per_MCHMID; // Multiple MCH-MID tracks can match with the same MFTsa. This function is to reject such global muons. void process(aod::EMPrimaryMuons const& muons) @@ -1500,24 +1502,42 @@ struct associateSameMFT { for (const auto& muon : muons) { if (muon.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { auto muons_with_same_mfttrackId = muons.sliceBy(perMFTTrack, muon.mfttrackId()); - self_Ids.reserve(muons_with_same_mfttrackId.size()); + auto muons_with_same_mchtrackId = muons.sliceBy(perMCHTrack, muon.mchtrackId()); + selfIds_per_MFT.reserve(muons_with_same_mfttrackId.size()); + selfIds_per_MCHMID.reserve(muons_with_same_mchtrackId.size()); + // LOGF(info, "muons_with_same_mchtrackId.size() = %d, muons_with_same_mfttrackId.size() = %d", muons_with_same_mchtrackId.size(), muons_with_same_mfttrackId.size()); + for (const auto& global_muon : muons_with_same_mfttrackId) { + // LOGF(info, "same MFT: global_muon.globalIndex() = %d, global_muon.mchtrackId() = %d, global_muon.mfttrackId() = %d, global_muon.collisionId() = %d", global_muon.globalIndex(), global_muon.mchtrackId(), global_muon.mfttrackId(), global_muon.collisionId()); if (global_muon.globalIndex() == muon.globalIndex()) { // don't store myself. continue; } - // self_Ids.emplace_back(global_muon.globalIndex()); + if (global_muon.collisionId() == muon.collisionId()) { // the same global muon is repeatedly stored and associated to different collisions if FTTCA is used. + selfIds_per_MFT.emplace_back(global_muon.globalIndex()); + } + } + for (const auto& global_muon : muons_with_same_mchtrackId) { + // LOGF(info, "same MCH: global_muon.globalIndex() = %d, global_muon.mchtrackId() = %d, global_muon.mfttrackId() = %d, global_muon.collisionId() = %d", global_muon.globalIndex(), global_muon.mchtrackId(), global_muon.mfttrackId(), global_muon.collisionId()); + if (global_muon.globalIndex() == muon.globalIndex()) { // don't store myself. + continue; + } if (global_muon.collisionId() == muon.collisionId()) { // the same global muon is repeatedly stored and associated to different collisions if FTTCA is used. - self_Ids.emplace_back(global_muon.globalIndex()); + selfIds_per_MCHMID.emplace_back(global_muon.globalIndex()); } } - em_same_mft_ids(self_Ids); - self_Ids.clear(); - self_Ids.shrink_to_fit(); + + glmuon_same_ids(selfIds_per_MCHMID, selfIds_per_MFT); + selfIds_per_MFT.clear(); + selfIds_per_MFT.shrink_to_fit(); + selfIds_per_MCHMID.clear(); + selfIds_per_MCHMID.shrink_to_fit(); } else { - em_same_mft_ids(std::vector{}); // empty for standalone muons - self_Ids.clear(); - self_Ids.shrink_to_fit(); + glmuon_same_ids(std::vector{}, std::vector{}); // empty for standalone muons + selfIds_per_MFT.clear(); + selfIds_per_MFT.shrink_to_fit(); + selfIds_per_MCHMID.clear(); + selfIds_per_MCHMID.shrink_to_fit(); } } // end of muon loop } @@ -1527,5 +1547,5 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) return WorkflowSpec{ adaptAnalysisTask(cfgc, TaskName{"skimmer-primary-muon"}), adaptAnalysisTask(cfgc, TaskName{"associate-ambiguous-muon"}), - adaptAnalysisTask(cfgc, TaskName{"associate-same-mft"})}; + adaptAnalysisTask(cfgc, TaskName{"associate-same-muon-element"})}; } diff --git a/PWGEM/Dilepton/Utils/EMTrackUtilities.h b/PWGEM/Dilepton/Utils/EMTrackUtilities.h index d5a42a1b4bf..d2844c86517 100644 --- a/PWGEM/Dilepton/Utils/EMTrackUtilities.h +++ b/PWGEM/Dilepton/Utils/EMTrackUtilities.h @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -140,26 +141,49 @@ bool isBestMatch(TTrack const& track, TCut const& cut, TTracks const& tracks) // this is only for global muons at forward rapidity // Be careful! tracks are fwdtracks per DF. if (track.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { + bool isBestFromMCHMID2MFT = false; + bool isBestFromMFT2MCHMID = false; std::map map_chi2MCHMFT; + + // 1 MFTsa track can match several MCH-MID tracks. find best global muon per MFTsa. map_chi2MCHMFT[track.globalIndex()] = track.chi2MatchMCHMFT(); // add myself for (const auto& glmuonId : track.globalMuonsWithSameMFTIds()) { - const auto& candidate = tracks.rawIteratorAt(glmuonId); - if (candidate.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && candidate.emeventId() == track.emeventId()) { + auto candidate = tracks.rawIteratorAt(glmuonId); + if (candidate.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && candidate.emeventId() == track.emeventId() && candidate.mchtrackId() != track.mchtrackId()) { if (cut.template IsSelectedTrack(candidate)) { map_chi2MCHMFT[candidate.globalIndex()] = candidate.chi2MatchMCHMFT(); } } } // end of glmuonId - auto it = std::min_element(map_chi2MCHMFT.begin(), map_chi2MCHMFT.end(), [](decltype(map_chi2MCHMFT)::value_type& l, decltype(map_chi2MCHMFT)::value_type& r) -> bool { return l.second < r.second; }); // search for minimum matching-chi2 + auto it0 = std::min_element(map_chi2MCHMFT.begin(), map_chi2MCHMFT.end(), [](decltype(map_chi2MCHMFT)::value_type& l, decltype(map_chi2MCHMFT)::value_type& r) -> bool { return l.second < r.second; }); // search for minimum matching-chi2 + if (it0->first == track.globalIndex()) { + isBestFromMFT2MCHMID = true; + } else { + isBestFromMFT2MCHMID = false; + } + map_chi2MCHMFT.clear(); - if (it->first == track.globalIndex()) { - map_chi2MCHMFT.clear(); - return true; + // find best global muon per MCH-MID tracks. Keep in mind that there are 5 global muons per MCH-MID in pp/OO and 20 global muons per MCH-MID in PbPb. + map_chi2MCHMFT[track.globalIndex()] = track.chi2MatchMCHMFT(); // add myself + for (const auto& glmuonId : track.globalMuonsWithSameMCHMIDIds()) { + auto candidate = tracks.rawIteratorAt(glmuonId); + if (candidate.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && candidate.emeventId() == track.emeventId() && candidate.mfttrackId() != track.mfttrackId()) { + if (cut.template IsSelectedTrack(candidate)) { + map_chi2MCHMFT[candidate.globalIndex()] = candidate.chi2MatchMCHMFT(); + } + } + } // end of glmuonId + + auto it1 = std::min_element(map_chi2MCHMFT.begin(), map_chi2MCHMFT.end(), [](decltype(map_chi2MCHMFT)::value_type& l, decltype(map_chi2MCHMFT)::value_type& r) -> bool { return l.second < r.second; }); // search for minimum matching-chi2 + if (it1->first == track.globalIndex()) { + isBestFromMCHMID2MFT = true; } else { - map_chi2MCHMFT.clear(); - return false; + isBestFromMCHMID2MFT = false; } + map_chi2MCHMFT.clear(); + + return isBestFromMCHMID2MFT && isBestFromMFT2MCHMID; } else { return true; } From 7c71ca6040288d1570617f0924aebce982026a70 Mon Sep 17 00:00:00 2001 From: SCHOTTER Romain <47983209+romainschotter@users.noreply.github.com> Date: Sun, 1 Mar 2026 19:30:17 +0100 Subject: [PATCH 122/347] [PWGLF] Fix rapidity calculation for Xi particles (#15202) Co-authored-by: ALICE Builder --- PWGLF/Tasks/Strangeness/derivedlambdakzeroanalysis.cxx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/PWGLF/Tasks/Strangeness/derivedlambdakzeroanalysis.cxx b/PWGLF/Tasks/Strangeness/derivedlambdakzeroanalysis.cxx index 75d73541798..28a6759f51e 100644 --- a/PWGLF/Tasks/Strangeness/derivedlambdakzeroanalysis.cxx +++ b/PWGLF/Tasks/Strangeness/derivedlambdakzeroanalysis.cxx @@ -2062,7 +2062,12 @@ struct derivedlambdakzeroanalysis { return; // does not have mother particle in record, skip auto v0mother = v0.motherMCPart(); - float rapidityXi = RecoDecay::y(std::array{v0mother.px(), v0mother.py(), v0mother.pz()}, o2::constants::physics::MassXiMinus); + float rapidityXi = 999.; + if (std::abs(v0mother.pdgCode()) == PDG_t::kXiMinus) + rapidityXi = RecoDecay::y(std::array{v0mother.px(), v0mother.py(), v0mother.pz()}, o2::constants::physics::MassXiMinus); + if (std::abs(v0mother.pdgCode()) == o2::constants::physics::Pdg::kXi0) + rapidityXi = RecoDecay::y(std::array{v0mother.px(), v0mother.py(), v0mother.pz()}, o2::constants::physics::MassXi0); + if (std::fabs(rapidityXi) > 0.5f) return; // not a valid mother rapidity (PDG selection is later) From ee2b6ac99acf025ad5c648a0243c1c42dcc131de Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Sun, 1 Mar 2026 23:33:42 +0100 Subject: [PATCH 123/347] [PWGEM/Dilepton] update matchingMFT.cxx (#15209) Co-authored-by: ALICE Action Bot --- PWGEM/Dilepton/Tasks/matchingMFT.cxx | 59 ++++++++++++++-------------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/PWGEM/Dilepton/Tasks/matchingMFT.cxx b/PWGEM/Dilepton/Tasks/matchingMFT.cxx index e38648e48d0..48db3215bfc 100644 --- a/PWGEM/Dilepton/Tasks/matchingMFT.cxx +++ b/PWGEM/Dilepton/Tasks/matchingMFT.cxx @@ -210,10 +210,10 @@ struct matchingMFT { fRegistry.add("MFTMCHMID/primary/correct/hMFTClusterMap", "MFT cluster map", kTH1F, {{1024, -0.5, 1023.5}}, false); fRegistry.add("MFTMCHMID/primary/correct/hRatAbsorberEnd", "R at absorber end;R at absorber end (cm)", kTH1F, {{100, 0.0f, 100}}, false); fRegistry.add("MFTMCHMID/primary/correct/hPDCA_Rabs", "pDCA vs. Rabs;R at absorber end (cm);p #times DCA (GeV/c #upoint cm)", kTH2F, {{100, 0, 100}, {100, 0.0f, 1000}}, false); - fRegistry.add("MFTMCHMID/primary/correct/hChi2", "chi2;chi2/ndf", kTH1F, {{100, 0.0f, 10}}, false); - fRegistry.add("MFTMCHMID/primary/correct/hChi2MFT", "chi2 MFT/ndf;chi2 MFT/ndf", kTH1F, {{100, 0.0f, 10}}, false); - fRegistry.add("MFTMCHMID/primary/correct/hChi2MatchMCHMID", "chi2 match MCH-MID;chi2", kTH1F, {{100, 0.0f, 100}}, false); - fRegistry.add("MFTMCHMID/primary/correct/hChi2MatchMCHMFT", "chi2 match MCH-MFT;chi2", kTH1F, {{100, 0.0f, 100}}, false); + fRegistry.add("MFTMCHMID/primary/correct/hChi2_Pt", "chi2;p_{T,#mu} (GeV/c);chi2/ndf", kTH2F, {{100, 0, 10}, {100, 0.0f, 10}}, false); + fRegistry.add("MFTMCHMID/primary/correct/hChi2MFT_Pt", "chi2 MFT/ndf;p_{T,#mu} (GeV/c);chi2 MFT/ndf", kTH2F, {{100, 0, 10}, {100, 0.0f, 10}}, false); + fRegistry.add("MFTMCHMID/primary/correct/hChi2MatchMCHMID_Pt", "chi2 match MCH-MID;p_{T,#mu} (GeV/c);chi2", kTH2F, {{100, 0, 10}, {100, 0.0f, 100}}, false); + fRegistry.add("MFTMCHMID/primary/correct/hChi2MatchMCHMFT_Pt", "chi2 match MCH-MFT;p_{T,#mu} (GeV/c);chi2", kTH2F, {{100, 0, 10}, {100, 0.0f, 100}}, false); fRegistry.add("MFTMCHMID/primary/correct/hDCAxy2D", "DCA x vs. y;DCA_{x} (cm);DCA_{y} (cm)", kTH2F, {{200, -0.5, 0.5}, {200, -0.5, +0.5}}, false); fRegistry.add("MFTMCHMID/primary/correct/hDCAxy2DinSigma", "DCA x vs. y in sigma;DCA_{x} (#sigma);DCA_{y} (#sigma)", kTH2F, {{200, -10, 10}, {200, -10, +10}}, false); fRegistry.add("MFTMCHMID/primary/correct/hDCAxy", "DCAxy;DCA_{xy} (cm);", kTH1F, {{100, 0, 1}}, false); @@ -571,10 +571,10 @@ struct matchingMFT { fRegistry.fill(HIST("MFTMCHMID/primary/correct/hMFTClusterMap"), mftClusterMap(mfttrack)); fRegistry.fill(HIST("MFTMCHMID/primary/correct/hPDCA_Rabs"), rAtAbsorberEnd, pDCA); fRegistry.fill(HIST("MFTMCHMID/primary/correct/hRatAbsorberEnd"), rAtAbsorberEnd); - fRegistry.fill(HIST("MFTMCHMID/primary/correct/hChi2"), fwdtrack.chi2() / (2.f * (fwdtrack.nClusters() + nClustersMFT) - 5.f)); - fRegistry.fill(HIST("MFTMCHMID/primary/correct/hChi2MFT"), chi2mft); - fRegistry.fill(HIST("MFTMCHMID/primary/correct/hChi2MatchMCHMID"), fwdtrack.chi2MatchMCHMID()); - fRegistry.fill(HIST("MFTMCHMID/primary/correct/hChi2MatchMCHMFT"), fwdtrack.chi2MatchMCHMFT()); + fRegistry.fill(HIST("MFTMCHMID/primary/correct/hChi2_Pt"), pt, fwdtrack.chi2() / (2.f * (fwdtrack.nClusters() + nClustersMFT) - 5.f)); + fRegistry.fill(HIST("MFTMCHMID/primary/correct/hChi2MFT_Pt"), pt, chi2mft); + fRegistry.fill(HIST("MFTMCHMID/primary/correct/hChi2MatchMCHMID_Pt"), pt, fwdtrack.chi2MatchMCHMID()); + fRegistry.fill(HIST("MFTMCHMID/primary/correct/hChi2MatchMCHMFT_Pt"), pt, fwdtrack.chi2MatchMCHMFT()); fRegistry.fill(HIST("MFTMCHMID/primary/correct/hDCAxy2D"), dcaX, dcaY); fRegistry.fill(HIST("MFTMCHMID/primary/correct/hDCAxy2DinSigma"), dcaX / std::sqrt(cXX), dcaY / std::sqrt(cYY)); fRegistry.fill(HIST("MFTMCHMID/primary/correct/hDCAxy"), dcaXY); @@ -611,10 +611,10 @@ struct matchingMFT { fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hMFTClusterMap"), mftClusterMap(mfttrack)); fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hPDCA_Rabs"), rAtAbsorberEnd, pDCA); fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hRatAbsorberEnd"), rAtAbsorberEnd); - fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hChi2"), fwdtrack.chi2() / (2.f * (fwdtrack.nClusters() + nClustersMFT) - 5.f)); - fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hChi2MFT"), chi2mft); - fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hChi2MatchMCHMID"), fwdtrack.chi2MatchMCHMID()); - fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hChi2MatchMCHMFT"), fwdtrack.chi2MatchMCHMFT()); + fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hChi2_Pt"), pt, fwdtrack.chi2() / (2.f * (fwdtrack.nClusters() + nClustersMFT) - 5.f)); + fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hChi2MFT_Pt"), pt, chi2mft); + fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hChi2MatchMCHMID_Pt"), pt, fwdtrack.chi2MatchMCHMID()); + fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hChi2MatchMCHMFT_Pt"), pt, fwdtrack.chi2MatchMCHMFT()); fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hDCAxy2D"), dcaX, dcaY); fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hDCAxy2DinSigma"), dcaX / std::sqrt(cXX), dcaY / std::sqrt(cYY)); fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hDCAxy"), dcaXY); @@ -653,10 +653,10 @@ struct matchingMFT { fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hMFTClusterMap"), mftClusterMap(mfttrack)); fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hPDCA_Rabs"), rAtAbsorberEnd, pDCA); fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hRatAbsorberEnd"), rAtAbsorberEnd); - fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hChi2"), fwdtrack.chi2() / (2.f * (fwdtrack.nClusters() + nClustersMFT) - 5.f)); - fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hChi2MFT"), chi2mft); - fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hChi2MatchMCHMID"), fwdtrack.chi2MatchMCHMID()); - fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hChi2MatchMCHMFT"), fwdtrack.chi2MatchMCHMFT()); + fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hChi2_Pt"), pt, fwdtrack.chi2() / (2.f * (fwdtrack.nClusters() + nClustersMFT) - 5.f)); + fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hChi2MFT_Pt"), pt, chi2mft); + fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hChi2MatchMCHMID_Pt"), pt, fwdtrack.chi2MatchMCHMID()); + fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hChi2MatchMCHMFT_Pt"), pt, fwdtrack.chi2MatchMCHMFT()); fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hDCAxy2D"), dcaX, dcaY); fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hDCAxy2DinSigma"), dcaX / std::sqrt(cXX), dcaY / std::sqrt(cYY)); fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hDCAxy"), dcaXY); @@ -693,10 +693,10 @@ struct matchingMFT { fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hMFTClusterMap"), mftClusterMap(mfttrack)); fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hPDCA_Rabs"), rAtAbsorberEnd, pDCA); fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hRatAbsorberEnd"), rAtAbsorberEnd); - fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hChi2"), fwdtrack.chi2() / (2.f * (fwdtrack.nClusters() + nClustersMFT) - 5.f)); - fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hChi2MFT"), chi2mft); - fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hChi2MatchMCHMID"), fwdtrack.chi2MatchMCHMID()); - fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hChi2MatchMCHMFT"), fwdtrack.chi2MatchMCHMFT()); + fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hChi2_Pt"), pt, fwdtrack.chi2() / (2.f * (fwdtrack.nClusters() + nClustersMFT) - 5.f)); + fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hChi2MFT_Pt"), pt, chi2mft); + fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hChi2MatchMCHMID_Pt"), pt, fwdtrack.chi2MatchMCHMID()); + fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hChi2MatchMCHMFT_Pt"), pt, fwdtrack.chi2MatchMCHMFT()); fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hDCAxy2D"), dcaX, dcaY); fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hDCAxy2DinSigma"), dcaX / std::sqrt(cXX), dcaY / std::sqrt(cYY)); fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hDCAxy"), dcaXY); @@ -1045,9 +1045,9 @@ struct matchingMFT { continue; } - if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { - continue; - } + // if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { + // continue; + // } fillHistograms(collision, fwdtrack, fwdtracks, mfttracks, nullptr); } // end of fwdtrack loop @@ -1098,9 +1098,9 @@ struct matchingMFT { continue; } - if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { - continue; - } + // if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { + // continue; + // } fillHistograms(collision, fwdtrack, fwdtracks, mfttracks, nullptr); } // end of fwdtrack loop @@ -1158,9 +1158,10 @@ struct matchingMFT { continue; } - if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { - continue; - } + // if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { + // continue; + // } + fillHistograms(collision, fwdtrack, fwdtracks, mfttracks, mftCovs); } // end of fwdtrack loop } // end of collision loop From b022d1a51593882e1dc487fc845d3e63f774184b Mon Sep 17 00:00:00 2001 From: Swati <69241911+SwatiSaha-1997@users.noreply.github.com> Date: Mon, 2 Mar 2026 12:17:18 +0530 Subject: [PATCH 124/347] [PWGCF] Added QA histograms (#15204) --- .../Tasks/v0ptHadPiKaProt.cxx | 138 +++++++++++++++++- 1 file changed, 137 insertions(+), 1 deletion(-) diff --git a/PWGCF/EbyEFluctuations/Tasks/v0ptHadPiKaProt.cxx b/PWGCF/EbyEFluctuations/Tasks/v0ptHadPiKaProt.cxx index 6bdeab9fe76..49c44591cf6 100644 --- a/PWGCF/EbyEFluctuations/Tasks/v0ptHadPiKaProt.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/v0ptHadPiKaProt.cxx @@ -39,6 +39,7 @@ #include "ReconstructionDataFormats/Track.h" #include +#include #include #include #include @@ -133,9 +134,13 @@ struct V0ptHadPiKaProt { Configurable cfgPtCutTOF{"cfgPtCutTOF", 0.3f, "Minimum pt to use TOF N-sigma"}; Configurable> nSigmas{"nSigmas", {LongArrayFloat[0], 3, 6, {"TPC", "TOF", "ITS"}, {"pos_pi", "pos_ka", "pos_pr", "neg_pi", "neg_ka", "neg_pr"}}, "Labeled array for n-sigma values for TPC, TOF, ITS for pions, kaons, protons (positive and negative)"}; Configurable cfgUseRun3V2PID{"cfgUseRun3V2PID", true, "True if PID cuts to be used are similar to Run3 v2 PID analysis"}; + Configurable cfgNbinsV02pt{"cfgNbinsV02pt", 14, "No. of pT bins for v02(pT) analysis"}; + Configurable cfgCutPtMaxForV02{"cfgCutPtMaxForV02", 3.0f, "Max. pT for v02(pT)"}; + Configurable cfgCutEtaWindowB{"cfgCutEtaWindowB", 0.4f, "value of x in |eta|>> subSample; + std::vector>> subSampleV02; TRandom3* funRndm = new TRandom3(0); // Filter command*********** @@ -244,10 +249,23 @@ struct V0ptHadPiKaProt { histos.add("Prof_Bone_prot", "", {HistType::kTProfile2D, {centAxis, noAxis}}); histos.add("Prof_Btwo_prot", "", {HistType::kTProfile2D, {centAxis, noAxis}}); + // Analysis profile for v02(pT) + histos.add("Prof_XY", "", {HistType::kTProfile2D, {centAxis, noAxis}}); + histos.add("Prof_XYZ_had", "", {HistType::kTProfile2D, {centAxis, ptAxis}}); + histos.add("Prof_Z_had", "", {HistType::kTProfile2D, {centAxis, ptAxis}}); + histos.add("Prof_XYZ_pi", "", {HistType::kTProfile2D, {centAxis, ptAxis}}); + histos.add("Prof_Z_pi", "", {HistType::kTProfile2D, {centAxis, ptAxis}}); + histos.add("Prof_XYZ_ka", "", {HistType::kTProfile2D, {centAxis, ptAxis}}); + histos.add("Prof_Z_ka", "", {HistType::kTProfile2D, {centAxis, ptAxis}}); + histos.add("Prof_XYZ_prot", "", {HistType::kTProfile2D, {centAxis, ptAxis}}); + histos.add("Prof_Z_prot", "", {HistType::kTProfile2D, {centAxis, ptAxis}}); + // initial array subSample.resize(cfgNSubsample); + subSampleV02.resize(cfgNSubsample); for (int i = 0; i < cfgNSubsample; i++) { subSample[i].resize(20); + subSampleV02[i].resize(20); } for (int i = 0; i < cfgNSubsample; i++) { subSample[i][0] = std::get>(histos.add(Form("subSample_%d/Prof_A_had", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); @@ -273,6 +291,16 @@ struct V0ptHadPiKaProt { subSample[i][17] = std::get>(histos.add(Form("subSample_%d/Prof_D_prot", i), "", {HistType::kTProfile2D, {centAxis, noAxis}})); subSample[i][18] = std::get>(histos.add(Form("subSample_%d/Prof_Bone_prot", i), "", {HistType::kTProfile2D, {centAxis, noAxis}})); subSample[i][19] = std::get>(histos.add(Form("subSample_%d/Prof_Btwo_prot", i), "", {HistType::kTProfile2D, {centAxis, noAxis}})); + + subSampleV02[i][0] = std::get>(histos.add(Form("subSampleV02_%d/Prof_XY", i), "", {HistType::kTProfile2D, {centAxis, noAxis}})); + subSampleV02[i][1] = std::get>(histos.add(Form("subSampleV02_%d/Prof_XYZ_had", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); + subSampleV02[i][2] = std::get>(histos.add(Form("subSampleV02_%d/Prof_Z_had", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); + subSampleV02[i][3] = std::get>(histos.add(Form("subSampleV02_%d/Prof_XYZ_pi", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); + subSampleV02[i][4] = std::get>(histos.add(Form("subSampleV02_%d/Prof_Z_pi", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); + subSampleV02[i][5] = std::get>(histos.add(Form("subSampleV02_%d/Prof_XYZ_ka", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); + subSampleV02[i][6] = std::get>(histos.add(Form("subSampleV02_%d/Prof_Z_ka", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); + subSampleV02[i][1] = std::get>(histos.add(Form("subSampleV02_%d/Prof_XYZ_prot", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); + subSampleV02[i][2] = std::get>(histos.add(Form("subSampleV02_%d/Prof_Z_prot", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); } } // end init @@ -482,7 +510,7 @@ struct V0ptHadPiKaProt { histos.fill(HIST("Hist2D_globalTracks_PVTracks"), coll.multNTracksPV(), inputTracks.size()); histos.fill(HIST("Hist2D_cent_nch"), inputTracks.size(), cent); - // Analysis variables + // Analysis variables for v0(pT) int nbinsHad = 20; int nbinsPid = 18; double binsarray[21] = {0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.5, 4.0, 5.0, 6.0, 8.0, 10.0}; @@ -498,6 +526,18 @@ struct V0ptHadPiKaProt { double nSumEtaLeftKa = 0.0; double nSumEtaLeftProt = 0.0; + // Analysis variables for v02(pT) + TH1D* fPtProfileHadInWinB = new TH1D("fPtProfileHadInWinB", "fPtProfileHadInWinB", 20, binsarray); + TH1D* fPtProfilePiInWinB = new TH1D("fPtProfilePiInWinB", "fPtProfilePiInWinB", 20, binsarray); + TH1D* fPtProfileKaInWinB = new TH1D("fPtProfileKaInWinB", "fPtProfileKaInWinB", 20, binsarray); + TH1D* fPtProfileProtInWinB = new TH1D("fPtProfileProtInWinB", "fPtProfileProtInWinB", 20, binsarray); + double nSumInWinB = 0.0; // for Z = f(pT) = n(pT)/N_B in window B + + double nSumInWinA = 0.0; // for X (in window A) to calculate v2^2 + double nSumInWinC = 0.0; // for Y (in window C) to calculate v2^2 + TComplex vecQInWinA = TComplex(0., 0.); + TComplex vecQInWinC = TComplex(0., 0.); + for (const auto& track : inputTracks) { // Loop over tracks if (!track.has_collision()) { @@ -521,6 +561,7 @@ struct V0ptHadPiKaProt { double trkPt = track.pt(); double trkEta = track.eta(); + double trkPhi = track.phi(); // inclusive charged particles if (track.sign() != 0) { @@ -535,6 +576,29 @@ struct V0ptHadPiKaProt { } } + // fill subevent B for f(pT) in v02(pT) + if (track.sign() != 0 && trkPt < cfgCutPtMaxForV02) { + if (std::abs(trkEta) < cfgCutEtaWindowB) { + fPtProfileHadInWinB->Fill(trkPt); + nSumInWinB += 1.0; + } + } + double phiweight = 1.0; + // fill subevent C for v2^2 in v02(pT) + if (track.sign() != 0 && trkPt < cfgCutPtMaxForV02) { + if (cfgCutEtaWindowB < trkEta && trkEta < 0.8) { + vecQInWinC += phiweight * TComplex(TMath::Cos(2. * trkPhi), TMath::Sin(2. * trkPhi)); + nSumInWinC += phiweight; + } + } + // fill subevent A for v2^2 in v02(pT) + if (track.sign() != 0 && trkPt < cfgCutPtMaxForV02) { + if (-0.8 < trkEta && trkEta < -1.0 * cfgCutEtaWindowB) { + vecQInWinA += phiweight * TComplex(TMath::Cos(2. * trkPhi), TMath::Sin(2. * trkPhi)); + nSumInWinA += phiweight; + } + } + // PID QAs before selection double nSigmaTpcPi = track.tpcNSigmaPi(); double nSigmaTpcKa = track.tpcNSigmaKa(); @@ -607,6 +671,21 @@ struct V0ptHadPiKaProt { } } + // fill subevent B for ***identified particles'*** f(pT) in v02(pT) + if (track.sign() != 0 && trkPt < cfgCutPtMaxForV02) { + if (std::abs(trkEta) < cfgCutEtaWindowB) { + if (isPion) { + fPtProfilePiInWinB->Fill(trkPt); + } + if (isKaon) { + fPtProfileKaInWinB->Fill(trkPt); + } + if (isProton && trkPt > cfgCutPtLowerProt) { + fPtProfileProtInWinB->Fill(trkPt); + } + } + } + } // End track loop // selecting subsample and filling profiles @@ -676,11 +755,68 @@ struct V0ptHadPiKaProt { } } + if (nSumInWinA > 4 && nSumInWinB > 4 && nSumInWinC > 4) { + double twoParCorr = (vecQInWinA * TComplex::Conjugate(vecQInWinC)).Re(); + twoParCorr *= 1.0 / (nSumInWinA * nSumInWinC); + histos.get(HIST("Prof_XY"))->Fill(cent, 0.5, twoParCorr); + + subSampleV02[sampleIndex][0]->Fill(cent, 0.5, twoParCorr); + + // hadrons + for (int i = 0; i < cfgNbinsV02pt; i++) { + double threeParCorrHad = (vecQInWinA * TComplex::Conjugate(vecQInWinC) * fPtProfileHadInWinB->GetBinContent(i + 1)).Re(); + threeParCorrHad *= 1.0 / (nSumInWinA * nSumInWinC * nSumInWinB); + histos.get(HIST("Prof_XYZ_had"))->Fill(cent, fPtProfileHadInWinB->GetBinCenter(i + 1), threeParCorrHad); + histos.get(HIST("Prof_Z_had"))->Fill(cent, fPtProfileHadInWinB->GetBinCenter(i + 1), (fPtProfileHadInWinB->GetBinContent(i + 1) / nSumInWinB)); + + subSampleV02[sampleIndex][1]->Fill(cent, fPtProfileHadInWinB->GetBinCenter(i + 1), threeParCorrHad); + subSampleV02[sampleIndex][2]->Fill(cent, fPtProfileHadInWinB->GetBinCenter(i + 1), (fPtProfileHadInWinB->GetBinContent(i + 1) / nSumInWinB)); + } + + // pions + for (int i = 0; i < cfgNbinsV02pt; i++) { + double threeParCorrPi = (vecQInWinA * TComplex::Conjugate(vecQInWinC) * fPtProfilePiInWinB->GetBinContent(i + 1)).Re(); + threeParCorrPi *= 1.0 / (nSumInWinA * nSumInWinC * nSumInWinB); + histos.get(HIST("Prof_XYZ_pi"))->Fill(cent, fPtProfilePiInWinB->GetBinCenter(i + 1), threeParCorrPi); + histos.get(HIST("Prof_Z_pi"))->Fill(cent, fPtProfilePiInWinB->GetBinCenter(i + 1), (fPtProfilePiInWinB->GetBinContent(i + 1) / nSumInWinB)); + + subSampleV02[sampleIndex][1]->Fill(cent, fPtProfilePiInWinB->GetBinCenter(i + 1), threeParCorrPi); + subSampleV02[sampleIndex][2]->Fill(cent, fPtProfilePiInWinB->GetBinCenter(i + 1), (fPtProfilePiInWinB->GetBinContent(i + 1) / nSumInWinB)); + } + + // kaons + for (int i = 0; i < cfgNbinsV02pt; i++) { + double threeParCorrKa = (vecQInWinA * TComplex::Conjugate(vecQInWinC) * fPtProfileKaInWinB->GetBinContent(i + 1)).Re(); + threeParCorrKa *= 1.0 / (nSumInWinA * nSumInWinC * nSumInWinB); + histos.get(HIST("Prof_XYZ_ka"))->Fill(cent, fPtProfileKaInWinB->GetBinCenter(i + 1), threeParCorrKa); + histos.get(HIST("Prof_Z_ka"))->Fill(cent, fPtProfileKaInWinB->GetBinCenter(i + 1), (fPtProfileKaInWinB->GetBinContent(i + 1) / nSumInWinB)); + + subSampleV02[sampleIndex][1]->Fill(cent, fPtProfileKaInWinB->GetBinCenter(i + 1), threeParCorrKa); + subSampleV02[sampleIndex][2]->Fill(cent, fPtProfileKaInWinB->GetBinCenter(i + 1), (fPtProfileKaInWinB->GetBinContent(i + 1) / nSumInWinB)); + } + + // protons + for (int i = 1; i < cfgNbinsV02pt; i++) { + double threeParCorrProt = (vecQInWinA * TComplex::Conjugate(vecQInWinC) * fPtProfileProtInWinB->GetBinContent(i + 1)).Re(); + threeParCorrProt *= 1.0 / (nSumInWinA * nSumInWinC * nSumInWinB); + histos.get(HIST("Prof_XYZ_prot"))->Fill(cent, fPtProfileProtInWinB->GetBinCenter(i + 1), threeParCorrProt); + histos.get(HIST("Prof_Z_prot"))->Fill(cent, fPtProfileProtInWinB->GetBinCenter(i + 1), (fPtProfileProtInWinB->GetBinContent(i + 1) / nSumInWinB)); + + subSampleV02[sampleIndex][1]->Fill(cent, fPtProfileProtInWinB->GetBinCenter(i + 1), threeParCorrProt); + subSampleV02[sampleIndex][2]->Fill(cent, fPtProfileProtInWinB->GetBinCenter(i + 1), (fPtProfileProtInWinB->GetBinContent(i + 1) / nSumInWinB)); + } + } + fPtProfileHad->Delete(); fPtProfilePi->Delete(); fPtProfileKa->Delete(); fPtProfileProt->Delete(); + fPtProfileHadInWinB->Delete(); + fPtProfilePiInWinB->Delete(); + fPtProfileKaInWinB->Delete(); + fPtProfileProtInWinB->Delete(); + } // End process loop }; From cf14126fcbd12b03a68a8b0e76e2d1203d4da0e0 Mon Sep 17 00:00:00 2001 From: Hirak Koley Date: Mon, 2 Mar 2026 16:22:39 +0530 Subject: [PATCH 125/347] [PWGLF] Change return statements to continue in mixed event selection (#15217) --- PWGLF/Tasks/Resonances/lambda1520analysisinpp.cxx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/PWGLF/Tasks/Resonances/lambda1520analysisinpp.cxx b/PWGLF/Tasks/Resonances/lambda1520analysisinpp.cxx index 6758d7ba9ca..a494b545539 100644 --- a/PWGLF/Tasks/Resonances/lambda1520analysisinpp.cxx +++ b/PWGLF/Tasks/Resonances/lambda1520analysisinpp.cxx @@ -1239,16 +1239,16 @@ struct Lambda1520analysisinpp { // } if (!colCuts.isSelected(collision1, false)) // Default event selection - return; + continue; if (!colCuts.isSelected(collision2, false)) // Default event selection - return; + continue; if (!collision1.isInelGt0()) // <-- - return; + continue; if (!collision2.isInelGt0()) // <-- - return; + continue; if (cFilladditionalQAeventPlots) { // Fill histograms for the characteristics of the *mixed* events (collision1 and collision2) From 9c15ec60e6c974a6beeb16643ab480dd6604dc4a Mon Sep 17 00:00:00 2001 From: somabhatta <48771326+somabhatta@users.noreply.github.com> Date: Mon, 2 Mar 2026 13:08:40 +0100 Subject: [PATCH 126/347] [PWGCF] Update radial flow decorr task to include PID (#15210) --- .../Tasks/radialFlowDecorr.cxx | 3444 ++++++++--------- 1 file changed, 1669 insertions(+), 1775 deletions(-) diff --git a/PWGCF/EbyEFluctuations/Tasks/radialFlowDecorr.cxx b/PWGCF/EbyEFluctuations/Tasks/radialFlowDecorr.cxx index 8a6cf4b5f61..31f9d1b9d6e 100644 --- a/PWGCF/EbyEFluctuations/Tasks/radialFlowDecorr.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/radialFlowDecorr.cxx @@ -17,6 +17,7 @@ #include "Common/Core/trackUtilities.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/FT0Corrected.h" #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" @@ -25,6 +26,8 @@ #include "CCDB/BasicCCDBManager.h" #include "CommonConstants/MathConstants.h" #include "DataFormatsParameters/GRPObject.h" +#include "DetectorsCommonDataFormats/AlignParam.h" +#include "FT0Base/Geometry.h" #include "Framework/ASoAHelpers.h" #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" @@ -68,44 +71,30 @@ using namespace constants::math; struct RadialFlowDecorr { + static constexpr int KnFt0cCell = 96; static constexpr int KIntM = 3; static constexpr int KIntK = 3; - static constexpr int KNEta = 17; - static constexpr int KNpT = 3; - static constexpr float KFloatEpsilon = 1e-6f; static constexpr int KPiPlus = 211; static constexpr int KKPlus = 321; static constexpr int KProton = 2212; - static constexpr int KNsp = 4; - - static constexpr float KCentTestMin = 10.f; - static constexpr float KCentTestMaxLo = 60.f; - static constexpr float KCentTestMaxHi = 70.f; - static constexpr float KCentCovCut = 1.0f; + static constexpr int KNsp = 10; static constexpr float KBinOffset = 0.5f; - - static constexpr float KHalf = 0.5f; static constexpr float KPhiMin = 0.f; - static constexpr int KNbinsZvtx = 240; static constexpr float KZvtxMin = -12.f; static constexpr float KZvtxMax = 12.f; - static constexpr int KNbinsP = 100; static constexpr float KPMin = 0.f; static constexpr float KPMax = 10.f; static constexpr int KNbinsPt = 200; static constexpr float KPtMin = 0.f; static constexpr float KPtMax = 10.f; - static constexpr int KNbinsEta = 120; static constexpr float KEtaMin = -1.2f; static constexpr float KEtaMax = 1.2f; static constexpr int KNbinsPhi = 64; static constexpr float KEtaAxisMin = -0.8f; static constexpr float KEtaAxisMax = 0.8f; - static constexpr int KNbinsPhiFine = 16; - static constexpr int KNbinsPtRes = 50; static constexpr float KPtResMax = 1.f; static constexpr int KNbinsEtaRes = 100; @@ -118,32 +107,31 @@ struct RadialFlowDecorr { static constexpr float KEtaFineMax = 1.f; static constexpr int KNbinsDca = 400; static constexpr float KDcaMax = 0.2f; - static constexpr int KNbinsPtCoarse = 50; - static constexpr float KPtMinDefault = 0.2f; - static constexpr float KPtMidMax = 3.0f; - static constexpr float KPtHighMax = 5.0f; - static constexpr float KPtFullMax = 10.0f; static constexpr float KCentMax = 90; enum PID { - numKInclusive = 0, // Suffix "" - numKPion, // Suffix "_Pi" - numKKaon, // Suffix "_Ka" - numKProton, // Suffix "_Pr" - numKNumPID // Total: 4 + kInclusive = 0, // Suffix "" + kPiMinus, // Suffix "_PiMinus" + kPiPlus, // Suffix "_PiPlus" + kPiAll, // Suffix "_PiAll" + kKaMinus, // Suffix "_KaMinus" + kKaPlus, // Suffix "_KaPlus" + kKaAll, // Suffix "_KaAll" + kAntiProton, // Suffix "_AntiPr" + kProton, // Suffix "_Pr" + kAllProton, // Suffix "_AllPr" + kNumPID // Total: 10 }; - const std::vector pidSuffix = {"", "_Pi", "_Ka", "_Pr"}; + const std::vector pidSuffix = {"", "_PiMinus", "_PiPlus", "_PiAll", "_KaMinus", "_KaPlus", "_KaAll", "_AntiPr", "_Pr", "_AllPr"}; enum ECentralityEstimator { kCentFT0C = 1, - kCentFT0A = 2, - kCentFT0M = 3, - kCentFV0A = 4 + kCentFV0A = 2 }; enum SystemType { kPbPb = 1, - kOO = 2, - kpPb = 3, + kNeNe = 2, + kOO = 3, kpp = 4 }; static constexpr float KinvalidCentrality = -1.0f; @@ -154,9 +142,6 @@ struct RadialFlowDecorr { 0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.1, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8}; - const std::vector pTLw = {KPtMinDefault, KPtMinDefault, KPtMinDefault}; - const std::vector pTUp = {KPtMidMax, KPtHighMax, KPtFullMax}; - Configurable cfgVtxZCut{"cfgVtxZCut", 10.f, "z-vertex range"}; Configurable cfgPtMin{"cfgPtMin", 0.2f, "min pT"}; Configurable cfgPtMax{"cfgPtMax", 10.0f, "max pT"}; @@ -165,11 +150,12 @@ struct RadialFlowDecorr { Configurable cfgDCAZ{"cfgDCAZ", 3.2f, "DCAz cut"}; Configurable cfgTPCClsMin{"cfgTPCClsMin", 70.f, "min TPC clusters"}; Configurable cfgChi2TPCMax{"cfgChi2TPCMax", 4.0f, "max TPC χ²"}; + Configurable cfgCutTpcChi2NCl{"cfgCutTpcChi2NCl", 2.5f, "Maximum TPCchi2NCl"}; + Configurable cfgCutItsChi2NCl{"cfgCutItsChi2NCl", 36.0f, "Maximum ITSchi2NCl"}; + Configurable cfgPIDnSigmaCut{"cfgPIDnSigmaCut", 3.f, "TPC PID |nσ| cut"}; Configurable cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted z-vertex range"}; - Configurable cfgCutTpcChi2NCl{"cfgCutTpcChi2NCl", 2.5f, "Maximum TPCchi2NCl"}; - Configurable cfgCutItsChi2NCl{"cfgCutItsChi2NCl", 36.0f, "Maximum ITSchi2NCl"}; Configurable cfgCutTracKDcaMaxZ{"cfgCutTracKDcaMaxZ", 2.0f, "Maximum DcaZ"}; Configurable cfgCutTracKDcaMaxXY{"cfgCutTracKDcaMaxXY", 0.2f, "Maximum DcaZ"}; @@ -187,9 +173,9 @@ struct RadialFlowDecorr { Configurable cfgCutEta{"cfgCutEta", 0.8f, "absolute Eta cut"}; Configurable cfgCutEtaLeft{"cfgCutEtaLeft", 0.8f, "Left end of eta gap"}; Configurable cfgCutEtaRight{"cfgCutEtaRight", 0.8f, "Right end of eta gap"}; - Configurable cfgNSubsample{"cfgNSubsample", 10, "Number of subsamples"}; - Configurable cfgCentralityChoice{"cfgCentralityChoice", 1, "Which centrality estimator? 1-->FT0C, 2-->FT0A, 3-->FT0M, 4-->FV0A"}; - Configurable cfgEvSelkNoSameBunchPileup{"cfgEvSelkNoSameBunchPileup", true, "Pileup removal"}; + Configurable cfgNsubsample{"cfgNsubsample", 10, "Number of subsamples"}; + Configurable cfgCentralityChoice{"cfgCentralityChoice", 1, "Which centrality estimator? 1-->FT0C, 2-->FV0A"}; + Configurable cfgEvSelNoSameBunchPileup{"cfgEvSelNoSameBunchPileup", true, "Pileup removal"}; Configurable cfgUseGoodITSLayerAllCut{"cfgUseGoodITSLayerAllCut", true, "Remove time interval with dead ITS zone"}; Configurable cfgEvSelkNoITSROFrameBorder{"cfgEvSelkNoITSROFrameBorder", true, "ITSROFrame border event selection cut"}; Configurable cfgEvSelkNoTimeFrameBorder{"cfgEvSelkNoTimeFrameBorder", true, "TimeFrame border event selection cut"}; @@ -198,7 +184,7 @@ struct RadialFlowDecorr { Configurable cfgNchPbMax{"cfgNchPbMax", 4000, "Max Nch range for PbPb collisions"}; Configurable cfgNchOMax{"cfgNchOMax", 600, "Max Nch range for OO collisions"}; - Configurable cfgSys{"cfgSys", 1, "Efficiency to be used for which system? 1-->PbPb, 2-->OO, 3-->pPb, 4-->pp"}; + Configurable cfgSys{"cfgSys", 1, "Efficiency to be used for which system? 1-->PbPb, 2-->NeNe, 3-->OO, 4-->pp"}; Configurable cfgFlat{"cfgFlat", false, "Whether to use flattening weights"}; Configurable cfgEff{"cfgEff", false, "Whether to use Efficiency weights"}; Configurable cfgZDC{"cfgZDC", false, "Whether to use ZDC for pileup histograms"}; @@ -209,9 +195,7 @@ struct RadialFlowDecorr { ConfigurableAxis cfgAxisCent{"cfgAxisCent", {0.0, 1.0, 3.0, 5.0, 10, 20, 30, 40, 50, 60, 70, 80, 100}, "centrality axis (percentile)"}; const AxisSpec centAxis{cfgAxisCent, "Centrality (%)"}; - const AxisSpec centAxis1Per{101, -0.5, 100.5, - "Centrality (%)" - "Centrality (%)"}; + const AxisSpec centAxis1Per{101, -0.5, 100.5, "Centrality (%)"}; AxisSpec nChAxis{1, 0., 1., "Nch", "Nch"}; AxisSpec nChAxis2{1, 0., 1., "Nch", "Nch"}; @@ -219,9 +203,10 @@ struct RadialFlowDecorr { const AxisSpec chgAxis{3, -1.5, 1.5}; const AxisSpec pTAxis{{0.0, 0.2, 0.5, 1, 3, 5, 7.5, 10}, "pT Axis"}; const AxisSpec etaAxis{{-0.9, -0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.1, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9}, "Eta"}; + const AxisSpec phiAxis{KNbinsPhi, KPhiMin, TwoPI, "#phi"}; + const AxisSpec etaBinAxis{KNEta + 1, -KBinOffset, KNEta + KBinOffset, "#eta bin Number"}; const AxisSpec gapAxis{{-1.55, -1.45, -1.35, -1.25, -1.15, -1.05, -0.95, -0.85, -0.75, -0.65, -0.55, -0.45, -0.35, -0.25, -0.15, -0.05, 0.05, 0.15, 0.25, 0.35, 0.45, 0.55, 0.65, 0.75, 0.85, 0.95, 1.05, 1.15, 1.25, 1.35, 1.45, 1.55}, "Gaps"}; - const AxisSpec sumAxis{{-0.775, -0.725, -0.675, -0.625, -0.575, -0.525, -0.475, -0.425, -0.375, -0.325, -0.275, -0.225, -0.175, -0.125, -0.075, -0.025, 0.025, 0.075, 0.125, 0.175, 0.225, 0.275, 0.325, 0.375, 0.425, 0.475, 0.525, 0.575, 0.625, 0.675, 0.725, 0.775}, "Sums"}; - + const AxisSpec sumAxis{{-0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.1, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8}, "Sums"}; Configurable cfgRunGetEff{"cfgRunGetEff", false, "Run MC pass to build efficiency/fake maps"}; Configurable cfgRunGetMCFlat{"cfgRunGetMCFlat", false, "Run MC to Get Flattening Weights"}; Configurable cfgRunMCMean{"cfgRunMCMean", false, "Run MC mean(pT) & mean(Et)"}; @@ -234,20 +219,25 @@ struct RadialFlowDecorr { Service pdg; HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; - std::array hEff{}; - std::array hFake{}; - std::array hFlatWeight{}; + std::array hEff{}; + std::array hFake{}; + std::array hFlatWeight{}; + + TProfile3D* pmeanTruNchEtabinSpbinStep2 = nullptr; + TProfile3D* pmeanRecoNchEtabinSpbinStep2 = nullptr; + TProfile3D* pmeanRecoEffcorrNchEtabinSpbinStep2 = nullptr; + + TProfile3D* pmeanMultTruNchEtabinSpbinStep2 = nullptr; + TProfile3D* pmeanMultRecoNchEtabinSpbinStep2 = nullptr; + TProfile3D* pmeanMultRecoEffcorrNchEtabinSpbinStep2 = nullptr; - std::array pmeanTruNchEtabinPtbinStep2{}; - std::array pmeanRecoNchEtabinPtbinStep2{}; - std::array pmeanRecoEffcorrNchEtabinPtbinStep2{}; + TProfile3D* pmeanNchEtabinSpbinStep2 = nullptr; + TProfile3D* pmeanMultNchEtabinSpbinStep2 = nullptr; - std::array pmeanMultTruNchEtabinPtbinStep2{}; - std::array pmeanMultRecoNchEtabinPtbinStep2{}; - std::array pmeanMultRecoEffcorrNchEtabinPtbinStep2{}; + TProfile* pmeanFT0AmultpvStep2 = nullptr; + TProfile* pmeanFT0CmultpvStep2 = nullptr; - std::array pmeanNchEtabinPtbinStep2{}; - std::array pmeanMultNchEtabinPtbinStep2{}; + o2::ft0::Geometry ft0Det; template static std::tuple getAllCombinedNSigmas(const T& candidate) @@ -266,11 +256,12 @@ struct RadialFlowDecorr { return false; if (std::abs(col.posZ()) > cfgCutVertex) return false; - if (cfgEvSelkNoSameBunchPileup && !col.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) + if (cfgEvSelNoSameBunchPileup && !col.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) + return false; + if (cfgUseGoodITSLayerAllCut && !col.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) return false; if (cfgIsGoodZvtxFT0VsPV && !col.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) return false; - return true; } @@ -318,7 +309,6 @@ struct RadialFlowDecorr { if (!candidate.hasTPC()) return false; int flag = 0; - if (candidate.pt() > cfgCutPtLower && candidate.pt() <= cfgCutPtUpperTPC) { if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaPr()) < cfgnSigmaCutTPC) { flag = 1; @@ -424,10 +414,6 @@ struct RadialFlowDecorr { { if (cfgCentralityChoice.value == kCentFT0C) return col.centFT0C(); - if (cfgCentralityChoice.value == kCentFT0A) - return col.centFT0A(); - if (cfgCentralityChoice.value == kCentFT0M) - return col.centFT0M(); if (cfgCentralityChoice.value == kCentFV0A) return col.centFV0A(); return KinvalidCentrality; @@ -474,6 +460,40 @@ struct RadialFlowDecorr { return val; } + std::vector* offsetFT0 = nullptr; + uint64_t mLastTimestamp = 0; + double getEtaFT0(uint64_t globalChno, int i) + { + if (i > 1 || i < 0) { + LOGF(fatal, "kFIT Index %d out of range", i); + } + auto chPos = ft0Det.getChannelCenter(globalChno); + auto x = chPos.X() + (*offsetFT0)[i].getX(); + auto y = chPos.Y() + (*offsetFT0)[i].getY(); + auto z = chPos.Z() + (*offsetFT0)[i].getZ(); + // i == 0 is FT0A (A-side, positive Z) + // i == 1 is FT0C (C-side, negative Z) + if (i == 1) { + z = -std::abs(z); + } else if (i == 0) { + z = std::abs(z); + } + auto r = std::sqrt(x * x + y * y); + auto theta = std::atan2(r, z); + return -std::log(std::tan(0.5 * theta)); + } + + void loadAlignParam(uint64_t timestamp) + { + if (timestamp == mLastTimestamp && offsetFT0 != nullptr) { + return; + } + offsetFT0 = ccdb->getForTimeStamp>("FT0/Calib/Align", timestamp); + mLastTimestamp = timestamp; + LOGF(info, "Successfully loaded new alignment parameters for timestamp %llu", timestamp); + LOGF(info, "Offset for FT0A: x = %.3f y = %.3f z = %.3f\n", (*offsetFT0)[0].getX(), (*offsetFT0)[0].getY(), (*offsetFT0)[0].getZ()); + LOGF(info, "Offset for FT0C: x = %.3f y = %.3f z = %.3f\n", (*offsetFT0)[1].getX(), (*offsetFT0)[1].getY(), (*offsetFT0)[1].getZ()); + } template std::pair calculateMeanAndC2FromSums(const double sumpmwk[KIntM][KIntK], const double sumwk[KIntK], float referenceMeanPt) const @@ -563,11 +583,13 @@ struct RadialFlowDecorr { histos.add("hCentrality", ";centrality (%)", kTH1F, {{centAxis1Per}}); histos.add("Hist2D_globalTracks_PVTracks", ";N_{global};N_{PV}", kTH2F, {{nChAxis2}, {nChAxis2}}); histos.add("Hist2D_cent_nch", ";N_{PV};cent (%)", kTH2F, {{nChAxis2}, {centAxis1Per}}); - histos.add("hP", ";p (GeV/c)", kTH1F, {{KNbinsP, KPMin, KPMax}}); + histos.add("hP", ";p (GeV/c)", kTH1F, {{KNbinsPt, KPMin, KPMax}}); histos.add("hPt", ";p_{T} (GeV/c)", kTH1F, {{KNbinsPt, KPtMin, KPtMax}}); - histos.add("hEta", ";#eta", kTH1F, {{KNbinsEta, KEtaMin, KEtaMax}}); + histos.add("hEta", ";#eta", kTH1F, {{KNbinsEtaFine, KEtaMin, KEtaMax}}); histos.add("hPhi", ";#phi", kTH1F, {{KNbinsPhi, KPhiMin, TwoPI}}); + histos.add("hEtaPhiReco", ";z_{vtx};sign;p_{T};#eta;#phi", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {etaAxis}, {phiAxis}}); } + void declareMCCommonHists() { for (const auto& suf : pidSuffix) { @@ -576,216 +598,154 @@ struct RadialFlowDecorr { histos.add("h3_AllReco" + suf, ";N_{PV};p_{T};#eta", kTH3F, {{nChAxis2}, {KNbinsPtRes, cfgPtMin, cfgPtMax}, {KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); histos.add("h3_RecoUnMatchedToPrimary_Secondary" + suf, ";N_{PV};p_{T};#eta", kTH3F, {{nChAxis2}, {KNbinsPtRes, cfgPtMin, cfgPtMax}, {KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); histos.add("h3_RecoUnMatchedToPrimary_Fake" + suf, ";N_{PV};p_{T};#eta", kTH3F, {{nChAxis2}, {KNbinsPtRes, cfgPtMin, cfgPtMax}, {KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); - histos.add("hTruth_ParticleWeight" + suf, ";cent;p_{T};#eta", kTH3F, {{centAxis1Per}, {KNbinsPtRes, cfgPtMin, cfgPtMax}, {KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); } - histos.add("ptResolution", ";p_{T}^{MC};p_{T}^{MC}-p_{T}^{reco}", kTH2F, {{KNbinsPtRes, cfgPtMin, cfgPtMax}, {KNbinsPtRes, -KPtResMax, KPtResMax}}); - histos.add("ptTruthReco", ";p_{T}^{MC};p_{T}^{reco}", kTH2F, {{KNbinsPtRes, cfgPtMin, cfgPtMax}, {KNbinsPtRes, cfgPtMin, cfgPtMax}}); - histos.add("etaResolution", ";#eta^{MC};#eta^{MC}-#eta^{reco}", kTH2F, {{KNbinsEtaRes, -KEtaFineMax, KEtaFineMax}, {KNbinsPtRes, -KEtaResMax, KEtaResMax}}); - histos.add("etaTruthReco", ";#eta^{MC};#eta^{reco}", kTH2F, {{KNbinsPtRes, -KEtaFineMax, KEtaFineMax}, {KNbinsPtRes, -KEtaFineMax, KEtaFineMax}}); + histos.add("ptResolution", ";p_{T}^{MC};(p_{T}^{reco}-p_{T}^{MC})/p_{T}^{MC}", kTH2F, {{KNbinsPtRes, cfgPtMin, cfgPtMax}, {100, -0.2, 0.2}}); + histos.add("etaResolution", ";#eta^{MC};#eta^{reco}-#eta^{MC}", kTH2F, {{KNbinsEtaRes, -KEtaFineMax, KEtaFineMax}, {100, -0.02, 0.02}}); + histos.add("etaTruthReco", ";#eta^{MC};#eta^{reco}", kTH2F, {{KNbinsEtaRes, -KEtaFineMax, KEtaFineMax}, {KNbinsEtaRes, -KEtaFineMax, KEtaFineMax}}); histos.add("TruthTracKVz", ";Vz^{MC};Vz^{Reco}", kTH2F, {{KNbinsVz, KVzMin, KVzMax}, {KNbinsVz, KVzMin, KVzMax}}); - histos.add("vzResolution", ";Vz^{MC};Vz^{MC}-Vz^{Reco}", kTH2F, {{KNbinsVz, KVzMin, KVzMax}, {KNbinsVz, -KVzResMax, KVzResMax}}); + histos.add("vzResolution", ";Vz^{MC};(Vz^{reco}-Vz^{MC})/Vz^{MC}", kTH2F, {{KNbinsVz, KVzMin, KVzMax}, {100, -0.1, 0.1}}); - histos.add("h_AllPrimary", ";p_{T}", kTH1F, {{KNbinsPtRes, cfgPtMin, cfgPtMax}}); - histos.add("h_RecoMatchedToPrimary", ";p_{T}", kTH1F, {{KNbinsPtRes, cfgPtMin, cfgPtMax}}); histos.add("h_RecoUnMatchedToPrimary", ";p_{T}", kTH1F, {{KNbinsPtRes, cfgPtMin, cfgPtMax}}); - histos.add("h_AllReco", ";p_{T}", kTH1F, {{KNbinsPtRes, cfgPtMin, cfgPtMax}}); - histos.add("h_AllRecoEffCorr", ";p_{T}", kTH1F, {{KNbinsPtRes, cfgPtMin, cfgPtMax}}); - - histos.add("hDCAxy_Unmatched", ";DCA_{xy} (cm)", kTH1F, {{KNbinsDca, -KDcaMax, KDcaMax}}); - histos.add("hDCAz_Unmatched", ";DCA_{z} (cm)", kTH1F, {{KNbinsDca, -KDcaMax, KDcaMax}}); - histos.add("hDCAxy_NotPrimary", ";DCA_{xy} (cm)", kTH1F, {{KNbinsDca, -KDcaMax, KDcaMax}}); - histos.add("hDCAz_NotPrimary", ";DCA_{z} (cm)", kTH1F, {{KNbinsDca, -KDcaMax, KDcaMax}}); - histos.add("hDCAxy_RecoMatched", ";DCA_{xy} (cm)", kTH1F, {{KNbinsDca, -KDcaMax, KDcaMax}}); - histos.add("hDCAz_RecoMatched", ";DCA_{z} (cm)", kTH1F, {{KNbinsDca, -KDcaMax, KDcaMax}}); - histos.add("hDCAxy_Reco", ";DCA_{xy} (cm)", kTH1F, {{KNbinsDca, -KDcaMax, KDcaMax}}); - histos.add("hDCAz_Reco", ";DCA_{z} (cm)", kTH1F, {{KNbinsDca, -KDcaMax, KDcaMax}}); } void declareMCGetFlatHists() { for (const auto& suf : pidSuffix) { - std::string nameEff = "hEtaPhiReco" + suf; - std::string nameWtd = "hEtaPhiRecoWtd" + suf; - std::string nameEffWtd = "hEtaPhiRecoEffWtd" + suf; - - histos.add(nameEffWtd, nameEffWtd.c_str(), kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); - histos.add(nameEff, nameEff.c_str(), kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); - histos.add(nameWtd, nameWtd.c_str(), kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); + histos.add("MCGen/hEtaPhiReco" + suf, ";vz;sign;pt;eta;phi", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {etaAxis}, {phiAxis}}); + histos.add("MCGen/hEtaPhiRecoEffWtd" + suf, ";vz;sign;pt;eta;phi", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {etaAxis}, {phiAxis}}); + histos.add("MCGen/hEtaPhiRecoWtd" + suf, ";vz;sign;pt;eta;phi", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {etaAxis}, {phiAxis}}); } } void declareMCMeanHists() { - histos.add("Eff_cent", ";cent;#epsilon", kTProfile, {centAxis1Per}); - histos.add("Fake_cent", ";cent;f_{fake}", kTProfile, {centAxis1Per}); - histos.add("wgt_cent", ";cent;w", kTProfile, {centAxis1Per}); - histos.add("Eff_Ntrk", ";N_{PV};#epsilon", kTProfile, {nChAxis2}); - histos.add("Fake_Ntrk", ";N_{PV};f_{fake}", kTProfile, {nChAxis2}); - histos.add("wgt_Ntrk", ";N_{PV};w", kTProfile, {nChAxis2}); - histos.add("Eff_pT", ";p_{T};#epsilon", kTProfile, {{KNbinsPtRes, cfgPtMin, cfgPtMax}}); - histos.add("Fake_pT", ";p_{T};f_{fake}", kTProfile, {{KNbinsPtRes, cfgPtMin, cfgPtMax}}); - histos.add("wgt_pT", ";p_{T};w", kTProfile, {{KNbinsPtRes, KPtMin, KPtMax}}); - histos.add("Eff_eta", ";#eta;#epsilon", kTProfile, {{KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); - histos.add("Fake_eta", ";#eta;f_{fake}", kTProfile, {{KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); - histos.add("wgt_eta", ";#eta;w", kTProfile, {{KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); + histos.add("Eff_cent", ";cent", kTProfile, {centAxis1Per}); + histos.add("Eff_Ntrk", ";N_{PV}", kTProfile, {nChAxis2}); + histos.add("Eff_pT", ";p_{T}", kTProfile, {{KNbinsPtRes, cfgPtMin, cfgPtMax}}); + histos.add("Eff_eta", ";#eta", kTProfile, {{KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); + + histos.add("Fake_cent", ";cent", kTProfile, {centAxis1Per}); + histos.add("Fake_Ntrk", ";N_{PV}", kTProfile, {nChAxis2}); + histos.add("Fake_pT", ";p_{T}", kTProfile, {{KNbinsPtRes, cfgPtMin, cfgPtMax}}); + histos.add("Fake_eta", ";#eta", kTProfile, {{KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); + + histos.add("wgt_cent", ";cent", kTProfile, {centAxis1Per}); + histos.add("wgt_Ntrk", ";N_{PV}", kTProfile, {nChAxis2}); + histos.add("wgt_pT", ";p_{T}", kTProfile, {{KNbinsPtRes, cfgPtMin, cfgPtMax}}); + histos.add("wgt_eta", ";#eta", kTProfile, {{KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); + + histos.add("pmeanFT0Amultpv", ";N_{PV};Ampl", kTProfile, {nChAxis}); + histos.add("pmeanFT0Cmultpv", ";N_{PV};Ampl", kTProfile, {nChAxis}); + histos.add("pmeanFT0A_cent", ";cent;Ampl", kTProfile, {centAxis1Per}); + histos.add("pmeanFT0C_cent", ";cent;Ampl", kTProfile, {centAxis1Per}); + histos.add("pmean_cent_id_eta_FT0", ";cent;id;#eta", kTProfile3D, {{centAxis1Per}, {100, -0.5, 99.5}, {100, -5.0, 5.0}}); + histos.add("h3_cent_id_eta_FT0", ";cent;id;#eta", kTH3F, {{centAxis1Per}, {100, -0.5, 99.5}, {100, -5.0, 5.0}}); + + histos.add("MCGen/Prof_Cent_Nsp_Nchrec", ";cent;isp", kTProfile2D, {{centAxis1Per}, {KNsp, -0.5, KNsp - 0.5}}); + histos.add("MCGen/Prof_Mult_Nsp_Nchrec", ";mult;isp", kTProfile2D, {{nChAxis}, {KNsp, -0.5, KNsp - 0.5}}); + histos.add("MCGen/Prof_Cent_Nsp_MeanpT", ";cent;isp", kTProfile2D, {{centAxis1Per}, {KNsp, -0.5, KNsp - 0.5}}); + histos.add("MCGen/Prof_Mult_Nsp_MeanpT", ";mult;isp", kTProfile2D, {{nChAxis}, {KNsp, -0.5, KNsp - 0.5}}); + + histos.add("pmeanTru_nch_etabin_spbin", ";mult;eta;isp", kTProfile3D, {{nChAxis}, {KNEta, 0.5, KNEta + 0.5}, {KNsp, -0.5, KNsp - 0.5}}); + histos.add("pmeanReco_nch_etabin_spbin", ";mult;eta;isp", kTProfile3D, {{nChAxis}, {KNEta, 0.5, KNEta + 0.5}, {KNsp, -0.5, KNsp - 0.5}}); + histos.add("pmeanRecoEffcorr_nch_etabin_spbin", ";mult;eta;isp", kTProfile3D, {{nChAxis}, {KNEta, 0.5, KNEta + 0.5}, {KNsp, -0.5, KNsp - 0.5}}); + + histos.add("pmeanMultTru_nch_etabin_spbin", ";mult;eta;isp", kTProfile3D, {{nChAxis}, {KNEta, 0.5, KNEta + 0.5}, {KNsp, -0.5, KNsp - 0.5}}); + histos.add("pmeanMultReco_nch_etabin_spbin", ";mult;eta;isp", kTProfile3D, {{nChAxis}, {KNEta, 0.5, KNEta + 0.5}, {KNsp, -0.5, KNsp - 0.5}}); + histos.add("pmeanMultRecoEffcorr_nch_etabin_spbin", ";mult;eta;isp", kTProfile3D, {{nChAxis}, {KNEta, 0.5, KNEta + 0.5}, {KNsp, -0.5, KNsp - 0.5}}); for (const auto& suf : pidSuffix) { - // Basic Profiles - histos.add("MCGen/Prof_Cent_Nchrec" + suf, ";cent;#LT N_{PV}#GT", kTProfile, {centAxis1Per}); - histos.add("MCGen/Prof_Mult_Nchrec" + suf, ";N_{PV};#LT N_{PV}#GT", kTProfile, {nChAxis}); - - histos.add("MCGen/Prof_Cent_MeanpT" + suf, ";cent;#LT p_{T}#GT", kTProfile, {centAxis1Per}); - histos.add("MCGen/Prof_Mult_MeanpT" + suf, ";N_{PV};#LT p_{T}#GT", kTProfile, {nChAxis}); - - histos.add("pmeanTruNchEtabinPtbin" + suf, ";N_{PV};#eta bin;p_{T} bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("pmeanRecoNchEtabinPtbin" + suf, ";N_{PV};#eta bin;p_{T} bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("pmeanRecoEffcorrNchEtabinPtbin" + suf, ";N_{PV};#eta bin;p_{T} bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - - histos.add("pmeanMultTruNchEtabinPtbin" + suf, ";N_{PV};#eta bin;p_{T} bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("pmeanMultRecoNchEtabinPtbin" + suf, ";N_{PV};#eta bin;p_{T} bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("pmeanMultRecoEffcorrNchEtabinPtbin" + suf, ";N_{PV};#eta bin;p_{T} bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - - for (const int& i : {0, 1, 2}) { - std::string ptTag = "_ipt" + std::to_string(i); - histos.add("Prof2D_MeanpT_Sub" + ptTag + "_Tru" + suf, ";cent;etaA;etaB", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}}); - histos.add("Prof2D_MeanpT_Sub" + ptTag + "_Reco" + suf, ";cent;etaA;etaB", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}}); - histos.add("Prof2D_MeanpT_Sub" + ptTag + "_RecoEffCorr" + suf, ";cent;etaA;etaB", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}}); - } - } - - for (const auto& suf : pidSuffix) { - std::string nameEff = "hEtaPhiReco" + suf; - std::string nameWtd = "hEtaPhiRecoWtd" + suf; - std::string nameEffWtd = "hEtaPhiRecoEffWtd" + suf; - - histos.add(nameEffWtd, nameEffWtd.c_str(), kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); - histos.add(nameEff, nameEff.c_str(), kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); - histos.add(nameWtd, nameWtd.c_str(), kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); + histos.add("Prof2D_MeanpTSub_Tru" + suf, ";cent;etaA;etaC", kTProfile3D, {{centAxis1Per}, {etaBinAxis}, {etaBinAxis}}); + histos.add("Prof2D_MeanpTSub_Reco" + suf, ";cent;etaA;etaC", kTProfile3D, {{centAxis1Per}, {etaBinAxis}, {etaBinAxis}}); + histos.add("Prof2D_MeanpTSub_RecoEffCorr" + suf, ";cent;etaA;etaC", kTProfile3D, {{centAxis1Per}, {etaBinAxis}, {etaBinAxis}}); } } void declareMCFlucHists() { + histos.add("MCGen/Prof_MeanpT_Cent_etabin_spbin", ";cent;eta;isp", kTProfile3D, {{centAxis1Per}, {etaBinAxis}, {KNsp, -0.5, KNsp - 0.5}}); + histos.add("MCGen/Prof_C2_Cent_etabin_spbin", ";cent;eta;isp", kTProfile3D, {{centAxis1Per}, {etaBinAxis}, {KNsp, -0.5, KNsp - 0.5}}); + histos.add("MCGen/Prof_C2Sub_Cent_etabin_spbin", ";cent;eta;isp", kTProfile3D, {{centAxis1Per}, {etaBinAxis}, {KNsp, -0.5, KNsp - 0.5}}); + histos.add("MCGen/Prof_Cov_Cent_etabin_spbin", ";cent;eta;isp", kTProfile3D, {{centAxis1Per}, {etaBinAxis}, {KNsp, -0.5, KNsp - 0.5}}); + histos.add("MCGen/Prof_CovFT0A_Cent_etabin_spbin", ";cent;eta;isp", kTProfile3D, {{centAxis1Per}, {etaBinAxis}, {KNsp, -0.5, KNsp - 0.5}}); + histos.add("MCGen/Prof_CovFT0C_Cent_etabin_spbin", ";cent;eta;isp", kTProfile3D, {{centAxis1Per}, {etaBinAxis}, {KNsp, -0.5, KNsp - 0.5}}); for (const auto& suf : pidSuffix) { - // --- 1D Full Event Calc Profiles --- - histos.add("MCGen/Prof_MeanpT_Cent_etabin_ptbin" + suf, ";cent;#eta-bin; p_{T}-bin", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("MCGen/Prof_MeanpT_Mult_etabin_ptbin" + suf, ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - - histos.add("MCGen/Prof_C2_Cent_etabin_ptbin" + suf, ";cent;#eta-bin; p_{T}-bin", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("MCGen/Prof_C2_Mult_etabin_ptbin" + suf, ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - - // --- 1D Sub-Event Covariances --- - histos.add("MCGen/Prof_C2Sub_Cent_etabin_ptbin" + suf, ";Centrality;#eta-bin; p_{T}-bin", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("MCGen/Prof_C2Sub_Mult_etabin_ptbin" + suf, ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - - histos.add("MCGen/Prof_Cov_Cent_etabin_ptbin" + suf, ";Centrality;#eta-bin; p_{T}-bin", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("MCGen/Prof_Cov_Mult_etabin_ptbin" + suf, ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - - for (const int& i : {0, 1, 2}) { - std::string ptTag = "_ipt" + std::to_string(i); - histos.add("MCGen/Prof" + ptTag + "_C2Sub2D_Cent_etaA_etaC" + suf, ";cent;#eta_{A};#eta_{B}", kTProfile3D, {{centAxis1Per}, {etaAxis}, {etaAxis}}); - histos.add("MCGen/Prof" + ptTag + "_Cov2D_Cent_etaA_etaC" + suf, ";cent;#eta_{A};#eta_{B}", kTProfile3D, {{centAxis1Per}, {etaAxis}, {etaAxis}}); - histos.add("MCGen/Prof" + ptTag + "_GapSum2D" + suf, ";cent;#Delta#eta (Gap);#Sigma#eta/2 (Sum)", kTProfile3D, {{centAxis1Per}, {gapAxis}, {sumAxis}}); - } - - std::string nameEff = "hEtaPhiReco" + suf; - std::string nameWtd = "hEtaPhiRecoWtd" + suf; - std::string nameEffWtd = "hEtaPhiRecoEffWtd" + suf; - histos.add(nameEffWtd, nameEffWtd.c_str(), kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); - histos.add(nameEff, nameEff.c_str(), kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); - histos.add(nameWtd, nameWtd.c_str(), kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); - - histos.add("MCGen/Prof_Cent_Nchrec" + suf, ";cent;#LT N_{PV}#GT", kTProfile, {centAxis1Per}); - histos.add("MCGen/Prof_Mult_Nchrec" + suf, ";N_{PV};#LT N_{PV}#GT", kTProfile, {nChAxis}); - histos.add("MCGen/Prof_Cent_MeanpT" + suf, ";cent;#LT p_{T}#GT", kTProfile, {centAxis1Per}); - histos.add("MCGen/Prof_Mult_MeanpT" + suf, ";N_{PV};#LT p_{T}#GT", kTProfile, {nChAxis}); + histos.add(Form("MCGen/Prof_C2Sub2D_Cent_etaA_etaC%s", suf.c_str()), ";cent;etaA;etaC", kTProfile3D, {{centAxis1Per}, {etaAxis}, {etaAxis}}); + histos.add(Form("MCGen/Prof_GapSum2D%s", suf.c_str()), ";cent;gap;sum", kTProfile3D, {{centAxis1Per}, {gapAxis}, {sumAxis}}); + histos.add(Form("MCGen/Prof_Cov2D_Cent_etaA_etaC%s", suf.c_str()), ";cent;etaA;etaC", kTProfile3D, {{centAxis1Per}, {etaAxis}, {etaAxis}}); } } void declareDataGetFlatHists() { - // 1. Species-dependent Sparse Histograms for (const auto& suf : pidSuffix) { - std::string nameEff = "hEtaPhiReco" + suf; - std::string nameWtd = "hEtaPhiRecoWtd" + suf; - std::string nameEffWtd = "hEtaPhiRecoEffWtd" + suf; - - histos.add(nameEffWtd, nameEffWtd.c_str(), kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); - histos.add(nameEff, nameEff.c_str(), kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); - histos.add(nameWtd, nameWtd.c_str(), kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); + histos.add("hEtaPhiReco" + suf, ";vz;sign;pt;eta;phi", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {etaAxis}, {phiAxis}}); + histos.add("hEtaPhiRecoEffWtd" + suf, ";vz;sign;pt;eta;phi", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {etaAxis}, {phiAxis}}); + histos.add("hEtaPhiRecoWtd" + suf, ";vz;sign;pt;eta;phi", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {etaAxis}, {phiAxis}}); } - histos.add("hnTrkPVZDC", ";N_{PV};ZDC_{A+C}", kTH2F, {{nChAxis2}, {200, 0, 3000}}); histos.add("hNchZDC", ";N_{trk};ZDC_{A+C}", kTH2F, {{nChAxis2}, {200, 0, 30000}}); - histos.add("hCentnTrk", ";Centrality (%);N_{trk}", kTH2F, {{centAxis1Per}, {nChAxis2}}); histos.add("hCentnTrkPV", ";Centrality (%);N_{trk, PV}", kTH2F, {{centAxis1Per}, {nChAxis2}}); } void declareDataMeanHists() { - for (const auto& suf : pidSuffix) { - std::string nameReco = "hEtaPhiReco" + suf; - std::string nameWtd = "hEtaPhiRecoWtd" + suf; - std::string nameEffWtd = "hEtaPhiRecoEffWtd" + suf; + histos.add("pmeanFT0Amultpv", "N_{PV}; AmplitudeA", kTProfile, {nChAxis}); + histos.add("pmeanFT0A_cent", "cent; AmplitudeA", kTProfile, {centAxis1Per}); + histos.add("pmeanFT0Cmultpv", "N_{PV}; AmplitudeA", kTProfile, {nChAxis}); + histos.add("pmeanFT0C_cent", "cent; AmplitudeA", kTProfile, {centAxis1Per}); - histos.add(nameReco, nameReco.c_str(), kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); - histos.add(nameWtd, nameWtd.c_str(), kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); - histos.add(nameEffWtd, nameEffWtd.c_str(), kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); + histos.add("pmean_cent_id_eta_FT0", ";cent;channel id; #eta;amplitude", kTProfile3D, {{centAxis1Per}, {100, -0.5, 99.5}, {100, -5.0, 5.0}}); + histos.add("h3_cent_id_eta_FT0", ";cent;channel id; #eta", kTH3F, {{centAxis1Per}, {100, -0.5, 99.5}, {100, -5.0, 5.0}}); - histos.add("Prof_Cent_Nchrec" + suf, ";cent;#LT N_{PV}#GT", kTProfile, {centAxis1Per}); - histos.add("Prof_Mult_Nchrec" + suf, ";N_{PV};#LT N_{PV}#GT", kTProfile, {nChAxis}); - histos.add("Prof_Cent_MeanpT" + suf, ";cent;#LT p_{T}#GT", kTProfile, {centAxis1Per}); + histos.add("Prof_Cent_Nsp_Nchrec", ";cent;Species;#LT N_{PV}#GT", kTProfile2D, {{centAxis1Per}, {KNsp, -0.5, KNsp - 0.5}}); + histos.add("Prof_Mult_Nsp_Nchrec", ";N_{PV};Species;#LT N_{PV}#GT", kTProfile2D, {{nChAxis}, {KNsp, -0.5, KNsp - 0.5}}); + histos.add("Prof_Cent_Nsp_MeanpT", ";cent;Species;#LT p_{T}#GT", kTProfile2D, {{centAxis1Per}, {KNsp, -0.5, KNsp - 0.5}}); + histos.add("Prof_Mult_Nsp_MeanpT", ";N_{PV};Species;#LT p_{T}#GT", kTProfile2D, {{nChAxis}, {KNsp, -0.5, KNsp - 0.5}}); - histos.add("pmean_nch_etabin_ptbin" + suf, ";N_{PV};#eta-bin;p_{T}-bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("pmeanMult_nch_etabin_ptbin" + suf, ";N_{PV};#eta-bin;p_{T}-bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); + histos.add("pmean_nch_etabin_spbin", ";N_{PV};#eta-bin;Species", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNsp, -0.5, KNsp - 0.5}}); + histos.add("pmeanMult_nch_etabin_spbin", ";N_{PV};#eta-bin;Species", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNsp, -0.5, KNsp - 0.5}}); + histos.add("pmean_cent_etabin_spbin", ";Centrality (%) ;#eta-bin;Species", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNsp, -0.5, KNsp - 0.5}}); + histos.add("pmeanMult_cent_etabin_spbin", ";Centrality (%) ;#eta-bin;Species", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNsp, -0.5, KNsp - 0.5}}); - histos.add("pmean_cent_etabin_ptbin" + suf, ";Centrality (%) ;#eta-bin;p_{T}-bin", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("pmeanMult_cent_etabin_ptbin" + suf, ";Centrality (%) ;#eta-bin;p_{T}-bin", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); + for (const auto& suf : pidSuffix) { + histos.add("hEtaPhiReco" + suf, ";vz;sign;pt;eta;phi", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {etaAxis}, {phiAxis}}); + histos.add("hEtaPhiRecoEffWtd" + suf, ";vz;sign;pt;eta;phi", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {etaAxis}, {phiAxis}}); + histos.add("hEtaPhiRecoWtd" + suf, ";vz;sign;pt;eta;phi", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {etaAxis}, {phiAxis}}); - for (const int& i : {0, 1, 2}) { - std::string ptTag = "_ipt" + std::to_string(i); - std::string histName = "Prof2D_MeanpT_Sub" + ptTag + suf; - histos.add(histName, ";cent;#eta_{A} bin;#eta_{B} bin", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}}); - } + histos.add("Prof2D_MeanpTSub" + suf, ";cent;#eta_{A} bin;#eta_{C} bin", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}}); } } void declareDataFlucHists() { - for (const auto& suf : pidSuffix) { - - // --- THnSparse QA Histograms --- - std::string nameReco = "hEtaPhiReco" + suf; - std::string nameEff = "hEtaPhiRecoEffWtd" + suf; - std::string nameWtd = "hEtaPhiRecoWtd" + suf; - - histos.add(nameReco, nameReco.c_str(), kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); - histos.add(nameEff, nameEff.c_str(), kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); - histos.add(nameWtd, nameWtd.c_str(), kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); + histos.add("Prof_MeanpT_Cent_etabin_spbin", ";cent;#eta-bin;Species", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNsp, -0.5, KNsp - 0.5}}); + histos.add("Prof_MeanpT_Mult_etabin_spbin", ";N_{PV};#eta-bin;Species", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNsp, -0.5, KNsp - 0.5}}); + histos.add("Prof_C2_Cent_etabin_spbin", ";cent;#eta-bin;Species", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNsp, -0.5, KNsp - 0.5}}); + histos.add("Prof_C2_Mult_etabin_spbin", ";N_{PV};#eta-bin;Species", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNsp, -0.5, KNsp - 0.5}}); - // --- 1D Full Event Calc Profiles --- - histos.add("Prof_MeanpT_Cent_etabin_ptbin" + suf, ";cent;#eta-bin; p_{T}-bin", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("Prof_MeanpT_Mult_etabin_ptbin" + suf, ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); + histos.add("Prof_C2Sub_Cent_etabin_spbin", ";Centrality;#eta-bin;Species", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNsp, -0.5, KNsp - 0.5}}); + histos.add("Prof_C2Sub_Mult_etabin_spbin", ";N_{PV};#eta-bin;Species", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNsp, -0.5, KNsp - 0.5}}); + histos.add("Prof_Cov_Cent_etabin_spbin", ";Centrality;#eta-bin;Species", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNsp, -0.5, KNsp - 0.5}}); + histos.add("Prof_Cov_Mult_etabin_spbin", ";N_{PV};#eta-bin;Species", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNsp, -0.5, KNsp - 0.5}}); - histos.add("Prof_C2_Cent_etabin_ptbin" + suf, ";cent;#eta-bin; p_{T}-bin", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("Prof_C2_Mult_etabin_ptbin" + suf, ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); + histos.add("Prof_CovFT0A_Cent_etabin_spbin", ";Centrality;#eta-bin;Species", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNsp, -0.5, KNsp - 0.5}}); + histos.add("Prof_CovFT0A_Mult_etabin_spbin", ";N_{PV};#eta-bin;Species", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNsp, -0.5, KNsp - 0.5}}); + histos.add("Prof_CovFT0C_Cent_etabin_spbin", ";Centrality;#eta-bin;Species", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNsp, -0.5, KNsp - 0.5}}); + histos.add("Prof_CovFT0C_Mult_etabin_spbin", ";N_{PV};#eta-bin;Species", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNsp, -0.5, KNsp - 0.5}}); - // --- 1D Sub-Event Covariances --- - histos.add("Prof_C2Sub_Cent_etabin_ptbin" + suf, ";Centrality;#eta-bin; p_{T}-bin", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("Prof_C2Sub_Mult_etabin_ptbin" + suf, ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - - histos.add("Prof_Cov_Cent_etabin_ptbin" + suf, ";Centrality;#eta-bin; p_{T}-bin", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("Prof_Cov_Mult_etabin_ptbin" + suf, ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - - for (const int& i : {0, 1, 2}) { - std::string ptTag = "_ipt" + std::to_string(i); - histos.add("Prof" + ptTag + "_C2Sub2D_Cent_etaA_etaC" + suf, ";cent;#eta_{A};#eta_{C}", kTProfile3D, {{centAxis1Per}, {etaAxis}, {etaAxis}}); - histos.add("Prof" + ptTag + "_GapSum2D" + suf, ";cent;#Delta#eta (Gap);#Sigma#eta/2 (Sum)", kTProfile3D, {{centAxis1Per}, {gapAxis}, {sumAxis}}); - histos.add("Prof" + ptTag + "_Cov2D_Cent_etaA_etaC" + suf, ";cent;#eta_{A} bin;#eta_{C} bin", kTProfile3D, {{centAxis1Per}, {etaAxis}, {etaAxis}}); - } + for (const auto& suf : pidSuffix) { + histos.add("hEtaPhiReco" + suf, ";vz;sign;pt;eta;phi", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {etaAxis}, {phiAxis}}); + histos.add("hEtaPhiRecoEffWtd" + suf, ";vz;sign;pt;eta;phi", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {etaAxis}, {phiAxis}}); + histos.add("hEtaPhiRecoWtd" + suf, ";vz;sign;pt;eta;phi", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {etaAxis}, {phiAxis}}); + histos.add("Prof_C2Sub2D_Cent_etaA_etaC" + suf, ";cent;#eta_{A};#eta_{C}", kTProfile3D, {{centAxis1Per}, {etaAxis}, {etaAxis}}); + histos.add("Prof_GapSum2D" + suf, ";cent;#Delta#eta (Gap);#Sigma#eta/2 (Sum)", kTProfile3D, {{centAxis1Per}, {gapAxis}, {sumAxis}}); + histos.add("Prof_Cov2D_Cent_etaA_etaC" + suf, ";cent;#eta_{A} bin;#eta_{C} bin", kTProfile3D, {{centAxis1Per}, {etaAxis}, {etaAxis}}); + histos.add("Prof_CovFT0A2D_Cent_etaA_etaC" + suf, ";cent;#eta_{A};#eta_{B}", kTProfile3D, {{centAxis1Per}, {etaAxis}, {etaAxis}}); + histos.add("Prof_CovFT0C2D_Cent_etaA_etaC" + suf, ";cent;#eta_{A};#eta_{B}", kTProfile3D, {{centAxis1Per}, {etaAxis}, {etaAxis}}); } } @@ -800,7 +760,7 @@ struct RadialFlowDecorr { hWMap->Reset(); auto axV = hRaw->GetAxis(0); // Vz auto axChg = hRaw->GetAxis(1); // Charge - auto axPt = hRaw->GetAxis(2); // Charge + auto axPt = hRaw->GetAxis(2); // Pt auto axE = hRaw->GetAxis(3); // Eta auto axP = hRaw->GetAxis(4); // Phi @@ -861,7 +821,7 @@ struct RadialFlowDecorr { if (cfgSys == kPbPb) { nChAxis = {cfgNchPbMax / 4, KBinOffset, cfgNchPbMax + KBinOffset, "Nch", "PV-contributor track multiplicity"}; nChAxis2 = {cfgNchPbMax / 20, KBinOffset, cfgNchPbMax + KBinOffset, "Nch", "PV-contributor track multiplicity"}; - } else if (cfgSys == kOO || cfgSys == kpPb) { + } else if (cfgSys == kNeNe || cfgSys == kOO) { nChAxis = {cfgNchOMax / 2, KBinOffset, cfgNchOMax + KBinOffset, "Nch", "PV-contributor track multiplicity"}; nChAxis2 = {cfgNchOMax / 5, KBinOffset, cfgNchOMax + KBinOffset, "Nch", "PV-contributor track multiplicity"}; } else { @@ -875,17 +835,20 @@ struct RadialFlowDecorr { int64_t now = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); ccdb->setCreatedNotAfter(now); + loadAlignParam(now); + ft0Det.calculateChannelCenter(); + std::string sysDir = ""; switch (cfgSys) { case kPbPb: sysDir = "PbPbTest"; break; + case kNeNe: + sysDir = "NeNeTest"; + break; case kOO: sysDir = "OOTest"; break; - case kpPb: - sysDir = "pPbTest"; - break; case kpp: sysDir = "ppTest"; break; @@ -900,19 +863,6 @@ struct RadialFlowDecorr { std::string pathDataMean = cfgCCDBUserPath.value + "/" + sysDir + "/Job2_DataMean"; declareCommonQA(); - std::string userCcdbPath; - if (cfgSys == kPbPb) { - userCcdbPath = "/Users/s/somadutt/PbPbTest/"; - } - if (cfgSys == kOO) { - userCcdbPath = "/Users/s/somadutt/OOTest/"; - } - if (cfgSys == kpPb) { - userCcdbPath = "/Users/s/somadutt/pPbTest/"; - } - if (cfgSys == kpp) { - userCcdbPath = "/Users/s/somadutt/ppTest/"; - } if (cfgRunMCMean || cfgRunMCFluc || cfgRunGetEff) { declareMCCommonHists(); @@ -932,6 +882,8 @@ struct RadialFlowDecorr { } if (cfgRunGetMCFlat) { declareMCGetFlatHists(); + histos.addClone("MCGen/", "MCReco/"); + histos.addClone("MCGen/", "MCRecoEffCorr/"); } if (cfgRunDataMean) { declareDataMeanHists(); @@ -982,21 +934,18 @@ struct RadialFlowDecorr { } }; - // Loop through all PID types: kInclusive, kPion, kKaon, KProton - for (int i = 0; i < PID::numKNumPID; ++i) { + for (int i = 0; i < KNsp; ++i) { loadEffFakeForPID(static_cast(i)); } } if (!cfgRunGetEff && (cfgFlat)) { - // --- 1. Load Data Flattening Maps --- if (cfgRunDataMean || cfgRunDataFluc) { LOGF(info, "Data Run: Loading flattening maps from %s", pathDataFlat.c_str()); TList* lstDataFlat = ccdb->getForTimeStamp(pathDataFlat, now); if (lstDataFlat) { - // Use a loop to load species-specific flattening weights if they exist in data - for (int i = 0; i < PID::numKNumPID; ++i) { + for (int i = 0; i < KNsp; ++i) { std::string suffix = pidSuffix[i]; std::string hName; @@ -1020,7 +969,6 @@ struct RadialFlowDecorr { } } - // --- 2. Load MC Flattening Maps --- if (cfgRunMCMean || cfgRunMCFluc) { LOGF(info, "MC Run: Loading flattening maps from %s", pathMCFlat.c_str()); TList* lstMCFlat = ccdb->getForTimeStamp(pathMCFlat, now); @@ -1046,7 +994,7 @@ struct RadialFlowDecorr { } }; - for (int i = 0; i < PID::numKNumPID; ++i) { + for (int i = 0; i < KNsp; ++i) { loadFlatForPID(static_cast(i)); } } else { @@ -1058,7 +1006,6 @@ struct RadialFlowDecorr { auto loadTProfile3DFromList = [&](TList* sourceList, const char* objName, TProfile3D*& target) { if (!sourceList) return; - auto* tp = reinterpret_cast(sourceList->FindObject(objName)); if (tp) { target = reinterpret_cast(tp->Clone()); @@ -1069,21 +1016,34 @@ struct RadialFlowDecorr { } }; + auto loadTProfileFromList = [&](TList* sourceList, const char* objName, TProfile*& target) { + if (!sourceList) + return; + auto* tp = reinterpret_cast(sourceList->FindObject(objName)); + if (tp) { + target = reinterpret_cast(tp->Clone()); + target->SetDirectory(nullptr); + LOGF(info, "Loaded %s from list", objName); + } else { + LOGF(error, "Histogram %s missing in CCDB TList", objName); + } + }; + if (cfgRunMCFluc) { LOGF(info, "Loading MC Mean profiles from CCDB path: %s", pathMCMean.c_str()); TList* lstMCMean = ccdb->getForTimeStamp(pathMCMean, now); if (lstMCMean) { - for (int isp = 0; isp < KNsp; ++isp) { - std::string suf = pidSuffix[isp]; - loadTProfile3DFromList(lstMCMean, ("pmeanTruNchEtabinPtbin" + suf).c_str(), pmeanTruNchEtabinPtbinStep2[isp]); - loadTProfile3DFromList(lstMCMean, ("pmeanRecoNchEtabinPtbin" + suf).c_str(), pmeanRecoNchEtabinPtbinStep2[isp]); - loadTProfile3DFromList(lstMCMean, ("pmeanRecoEffcorrNchEtabinPtbin" + suf).c_str(), pmeanRecoEffcorrNchEtabinPtbinStep2[isp]); - - loadTProfile3DFromList(lstMCMean, ("pmeanMultTruNchEtabinPtbin" + suf).c_str(), pmeanMultTruNchEtabinPtbinStep2[isp]); - loadTProfile3DFromList(lstMCMean, ("pmeanMultRecoNchEtabinPtbin" + suf).c_str(), pmeanMultRecoNchEtabinPtbinStep2[isp]); - loadTProfile3DFromList(lstMCMean, ("pmeanMultRecoEffcorrNchEtabinPtbin" + suf).c_str(), pmeanMultRecoEffcorrNchEtabinPtbinStep2[isp]); - } + loadTProfileFromList(lstMCMean, "pmeanFT0Amultpv", pmeanFT0AmultpvStep2); + loadTProfileFromList(lstMCMean, "pmeanFT0Cmultpv", pmeanFT0CmultpvStep2); + + loadTProfile3DFromList(lstMCMean, "pmeanTru_nch_etabin_spbin", pmeanTruNchEtabinSpbinStep2); + loadTProfile3DFromList(lstMCMean, "pmeanReco_nch_etabin_spbin", pmeanRecoNchEtabinSpbinStep2); + loadTProfile3DFromList(lstMCMean, "pmeanRecoEffcorr_nch_etabin_spbin", pmeanRecoEffcorrNchEtabinSpbinStep2); + + loadTProfile3DFromList(lstMCMean, "pmeanMultTru_nch_etabin_spbin", pmeanMultTruNchEtabinSpbinStep2); + loadTProfile3DFromList(lstMCMean, "pmeanMultReco_nch_etabin_spbin", pmeanMultRecoNchEtabinSpbinStep2); + loadTProfile3DFromList(lstMCMean, "pmeanMultRecoEffcorr_nch_etabin_spbin", pmeanMultRecoEffcorrNchEtabinSpbinStep2); } else { LOGF(error, "Could not retrieve TList for MC Mean from: %s", pathMCMean.c_str()); } @@ -1094,11 +1054,11 @@ struct RadialFlowDecorr { TList* lstDataMean = ccdb->getForTimeStamp(pathDataMean, now); if (lstDataMean) { - for (int isp = 0; isp < KNsp; ++isp) { - std::string suf = pidSuffix[isp]; - loadTProfile3DFromList(lstDataMean, ("pmean_nch_etabin_ptbin" + suf).c_str(), pmeanNchEtabinPtbinStep2[isp]); - loadTProfile3DFromList(lstDataMean, ("pmeanMult_nch_etabin_ptbin" + suf).c_str(), pmeanMultNchEtabinPtbinStep2[isp]); - } + loadTProfileFromList(lstDataMean, "pmeanFT0Amultpv", pmeanFT0AmultpvStep2); + loadTProfileFromList(lstDataMean, "pmeanFT0Cmultpv", pmeanFT0CmultpvStep2); + + loadTProfile3DFromList(lstDataMean, "pmean_nch_etabin_spbin", pmeanNchEtabinSpbinStep2); + loadTProfile3DFromList(lstDataMean, "pmeanMult_nch_etabin_spbin", pmeanMultNchEtabinSpbinStep2); } else { LOGF(error, "Could not retrieve TList for Data Mean from: %s", pathDataMean.c_str()); } @@ -1106,7 +1066,7 @@ struct RadialFlowDecorr { LOGF(info, "CCDB initialization complete for RadialFlowDecorr."); } - void processGetEffHists(aod::McCollisions const& mcColl, MyRun3MCCollisions const& collisions, /*soa::SmallGroups const& collisions,*/ TCs const& tracks, FilteredTCs const& /*filteredTracks*/, aod::McParticles const& mcParticles) + void processGetEffHists(aod::McCollisions const& mcColl, MyRun3MCCollisions const& collisions, TCs const& tracks, FilteredTCs const& /*filteredTracks*/, aod::McParticles const& mcParticles) { for (const auto& mcCollision : mcColl) { auto colSlice = collisions.sliceBy(colPerMcCollision, mcCollision.globalIndex()); @@ -1135,35 +1095,51 @@ struct RadialFlowDecorr { histos.fill(HIST("Hist2D_globalTracks_PVTracks"), multPV, tracks.size()); histos.fill(HIST("Hist2D_cent_nch"), multPV, cent); - // --- Denominator: Truth Particles --- for (const auto& particle : partSlice) { if (!isParticleSelected(particle) || !particle.isPhysicalPrimary()) continue; - const int absPdgId = std::abs(particle.pdgCode()); + const int pdgCode = particle.pdgCode(); + const int absPdg = std::abs(pdgCode); float pt = particle.pt(); float eta = particle.eta(); - float w = particle.weight(); + bool isSpecies[KNsp] = { + true, // kInclusive + pdgCode == kPiMinus, // kPiMinus + pdgCode == kPiPlus, // kPiPlus + absPdg == kPiPlus, // kPiAll + pdgCode == kKMinus, // kKaMinus + pdgCode == kKPlus, // kKaPlus + absPdg == kKPlus, // kKaAll + pdgCode == kProtonBar, // kAntiProton + pdgCode == kProton, // kProton + absPdg == kProton // kAllProton + }; - // Inclusive (Denominator) - histos.fill(HIST("hTruth_ParticleWeight"), cent, pt, eta, w); histos.fill(HIST("h3_AllPrimary"), multPV, pt, eta); - histos.fill(HIST("h_AllPrimary"), pt); - - // Species Specific Denominators - if (absPdgId == KPiPlus) { - histos.fill(HIST("hTruth_ParticleWeight_Pi"), cent, pt, eta, w); - histos.fill(HIST("h3_AllPrimary_Pi"), multPV, pt, eta); - } else if (absPdgId == KKPlus) { - histos.fill(HIST("hTruth_ParticleWeight_Ka"), cent, pt, eta, w); - histos.fill(HIST("h3_AllPrimary_Ka"), multPV, pt, eta); - } else if (absPdgId == KProton) { - histos.fill(HIST("hTruth_ParticleWeight_Pr"), cent, pt, eta, w); + + if (isSpecies[kPiMinus]) + histos.fill(HIST("h3_AllPrimary_PiMinus"), multPV, pt, eta); + else if (isSpecies[kPiPlus]) + histos.fill(HIST("h3_AllPrimary_PiPlus"), multPV, pt, eta); + if (isSpecies[kPiAll]) + histos.fill(HIST("h3_AllPrimary_PiAll"), multPV, pt, eta); + + if (isSpecies[kKaMinus]) + histos.fill(HIST("h3_AllPrimary_KaMinus"), multPV, pt, eta); + else if (isSpecies[kKaPlus]) + histos.fill(HIST("h3_AllPrimary_KaPlus"), multPV, pt, eta); + if (isSpecies[kKaAll]) + histos.fill(HIST("h3_AllPrimary_KaAll"), multPV, pt, eta); + + if (isSpecies[kAntiProton]) + histos.fill(HIST("h3_AllPrimary_AntiPr"), multPV, pt, eta); + else if (isSpecies[kProton]) histos.fill(HIST("h3_AllPrimary_Pr"), multPV, pt, eta); - } + if (isSpecies[kAllProton]) + histos.fill(HIST("h3_AllPrimary_AllPr"), multPV, pt, eta); } - // --- Numerator and Fakes: Reconstructed Tracks --- for (const auto& track : trackSlice) { if (!isTrackSelected(track)) continue; @@ -1171,79 +1147,157 @@ struct RadialFlowDecorr { float pt = track.pt(); float eta = track.eta(); float phi = track.phi(); + auto sign = track.sign(); bool isPi = selectionPion(track); bool isKa = selectionKaon(track); bool isPr = selectionProton(track); - // Inclusive QA - histos.fill(HIST("h_AllReco"), pt); - histos.fill(HIST("h3_AllReco"), multPV, pt, eta); - histos.fill(HIST("hEtaPhiReco"), col.posZ(), track.sign(), pt, eta, phi); - - // Species QA (Fills based on your PID selection) - if (isPi) { - histos.fill(HIST("h3_AllReco_Pi"), multPV, pt, eta); - } - if (isKa) { - histos.fill(HIST("h3_AllReco_Ka"), multPV, pt, eta); - } - if (isPr) { - histos.fill(HIST("h3_AllReco_Pr"), multPV, pt, eta); - } - - if (track.has_mcParticle()) { - auto mcPart2 = track.mcParticle(); - const int absPdgId = std::abs(mcPart2.pdgCode()); - - if (mcPart2.isPhysicalPrimary()) { - - histos.fill(HIST("ptResolution"), mcPart2.pt(), (pt - mcPart2.pt()) / mcPart2.pt()); - histos.fill(HIST("etaResolution"), mcPart2.eta(), eta - mcPart2.eta()); - histos.fill(HIST("etaTruthReco"), mcPart2.eta(), eta); - histos.fill(HIST("vzResolution"), mcPart2.vz(), (col.posZ() - mcPart2.vz()) / mcPart2.vz()); - histos.fill(HIST("TruthTracKVz"), mcPart2.vz(), col.posZ()); - - // Reconstructed Numerator (Inclusive) - histos.fill(HIST("h3_RecoMatchedToPrimary"), multPV, mcPart2.pt(), mcPart2.eta()); - histos.fill(HIST("h_RecoMatchedToPrimary"), pt); + bool isSpecies[KNsp] = { + true, // kInclusive + isPi && sign < 0, // kPiMinus + isPi && sign > 0, // kPiPlus + isPi, // kPiAll + isKa && sign < 0, // kKaMinus + isKa && sign > 0, // kKaPlus + isKa, // kKaAll + isPr && sign < 0, // kAntiProton + isPr && sign > 0, // kProton + isPr // kAllProton + }; - // Species Matching (Efficiency Numerator) - // We fill ONLY if the reconstructed PID matches the Truth PDG - if (isPi && absPdgId == KPiPlus) - histos.fill(HIST("h3_RecoMatchedToPrimary_Pi"), multPV, mcPart2.pt(), mcPart2.eta()); - if (isKa && absPdgId == KKPlus) - histos.fill(HIST("h3_RecoMatchedToPrimary_Ka"), multPV, mcPart2.pt(), mcPart2.eta()); - if (isPr && absPdgId == KProton) - histos.fill(HIST("h3_RecoMatchedToPrimary_Pr"), multPV, mcPart2.pt(), mcPart2.eta()); + for (int isp = 0; isp < KNsp; ++isp) { + if (!isSpecies[isp]) + continue; - } else { - // Secondary (Contamination) - histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary"), multPV, pt, eta); - histos.fill(HIST("h_RecoUnMatchedToPrimary"), pt); - if (isPi) - histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_Pi"), multPV, pt, eta); - if (isKa) - histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_Ka"), multPV, pt, eta); - if (isPr) - histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_Pr"), multPV, pt, eta); + if (isp == kInclusive) { + histos.fill(HIST("h3_AllReco"), multPV, pt, eta); + histos.fill(HIST("hEtaPhiReco"), col.posZ(), sign, pt, eta, phi); + if (track.has_mcParticle()) { + auto mcP = track.mcParticle(); + + if (mcP.isPhysicalPrimary()) { + histos.fill(HIST("ptResolution"), mcP.pt(), (pt - mcP.pt()) / mcP.pt()); + histos.fill(HIST("etaResolution"), mcP.eta(), eta - mcP.eta()); + histos.fill(HIST("etaTruthReco"), mcP.eta(), eta); + histos.fill(HIST("vzResolution"), mcP.vz(), (col.posZ() - mcP.vz()) / mcP.vz()); + histos.fill(HIST("TruthTracKVz"), mcP.vz(), col.posZ()); + + histos.fill(HIST("h3_RecoMatchedToPrimary"), multPV, mcP.pt(), mcP.eta()); + } else { + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary"), multPV, pt, eta); + histos.fill(HIST("h_RecoUnMatchedToPrimary"), pt); + } + } else { + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake"), multPV, pt, eta); + } + } else if (isp == kPiMinus) { + histos.fill(HIST("h3_AllReco_PiMinus"), multPV, pt, eta); + if (track.has_mcParticle()) { + auto mcP = track.mcParticle(); + if (mcP.isPhysicalPrimary() && mcP.pdgCode() == kPiMinus) + histos.fill(HIST("h3_RecoMatchedToPrimary_PiMinus"), multPV, mcP.pt(), mcP.eta()); + else if (!mcP.isPhysicalPrimary()) + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_PiMinus"), multPV, pt, eta); + } else { + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_PiMinus"), multPV, pt, eta); + } + } else if (isp == kPiPlus) { + histos.fill(HIST("h3_AllReco_PiPlus"), multPV, pt, eta); + if (track.has_mcParticle()) { + auto mcP = track.mcParticle(); + if (mcP.isPhysicalPrimary() && mcP.pdgCode() == kPiPlus) + histos.fill(HIST("h3_RecoMatchedToPrimary_PiPlus"), multPV, mcP.pt(), mcP.eta()); + else if (!mcP.isPhysicalPrimary()) + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_PiPlus"), multPV, pt, eta); + } else { + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_PiPlus"), multPV, pt, eta); + } + } else if (isp == kPiAll) { + histos.fill(HIST("h3_AllReco_PiAll"), multPV, pt, eta); + if (track.has_mcParticle()) { + auto mcP = track.mcParticle(); + if (mcP.isPhysicalPrimary() && std::abs(mcP.pdgCode()) == kPiPlus) + histos.fill(HIST("h3_RecoMatchedToPrimary_PiAll"), multPV, mcP.pt(), mcP.eta()); + else if (!mcP.isPhysicalPrimary()) + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_PiAll"), multPV, pt, eta); + } else { + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_PiAll"), multPV, pt, eta); + } + } else if (isp == kKaMinus) { + histos.fill(HIST("h3_AllReco_KaMinus"), multPV, pt, eta); + if (track.has_mcParticle()) { + auto mcP = track.mcParticle(); + if (mcP.isPhysicalPrimary() && mcP.pdgCode() == kKMinus) + histos.fill(HIST("h3_RecoMatchedToPrimary_KaMinus"), multPV, mcP.pt(), mcP.eta()); + else if (!mcP.isPhysicalPrimary()) + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_KaMinus"), multPV, pt, eta); + } else { + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_KaMinus"), multPV, pt, eta); + } + } else if (isp == kKaPlus) { + histos.fill(HIST("h3_AllReco_KaPlus"), multPV, pt, eta); + if (track.has_mcParticle()) { + auto mcP = track.mcParticle(); + if (mcP.isPhysicalPrimary() && mcP.pdgCode() == kKPlus) + histos.fill(HIST("h3_RecoMatchedToPrimary_KaPlus"), multPV, mcP.pt(), mcP.eta()); + else if (!mcP.isPhysicalPrimary()) + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_KaPlus"), multPV, pt, eta); + } else { + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_KaPlus"), multPV, pt, eta); + } + } else if (isp == kKaAll) { + histos.fill(HIST("h3_AllReco_KaAll"), multPV, pt, eta); + if (track.has_mcParticle()) { + auto mcP = track.mcParticle(); + if (mcP.isPhysicalPrimary() && std::abs(mcP.pdgCode()) == kKPlus) + histos.fill(HIST("h3_RecoMatchedToPrimary_KaAll"), multPV, mcP.pt(), mcP.eta()); + else if (!mcP.isPhysicalPrimary()) + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_KaAll"), multPV, pt, eta); + } else { + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_KaAll"), multPV, pt, eta); + } + } else if (isp == kAntiProton) { + histos.fill(HIST("h3_AllReco_AntiPr"), multPV, pt, eta); + if (track.has_mcParticle()) { + auto mcP = track.mcParticle(); + if (mcP.isPhysicalPrimary() && mcP.pdgCode() == kProtonBar) + histos.fill(HIST("h3_RecoMatchedToPrimary_AntiPr"), multPV, mcP.pt(), mcP.eta()); + else if (!mcP.isPhysicalPrimary()) + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_AntiPr"), multPV, pt, eta); + } else { + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_AntiPr"), multPV, pt, eta); + } + } else if (isp == kProton) { + histos.fill(HIST("h3_AllReco_Pr"), multPV, pt, eta); + if (track.has_mcParticle()) { + auto mcP = track.mcParticle(); + if (mcP.isPhysicalPrimary() && mcP.pdgCode() == kProton) + histos.fill(HIST("h3_RecoMatchedToPrimary_Pr"), multPV, mcP.pt(), mcP.eta()); + else if (!mcP.isPhysicalPrimary()) + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_Pr"), multPV, pt, eta); + } else { + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_Pr"), multPV, pt, eta); + } + } else if (isp == kAllProton) { + histos.fill(HIST("h3_AllReco_AllPr"), multPV, pt, eta); + if (track.has_mcParticle()) { + auto mcP = track.mcParticle(); + if (mcP.isPhysicalPrimary() && std::abs(mcP.pdgCode()) == kProton) + histos.fill(HIST("h3_RecoMatchedToPrimary_AllPr"), multPV, mcP.pt(), mcP.eta()); + else if (!mcP.isPhysicalPrimary()) + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_AllPr"), multPV, pt, eta); + } else { + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_AllPr"), multPV, pt, eta); + } } - } else { - // Fake Tracks (No MC matching) - histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake"), multPV, pt, eta); - if (isPi) - histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_Pi"), multPV, pt, eta); - if (isKa) - histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_Ka"), multPV, pt, eta); - if (isPr) - histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_Pr"), multPV, pt, eta); - } - } + } // end isp loop + } // end track loop } } LOGF(info, "FINISHED RUNNING processGetEffHists"); } - PROCESS_SWITCH(RadialFlowDecorr, processGetEffHists, "process MC to calculate Eff and Fakes", cfgRunGetEff); + PROCESS_SWITCH(RadialFlowDecorr, processGetEffHists, "process MC to calculate EffWeights", cfgRunGetEff); void processMCFlat(aod::McCollisions const& mcColl, MyRun3MCCollisions const& collisions, /*soa::SmallGroups const& collisions,*/ TCs const& tracks, FilteredTCs const& /*filteredTracks*/, aod::McParticles const& mcParticles) { @@ -1272,46 +1326,64 @@ struct RadialFlowDecorr { float phi = track.phi(); auto sign = track.sign(); - // 1. Inclusive Weighting (Always filled for selected tracks) - float effIncl = getEfficiency(multPV, pt, eta, numKInclusive, 0, cfgEff); - float fakeIncl = getEfficiency(multPV, pt, eta, numKInclusive, 1, cfgEff); - float wIncl = (1.0 - fakeIncl) / effIncl; - - if (std::isfinite(wIncl) && wIncl > 0.f && effIncl > KFloatEpsilon) { - histos.fill(HIST("hEtaPhiRecoEffWtd"), vz, sign, pt, eta, phi, wIncl); - histos.fill(HIST("hEtaPhiReco"), vz, sign, pt, eta, phi, 1.0); - } + bool isPi = selectionPion(track); + bool isKa = selectionKaon(track); + bool isPr = selectionProton(track); - // 2. Pion Weighting - if (selectionPion(track)) { - float effPi = getEfficiency(multPV, pt, eta, numKPion, 0, cfgEff); - float fakePi = getEfficiency(multPV, pt, eta, numKPion, 1, cfgEff); - float wPi = (1.0 - fakePi) / effPi; - if (std::isfinite(wPi) && wPi > 0.f && effPi > KFloatEpsilon) { - histos.fill(HIST("hEtaPhiRecoEffWtd_Pi"), vz, sign, pt, eta, phi, wPi); - histos.fill(HIST("hEtaPhiReco_Pi"), vz, sign, pt, eta, phi, 1.0); - } - } + bool isSpecies[KNsp] = { + true, // kInclusive + isPi && sign < 0, // kPiMinus + isPi && sign > 0, // kPiPlus + isPi, // kPiAll + isKa && sign < 0, // kKaMinus + isKa && sign > 0, // kKaPlus + isKa, // kKaAll + isPr && sign < 0, // kAntiProton (Negative) + isPr && sign > 0, // kProton (Positive) + isPr // kAllProton + }; - // 3. Kaon Weighting - if (selectionKaon(track)) { - float effKa = getEfficiency(multPV, pt, eta, numKKaon, 0, cfgEff); - float fakeKa = getEfficiency(multPV, pt, eta, numKKaon, 1, cfgEff); - float wKa = (1.0 - fakeKa) / effKa; - if (std::isfinite(wKa) && wKa > 0.f && effKa > KFloatEpsilon) { - histos.fill(HIST("hEtaPhiRecoEffWtd_Ka"), vz, sign, pt, eta, phi, wKa); - histos.fill(HIST("hEtaPhiReco_Ka"), vz, sign, pt, eta, phi, 1.0); - } - } + for (int isp = 0; isp < KNsp; ++isp) { + if (!isSpecies[isp]) + continue; + std::string suffix = pidSuffix[isp]; - // 4. Proton Weighting - if (selectionProton(track)) { - float effPr = getEfficiency(multPV, pt, eta, numKProton, 0, cfgEff); - float fakePr = getEfficiency(multPV, pt, eta, numKProton, 1, cfgEff); - float wPr = (1.0 - fakePr) / effPr; - if (std::isfinite(wPr) && wPr > 0.f && effPr > KFloatEpsilon) { - histos.fill(HIST("hEtaPhiRecoEffWtd_Pr"), vz, sign, pt, eta, phi, wPr); - histos.fill(HIST("hEtaPhiReco_Pr"), vz, sign, pt, eta, phi, 1.0); + float eff = getEfficiency(multPV, pt, eta, static_cast(isp), 0, cfgEff); + float fake = getEfficiency(multPV, pt, eta, static_cast(isp), 1, cfgEff); + float w = (1.0 - fake) / eff; + + if (std::isfinite(w) && w > 0.f && eff > KFloatEpsilon) { + if (isp == kInclusive) { + histos.fill(HIST("hEtaPhiRecoEffWtd"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiReco"), vz, sign, pt, eta, phi, 1.0); + } else if (isp == kPiMinus) { + histos.fill(HIST("hEtaPhiRecoEffWtd_PiMinus"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiReco_PiMinus"), vz, sign, pt, eta, phi, 1.0); + } else if (isp == kPiPlus) { + histos.fill(HIST("hEtaPhiRecoEffWtd_PiPlus"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiReco_PiPlus"), vz, sign, pt, eta, phi, 1.0); + } else if (isp == kPiAll) { + histos.fill(HIST("hEtaPhiRecoEffWtd_PiAll"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiReco_PiAll"), vz, sign, pt, eta, phi, 1.0); + } else if (isp == kKaMinus) { + histos.fill(HIST("hEtaPhiRecoEffWtd_KaMinus"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiReco_KaMinus"), vz, sign, pt, eta, phi, 1.0); + } else if (isp == kKaPlus) { + histos.fill(HIST("hEtaPhiRecoEffWtd_KaPlus"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiReco_KaPlus"), vz, sign, pt, eta, phi, 1.0); + } else if (isp == kKaAll) { + histos.fill(HIST("hEtaPhiRecoEffWtd_KaAll"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiReco_KaAll"), vz, sign, pt, eta, phi, 1.0); + } else if (isp == kAntiProton) { + histos.fill(HIST("hEtaPhiRecoEffWtd_AntiPr"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiReco_AntiPr"), vz, sign, pt, eta, phi, 1.0); + } else if (isp == kProton) { + histos.fill(HIST("hEtaPhiRecoEffWtd_Pr"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiReco_Pr"), vz, sign, pt, eta, phi, 1.0); + } else if (isp == kAllProton) { + histos.fill(HIST("hEtaPhiRecoEffWtd_AllPr"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiReco_AllPr"), vz, sign, pt, eta, phi, 1.0); + } } } } // end track loop @@ -1321,12 +1393,11 @@ struct RadialFlowDecorr { } PROCESS_SWITCH(RadialFlowDecorr, processMCFlat, "process MC to calculate FlatWeights", cfgRunGetMCFlat); - void processMCMean(aod::McCollisions const& mcColl, MyRun3MCCollisions const& collisions, TCs const& tracks, FilteredTCs const& /*filteredTracks*/, aod::McParticles const& mcParticles) + void processMCMean(aod::McCollisions const& mcColl, MyRun3MCCollisions const& collisions, TCs const& tracks, FilteredTCs const& /*filteredTracks*/, aod::FT0s const&, aod::McParticles const& mcParticles) { - // Track-sum arrays using KNsp index (isp=0: Incl, 1: Pi, 2: Ka, 3: Pr) - double sumWiTruth[KNsp][KNEta][KNpT]{}, sumWiptiTruth[KNsp][KNEta][KNpT]{}; - double sumWiReco[KNsp][KNEta][KNpT]{}, sumWiptiReco[KNsp][KNEta][KNpT]{}; - double sumWiRecoEffCorr[KNsp][KNEta][KNpT]{}, sumWiptiRecoEffCorr[KNsp][KNEta][KNpT]{}; + double sumWiTruth[KNsp][KNEta]{}, sumWiptiTruth[KNsp][KNEta]{}; + double sumWiReco[KNsp][KNEta]{}, sumWiptiReco[KNsp][KNEta]{}; + double sumWiRecoEffCorr[KNsp][KNEta]{}, sumWiptiRecoEffCorr[KNsp][KNEta]{}; for (const auto& mcCollision : mcColl) { auto colSlice = collisions.sliceBy(colPerMcCollision, mcCollision.globalIndex()); @@ -1348,7 +1419,6 @@ struct RadialFlowDecorr { float multPV = col.multNTracksPV(); float vz = col.posZ(); - // Reset local event sum memset(sumWiTruth, 0, sizeof(sumWiTruth)); memset(sumWiptiTruth, 0, sizeof(sumWiptiTruth)); memset(sumWiReco, 0, sizeof(sumWiReco)); @@ -1356,73 +1426,74 @@ struct RadialFlowDecorr { memset(sumWiRecoEffCorr, 0, sizeof(sumWiRecoEffCorr)); memset(sumWiptiRecoEffCorr, 0, sizeof(sumWiptiRecoEffCorr)); - // --- 1. Truth Loop --- for (const auto& particle : partSlice) { if (!isParticleSelected(particle) || !particle.isPhysicalPrimary()) continue; float pt = particle.pt(), eta = particle.eta(); - const int absPdgId = std::abs(particle.pdgCode()); - bool isSpecies[KNsp] = {true, (absPdgId == KPiPlus), (absPdgId == KKPlus), (absPdgId == KProton)}; + if (pt <= KPtMin || pt > KPtMax) + continue; + int pdgCode = particle.pdgCode(); + int absPdg = std::abs(pdgCode); + + bool isSpecies[KNsp] = { + true, // kInclusive + pdgCode == kPiMinus, // kPiMinus + pdgCode == kPiPlus, // kPiPlus + absPdg == kPiPlus, // kPiAll + pdgCode == kKMinus, // kKaMinus + pdgCode == kKPlus, // kKaPlus + absPdg == kKPlus, // kKaAll + pdgCode == kProtonBar, // kAntiProton + pdgCode == kProton, // kProton + absPdg == kProton // kAllProton + }; + for (int ieta = 0; ieta < KNEta; ++ieta) { if (eta <= etaLw[ieta] || eta > etaUp[ieta]) continue; - for (int ipt = 0; ipt < KNpT; ++ipt) { - if (pt <= pTLw[ipt] || pt > pTUp[ipt]) - continue; - for (int isp = 0; isp < KNsp; ++isp) { - if (isSpecies[isp]) { - sumWiTruth[isp][ieta][ipt]++; - sumWiptiTruth[isp][ieta][ipt] += pt; - } + + for (int isp = 0; isp < KNsp; ++isp) { + if (isSpecies[isp]) { + sumWiTruth[isp][ieta]++; + sumWiptiTruth[isp][ieta] += pt; } } } } for (int isp = 0; isp < KNsp; ++isp) { - if (isp == numKInclusive) { - histos.fill(HIST("MCGen/Prof_Cent_Nchrec"), cent, sumWiTruth[0][0][0]); - histos.fill(HIST("MCGen/Prof_Mult_Nchrec"), multPV, sumWiTruth[0][0][0]); - if (sumWiTruth[0][0][0] > 1.0f) { - histos.fill(HIST("MCGen/Prof_Cent_MeanpT"), cent, sumWiptiTruth[0][0][0] / sumWiTruth[0][0][0]); - histos.fill(HIST("MCGen/Prof_Mult_MeanpT"), multPV, sumWiptiTruth[0][0][0] / sumWiTruth[0][0][0]); - } - - } else if (isp == numKPion) { - histos.fill(HIST("MCGen/Prof_Cent_Nchrec_Pi"), cent, sumWiTruth[1][0][0]); - histos.fill(HIST("MCGen/Prof_Mult_Nchrec_Pi"), multPV, sumWiTruth[1][0][0]); - - if (sumWiTruth[1][0][0] > 1.0f) { - histos.fill(HIST("MCGen/Prof_Cent_MeanpT_Pi"), cent, sumWiptiTruth[1][0][0] / sumWiTruth[1][0][0]); - histos.fill(HIST("MCGen/Prof_Mult_MeanpT_Pi"), multPV, sumWiptiTruth[1][0][0] / sumWiTruth[1][0][0]); - } - - } else if (isp == numKKaon) { - histos.fill(HIST("MCGen/Prof_Cent_Nchrec_Ka"), cent, sumWiTruth[2][0][0]); - histos.fill(HIST("MCGen/Prof_Mult_Nchrec_Ka"), multPV, sumWiTruth[2][0][0]); - - if (sumWiTruth[2][0][0] > 1.0f) { - histos.fill(HIST("MCGen/Prof_Cent_MeanpT_Ka"), cent, sumWiptiTruth[2][0][0] / sumWiTruth[2][0][0]); - histos.fill(HIST("MCGen/Prof_Mult_MeanpT_Ka"), multPV, sumWiptiTruth[2][0][0] / sumWiTruth[2][0][0]); - } - } else if (isp == numKProton) { - histos.fill(HIST("MCGen/Prof_Cent_Nchrec_Pr"), cent, sumWiTruth[3][0][0]); - histos.fill(HIST("MCGen/Prof_Mult_Nchrec_Pr"), multPV, sumWiTruth[3][0][0]); - - if (sumWiTruth[3][0][0] > 1.0f) { - histos.fill(HIST("MCGen/Prof_Cent_MeanpT_Pr"), cent, sumWiptiTruth[3][0][0] / sumWiTruth[3][0][0]); - histos.fill(HIST("MCGen/Prof_Mult_MeanpT_Pr"), multPV, sumWiptiTruth[3][0][0] / sumWiTruth[3][0][0]); - } + histos.fill(HIST("MCGen/Prof_Cent_Nsp_Nchrec"), cent, isp, sumWiTruth[isp][0]); + histos.fill(HIST("MCGen/Prof_Mult_Nsp_Nchrec"), multPV, isp, sumWiTruth[isp][0]); + if (sumWiTruth[isp][0] > 1.0f) { + histos.fill(HIST("MCGen/Prof_Cent_Nsp_MeanpT"), cent, isp, sumWiptiTruth[isp][0] / sumWiTruth[isp][0]); + histos.fill(HIST("MCGen/Prof_Mult_Nsp_MeanpT"), multPV, isp, sumWiptiTruth[isp][0] / sumWiTruth[isp][0]); } } - // --- 2. Reco Loop --- for (const auto& track : trackSlice) { if (!isTrackSelected(track)) continue; float pt = track.pt(), eta = track.eta(), phi = track.phi(); + if (pt <= KPtMin || pt > KPtMax) + continue; auto sign = track.sign(); - bool isSpecies[KNsp] = {true, selectionPion(track), selectionKaon(track), selectionProton(track)}; + bool isPi = selectionPion(track); + bool isKa = selectionKaon(track); + bool isPr = selectionProton(track); + + bool isSpecies[KNsp] = { + true, // kInclusive + isPi && sign < 0, // kPiMinus + isPi && sign > 0, // kPiPlus + isPi, // kPiAll + isKa && sign < 0, // kKaMinus + isKa && sign > 0, // kKaPlus + isKa, // kKaAll + isPr && sign < 0, // kAntiProton (Negative) + isPr && sign > 0, // kProton (Positive) + isPr // kAllProton + }; + for (int isp = 0; isp < KNsp; ++isp) { if (!isSpecies[isp]) continue; @@ -1436,347 +1507,245 @@ struct RadialFlowDecorr { for (int ieta = 0; ieta < KNEta; ++ieta) { if (eta <= etaLw[ieta] || eta > etaUp[ieta]) continue; - for (int ipt = 0; ipt < KNpT; ++ipt) { - if (pt <= pTLw[ipt] || pt > pTUp[ipt]) - continue; - sumWiReco[isp][ieta][ipt]++; - sumWiptiReco[isp][ieta][ipt] += pt; - sumWiRecoEffCorr[isp][ieta][ipt] += w; - sumWiptiRecoEffCorr[isp][ieta][ipt] += w * pt; - - if (ipt == 0) { - // Fill profiles vs. Centrality - histos.fill(HIST("Eff_cent"), cent, eff); - histos.fill(HIST("Fake_cent"), cent, fake); - histos.fill(HIST("wgt_cent"), cent, w); - - // Fill profiles vs. Multiplicity (Ntrk) - histos.fill(HIST("Eff_Ntrk"), multPV, eff); - histos.fill(HIST("Fake_Ntrk"), multPV, fake); - histos.fill(HIST("wgt_Ntrk"), multPV, w); - - // Fill profiles vs. pT - histos.fill(HIST("Eff_pT"), pt, eff); - histos.fill(HIST("Fake_pT"), pt, fake); - histos.fill(HIST("wgt_pT"), pt, w); - - // Fill profiles vs. Eta - histos.fill(HIST("Eff_eta"), eta, eff); - histos.fill(HIST("Fake_eta"), eta, fake); - histos.fill(HIST("wgt_eta"), eta, w); - } - } + sumWiReco[isp][ieta]++; + sumWiptiReco[isp][ieta] += pt; + sumWiRecoEffCorr[isp][ieta] += w; + sumWiptiRecoEffCorr[isp][ieta] += w * pt; } - if (isp == numKInclusive) { + if (isp == kInclusive) { + histos.fill(HIST("Eff_cent"), cent, eff); + histos.fill(HIST("Fake_cent"), cent, fake); + histos.fill(HIST("wgt_cent"), cent, w); - histos.fill(HIST("hEtaPhiReco"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoWtd"), vz, sign, pt, eta, phi, w); - histos.fill(HIST("hEtaPhiRecoEffWtd"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + histos.fill(HIST("Eff_Ntrk"), multPV, eff); + histos.fill(HIST("Fake_Ntrk"), multPV, fake); + histos.fill(HIST("wgt_Ntrk"), multPV, w); - } else if (isp == numKPion) { // Pion - histos.fill(HIST("hEtaPhiReco_Pi"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoWtd_Pi"), vz, sign, pt, eta, phi, w); - histos.fill(HIST("hEtaPhiRecoEffWtd_Pi"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + histos.fill(HIST("Eff_pT"), pt, eff); + histos.fill(HIST("Fake_pT"), pt, fake); + histos.fill(HIST("wgt_pT"), pt, w); - } else if (isp == numKKaon) { // Kaon - histos.fill(HIST("hEtaPhiReco_Ka"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoWtd_Ka"), vz, sign, pt, eta, phi, w); - histos.fill(HIST("hEtaPhiRecoEffWtd_Ka"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + histos.fill(HIST("Eff_eta"), eta, eff); + histos.fill(HIST("Fake_eta"), eta, fake); + histos.fill(HIST("wgt_eta"), eta, w); + } - } else if (isp == numKProton) { // Proton + if (isp == kInclusive) { + histos.fill(HIST("hEtaPhiReco"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kPiMinus) { + histos.fill(HIST("hEtaPhiReco_PiMinus"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_PiMinus"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_PiMinus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kPiPlus) { + histos.fill(HIST("hEtaPhiReco_PiPlus"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_PiPlus"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_PiPlus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kPiAll) { + histos.fill(HIST("hEtaPhiReco_PiAll"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_PiAll"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_PiAll"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kKaMinus) { + histos.fill(HIST("hEtaPhiReco_KaMinus"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_KaMinus"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_KaMinus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kKaPlus) { + histos.fill(HIST("hEtaPhiReco_KaPlus"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_KaPlus"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_KaPlus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kKaAll) { + histos.fill(HIST("hEtaPhiReco_KaAll"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_KaAll"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_KaAll"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kProton) { histos.fill(HIST("hEtaPhiReco_Pr"), vz, sign, pt, eta, phi); histos.fill(HIST("hEtaPhiRecoWtd_Pr"), vz, sign, pt, eta, phi, w); histos.fill(HIST("hEtaPhiRecoEffWtd_Pr"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kAntiProton) { + histos.fill(HIST("hEtaPhiReco_AntiPr"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_AntiPr"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_AntiPr"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kAllProton) { + histos.fill(HIST("hEtaPhiReco_AllPr"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_AllPr"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_AllPr"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); } } } for (int isp = 0; isp < KNsp; ++isp) { - if (isp == numKInclusive) { - histos.fill(HIST("MCReco/Prof_Cent_Nchrec"), cent, sumWiReco[0][0][0]); - histos.fill(HIST("MCReco/Prof_Mult_Nchrec"), multPV, sumWiReco[0][0][0]); - if (sumWiReco[0][0][0] > 1.0f) { - histos.fill(HIST("MCReco/Prof_Cent_MeanpT"), cent, sumWiptiReco[0][0][0] / sumWiReco[0][0][0]); - histos.fill(HIST("MCReco/Prof_Mult_MeanpT"), multPV, sumWiptiReco[0][0][0] / sumWiReco[0][0][0]); - } - - } else if (isp == numKPion) { - histos.fill(HIST("MCReco/Prof_Cent_Nchrec_Pi"), cent, sumWiReco[1][0][0]); - histos.fill(HIST("MCReco/Prof_Mult_Nchrec_Pi"), multPV, sumWiReco[1][0][0]); - - if (sumWiReco[1][0][0] > 1.0f) { - histos.fill(HIST("MCReco/Prof_Cent_MeanpT_Pi"), cent, sumWiptiReco[1][0][0] / sumWiReco[1][0][0]); - histos.fill(HIST("MCReco/Prof_Mult_MeanpT_Pi"), multPV, sumWiptiReco[1][0][0] / sumWiReco[1][0][0]); - } + histos.fill(HIST("MCReco/Prof_Cent_Nsp_Nchrec"), cent, isp, sumWiReco[isp][0]); + histos.fill(HIST("MCReco/Prof_Mult_Nsp_Nchrec"), multPV, isp, sumWiReco[isp][0]); - } else if (isp == numKKaon) { - histos.fill(HIST("MCReco/Prof_Cent_Nchrec_Ka"), cent, sumWiReco[2][0][0]); - histos.fill(HIST("MCReco/Prof_Mult_Nchrec_Ka"), multPV, sumWiReco[2][0][0]); + histos.fill(HIST("MCRecoEffCorr/Prof_Cent_Nsp_Nchrec"), cent, isp, sumWiRecoEffCorr[isp][0]); + histos.fill(HIST("MCRecoEffCorr/Prof_Mult_Nsp_Nchrec"), multPV, isp, sumWiRecoEffCorr[isp][0]); - if (sumWiReco[2][0][0] > 1.0f) { - histos.fill(HIST("MCReco/Prof_Cent_MeanpT_Ka"), cent, sumWiptiReco[2][0][0] / sumWiReco[2][0][0]); - histos.fill(HIST("MCReco/Prof_Mult_MeanpT_Ka"), multPV, sumWiptiReco[2][0][0] / sumWiReco[2][0][0]); - } - } else if (isp == numKProton) { - histos.fill(HIST("MCReco/Prof_Cent_Nchrec_Pr"), cent, sumWiReco[3][0][0]); - histos.fill(HIST("MCReco/Prof_Mult_Nchrec_Pr"), multPV, sumWiReco[3][0][0]); - if (sumWiReco[3][0][0] > 1.0f) { - histos.fill(HIST("MCReco/Prof_Cent_MeanpT_Pr"), cent, sumWiptiReco[3][0][0] / sumWiReco[3][0][0]); - histos.fill(HIST("MCReco/Prof_Mult_MeanpT_Pr"), multPV, sumWiptiReco[3][0][0] / sumWiReco[3][0][0]); - } + if (sumWiReco[isp][0] > 1.0f) { + histos.fill(HIST("MCReco/Prof_Cent_Nsp_MeanpT"), cent, isp, sumWiptiReco[isp][0] / sumWiReco[isp][0]); + histos.fill(HIST("MCReco/Prof_Mult_Nsp_MeanpT"), multPV, isp, sumWiptiReco[isp][0] / sumWiReco[isp][0]); } - - if (isp == numKInclusive) { - histos.fill(HIST("MCRecoEffCorr/Prof_Cent_Nchrec"), cent, sumWiRecoEffCorr[0][0][0]); - histos.fill(HIST("MCRecoEffCorr/Prof_Mult_Nchrec"), multPV, sumWiRecoEffCorr[0][0][0]); - if (sumWiRecoEffCorr[0][0][0] > 1.0f) { - histos.fill(HIST("MCRecoEffCorr/Prof_Cent_MeanpT"), cent, sumWiptiRecoEffCorr[0][0][0] / sumWiRecoEffCorr[0][0][0]); - histos.fill(HIST("MCRecoEffCorr/Prof_Mult_MeanpT"), multPV, sumWiptiRecoEffCorr[0][0][0] / sumWiRecoEffCorr[0][0][0]); - } - - } else if (isp == numKPion) { - histos.fill(HIST("MCRecoEffCorr/Prof_Cent_Nchrec_Pi"), cent, sumWiRecoEffCorr[1][0][0]); - histos.fill(HIST("MCRecoEffCorr/Prof_Mult_Nchrec_Pi"), multPV, sumWiRecoEffCorr[1][0][0]); - if (sumWiRecoEffCorr[1][0][0] > 1.0f) { - histos.fill(HIST("MCRecoEffCorr/Prof_Cent_MeanpT_Pi"), cent, sumWiptiRecoEffCorr[1][0][0] / sumWiRecoEffCorr[1][0][0]); - histos.fill(HIST("MCRecoEffCorr/Prof_Mult_MeanpT_Pi"), multPV, sumWiptiRecoEffCorr[1][0][0] / sumWiRecoEffCorr[1][0][0]); - } - - } else if (isp == numKKaon) { - histos.fill(HIST("MCRecoEffCorr/Prof_Cent_Nchrec_Ka"), cent, sumWiRecoEffCorr[2][0][0]); - histos.fill(HIST("MCRecoEffCorr/Prof_Mult_Nchrec_Ka"), multPV, sumWiRecoEffCorr[2][0][0]); - if (sumWiRecoEffCorr[2][0][0] > 1.0f) { - histos.fill(HIST("MCRecoEffCorr/Prof_Cent_MeanpT_Ka"), cent, sumWiptiRecoEffCorr[2][0][0] / sumWiRecoEffCorr[2][0][0]); - histos.fill(HIST("MCRecoEffCorr/Prof_Mult_MeanpT_Ka"), multPV, sumWiptiRecoEffCorr[2][0][0] / sumWiRecoEffCorr[2][0][0]); - } - } else if (isp == numKProton) { - histos.fill(HIST("MCRecoEffCorr/Prof_Cent_Nchrec_Pr"), cent, sumWiRecoEffCorr[3][0][0]); - histos.fill(HIST("MCRecoEffCorr/Prof_Mult_Nchrec_Pr"), multPV, sumWiRecoEffCorr[3][0][0]); - if (sumWiRecoEffCorr[3][0][0] > 1.0f) { - histos.fill(HIST("MCRecoEffCorr/Prof_Cent_MeanpT_Pr"), cent, sumWiptiRecoEffCorr[3][0][0] / sumWiRecoEffCorr[3][0][0]); - histos.fill(HIST("MCRecoEffCorr/Prof_Mult_MeanpT_Pr"), multPV, sumWiptiRecoEffCorr[3][0][0] / sumWiRecoEffCorr[3][0][0]); - } + if (sumWiRecoEffCorr[isp][0] > 1.0f) { + histos.fill(HIST("MCRecoEffCorr/Prof_Cent_Nsp_MeanpT"), cent, isp, sumWiptiRecoEffCorr[isp][0] / sumWiRecoEffCorr[isp][0]); + histos.fill(HIST("MCRecoEffCorr/Prof_Mult_Nsp_MeanpT"), multPV, isp, sumWiptiRecoEffCorr[isp][0] / sumWiRecoEffCorr[isp][0]); } } for (int ietaA = 0; ietaA < KNEta; ++ietaA) { - for (int ietaB = 0; ietaB < KNEta; ++ietaB) { - for (int ipt = 0; ipt < KNpT; ++ipt) { - for (int isp = 0; isp < KNsp; ++isp) { - - // 1. Truth Sub-event Mean - double nTruAB = sumWiTruth[isp][ietaA][ipt] + sumWiTruth[isp][ietaB][ipt]; - if (nTruAB > 0) { - float mptsubTru = (sumWiptiTruth[isp][ietaA][ipt] + sumWiptiTruth[isp][ietaB][ipt]) / nTruAB; - if (isp == numKInclusive) { // Inclusive - if (ipt == 0) - histos.fill(HIST("Prof2D_MeanpT_Sub_ipt0_Tru"), cent, ietaA, ietaB, mptsubTru); - if (ipt == KNpT - 2) - histos.fill(HIST("Prof2D_MeanpT_Sub_ipt1_Tru"), cent, ietaA, ietaB, mptsubTru); - if (ipt == KNpT - 1) - histos.fill(HIST("Prof2D_MeanpT_Sub_ipt2_Tru"), cent, ietaA, ietaB, mptsubTru); - } else if (isp == numKPion) { // Pion - if (ipt == 0) - histos.fill(HIST("Prof2D_MeanpT_Sub_ipt0_Tru_Pi"), cent, ietaA, ietaB, mptsubTru); - if (ipt == KNpT - 2) - histos.fill(HIST("Prof2D_MeanpT_Sub_ipt1_Tru_Pi"), cent, ietaA, ietaB, mptsubTru); - if (ipt == KNpT - 1) - histos.fill(HIST("Prof2D_MeanpT_Sub_ipt2_Tru_Pi"), cent, ietaA, ietaB, mptsubTru); - } else if (isp == numKKaon) { // Kaon - if (ipt == 0) - histos.fill(HIST("Prof2D_MeanpT_Sub_ipt0_Tru_Ka"), cent, ietaA, ietaB, mptsubTru); - if (ipt == KNpT - 2) - histos.fill(HIST("Prof2D_MeanpT_Sub_ipt1_Tru_Ka"), cent, ietaA, ietaB, mptsubTru); - if (ipt == KNpT - 1) - histos.fill(HIST("Prof2D_MeanpT_Sub_ipt2_Tru_Ka"), cent, ietaA, ietaB, mptsubTru); - } else if (isp == numKProton) { // Proton - if (ipt == 0) - histos.fill(HIST("Prof2D_MeanpT_Sub_ipt0_Tru_Pr"), cent, ietaA, ietaB, mptsubTru); - if (ipt == KNpT - 2) - histos.fill(HIST("Prof2D_MeanpT_Sub_ipt1_Tru_Pr"), cent, ietaA, ietaB, mptsubTru); - if (ipt == KNpT - 1) - histos.fill(HIST("Prof2D_MeanpT_Sub_ipt2_Tru_Pr"), cent, ietaA, ietaB, mptsubTru); - } - } - - // 2. Reco Raw Sub-event Mean - double nRecAB = sumWiReco[isp][ietaA][ipt] + sumWiReco[isp][ietaB][ipt]; - if (nRecAB > 0) { - float mptsubReco = (sumWiptiReco[isp][ietaA][ipt] + sumWiptiReco[isp][ietaB][ipt]) / nRecAB; - if (isp == numKInclusive) { - if (ipt == 0) - histos.fill(HIST("Prof2D_MeanpT_Sub_ipt0_Reco"), cent, ietaA, ietaB, mptsubReco); - if (ipt == KNpT - 2) - histos.fill(HIST("Prof2D_MeanpT_Sub_ipt1_Reco"), cent, ietaA, ietaB, mptsubReco); - if (ipt == KNpT - 1) - histos.fill(HIST("Prof2D_MeanpT_Sub_ipt2_Reco"), cent, ietaA, ietaB, mptsubReco); - } else if (isp == numKPion) { - if (ipt == 0) - histos.fill(HIST("Prof2D_MeanpT_Sub_ipt0_Reco_Pi"), cent, ietaA, ietaB, mptsubReco); - if (ipt == KNpT - 2) - histos.fill(HIST("Prof2D_MeanpT_Sub_ipt1_Reco_Pi"), cent, ietaA, ietaB, mptsubReco); - if (ipt == KNpT - 1) - histos.fill(HIST("Prof2D_MeanpT_Sub_ipt2_Reco_Pi"), cent, ietaA, ietaB, mptsubReco); - } else if (isp == numKKaon) { - if (ipt == 0) - histos.fill(HIST("Prof2D_MeanpT_Sub_ipt0_Reco_Ka"), cent, ietaA, ietaB, mptsubReco); - if (ipt == KNpT - 2) - histos.fill(HIST("Prof2D_MeanpT_Sub_ipt1_Reco_Ka"), cent, ietaA, ietaB, mptsubReco); - if (ipt == KNpT - 1) - histos.fill(HIST("Prof2D_MeanpT_Sub_ipt2_Reco_Ka"), cent, ietaA, ietaB, mptsubReco); - } else if (isp == numKProton) { - if (ipt == 0) - histos.fill(HIST("Prof2D_MeanpT_Sub_ipt0_Reco_Pr"), cent, ietaA, ietaB, mptsubReco); - if (ipt == KNpT - 2) - histos.fill(HIST("Prof2D_MeanpT_Sub_ipt1_Reco_Pr"), cent, ietaA, ietaB, mptsubReco); - if (ipt == KNpT - 1) - histos.fill(HIST("Prof2D_MeanpT_Sub_ipt2_Reco_Pr"), cent, ietaA, ietaB, mptsubReco); - } - } - - // 3. Reco Efficiency Corrected Sub-event Mean - double wCorrAB = sumWiRecoEffCorr[isp][ietaA][ipt] + sumWiRecoEffCorr[isp][ietaB][ipt]; - if (wCorrAB > 0) { - float mptsubRecoEffCorr = (sumWiptiRecoEffCorr[isp][ietaA][ipt] + sumWiptiRecoEffCorr[isp][ietaB][ipt]) / wCorrAB; - if (isp == numKInclusive) { - if (ipt == 0) - histos.fill(HIST("Prof2D_MeanpT_Sub_ipt0_RecoEffCorr"), cent, ietaA, ietaB, mptsubRecoEffCorr); - if (ipt == KNpT - 2) - histos.fill(HIST("Prof2D_MeanpT_Sub_ipt1_RecoEffCorr"), cent, ietaA, ietaB, mptsubRecoEffCorr); - if (ipt == KNpT - 1) - histos.fill(HIST("Prof2D_MeanpT_Sub_ipt2_RecoEffCorr"), cent, ietaA, ietaB, mptsubRecoEffCorr); - } else if (isp == numKPion) { - if (ipt == 0) - histos.fill(HIST("Prof2D_MeanpT_Sub_ipt0_RecoEffCorr_Pi"), cent, ietaA, ietaB, mptsubRecoEffCorr); - if (ipt == KNpT - 2) - histos.fill(HIST("Prof2D_MeanpT_Sub_ipt1_RecoEffCorr_Pi"), cent, ietaA, ietaB, mptsubRecoEffCorr); - if (ipt == KNpT - 1) - histos.fill(HIST("Prof2D_MeanpT_Sub_ipt2_RecoEffCorr_Pi"), cent, ietaA, ietaB, mptsubRecoEffCorr); - } else if (isp == numKKaon) { - if (ipt == 0) - histos.fill(HIST("Prof2D_MeanpT_Sub_ipt0_RecoEffCorr_Ka"), cent, ietaA, ietaB, mptsubRecoEffCorr); - if (ipt == KNpT - 2) - histos.fill(HIST("Prof2D_MeanpT_Sub_ipt1_RecoEffCorr_Ka"), cent, ietaA, ietaB, mptsubRecoEffCorr); - if (ipt == KNpT - 1) - histos.fill(HIST("Prof2D_MeanpT_Sub_ipt2_RecoEffCorr_Ka"), cent, ietaA, ietaB, mptsubRecoEffCorr); - } else if (isp == numKProton) { - if (ipt == 0) - histos.fill(HIST("Prof2D_MeanpT_Sub_ipt0_RecoEffCorr_Pr"), cent, ietaA, ietaB, mptsubRecoEffCorr); - if (ipt == KNpT - 2) - histos.fill(HIST("Prof2D_MeanpT_Sub_ipt1_RecoEffCorr_Pr"), cent, ietaA, ietaB, mptsubRecoEffCorr); - if (ipt == KNpT - 1) - histos.fill(HIST("Prof2D_MeanpT_Sub_ipt2_RecoEffCorr_Pr"), cent, ietaA, ietaB, mptsubRecoEffCorr); - } - } - - // 4. pmean Profiles (Individual Bins) - if (ietaA == ietaB) { // only fill once per eta bin - if (sumWiTruth[isp][ietaA][ipt] > 0) { - float val = sumWiptiTruth[isp][ietaA][ipt] / sumWiTruth[isp][ietaA][ipt]; - if (isp == numKInclusive) - histos.fill(HIST("pmeanTruNchEtabinPtbin"), multPV, ietaA, ipt, val); - else if (isp == numKPion) - histos.fill(HIST("pmeanTruNchEtabinPtbin_Pi"), multPV, ietaA, ipt, val); - else if (isp == numKKaon) - histos.fill(HIST("pmeanTruNchEtabinPtbin_Ka"), multPV, ietaA, ipt, val); - else if (isp == numKProton) - histos.fill(HIST("pmeanTruNchEtabinPtbin_Pr"), multPV, ietaA, ipt, val); - } + for (int ietaC = 0; ietaC < KNEta; ++ietaC) { + for (int isp = 0; isp < KNsp; ++isp) { + float nTruAB = sumWiTruth[isp][ietaA] + sumWiTruth[isp][ietaC]; + float nRecoAB = sumWiReco[isp][ietaA] + sumWiReco[isp][ietaC]; + float nCorrAB = sumWiRecoEffCorr[isp][ietaA] + sumWiRecoEffCorr[isp][ietaC]; + + float mptsubTru = (sumWiptiTruth[isp][ietaA] + sumWiptiTruth[isp][ietaC]) / nTruAB; + float mptsubReco = (sumWiptiReco[isp][ietaA] + sumWiptiReco[isp][ietaC]) / nRecoAB; + float mptsubRecoEffCorr = (sumWiptiRecoEffCorr[isp][ietaA] + sumWiptiRecoEffCorr[isp][ietaC]) / nCorrAB; + + if (nTruAB > 0) { + if (isp == kInclusive) + histos.fill(HIST("Prof2D_MeanpTSub_Tru"), cent, ietaA, ietaC, mptsubTru); + else if (isp == kPiMinus) + histos.fill(HIST("Prof2D_MeanpTSub_Tru_PiMinus"), cent, ietaA, ietaC, mptsubTru); + else if (isp == kPiPlus) + histos.fill(HIST("Prof2D_MeanpTSub_Tru_PiPlus"), cent, ietaA, ietaC, mptsubTru); + else if (isp == kPiAll) + histos.fill(HIST("Prof2D_MeanpTSub_Tru_PiAll"), cent, ietaA, ietaC, mptsubTru); + else if (isp == kKaMinus) + histos.fill(HIST("Prof2D_MeanpTSub_Tru_KaMinus"), cent, ietaA, ietaC, mptsubTru); + else if (isp == kKaPlus) + histos.fill(HIST("Prof2D_MeanpTSub_Tru_KaPlus"), cent, ietaA, ietaC, mptsubTru); + else if (isp == kKaAll) + histos.fill(HIST("Prof2D_MeanpTSub_Tru_KaAll"), cent, ietaA, ietaC, mptsubTru); + else if (isp == kProton) + histos.fill(HIST("Prof2D_MeanpTSub_Tru_Pr"), cent, ietaA, ietaC, mptsubTru); + else if (isp == kAntiProton) + histos.fill(HIST("Prof2D_MeanpTSub_Tru_AntiPr"), cent, ietaA, ietaC, mptsubTru); + else if (isp == kAllProton) + histos.fill(HIST("Prof2D_MeanpTSub_Tru_AllPr"), cent, ietaA, ietaC, mptsubTru); + } - if (sumWiReco[isp][ietaA][ipt] > 0) { - float val = sumWiptiReco[isp][ietaA][ipt] / sumWiReco[isp][ietaA][ipt]; - if (isp == numKInclusive) - histos.fill(HIST("pmeanRecoNchEtabinPtbin"), multPV, ietaA, ipt, val); - else if (isp == numKPion) - histos.fill(HIST("pmeanRecoNchEtabinPtbin_Pi"), multPV, ietaA, ipt, val); - else if (isp == numKKaon) - histos.fill(HIST("pmeanRecoNchEtabinPtbin_Ka"), multPV, ietaA, ipt, val); - else if (isp == numKProton) - histos.fill(HIST("pmeanRecoNchEtabinPtbin_Pr"), multPV, ietaA, ipt, val); - } - if (sumWiRecoEffCorr[isp][ietaA][ipt] > 0) { - float val = sumWiptiRecoEffCorr[isp][ietaA][ipt] / sumWiRecoEffCorr[isp][ietaA][ipt]; - if (isp == numKInclusive) - histos.fill(HIST("pmeanRecoEffcorrNchEtabinPtbin"), multPV, ietaA, ipt, val); - else if (isp == numKPion) - histos.fill(HIST("pmeanRecoEffcorrNchEtabinPtbin_Pi"), multPV, ietaA, ipt, val); - else if (isp == numKKaon) - histos.fill(HIST("pmeanRecoEffcorrNchEtabinPtbin_Ka"), multPV, ietaA, ipt, val); - else if (isp == numKProton) - histos.fill(HIST("pmeanRecoEffcorrNchEtabinPtbin_Pr"), multPV, ietaA, ipt, val); - } + if (nRecoAB > 0) { + if (isp == kInclusive) + histos.fill(HIST("Prof2D_MeanpTSub_Reco"), cent, ietaA, ietaC, mptsubReco); + else if (isp == kPiMinus) + histos.fill(HIST("Prof2D_MeanpTSub_Reco_PiMinus"), cent, ietaA, ietaC, mptsubReco); + else if (isp == kPiPlus) + histos.fill(HIST("Prof2D_MeanpTSub_Reco_PiPlus"), cent, ietaA, ietaC, mptsubReco); + else if (isp == kPiAll) + histos.fill(HIST("Prof2D_MeanpTSub_Reco_PiAll"), cent, ietaA, ietaC, mptsubReco); + else if (isp == kKaMinus) + histos.fill(HIST("Prof2D_MeanpTSub_Reco_KaMinus"), cent, ietaA, ietaC, mptsubReco); + else if (isp == kKaPlus) + histos.fill(HIST("Prof2D_MeanpTSub_Reco_KaPlus"), cent, ietaA, ietaC, mptsubReco); + else if (isp == kKaAll) + histos.fill(HIST("Prof2D_MeanpTSub_Reco_KaAll"), cent, ietaA, ietaC, mptsubReco); + else if (isp == kProton) + histos.fill(HIST("Prof2D_MeanpTSub_Reco_Pr"), cent, ietaA, ietaC, mptsubReco); + else if (isp == kAntiProton) + histos.fill(HIST("Prof2D_MeanpTSub_Reco_AntiPr"), cent, ietaA, ietaC, mptsubReco); + else if (isp == kAllProton) + histos.fill(HIST("Prof2D_MeanpTSub_Reco_AllPr"), cent, ietaA, ietaC, mptsubReco); + } - if (sumWiTruth[isp][ietaA][ipt] > 0) { - if (isp == numKInclusive) - histos.fill(HIST("pmeanMultTruNchEtabinPtbin"), multPV, ietaA, ipt, sumWiTruth[isp][ietaA][ipt]); - else if (isp == numKPion) - histos.fill(HIST("pmeanMultTruNchEtabinPtbin_Pi"), multPV, ietaA, ipt, sumWiTruth[isp][ietaA][ipt]); - else if (isp == numKKaon) - histos.fill(HIST("pmeanMultTruNchEtabinPtbin_Ka"), multPV, ietaA, ipt, sumWiTruth[isp][ietaA][ipt]); - else if (isp == numKProton) - histos.fill(HIST("pmeanMultTruNchEtabinPtbin_Pr"), multPV, ietaA, ipt, sumWiTruth[isp][ietaA][ipt]); - } + if (nCorrAB > 0) { + if (isp == kInclusive) + histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr"), cent, ietaA, ietaC, mptsubRecoEffCorr); + else if (isp == kPiMinus) + histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr_PiMinus"), cent, ietaA, ietaC, mptsubRecoEffCorr); + else if (isp == kPiPlus) + histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr_PiPlus"), cent, ietaA, ietaC, mptsubRecoEffCorr); + else if (isp == kPiAll) + histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr_PiAll"), cent, ietaA, ietaC, mptsubRecoEffCorr); + else if (isp == kKaMinus) + histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr_KaMinus"), cent, ietaA, ietaC, mptsubRecoEffCorr); + else if (isp == kKaPlus) + histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr_KaPlus"), cent, ietaA, ietaC, mptsubRecoEffCorr); + else if (isp == kKaAll) + histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr_KaAll"), cent, ietaA, ietaC, mptsubRecoEffCorr); + else if (isp == kProton) + histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr_Pr"), cent, ietaA, ietaC, mptsubRecoEffCorr); + else if (isp == kAntiProton) + histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr_AntiPr"), cent, ietaA, ietaC, mptsubRecoEffCorr); + else if (isp == kAllProton) + histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr_AllPr"), cent, ietaA, ietaC, mptsubRecoEffCorr); + } - if (sumWiReco[isp][ietaA][ipt] > 0) { - if (isp == numKInclusive) - histos.fill(HIST("pmeanMultRecoNchEtabinPtbin"), multPV, ietaA, ipt, sumWiReco[isp][ietaA][ipt]); - else if (isp == numKPion) - histos.fill(HIST("pmeanMultRecoNchEtabinPtbin_Pi"), multPV, ietaA, ipt, sumWiReco[isp][ietaA][ipt]); - else if (isp == numKKaon) - histos.fill(HIST("pmeanMultRecoNchEtabinPtbin_Ka"), multPV, ietaA, ipt, sumWiReco[isp][ietaA][ipt]); - else if (isp == numKProton) - histos.fill(HIST("pmeanMultRecoNchEtabinPtbin_Pr"), multPV, ietaA, ipt, sumWiReco[isp][ietaA][ipt]); - } - if (sumWiRecoEffCorr[isp][ietaA][ipt] > 0) { - if (isp == numKInclusive) - histos.fill(HIST("pmeanMultRecoEffcorrNchEtabinPtbin"), multPV, ietaA, ipt, sumWiRecoEffCorr[isp][ietaA][ipt]); - else if (isp == numKPion) - histos.fill(HIST("pmeanMultRecoEffcorrNchEtabinPtbin_Pi"), multPV, ietaA, ipt, sumWiRecoEffCorr[isp][ietaA][ipt]); - else if (isp == numKKaon) - histos.fill(HIST("pmeanMultRecoEffcorrNchEtabinPtbin_Ka"), multPV, ietaA, ipt, sumWiRecoEffCorr[isp][ietaA][ipt]); - else if (isp == numKProton) - histos.fill(HIST("pmeanMultRecoEffcorrNchEtabinPtbin_Pr"), multPV, ietaA, ipt, sumWiRecoEffCorr[isp][ietaA][ipt]); - } + if (ietaA == ietaC) { + if (sumWiTruth[isp][ietaA] > 0) { + float val = sumWiptiTruth[isp][ietaA] / sumWiTruth[isp][ietaA]; + histos.fill(HIST("pmeanTru_nch_etabin_spbin"), multPV, ietaA, isp, val); + } + if (sumWiReco[isp][ietaA] > 0) { + float val = sumWiptiReco[isp][ietaA] / sumWiReco[isp][ietaA]; + histos.fill(HIST("pmeanReco_nch_etabin_spbin"), multPV, ietaA, isp, val); } - } // end isp - } // end ipt - } // end ietaB + if (sumWiRecoEffCorr[isp][ietaA] > 0) { + float val = sumWiptiRecoEffCorr[isp][ietaA] / sumWiRecoEffCorr[isp][ietaA]; + histos.fill(HIST("pmeanRecoEffcorr_nch_etabin_spbin"), multPV, ietaA, isp, val); + histos.fill(HIST("pmeanMultRecoEffcorr_nch_etabin_spbin"), multPV, ietaA, isp, sumWiRecoEffCorr[isp][ietaA]); + } + } + } // end isp + } // end ietaC } // end ietaA + + double amplFT0A = 0, amplFT0C = 0; + if (col.has_foundFT0()) { + const auto& ft0 = col.foundFT0(); + for (std::size_t iCh = 0; iCh < ft0.channelA().size(); iCh++) { + auto chanelid = ft0.channelA()[iCh]; + float ampl = ft0.amplitudeA()[iCh]; + amplFT0A += ampl; + auto eta = getEtaFT0(chanelid, 0); + histos.fill(HIST("pmean_cent_id_eta_FT0"), cent, iCh, eta, ampl); + histos.fill(HIST("h3_cent_id_eta_FT0"), cent, iCh, eta, ampl); + } + for (std::size_t iCh = 0; iCh < ft0.channelC().size(); iCh++) { + auto chanelid = ft0.channelC()[iCh]; + auto globalId = chanelid + KnFt0cCell; + float ampl = ft0.amplitudeC()[iCh]; + auto eta = getEtaFT0(globalId, 1); + amplFT0C += ampl; + histos.fill(HIST("pmean_cent_id_eta_FT0"), cent, iCh, eta, ampl); + histos.fill(HIST("h3_cent_id_eta_FT0"), cent, iCh, eta, ampl); + } + } + + histos.fill(HIST("pmeanFT0Amultpv"), multPV, amplFT0A); + histos.fill(HIST("pmeanFT0A_cent"), cent, amplFT0A); + histos.fill(HIST("pmeanFT0Cmultpv"), multPV, amplFT0C); + histos.fill(HIST("pmeanFT0C_cent"), cent, amplFT0C); } } } - PROCESS_SWITCH(RadialFlowDecorr, processMCMean, "process MC to calculate mean pt/Et and Eff Hists", cfgRunMCMean); + PROCESS_SWITCH(RadialFlowDecorr, processMCMean, "process MC to calculate mean pt and Eff Hists", cfgRunMCMean); - void processMCFluc(aod::McCollisions const& mcColl, MyRun3MCCollisions const& collisions, TCs const& tracks, FilteredTCs const& /*filteredTracks*/, aod::McParticles const& mcParticles) + void processMCFluc(aod::McCollisions const& mcColl, MyRun3MCCollisions const& collisions, TCs const& tracks, FilteredTCs const& /*filteredTracks*/, aod::FT0s const&, aod::McParticles const& mcParticles) { - // 1. Safety Check: Step 2 Mean Maps - for (int isp = 0; isp < KNsp; ++isp) { - if (!pmeanTruNchEtabinPtbinStep2[isp] || !pmeanRecoNchEtabinPtbinStep2[isp] || !pmeanRecoEffcorrNchEtabinPtbinStep2[isp] || - !pmeanMultTruNchEtabinPtbinStep2[isp] || !pmeanMultRecoNchEtabinPtbinStep2[isp] || !pmeanMultRecoEffcorrNchEtabinPtbinStep2[isp]) { - LOGF(warning, "MC fluc: Mean pT or Mult map missing for species index %d", isp); - return; - } + if (!pmeanTruNchEtabinSpbinStep2 || !pmeanRecoNchEtabinSpbinStep2 || !pmeanRecoEffcorrNchEtabinSpbinStep2 || + !pmeanMultTruNchEtabinSpbinStep2 || !pmeanMultRecoNchEtabinSpbinStep2 || !pmeanMultRecoEffcorrNchEtabinSpbinStep2) { + LOGF(warning, "MC fluc: Unified Mean pT or Mult map missing"); + return; } + double sumPmwkTru[KNsp][KNEta][KIntM][KIntK]{}; + double sumWkTru[KNsp][KNEta][KIntK]{}; + double sumPmwkReco[KNsp][KNEta][KIntM][KIntK]{}; + double sumWkReco[KNsp][KNEta][KIntK]{}; + double sumPmwkRecoEffCor[KNsp][KNEta][KIntM][KIntK]{}; + double sumWkRecoEffCor[KNsp][KNEta][KIntK]{}; - // Expanded with KNsp index (isp=0: Incl, 1: Pi, 2: Ka, 3: Pr) - double sumPmwkTru[KNsp][KNEta][KNpT][KIntM][KIntK]{}; - double sumWkTru[KNsp][KNEta][KNpT][KIntK]{}; - double sumPmwkReco[KNsp][KNEta][KNpT][KIntM][KIntK]{}; - double sumWkReco[KNsp][KNEta][KNpT][KIntK]{}; - double sumPmwkRecoEffCor[KNsp][KNEta][KNpT][KIntM][KIntK]{}; - double sumWkRecoEffCor[KNsp][KNEta][KNpT][KIntK]{}; - - double meanTru[KNsp][KNEta][KNpT]{}, c2Tru[KNsp][KNEta][KNpT]{}; - double meanReco[KNsp][KNEta][KNpT]{}, c2Reco[KNsp][KNEta][KNpT]{}; - double meanRecoEffCor[KNsp][KNEta][KNpT]{}, c2RecoEffCor[KNsp][KNEta][KNpT]{}; + double meanTru[KNsp][KNEta]{}, c2Tru[KNsp][KNEta]{}; + double meanReco[KNsp][KNEta]{}, c2Reco[KNsp][KNEta]{}; + double meanRecoEffCor[KNsp][KNEta]{}, c2RecoEffCor[KNsp][KNEta]{}; - double meanTruMult[KNsp][KNEta][KNpT]{}; - double meanRecoMult[KNsp][KNEta][KNpT]{}; - double meanRecoEffCorMult[KNsp][KNEta][KNpT]{}; + double meanTruMult[KNsp][KNEta]{}; + double meanRecoMult[KNsp][KNEta]{}; + double meanRecoEffCorMult[KNsp][KNEta]{}; - double p1kBarTru[KNsp][KNEta][KNpT]{}, p1kBarReco[KNsp][KNEta][KNpT]{}, p1kBarRecoEffCor[KNsp][KNEta][KNpT]{}; - double p1kBarTruMult[KNsp][KNEta][KNpT]{}, p1kBarRecoMult[KNsp][KNEta][KNpT]{}, p1kBarRecoEffCorMult[KNsp][KNEta][KNpT]{}; + double p1kBarTru[KNsp][KNEta]{}, p1kBarReco[KNsp][KNEta]{}, p1kBarRecoEffCor[KNsp][KNEta]{}; + double p1kBarTruMult[KNsp][KNEta]{}, p1kBarRecoMult[KNsp][KNEta]{}, p1kBarRecoEffCorMult[KNsp][KNEta]{}; for (const auto& mcCollision : mcColl) { auto partSlice = mcParticles.sliceBy(partPerMcCollision, mcCollision.globalIndex()); @@ -1796,7 +1765,6 @@ struct RadialFlowDecorr { if (cent > KCentMax) continue; float multPV = col.multNTracksPV(); - // Reset local arrays memset(sumPmwkTru, 0, sizeof(sumPmwkTru)); memset(sumWkTru, 0, sizeof(sumWkTru)); memset(sumPmwkReco, 0, sizeof(sumPmwkReco)); @@ -1823,48 +1791,74 @@ struct RadialFlowDecorr { memset(p1kBarRecoMult, 0, sizeof(p1kBarRecoMult)); memset(p1kBarRecoEffCorMult, 0, sizeof(p1kBarRecoEffCorMult)); - // --- 1. Truth Loop --- + double p1kBarFt0A = 0.0, p1kBarFt0C = 0.0; + for (const auto& particle : partSlice) { if (!isParticleSelected(particle) || !particle.isPhysicalPrimary()) continue; float pt = particle.pt(); + if (pt <= KPtMin || pt > KPtMax) + continue; float eta = particle.eta(); - const int absPdgId = std::abs(particle.pdgCode()); - bool isSpecies[KNsp] = {true, (absPdgId == KPiPlus), (absPdgId == KKPlus), (absPdgId == KProton)}; + int pdgCode = particle.pdgCode(); + int absPdg = std::abs(pdgCode); + + bool isSpecies[KNsp] = { + true, // kInclusive + pdgCode == kPiMinus, // kPiMinus + pdgCode == kPiPlus, // kPiPlus + absPdg == kPiPlus, // kPiAll + pdgCode == kKMinus, // kKaMinus + pdgCode == kKPlus, // kKaPlus + absPdg == kKPlus, // kKaAll + pdgCode == kProtonBar, // kAntiProton + pdgCode == kProton, // kProton + absPdg == kProton // kAllProton + }; for (int ieta = 0; ieta < KNEta; ++ieta) { if (eta <= etaLw[ieta] || eta > etaUp[ieta]) continue; - for (int ipt = 0; ipt < KNpT; ++ipt) { - if (pt <= pTLw[ipt] || pt > pTUp[ipt]) - continue; - - for (int isp = 0; isp < KNsp; ++isp) { - if (isSpecies[isp]) { - for (int k = 0; k < KIntK; ++k) { - for (int m = 0; m < KIntM; ++m) { - sumPmwkTru[isp][ieta][ipt][m][k] += std::pow(pt, m); - } - sumWkTru[isp][ieta][ipt][k]++; + for (int isp = 0; isp < KNsp; ++isp) { + if (isSpecies[isp]) { + for (int k = 0; k < KIntK; ++k) { + for (int m = 0; m < KIntM; ++m) { + sumPmwkTru[isp][ieta][m][k] += std::pow(pt, m); } + sumWkTru[isp][ieta][k]++; } } } } } // end truth loop - - // --- 2. Reco Loop --- float vz = col.posZ(); for (const auto& track : trackSlice) { if (!isTrackSelected(track)) continue; float pt = track.pt(); + if (pt <= KPtMin || pt > KPtMax) + continue; float eta = track.eta(); float phi = track.phi(); - float sign = track.sign(); - bool isSpecies[KNsp] = {true, selectionPion(track), selectionKaon(track), selectionProton(track)}; + auto sign = track.sign(); + bool isPi = selectionPion(track); + bool isKa = selectionKaon(track); + bool isPr = selectionProton(track); + + bool isSpecies[KNsp] = { + true, // kInclusive + isPi && sign < 0, // kPiMinus + isPi && sign > 0, // kPiPlus + isPi, // kPiAll + isKa && sign < 0, // kKaMinus + isKa && sign > 0, // kKaPlus + isKa, // kKaAll + isPr && sign < 0, // kAntiProton (Negative) + isPr && sign > 0, // kProton (Positive) + isPr // kAllProton + }; for (int isp = 0; isp < KNsp; ++isp) { if (!isSpecies[isp]) @@ -1881,699 +1875,619 @@ struct RadialFlowDecorr { for (int ieta = 0; ieta < KNEta; ++ieta) { if (eta <= etaLw[ieta] || eta > etaUp[ieta]) continue; - for (int ipt = 0; ipt < KNpT; ++ipt) { - if (pt <= pTLw[ipt] || pt > pTUp[ipt]) - continue; - for (int k = 0; k < KIntK; ++k) { - for (int m = 0; m < KIntM; ++m) { - sumPmwkReco[isp][ieta][ipt][m][k] += std::pow(1.0, k) * std::pow(pt, m); - sumPmwkRecoEffCor[isp][ieta][ipt][m][k] += std::pow(w, k) * std::pow(pt, m); - } - sumWkReco[isp][ieta][ipt][k] += std::pow(1.0, k); - sumWkRecoEffCor[isp][ieta][ipt][k] += std::pow(w, k); + for (int k = 0; k < KIntK; ++k) { + for (int m = 0; m < KIntM; ++m) { + sumPmwkReco[isp][ieta][m][k] += std::pow(1.0, k) * std::pow(pt, m); + sumPmwkRecoEffCor[isp][ieta][m][k] += std::pow(w, k) * std::pow(pt, m); } + sumWkReco[isp][ieta][k] += std::pow(1.0, k); + sumWkRecoEffCor[isp][ieta][k] += std::pow(w, k); } } - if (isp == numKInclusive) { + if (isp == kInclusive) { histos.fill(HIST("hEtaPhiReco"), vz, sign, pt, eta, phi); histos.fill(HIST("hEtaPhiRecoWtd"), vz, sign, pt, eta, phi, w); histos.fill(HIST("hEtaPhiRecoEffWtd"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - - } else if (isp == numKPion) { // Pion - histos.fill(HIST("hEtaPhiReco_Pi"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoWtd_Pi"), vz, sign, pt, eta, phi, w); - histos.fill(HIST("hEtaPhiRecoEffWtd_Pi"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - - } else if (isp == numKKaon) { // Kaon - histos.fill(HIST("hEtaPhiReco_Ka"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoWtd_Ka"), vz, sign, pt, eta, phi, w); - histos.fill(HIST("hEtaPhiRecoEffWtd_Ka"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - - } else if (isp == numKProton) { // Proton + } else if (isp == kPiMinus) { + histos.fill(HIST("hEtaPhiReco_PiMinus"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_PiMinus"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_PiMinus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kPiPlus) { + histos.fill(HIST("hEtaPhiReco_PiPlus"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_PiPlus"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_PiPlus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kPiAll) { + histos.fill(HIST("hEtaPhiReco_PiAll"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_PiAll"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_PiAll"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kKaMinus) { + histos.fill(HIST("hEtaPhiReco_KaMinus"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_KaMinus"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_KaMinus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kKaPlus) { + histos.fill(HIST("hEtaPhiReco_KaPlus"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_KaPlus"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_KaPlus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kKaAll) { + histos.fill(HIST("hEtaPhiReco_KaAll"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_KaAll"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_KaAll"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kProton) { histos.fill(HIST("hEtaPhiReco_Pr"), vz, sign, pt, eta, phi); histos.fill(HIST("hEtaPhiRecoWtd_Pr"), vz, sign, pt, eta, phi, w); histos.fill(HIST("hEtaPhiRecoEffWtd_Pr"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kAntiProton) { + histos.fill(HIST("hEtaPhiReco_AntiPr"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_AntiPr"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_AntiPr"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kAllProton) { + histos.fill(HIST("hEtaPhiReco_AllPr"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_AllPr"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_AllPr"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); } } } // trkslice - // --- 3. FullEvent calculation & Covariances --- for (int ieta = 0; ieta < KNEta; ++ieta) { - for (int ipt = 0; ipt < KNpT; ++ipt) { + const int ibx = pmeanTruNchEtabinSpbinStep2->GetXaxis()->FindBin(col.multNTracksPV()); + const int iby = ieta + 1; - // Safely get the X-axis bin using the Inclusive map [0] - const int ibx = pmeanTruNchEtabinPtbinStep2[0]->GetXaxis()->FindBin(col.multNTracksPV()); - const int iby = ieta + 1; - const int ibz = ipt + 1; + for (int isp = 0; isp < KNsp; ++isp) { + const int ibz = isp + 1; + + meanTruMult[isp][ieta] = sumWkTru[isp][ieta][1]; + meanRecoMult[isp][ieta] = sumWkReco[isp][ieta][1]; + meanRecoEffCorMult[isp][ieta] = sumWkRecoEffCor[isp][ieta][1]; + + float mmptTru = pmeanTruNchEtabinSpbinStep2->GetBinContent(ibx, iby, ibz); + float mmptReco = pmeanRecoNchEtabinSpbinStep2->GetBinContent(ibx, iby, ibz); + float mmptRecoEffCor = pmeanRecoEffcorrNchEtabinSpbinStep2->GetBinContent(ibx, iby, ibz); + + float mmMultTru = pmeanMultTruNchEtabinSpbinStep2->GetBinContent(ibx, iby, ibz); + float mmMultReco = pmeanMultRecoNchEtabinSpbinStep2->GetBinContent(ibx, iby, ibz); + float mmMultRecoEffCor = pmeanMultRecoEffcorrNchEtabinSpbinStep2->GetBinContent(ibx, iby, ibz); + + if (std::isfinite(mmptTru)) + std::tie(meanTru[isp][ieta], c2Tru[isp][ieta]) = calculateMeanAndC2FromSums(sumPmwkTru[isp][ieta], sumWkTru[isp][ieta], mmptTru); + if (std::isfinite(mmptReco)) + std::tie(meanReco[isp][ieta], c2Reco[isp][ieta]) = calculateMeanAndC2FromSums(sumPmwkReco[isp][ieta], sumWkReco[isp][ieta], mmptReco); + if (std::isfinite(mmptRecoEffCor)) + std::tie(meanRecoEffCor[isp][ieta], c2RecoEffCor[isp][ieta]) = calculateMeanAndC2FromSums(sumPmwkRecoEffCor[isp][ieta], sumWkRecoEffCor[isp][ieta], mmptRecoEffCor); + + if (mmptTru != 0.0f) + p1kBarTru[isp][ieta] = meanTru[isp][ieta] - mmptTru; + if (mmptReco != 0.0f) + p1kBarReco[isp][ieta] = meanReco[isp][ieta] - mmptReco; + if (mmptRecoEffCor != 0.0f) + p1kBarRecoEffCor[isp][ieta] = meanRecoEffCor[isp][ieta] - mmptRecoEffCor; + + if (mmMultTru != 0.0f) + p1kBarTruMult[isp][ieta] = meanTruMult[isp][ieta] - mmMultTru; + if (mmMultReco != 0.0f) + p1kBarRecoMult[isp][ieta] = meanRecoMult[isp][ieta] - mmMultReco; + if (mmMultRecoEffCor != 0.0f) + p1kBarRecoEffCorMult[isp][ieta] = meanRecoEffCorMult[isp][ieta] - mmMultRecoEffCor; + } + } - for (int isp = 0; isp < KNsp; ++isp) { - meanTruMult[isp][ieta][ipt] = sumWkTru[isp][ieta][ipt][1]; - meanRecoMult[isp][ieta][ipt] = sumWkReco[isp][ieta][ipt][1]; - meanRecoEffCorMult[isp][ieta][ipt] = sumWkRecoEffCor[isp][ieta][ipt][1]; - - // Dynamically fetch from the arrays using the 'isp' index! - float mmptTru = pmeanTruNchEtabinPtbinStep2[isp]->GetBinContent(ibx, iby, ibz); - float mmptReco = pmeanRecoNchEtabinPtbinStep2[isp]->GetBinContent(ibx, iby, ibz); - float mmptRecoEffCor = pmeanRecoEffcorrNchEtabinPtbinStep2[isp]->GetBinContent(ibx, iby, ibz); - - float mmMultTru = pmeanMultTruNchEtabinPtbinStep2[isp]->GetBinContent(ibx, iby, ibz); - float mmMultReco = pmeanMultRecoNchEtabinPtbinStep2[isp]->GetBinContent(ibx, iby, ibz); - float mmMultRecoEffCor = pmeanMultRecoEffcorrNchEtabinPtbinStep2[isp]->GetBinContent(ibx, iby, ibz); - - if (std::isfinite(mmptTru)) - std::tie(meanTru[isp][ieta][ipt], c2Tru[isp][ieta][ipt]) = calculateMeanAndC2FromSums(sumPmwkTru[isp][ieta][ipt], sumWkTru[isp][ieta][ipt], mmptTru); - if (std::isfinite(mmptReco)) - std::tie(meanReco[isp][ieta][ipt], c2Reco[isp][ieta][ipt]) = calculateMeanAndC2FromSums(sumPmwkReco[isp][ieta][ipt], sumWkReco[isp][ieta][ipt], mmptReco); - if (std::isfinite(mmptRecoEffCor)) - std::tie(meanRecoEffCor[isp][ieta][ipt], c2RecoEffCor[isp][ieta][ipt]) = calculateMeanAndC2FromSums(sumPmwkRecoEffCor[isp][ieta][ipt], sumWkRecoEffCor[isp][ieta][ipt], mmptRecoEffCor); - - if (mmptTru != 0.0f) - p1kBarTru[isp][ieta][ipt] = meanTru[isp][ieta][ipt] - mmptTru; - if (mmptReco != 0.0f) - p1kBarReco[isp][ieta][ipt] = meanReco[isp][ieta][ipt] - mmptReco; - if (mmptRecoEffCor != 0.0f) - p1kBarRecoEffCor[isp][ieta][ipt] = meanRecoEffCor[isp][ieta][ipt] - mmptRecoEffCor; - - if (mmMultTru != 0.0f) - p1kBarTruMult[isp][ieta][ipt] = meanTruMult[isp][ieta][ipt] - mmMultTru; - if (mmMultReco != 0.0f) - p1kBarRecoMult[isp][ieta][ipt] = meanRecoMult[isp][ieta][ipt] - mmMultReco; - if (mmMultRecoEffCor != 0.0f) - p1kBarRecoEffCorMult[isp][ieta][ipt] = meanRecoEffCorMult[isp][ieta][ipt] - mmMultRecoEffCor; - } + double amplFT0A = 0, amplFT0C = 0; + if (col.has_foundFT0()) { + const auto& ft0 = col.foundFT0(); + for (std::size_t iCh = 0; iCh < ft0.channelA().size(); iCh++) { + float ampl = ft0.amplitudeA()[iCh]; + amplFT0A += ampl; + } + for (std::size_t iCh = 0; iCh < ft0.channelC().size(); iCh++) { + float ampl = ft0.amplitudeC()[iCh]; + amplFT0C += ampl; } } for (int isp = 0; isp < KNsp; ++isp) { - if (isp == numKInclusive) { - histos.fill(HIST("MCGen/Prof_Cent_Nchrec"), cent, sumWkTru[isp][0][0][1]); - histos.fill(HIST("MCGen/Prof_Mult_Nchrec"), multPV, sumWkTru[isp][0][0][1]); - if (sumWkTru[isp][0][0][1] > 1.0f) { - histos.fill(HIST("MCGen/Prof_Cent_MeanpT"), cent, meanTru[isp][0][0]); - histos.fill(HIST("MCGen/Prof_Mult_MeanpT"), multPV, meanTru[isp][0][0]); - } - - } else if (isp == numKPion) { - histos.fill(HIST("MCGen/Prof_Cent_Nchrec_Pi"), cent, sumWkTru[isp][0][0][1]); - histos.fill(HIST("MCGen/Prof_Mult_Nchrec_Pi"), multPV, sumWkTru[isp][0][0][1]); + for (int ieta = 0; ieta < KNEta; ++ieta) { + histos.fill(HIST("MCGen/Prof_Cent_NEta_Nsp_Nchrec"), cent, ieta, isp, sumWkTru[isp][ieta][1]); + histos.fill(HIST("MCGen/Prof_Mult_NEta_Nsp_Nchrec"), multPV, ieta, isp, sumWkTru[isp][ieta][1]); - if (sumWkTru[isp][0][0][1] > 1.0f) { - histos.fill(HIST("MCGen/Prof_Cent_MeanpT_Pi"), cent, meanTru[isp][0][0]); - histos.fill(HIST("MCGen/Prof_Mult_MeanpT_Pi"), multPV, meanTru[isp][0][0]); - } + histos.fill(HIST("MCReco/Prof_Cent_NEta_Nsp_Nchrec"), cent, ieta, isp, sumWkReco[isp][ieta][1]); + histos.fill(HIST("MCReco/Prof_Mult_NEta_Nsp_Nchrec"), multPV, ieta, isp, sumWkReco[isp][ieta][1]); - } else if (isp == numKKaon) { - histos.fill(HIST("MCGen/Prof_Cent_Nchrec_Ka"), cent, sumWkTru[isp][0][0][1]); - histos.fill(HIST("MCGen/Prof_Mult_Nchrec_Ka"), multPV, sumWkTru[isp][0][0][1]); + histos.fill(HIST("MCRecoEffCorr/Prof_Cent_NEta_Nsp_Nchrec"), cent, ieta, isp, sumWkRecoEffCor[isp][ieta][1]); + histos.fill(HIST("MCRecoEffCorr/Prof_Mult_NEta_Nsp_Nchrec"), multPV, ieta, isp, sumWkRecoEffCor[isp][ieta][1]); - if (sumWkTru[isp][0][0][1] > 1.0f) { - histos.fill(HIST("MCGen/Prof_Cent_MeanpT_Ka"), cent, meanTru[isp][0][0]); - histos.fill(HIST("MCGen/Prof_Mult_MeanpT_Ka"), multPV, meanTru[isp][0][0]); + if (sumWkTru[isp][ieta][1] > 1.0f) { + histos.fill(HIST("MCGen/Prof_Cent_NEta_Nsp_MeanpT"), cent, ieta, isp, meanTru[isp][ieta]); + histos.fill(HIST("MCGen/Prof_Mult_NEta_Nsp_MeanpT"), multPV, ieta, isp, meanTru[isp][ieta]); } - } else if (isp == numKProton) { - histos.fill(HIST("MCGen/Prof_Cent_Nchrec_Pr"), cent, sumWkTru[isp][0][0][1]); - histos.fill(HIST("MCGen/Prof_Mult_Nchrec_Pr"), multPV, sumWkTru[isp][0][0][1]); - - if (sumWkTru[isp][0][0][1] > 1.0f) { - histos.fill(HIST("MCGen/Prof_Cent_MeanpT_Pr"), cent, meanTru[isp][0][0]); - histos.fill(HIST("MCGen/Prof_Mult_MeanpT_Pr"), multPV, meanTru[isp][0][0]); + if (sumWkReco[isp][ieta][1] > 1.0f) { + histos.fill(HIST("MCReco/Prof_Cent_NEta_Nsp_MeanpT"), cent, ieta, isp, meanReco[isp][ieta]); + histos.fill(HIST("MCReco/Prof_Mult_NEta_Nsp_MeanpT"), multPV, ieta, isp, meanReco[isp][ieta]); + } + if (sumWkRecoEffCor[isp][ieta][1] > 1.0f) { + histos.fill(HIST("MCReco/Prof_Cent_NEta_Nsp_MeanpT"), cent, ieta, isp, meanRecoEffCor[isp][ieta]); + histos.fill(HIST("MCReco/Prof_Mult_NEta_Nsp_MeanpT"), multPV, ieta, isp, meanRecoEffCor[isp][ieta]); } } } - for (int isp = 0; isp < KNsp; ++isp) { - if (isp == numKInclusive) { - histos.fill(HIST("MCReco/Prof_Cent_Nchrec"), cent, sumWkReco[isp][0][0][1]); - histos.fill(HIST("MCReco/Prof_Mult_Nchrec"), multPV, sumWkReco[isp][0][0][1]); - if (sumWkReco[isp][0][0][1] > 1.0f) { - histos.fill(HIST("MCReco/Prof_Cent_MeanpT"), cent, meanReco[isp][0][0]); - histos.fill(HIST("MCReco/Prof_Mult_MeanpT"), multPV, meanReco[isp][0][0]); + for (int ieta = 0; ieta < KNEta; ++ieta) { + for (int isp = 0; isp < KNsp; ++isp) { + if (std::isfinite(meanTru[isp][ieta])) { + histos.fill(HIST("MCGen/Prof_MeanpT_Cent_etabin_spbin"), cent, ieta, isp, meanTru[isp][ieta]); + histos.fill(HIST("MCGen/Prof_MeanpT_Mult_etabin_spbin"), col.multNTracksPV(), ieta, isp, meanTru[isp][ieta]); + } + if (std::isfinite(c2Tru[isp][ieta])) { + histos.fill(HIST("MCGen/Prof_C2_Cent_etabin_spbin"), cent, ieta, isp, c2Tru[isp][ieta]); + histos.fill(HIST("MCGen/Prof_C2_Mult_etabin_spbin"), col.multNTracksPV(), ieta, isp, c2Tru[isp][ieta]); + } + if (std::isfinite(meanReco[isp][ieta])) { + histos.fill(HIST("MCReco/Prof_MeanpT_Cent_etabin_spbin"), cent, ieta, isp, meanReco[isp][ieta]); + histos.fill(HIST("MCReco/Prof_MeanpT_Mult_etabin_spbin"), col.multNTracksPV(), ieta, isp, meanReco[isp][ieta]); + } + if (std::isfinite(c2Reco[isp][ieta])) { + histos.fill(HIST("MCReco/Prof_C2_Cent_etabin_spbin"), cent, ieta, isp, c2Reco[isp][ieta]); + histos.fill(HIST("MCReco/Prof_C2_Mult_etabin_spbin"), col.multNTracksPV(), ieta, isp, c2Reco[isp][ieta]); } + if (std::isfinite(meanRecoEffCor[isp][ieta])) { + histos.fill(HIST("MCRecoEffCorr/Prof_MeanpT_Cent_etabin_spbin"), cent, ieta, isp, meanRecoEffCor[isp][ieta]); + histos.fill(HIST("MCRecoEffCorr/Prof_MeanpT_Mult_etabin_spbin"), col.multNTracksPV(), ieta, isp, meanRecoEffCor[isp][ieta]); + } + if (std::isfinite(c2RecoEffCor[isp][ieta])) { + histos.fill(HIST("MCRecoEffCorr/Prof_C2_Cent_etabin_spbin"), cent, ieta, isp, c2RecoEffCor[isp][ieta]); + histos.fill(HIST("MCRecoEffCorr/Prof_C2_Mult_etabin_spbin"), col.multNTracksPV(), ieta, isp, c2RecoEffCor[isp][ieta]); + } + } + } - } else if (isp == numKPion) { - histos.fill(HIST("MCReco/Prof_Cent_Nchrec_Pi"), cent, sumWkReco[isp][0][0][1]); - histos.fill(HIST("MCReco/Prof_Mult_Nchrec_Pi"), multPV, sumWkReco[isp][0][0][1]); + p1kBarFt0A = amplFT0A - pmeanFT0AmultpvStep2->GetBinContent(pmeanFT0AmultpvStep2->GetXaxis()->FindBin(col.multNTracksPV())); + p1kBarFt0C = amplFT0C - pmeanFT0CmultpvStep2->GetBinContent(pmeanFT0CmultpvStep2->GetXaxis()->FindBin(col.multNTracksPV())); - if (sumWkReco[isp][0][0][1] > 1.0f) { - histos.fill(HIST("MCReco/Prof_Cent_MeanpT_Pi"), cent, meanReco[isp][0][0]); - histos.fill(HIST("MCReco/Prof_Mult_MeanpT_Pi"), multPV, meanReco[isp][0][0]); - } + for (int ietaA = 1; ietaA <= (KNEta - 1) / 2; ++ietaA) { + int ietaC = KNEta - ietaA; + for (int isp = 0; isp < KNsp; ++isp) { + float c2SubTru = p1kBarTru[isp][ietaA] * p1kBarTru[isp][ietaC]; + float c2SubReco = p1kBarReco[isp][ietaA] * p1kBarReco[isp][ietaC]; + float c2SubRecoEffCor = p1kBarRecoEffCor[isp][ietaA] * p1kBarRecoEffCor[isp][ietaC]; + + float covTru = p1kBarTruMult[isp][ietaA] * p1kBarTru[isp][ietaC]; + float covReco = p1kBarRecoMult[isp][ietaA] * p1kBarReco[isp][ietaC]; + float covRecoEffCor = p1kBarRecoEffCorMult[isp][ietaA] * p1kBarRecoEffCor[isp][ietaC]; - } else if (isp == numKKaon) { - histos.fill(HIST("MCReco/Prof_Cent_Nchrec_Ka"), cent, sumWkReco[isp][0][0][1]); - histos.fill(HIST("MCReco/Prof_Mult_Nchrec_Ka"), multPV, sumWkReco[isp][0][0][1]); + float covFT0ATru = p1kBarFt0A * p1kBarTru[isp][ietaC]; + float covFT0AReco = p1kBarFt0A * p1kBarReco[isp][ietaC]; + float covFT0ARecoEffCor = p1kBarFt0A * p1kBarRecoEffCor[isp][ietaC]; - if (sumWkReco[isp][0][0][1] > 1.0f) { - histos.fill(HIST("MCReco/Prof_Cent_MeanpT_Ka"), cent, meanReco[isp][0][0]); - histos.fill(HIST("MCReco/Prof_Mult_MeanpT_Ka"), multPV, meanReco[isp][0][0]); + float covFT0CTru = p1kBarFt0C * p1kBarTru[isp][ietaA]; + float covFT0CReco = p1kBarFt0C * p1kBarReco[isp][ietaA]; + float covFT0CRecoEffCor = p1kBarFt0C * p1kBarRecoEffCor[isp][ietaA]; + + if (std::isfinite(c2SubTru)) { + histos.fill(HIST("MCGen/Prof_C2Sub_Cent_etabin_spbin"), cent, ietaA, isp, c2SubTru); + histos.fill(HIST("MCGen/Prof_C2Sub_Mult_etabin_spbin"), col.multNTracksPV(), ietaA, isp, c2SubTru); } - } else if (isp == numKProton) { - histos.fill(HIST("MCReco/Prof_Cent_Nchrec_Pr"), cent, sumWkReco[isp][0][0][1]); - histos.fill(HIST("MCReco/Prof_Mult_Nchrec_Pr"), multPV, sumWkReco[isp][0][0][1]); - if (sumWkReco[isp][0][0][1] > 1.0f) { - histos.fill(HIST("MCReco/Prof_Cent_MeanpT_Pr"), cent, meanReco[isp][0][0]); - histos.fill(HIST("MCReco/Prof_Mult_MeanpT_Pr"), multPV, meanReco[isp][0][0]); + if (std::isfinite(c2SubReco)) { + histos.fill(HIST("MCReco/Prof_C2Sub_Cent_etabin_spbin"), cent, ietaA, isp, c2SubReco); + histos.fill(HIST("MCReco/Prof_C2Sub_Mult_etabin_spbin"), col.multNTracksPV(), ietaA, isp, c2SubReco); } - } - - if (isp == numKInclusive) { - histos.fill(HIST("MCRecoEffCorr/Prof_Cent_Nchrec"), cent, sumWkRecoEffCor[isp][0][0][1]); - histos.fill(HIST("MCRecoEffCorr/Prof_Mult_Nchrec"), multPV, sumWkRecoEffCor[isp][0][0][1]); - if (sumWkRecoEffCor[isp][0][0][1] > 1.0f) { - histos.fill(HIST("MCRecoEffCorr/Prof_Cent_MeanpT"), cent, meanRecoEffCor[isp][0][0]); - histos.fill(HIST("MCRecoEffCorr/Prof_Mult_MeanpT"), multPV, meanRecoEffCor[isp][0][0]); + if (std::isfinite(c2SubRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub_Cent_etabin_spbin"), cent, ietaA, isp, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub_Mult_etabin_spbin"), col.multNTracksPV(), ietaA, isp, c2SubRecoEffCor); + } + if (std::isfinite(covTru)) { + histos.fill(HIST("MCGen/Prof_Cov_Cent_etabin_spbin"), cent, ietaA, isp, covTru); + histos.fill(HIST("MCGen/Prof_Cov_Mult_etabin_spbin"), col.multNTracksPV(), ietaA, isp, covTru); + } + if (std::isfinite(covReco)) { + histos.fill(HIST("MCReco/Prof_Cov_Cent_etabin_spbin"), cent, ietaA, isp, covReco); + histos.fill(HIST("MCReco/Prof_Cov_Mult_etabin_spbin"), col.multNTracksPV(), ietaA, isp, covReco); + } + if (std::isfinite(covRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_Cov_Cent_etabin_spbin"), cent, ietaA, isp, covRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_Cov_Mult_etabin_spbin"), col.multNTracksPV(), ietaA, isp, covRecoEffCor); } - } else if (isp == numKPion) { - histos.fill(HIST("MCRecoEffCorr/Prof_Cent_Nchrec_Pi"), cent, sumWkRecoEffCor[isp][0][0][1]); - histos.fill(HIST("MCRecoEffCorr/Prof_Mult_Nchrec_Pi"), multPV, sumWkRecoEffCor[isp][0][0][1]); - if (sumWkRecoEffCor[isp][0][0][1] > 1.0f) { - histos.fill(HIST("MCRecoEffCorr/Prof_Cent_MeanpT_Pi"), cent, meanRecoEffCor[isp][0][0]); - histos.fill(HIST("MCRecoEffCorr/Prof_Mult_MeanpT_Pi"), multPV, meanRecoEffCor[isp][0][0]); + if (std::isfinite(covFT0ATru)) { + histos.fill(HIST("MCGen/Prof_CovFT0A_Cent_etabin_spbin"), cent, ietaA, isp, covFT0ATru); + histos.fill(HIST("MCGen/Prof_CovFT0A_Mult_etabin_spbin"), col.multNTracksPV(), ietaA, isp, covFT0ATru); + } + if (std::isfinite(covFT0AReco)) { + histos.fill(HIST("MCReco/Prof_CovFT0A_Cent_etabin_spbin"), cent, ietaA, isp, covFT0AReco); + histos.fill(HIST("MCReco/Prof_CovFT0A_Mult_etabin_spbin"), col.multNTracksPV(), ietaA, isp, covFT0AReco); + } + if (std::isfinite(covFT0ARecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A_Cent_etabin_spbin"), cent, ietaA, isp, covFT0ARecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A_Mult_etabin_spbin"), col.multNTracksPV(), ietaA, isp, covFT0ARecoEffCor); } - } else if (isp == numKKaon) { - histos.fill(HIST("MCRecoEffCorr/Prof_Cent_Nchrec_Ka"), cent, sumWkRecoEffCor[isp][0][0][1]); - histos.fill(HIST("MCRecoEffCorr/Prof_Mult_Nchrec_Ka"), multPV, sumWkRecoEffCor[isp][0][0][1]); - if (sumWkRecoEffCor[isp][0][0][1] > 1.0f) { - histos.fill(HIST("MCRecoEffCorr/Prof_Cent_MeanpT_Ka"), cent, meanRecoEffCor[isp][0][0]); - histos.fill(HIST("MCRecoEffCorr/Prof_Mult_MeanpT_Ka"), multPV, meanRecoEffCor[isp][0][0]); + if (std::isfinite(covFT0CTru)) { + histos.fill(HIST("MCGen/Prof_CovFT0C_Cent_etabin_spbin"), cent, ietaA, isp, covFT0CTru); + histos.fill(HIST("MCGen/Prof_CovFT0C_Mult_etabin_spbin"), col.multNTracksPV(), ietaA, isp, covFT0CTru); } - } else if (isp == numKProton) { - histos.fill(HIST("MCRecoEffCorr/Prof_Cent_Nchrec_Pr"), cent, sumWkRecoEffCor[isp][0][0][1]); - histos.fill(HIST("MCRecoEffCorr/Prof_Mult_Nchrec_Pr"), multPV, sumWkRecoEffCor[isp][0][0][1]); - if (sumWkRecoEffCor[isp][0][0][1] > 1.0f) { - histos.fill(HIST("MCRecoEffCorr/Prof_Cent_MeanpT_Pr"), cent, meanRecoEffCor[isp][0][0]); - histos.fill(HIST("MCRecoEffCorr/Prof_Mult_MeanpT_Pr"), multPV, meanRecoEffCor[isp][0][0]); + if (std::isfinite(covFT0CReco)) { + histos.fill(HIST("MCReco/Prof_CovFT0C_Cent_etabin_spbin"), cent, ietaA, isp, covFT0CReco); + histos.fill(HIST("MCReco/Prof_CovFT0C_Mult_etabin_spbin"), col.multNTracksPV(), ietaA, isp, covFT0CReco); + } + if (std::isfinite(covFT0CRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C_Cent_etabin_spbin"), cent, ietaA, isp, covFT0CRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C_Mult_etabin_spbin"), col.multNTracksPV(), ietaA, isp, covFT0CRecoEffCor); } } } - // --- 3. Fill 1D Profiles: Gen, Reco, and EffCorr Levels --- - for (int ieta = 0; ieta < KNEta; ++ieta) { - for (int ipt = 0; ipt < KNpT; ++ipt) { - for (int isp = 0; isp < KNsp; ++isp) { - - if (isp == numKInclusive) { // Inclusive (No suffix) - // --- MCGen (Truth) --- - if (std::isfinite(meanTru[0][ieta][ipt])) { - histos.fill(HIST("MCGen/Prof_MeanpT_Cent_etabin_ptbin"), cent, ieta, ipt, meanTru[0][ieta][ipt]); - histos.fill(HIST("MCGen/Prof_MeanpT_Mult_etabin_ptbin"), col.multNTracksPV(), ieta, ipt, meanTru[0][ieta][ipt]); - } - if (std::isfinite(c2Tru[0][ieta][ipt])) { - histos.fill(HIST("MCGen/Prof_C2_Cent_etabin_ptbin"), cent, ieta, ipt, c2Tru[0][ieta][ipt]); - histos.fill(HIST("MCGen/Prof_C2_Mult_etabin_ptbin"), col.multNTracksPV(), ieta, ipt, c2Tru[0][ieta][ipt]); - } - // --- MCReco --- - if (std::isfinite(meanReco[0][ieta][ipt])) { - histos.fill(HIST("MCReco/Prof_MeanpT_Cent_etabin_ptbin"), cent, ieta, ipt, meanReco[0][ieta][ipt]); - histos.fill(HIST("MCReco/Prof_MeanpT_Mult_etabin_ptbin"), col.multNTracksPV(), ieta, ipt, meanReco[0][ieta][ipt]); - } - if (std::isfinite(c2Reco[0][ieta][ipt])) { - histos.fill(HIST("MCReco/Prof_C2_Cent_etabin_ptbin"), cent, ieta, ipt, c2Reco[0][ieta][ipt]); - histos.fill(HIST("MCReco/Prof_C2_Mult_etabin_ptbin"), col.multNTracksPV(), ieta, ipt, c2Reco[0][ieta][ipt]); - } - // --- MCRecoEffCorr --- - if (std::isfinite(meanRecoEffCor[0][ieta][ipt])) { - histos.fill(HIST("MCRecoEffCorr/Prof_MeanpT_Cent_etabin_ptbin"), cent, ieta, ipt, meanRecoEffCor[0][ieta][ipt]); - histos.fill(HIST("MCRecoEffCorr/Prof_MeanpT_Mult_etabin_ptbin"), col.multNTracksPV(), ieta, ipt, meanRecoEffCor[0][ieta][ipt]); - } - if (std::isfinite(c2RecoEffCor[0][ieta][ipt])) { - histos.fill(HIST("MCRecoEffCorr/Prof_C2_Cent_etabin_ptbin"), cent, ieta, ipt, c2RecoEffCor[0][ieta][ipt]); - histos.fill(HIST("MCRecoEffCorr/Prof_C2_Mult_etabin_ptbin"), col.multNTracksPV(), ieta, ipt, c2RecoEffCor[0][ieta][ipt]); - } + for (int ietaA = 1; ietaA < KNEta; ++ietaA) { + for (int ietaC = 1; ietaC < KNEta; ++ietaC) { - } else if (isp == numKPion) { // Pions (_Pi) - // --- MCGen (Truth) --- - if (std::isfinite(meanTru[1][ieta][ipt])) { - histos.fill(HIST("MCGen/Prof_MeanpT_Cent_etabin_ptbin_Pi"), cent, ieta, ipt, meanTru[1][ieta][ipt]); - histos.fill(HIST("MCGen/Prof_MeanpT_Mult_etabin_ptbin_Pi"), col.multNTracksPV(), ieta, ipt, meanTru[1][ieta][ipt]); - } - if (std::isfinite(c2Tru[1][ieta][ipt])) { - histos.fill(HIST("MCGen/Prof_C2_Cent_etabin_ptbin_Pi"), cent, ieta, ipt, c2Tru[1][ieta][ipt]); - histos.fill(HIST("MCGen/Prof_C2_Mult_etabin_ptbin_Pi"), col.multNTracksPV(), ieta, ipt, c2Tru[1][ieta][ipt]); - } - // --- MCReco --- - if (std::isfinite(meanReco[1][ieta][ipt])) { - histos.fill(HIST("MCReco/Prof_MeanpT_Cent_etabin_ptbin_Pi"), cent, ieta, ipt, meanReco[1][ieta][ipt]); - histos.fill(HIST("MCReco/Prof_MeanpT_Mult_etabin_ptbin_Pi"), col.multNTracksPV(), ieta, ipt, meanReco[1][ieta][ipt]); - } - if (std::isfinite(c2Reco[1][ieta][ipt])) { - histos.fill(HIST("MCReco/Prof_C2_Cent_etabin_ptbin_Pi"), cent, ieta, ipt, c2Reco[1][ieta][ipt]); - histos.fill(HIST("MCReco/Prof_C2_Mult_etabin_ptbin_Pi"), col.multNTracksPV(), ieta, ipt, c2Reco[1][ieta][ipt]); - } - // --- MCRecoEffCorr --- - if (std::isfinite(meanRecoEffCor[1][ieta][ipt])) { - histos.fill(HIST("MCRecoEffCorr/Prof_MeanpT_Cent_etabin_ptbin_Pi"), cent, ieta, ipt, meanRecoEffCor[1][ieta][ipt]); - histos.fill(HIST("MCRecoEffCorr/Prof_MeanpT_Mult_etabin_ptbin_Pi"), col.multNTracksPV(), ieta, ipt, meanRecoEffCor[1][ieta][ipt]); - } - if (std::isfinite(c2RecoEffCor[1][ieta][ipt])) { - histos.fill(HIST("MCRecoEffCorr/Prof_C2_Cent_etabin_ptbin_Pi"), cent, ieta, ipt, c2RecoEffCor[1][ieta][ipt]); - histos.fill(HIST("MCRecoEffCorr/Prof_C2_Mult_etabin_ptbin_Pi"), col.multNTracksPV(), ieta, ipt, c2RecoEffCor[1][ieta][ipt]); - } + float etaValA = (etaLw[ietaA] + etaUp[ietaA]) / 2.0f; + float etaValB = (etaLw[ietaC] + etaUp[ietaC]) / 2.0f; + float gap = etaValA - etaValB; + float sum = (etaValA + etaValB) / 2.0f; + for (int isp = 0; isp < KNsp; ++isp) { - } else if (isp == numKKaon) { // Kaons (_Ka) - // --- MCGen (Truth) --- - if (std::isfinite(meanTru[2][ieta][ipt])) { - histos.fill(HIST("MCGen/Prof_MeanpT_Cent_etabin_ptbin_Ka"), cent, ieta, ipt, meanTru[2][ieta][ipt]); - histos.fill(HIST("MCGen/Prof_MeanpT_Mult_etabin_ptbin_Ka"), col.multNTracksPV(), ieta, ipt, meanTru[2][ieta][ipt]); - } - if (std::isfinite(c2Tru[2][ieta][ipt])) { - histos.fill(HIST("MCGen/Prof_C2_Cent_etabin_ptbin_Ka"), cent, ieta, ipt, c2Tru[2][ieta][ipt]); - histos.fill(HIST("MCGen/Prof_C2_Mult_etabin_ptbin_Ka"), col.multNTracksPV(), ieta, ipt, c2Tru[2][ieta][ipt]); - } - // --- MCReco --- - if (std::isfinite(meanReco[2][ieta][ipt])) { - histos.fill(HIST("MCReco/Prof_MeanpT_Cent_etabin_ptbin_Ka"), cent, ieta, ipt, meanReco[2][ieta][ipt]); - histos.fill(HIST("MCReco/Prof_MeanpT_Mult_etabin_ptbin_Ka"), col.multNTracksPV(), ieta, ipt, meanReco[2][ieta][ipt]); - } - if (std::isfinite(c2Reco[2][ieta][ipt])) { - histos.fill(HIST("MCReco/Prof_C2_Cent_etabin_ptbin_Ka"), cent, ieta, ipt, c2Reco[2][ieta][ipt]); - histos.fill(HIST("MCReco/Prof_C2_Mult_etabin_ptbin_Ka"), col.multNTracksPV(), ieta, ipt, c2Reco[2][ieta][ipt]); - } - // --- MCRecoEffCorr --- - if (std::isfinite(meanRecoEffCor[2][ieta][ipt])) { - histos.fill(HIST("MCRecoEffCorr/Prof_MeanpT_Cent_etabin_ptbin_Ka"), cent, ieta, ipt, meanRecoEffCor[2][ieta][ipt]); - histos.fill(HIST("MCRecoEffCorr/Prof_MeanpT_Mult_etabin_ptbin_Ka"), col.multNTracksPV(), ieta, ipt, meanRecoEffCor[2][ieta][ipt]); - } - if (std::isfinite(c2RecoEffCor[2][ieta][ipt])) { - histos.fill(HIST("MCRecoEffCorr/Prof_C2_Cent_etabin_ptbin_Ka"), cent, ieta, ipt, c2RecoEffCor[2][ieta][ipt]); - histos.fill(HIST("MCRecoEffCorr/Prof_C2_Mult_etabin_ptbin_Ka"), col.multNTracksPV(), ieta, ipt, c2RecoEffCor[2][ieta][ipt]); - } + float c2SubTru = p1kBarTru[isp][ietaA] * p1kBarTru[isp][ietaC]; + float c2SubReco = p1kBarReco[isp][ietaA] * p1kBarReco[isp][ietaC]; + float c2SubRecoEffCor = p1kBarRecoEffCor[isp][ietaA] * p1kBarRecoEffCor[isp][ietaC]; - } else if (isp == numKProton) { // Protons (_Pr) - // --- MCGen (Truth) --- - if (std::isfinite(meanTru[3][ieta][ipt])) { - histos.fill(HIST("MCGen/Prof_MeanpT_Cent_etabin_ptbin_Pr"), cent, ieta, ipt, meanTru[3][ieta][ipt]); - histos.fill(HIST("MCGen/Prof_MeanpT_Mult_etabin_ptbin_Pr"), col.multNTracksPV(), ieta, ipt, meanTru[3][ieta][ipt]); - } - if (std::isfinite(c2Tru[3][ieta][ipt])) { - histos.fill(HIST("MCGen/Prof_C2_Cent_etabin_ptbin_Pr"), cent, ieta, ipt, c2Tru[3][ieta][ipt]); - histos.fill(HIST("MCGen/Prof_C2_Mult_etabin_ptbin_Pr"), col.multNTracksPV(), ieta, ipt, c2Tru[3][ieta][ipt]); - } - // --- MCReco --- - if (std::isfinite(meanReco[3][ieta][ipt])) { - histos.fill(HIST("MCReco/Prof_MeanpT_Cent_etabin_ptbin_Pr"), cent, ieta, ipt, meanReco[3][ieta][ipt]); - histos.fill(HIST("MCReco/Prof_MeanpT_Mult_etabin_ptbin_Pr"), col.multNTracksPV(), ieta, ipt, meanReco[3][ieta][ipt]); - } - if (std::isfinite(c2Reco[3][ieta][ipt])) { - histos.fill(HIST("MCReco/Prof_C2_Cent_etabin_ptbin_Pr"), cent, ieta, ipt, c2Reco[3][ieta][ipt]); - histos.fill(HIST("MCReco/Prof_C2_Mult_etabin_ptbin_Pr"), col.multNTracksPV(), ieta, ipt, c2Reco[3][ieta][ipt]); - } - // --- MCRecoEffCorr --- - if (std::isfinite(meanRecoEffCor[3][ieta][ipt])) { - histos.fill(HIST("MCRecoEffCorr/Prof_MeanpT_Cent_etabin_ptbin_Pr"), cent, ieta, ipt, meanRecoEffCor[3][ieta][ipt]); - histos.fill(HIST("MCRecoEffCorr/Prof_MeanpT_Mult_etabin_ptbin_Pr"), col.multNTracksPV(), ieta, ipt, meanRecoEffCor[3][ieta][ipt]); - } - if (std::isfinite(c2RecoEffCor[3][ieta][ipt])) { - histos.fill(HIST("MCRecoEffCorr/Prof_C2_Cent_etabin_ptbin_Pr"), cent, ieta, ipt, c2RecoEffCor[3][ieta][ipt]); - histos.fill(HIST("MCRecoEffCorr/Prof_C2_Mult_etabin_ptbin_Pr"), col.multNTracksPV(), ieta, ipt, c2RecoEffCor[3][ieta][ipt]); - } - } - } - } - } + float covTru = p1kBarTruMult[isp][ietaA] * p1kBarTru[isp][ietaC]; + float covReco = p1kBarRecoMult[isp][ietaA] * p1kBarReco[isp][ietaC]; + float covRecoEffCor = p1kBarRecoEffCorMult[isp][ietaA] * p1kBarRecoEffCor[isp][ietaC]; - // --- 4. Symmetric Sub-Event (1D) Covariances --- - for (int ietaA = 1; ietaA <= (KNEta - 1) / 2; ++ietaA) { - int ietaC = KNEta - ietaA; - for (int ipt = 0; ipt < KNpT; ++ipt) { - for (int isp = 0; isp < KNsp; ++isp) { - float c2SubTru = p1kBarTru[isp][ietaA][ipt] * p1kBarTru[isp][ietaC][ipt]; - float c2SubReco = p1kBarReco[isp][ietaA][ipt] * p1kBarReco[isp][ietaC][ipt]; - float c2SubRecoEffCor = p1kBarRecoEffCor[isp][ietaA][ipt] * p1kBarRecoEffCor[isp][ietaC][ipt]; + float covFT0ATru = p1kBarFt0A * p1kBarTru[isp][ietaC]; + float covFT0AReco = p1kBarFt0A * p1kBarReco[isp][ietaC]; + float covFT0ARecoEffCor = p1kBarFt0A * p1kBarRecoEffCor[isp][ietaC]; - float covTru = p1kBarTruMult[isp][ietaA][ipt] * p1kBarTru[isp][ietaC][ipt]; - float covReco = p1kBarRecoMult[isp][ietaA][ipt] * p1kBarReco[isp][ietaC][ipt]; - float covRecoEffCor = p1kBarRecoEffCorMult[isp][ietaA][ipt] * p1kBarRecoEffCor[isp][ietaC][ipt]; + float covFT0CTru = p1kBarFt0C * p1kBarTru[isp][ietaA]; + float covFT0CReco = p1kBarFt0C * p1kBarReco[isp][ietaA]; + float covFT0CRecoEffCor = p1kBarFt0C * p1kBarRecoEffCor[isp][ietaA]; - if (isp == numKInclusive) { + if (isp == kInclusive) { if (std::isfinite(c2SubTru)) { - histos.fill(HIST("MCGen/Prof_C2Sub_Cent_etabin_ptbin"), cent, ietaA, ipt, c2SubTru); - histos.fill(HIST("MCGen/Prof_C2Sub_Mult_etabin_ptbin"), col.multNTracksPV(), ietaA, ipt, c2SubTru); + histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC"), cent, etaValA, etaValB, c2SubTru); + histos.fill(HIST("MCGen/Prof_GapSum2D"), cent, gap, sum, c2SubTru); } if (std::isfinite(c2SubReco)) { - histos.fill(HIST("MCReco/Prof_C2Sub_Cent_etabin_ptbin"), cent, ietaA, ipt, c2SubReco); - histos.fill(HIST("MCReco/Prof_C2Sub_Mult_etabin_ptbin"), col.multNTracksPV(), ietaA, ipt, c2SubReco); + histos.fill(HIST("MCReco/Prof_C2Sub2D_Cent_etaA_etaC"), cent, etaValA, etaValB, c2SubReco); + histos.fill(HIST("MCReco/Prof_GapSum2D"), cent, gap, sum, c2SubReco); } if (std::isfinite(c2SubRecoEffCor)) { - histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub_Cent_etabin_ptbin"), cent, ietaA, ipt, c2SubRecoEffCor); - histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub_Mult_etabin_ptbin"), col.multNTracksPV(), ietaA, ipt, c2SubRecoEffCor); - } - if (std::isfinite(covTru)) { - histos.fill(HIST("MCGen/Prof_Cov_Cent_etabin_ptbin"), cent, ietaA, ipt, covTru); - histos.fill(HIST("MCGen/Prof_Cov_Mult_etabin_ptbin"), col.multNTracksPV(), ietaA, ipt, covTru); - } - if (std::isfinite(covReco)) { - histos.fill(HIST("MCReco/Prof_Cov_Cent_etabin_ptbin"), cent, ietaA, ipt, covReco); - histos.fill(HIST("MCReco/Prof_Cov_Mult_etabin_ptbin"), col.multNTracksPV(), ietaA, ipt, covReco); - } - if (std::isfinite(covRecoEffCor)) { - histos.fill(HIST("MCRecoEffCorr/Prof_Cov_Cent_etabin_ptbin"), cent, ietaA, ipt, covRecoEffCor); - histos.fill(HIST("MCRecoEffCorr/Prof_Cov_Mult_etabin_ptbin"), col.multNTracksPV(), ietaA, ipt, covRecoEffCor); - } - - } else if (isp == numKPion) { // Pion + histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub2D_Cent_etaA_etaC"), cent, etaValA, etaValB, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_GapSum2D"), cent, gap, sum, c2SubRecoEffCor); + } + + if (std::isfinite(covTru)) + histos.fill(HIST("MCGen/Prof_Cov2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covTru); + if (std::isfinite(covReco)) + histos.fill(HIST("MCReco/Prof_Cov2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covReco); + if (std::isfinite(covRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_Cov2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covRecoEffCor); + + if (std::isfinite(covFT0ATru)) + histos.fill(HIST("MCGen/Prof_CovFT0A2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covFT0ATru); + if (std::isfinite(covFT0AReco)) + histos.fill(HIST("MCReco/Prof_CovFT0A2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covFT0AReco); + if (std::isfinite(covFT0ARecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covFT0ARecoEffCor); + + if (std::isfinite(covFT0CTru)) + histos.fill(HIST("MCGen/Prof_CovFT0C2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covFT0CTru); + if (std::isfinite(covFT0CReco)) + histos.fill(HIST("MCReco/Prof_CovFT0C2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covFT0CReco); + if (std::isfinite(covFT0CRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covFT0CRecoEffCor); + + } else if (isp == kPiMinus) { if (std::isfinite(c2SubTru)) { - histos.fill(HIST("MCGen/Prof_C2Sub_Cent_etabin_ptbin_Pi"), cent, ietaA, ipt, c2SubTru); - histos.fill(HIST("MCGen/Prof_C2Sub_Mult_etabin_ptbin_Pi"), col.multNTracksPV(), ietaA, ipt, c2SubTru); + histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, c2SubTru); + histos.fill(HIST("MCGen/Prof_GapSum2D_PiMinus"), cent, gap, sum, c2SubTru); } if (std::isfinite(c2SubReco)) { - histos.fill(HIST("MCReco/Prof_C2Sub_Cent_etabin_ptbin_Pi"), cent, ietaA, ipt, c2SubReco); - histos.fill(HIST("MCReco/Prof_C2Sub_Mult_etabin_ptbin_Pi"), col.multNTracksPV(), ietaA, ipt, c2SubReco); + histos.fill(HIST("MCReco/Prof_C2Sub2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, c2SubReco); + histos.fill(HIST("MCReco/Prof_GapSum2D_PiMinus"), cent, gap, sum, c2SubReco); } if (std::isfinite(c2SubRecoEffCor)) { - histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub_Cent_etabin_ptbin_Pi"), cent, ietaA, ipt, c2SubRecoEffCor); - histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub_Mult_etabin_ptbin_Pi"), col.multNTracksPV(), ietaA, ipt, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_GapSum2D_PiMinus"), cent, gap, sum, c2SubRecoEffCor); + } + + if (std::isfinite(covTru)) + histos.fill(HIST("MCGen/Prof_Cov2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, covTru); + if (std::isfinite(covReco)) + histos.fill(HIST("MCReco/Prof_Cov2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, covReco); + if (std::isfinite(covRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_Cov2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, covRecoEffCor); + + if (std::isfinite(covFT0ATru)) + histos.fill(HIST("MCGen/Prof_CovFT0A2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, covFT0ATru); + if (std::isfinite(covFT0AReco)) + histos.fill(HIST("MCReco/Prof_CovFT0A2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, covFT0AReco); + if (std::isfinite(covFT0ARecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, covFT0ARecoEffCor); + + if (std::isfinite(covFT0CTru)) + histos.fill(HIST("MCGen/Prof_CovFT0C2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, covFT0CTru); + if (std::isfinite(covFT0CReco)) + histos.fill(HIST("MCReco/Prof_CovFT0C2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, covFT0CReco); + if (std::isfinite(covFT0CRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, covFT0CRecoEffCor); + + } else if (isp == kPiPlus) { + if (std::isfinite(c2SubTru)) { + histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, c2SubTru); + histos.fill(HIST("MCGen/Prof_GapSum2D_PiPlus"), cent, gap, sum, c2SubTru); } - if (std::isfinite(covTru)) { - histos.fill(HIST("MCGen/Prof_Cov_Cent_etabin_ptbin_Pi"), cent, ietaA, ipt, covTru); - histos.fill(HIST("MCGen/Prof_Cov_Mult_etabin_ptbin_Pi"), col.multNTracksPV(), ietaA, ipt, covTru); + if (std::isfinite(c2SubReco)) { + histos.fill(HIST("MCReco/Prof_C2Sub2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, c2SubReco); + histos.fill(HIST("MCReco/Prof_GapSum2D_PiPlus"), cent, gap, sum, c2SubReco); } - if (std::isfinite(covReco)) { - histos.fill(HIST("MCReco/Prof_Cov_Cent_etabin_ptbin_Pi"), cent, ietaA, ipt, covReco); - histos.fill(HIST("MCReco/Prof_Cov_Mult_etabin_ptbin_Pi"), col.multNTracksPV(), ietaA, ipt, covReco); + if (std::isfinite(c2SubRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_GapSum2D_PiPlus"), cent, gap, sum, c2SubRecoEffCor); + } + + if (std::isfinite(covTru)) + histos.fill(HIST("MCGen/Prof_Cov2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, covTru); + if (std::isfinite(covReco)) + histos.fill(HIST("MCReco/Prof_Cov2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, covReco); + if (std::isfinite(covRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_Cov2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, covRecoEffCor); + + if (std::isfinite(covFT0ATru)) + histos.fill(HIST("MCGen/Prof_CovFT0A2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, covFT0ATru); + if (std::isfinite(covFT0AReco)) + histos.fill(HIST("MCReco/Prof_CovFT0A2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, covFT0AReco); + if (std::isfinite(covFT0ARecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, covFT0ARecoEffCor); + + if (std::isfinite(covFT0CTru)) + histos.fill(HIST("MCGen/Prof_CovFT0C2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, covFT0CTru); + if (std::isfinite(covFT0CReco)) + histos.fill(HIST("MCReco/Prof_CovFT0C2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, covFT0CReco); + if (std::isfinite(covFT0CRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, covFT0CRecoEffCor); + + } else if (isp == kPiAll) { + if (std::isfinite(c2SubTru)) { + histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, c2SubTru); + histos.fill(HIST("MCGen/Prof_GapSum2D_PiAll"), cent, gap, sum, c2SubTru); } - if (std::isfinite(covRecoEffCor)) { - histos.fill(HIST("MCRecoEffCorr/Prof_Cov_Cent_etabin_ptbin_Pi"), cent, ietaA, ipt, covRecoEffCor); - histos.fill(HIST("MCRecoEffCorr/Prof_Cov_Mult_etabin_ptbin_Pi"), col.multNTracksPV(), ietaA, ipt, covRecoEffCor); + if (std::isfinite(c2SubReco)) { + histos.fill(HIST("MCReco/Prof_C2Sub2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, c2SubReco); + histos.fill(HIST("MCReco/Prof_GapSum2D_PiAll"), cent, gap, sum, c2SubReco); } - - } else if (isp == numKKaon) { // Kaon + if (std::isfinite(c2SubRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_GapSum2D_PiAll"), cent, gap, sum, c2SubRecoEffCor); + } + + if (std::isfinite(covTru)) + histos.fill(HIST("MCGen/Prof_Cov2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, covTru); + if (std::isfinite(covReco)) + histos.fill(HIST("MCReco/Prof_Cov2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, covReco); + if (std::isfinite(covRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_Cov2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, covRecoEffCor); + + if (std::isfinite(covFT0ATru)) + histos.fill(HIST("MCGen/Prof_CovFT0A2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, covFT0ATru); + if (std::isfinite(covFT0AReco)) + histos.fill(HIST("MCReco/Prof_CovFT0A2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, covFT0AReco); + if (std::isfinite(covFT0ARecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, covFT0ARecoEffCor); + + if (std::isfinite(covFT0CTru)) + histos.fill(HIST("MCGen/Prof_CovFT0C2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, covFT0CTru); + if (std::isfinite(covFT0CReco)) + histos.fill(HIST("MCReco/Prof_CovFT0C2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, covFT0CReco); + if (std::isfinite(covFT0CRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, covFT0CRecoEffCor); + + } else if (isp == kKaMinus) { if (std::isfinite(c2SubTru)) { - histos.fill(HIST("MCGen/Prof_C2Sub_Cent_etabin_ptbin_Ka"), cent, ietaA, ipt, c2SubTru); - histos.fill(HIST("MCGen/Prof_C2Sub_Mult_etabin_ptbin_Ka"), col.multNTracksPV(), ietaA, ipt, c2SubTru); + histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, c2SubTru); + histos.fill(HIST("MCGen/Prof_GapSum2D_KaMinus"), cent, gap, sum, c2SubTru); } if (std::isfinite(c2SubReco)) { - histos.fill(HIST("MCReco/Prof_C2Sub_Cent_etabin_ptbin_Ka"), cent, ietaA, ipt, c2SubReco); - histos.fill(HIST("MCReco/Prof_C2Sub_Mult_etabin_ptbin_Ka"), col.multNTracksPV(), ietaA, ipt, c2SubReco); + histos.fill(HIST("MCReco/Prof_C2Sub2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, c2SubReco); + histos.fill(HIST("MCReco/Prof_GapSum2D_KaMinus"), cent, gap, sum, c2SubReco); } if (std::isfinite(c2SubRecoEffCor)) { - histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub_Cent_etabin_ptbin_Ka"), cent, ietaA, ipt, c2SubRecoEffCor); - histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub_Mult_etabin_ptbin_Ka"), col.multNTracksPV(), ietaA, ipt, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_GapSum2D_KaMinus"), cent, gap, sum, c2SubRecoEffCor); + } + + if (std::isfinite(covTru)) + histos.fill(HIST("MCGen/Prof_Cov2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, covTru); + if (std::isfinite(covReco)) + histos.fill(HIST("MCReco/Prof_Cov2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, covReco); + if (std::isfinite(covRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_Cov2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, covRecoEffCor); + + if (std::isfinite(covFT0ATru)) + histos.fill(HIST("MCGen/Prof_CovFT0A2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, covFT0ATru); + if (std::isfinite(covFT0AReco)) + histos.fill(HIST("MCReco/Prof_CovFT0A2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, covFT0AReco); + if (std::isfinite(covFT0ARecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, covFT0ARecoEffCor); + + if (std::isfinite(covFT0CTru)) + histos.fill(HIST("MCGen/Prof_CovFT0C2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, covFT0CTru); + if (std::isfinite(covFT0CReco)) + histos.fill(HIST("MCReco/Prof_CovFT0C2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, covFT0CReco); + if (std::isfinite(covFT0CRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, covFT0CRecoEffCor); + + } else if (isp == kKaPlus) { + if (std::isfinite(c2SubTru)) { + histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, c2SubTru); + histos.fill(HIST("MCGen/Prof_GapSum2D_KaPlus"), cent, gap, sum, c2SubTru); } - if (std::isfinite(covTru)) { - histos.fill(HIST("MCGen/Prof_Cov_Cent_etabin_ptbin_Ka"), cent, ietaA, ipt, covTru); - histos.fill(HIST("MCGen/Prof_Cov_Mult_etabin_ptbin_Ka"), col.multNTracksPV(), ietaA, ipt, covTru); + if (std::isfinite(c2SubReco)) { + histos.fill(HIST("MCReco/Prof_C2Sub2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, c2SubReco); + histos.fill(HIST("MCReco/Prof_GapSum2D_KaPlus"), cent, gap, sum, c2SubReco); } - if (std::isfinite(covReco)) { - histos.fill(HIST("MCReco/Prof_Cov_Cent_etabin_ptbin_Ka"), cent, ietaA, ipt, covReco); - histos.fill(HIST("MCReco/Prof_Cov_Mult_etabin_ptbin_Ka"), col.multNTracksPV(), ietaA, ipt, covReco); + if (std::isfinite(c2SubRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_GapSum2D_KaPlus"), cent, gap, sum, c2SubRecoEffCor); + } + + if (std::isfinite(covTru)) + histos.fill(HIST("MCGen/Prof_Cov2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, covTru); + if (std::isfinite(covReco)) + histos.fill(HIST("MCReco/Prof_Cov2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, covReco); + if (std::isfinite(covRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_Cov2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, covRecoEffCor); + + if (std::isfinite(covFT0ATru)) + histos.fill(HIST("MCGen/Prof_CovFT0A2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, covFT0ATru); + if (std::isfinite(covFT0AReco)) + histos.fill(HIST("MCReco/Prof_CovFT0A2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, covFT0AReco); + if (std::isfinite(covFT0ARecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, covFT0ARecoEffCor); + + if (std::isfinite(covFT0CTru)) + histos.fill(HIST("MCGen/Prof_CovFT0C2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, covFT0CTru); + if (std::isfinite(covFT0CReco)) + histos.fill(HIST("MCReco/Prof_CovFT0C2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, covFT0CReco); + if (std::isfinite(covFT0CRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, covFT0CRecoEffCor); + + } else if (isp == kKaAll) { + if (std::isfinite(c2SubTru)) { + histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, c2SubTru); + histos.fill(HIST("MCGen/Prof_GapSum2D_KaAll"), cent, gap, sum, c2SubTru); } - if (std::isfinite(covRecoEffCor)) { - histos.fill(HIST("MCRecoEffCorr/Prof_Cov_Cent_etabin_ptbin_Ka"), cent, ietaA, ipt, covRecoEffCor); - histos.fill(HIST("MCRecoEffCorr/Prof_Cov_Mult_etabin_ptbin_Ka"), col.multNTracksPV(), ietaA, ipt, covRecoEffCor); + if (std::isfinite(c2SubReco)) { + histos.fill(HIST("MCReco/Prof_C2Sub2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, c2SubReco); + histos.fill(HIST("MCReco/Prof_GapSum2D_KaAll"), cent, gap, sum, c2SubReco); } - } else if (isp == numKProton) { // Proton + if (std::isfinite(c2SubRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_GapSum2D_KaAll"), cent, gap, sum, c2SubRecoEffCor); + } + + if (std::isfinite(covTru)) + histos.fill(HIST("MCGen/Prof_Cov2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, covTru); + if (std::isfinite(covReco)) + histos.fill(HIST("MCReco/Prof_Cov2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, covReco); + if (std::isfinite(covRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_Cov2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, covRecoEffCor); + + if (std::isfinite(covFT0ATru)) + histos.fill(HIST("MCGen/Prof_CovFT0A2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, covFT0ATru); + if (std::isfinite(covFT0AReco)) + histos.fill(HIST("MCReco/Prof_CovFT0A2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, covFT0AReco); + if (std::isfinite(covFT0ARecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, covFT0ARecoEffCor); + + if (std::isfinite(covFT0CTru)) + histos.fill(HIST("MCGen/Prof_CovFT0C2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, covFT0CTru); + if (std::isfinite(covFT0CReco)) + histos.fill(HIST("MCReco/Prof_CovFT0C2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, covFT0CReco); + if (std::isfinite(covFT0CRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, covFT0CRecoEffCor); + + } else if (isp == kProton) { if (std::isfinite(c2SubTru)) { - histos.fill(HIST("MCGen/Prof_C2Sub_Cent_etabin_ptbin_Pr"), cent, ietaA, ipt, c2SubTru); - histos.fill(HIST("MCGen/Prof_C2Sub_Mult_etabin_ptbin_Pr"), col.multNTracksPV(), ietaA, ipt, c2SubTru); + histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, c2SubTru); + histos.fill(HIST("MCGen/Prof_GapSum2D_Pr"), cent, gap, sum, c2SubTru); } if (std::isfinite(c2SubReco)) { - histos.fill(HIST("MCReco/Prof_C2Sub_Cent_etabin_ptbin_Pr"), cent, ietaA, ipt, c2SubReco); - histos.fill(HIST("MCReco/Prof_C2Sub_Mult_etabin_ptbin_Pr"), col.multNTracksPV(), ietaA, ipt, c2SubReco); + histos.fill(HIST("MCReco/Prof_C2Sub2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, c2SubReco); + histos.fill(HIST("MCReco/Prof_GapSum2D_Pr"), cent, gap, sum, c2SubReco); } if (std::isfinite(c2SubRecoEffCor)) { - histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub_Cent_etabin_ptbin_Pr"), cent, ietaA, ipt, c2SubRecoEffCor); - histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub_Mult_etabin_ptbin_Pr"), col.multNTracksPV(), ietaA, ipt, c2SubRecoEffCor); - } - if (std::isfinite(covTru)) { - histos.fill(HIST("MCGen/Prof_Cov_Cent_etabin_ptbin_Pr"), cent, ietaA, ipt, covTru); - histos.fill(HIST("MCGen/Prof_Cov_Mult_etabin_ptbin_Pr"), col.multNTracksPV(), ietaA, ipt, covTru); + histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_GapSum2D_Pr"), cent, gap, sum, c2SubRecoEffCor); + } + + if (std::isfinite(covTru)) + histos.fill(HIST("MCGen/Prof_Cov2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covTru); + if (std::isfinite(covReco)) + histos.fill(HIST("MCReco/Prof_Cov2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covReco); + if (std::isfinite(covRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_Cov2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covRecoEffCor); + + if (std::isfinite(covFT0ATru)) + histos.fill(HIST("MCGen/Prof_CovFT0A2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covFT0ATru); + if (std::isfinite(covFT0AReco)) + histos.fill(HIST("MCReco/Prof_CovFT0A2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covFT0AReco); + if (std::isfinite(covFT0ARecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covFT0ARecoEffCor); + + if (std::isfinite(covFT0CTru)) + histos.fill(HIST("MCGen/Prof_CovFT0C2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covFT0CTru); + if (std::isfinite(covFT0CReco)) + histos.fill(HIST("MCReco/Prof_CovFT0C2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covFT0CReco); + if (std::isfinite(covFT0CRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covFT0CRecoEffCor); + + } else if (isp == kAntiProton) { + if (std::isfinite(c2SubTru)) { + histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, c2SubTru); + histos.fill(HIST("MCGen/Prof_GapSum2D_AntiPr"), cent, gap, sum, c2SubTru); } - if (std::isfinite(covReco)) { - histos.fill(HIST("MCReco/Prof_Cov_Cent_etabin_ptbin_Pr"), cent, ietaA, ipt, covReco); - histos.fill(HIST("MCReco/Prof_Cov_Mult_etabin_ptbin_Pr"), col.multNTracksPV(), ietaA, ipt, covReco); + if (std::isfinite(c2SubReco)) { + histos.fill(HIST("MCReco/Prof_C2Sub2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, c2SubReco); + histos.fill(HIST("MCReco/Prof_GapSum2D_AntiPr"), cent, gap, sum, c2SubReco); } - if (std::isfinite(covRecoEffCor)) { - histos.fill(HIST("MCRecoEffCorr/Prof_Cov_Cent_etabin_ptbin_Pr"), cent, ietaA, ipt, covRecoEffCor); - histos.fill(HIST("MCRecoEffCorr/Prof_Cov_Mult_etabin_ptbin_Pr"), col.multNTracksPV(), ietaA, ipt, covRecoEffCor); + if (std::isfinite(c2SubRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_GapSum2D_AntiPr"), cent, gap, sum, c2SubRecoEffCor); + } + + if (std::isfinite(covTru)) + histos.fill(HIST("MCGen/Prof_Cov2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, covTru); + if (std::isfinite(covReco)) + histos.fill(HIST("MCReco/Prof_Cov2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, covReco); + if (std::isfinite(covRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_Cov2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, covRecoEffCor); + + if (std::isfinite(covFT0ATru)) + histos.fill(HIST("MCGen/Prof_CovFT0A2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, covFT0ATru); + if (std::isfinite(covFT0AReco)) + histos.fill(HIST("MCReco/Prof_CovFT0A2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, covFT0AReco); + if (std::isfinite(covFT0ARecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, covFT0ARecoEffCor); + + if (std::isfinite(covFT0CTru)) + histos.fill(HIST("MCGen/Prof_CovFT0C2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, covFT0CTru); + if (std::isfinite(covFT0CReco)) + histos.fill(HIST("MCReco/Prof_CovFT0C2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, covFT0CReco); + if (std::isfinite(covFT0CRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, covFT0CRecoEffCor); + + } else if (isp == kAllProton) { + if (std::isfinite(c2SubTru)) { + histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC_AllPr"), cent, etaValA, etaValB, c2SubTru); + histos.fill(HIST("MCGen/Prof_GapSum2D_AllPr"), cent, gap, sum, c2SubTru); } - } - } - } - } - - // --- 5. Full 2D Covariances & GapSum2D Profiles --- - for (int ietaA = 1; ietaA < KNEta; ++ietaA) { - for (int ietaB = 1; ietaB < KNEta; ++ietaB) { - - // Gap and Sum calculations - float etaValA = (etaLw[ietaA] + etaUp[ietaA]) / 2.0f; - float etaValB = (etaLw[ietaB] + etaUp[ietaB]) / 2.0f; - float gap = etaValA - etaValB; - float sum = (etaValA + etaValB) / 2.0f; - - for (int ipt = 0; ipt < KNpT; ++ipt) { - for (int isp = 0; isp < KNsp; ++isp) { - - float c2SubTru = p1kBarTru[isp][ietaA][ipt] * p1kBarTru[isp][ietaB][ipt]; - float c2SubReco = p1kBarReco[isp][ietaA][ipt] * p1kBarReco[isp][ietaB][ipt]; - float c2SubRecoEffCor = p1kBarRecoEffCor[isp][ietaA][ipt] * p1kBarRecoEffCor[isp][ietaB][ipt]; - - float covTru = p1kBarTruMult[isp][ietaA][ipt] * p1kBarTru[isp][ietaB][ipt]; - float covReco = p1kBarRecoMult[isp][ietaA][ipt] * p1kBarReco[isp][ietaB][ipt]; - float covRecoEffCor = p1kBarRecoEffCorMult[isp][ietaA][ipt] * p1kBarRecoEffCor[isp][ietaB][ipt]; - - if (isp == numKInclusive) { // Inclusive - if (ipt == 0) { - if (std::isfinite(c2SubTru)) { - histos.fill(HIST("MCGen/Prof_ipt0_C2Sub2D_Cent_etaA_etaC"), cent, etaValA, etaValB, c2SubTru); - histos.fill(HIST("MCGen/Prof_ipt0_GapSum2D"), cent, gap, sum, c2SubTru); - } - if (std::isfinite(c2SubReco)) { - histos.fill(HIST("MCReco/Prof_ipt0_C2Sub2D_Cent_etaA_etaC"), cent, etaValA, etaValB, c2SubReco); - histos.fill(HIST("MCReco/Prof_ipt0_GapSum2D"), cent, gap, sum, c2SubReco); - } - if (std::isfinite(c2SubRecoEffCor)) { - histos.fill(HIST("MCRecoEffCorr/Prof_ipt0_C2Sub2D_Cent_etaA_etaC"), cent, etaValA, etaValB, c2SubRecoEffCor); - histos.fill(HIST("MCRecoEffCorr/Prof_ipt0_GapSum2D"), cent, gap, sum, c2SubRecoEffCor); - } - if (std::isfinite(covTru)) - histos.fill(HIST("MCGen/Prof_ipt0_Cov2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covTru); - if (std::isfinite(covReco)) - histos.fill(HIST("MCReco/Prof_ipt0_Cov2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covReco); - if (std::isfinite(covRecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_ipt0_Cov2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covRecoEffCor); - } else if (ipt == KNpT - 2) { - if (std::isfinite(c2SubTru)) { - histos.fill(HIST("MCGen/Prof_ipt1_C2Sub2D_Cent_etaA_etaC"), cent, etaValA, etaValB, c2SubTru); - histos.fill(HIST("MCGen/Prof_ipt1_GapSum2D"), cent, gap, sum, c2SubTru); - } - if (std::isfinite(c2SubReco)) { - histos.fill(HIST("MCReco/Prof_ipt1_C2Sub2D_Cent_etaA_etaC"), cent, etaValA, etaValB, c2SubReco); - histos.fill(HIST("MCReco/Prof_ipt1_GapSum2D"), cent, gap, sum, c2SubReco); - } - if (std::isfinite(c2SubRecoEffCor)) { - histos.fill(HIST("MCRecoEffCorr/Prof_ipt1_C2Sub2D_Cent_etaA_etaC"), cent, etaValA, etaValB, c2SubRecoEffCor); - histos.fill(HIST("MCRecoEffCorr/Prof_ipt1_GapSum2D"), cent, gap, sum, c2SubRecoEffCor); - } - if (std::isfinite(covTru)) - histos.fill(HIST("MCGen/Prof_ipt1_Cov2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covTru); - if (std::isfinite(covReco)) - histos.fill(HIST("MCReco/Prof_ipt1_Cov2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covReco); - if (std::isfinite(covRecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_ipt1_Cov2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covRecoEffCor); - } else if (ipt == KNpT - 1) { - if (std::isfinite(c2SubTru)) { - histos.fill(HIST("MCGen/Prof_ipt2_C2Sub2D_Cent_etaA_etaC"), cent, etaValA, etaValB, c2SubTru); - histos.fill(HIST("MCGen/Prof_ipt2_GapSum2D"), cent, gap, sum, c2SubTru); - } - if (std::isfinite(c2SubReco)) { - histos.fill(HIST("MCReco/Prof_ipt2_C2Sub2D_Cent_etaA_etaC"), cent, etaValA, etaValB, c2SubReco); - histos.fill(HIST("MCReco/Prof_ipt2_GapSum2D"), cent, gap, sum, c2SubReco); - } - if (std::isfinite(c2SubRecoEffCor)) { - histos.fill(HIST("MCRecoEffCorr/Prof_ipt2_C2Sub2D_Cent_etaA_etaC"), cent, etaValA, etaValB, c2SubRecoEffCor); - histos.fill(HIST("MCRecoEffCorr/Prof_ipt2_GapSum2D"), cent, gap, sum, c2SubRecoEffCor); - } - if (std::isfinite(covTru)) - histos.fill(HIST("MCGen/Prof_ipt2_Cov2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covTru); - if (std::isfinite(covReco)) - histos.fill(HIST("MCReco/Prof_ipt2_Cov2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covReco); - if (std::isfinite(covRecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_ipt2_Cov2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covRecoEffCor); - } - - } else if (isp == numKPion) { // Pion - if (ipt == 0) { - if (std::isfinite(c2SubTru)) { - histos.fill(HIST("MCGen/Prof_ipt0_C2Sub2D_Cent_etaA_etaC_Pi"), cent, etaValA, etaValB, c2SubTru); - histos.fill(HIST("MCGen/Prof_ipt0_GapSum2D_Pi"), cent, gap, sum, c2SubTru); - } - if (std::isfinite(c2SubReco)) { - histos.fill(HIST("MCReco/Prof_ipt0_C2Sub2D_Cent_etaA_etaC_Pi"), cent, etaValA, etaValB, c2SubReco); - histos.fill(HIST("MCReco/Prof_ipt0_GapSum2D_Pi"), cent, gap, sum, c2SubReco); - } - if (std::isfinite(c2SubRecoEffCor)) { - histos.fill(HIST("MCRecoEffCorr/Prof_ipt0_C2Sub2D_Cent_etaA_etaC_Pi"), cent, etaValA, etaValB, c2SubRecoEffCor); - histos.fill(HIST("MCRecoEffCorr/Prof_ipt0_GapSum2D_Pi"), cent, gap, sum, c2SubRecoEffCor); - } - if (std::isfinite(covTru)) - histos.fill(HIST("MCGen/Prof_ipt0_Cov2D_Cent_etaA_etaC_Pi"), cent, etaValA, etaValB, covTru); - if (std::isfinite(covReco)) - histos.fill(HIST("MCReco/Prof_ipt0_Cov2D_Cent_etaA_etaC_Pi"), cent, etaValA, etaValB, covReco); - if (std::isfinite(covRecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_ipt0_Cov2D_Cent_etaA_etaC_Pi"), cent, etaValA, etaValB, covRecoEffCor); - } else if (ipt == KNpT - 2) { - if (std::isfinite(c2SubTru)) { - histos.fill(HIST("MCGen/Prof_ipt1_C2Sub2D_Cent_etaA_etaC_Pi"), cent, etaValA, etaValB, c2SubTru); - histos.fill(HIST("MCGen/Prof_ipt1_GapSum2D_Pi"), cent, gap, sum, c2SubTru); - } - if (std::isfinite(c2SubReco)) { - histos.fill(HIST("MCReco/Prof_ipt1_C2Sub2D_Cent_etaA_etaC_Pi"), cent, etaValA, etaValB, c2SubReco); - histos.fill(HIST("MCReco/Prof_ipt1_GapSum2D_Pi"), cent, gap, sum, c2SubReco); - } - if (std::isfinite(c2SubRecoEffCor)) { - histos.fill(HIST("MCRecoEffCorr/Prof_ipt1_C2Sub2D_Cent_etaA_etaC_Pi"), cent, etaValA, etaValB, c2SubRecoEffCor); - histos.fill(HIST("MCRecoEffCorr/Prof_ipt1_GapSum2D_Pi"), cent, gap, sum, c2SubRecoEffCor); - } - if (std::isfinite(covTru)) - histos.fill(HIST("MCGen/Prof_ipt1_Cov2D_Cent_etaA_etaC_Pi"), cent, etaValA, etaValB, covTru); - if (std::isfinite(covReco)) - histos.fill(HIST("MCReco/Prof_ipt1_Cov2D_Cent_etaA_etaC_Pi"), cent, etaValA, etaValB, covReco); - if (std::isfinite(covRecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_ipt1_Cov2D_Cent_etaA_etaC_Pi"), cent, etaValA, etaValB, covRecoEffCor); - } else if (ipt == KNpT - 1) { - if (std::isfinite(c2SubTru)) { - histos.fill(HIST("MCGen/Prof_ipt2_C2Sub2D_Cent_etaA_etaC_Pi"), cent, etaValA, etaValB, c2SubTru); - histos.fill(HIST("MCGen/Prof_ipt2_GapSum2D_Pi"), cent, gap, sum, c2SubTru); - } - if (std::isfinite(c2SubReco)) { - histos.fill(HIST("MCReco/Prof_ipt2_C2Sub2D_Cent_etaA_etaC_Pi"), cent, etaValA, etaValB, c2SubReco); - histos.fill(HIST("MCReco/Prof_ipt2_GapSum2D_Pi"), cent, gap, sum, c2SubReco); - } - if (std::isfinite(c2SubRecoEffCor)) { - histos.fill(HIST("MCRecoEffCorr/Prof_ipt2_C2Sub2D_Cent_etaA_etaC_Pi"), cent, etaValA, etaValB, c2SubRecoEffCor); - histos.fill(HIST("MCRecoEffCorr/Prof_ipt2_GapSum2D_Pi"), cent, gap, sum, c2SubRecoEffCor); - } - if (std::isfinite(covTru)) - histos.fill(HIST("MCGen/Prof_ipt2_Cov2D_Cent_etaA_etaC_Pi"), cent, etaValA, etaValB, covTru); - if (std::isfinite(covReco)) - histos.fill(HIST("MCReco/Prof_ipt2_Cov2D_Cent_etaA_etaC_Pi"), cent, etaValA, etaValB, covReco); - if (std::isfinite(covRecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_ipt2_Cov2D_Cent_etaA_etaC_Pi"), cent, etaValA, etaValB, covRecoEffCor); - } - } else if (isp == numKKaon) { // Kaon - if (ipt == 0) { - if (std::isfinite(c2SubTru)) { - histos.fill(HIST("MCGen/Prof_ipt0_C2Sub2D_Cent_etaA_etaC_Ka"), cent, etaValA, etaValB, c2SubTru); - histos.fill(HIST("MCGen/Prof_ipt0_GapSum2D_Ka"), cent, gap, sum, c2SubTru); - } - if (std::isfinite(c2SubReco)) { - histos.fill(HIST("MCReco/Prof_ipt0_C2Sub2D_Cent_etaA_etaC_Ka"), cent, etaValA, etaValB, c2SubReco); - histos.fill(HIST("MCReco/Prof_ipt0_GapSum2D_Ka"), cent, gap, sum, c2SubReco); - } - if (std::isfinite(c2SubRecoEffCor)) { - histos.fill(HIST("MCRecoEffCorr/Prof_ipt0_C2Sub2D_Cent_etaA_etaC_Ka"), cent, etaValA, etaValB, c2SubRecoEffCor); - histos.fill(HIST("MCRecoEffCorr/Prof_ipt0_GapSum2D_Ka"), cent, gap, sum, c2SubRecoEffCor); - } - if (std::isfinite(covTru)) - histos.fill(HIST("MCGen/Prof_ipt0_Cov2D_Cent_etaA_etaC_Ka"), cent, etaValA, etaValB, covTru); - if (std::isfinite(covReco)) - histos.fill(HIST("MCReco/Prof_ipt0_Cov2D_Cent_etaA_etaC_Ka"), cent, etaValA, etaValB, covReco); - if (std::isfinite(covRecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_ipt0_Cov2D_Cent_etaA_etaC_Ka"), cent, etaValA, etaValB, covRecoEffCor); - } else if (ipt == KNpT - 2) { - if (std::isfinite(c2SubTru)) { - histos.fill(HIST("MCGen/Prof_ipt1_C2Sub2D_Cent_etaA_etaC_Ka"), cent, etaValA, etaValB, c2SubTru); - histos.fill(HIST("MCGen/Prof_ipt1_GapSum2D_Ka"), cent, gap, sum, c2SubTru); - } - if (std::isfinite(c2SubReco)) { - histos.fill(HIST("MCReco/Prof_ipt1_C2Sub2D_Cent_etaA_etaC_Ka"), cent, etaValA, etaValB, c2SubReco); - histos.fill(HIST("MCReco/Prof_ipt1_GapSum2D_Ka"), cent, gap, sum, c2SubReco); - } - if (std::isfinite(c2SubRecoEffCor)) { - histos.fill(HIST("MCRecoEffCorr/Prof_ipt1_C2Sub2D_Cent_etaA_etaC_Ka"), cent, etaValA, etaValB, c2SubRecoEffCor); - histos.fill(HIST("MCRecoEffCorr/Prof_ipt1_GapSum2D_Ka"), cent, gap, sum, c2SubRecoEffCor); - } - if (std::isfinite(covTru)) - histos.fill(HIST("MCGen/Prof_ipt1_Cov2D_Cent_etaA_etaC_Ka"), cent, etaValA, etaValB, covTru); - if (std::isfinite(covReco)) - histos.fill(HIST("MCReco/Prof_ipt1_Cov2D_Cent_etaA_etaC_Ka"), cent, etaValA, etaValB, covReco); - if (std::isfinite(covRecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_ipt1_Cov2D_Cent_etaA_etaC_Ka"), cent, etaValA, etaValB, covRecoEffCor); - } else if (ipt == KNpT - 1) { - if (std::isfinite(c2SubTru)) { - histos.fill(HIST("MCGen/Prof_ipt2_C2Sub2D_Cent_etaA_etaC_Ka"), cent, etaValA, etaValB, c2SubTru); - histos.fill(HIST("MCGen/Prof_ipt2_GapSum2D_Ka"), cent, gap, sum, c2SubTru); - } - if (std::isfinite(c2SubReco)) { - histos.fill(HIST("MCReco/Prof_ipt2_C2Sub2D_Cent_etaA_etaC_Ka"), cent, etaValA, etaValB, c2SubReco); - histos.fill(HIST("MCReco/Prof_ipt2_GapSum2D_Ka"), cent, gap, sum, c2SubReco); - } - if (std::isfinite(c2SubRecoEffCor)) { - histos.fill(HIST("MCRecoEffCorr/Prof_ipt2_C2Sub2D_Cent_etaA_etaC_Ka"), cent, etaValA, etaValB, c2SubRecoEffCor); - histos.fill(HIST("MCRecoEffCorr/Prof_ipt2_GapSum2D_Ka"), cent, gap, sum, c2SubRecoEffCor); - } - if (std::isfinite(covTru)) - histos.fill(HIST("MCGen/Prof_ipt2_Cov2D_Cent_etaA_etaC_Ka"), cent, etaValA, etaValB, covTru); - if (std::isfinite(covReco)) - histos.fill(HIST("MCReco/Prof_ipt2_Cov2D_Cent_etaA_etaC_Ka"), cent, etaValA, etaValB, covReco); - if (std::isfinite(covRecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_ipt2_Cov2D_Cent_etaA_etaC_Ka"), cent, etaValA, etaValB, covRecoEffCor); - } - } else if (isp == numKProton) { // Proton - if (ipt == 0) { - if (std::isfinite(c2SubTru)) { - histos.fill(HIST("MCGen/Prof_ipt0_C2Sub2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, c2SubTru); - histos.fill(HIST("MCGen/Prof_ipt0_GapSum2D_Pr"), cent, gap, sum, c2SubTru); - } - if (std::isfinite(c2SubReco)) { - histos.fill(HIST("MCReco/Prof_ipt0_C2Sub2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, c2SubReco); - histos.fill(HIST("MCReco/Prof_ipt0_GapSum2D_Pr"), cent, gap, sum, c2SubReco); - } - if (std::isfinite(c2SubRecoEffCor)) { - histos.fill(HIST("MCRecoEffCorr/Prof_ipt0_C2Sub2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, c2SubRecoEffCor); - histos.fill(HIST("MCRecoEffCorr/Prof_ipt0_GapSum2D_Pr"), cent, gap, sum, c2SubRecoEffCor); - } - if (std::isfinite(covTru)) - histos.fill(HIST("MCGen/Prof_ipt0_Cov2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covTru); - if (std::isfinite(covReco)) - histos.fill(HIST("MCReco/Prof_ipt0_Cov2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covReco); - if (std::isfinite(covRecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_ipt0_Cov2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covRecoEffCor); - } else if (ipt == KNpT - 2) { - if (std::isfinite(c2SubTru)) { - histos.fill(HIST("MCGen/Prof_ipt1_C2Sub2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, c2SubTru); - histos.fill(HIST("MCGen/Prof_ipt1_GapSum2D_Pr"), cent, gap, sum, c2SubTru); - } - if (std::isfinite(c2SubReco)) { - histos.fill(HIST("MCReco/Prof_ipt1_C2Sub2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, c2SubReco); - histos.fill(HIST("MCReco/Prof_ipt1_GapSum2D_Pr"), cent, gap, sum, c2SubReco); - } - if (std::isfinite(c2SubRecoEffCor)) { - histos.fill(HIST("MCRecoEffCorr/Prof_ipt1_C2Sub2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, c2SubRecoEffCor); - histos.fill(HIST("MCRecoEffCorr/Prof_ipt1_GapSum2D_Pr"), cent, gap, sum, c2SubRecoEffCor); - } - if (std::isfinite(covTru)) - histos.fill(HIST("MCGen/Prof_ipt1_Cov2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covTru); - if (std::isfinite(covReco)) - histos.fill(HIST("MCReco/Prof_ipt1_Cov2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covReco); - if (std::isfinite(covRecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_ipt1_Cov2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covRecoEffCor); - } else if (ipt == KNpT - 1) { - if (std::isfinite(c2SubTru)) { - histos.fill(HIST("MCGen/Prof_ipt2_C2Sub2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, c2SubTru); - histos.fill(HIST("MCGen/Prof_ipt2_GapSum2D_Pr"), cent, gap, sum, c2SubTru); - } - if (std::isfinite(c2SubReco)) { - histos.fill(HIST("MCReco/Prof_ipt2_C2Sub2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, c2SubReco); - histos.fill(HIST("MCReco/Prof_ipt2_GapSum2D_Pr"), cent, gap, sum, c2SubReco); - } - if (std::isfinite(c2SubRecoEffCor)) { - histos.fill(HIST("MCRecoEffCorr/Prof_ipt2_C2Sub2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, c2SubRecoEffCor); - histos.fill(HIST("MCRecoEffCorr/Prof_ipt2_GapSum2D_Pr"), cent, gap, sum, c2SubRecoEffCor); - } - if (std::isfinite(covTru)) - histos.fill(HIST("MCGen/Prof_ipt2_Cov2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covTru); - if (std::isfinite(covReco)) - histos.fill(HIST("MCReco/Prof_ipt2_Cov2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covReco); - if (std::isfinite(covRecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_ipt2_Cov2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covRecoEffCor); - } + if (std::isfinite(c2SubReco)) { + histos.fill(HIST("MCReco/Prof_C2Sub2D_Cent_etaA_etaC_AllPr"), cent, etaValA, etaValB, c2SubReco); + histos.fill(HIST("MCReco/Prof_GapSum2D_AllPr"), cent, gap, sum, c2SubReco); } + if (std::isfinite(c2SubRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub2D_Cent_etaA_etaC_AllPr"), cent, etaValA, etaValB, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_GapSum2D_AllPr"), cent, gap, sum, c2SubRecoEffCor); + } + + if (std::isfinite(covTru)) + histos.fill(HIST("MCGen/Prof_Cov2D_Cent_etaA_etaC_AllPr"), cent, etaValA, etaValB, covTru); + if (std::isfinite(covReco)) + histos.fill(HIST("MCReco/Prof_Cov2D_Cent_etaA_etaC_AllPr"), cent, etaValA, etaValB, covReco); + if (std::isfinite(covRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_Cov2D_Cent_etaA_etaC_AllPr"), cent, etaValA, etaValB, covRecoEffCor); + + if (std::isfinite(covFT0ATru)) + histos.fill(HIST("MCGen/Prof_CovFT0A2D_Cent_etaA_etaC_AllPr"), cent, etaValA, etaValB, covFT0ATru); + if (std::isfinite(covFT0AReco)) + histos.fill(HIST("MCReco/Prof_CovFT0A2D_Cent_etaA_etaC_AllPr"), cent, etaValA, etaValB, covFT0AReco); + if (std::isfinite(covFT0ARecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A2D_Cent_etaA_etaC_AllPr"), cent, etaValA, etaValB, covFT0ARecoEffCor); + + if (std::isfinite(covFT0CTru)) + histos.fill(HIST("MCGen/Prof_CovFT0C2D_Cent_etaA_etaC_AllPr"), cent, etaValA, etaValB, covFT0CTru); + if (std::isfinite(covFT0CReco)) + histos.fill(HIST("MCReco/Prof_CovFT0C2D_Cent_etaA_etaC_AllPr"), cent, etaValA, etaValB, covFT0CReco); + if (std::isfinite(covFT0CRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC_AllPr"), cent, etaValA, etaValB, covFT0CRecoEffCor); } } } @@ -2605,52 +2519,80 @@ struct RadialFlowDecorr { for (const auto& track : tracks) { if (!isTrackSelected(track)) continue; - - float p = track.p(); float pt = track.pt(); + if (pt <= KPtMin || pt > KPtMax) + continue; float eta = track.eta(); float phi = track.phi(); auto sign = track.sign(); - - if (p < KFloatEpsilon) - continue; - - // Count tracks in the primary eta acceptance if (eta > etaLw[0] && eta < etaUp[0]) ntrk++; - - // Define species array (0: Inclusive, 1: Pion, 2: Kaon, 3: Proton) - bool isSpecies[KNsp] = {true, selectionPion(track), selectionKaon(track), selectionProton(track)}; + bool isPi = selectionPion(track); + bool isKa = selectionKaon(track); + bool isPr = selectionProton(track); + + bool isSpecies[KNsp] = { + true, // kInclusive + isPi && sign < 0, // kPiMinus + isPi && sign > 0, // kPiPlus + isPi, // kPiAll + isKa && sign < 0, // kKaMinus + isKa && sign > 0, // kKaPlus + isKa, // kKaAll + isPr && sign < 0, // kAntiProton (Negative) + isPr && sign > 0, // kProton (Positive) + isPr // kAllProton + }; for (int isp = 0; isp < KNsp; ++isp) { if (!isSpecies[isp]) continue; - - // Fetch efficiency specifically for this particle species float eff = getEfficiency(coll.multNTracksPV(), pt, eta, static_cast(isp), 0, cfgEff); float fake = getEfficiency(coll.multNTracksPV(), pt, eta, static_cast(isp), 1, cfgEff); float w = (1.0 - fake) / eff; if (!std::isfinite(w) || w <= KFloatEpsilon || eff <= KFloatEpsilon) continue; - - // Unrolled THnSparse / QA Fills - if (isp == numKInclusive) { + if (isp == kInclusive) { histos.fill(HIST("hEtaPhiReco"), vz, sign, pt, eta, phi); histos.fill(HIST("hEtaPhiRecoEffWtd"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); histos.fill(HIST("hEtaPhiRecoWtd"), vz, sign, pt, eta, phi, w); - } else if (isp == numKPion) { // Pion - histos.fill(HIST("hEtaPhiReco_Pi"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoEffWtd_Pi"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - histos.fill(HIST("hEtaPhiRecoWtd_Pi"), vz, sign, pt, eta, phi, w); - } else if (isp == numKKaon) { // Kaon - histos.fill(HIST("hEtaPhiReco_Ka"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoEffWtd_Ka"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - histos.fill(HIST("hEtaPhiRecoWtd_Ka"), vz, sign, pt, eta, phi, w); - } else if (isp == numKProton) { // Proton + } else if (isp == kPiMinus) { + histos.fill(HIST("hEtaPhiReco_PiMinus"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd_PiMinus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd_PiMinus"), vz, sign, pt, eta, phi, w); + } else if (isp == kPiPlus) { + histos.fill(HIST("hEtaPhiReco_PiPlus"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd_PiPlus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd_PiPlus"), vz, sign, pt, eta, phi, w); + } else if (isp == kPiAll) { + histos.fill(HIST("hEtaPhiReco_PiAll"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd_PiAll"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd_PiAll"), vz, sign, pt, eta, phi, w); + } else if (isp == kKaMinus) { + histos.fill(HIST("hEtaPhiReco_KaMinus"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd_KaMinus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd_KaMinus"), vz, sign, pt, eta, phi, w); + } else if (isp == kKaPlus) { + histos.fill(HIST("hEtaPhiReco_KaPlus"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd_KaPlus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd_KaPlus"), vz, sign, pt, eta, phi, w); + } else if (isp == kKaAll) { + histos.fill(HIST("hEtaPhiReco_KaAll"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd_KaAll"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd_KaAll"), vz, sign, pt, eta, phi, w); + } else if (isp == kProton) { histos.fill(HIST("hEtaPhiReco_Pr"), vz, sign, pt, eta, phi); histos.fill(HIST("hEtaPhiRecoEffWtd_Pr"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); histos.fill(HIST("hEtaPhiRecoWtd_Pr"), vz, sign, pt, eta, phi, w); + } else if (isp == kAntiProton) { + histos.fill(HIST("hEtaPhiReco_AntiPr"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd_AntiPr"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd_AntiPr"), vz, sign, pt, eta, phi, w); + } else if (isp == kAllProton) { + histos.fill(HIST("hEtaPhiReco_AllPr"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd_AllPr"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd_AllPr"), vz, sign, pt, eta, phi, w); } } } @@ -2671,10 +2613,9 @@ struct RadialFlowDecorr { } PROCESS_SWITCH(RadialFlowDecorr, processGetDataFlat, "process data to calculate Flattening maps", cfgRunGetDataFlat); - void processDataMean(AodCollisionsSel::iterator const& coll, BCsRun3 const& /*bcs*/, aod::Zdcs const& /*zdcsData*/, AodTracksSel const& tracks) + void processDataMean(AodCollisionsSel::iterator const& coll, BCsRun3 const& /*bcs*/, aod::Zdcs const& /*zdcsData*/, aod::FT0s const&, AodTracksSel const& tracks) { - // Expanded to 4 species (isp = 0: Incl, 1: Pi, 2: Ka, 3: Pr) - double sumWi[KNsp][KNEta][KNpT]{}, sumWipti[KNsp][KNEta][KNpT]{}; + double sumWi[KNsp][KNEta]{}, sumWipti[KNsp][KNEta]{}; if (!isEventSelected(coll)) return; @@ -2695,22 +2636,39 @@ struct RadialFlowDecorr { if (!isTrackSelected(track)) continue; + float p = track.p(); float pt = track.pt(); float eta = track.eta(); - float p = track.p(); float phi = track.phi(); auto sign = track.sign(); if (p < KFloatEpsilon) continue; + if (pt <= KPtMin || pt > KPtMax) + continue; + histos.fill(HIST("hP"), p); histos.fill(HIST("hPt"), pt); histos.fill(HIST("hEta"), eta); histos.fill(HIST("hPhi"), phi); - // Define species array - bool isSpecies[KNsp] = {true, selectionPion(track), selectionKaon(track), selectionProton(track)}; + bool isPi = selectionPion(track); + bool isKa = selectionKaon(track); + bool isPr = selectionProton(track); + + bool isSpecies[KNsp] = { + true, // kInclusive + isPi && sign < 0, // kPiMinus + isPi && sign > 0, // kPiPlus + isPi, // kPiAll + isKa && sign < 0, // kKaMinus + isKa && sign > 0, // kKaPlus + isKa, // kKaAll + isPr && sign < 0, // kAntiProton (Negative) + isPr && sign > 0, // kProton (Positive) + isPr // kAllProton + }; for (int isp = 0; isp < KNsp; ++isp) { if (!isSpecies[isp]) @@ -2724,143 +2682,133 @@ struct RadialFlowDecorr { if (!std::isfinite(w) || w <= KFloatEpsilon || eff <= KFloatEpsilon) continue; - // Unrolled THnSparse / QA Fills - if (isp == numKInclusive) { + if (isp == kInclusive) { histos.fill(HIST("hEtaPhiReco"), vz, sign, pt, eta, phi); histos.fill(HIST("hEtaPhiRecoEffWtd"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); histos.fill(HIST("hEtaPhiRecoWtd"), vz, sign, pt, eta, phi, w); - } else if (isp == numKPion) { // Pion - histos.fill(HIST("hEtaPhiReco_Pi"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoEffWtd_Pi"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - histos.fill(HIST("hEtaPhiRecoWtd_Pi"), vz, sign, pt, eta, phi, w); - } else if (isp == numKKaon) { // Kaon - histos.fill(HIST("hEtaPhiReco_Ka"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoEffWtd_Ka"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - histos.fill(HIST("hEtaPhiRecoWtd_Ka"), vz, sign, pt, eta, phi, w); - } else if (isp == numKProton) { // Proton + } else if (isp == kPiMinus) { + histos.fill(HIST("hEtaPhiReco_PiMinus"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd_PiMinus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd_PiMinus"), vz, sign, pt, eta, phi, w); + } else if (isp == kPiPlus) { + histos.fill(HIST("hEtaPhiReco_PiPlus"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd_PiPlus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd_PiPlus"), vz, sign, pt, eta, phi, w); + } else if (isp == kPiAll) { + histos.fill(HIST("hEtaPhiReco_PiAll"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd_PiAll"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd_PiAll"), vz, sign, pt, eta, phi, w); + } else if (isp == kKaMinus) { + histos.fill(HIST("hEtaPhiReco_KaMinus"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd_KaMinus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd_KaMinus"), vz, sign, pt, eta, phi, w); + } else if (isp == kKaPlus) { + histos.fill(HIST("hEtaPhiReco_KaPlus"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd_KaPlus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd_KaPlus"), vz, sign, pt, eta, phi, w); + } else if (isp == kKaAll) { + histos.fill(HIST("hEtaPhiReco_KaAll"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd_KaAll"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd_KaAll"), vz, sign, pt, eta, phi, w); + } else if (isp == kProton) { histos.fill(HIST("hEtaPhiReco_Pr"), vz, sign, pt, eta, phi); histos.fill(HIST("hEtaPhiRecoEffWtd_Pr"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); histos.fill(HIST("hEtaPhiRecoWtd_Pr"), vz, sign, pt, eta, phi, w); + } else if (isp == kAntiProton) { + histos.fill(HIST("hEtaPhiReco_AntiPr"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd_AntiPr"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd_AntiPr"), vz, sign, pt, eta, phi, w); + } else if (isp == kAllProton) { + histos.fill(HIST("hEtaPhiReco_AllPr"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd_AllPr"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd_AllPr"), vz, sign, pt, eta, phi, w); } - // Accumulate sum for (int ieta = 0; ieta < KNEta; ++ieta) { if (eta <= etaLw[ieta] || eta > etaUp[ieta]) continue; - for (int ipt = 0; ipt < KNpT; ++ipt) { - if (pt <= pTLw[ipt] || pt > pTUp[ipt]) - continue; - sumWi[isp][ieta][ipt] += w; - sumWipti[isp][ieta][ipt] += w * pt; - } + sumWi[isp][ieta] += w; + sumWipti[isp][ieta] += w * pt; } } } - // Full Event Means for (int isp = 0; isp < KNsp; ++isp) { - if (isp == numKInclusive) { - histos.fill(HIST("Prof_Cent_Nchrec"), cent, sumWi[0][0][0]); - histos.fill(HIST("Prof_Mult_Nchrec"), coll.multNTracksPV(), sumWi[0][0][0]); - if (sumWi[0][0][0] > 1.0f) - histos.fill(HIST("Prof_Cent_MeanpT"), cent, sumWipti[0][0][0] / sumWi[0][0][0]); - } else if (isp == numKPion) { - histos.fill(HIST("Prof_Cent_Nchrec_Pi"), cent, sumWi[1][0][0]); - histos.fill(HIST("Prof_Mult_Nchrec_Pi"), coll.multNTracksPV(), sumWi[1][0][0]); - - if (sumWi[1][0][0] > 1.0f) - histos.fill(HIST("Prof_Cent_MeanpT_Pi"), cent, sumWipti[1][0][0] / sumWi[1][0][0]); - } else if (isp == numKKaon) { - histos.fill(HIST("Prof_Cent_Nchrec_Ka"), cent, sumWi[2][0][0]); - histos.fill(HIST("Prof_Mult_Nchrec_Ka"), coll.multNTracksPV(), sumWi[2][0][0]); - - if (sumWi[2][0][0] > 1.0f) - histos.fill(HIST("Prof_Cent_MeanpT_Ka"), cent, sumWipti[2][0][0] / sumWi[2][0][0]); - } else if (isp == numKProton) { - histos.fill(HIST("Prof_Cent_Nchrec_Pr"), cent, sumWi[3][0][0]); - histos.fill(HIST("Prof_Mult_Nchrec_Pr"), coll.multNTracksPV(), sumWi[3][0][0]); - - if (sumWi[3][0][0] > 1.0f) - histos.fill(HIST("Prof_Cent_MeanpT_Pr"), cent, sumWipti[3][0][0] / sumWi[3][0][0]); - } + histos.fill(HIST("Prof_Cent_Nsp_Nchrec"), cent, isp, sumWi[isp][0]); + histos.fill(HIST("Prof_Mult_Nsp_Nchrec"), coll.multNTracksPV(), isp, sumWi[isp][0]); + if (sumWi[isp][0] > 1.0f) + histos.fill(HIST("Prof_Cent_Nsp_MeanpT"), cent, isp, sumWipti[isp][0] / sumWi[isp][0]); } - - // Kinematic Bin Means (1D and 2D Sub-event) for (int ietaA = 0; ietaA < KNEta; ++ietaA) { - for (int ietaB = 0; ietaB < KNEta; ++ietaB) { - for (int ipt = 0; ipt < KNpT; ++ipt) { - for (int isp = 0; isp < KNsp; ++isp) { - - // --- 2D Sub-Event Calculations --- - double wCorrAB = sumWi[isp][ietaA][ipt] + sumWi[isp][ietaB][ipt]; - if (wCorrAB > 0) { - float mptsub = (sumWipti[isp][ietaA][ipt] + sumWipti[isp][ietaB][ipt]) / wCorrAB; - if (isp == numKInclusive) { - if (ipt == 0) - histos.fill(HIST("Prof2D_MeanpT_Sub_ipt0"), cent, ietaA, ietaB, mptsub); - if (ipt == KNpT - 2) - histos.fill(HIST("Prof2D_MeanpT_Sub_ipt1"), cent, ietaA, ietaB, mptsub); - if (ipt == KNpT - 1) - histos.fill(HIST("Prof2D_MeanpT_Sub_ipt2"), cent, ietaA, ietaB, mptsub); - } else if (isp == numKPion) { - if (ipt == 0) - histos.fill(HIST("Prof2D_MeanpT_Sub_ipt0_Pi"), cent, ietaA, ietaB, mptsub); - if (ipt == KNpT - 2) - histos.fill(HIST("Prof2D_MeanpT_Sub_ipt1_Pi"), cent, ietaA, ietaB, mptsub); - if (ipt == KNpT - 1) - histos.fill(HIST("Prof2D_MeanpT_Sub_ipt2_Pi"), cent, ietaA, ietaB, mptsub); - } else if (isp == numKKaon) { - if (ipt == 0) - histos.fill(HIST("Prof2D_MeanpT_Sub_ipt0_Ka"), cent, ietaA, ietaB, mptsub); - if (ipt == KNpT - 2) - histos.fill(HIST("Prof2D_MeanpT_Sub_ipt1_Ka"), cent, ietaA, ietaB, mptsub); - if (ipt == KNpT - 1) - histos.fill(HIST("Prof2D_MeanpT_Sub_ipt2_Ka"), cent, ietaA, ietaB, mptsub); - } else if (isp == numKProton) { - if (ipt == 0) - histos.fill(HIST("Prof2D_MeanpT_Sub_ipt0_Pr"), cent, ietaA, ietaB, mptsub); - if (ipt == KNpT - 2) - histos.fill(HIST("Prof2D_MeanpT_Sub_ipt1_Pr"), cent, ietaA, ietaB, mptsub); - if (ipt == KNpT - 1) - histos.fill(HIST("Prof2D_MeanpT_Sub_ipt2_Pr"), cent, ietaA, ietaB, mptsub); - } - } - - // --- 1D Individual Bin Calculations (Only do when A == B to avoid overfilling) --- - if (ietaA == ietaB) { - double mpt = sumWipti[isp][ietaA][ipt] / sumWi[isp][ietaA][ipt]; - if (sumWi[isp][ietaA][ipt] >= 1.0f && std::isfinite(mpt)) { - if (isp == numKInclusive) { - histos.fill(HIST("pmean_nch_etabin_ptbin"), coll.multNTracksPV(), ietaA, ipt, mpt); - histos.fill(HIST("pmeanMult_nch_etabin_ptbin"), coll.multNTracksPV(), ietaA, ipt, sumWi[0][ietaA][ipt]); - histos.fill(HIST("pmean_cent_etabin_ptbin"), cent, ietaA, ipt, mpt); - histos.fill(HIST("pmeanMult_cent_etabin_ptbin"), cent, ietaA, ipt, sumWi[0][ietaA][ipt]); - } else if (isp == numKPion) { - histos.fill(HIST("pmean_nch_etabin_ptbin_Pi"), coll.multNTracksPV(), ietaA, ipt, mpt); - histos.fill(HIST("pmeanMult_nch_etabin_ptbin_Pi"), coll.multNTracksPV(), ietaA, ipt, sumWi[1][ietaA][ipt]); - histos.fill(HIST("pmean_cent_etabin_ptbin_Pi"), cent, ietaA, ipt, mpt); - histos.fill(HIST("pmeanMult_cent_etabin_ptbin_Pi"), cent, ietaA, ipt, sumWi[1][ietaA][ipt]); - } else if (isp == numKKaon) { - histos.fill(HIST("pmean_nch_etabin_ptbin_Ka"), coll.multNTracksPV(), ietaA, ipt, mpt); - histos.fill(HIST("pmeanMult_nch_etabin_ptbin_Ka"), coll.multNTracksPV(), ietaA, ipt, sumWi[2][ietaA][ipt]); - histos.fill(HIST("pmean_cent_etabin_ptbin_Ka"), cent, ietaA, ipt, mpt); - histos.fill(HIST("pmeanMult_cent_etabin_ptbin_Ka"), cent, ietaA, ipt, sumWi[2][ietaA][ipt]); - } else if (isp == numKProton) { - histos.fill(HIST("pmean_nch_etabin_ptbin_Pr"), coll.multNTracksPV(), ietaA, ipt, mpt); - histos.fill(HIST("pmeanMult_nch_etabin_ptbin_Pr"), coll.multNTracksPV(), ietaA, ipt, sumWi[3][ietaA][ipt]); - histos.fill(HIST("pmean_cent_etabin_ptbin_Pr"), cent, ietaA, ipt, mpt); - histos.fill(HIST("pmeanMult_cent_etabin_ptbin_Pr"), cent, ietaA, ipt, sumWi[3][ietaA][ipt]); - } - } + for (int ietaC = 0; ietaC < KNEta; ++ietaC) { + for (int isp = 0; isp < KNsp; ++isp) { + double wCorrAB = sumWi[isp][ietaA] + sumWi[isp][ietaC]; + if (wCorrAB > 0) { + float mptsub = (sumWipti[isp][ietaA] + sumWipti[isp][ietaC]) / wCorrAB; + if (isp == kInclusive) + histos.fill(HIST("Prof2D_MeanpTSub"), cent, ietaA, ietaC, mptsub); + else if (isp == kPiMinus) + histos.fill(HIST("Prof2D_MeanpTSub_PiMinus"), cent, ietaA, ietaC, mptsub); + else if (isp == kPiPlus) + histos.fill(HIST("Prof2D_MeanpTSub_PiPlus"), cent, ietaA, ietaC, mptsub); + else if (isp == kPiAll) + histos.fill(HIST("Prof2D_MeanpTSub_PiAll"), cent, ietaA, ietaC, mptsub); + else if (isp == kKaMinus) + histos.fill(HIST("Prof2D_MeanpTSub_KaMinus"), cent, ietaA, ietaC, mptsub); + else if (isp == kKaPlus) + histos.fill(HIST("Prof2D_MeanpTSub_KaPlus"), cent, ietaA, ietaC, mptsub); + else if (isp == kKaAll) + histos.fill(HIST("Prof2D_MeanpTSub_KaAll"), cent, ietaA, ietaC, mptsub); + else if (isp == kProton) + histos.fill(HIST("Prof2D_MeanpTSub_Pr"), cent, ietaA, ietaC, mptsub); + else if (isp == kAntiProton) + histos.fill(HIST("Prof2D_MeanpTSub_AntiPr"), cent, ietaA, ietaC, mptsub); + else if (isp == kAllProton) + histos.fill(HIST("Prof2D_MeanpTSub_AllPr"), cent, ietaA, ietaC, mptsub); + } + if (ietaA == ietaC) { + double mpt = sumWipti[isp][ietaA] / sumWi[isp][ietaA]; + if (sumWi[isp][ietaA] >= 1.0f && std::isfinite(mpt)) { + histos.fill(HIST("pmean_nch_etabin_spbin"), coll.multNTracksPV(), ietaA, isp, mpt); + histos.fill(HIST("pmeanMult_nch_etabin_spbin"), coll.multNTracksPV(), ietaA, isp, sumWi[isp][ietaA]); + histos.fill(HIST("pmean_cent_etabin_spbin"), cent, ietaA, isp, mpt); + histos.fill(HIST("pmeanMult_cent_etabin_spbin"), cent, ietaA, isp, sumWi[isp][ietaA]); } } } } } + + double amplFT0A = 0, amplFT0C = 0; + if (coll.has_foundFT0()) { + const auto& ft0 = coll.foundFT0(); + for (std::size_t iCh = 0; iCh < ft0.channelA().size(); iCh++) { + auto chanelid = ft0.channelA()[iCh]; + float ampl = ft0.amplitudeA()[iCh]; + amplFT0A += ampl; + auto eta = getEtaFT0(chanelid, 0); + histos.fill(HIST("pmean_cent_id_eta_FT0"), cent, iCh, eta, ampl); + histos.fill(HIST("h3_cent_id_eta_FT0"), cent, iCh, eta, ampl); + } + for (std::size_t iCh = 0; iCh < ft0.channelC().size(); iCh++) { + auto chanelid = ft0.channelC()[iCh]; + auto globalId = chanelid + KnFt0cCell; + float ampl = ft0.amplitudeC()[iCh]; + auto eta = getEtaFT0(globalId, 1); + amplFT0C += ampl; + histos.fill(HIST("pmean_cent_id_eta_FT0"), cent, iCh, eta, ampl); + histos.fill(HIST("h3_cent_id_eta_FT0"), cent, iCh, eta, ampl); + } + } + + histos.fill(HIST("pmeanFT0Amultpv"), coll.multNTracksPV(), amplFT0A); + histos.fill(HIST("pmeanFT0A_cent"), cent, amplFT0A); + histos.fill(HIST("pmeanFT0Cmultpv"), coll.multNTracksPV(), amplFT0C); + histos.fill(HIST("pmeanFT0C_cent"), cent, amplFT0C); } PROCESS_SWITCH(RadialFlowDecorr, processDataMean, "process data to calculate mean pT", cfgRunDataMean); - void processDataFluc(AodCollisionsSel::iterator const& coll, BCsRun3 const& /*bcs*/, aod::Zdcs const& /*zdcsData*/, AodTracksSel const& tracks) + void processDataFluc(AodCollisionsSel::iterator const& coll, BCsRun3 const& /*bcs*/, aod::Zdcs const& /*zdcsData*/, aod::FT0s const&, AodTracksSel const& tracks) { if (!isEventSelected(coll)) return; @@ -2868,15 +2816,11 @@ struct RadialFlowDecorr { if (cent > KCentMax) return; - // 1. Safety Check: Step 2 Mean Maps - for (int isp = 0; isp < KNsp; ++isp) { - if (!pmeanNchEtabinPtbinStep2[isp] || !pmeanMultNchEtabinPtbinStep2[isp]) { - LOGF(warning, "Data fluc: Mean pT or Mult map missing for species index %d", isp); - return; - } + if (!pmeanNchEtabinSpbinStep2 || !pmeanMultNchEtabinSpbinStep2) { + LOGF(warning, "Data fluc: Mean pT or Mult map missing"); + return; } - // 2. Safety Check: Correction Maps (Looping over Inclusive, Pi, Ka, Pr) for (int isp = 0; isp < KNsp; ++isp) { auto pid = static_cast(isp); if (!hEff[pid] || !hFake[pid] || !hFlatWeight[pid]) { @@ -2885,31 +2829,47 @@ struct RadialFlowDecorr { } } - // Expanded arrays to handle KNsp species (0: Incl, 1: Pi, 2: Ka, 3: Pr) - double sumpmwk[KNsp][KNEta][KNpT][KIntM][KIntK]{}; - double sumwk[KNsp][KNEta][KNpT][KIntK]{}; + double sumpmwk[KNsp][KNEta][KIntM][KIntK]{}; + double sumwk[KNsp][KNEta][KIntK]{}; - double mean[KNsp][KNEta][KNpT]{}, c2[KNsp][KNEta][KNpT]{}; - double p1kBar[KNsp][KNEta][KNpT]{}; - double meanMult[KNsp][KNEta][KNpT]{}, p1kBarMult[KNsp][KNEta][KNpT]{}; + double mean[KNsp][KNEta]{}, c2[KNsp][KNEta]{}; + double p1kBar[KNsp][KNEta]{}; + double meanMult[KNsp][KNEta]{}, p1kBarMult[KNsp][KNEta]{}; float vz = coll.posZ(); - // --- 1. Track Loop: Accumulate sum --- for (const auto& track : tracks) { if (!isTrackSelected(track)) continue; + float p = track.p(); float pt = track.pt(); float eta = track.eta(); - float p = track.p(); float phi = track.phi(); auto sign = track.sign(); if (p < KFloatEpsilon) continue; - bool isSpecies[KNsp] = {true, selectionPion(track), selectionKaon(track), selectionProton(track)}; + if (pt <= KPtMin || pt > KPtMax) + continue; + + bool isPi = selectionPion(track); + bool isKa = selectionKaon(track); + bool isPr = selectionProton(track); + + bool isSpecies[KNsp] = { + true, // kInclusive + isPi && sign < 0, // kPiMinus + isPi && sign > 0, // kPiPlus + isPi, // kPiAll + isKa && sign < 0, // kKaMinus + isKa && sign > 0, // kKaPlus + isKa, // kKaAll + isPr && sign < 0, // kAntiProton (Negative) + isPr && sign > 0, // kProton (Positive) + isPr // kAllProton + }; for (int isp = 0; isp < KNsp; ++isp) { if (!isSpecies[isp]) @@ -2922,296 +2882,230 @@ struct RadialFlowDecorr { if (!std::isfinite(w) || w <= KFloatEpsilon || eff <= KFloatEpsilon) continue; - - // QA Fills - if (isp == numKInclusive) { - histos.fill(HIST("hEtaPhiReco"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoEffWtd"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - histos.fill(HIST("hEtaPhiRecoWtd"), vz, sign, pt, eta, phi, w); - } else if (isp == numKPion) { // Pion - histos.fill(HIST("hEtaPhiReco_Pi"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoEffWtd_Pi"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - histos.fill(HIST("hEtaPhiRecoWtd_Pi"), vz, sign, pt, eta, phi, w); - } else if (isp == numKKaon) { // Kaon - histos.fill(HIST("hEtaPhiReco_Ka"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoEffWtd_Ka"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - histos.fill(HIST("hEtaPhiRecoWtd_Ka"), vz, sign, pt, eta, phi, w); - } else if (isp == numKProton) { // Proton - histos.fill(HIST("hEtaPhiReco_Pr"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoEffWtd_Pr"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - histos.fill(HIST("hEtaPhiRecoWtd_Pr"), vz, sign, pt, eta, phi, w); - } - - // Kinematic Bin sum for (int ieta = 0; ieta < KNEta; ++ieta) { if (eta <= etaLw[ieta] || eta > etaUp[ieta]) continue; - for (int ipt = 0; ipt < KNpT; ++ipt) { - if (pt <= pTLw[ipt] || pt > pTUp[ipt]) - continue; - for (int k = 0; k < KIntK; ++k) { - for (int m = 0; m < KIntM; ++m) { - sumpmwk[isp][ieta][ipt][m][k] += std::pow(w, k) * std::pow(pt, m); - } - sumwk[isp][ieta][ipt][k] += std::pow(w, k); + for (int k = 0; k < KIntK; ++k) { + for (int m = 0; m < KIntM; ++m) { + sumpmwk[isp][ieta][m][k] += std::pow(w, k) * std::pow(pt, m); } + sumwk[isp][ieta][k] += std::pow(w, k); } } } } - // --- 2. Step 2 Means and 1D Fluc Variables --- + double amplFT0A = 0, amplFT0C = 0; + if (coll.has_foundFT0()) { + const auto& ft0 = coll.foundFT0(); + for (std::size_t iCh = 0; iCh < ft0.channelA().size(); iCh++) { + float ampl = ft0.amplitudeA()[iCh]; + amplFT0A += ampl; + } + for (std::size_t iCh = 0; iCh < ft0.channelC().size(); iCh++) { + float ampl = ft0.amplitudeC()[iCh]; + amplFT0C += ampl; + } + } + double p1kBarFt0A = amplFT0A - pmeanFT0AmultpvStep2->GetBinContent(pmeanFT0AmultpvStep2->GetXaxis()->FindBin(coll.multNTracksPV())); + double p1kBarFt0C = amplFT0C - pmeanFT0CmultpvStep2->GetBinContent(pmeanFT0CmultpvStep2->GetXaxis()->FindBin(coll.multNTracksPV())); + for (int ieta = 0; ieta < KNEta; ++ieta) { - for (int ipt = 0; ipt < KNpT; ++ipt) { + const int ibx = pmeanNchEtabinSpbinStep2->GetXaxis()->FindBin(coll.multNTracksPV()); + const int iby = ieta + 1; - // Use [0] to safely grab the X-axis from the array! - const int ibx = pmeanNchEtabinPtbinStep2[0]->GetXaxis()->FindBin(coll.multNTracksPV()); - const int iby = ieta + 1; - const int ibz = ipt + 1; + for (int isp = 0; isp < KNsp; ++isp) { + const int ibz = isp + 1; - for (int isp = 0; isp < KNsp; ++isp) { - // Dynamically fetch from the array - float mmpt = pmeanNchEtabinPtbinStep2[isp]->GetBinContent(ibx, iby, ibz); - float mmMult = pmeanMultNchEtabinPtbinStep2[isp]->GetBinContent(ibx, iby, ibz); + float mmpt = pmeanNchEtabinSpbinStep2->GetBinContent(ibx, iby, ibz); + float mmMult = pmeanMultNchEtabinSpbinStep2->GetBinContent(ibx, iby, ibz); - mean[isp][ieta][ipt] = sumpmwk[isp][ieta][ipt][1][1] / sumwk[isp][ieta][ipt][1]; - meanMult[isp][ieta][ipt] = sumwk[isp][ieta][ipt][1]; + mean[isp][ieta] = sumpmwk[isp][ieta][1][1] / sumwk[isp][ieta][1]; + meanMult[isp][ieta] = sumwk[isp][ieta][1]; - if (std::isfinite(mmpt)) { - std::tie(mean[isp][ieta][ipt], c2[isp][ieta][ipt]) = calculateMeanAndC2FromSums(sumpmwk[isp][ieta][ipt], sumwk[isp][ieta][ipt], mmpt); - p1kBar[isp][ieta][ipt] = mean[isp][ieta][ipt] - mmpt; - } - p1kBarMult[isp][ieta][ipt] = meanMult[isp][ieta][ipt] - mmMult; + if (std::isfinite(mmpt)) { + std::tie(mean[isp][ieta], c2[isp][ieta]) = calculateMeanAndC2FromSums(sumpmwk[isp][ieta], sumwk[isp][ieta], mmpt); + p1kBar[isp][ieta] = mean[isp][ieta] - mmpt; } + p1kBarMult[isp][ieta] = meanMult[isp][ieta] - mmMult; } } - - // --- 3. Fill 1D Profiles --- for (int ieta = 0; ieta < KNEta; ++ieta) { - for (int ipt = 0; ipt < KNpT; ++ipt) { - for (int isp = 0; isp < KNsp; ++isp) { - if (isp == numKInclusive) { - if (std::isfinite(mean[0][ieta][ipt])) { - histos.fill(HIST("Prof_MeanpT_Cent_etabin_ptbin"), cent, ieta, ipt, mean[0][ieta][ipt]); - histos.fill(HIST("Prof_MeanpT_Mult_etabin_ptbin"), coll.multNTracksPV(), ieta, ipt, mean[0][ieta][ipt]); - } - if (std::isfinite(c2[0][ieta][ipt])) { - histos.fill(HIST("Prof_C2_Cent_etabin_ptbin"), cent, ieta, ipt, c2[0][ieta][ipt]); - histos.fill(HIST("Prof_C2_Mult_etabin_ptbin"), coll.multNTracksPV(), ieta, ipt, c2[0][ieta][ipt]); - } - } else if (isp == numKPion) { // Pi - if (std::isfinite(mean[1][ieta][ipt])) { - histos.fill(HIST("Prof_MeanpT_Cent_etabin_ptbin_Pi"), cent, ieta, ipt, mean[1][ieta][ipt]); - histos.fill(HIST("Prof_MeanpT_Mult_etabin_ptbin_Pi"), coll.multNTracksPV(), ieta, ipt, mean[1][ieta][ipt]); - } - if (std::isfinite(c2[1][ieta][ipt])) { - histos.fill(HIST("Prof_C2_Cent_etabin_ptbin_Pi"), cent, ieta, ipt, c2[1][ieta][ipt]); - histos.fill(HIST("Prof_C2_Mult_etabin_ptbin_Pi"), coll.multNTracksPV(), ieta, ipt, c2[1][ieta][ipt]); - } - } else if (isp == numKKaon) { // Ka - if (std::isfinite(mean[2][ieta][ipt])) { - histos.fill(HIST("Prof_MeanpT_Cent_etabin_ptbin_Ka"), cent, ieta, ipt, mean[2][ieta][ipt]); - histos.fill(HIST("Prof_MeanpT_Mult_etabin_ptbin_Ka"), coll.multNTracksPV(), ieta, ipt, mean[2][ieta][ipt]); - } - if (std::isfinite(c2[2][ieta][ipt])) { - histos.fill(HIST("Prof_C2_Cent_etabin_ptbin_Ka"), cent, ieta, ipt, c2[2][ieta][ipt]); - histos.fill(HIST("Prof_C2_Mult_etabin_ptbin_Ka"), coll.multNTracksPV(), ieta, ipt, c2[2][ieta][ipt]); - } - } else if (isp == numKProton) { // Pr - if (std::isfinite(mean[3][ieta][ipt])) { - histos.fill(HIST("Prof_MeanpT_Cent_etabin_ptbin_Pr"), cent, ieta, ipt, mean[3][ieta][ipt]); - histos.fill(HIST("Prof_MeanpT_Mult_etabin_ptbin_Pr"), coll.multNTracksPV(), ieta, ipt, mean[3][ieta][ipt]); - } - if (std::isfinite(c2[3][ieta][ipt])) { - histos.fill(HIST("Prof_C2_Cent_etabin_ptbin_Pr"), cent, ieta, ipt, c2[3][ieta][ipt]); - histos.fill(HIST("Prof_C2_Mult_etabin_ptbin_Pr"), coll.multNTracksPV(), ieta, ipt, c2[3][ieta][ipt]); - } - } + for (int isp = 0; isp < KNsp; ++isp) { + if (std::isfinite(mean[isp][ieta])) { + histos.fill(HIST("Prof_MeanpT_Cent_etabin_spbin"), cent, ieta, isp, mean[isp][ieta]); + histos.fill(HIST("Prof_MeanpT_Mult_etabin_spbin"), coll.multNTracksPV(), ieta, isp, mean[isp][ieta]); + } + if (std::isfinite(c2[isp][ieta])) { + histos.fill(HIST("Prof_C2_Cent_etabin_spbin"), cent, ieta, isp, c2[isp][ieta]); + histos.fill(HIST("Prof_C2_Mult_etabin_spbin"), coll.multNTracksPV(), ieta, isp, c2[isp][ieta]); } } } for (int ietaA = 1; ietaA <= (KNEta - 1) / 2; ++ietaA) { int ietaC = KNEta - ietaA; - for (int ipt = 0; ipt < KNpT; ++ipt) { - for (int isp = 0; isp < KNsp; ++isp) { - float c2Sub = p1kBar[isp][ietaA][ipt] * p1kBar[isp][ietaC][ipt]; - float covAC = p1kBarMult[isp][ietaA][ipt] * p1kBar[isp][ietaC][ipt]; - float covCA = p1kBar[isp][ietaA][ipt] * p1kBarMult[isp][ietaC][ipt]; + for (int isp = 0; isp < KNsp; ++isp) { + float c2Sub = p1kBar[isp][ietaA] * p1kBar[isp][ietaC]; + float covAC = p1kBarMult[isp][ietaA] * p1kBar[isp][ietaC]; + float covCA = p1kBar[isp][ietaA] * p1kBarMult[isp][ietaC]; - if (isp == numKInclusive) { - if (std::isfinite(c2Sub)) { - histos.fill(HIST("Prof_C2Sub_Cent_etabin_ptbin"), cent, ietaA, ipt, c2Sub); - histos.fill(HIST("Prof_C2Sub_Mult_etabin_ptbin"), coll.multNTracksPV(), ietaA, ipt, c2Sub); - } - if (std::isfinite(covAC)) { - histos.fill(HIST("Prof_Cov_Cent_etabin_ptbin"), cent, ietaA, ipt, covAC); - histos.fill(HIST("Prof_Cov_Mult_etabin_ptbin"), coll.multNTracksPV(), ietaA, ipt, covAC); - } - if (std::isfinite(covCA)) { - histos.fill(HIST("Prof_Cov_Cent_etabin_ptbin"), cent, ietaA, ipt, covCA); - histos.fill(HIST("Prof_Cov_Mult_etabin_ptbin"), coll.multNTracksPV(), ietaA, ipt, covCA); - } - } else if (isp == numKPion) { // Pi - if (std::isfinite(c2Sub)) { - histos.fill(HIST("Prof_C2Sub_Cent_etabin_ptbin_Pi"), cent, ietaA, ipt, c2Sub); - histos.fill(HIST("Prof_C2Sub_Mult_etabin_ptbin_Pi"), coll.multNTracksPV(), ietaA, ipt, c2Sub); - } - if (std::isfinite(covAC)) { - histos.fill(HIST("Prof_Cov_Cent_etabin_ptbin_Pi"), cent, ietaA, ipt, covAC); - histos.fill(HIST("Prof_Cov_Mult_etabin_ptbin_Pi"), coll.multNTracksPV(), ietaA, ipt, covAC); - } - if (std::isfinite(covCA)) { - histos.fill(HIST("Prof_Cov_Cent_etabin_ptbin_Pi"), cent, ietaA, ipt, covCA); - histos.fill(HIST("Prof_Cov_Mult_etabin_ptbin_Pi"), coll.multNTracksPV(), ietaA, ipt, covCA); - } - } else if (isp == numKKaon) { // Ka - if (std::isfinite(c2Sub)) { - histos.fill(HIST("Prof_C2Sub_Cent_etabin_ptbin_Ka"), cent, ietaA, ipt, c2Sub); - histos.fill(HIST("Prof_C2Sub_Mult_etabin_ptbin_Ka"), coll.multNTracksPV(), ietaA, ipt, c2Sub); - } - if (std::isfinite(covAC)) { - histos.fill(HIST("Prof_Cov_Cent_etabin_ptbin_Ka"), cent, ietaA, ipt, covAC); - histos.fill(HIST("Prof_Cov_Mult_etabin_ptbin_Ka"), coll.multNTracksPV(), ietaA, ipt, covAC); - } - if (std::isfinite(covCA)) { - histos.fill(HIST("Prof_Cov_Cent_etabin_ptbin_Ka"), cent, ietaA, ipt, covCA); - histos.fill(HIST("Prof_Cov_Mult_etabin_ptbin_Ka"), coll.multNTracksPV(), ietaA, ipt, covCA); - } - } else if (isp == numKProton) { // Pr - if (std::isfinite(c2Sub)) { - histos.fill(HIST("Prof_C2Sub_Cent_etabin_ptbin_Pr"), cent, ietaA, ipt, c2Sub); - histos.fill(HIST("Prof_C2Sub_Mult_etabin_ptbin_Pr"), coll.multNTracksPV(), ietaA, ipt, c2Sub); - } - if (std::isfinite(covAC)) { - histos.fill(HIST("Prof_Cov_Cent_etabin_ptbin_Pr"), cent, ietaA, ipt, covAC); - histos.fill(HIST("Prof_Cov_Mult_etabin_ptbin_Pr"), coll.multNTracksPV(), ietaA, ipt, covAC); - } - if (std::isfinite(covCA)) { - histos.fill(HIST("Prof_Cov_Cent_etabin_ptbin_Pr"), cent, ietaA, ipt, covCA); - histos.fill(HIST("Prof_Cov_Mult_etabin_ptbin_Pr"), coll.multNTracksPV(), ietaA, ipt, covCA); - } - } + float covFT0A = p1kBarFt0A * p1kBar[isp][ietaC]; + float covFT0C = p1kBarFt0C * p1kBar[isp][ietaA]; + + if (std::isfinite(c2Sub)) { + histos.fill(HIST("Prof_C2Sub_Cent_etabin_spbin"), cent, ietaA, isp, c2Sub); + histos.fill(HIST("Prof_C2Sub_Mult_etabin_spbin"), coll.multNTracksPV(), ietaA, isp, c2Sub); + } + if (std::isfinite(covAC)) { + histos.fill(HIST("Prof_Cov_Cent_etabin_spbin"), cent, ietaA, isp, covAC); + histos.fill(HIST("Prof_Cov_Mult_etabin_spbin"), coll.multNTracksPV(), ietaA, isp, covAC); + } + if (std::isfinite(covCA)) { + histos.fill(HIST("Prof_Cov_Cent_etabin_spbin"), cent, ietaA, isp, covCA); + histos.fill(HIST("Prof_Cov_Mult_etabin_spbin"), coll.multNTracksPV(), ietaA, isp, covCA); + } + if (std::isfinite(covFT0A)) { + histos.fill(HIST("Prof_CovFT0A_Cent_etabin_spbin"), cent, ietaA, isp, covFT0A); + histos.fill(HIST("Prof_CovFT0A_Mult_etabin_spbin"), coll.multNTracksPV(), ietaA, isp, covFT0A); + } + if (std::isfinite(covFT0C)) { + histos.fill(HIST("Prof_CovFT0C_Cent_etabin_spbin"), cent, ietaA, isp, covFT0C); + histos.fill(HIST("Prof_CovFT0C_Mult_etabin_spbin"), coll.multNTracksPV(), ietaA, isp, covFT0C); } } } - - // --- 5. Full 2D Covariances & GapSum Profiles --- for (int ietaA = 1; ietaA < KNEta; ++ietaA) { - for (int ietaB = 1; ietaB < KNEta; ++ietaB) { + for (int ietaC = 1; ietaC < KNEta; ++ietaC) { float etaValA = (etaLw[ietaA] + etaUp[ietaA]) / 2.0f; - float etaValB = (etaLw[ietaB] + etaUp[ietaB]) / 2.0f; + float etaValB = (etaLw[ietaC] + etaUp[ietaC]) / 2.0f; float gap = etaValA - etaValB; float sum = (etaValA + etaValB) / 2.0f; + for (int isp = 0; isp < KNsp; ++isp) { - for (int ipt = 0; ipt < KNpT; ++ipt) { - for (int isp = 0; isp < KNsp; ++isp) { - - float c2Sub = p1kBar[isp][ietaA][ipt] * p1kBar[isp][ietaB][ipt]; - float cov = p1kBarMult[isp][ietaA][ipt] * p1kBar[isp][ietaB][ipt]; + float c2Sub = p1kBar[isp][ietaA] * p1kBar[isp][ietaC]; + float cov = p1kBarMult[isp][ietaA] * p1kBar[isp][ietaC]; + float covFT0A = p1kBarFt0A * p1kBar[isp][ietaC]; + float covFT0C = p1kBarFt0C * p1kBar[isp][ietaA]; - if (isp == numKInclusive) { // Inclusive - if (ipt == 0) { - if (std::isfinite(c2Sub)) { - histos.fill(HIST("Prof_ipt0_C2Sub2D_Cent_etaA_etaC"), cent, etaValA, etaValB, c2Sub); - histos.fill(HIST("Prof_ipt0_GapSum2D"), cent, gap, sum, c2Sub); - } - if (std::isfinite(cov)) - histos.fill(HIST("Prof_ipt0_Cov2D_Cent_etaA_etaC"), cent, etaValA, etaValB, cov); - } else if (ipt == KNpT - 2) { - if (std::isfinite(c2Sub)) { - histos.fill(HIST("Prof_ipt1_C2Sub2D_Cent_etaA_etaC"), cent, etaValA, etaValB, c2Sub); - histos.fill(HIST("Prof_ipt1_GapSum2D"), cent, gap, sum, c2Sub); - } - if (std::isfinite(cov)) - histos.fill(HIST("Prof_ipt1_Cov2D_Cent_etaA_etaC"), cent, etaValA, etaValB, cov); - } else if (ipt == KNpT - 1) { - if (std::isfinite(c2Sub)) { - histos.fill(HIST("Prof_ipt2_C2Sub2D_Cent_etaA_etaC"), cent, etaValA, etaValB, c2Sub); - histos.fill(HIST("Prof_ipt2_GapSum2D"), cent, gap, sum, c2Sub); - } - if (std::isfinite(cov)) - histos.fill(HIST("Prof_ipt2_Cov2D_Cent_etaA_etaC"), cent, etaValA, etaValB, cov); - } - } else if (isp == numKPion) { // Pi - if (ipt == 0) { - if (std::isfinite(c2Sub)) { - histos.fill(HIST("Prof_ipt0_C2Sub2D_Cent_etaA_etaC_Pi"), cent, etaValA, etaValB, c2Sub); - histos.fill(HIST("Prof_ipt0_GapSum2D_Pi"), cent, gap, sum, c2Sub); - } - if (std::isfinite(cov)) - histos.fill(HIST("Prof_ipt0_Cov2D_Cent_etaA_etaC_Pi"), cent, etaValA, etaValB, cov); - } else if (ipt == KNpT - 2) { - if (std::isfinite(c2Sub)) { - histos.fill(HIST("Prof_ipt1_C2Sub2D_Cent_etaA_etaC_Pi"), cent, etaValA, etaValB, c2Sub); - histos.fill(HIST("Prof_ipt1_GapSum2D_Pi"), cent, gap, sum, c2Sub); - } - if (std::isfinite(cov)) - histos.fill(HIST("Prof_ipt1_Cov2D_Cent_etaA_etaC_Pi"), cent, etaValA, etaValB, cov); - } else if (ipt == KNpT - 1) { - if (std::isfinite(c2Sub)) { - histos.fill(HIST("Prof_ipt2_C2Sub2D_Cent_etaA_etaC_Pi"), cent, etaValA, etaValB, c2Sub); - histos.fill(HIST("Prof_ipt2_GapSum2D_Pi"), cent, gap, sum, c2Sub); - } - if (std::isfinite(cov)) - histos.fill(HIST("Prof_ipt2_Cov2D_Cent_etaA_etaC_Pi"), cent, etaValA, etaValB, cov); - } - } else if (isp == numKKaon) { // Ka - if (ipt == 0) { - if (std::isfinite(c2Sub)) { - histos.fill(HIST("Prof_ipt0_C2Sub2D_Cent_etaA_etaC_Ka"), cent, etaValA, etaValB, c2Sub); - histos.fill(HIST("Prof_ipt0_GapSum2D_Ka"), cent, gap, sum, c2Sub); - } - if (std::isfinite(cov)) - histos.fill(HIST("Prof_ipt0_Cov2D_Cent_etaA_etaC_Ka"), cent, etaValA, etaValB, cov); - } else if (ipt == KNpT - 2) { - if (std::isfinite(c2Sub)) { - histos.fill(HIST("Prof_ipt1_C2Sub2D_Cent_etaA_etaC_Ka"), cent, etaValA, etaValB, c2Sub); - histos.fill(HIST("Prof_ipt1_GapSum2D_Ka"), cent, gap, sum, c2Sub); - } - if (std::isfinite(cov)) - histos.fill(HIST("Prof_ipt1_Cov2D_Cent_etaA_etaC_Ka"), cent, etaValA, etaValB, cov); - } else if (ipt == KNpT - 1) { - if (std::isfinite(c2Sub)) { - histos.fill(HIST("Prof_ipt2_C2Sub2D_Cent_etaA_etaC_Ka"), cent, etaValA, etaValB, c2Sub); - histos.fill(HIST("Prof_ipt2_GapSum2D_Ka"), cent, gap, sum, c2Sub); - } - if (std::isfinite(cov)) - histos.fill(HIST("Prof_ipt2_Cov2D_Cent_etaA_etaC_Ka"), cent, etaValA, etaValB, cov); - } - } else if (isp == numKProton) { // Pr - if (ipt == 0) { - if (std::isfinite(c2Sub)) { - histos.fill(HIST("Prof_ipt0_C2Sub2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, c2Sub); - histos.fill(HIST("Prof_ipt0_GapSum2D_Pr"), cent, gap, sum, c2Sub); - } - if (std::isfinite(cov)) - histos.fill(HIST("Prof_ipt0_Cov2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, cov); - } else if (ipt == KNpT - 2) { - if (std::isfinite(c2Sub)) { - histos.fill(HIST("Prof_ipt1_C2Sub2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, c2Sub); - histos.fill(HIST("Prof_ipt1_GapSum2D_Pr"), cent, gap, sum, c2Sub); - } - if (std::isfinite(cov)) - histos.fill(HIST("Prof_ipt1_Cov2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, cov); - } else if (ipt == KNpT - 1) { - if (std::isfinite(c2Sub)) { - histos.fill(HIST("Prof_ipt2_C2Sub2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, c2Sub); - histos.fill(HIST("Prof_ipt2_GapSum2D_Pr"), cent, gap, sum, c2Sub); - } - if (std::isfinite(cov)) - histos.fill(HIST("Prof_ipt2_Cov2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, cov); - } - } + if (isp == kInclusive) { + if (std::isfinite(c2Sub)) { + histos.fill(HIST("Prof_C2Sub2D_Cent_etaA_etaC"), cent, etaValA, etaValB, c2Sub); + histos.fill(HIST("Prof_GapSum2D"), cent, gap, sum, c2Sub); + } + if (std::isfinite(cov)) + histos.fill(HIST("Prof_Cov2D_Cent_etaA_etaC"), cent, etaValA, etaValB, cov); + if (std::isfinite(covFT0A)) + histos.fill(HIST("Prof_CovFT0A2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covFT0A); + if (std::isfinite(covFT0C)) + histos.fill(HIST("Prof_CovFT0C2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covFT0C); + } else if (isp == kPiMinus) { + if (std::isfinite(c2Sub)) { + histos.fill(HIST("Prof_C2Sub2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, c2Sub); + histos.fill(HIST("Prof_GapSum2D_PiMinus"), cent, gap, sum, c2Sub); + } + if (std::isfinite(cov)) + histos.fill(HIST("Prof_Cov2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, cov); + if (std::isfinite(covFT0A)) + histos.fill(HIST("Prof_CovFT0A2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, covFT0A); + if (std::isfinite(covFT0C)) + histos.fill(HIST("Prof_CovFT0C2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, covFT0C); + } else if (isp == kPiPlus) { + if (std::isfinite(c2Sub)) { + histos.fill(HIST("Prof_C2Sub2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, c2Sub); + histos.fill(HIST("Prof_GapSum2D_PiPlus"), cent, gap, sum, c2Sub); + } + if (std::isfinite(cov)) + histos.fill(HIST("Prof_Cov2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, cov); + if (std::isfinite(covFT0A)) + histos.fill(HIST("Prof_CovFT0A2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, covFT0A); + if (std::isfinite(covFT0C)) + histos.fill(HIST("Prof_CovFT0C2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, covFT0C); + } else if (isp == kPiAll) { + if (std::isfinite(c2Sub)) { + histos.fill(HIST("Prof_C2Sub2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, c2Sub); + histos.fill(HIST("Prof_GapSum2D_PiAll"), cent, gap, sum, c2Sub); + } + if (std::isfinite(cov)) + histos.fill(HIST("Prof_Cov2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, cov); + if (std::isfinite(covFT0A)) + histos.fill(HIST("Prof_CovFT0A2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, covFT0A); + if (std::isfinite(covFT0C)) + histos.fill(HIST("Prof_CovFT0C2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, covFT0C); + } else if (isp == kKaMinus) { + if (std::isfinite(c2Sub)) { + histos.fill(HIST("Prof_C2Sub2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, c2Sub); + histos.fill(HIST("Prof_GapSum2D_KaMinus"), cent, gap, sum, c2Sub); + } + if (std::isfinite(cov)) + histos.fill(HIST("Prof_Cov2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, cov); + if (std::isfinite(covFT0A)) + histos.fill(HIST("Prof_CovFT0A2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, covFT0A); + if (std::isfinite(covFT0C)) + histos.fill(HIST("Prof_CovFT0C2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, covFT0C); + } else if (isp == kKaPlus) { + if (std::isfinite(c2Sub)) { + histos.fill(HIST("Prof_C2Sub2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, c2Sub); + histos.fill(HIST("Prof_GapSum2D_KaPlus"), cent, gap, sum, c2Sub); + } + if (std::isfinite(cov)) + histos.fill(HIST("Prof_Cov2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, cov); + if (std::isfinite(covFT0A)) + histos.fill(HIST("Prof_CovFT0A2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, covFT0A); + if (std::isfinite(covFT0C)) + histos.fill(HIST("Prof_CovFT0C2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, covFT0C); + } else if (isp == kKaAll) { + if (std::isfinite(c2Sub)) { + histos.fill(HIST("Prof_C2Sub2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, c2Sub); + histos.fill(HIST("Prof_GapSum2D_KaAll"), cent, gap, sum, c2Sub); + } + if (std::isfinite(cov)) + histos.fill(HIST("Prof_Cov2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, cov); + if (std::isfinite(covFT0A)) + histos.fill(HIST("Prof_CovFT0A2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, covFT0A); + if (std::isfinite(covFT0C)) + histos.fill(HIST("Prof_CovFT0C2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, covFT0C); + } else if (isp == kProton) { + if (std::isfinite(c2Sub)) { + histos.fill(HIST("Prof_C2Sub2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, c2Sub); + histos.fill(HIST("Prof_GapSum2D_Pr"), cent, gap, sum, c2Sub); + } + if (std::isfinite(cov)) + histos.fill(HIST("Prof_Cov2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, cov); + if (std::isfinite(covFT0A)) + histos.fill(HIST("Prof_CovFT0A2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covFT0A); + if (std::isfinite(covFT0C)) + histos.fill(HIST("Prof_CovFT0C2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covFT0C); + } else if (isp == kAntiProton) { + if (std::isfinite(c2Sub)) { + histos.fill(HIST("Prof_C2Sub2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, c2Sub); + histos.fill(HIST("Prof_GapSum2D_AntiPr"), cent, gap, sum, c2Sub); + } + if (std::isfinite(cov)) + histos.fill(HIST("Prof_Cov2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, cov); + if (std::isfinite(covFT0A)) + histos.fill(HIST("Prof_CovFT0A2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, covFT0A); + if (std::isfinite(covFT0C)) + histos.fill(HIST("Prof_CovFT0C2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, covFT0C); + } else if (isp == kAllProton) { + if (std::isfinite(c2Sub)) { + histos.fill(HIST("Prof_C2Sub2D_Cent_etaA_etaC_AllPr"), cent, etaValA, etaValB, c2Sub); + histos.fill(HIST("Prof_GapSum2D_AllPr"), cent, gap, sum, c2Sub); + } + if (std::isfinite(cov)) + histos.fill(HIST("Prof_Cov2D_Cent_etaA_etaC_AllPr"), cent, etaValA, etaValB, cov); + if (std::isfinite(covFT0A)) + histos.fill(HIST("Prof_CovFT0A2D_Cent_etaA_etaC_AllPr"), cent, etaValA, etaValB, covFT0A); + if (std::isfinite(covFT0C)) + histos.fill(HIST("Prof_CovFT0C2D_Cent_etaA_etaC_AllPr"), cent, etaValA, etaValB, covFT0C); } } } } } - PROCESS_SWITCH(RadialFlowDecorr, processDataFluc, "process data to calculate fluc pT and Et", cfgRunDataFluc); + PROCESS_SWITCH(RadialFlowDecorr, processDataFluc, "process data to calculate fluc pT", cfgRunDataFluc); }; - WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { WorkflowSpec workflow{adaptAnalysisTask(cfgc)}; From 875e61ab30b668cdbab723e2709935796ffc2ccb Mon Sep 17 00:00:00 2001 From: alicja-pp <101565842+alicja-pp@users.noreply.github.com> Date: Mon, 2 Mar 2026 13:57:44 +0100 Subject: [PATCH 127/347] [PWGCF] FemtoUniverse producer: Add option to call fillParticles for MC truth for V0 (#15191) --- .../TableProducer/femtoUniverseProducerTask.cxx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx b/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx index 97d4e4f7437..a9b94fe4b0a 100644 --- a/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx +++ b/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx @@ -136,6 +136,7 @@ struct FemtoUniverseProducerTask { Configurable confFillCollExt{"confFillCollExt", false, "Option to fill collision extended table"}; Configurable confCollMCTruthOnlyReco{"confCollMCTruthOnlyReco", false, "Fill only MC truth collisions that were reconstructed and selected"}; + Configurable confFillMCTruthV0Daugh{"confFillMCTruthV0Daugh", true, "Fill MC truth daughters of V0"}; /// Event filtering (used for v0-cascade analysis) Configurable zorroMask{"zorroMask", "", "zorro trigger class to select on (empty: none)"}; @@ -2913,7 +2914,11 @@ struct FemtoUniverseProducerTask { const auto colcheck = fillMCTruthCollisionsCentRun3(col); if (colcheck) { outputCollExtra(1.0, 1.0); - fillV0MCTruth(groupedMCParticles); // fills MC V0s and its daughters + if (confFillMCTruthV0Daugh) { + fillV0MCTruth(groupedMCParticles); // fills MC V0s and its daughters + } else { + fillParticles(groupedMCParticles, recoMcIds); // fills mc particles + } } } } From 133994c9dad02010a3558c8e2a9fe4f423b7909a Mon Sep 17 00:00:00 2001 From: Xufei Xue <150438610+dongfangqingxin@users.noreply.github.com> Date: Mon, 2 Mar 2026 21:18:10 +0800 Subject: [PATCH 128/347] [PWGHF] Add Lc into derivedDataCreatorCorrelationsReduced (#15187) Co-authored-by: ALICE Action Bot --- .../derivedDataCreatorCorrelationsReduced.cxx | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/PWGHF/HFC/TableProducer/derivedDataCreatorCorrelationsReduced.cxx b/PWGHF/HFC/TableProducer/derivedDataCreatorCorrelationsReduced.cxx index bc222987dc6..22277105bb4 100644 --- a/PWGHF/HFC/TableProducer/derivedDataCreatorCorrelationsReduced.cxx +++ b/PWGHF/HFC/TableProducer/derivedDataCreatorCorrelationsReduced.cxx @@ -63,6 +63,7 @@ enum CandidateType { DsToPiKK, D0ToPiK, D0ToKPi, + LcToPKPi, Hadron }; @@ -113,22 +114,26 @@ struct HfDerivedDataCreatorCorrelationsReduced { using CandDsData = soa::Filtered>; using CandDplusData = soa::Filtered>; using CandD0Data = soa::Filtered>; + using CandLcData = soa::Filtered>; using TracksData = soa::Filtered>; Filter filterSelectDsCandidates = aod::hf_sel_candidate_ds::isSelDsToKKPi >= selectionFlag || aod::hf_sel_candidate_ds::isSelDsToPiKK >= selectionFlag; Filter filterSelectDplusCandidates = aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlag; Filter filterSelectD0Candidates = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlag || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlag; + Filter filterSelectLcCandidates = aod::hf_sel_candidate_lc::isSelLcToPKPi >= selectionFlag; Filter filterSelectTrkData = (nabs(aod::track::eta) < etaTrkMax) && (aod::track::pt > ptTrkMin) && (aod::track::pt < ptTrkMax) && (nabs(aod::track::dcaXY) < dcaXYTrkMax) && (nabs(aod::track::dcaZ) < dcaZTrkMax); Preslice candsDsPerColl = aod::hf_cand::collisionId; Preslice candsDplusPerColl = aod::hf_cand::collisionId; Preslice candsD0PerColl = aod::hf_cand::collisionId; + Preslice candsLcPerColl = aod::hf_cand::collisionId; Preslice trackIndicesPerColl = aod::track::collisionId; Partition selectedDsToKKPi = aod::hf_sel_candidate_ds::isSelDsToKKPi >= selectionFlag; Partition selectedDsToPiKK = aod::hf_sel_candidate_ds::isSelDsToPiKK >= selectionFlag; Partition selectedD0ToPiK = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlag; Partition selectedD0ToKPi = aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlag; + Partition selectedLcToPKPi = aod::hf_sel_candidate_lc::isSelLcToPKPi >= selectionFlag; ConfigurableAxis binsInvMass{"binsInvMass", {300, 1.6, 2.2}, ""}; ConfigurableAxis binsMultFT0M{"binsMultFT0M", {100, 0., 10000.}, "Multiplicity as FT0M signal amplitude"}; @@ -152,6 +157,8 @@ struct HfDerivedDataCreatorCorrelationsReduced { massCharm = o2::constants::physics::MassDS; } else if (doprocessD0SameEvent || doprocessD0MixedEvent) { massCharm = o2::constants::physics::MassD0; + } else if (doprocessLcSameEvent || doprocessLcMixedEvent) { + massCharm = o2::constants::physics::MassLambdaCPlus; } else if (doprocessHadronHadronSameEvent || doprocessHadronHadronMixedEvent) { LOG(info) << "Charm mass not set, processing Hadron-Hadron case"; } else { @@ -211,6 +218,9 @@ struct HfDerivedDataCreatorCorrelationsReduced { if constexpr (CandType == CandidateType::D0ToKPi) { return HfHelper::invMassD0barToKPi(candidate); } + if constexpr (CandType == CandidateType::LcToPKPi) { + return HfHelper::invMassLcToPKPi(candidate); + } return -1.; } @@ -245,6 +255,11 @@ struct HfDerivedDataCreatorCorrelationsReduced { outputMl[iclass] = candidate.mlProbD0bar()[classMl->at(iclass)]; } } + if constexpr (CandType == CandidateType::LcToPKPi) { + for (unsigned int iclass = 0; iclass < classMl->size(); iclass++) { + outputMl[iclass] = candidate.mlProbLcToPKPi()[classMl->at(iclass)]; + } + } return outputMl; } @@ -534,6 +549,43 @@ struct HfDerivedDataCreatorCorrelationsReduced { } PROCESS_SWITCH(HfDerivedDataCreatorCorrelationsReduced, processD0MixedEvent, "Process Mixed Event for D0 candidates", false); + // Lc with ML selections + void processLcSameEvent(CollsWithCentMult::iterator const& coll, + TracksData const& tracks, + CandLcData const&) + { + auto candsLcToPKPi = selectedLcToPKPi->sliceByCached(aod::hf_cand::collisionId, coll.globalIndex(), cache); + if (forceCharmInCollision && candsLcToPKPi.size() < 1) { + return; + } + float cent{-1.}, mult{-1.}; + if (!checkCollision(coll, cent, mult)) { + return; + } + rowCollisions(mult, coll.numContrib(), cent, coll.posZ()); + fillSameEvent(candsLcToPKPi, tracks, cent); + } + PROCESS_SWITCH(HfDerivedDataCreatorCorrelationsReduced, processLcSameEvent, "Process Same Event for Lc candidates", false); + + // Lc with ML selections + void processLcMixedEvent(CollsWithCentMult::iterator const& coll, + TracksData const& tracks, + CandLcData const&) + { + auto candsLcToPKPi = selectedLcToPKPi->sliceByCached(aod::hf_cand::collisionId, coll.globalIndex(), cache); + if (forceCharmInCollision && candsLcToPKPi.size() < 1) { + return; + } + float cent{-1.}, mult{-1.}; + if (!checkCollision(coll, cent, mult)) { + return; + } + rowCollisions(mult, coll.numContrib(), cent, coll.posZ()); + fillCharmMixedEvent(candsLcToPKPi); + fillTrkMixedEvent(tracks, cent); + } + PROCESS_SWITCH(HfDerivedDataCreatorCorrelationsReduced, processLcMixedEvent, "Process Mixed Event for Lc candidates", false); + // Hadron Hadron Same Event void processHadronHadronSameEvent(CollsWithCentMult::iterator const& coll, TracksData const& tracks) From 9affd6de3644e6c341cffb9b5ad49928bf9f19ed Mon Sep 17 00:00:00 2001 From: Lucia Anna Tarasovicova Date: Mon, 2 Mar 2026 14:20:42 +0100 Subject: [PATCH 129/347] [PWGLF] Change in hStrangeCorrelation.cxx (#15214) Co-authored-by: Lucia Anna Tarasovicova --- PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx b/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx index 04e01e1347a..159c2e492ce 100644 --- a/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx +++ b/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx @@ -419,6 +419,8 @@ struct HStrangeCorrelation { hPurityUncertaintyHadronMult = static_cast(listEfficiencies->FindObject("hPurityUncertaintyHadronMult")); if (efficiencyFlags.applyEfficiencyPropagation && !efficiencyFlags.applyEffAsFunctionOfMultAndPhi && !hEfficiencyUncertaintyTrigger) LOG(fatal) << "Problem getting hEfficiencyUncertaintyTrigger!"; + if (efficiencyFlags.applyEffAsFunctionOfMult && !hEfficiencyTriggerMult) + LOG(fatal) << "Problem getting hEfficiencyTriggerMult!"; LOG(info) << "Efficiencies now loaded for " << mRunNumber; } @@ -1173,7 +1175,7 @@ struct HStrangeCorrelation { } else { efficiency = hEfficiencyCascade[Index]->Interpolate(ptassoc, assoc.eta()); if (efficiencyFlags.applyEfficiencyPropagation) - efficiencyError = hEfficiencyUncertaintyCascade[Index]->Interpolate(ptassoc, assoc.eta(), assoc.phi()); + efficiencyError = hEfficiencyUncertaintyCascade[Index]->Interpolate(ptassoc, assoc.eta()); } } if (efficiency == 0) { // check for zero efficiency, do not apply if the case From 5c911243999340dc3442e6b5a8cf4c5f14c699d9 Mon Sep 17 00:00:00 2001 From: Stefanie Mrozinski <63045530+Steffimro@users.noreply.github.com> Date: Mon, 2 Mar 2026 14:21:22 +0100 Subject: [PATCH 130/347] [PWGEM] Fix Event subscription in process functions (#15218) Co-authored-by: ALICE Action Bot --- PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h | 2 +- PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h | 2 +- PWGEM/PhotonMeson/DataModel/gammaTables.h | 5 +-- .../TableProducer/createEMEventPhoton.cxx | 12 +++---- .../TableProducer/photonconversionbuilder.cxx | 35 ++++++++++--------- .../TableProducer/skimmerDalitzEE.cxx | 4 +-- PWGEM/PhotonMeson/Tasks/gammaConversions.cxx | 4 +-- 7 files changed, 33 insertions(+), 31 deletions(-) diff --git a/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h b/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h index 965d88ddcc0..25d149538cb 100644 --- a/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h +++ b/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h @@ -1094,7 +1094,7 @@ struct Pi0EtaToGammaGamma { } PROCESS_SWITCH(Pi0EtaToGammaGamma, processAnalysisJJMC, "process pair analysis", false); - void processDummy(o2::aod::EMEvents const&) {} + void processDummy(o2::aod::EMEvents_004 const&) {} PROCESS_SWITCH(Pi0EtaToGammaGamma, processDummy, "Dummy function", false); }; #endif // PWGEM_PHOTONMESON_CORE_PI0ETATOGAMMAGAMMA_H_ diff --git a/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h b/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h index a67295b4227..3308b9c817c 100644 --- a/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h +++ b/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h @@ -985,7 +985,7 @@ struct Pi0EtaToGammaGammaMC { } PROCESS_SWITCH(Pi0EtaToGammaGammaMC, processAnalysisJJMC, "process pair analysis", false); - void processDummy(o2::aod::EMEvents const&) {} + void processDummy(o2::aod::EMEvents_004 const&) {} PROCESS_SWITCH(Pi0EtaToGammaGammaMC, processDummy, "Dummy function", false); }; #endif // PWGEM_PHOTONMESON_CORE_PI0ETATOGAMMAGAMMAMC_H_ diff --git a/PWGEM/PhotonMeson/DataModel/gammaTables.h b/PWGEM/PhotonMeson/DataModel/gammaTables.h index 9b680aed2c9..be66a8d611a 100644 --- a/PWGEM/PhotonMeson/DataModel/gammaTables.h +++ b/PWGEM/PhotonMeson/DataModel/gammaTables.h @@ -468,8 +468,9 @@ DECLARE_SOA_TABLE(DalitzEEs, "AOD", "DALITZEE", //! // iterators using DalitzEE = DalitzEEs::iterator; -DECLARE_SOA_TABLE(DalitzEEEMEventIds, "AOD", "EEEMEVENTID", dalitzee::EMEventId); // To be joined with DalitzEEs table at analysis level. -// iterators +DECLARE_SOA_TABLE(DalitzEEEMEventIds_000, "AOD", "EEEMEVENTID", dalitzee::EMEventId); // To be joined with DalitzEEs table at analysis level. +DECLARE_SOA_TABLE_VERSIONED(DalitzEEEMEventIds_001, "AOD", "EEEMEVENTID", 1, dalitzee::EMPhotonEventId); // To be joined with DalitzEEs table at analysis level. +using DalitzEEEMEventIds = DalitzEEEMEventIds_001; using DalitzEEEMEventId = DalitzEEEMEventIds::iterator; namespace pwgem::photon::swtinfo diff --git a/PWGEM/PhotonMeson/TableProducer/createEMEventPhoton.cxx b/PWGEM/PhotonMeson/TableProducer/createEMEventPhoton.cxx index 0081bf67244..48720ac6863 100644 --- a/PWGEM/PhotonMeson/TableProducer/createEMEventPhoton.cxx +++ b/PWGEM/PhotonMeson/TableProducer/createEMEventPhoton.cxx @@ -387,32 +387,32 @@ struct AssociatePhotonToEMEvent { // This struct is for both data and MC. // Note that reconstructed collisions without mc collisions are already rejected in CreateEMEventPhoton in MC. - void processPCM(aod::EMEvents const& collisions, aod::V0PhotonsKF const& photons) + void processPCM(aod::EMEvents_004 const& collisions, aod::V0PhotonsKF const& photons) { fillEventId(collisions, photons, v0kfeventid, perCollisionPCM); } - void processElectronFromDalitz(aod::EMEvents const& collisions, aod::EMPrimaryElectronsFromDalitz const& tracks) + void processElectronFromDalitz(aod::EMEvents_004 const& collisions, aod::EMPrimaryElectronsFromDalitz const& tracks) { fillEventId(collisions, tracks, prmeleventid, perCollisionEl); } - void processPHOS(aod::EMEvents const& collisions, aod::PHOSClusters const& photons) + void processPHOS(aod::EMEvents_004 const& collisions, aod::PHOSClusters const& photons) { fillEventId(collisions, photons, phoseventid, perCollisionPHOS); } - void processEMC(aod::EMEvents const& collisions, aod::SkimEMCClusters const& photons) + void processEMC(aod::EMEvents_004 const& collisions, aod::SkimEMCClusters const& photons) { fillEventId(collisions, photons, emceventid, perCollisionEMC); } - // void processChargedTrack(aod::EMEvents const& collisions, aod::EMPrimaryTracks const& tracks) + // void processChargedTrack(aod::EMEvents_004 const& collisions, aod::EMPrimaryTracks const& tracks) // { // fillEventId(collisions, tracks, prmtrackeventid, perCollision_track); // } - void processDummy(aod::EMEvents const&) {} + void processDummy(aod::EMEvents_004 const&) {} PROCESS_SWITCH(AssociatePhotonToEMEvent, processPCM, "process pcm-event indexing", false); PROCESS_SWITCH(AssociatePhotonToEMEvent, processElectronFromDalitz, "process dalitzee-event indexing", false); diff --git a/PWGEM/PhotonMeson/TableProducer/photonconversionbuilder.cxx b/PWGEM/PhotonMeson/TableProducer/photonconversionbuilder.cxx index d8f9edbf43a..0591f841f2c 100644 --- a/PWGEM/PhotonMeson/TableProducer/photonconversionbuilder.cxx +++ b/PWGEM/PhotonMeson/TableProducer/photonconversionbuilder.cxx @@ -237,23 +237,24 @@ struct PhotonConversionBuilder { ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); ccdb->setFatalWhenNull(false); - - if (useMatCorrType == MatCorrType::TGeo) { - LOGF(info, "TGeo correction requested, loading geometry"); - if (!o2::base::GeometryManager::isGeometryLoaded()) { - ccdb->get(geoPath); - } - } - if (useMatCorrType == MatCorrType::LUT) { - LOGF(info, "LUT correction requested, loading LUT"); - lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get(lutPath)); - } - - if (useMatCorrType == MatCorrType::TGeo) { - matCorr = o2::base::Propagator::MatCorrType::USEMatCorrTGeo; - } - if (useMatCorrType == MatCorrType::LUT) { - matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; + switch (useMatCorrType) { + case MatCorrType::TGeo: + LOGF(info, "TGeo correction requested, loading geometry"); + if (!o2::base::GeometryManager::isGeometryLoaded()) { + ccdb->get(geoPath); + } + matCorr = o2::base::Propagator::MatCorrType::USEMatCorrTGeo; + break; + case MatCorrType::LUT: + LOGF(info, "LUT correction requested, loading LUT"); + lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get(lutPath)); + matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; + break; + default: + LOGF(info, "no correction requested, loading LUT by default!"); + lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get(lutPath)); + matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; + break; } if (applyPCMMl) { diff --git a/PWGEM/PhotonMeson/TableProducer/skimmerDalitzEE.cxx b/PWGEM/PhotonMeson/TableProducer/skimmerDalitzEE.cxx index c33a1e2020e..49486d54ca0 100644 --- a/PWGEM/PhotonMeson/TableProducer/skimmerDalitzEE.cxx +++ b/PWGEM/PhotonMeson/TableProducer/skimmerDalitzEE.cxx @@ -37,7 +37,7 @@ using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::constants::physics; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; using MyTracks = soa::Join; @@ -375,7 +375,7 @@ struct skimmerDalitzEE { } PROCESS_SWITCH(skimmerDalitzEE, processCEFP, "Process dalitz ee for CEFP", false); // for central event filter processing - void processOnlyNee(soa::Join const& collisions) + void processOnlyNee(soa::Join const& collisions) { for (auto& collision : collisions) { float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; diff --git a/PWGEM/PhotonMeson/Tasks/gammaConversions.cxx b/PWGEM/PhotonMeson/Tasks/gammaConversions.cxx index c1a9eeed496..8a559d3c669 100644 --- a/PWGEM/PhotonMeson/Tasks/gammaConversions.cxx +++ b/PWGEM/PhotonMeson/Tasks/gammaConversions.cxx @@ -620,7 +620,7 @@ struct GammaConversions { } Preslice perCollision = aod::v0photonkf::emphotoneventId; - void processRec(aod::EMEvents::iterator const& theCollision, + void processRec(aod::EMEvents_004::iterator const& theCollision, V0DatasAdditional const& theV0s, aod::V0Legs const&) { @@ -645,7 +645,7 @@ struct GammaConversions { Preslice gperV0 = aod::gammamctrue::v0photonkfId; - void processMc(aod::EMEvents::iterator const& theCollision, + void processMc(aod::EMEvents_004::iterator const& theCollision, V0DatasAdditional const& theV0s, V0LegsWithMC const&, aod::V0DaughterMcParticles const&, From 41933ed5910e424cd34ff7dc8c105736742ed164 Mon Sep 17 00:00:00 2001 From: Swati <69241911+SwatiSaha-1997@users.noreply.github.com> Date: Mon, 2 Mar 2026 18:57:20 +0530 Subject: [PATCH 131/347] [PWGCF] Calculate observables as a func. of Ngen in MCgen and rec (#15221) --- .../Tasks/MeanptFluctuations.cxx | 86 ++++++++++++++++++- 1 file changed, 82 insertions(+), 4 deletions(-) diff --git a/PWGCF/EbyEFluctuations/Tasks/MeanptFluctuations.cxx b/PWGCF/EbyEFluctuations/Tasks/MeanptFluctuations.cxx index 21ed21ad9de..c67c9f767f8 100644 --- a/PWGCF/EbyEFluctuations/Tasks/MeanptFluctuations.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/MeanptFluctuations.cxx @@ -27,6 +27,7 @@ #include "Framework/runDataProcessing.h" #include +#include "TDatabasePDG.h" #include #include #include @@ -149,6 +150,8 @@ struct MeanptFluctuationsAnalysis { HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; std::vector>> subSampleMcGen; std::vector>> subSample; + std::vector>> subSampleMcGenV2; + std::vector>> subSampleV2; TRandom3* fRndm = new TRandom3(0); // filtering collisions and tracks*********** @@ -161,6 +164,7 @@ struct MeanptFluctuationsAnalysis { using EventCandidatesMC = soa::Join; Preslice perCollision = aod::track::collisionId; + Preslice perMcCollision = aod::mcparticle::mcCollisionId; // Event selection cuts - Alex TF1* fMultPVCutLow = nullptr; @@ -246,6 +250,7 @@ struct MeanptFluctuationsAnalysis { histos.add("MCGenerated/hPtParticleVsTrack", "", kTH2F, {ptAxis, ptAxis}); histos.add("MCGenerated/hEtaParticleVsTrack", "", kTH2F, {{100, -2.01, 2.01}, {100, -2.01, 2.01}}); histos.add("MCGenerated/hPhiParticleVsTrack", "", kTH2F, {{100, 0., o2::constants::math::TwoPI}, {100, 0., o2::constants::math::TwoPI}}); + histos.add("MCGenerated/hNgenVsNrec", "Gen multiplicity vs. Rec multiplicity in MC", kTH2F, {multAxis, multAxis}); // Analysis Profiles for central val histos.add("MCGenerated/AnalysisProfiles/Prof_mean_t1", "", {HistType::kTProfile2D, {centAxis, multAxis}}); @@ -255,16 +260,39 @@ struct MeanptFluctuationsAnalysis { histos.add("MCGenerated/AnalysisProfiles/Hist2D_Nch_centrality", "", {HistType::kTH2D, {centAxis, multAxis}}); histos.add("MCGenerated/AnalysisProfiles/Hist2D_meanpt_centrality", "", {HistType::kTH2D, {centAxis, meanpTAxis}}); + histos.add("MCGenerated/AnalysisProfilesV2/Prof_mean_t1", "", {HistType::kTProfile, {multAxis}}); + histos.add("MCGenerated/AnalysisProfilesV2/Prof_var_t1", "", {HistType::kTProfile, {multAxis}}); + histos.add("MCGenerated/AnalysisProfilesV2/Prof_skew_t1", "", {HistType::kTProfile, {multAxis}}); + histos.add("MCGenerated/AnalysisProfilesV2/Prof_kurt_t1", "", {HistType::kTProfile, {multAxis}}); + histos.add("AnalysisProfilesV2/Prof_mean_t1", "", {HistType::kTProfile2D, {multAxis, multAxis}}); + histos.add("AnalysisProfilesV2/Prof_var_t1", "", {HistType::kTProfile2D, {multAxis, multAxis}}); + histos.add("AnalysisProfilesV2/Prof_skew_t1", "", {HistType::kTProfile2D, {multAxis, multAxis}}); + histos.add("AnalysisProfilesV2/Prof_kurt_t1", "", {HistType::kTProfile2D, {multAxis, multAxis}}); + // Analysis Profiles for error subSampleMcGen.resize(cfgNsubSample); + subSampleMcGenV2.resize(cfgNsubSample); + subSampleV2.resize(cfgNsubSample); for (int i = 0; i < cfgNsubSample; i++) { subSampleMcGen[i].resize(4); + subSampleMcGenV2[i].resize(4); + subSampleV2[i].resize(4); } for (int i = 0; i < cfgNsubSample; i++) { subSampleMcGen[i][0] = std::get>(histos.add(Form("MCGenerated/AnalysisProfiles/subSample_%d/Prof_mean_t1", i), "", {HistType::kTProfile2D, {centAxis, multAxis}})); subSampleMcGen[i][1] = std::get>(histos.add(Form("MCGenerated/AnalysisProfiles/subSample_%d/Prof_var_t1", i), "", {HistType::kTProfile2D, {centAxis, multAxis}})); subSampleMcGen[i][2] = std::get>(histos.add(Form("MCGenerated/AnalysisProfiles/subSample_%d/Prof_skew_t1", i), "", {HistType::kTProfile2D, {centAxis, multAxis}})); subSampleMcGen[i][3] = std::get>(histos.add(Form("MCGenerated/AnalysisProfiles/subSample_%d/Prof_kurt_t1", i), "", {HistType::kTProfile2D, {centAxis, multAxis}})); + + subSampleMcGenV2[i][0] = std::get>(histos.add(Form("MCGenerated/AnalysisProfilesV2/subSample_%d/Prof_mean_t1", i), "", {HistType::kTProfile, {multAxis}})); + subSampleMcGenV2[i][1] = std::get>(histos.add(Form("MCGenerated/AnalysisProfilesV2/subSample_%d/Prof_var_t1", i), "", {HistType::kTProfile, {multAxis}})); + subSampleMcGenV2[i][2] = std::get>(histos.add(Form("MCGenerated/AnalysisProfilesV2/subSample_%d/Prof_skew_t1", i), "", {HistType::kTProfile, {multAxis}})); + subSampleMcGenV2[i][3] = std::get>(histos.add(Form("MCGenerated/AnalysisProfilesV2/subSample_%d/Prof_kurt_t1", i), "", {HistType::kTProfile, {multAxis}})); + + subSampleV2[i][0] = std::get>(histos.add(Form("AnalysisProfilesV2/subSample_%d/Prof_mean_t1", i), "", {HistType::kTProfile2D, {multAxis, multAxis}})); + subSampleV2[i][1] = std::get>(histos.add(Form("AnalysisProfilesV2/subSample_%d/Prof_var_t1", i), "", {HistType::kTProfile2D, {multAxis, multAxis}})); + subSampleV2[i][2] = std::get>(histos.add(Form("AnalysisProfilesV2/subSample_%d/Prof_skew_t1", i), "", {HistType::kTProfile2D, {multAxis, multAxis}})); + subSampleV2[i][3] = std::get>(histos.add(Form("AnalysisProfilesV2/subSample_%d/Prof_kurt_t1", i), "", {HistType::kTProfile2D, {multAxis, multAxis}})); } } @@ -530,9 +558,11 @@ struct MeanptFluctuationsAnalysis { if (!mcParticle.has_mcCollision()) continue; - int pdgCode = std::abs(mcParticle.pdgCode()); - bool extraPDGType = (pdgCode != PDG_t::kK0Short && pdgCode != PDG_t::kLambda0); - if (extraPDGType && pdgCode != PDG_t::kElectron && pdgCode != PDG_t::kMuonMinus && pdgCode != PDG_t::kPiPlus && pdgCode != kKPlus && pdgCode != PDG_t::kProton) + // charged check + auto pdgEntry = TDatabasePDG::Instance()->GetParticle(mcParticle.pdgCode()); + if (!pdgEntry) + continue; + if (pdgEntry->Charge() == 0) continue; if (mcParticle.isPhysicalPrimary()) { @@ -575,6 +605,11 @@ struct MeanptFluctuationsAnalysis { histos.fill(HIST("MCGenerated/AnalysisProfiles/Hist2D_Nch_centrality"), cent, nChgen); histos.fill(HIST("MCGenerated/AnalysisProfiles/Hist2D_meanpt_centrality"), cent, meanTerm1gen); + histos.get(HIST("MCGenerated/AnalysisProfilesV2/Prof_mean_t1"))->Fill(nChgen, meanTerm1gen); + histos.get(HIST("MCGenerated/AnalysisProfilesV2/Prof_var_t1"))->Fill(nChgen, varianceTerm1gen); + histos.get(HIST("MCGenerated/AnalysisProfilesV2/Prof_skew_t1"))->Fill(nChgen, skewnessTerm1gen); + histos.get(HIST("MCGenerated/AnalysisProfilesV2/Prof_kurt_t1"))->Fill(nChgen, kurtosisTerm1gen); + // selecting subsample and filling profiles float lRandomMc = fRndm->Rndm(); int sampleIndexMc = static_cast(cfgNsubSample * lRandomMc); @@ -582,12 +617,17 @@ struct MeanptFluctuationsAnalysis { subSampleMcGen[sampleIndexMc][1]->Fill(cent, nChgen, varianceTerm1gen); subSampleMcGen[sampleIndexMc][2]->Fill(cent, nChgen, skewnessTerm1gen); subSampleMcGen[sampleIndexMc][3]->Fill(cent, nChgen, kurtosisTerm1gen); + + subSampleMcGenV2[sampleIndexMc][0]->Fill(nChgen, meanTerm1gen); + subSampleMcGenV2[sampleIndexMc][1]->Fill(nChgen, varianceTerm1gen); + subSampleMcGenV2[sampleIndexMc][2]->Fill(nChgen, skewnessTerm1gen); + subSampleMcGenV2[sampleIndexMc][3]->Fill(nChgen, kurtosisTerm1gen); } //------------------------------------------------------------------------------------------- } PROCESS_SWITCH(MeanptFluctuationsAnalysis, processMCGen, "Process Generated MC data", true); - void processMCRec(MyMCRecCollisions::iterator const& collision, MyMCTracks const& tracks, aod::McCollisions const&, aod::McParticles const&) + void processMCRec(MyMCRecCollisions::iterator const& collision, MyMCTracks const& tracks, aod::McCollisions const&, aod::McParticles const& mcParticles) { histos.fill(HIST("MCGenerated/hMC"), 5.5); @@ -635,6 +675,32 @@ struct MeanptFluctuationsAnalysis { histos.fill(HIST("Hist2D_globalTracks_PVTracks"), collision.multNTracksPV(), tracks.size()); histos.fill(HIST("Hist2D_cent_nch"), tracks.size(), centralityFT0C); + // Calculating generated no of particles for the collision event + double noGen = 0.0; + auto mcColl = collision.mcCollision(); + // Slice particles belonging only to this MC collision + auto particlesThisEvent = mcParticles.sliceBy(perMcCollision, mcColl.globalIndex()); + + for (const auto& mcParticle : particlesThisEvent) { + if (!mcParticle.has_mcCollision()) + continue; + + // charged check + auto pdgEntry = TDatabasePDG::Instance()->GetParticle(mcParticle.pdgCode()); + if (!pdgEntry) + continue; + if (pdgEntry->Charge() == 0) + continue; + + if (mcParticle.isPhysicalPrimary()) { + if ((mcParticle.pt() > cfgCutPtLower) && (mcParticle.pt() < cfgCutPreSelPt) && (std::abs(mcParticle.eta()) < cfgCutPreSelEta)) { + if (mcParticle.pt() > cfgCutPtLower && mcParticle.pt() < cfgCutPtUpper) { + noGen = noGen + 1.0; + } + } + } + } //! end particle loop + // variables double pTsum = 0.0; double nN = 0.0; @@ -706,6 +772,8 @@ struct MeanptFluctuationsAnalysis { } } // end track loop + histos.fill(HIST("MCGenerated/hNgenVsNrec"), noGen, nCh); + // MeanPt if (nN > 0.0f) histos.fill(HIST("hMeanPt"), cent, pTsum / nN); @@ -725,6 +793,11 @@ struct MeanptFluctuationsAnalysis { histos.fill(HIST("AnalysisProfiles/Hist2D_Nch_centrality"), cent, nCh); histos.fill(HIST("AnalysisProfiles/Hist2D_meanpt_centrality"), cent, meanTerm1); + histos.get(HIST("AnalysisProfilesV2/Prof_mean_t1"))->Fill(noGen, nCh, meanTerm1); + histos.get(HIST("AnalysisProfilesV2/Prof_var_t1"))->Fill(noGen, nCh, varianceTerm1); + histos.get(HIST("AnalysisProfilesV2/Prof_skew_t1"))->Fill(noGen, nCh, skewnessTerm1); + histos.get(HIST("AnalysisProfilesV2/Prof_kurt_t1"))->Fill(noGen, nCh, kurtosisTerm1); + // selecting subsample and filling profiles float lRandom = fRndm->Rndm(); int sampleIndex = static_cast(cfgNsubSample * lRandom); @@ -732,6 +805,11 @@ struct MeanptFluctuationsAnalysis { subSample[sampleIndex][1]->Fill(cent, nCh, varianceTerm1); subSample[sampleIndex][2]->Fill(cent, nCh, skewnessTerm1); subSample[sampleIndex][3]->Fill(cent, nCh, kurtosisTerm1); + + subSampleV2[sampleIndex][0]->Fill(noGen, nCh, meanTerm1); + subSampleV2[sampleIndex][1]->Fill(noGen, nCh, varianceTerm1); + subSampleV2[sampleIndex][2]->Fill(noGen, nCh, skewnessTerm1); + subSampleV2[sampleIndex][3]->Fill(noGen, nCh, kurtosisTerm1); } //------------------------------------------------------------------------------------------- } From f93ed916a96166fc1d211d7da284c4e763be7449 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Mon, 2 Mar 2026 16:14:05 +0100 Subject: [PATCH 132/347] [PWGEM/Dilepton] option to select only correct/wrong match for muon in MC (#15222) Co-authored-by: ALICE Action Bot --- PWGEM/Dilepton/Core/DileptonMC.h | 13 +++++++++++-- PWGEM/Dilepton/Core/SingleTrackQCMC.h | 8 ++++++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/PWGEM/Dilepton/Core/DileptonMC.h b/PWGEM/Dilepton/Core/DileptonMC.h index 478695d906c..cbab42900e7 100644 --- a/PWGEM/Dilepton/Core/DileptonMC.h +++ b/PWGEM/Dilepton/Core/DileptonMC.h @@ -289,7 +289,8 @@ struct DileptonMC { Configurable cfg_max_DPhi_wrt_matchedMCHMID{"cfg_max_DPhi_wrt_matchedMCHMID", 1e+10f, "max. dphi between MFT-MCH-MID and MCH-MID"}; Configurable requireMFTHitMap{"requireMFTHitMap", false, "flag to apply MFT hit map"}; Configurable> requiredMFTDisks{"requiredMFTDisks", std::vector{0}, "hit map on MFT disks [0,1,2,3,4]. logical-OR of each double-sided disk"}; - Configurable rejectWrongMatch{"rejectWrongMatch", false, "flag to reject wrong match between MFT and MCH-MID"}; // this is only for MC study, as we don't know correct match in data. + Configurable acceptOnlyCorrectMatch{"acceptOnlyCorrectMatch", false, "flag to accept only correct match between MFT and MCH-MID"}; // this is only for MC study, as we don't know correct match in data. + Configurable acceptOnlyWrongMatch{"acceptOnlyWrongMatch", false, "flag to accept only wrong match between MFT and MCH-MID"}; // this is only for MC study, as we don't know correct match in data. } dimuoncuts; o2::aod::rctsel::RCTFlagsChecker rctChecker; @@ -1433,7 +1434,7 @@ struct DileptonMC { if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t2, cut, tracks)) { return false; } - if (dimuoncuts.rejectWrongMatch) { + if (dimuoncuts.acceptOnlyCorrectMatch) { if (t1.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) && t1.emmcparticleId() != t1.emmftmcparticleId()) { return false; } @@ -1441,6 +1442,14 @@ struct DileptonMC { return false; } } + if (dimuoncuts.acceptOnlyWrongMatch) { // reject correctly matched MFT-MCH-MID for bkg estimation + if (t1.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) && t1.emmcparticleId() == t1.emmftmcparticleId()) { + return false; + } + if (t2.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) && t2.emmcparticleId() == t2.emmftmcparticleId()) { + return false; + } + } if (!cut.IsSelectedPair(t1, t2)) { return false; diff --git a/PWGEM/Dilepton/Core/SingleTrackQCMC.h b/PWGEM/Dilepton/Core/SingleTrackQCMC.h index d60e266da19..34eb5e4094c 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQCMC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQCMC.h @@ -219,7 +219,8 @@ struct SingleTrackQCMC { Configurable cfg_max_DPhi_wrt_matchedMCHMID{"cfg_max_DPhi_wrt_matchedMCHMID", 1e+10f, "max. dphi between MFT-MCH-MID and MCH-MID"}; Configurable requireMFTHitMap{"requireMFTHitMap", false, "flag to apply MFT hit map"}; Configurable> requiredMFTDisks{"requiredMFTDisks", std::vector{0}, "hit map on MFT disks [0,1,2,3,4]. logical-OR of each double-sided disk"}; - Configurable rejectWrongMatch{"rejectWrongMatch", false, "flag to reject wrong match between MFT and MCH-MID"}; // this is only for MC study, as we don't know correct match in data. + Configurable acceptOnlyCorrectMatch{"acceptOnlyCorrectMatch", false, "flag to accept only correct match between MFT and MCH-MID"}; // this is only for MC study, as we don't know correct match in data. + Configurable acceptOnlyWrongMatch{"acceptOnlyWrongMatch", false, "flag to accept only wrong match between MFT and MCH-MID"}; // this is only for MC study, as we don't know correct match in data. } dimuoncuts; o2::aod::rctsel::RCTFlagsChecker rctChecker; @@ -885,7 +886,10 @@ struct SingleTrackQCMC { if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(track, cut, tracks)) { continue; } - if (dimuoncuts.rejectWrongMatch && track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) && track.emmcparticleId() != track.emmftmcparticleId()) { + if (dimuoncuts.acceptOnlyCorrectMatch && track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) && track.emmcparticleId() != track.emmftmcparticleId()) { + continue; + } + if (dimuoncuts.acceptOnlyWrongMatch && track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) && track.emmcparticleId() == track.emmftmcparticleId()) { continue; } } From dc5101b1a152baeee13e68354cc6b28e1c22ebb3 Mon Sep 17 00:00:00 2001 From: Joachim Carlo Kristian Bjerg Hansen <50103987+joachimckh@users.noreply.github.com> Date: Mon, 2 Mar 2026 18:00:28 +0100 Subject: [PATCH 133/347] [PWGJE] Fix on configurable axes (#15190) --- PWGJE/Tasks/jetSpectraEseTask.cxx | 60 +++++++++++-------------------- 1 file changed, 21 insertions(+), 39 deletions(-) diff --git a/PWGJE/Tasks/jetSpectraEseTask.cxx b/PWGJE/Tasks/jetSpectraEseTask.cxx index e9eff0f6cc1..54dbc47901a 100644 --- a/PWGJE/Tasks/jetSpectraEseTask.cxx +++ b/PWGJE/Tasks/jetSpectraEseTask.cxx @@ -53,29 +53,11 @@ using namespace o2::framework; using namespace o2::framework::expressions; struct JetSpectraEseTask { - ConfigurableAxis binJetPt{"binJetPt", {250, -50., 200.}, ""}; - ConfigurableAxis bindPhi{"bindPhi", {180, -o2::constants::math::PI, o2::constants::math::PI}, ""}; - ConfigurableAxis binESE{"binESE", {100, 0, 100}, ""}; - ConfigurableAxis binCos{"binCos", {100, -1.05, 1.05}, ""}; - ConfigurableAxis binOccupancy{"binOccupancy", {5000, 0, 25000}, ""}; - ConfigurableAxis binQVec{"binQVec", {500, -3, 3}, ""}; - ConfigurableAxis binCentrality{"binCentrality", {101, -1, 100}, ""}; - ConfigurableAxis binPhi{"binPhi", {60, -1.0, 7.0}, ""}; - ConfigurableAxis binEta{"binEta", {80, -0.9, 0.9}, ""}; - ConfigurableAxis binFit0{"binFit0", {100, 0, 50}, ""}; - ConfigurableAxis binFit13{"binFit13", {100, 0, 1.4}, ""}; - ConfigurableAxis binFit24{"binFit24", {100, 0, 10}, ""}; - ConfigurableAxis binTrackPt{"binTrackPt", {100, 0, 100}, ""}; - ConfigurableAxis dbinEta{"dbinEta", {100, -1.6, 1.6}, ""}; - ConfigurableAxis dbinPhi{"dbinPhi", {120, -o2::constants::math::PIHalf, 3 * o2::constants::math::PI / 2}, ""}; - Configurable jetPtMin{"jetPtMin", 5.0, "minimum jet pT cut"}; Configurable jetR{"jetR", 0.2, "jet resolution parameter"}; Configurable randomConeR{"randomConeR", 0.4, "size of random Cone for estimating background fluctuations"}; Configurable randomConeLeadJetDeltaR{"randomConeLeadJetDeltaR", -99.0, "min distance between leading jet axis and random cone (RC) axis; if negative, min distance is set to automatic value of R_leadJet+R_RC "}; Configurable vertexZCut{"vertexZCut", 10.0, "vertex z cut"}; - Configurable> centRange{"centRange", {0, 90}, "centrality region of interest"}; - Configurable cfgSelCentrality{"cfgSelCentrality", true, "Flag for centrality selection"}; // Configurable leadingTrackPtCut{"leadingTrackPtCut", 5.0, "leading jet pT cut"}; Configurable jetAreaFractionMin{"jetAreaFractionMin", -99, "used to make a cut on the jet areas"}; Configurable cfgCentVariant{"cfgCentVariant", false, "Flag for centrality variant 1"}; @@ -101,13 +83,11 @@ struct JetSpectraEseTask { Configurable jetEtaMin{"jetEtaMin", -0.7, "minimum jet pseudorapidity"}; Configurable jetEtaMax{"jetEtaMax", 0.7, "maximum jet pseudorapidity"}; - Configurable numberEventsMixed{"numberEventsMixed", 5, "number of events mixed in ME process"}; Configurable eventSelections{"eventSelections", "sel8FullPbPb", "choose event selection"}; Configurable trackSelections{"trackSelections", "globalTracks", "set track selections"}; Configurable cfgEvSelOccupancy{"cfgEvSelOccupancy", true, "Flag for occupancy cut"}; - Configurable> cfgCutOccupancy{"cfgCutOccupancy", {0, 1000}, "Occupancy cut"}; Configurable> cfgOccupancyPtCut{"cfgOccupancyPtCut", {0, 100}, "pT cut"}; @@ -120,25 +100,29 @@ struct JetSpectraEseTask { Configurable cfgEPRefB{"cfgEPRefB", "TPCpos", "EP reference B"}; Configurable cfgEPRefC{"cfgEPRefC", "TPCneg", "EP reference C"}; - AxisSpec jetPtAxis = {binJetPt, "#it{p}_{T,jet}"}; - AxisSpec dPhiAxis = {bindPhi, "#Delta#phi"}; - AxisSpec eseAxis = {binESE, "#it{q}_{2}"}; - AxisSpec cosAxis = {binCos, ""}; - AxisSpec occAxis = {binOccupancy, "Occupancy"}; - AxisSpec qvecAxis = {binQVec, "Q-vector"}; - AxisSpec centAxis = {binCentrality, "Centrality"}; - AxisSpec phiAxis = {binPhi, "#phi"}; - AxisSpec etaAxis = {binEta, "#eta"}; - AxisSpec detaAxis = {dbinEta, "#Delta#eta"}; - AxisSpec dphiAxis = {dbinPhi, "#Delta#phi"}; - AxisSpec fitAxis0 = {binFit0, "Fit0"}; - AxisSpec fitAxis13 = {binFit13, "Fit13"}; - AxisSpec fitAxis24 = {binFit24, "Fit24"}; - - AxisSpec trackPtAxis = {binTrackPt, "#it{p}_{T}"}; ConfigurableAxis assocTrackPt{"assocTrackPt", {VARIABLE_WIDTH, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0}, "pT of associated track"}; + ConfigurableAxis jetPtAxis{"jetPtAxis", {VARIABLE_WIDTH, 0.0, 5.0, 10.0, 15.0, 20.0, 25.0, 30.0, 40.0, 50.0, 70.0, 100.0, 150.0, 200.0}, "#it{p}_{T,jet} (GeV/#it{c})"}; + ConfigurableAxis dPhiAxis{"dPhiAxis", {60, -o2::constants::math::PI, o2::constants::math::PI}, "#Delta#phi"}; + ConfigurableAxis eseAxis{"eseAxis", {100, 0, 100}, "#it{q}_{2}"}; + Configurable cfgSelCentrality{"cfgSelCentrality", true, "Flag for centrality selection"}; + Configurable> centRange{"centRange", {0, 90}, "centrality region of interest"}; + ConfigurableAxis centAxis{"centAxis", {91, -1, 90}, "centrality"}; + ConfigurableAxis cosAxis{"cosAxis", {50, -1.0, 1.0}, "cos(2(#Psi_{2}^{A}-#Psi_{2}^{B}))"}; + ConfigurableAxis occAxis{"occAxis", {5000, 0, 25000}, "Occupancy"}; + ConfigurableAxis qvecAxis{"qvecAxis", {60, -3, 3}, "Q-vector"}; + ConfigurableAxis phiAxis{"phiAxis", {30, -1.0, 7.0}, "#phi"}; + ConfigurableAxis etaAxis{"etaAxis", {30, -1.0, 1.0}, "#eta"}; + ConfigurableAxis detaAxis{"detaAxis", {60, -1.6, 1.6}, "#Delta#eta"}; + ConfigurableAxis dphiAxis{"dphiAxis", {120, -o2::constants::math::PIHalf, 3 * o2::constants::math::PI / 2}, "#Delta#phi"}; + ConfigurableAxis trackPtAxis{"trackPtAxis", {100, 0, 100}, "#it{p}_{T} (GeV/#it{c})"}; + ConfigurableAxis fitAxis0{"fitAxis0", {100, 0, 50}, ""}; + ConfigurableAxis fitAxis13{"fitAxis13", {100, 0, 1.4}, ""}; + ConfigurableAxis fitAxis24{"fitAxis24", {100, 0, 10}, ""}; ConfigurableAxis rhoAxis{"rhoAxis", {50, 0, 200}, "#rho"}; - ConfigurableAxis vertexZAxis{"vertexZAxis", {50, -10.0, 10.0}, "z vertex"}; + ConfigurableAxis vertexZAxis{"vertexZAxis", {20, -10.0, 10.0}, "z vertex"}; + Configurable numberEventsMixed{"numberEventsMixed", 5, "number of events mixed in ME process"}; + ConfigurableAxis binsCentrality{"binsCentrality", {VARIABLE_WIDTH, 0.0, 10., 30., 50, 70., 100.}, "Mixing bins - centrality"}; + ConfigurableAxis binsZVtx{"binsZVtx", {VARIABLE_WIDTH, -10.0f, -2.5f, 2.5f, 10.0f}, "Mixing bins - z-vertex"}; HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; @@ -157,8 +141,6 @@ struct JetSpectraEseTask { Preslice mcdjetsPerJCollision = o2::aod::jet::collisionId; Preslice tracksPerJCollision = o2::aod::jtrack::collisionId; - ConfigurableAxis binsCentrality{"binsCentrality", {VARIABLE_WIDTH, 0.0, 10., 30., 50, 70., 100.}, "Mixing bins - centrality"}; - ConfigurableAxis binsZVtx{"binsZVtx", {VARIABLE_WIDTH, -10.0f, -2.5f, 2.5f, 10.0f}, "Mixing bins - z-vertex"}; SliceCache cache; using BinningType = ColumnBinningPolicy; BinningType corrBinning{{binsZVtx, binsCentrality}, true}; From 4c9835b59bafdc41fc93928f0c8ad965ff075779 Mon Sep 17 00:00:00 2001 From: Mattia Faggin Date: Mon, 2 Mar 2026 19:26:44 +0100 Subject: [PATCH 134/347] [PWGHF] Fix corr. bkg. Sc tree filling. (#15226) --- .../treeCreatorSigmacCorrBkg.cxx | 48 +++++++++++++++---- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/PWGHF/TableProducer/treeCreatorSigmacCorrBkg.cxx b/PWGHF/TableProducer/treeCreatorSigmacCorrBkg.cxx index 212d6e597a6..57af86a8a16 100644 --- a/PWGHF/TableProducer/treeCreatorSigmacCorrBkg.cxx +++ b/PWGHF/TableProducer/treeCreatorSigmacCorrBkg.cxx @@ -55,6 +55,8 @@ enum Decays { Sigmac2455Pi = 0, LambdacPiPi }; enum DecaysLambdac { PKPi = 0, PiKP }; +enum Reflections { NotReflected = 0, + Reflected }; DECLARE_SOA_COLUMN(Y, y, float); DECLARE_SOA_COLUMN(Pt, pt, float); DECLARE_SOA_COLUMN(Mass, mass, float); @@ -65,6 +67,7 @@ DECLARE_SOA_COLUMN(Decay, decay, int8_t); DECLARE_SOA_COLUMN(DecayLambdac, decayLambdac, int8_t); DECLARE_SOA_COLUMN(MlScoreFirstClass, mlScoreFirstClass, float); /// background score Λc DECLARE_SOA_COLUMN(MlScoreThirdClass, mlScoreThirdClass, float); /// non-prompt score Λc +DECLARE_SOA_COLUMN(IsReflected, isReflected, int8_t); } // namespace hf_sigmac_bkg DECLARE_SOA_TABLE(HfCorrBkgSc, "AOD", "HFCORRBKGSC", hf_sigmac_bkg::Y, @@ -76,7 +79,8 @@ DECLARE_SOA_TABLE(HfCorrBkgSc, "AOD", "HFCORRBKGSC", hf_sigmac_bkg::Decay, hf_sigmac_bkg::DecayLambdac, hf_sigmac_bkg::MlScoreFirstClass, - hf_sigmac_bkg::MlScoreThirdClass); + hf_sigmac_bkg::MlScoreThirdClass, + hf_sigmac_bkg::IsReflected); } // namespace o2::aod struct HfTreeCreatorSigmacCorrBkg { @@ -86,6 +90,7 @@ struct HfTreeCreatorSigmacCorrBkg { /// Selection of candidates Λc+ Configurable selectionFlagLc{"selectionFlagLc", 1, "Selection Flag for Lc"}; Configurable yCandRecoMax{"yCandRecoMax", -1, "Maximum Sc candidate rapidity"}; + Configurable keepReflectedSignals{"keepReflectedSignals", false, "Keep also the reflected signals (i.e. generated pKpi reco as piKp, and viceversa)"}; using RecoLcMc = soa::Join; using RecoScMc = soa::Join; @@ -103,33 +108,56 @@ struct HfTreeCreatorSigmacCorrBkg { float massLc = -1.f; float deltaMass = -1.f; const int8_t isCandPKPiPiKP = hf_sigmac_utils::isDecayToPKPiToPiKP(candLcDauSc, candidateSc); - std::array outputMl{-1., -1.}; + std::array outputMlLcPKPi{-1., -1.}; + std::array outputMlLcPiKP{-1., -1.}; /// rapidity selection on Σc0,++ if (yCandRecoMax >= 0. && std::abs(rapidity) > yCandRecoMax) { return; } /// BDT scores + // reconstructed Λc± → pK-π+ + if (!candLcDauSc.mlProbLcToPKPi().empty()) { + outputMlLcPKPi.at(0) = candLcDauSc.mlProbLcToPKPi()[0]; /// bkg score + outputMlLcPKPi.at(1) = candLcDauSc.mlProbLcToPKPi()[2]; /// non-prompt score + } + // reconstructed Λc± → π+K-p if (!candLcDauSc.mlProbLcToPiKP().empty()) { - outputMl.at(0) = candLcDauSc.mlProbLcToPiKP()[0]; /// bkg score - outputMl.at(1) = candLcDauSc.mlProbLcToPiKP()[2]; /// non-prompt score + outputMlLcPiKP.at(0) = candLcDauSc.mlProbLcToPiKP()[0]; /// bkg score + outputMlLcPiKP.at(1) = candLcDauSc.mlProbLcToPiKP()[2]; /// non-prompt score } - if ((TESTBIT(isCandPKPiPiKP, o2::aod::hf_cand_sigmac::Decays::PKPi)) && std::abs(candLcDauSc.template prong0_as().template mcParticle_as().pdgCode()) == kProton) { + int pdgCodeProng0Abs = std::abs(candLcDauSc.template prong0_as().template mcParticle_as().pdgCode()); + + /// candidates with Λc± reconstructed in the pK-π+ decay + if ((TESTBIT(isCandPKPiPiKP, o2::aod::hf_cand_sigmac::Decays::PKPi))) { + massSc = HfHelper::invMassScRecoLcToPKPi(candidateSc, candLcDauSc); massLc = HfHelper::invMassLcToPKPi(candLcDauSc); deltaMass = massSc - massLc; - /// fill the tree - rowCorrBkgSc(rapidity, candidateSc.pt(), massSc, deltaMass, chargeSc, motherPdg, motherDecay, aod::hf_sigmac_bkg::DecaysLambdac::PKPi, outputMl.at(0), outputMl.at(1)); + if (pdgCodeProng0Abs == kProton) { + /// candidates with reconstructed Λc± → pK-π+ decay that are generated Λc± → pK-π+ (not reflected) + rowCorrBkgSc(rapidity, candidateSc.pt(), massSc, deltaMass, chargeSc, motherPdg, motherDecay, aod::hf_sigmac_bkg::DecaysLambdac::PKPi, outputMlLcPKPi.at(0), outputMlLcPKPi.at(1), aod::hf_sigmac_bkg::Reflections::NotReflected); + } else if (keepReflectedSignals && pdgCodeProng0Abs == kPiPlus) { + /// candidates with reconstructed Λc± → pK-π+ decay that are actually generated Λc± → π+K-p (reflected) + rowCorrBkgSc(rapidity, candidateSc.pt(), massSc, deltaMass, chargeSc, motherPdg, motherDecay, aod::hf_sigmac_bkg::DecaysLambdac::PKPi, outputMlLcPKPi.at(0), outputMlLcPKPi.at(1), aod::hf_sigmac_bkg::Reflections::Reflected); + } } - if ((TESTBIT(isCandPKPiPiKP, o2::aod::hf_cand_sigmac::Decays::PiKP)) && std::abs(candLcDauSc.template prong0_as().template mcParticle_as().pdgCode()) == kPiPlus) { + /// candidates with Λc± reconstructed in the π+K-p decay + if ((TESTBIT(isCandPKPiPiKP, o2::aod::hf_cand_sigmac::Decays::PiKP))) { + massSc = HfHelper::invMassScRecoLcToPiKP(candidateSc, candLcDauSc); massLc = HfHelper::invMassLcToPiKP(candLcDauSc); deltaMass = massSc - massLc; - /// fill the tree - rowCorrBkgSc(rapidity, candidateSc.pt(), massSc, deltaMass, chargeSc, motherPdg, motherDecay, aod::hf_sigmac_bkg::DecaysLambdac::PiKP, outputMl.at(0), outputMl.at(1)); + if (pdgCodeProng0Abs == kPiPlus) { + /// candidates with reconstructed Λc± → π+K-p decay that are generated Λc± → π+K-p (not reflected) + rowCorrBkgSc(rapidity, candidateSc.pt(), massSc, deltaMass, chargeSc, motherPdg, motherDecay, aod::hf_sigmac_bkg::DecaysLambdac::PiKP, outputMlLcPiKP.at(0), outputMlLcPiKP.at(1), aod::hf_sigmac_bkg::Reflections::NotReflected); + } else if (keepReflectedSignals && pdgCodeProng0Abs == kProton) { + /// candidates with reconstructed Λc± → π+K-p decay that are actually generated Λc± → pK-π+ (reflected) + rowCorrBkgSc(rapidity, candidateSc.pt(), massSc, deltaMass, chargeSc, motherPdg, motherDecay, aod::hf_sigmac_bkg::DecaysLambdac::PiKP, outputMlLcPiKP.at(0), outputMlLcPiKP.at(1), aod::hf_sigmac_bkg::Reflections::Reflected); + } } } From 8fcfdb2b4deae38eef3b97bf6b0ab8345d8d8394 Mon Sep 17 00:00:00 2001 From: mcoquet642 <74600025+mcoquet642@users.noreply.github.com> Date: Mon, 2 Mar 2026 19:49:37 +0100 Subject: [PATCH 135/347] [Common] Use helix propagation to compute fwdtrack DCA in fwdtrackextension (#14282) Co-authored-by: Maurice Coquet --- Common/TableProducer/CMakeLists.txt | 4 +- Common/TableProducer/fwdtrackextension.cxx | 79 ++++++++++++++++------ 2 files changed, 62 insertions(+), 21 deletions(-) diff --git a/Common/TableProducer/CMakeLists.txt b/Common/TableProducer/CMakeLists.txt index ea9b96c496f..69cd6084a09 100644 --- a/Common/TableProducer/CMakeLists.txt +++ b/Common/TableProducer/CMakeLists.txt @@ -98,8 +98,8 @@ o2physics_add_dpl_workflow(fwdtrackextension SOURCES fwdtrackextension.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::ReconstructionDataFormats - O2::DetectorsBase - O2::DetectorsCommonDataFormats + O2::GlobalTracking + O2::MCHTracking COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(track-to-collision-associator diff --git a/Common/TableProducer/fwdtrackextension.cxx b/Common/TableProducer/fwdtrackextension.cxx index c554b2c4fbf..18a038c323d 100644 --- a/Common/TableProducer/fwdtrackextension.cxx +++ b/Common/TableProducer/fwdtrackextension.cxx @@ -10,21 +10,30 @@ // or submit itself to any jurisdiction. // -// Task performing forward track DCA computation +// \file fwdtrackextension.cxx +// \brief Task performing forward track DCA computation. +// \author Maurice Coquet, maurice.louis.coquet@cern.ch // +#include "Common/Core/fwdtrackUtilities.h" #include "Common/DataModel/TrackSelectionTables.h" +#include +#include +#include +#include #include #include #include #include #include +#include #include #include #include +#include #include using namespace o2; @@ -34,30 +43,62 @@ using namespace o2::framework::expressions; using SMatrix55 = ROOT::Math::SMatrix>; using SMatrix5 = ROOT::Math::SVector; +using MuonsWithCov = soa::Join; + struct FwdTrackExtension { - Produces extendedTrackQuantities; + Produces fwdDCA; + Configurable geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; + Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + Configurable configCcdbUrl{"configCcdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable refitGlobalMuon{"refitGlobalMuon", true, "Recompute parameters of global muons"}; + + Service fCCDB; + o2::parameters::GRPMagField* grpmag = nullptr; // for run 3, we access GRPMagField from GLO/Config/GRPMagField + int fCurrentRun; // needed to detect if the run changed and trigger update of magnetic field - void process(aod::FwdTracks const& tracks, aod::Collisions const&) + void init(o2::framework::InitContext&) { - for (auto& track : tracks) { - float dcaX = -999; - float dcaY = -999; - if (track.has_collision()) { - if (track.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack || track.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalForwardTrack || track.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { + // Load geometry + fCCDB->setURL(configCcdbUrl); + fCCDB->setCaching(true); + fCCDB->setLocalObjectValidityChecking(); - auto const& collision = track.collision(); - double chi2 = track.chi2(); - SMatrix5 tpars(track.x(), track.y(), track.phi(), track.tgl(), track.signed1Pt()); - std::vector v1; - SMatrix55 tcovs(v1.begin(), v1.end()); - o2::track::TrackParCovFwd pars1{track.z(), tpars, tcovs, chi2}; - pars1.propagateToZlinear(collision.posZ()); + if (!o2::base::GeometryManager::isGeometryLoaded()) { + LOGF(info, "Load geometry from CCDB"); + fCCDB->get(geoPath); + } + } - dcaX = (pars1.getX() - collision.posX()); - dcaY = (pars1.getY() - collision.posY()); - } + void process(aod::Collisions::iterator const& collision, o2::aod::BCsWithTimestamps const& /*...*/, MuonsWithCov const& tracks, aod::MFTTracks const& /*...*/) + { + auto bc = collision.template bc_as(); + if (fCurrentRun != bc.runNumber()) { + grpmag = fCCDB->getForTimeStamp(grpmagPath, bc.timestamp()); + if (grpmag != nullptr) { + LOGF(info, "Init field from GRP"); + o2::base::Propagator::initFieldFromGRP(grpmag); + } + LOGF(info, "Set field for muons"); + o2::mch::TrackExtrap::setField(); + fCurrentRun = bc.runNumber(); + } + const float zField = grpmag->getNominalL3Field(); + for (const auto& track : tracks) { + const auto trackType = track.trackType(); + o2::dataformats::GlobalFwdTrack fwdtrack = o2::aod::fwdtrackutils::getTrackParCovFwd(track, track); + if (refitGlobalMuon && (trackType == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack || trackType == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalForwardTrack)) { + auto muontrack = track.template matchMCHTrack_as(); + auto mfttrack = track.template matchMFTTrack_as(); + o2::dataformats::GlobalFwdTrack propmuon = o2::aod::fwdtrackutils::propagateMuon(muontrack, muontrack, collision, o2::aod::fwdtrackutils::propagationPoint::kToVertex, 0.f, zField); + SMatrix5 tpars(mfttrack.x(), mfttrack.y(), mfttrack.phi(), mfttrack.tgl(), mfttrack.signed1Pt()); + SMatrix55 tcovs{}; + o2::track::TrackParCovFwd mft{mfttrack.z(), tpars, tcovs, mfttrack.chi2()}; + fwdtrack = o2::aod::fwdtrackutils::refitGlobalMuonCov(propmuon, mft); } - extendedTrackQuantities(dcaX, dcaY); + const auto proptrack = o2::aod::fwdtrackutils::propagateTrackParCovFwd(fwdtrack, trackType, collision, o2::aod::fwdtrackutils::propagationPoint::kToDCA, 0.f, zField); + const float dcaX = (proptrack.getX() - collision.posX()); + const float dcaY = (proptrack.getY() - collision.posY()); + fwdDCA(dcaX, dcaY); } } }; From 3b05911bcfe6a9f37fcc03ec45b5765ff43bd268 Mon Sep 17 00:00:00 2001 From: Jeremy Wilkinson Date: Mon, 2 Mar 2026 19:54:41 +0100 Subject: [PATCH 136/347] [Common] TPC PID: Cleanup of CCDB accessors (#13265) --- Common/TableProducer/PID/pidTPC.cxx | 48 ++++++++----------- Common/TableProducer/PID/pidTPCService.cxx | 10 ++-- .../TableProducer/PID/pidTPCServiceRun2.cxx | 8 ++-- Common/Tools/PID/pidTPCModule.h | 45 +++++++---------- 4 files changed, 44 insertions(+), 67 deletions(-) diff --git a/Common/TableProducer/PID/pidTPC.cxx b/Common/TableProducer/PID/pidTPC.cxx index ebb66f8934a..1cdc936a175 100644 --- a/Common/TableProducer/PID/pidTPC.cxx +++ b/Common/TableProducer/PID/pidTPC.cxx @@ -103,17 +103,17 @@ struct tpcPid { // TPC PID Response o2::pid::tpc::Response* response; + // CCDB accessor + Service ccdb; + // Network correction for TPC PID response OnnxModel network; - o2::ccdb::CcdbApi ccdbApi; std::map metadata; - std::map nullmetadata; std::map headers; std::vector speciesNetworkFlags = std::vector(9); std::string networkVersion; // Input parameters - Service ccdb; Configurable paramfile{"param-file", "", "Path to the parametrization object, if empty the parametrization is not taken from file"}; Configurable url{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Configurable ccdbPath{"ccdbPath", "Analysis/PID/TPC/Response", "Path of the TPC parametrization on the CCDB"}; @@ -242,21 +242,18 @@ struct tpcPid { ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); ccdb->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); - ccdbApi.init(url); if (time != 0) { LOGP(info, "Initialising TPC PID response for fixed timestamp {} and reco pass {}:", time, recoPass.value); ccdb->setTimestamp(time); - response = ccdb->getSpecific(path, time, metadata); - headers = ccdbApi.retrieveHeaders(path, metadata, time); + response = ccdb->getSpecific(path, time, metadata, &headers); if (!response) { LOGF(warning, "Unable to find TPC parametrisation for specified pass name - falling back to latest object"); - response = ccdb->getForTimeStamp(path, time); - headers = ccdbApi.retrieveHeaders(path, metadata, time); - networkVersion = headers["NN-Version"]; + response = ccdb->getForTimeStamp(path, time, &headers); if (!response) { LOGF(fatal, "Unable to find any TPC object corresponding to timestamp {}!", time); } } + networkVersion = headers["NN-Version"]; LOG(info) << "Successfully retrieved TPC PID object from CCDB for timestamp " << time << ", period " << headers["LPMProductionTag"] << ", recoPass " << headers["RecoPassName"]; metadata["RecoPassName"] = headers["RecoPassName"]; // Force pass number for NN request to match retrieved BB response->PrintAll(); @@ -274,8 +271,7 @@ struct tpcPid { if (ccdbTimestamp > 0) { /// Fetching network for specific timestamp LOG(info) << "Fetching network for timestamp: " << ccdbTimestamp.value; - bool retrieveSuccess = ccdbApi.retrieveBlob(networkPathCCDB.value, ".", metadata, ccdbTimestamp.value, false, networkPathLocally.value); - headers = ccdbApi.retrieveHeaders(networkPathCCDB.value, metadata, ccdbTimestamp.value); + bool retrieveSuccess = ccdb->getCCDBAccessor().retrieveBlob(networkPathCCDB.value, ".", metadata, ccdbTimestamp.value, false, networkPathLocally.value, "", "", &headers); networkVersion = headers["NN-Version"]; if (retrieveSuccess) { network.initModel(networkPathLocally.value, enableNetworkOptimizations.value, networkSetNumThreads.value, strtoul(headers["Valid-From"].c_str(), NULL, 0), strtoul(headers["Valid-Until"].c_str(), NULL, 0)); @@ -318,17 +314,15 @@ struct tpcPid { } else { LOGP(info, "Retrieving TPC Response for timestamp {} and recoPass {}:", bc.timestamp(), recoPass.value); } - response = ccdb->getSpecific(ccdbPath.value, bc.timestamp(), metadata); - headers = ccdbApi.retrieveHeaders(ccdbPath.value, metadata, bc.timestamp()); - networkVersion = headers["NN-Version"]; + response = ccdb->getSpecific(ccdbPath.value, bc.timestamp(), metadata, &headers); if (!response) { LOGP(warning, "!! Could not find a valid TPC response object for specific pass name {}! Falling back to latest uploaded object.", metadata["RecoPassName"]); - headers = ccdbApi.retrieveHeaders(ccdbPath.value, nullmetadata, bc.timestamp()); - response = ccdb->getForTimeStamp(ccdbPath.value, bc.timestamp()); + response = ccdb->getForTimeStamp(ccdbPath.value, bc.timestamp(), &headers); if (!response) { LOGP(fatal, "Could not find ANY TPC response object for the timestamp {}!", bc.timestamp()); } } + networkVersion = headers["NN-Version"]; LOG(info) << "Successfully retrieved TPC PID object from CCDB for timestamp " << bc.timestamp() << ", period " << headers["LPMProductionTag"] << ", recoPass " << headers["RecoPassName"]; metadata["RecoPassName"] = headers["RecoPassName"]; // Force pass number for NN request to match retrieved BB response->PrintAll(); @@ -336,14 +330,13 @@ struct tpcPid { if (bc.timestamp() < network.getValidityFrom() || bc.timestamp() > network.getValidityUntil()) { // fetches network only if the runnumbers change LOG(info) << "Fetching network for timestamp: " << bc.timestamp(); - bool retrieveSuccess = ccdbApi.retrieveBlob(networkPathCCDB.value, ".", metadata, bc.timestamp(), false, networkPathLocally.value); - headers = ccdbApi.retrieveHeaders(networkPathCCDB.value, metadata, bc.timestamp()); + bool retrieveSuccess = ccdb->getCCDBAccessor().retrieveBlob(networkPathCCDB.value, ".", metadata, bc.timestamp(), false, networkPathLocally.value, "", "", &headers); networkVersion = headers["NN-Version"]; if (retrieveSuccess) { network.initModel(networkPathLocally.value, enableNetworkOptimizations.value, networkSetNumThreads.value, strtoul(headers["Valid-From"].c_str(), NULL, 0), strtoul(headers["Valid-Until"].c_str(), NULL, 0)); std::vector dummyInput(network.getNumInputNodes(), 1.); network.evalModel(dummyInput); - LOGP(info, "Retrieved NN corrections for production tag {}, pass number {}, NN-Version number{}", headers["LPMProductionTag"], headers["RecoPassName"], headers["NN-Version"]); + LOGP(info, "Retrieved NN corrections for production tag {}, pass number {}, NN-Version number {}", headers["LPMProductionTag"], headers["RecoPassName"], headers["NN-Version"]); } else { LOG(fatal) << "No valid NN object found matching retrieved Bethe-Bloch parametrisation for pass " << metadata["RecoPassName"] << ". Please ensure that the requested pass has dedicated NN corrections available"; } @@ -553,12 +546,10 @@ struct tpcPid { } else { LOGP(info, "Retrieving TPC Response for timestamp {} and recoPass {}:", bc.timestamp(), recoPass.value); } - response = ccdb->getSpecific(ccdbPath.value, bc.timestamp(), metadata); - headers = ccdbApi.retrieveHeaders(ccdbPath.value, metadata, bc.timestamp()); + response = ccdb->getSpecific(ccdbPath.value, bc.timestamp(), metadata, &headers); if (!response) { LOGP(warning, "!! Could not find a valid TPC response object for specific pass name {}! Falling back to latest uploaded object.", metadata["RecoPassName"]); - response = ccdb->getForTimeStamp(ccdbPath.value, bc.timestamp()); - headers = ccdbApi.retrieveHeaders(ccdbPath.value, nullmetadata, bc.timestamp()); + response = ccdb->getForTimeStamp(ccdbPath.value, bc.timestamp(), &headers); if (!response) { LOGP(fatal, "Could not find ANY TPC response object for the timestamp {}!", bc.timestamp()); } @@ -651,12 +642,11 @@ struct tpcPid { } else { LOGP(info, "Retrieving TPC Response for timestamp {} and recoPass {}:", bc.timestamp(), recoPass.value); } - response = ccdb->getSpecific(ccdbPath.value, bc.timestamp(), metadata); - headers = ccdbApi.retrieveHeaders(ccdbPath.value, metadata, bc.timestamp()); + response = ccdb->getSpecific(ccdbPath.value, bc.timestamp(), metadata, &headers); + if (!response) { LOGP(warning, "!! Could not find a valid TPC response object for specific pass name {}! Falling back to latest uploaded object.", metadata["RecoPassName"]); - response = ccdb->getForTimeStamp(ccdbPath.value, bc.timestamp()); - headers = ccdbApi.retrieveHeaders(ccdbPath.value, nullmetadata, bc.timestamp()); + response = ccdb->getForTimeStamp(ccdbPath.value, bc.timestamp(), &headers); if (!response) { LOGP(fatal, "Could not find ANY TPC response object for the timestamp {}!", bc.timestamp()); } @@ -737,10 +727,10 @@ struct tpcPid { } else { LOGP(info, "Retrieving TPC Response for timestamp {} and recoPass {}:", bc.timestamp(), recoPass.value); } - response = ccdb->getSpecific(ccdbPath.value, bc.timestamp(), metadata); + response = ccdb->getSpecific(ccdbPath.value, bc.timestamp(), metadata, &headers); if (!response) { LOGP(warning, "!! Could not find a valid TPC response object for specific pass name {}! Falling back to latest uploaded object.", metadata["RecoPassName"]); - response = ccdb->getForTimeStamp(ccdbPath.value, bc.timestamp()); + response = ccdb->getForTimeStamp(ccdbPath.value, bc.timestamp(), &headers); if (!response) { LOGP(fatal, "Could not find ANY TPC response object for the timestamp {}!", bc.timestamp()); } diff --git a/Common/TableProducer/PID/pidTPCService.cxx b/Common/TableProducer/PID/pidTPCService.cxx index 6ad86916c1f..974f29b2106 100644 --- a/Common/TableProducer/PID/pidTPCService.cxx +++ b/Common/TableProducer/PID/pidTPCService.cxx @@ -47,7 +47,6 @@ struct pidTpcService { // CCDB boilerplate declarations o2::framework::Configurable ccdburl{"ccdburl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Service ccdb; - o2::ccdb::CcdbApi ccdbApi; o2::aod::pid::pidTPCProducts products; o2::aod::pid::pidTPCConfigurables pidTPCopts; @@ -61,25 +60,24 @@ struct pidTpcService { ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); ccdb->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); - ccdbApi.init(ccdburl.value); // task-specific - pidTPC.init(ccdb, ccdbApi, initContext, pidTPCopts, metadataInfo); + pidTPC.init(ccdb, initContext, pidTPCopts, metadataInfo); } void processTracksIU(soa::Join const& collisions, soa::Join const& tracks, aod::BCsWithTimestamps const& bcs) { - pidTPC.process(ccdb, ccdbApi, bcs, collisions, tracks, static_cast(nullptr), products); + pidTPC.process(ccdb, bcs, collisions, tracks, static_cast(nullptr), products); } void processTracksMCIU(soa::Join const& collisions, soa::Join const& tracks, aod::BCsWithTimestamps const& bcs, aod::McParticles const&) { - pidTPC.process(ccdb, ccdbApi, bcs, collisions, tracks, static_cast(nullptr), products); + pidTPC.process(ccdb, bcs, collisions, tracks, static_cast(nullptr), products); } void processTracksIUWithTracksQA(soa::Join const& collisions, soa::Join const& tracks, aod::BCsWithTimestamps const& bcs, aod::TracksQAVersion const& tracksQA) { - pidTPC.process(ccdb, ccdbApi, bcs, collisions, tracks, tracksQA, products); + pidTPC.process(ccdb, bcs, collisions, tracks, tracksQA, products); } PROCESS_SWITCH(pidTpcService, processTracksIU, "Process TracksIU (Run 3)", true); diff --git a/Common/TableProducer/PID/pidTPCServiceRun2.cxx b/Common/TableProducer/PID/pidTPCServiceRun2.cxx index 184fb4eb6e0..642f3bf08b7 100644 --- a/Common/TableProducer/PID/pidTPCServiceRun2.cxx +++ b/Common/TableProducer/PID/pidTPCServiceRun2.cxx @@ -47,7 +47,6 @@ struct pidTpcServiceRun2 { // CCDB boilerplate declarations o2::framework::Configurable ccdburl{"ccdburl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Service ccdb; - o2::ccdb::CcdbApi ccdbApi; o2::aod::pid::pidTPCProducts products; o2::aod::pid::pidTPCConfigurables pidTPCopts; @@ -61,20 +60,19 @@ struct pidTpcServiceRun2 { ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); ccdb->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); - ccdbApi.init(ccdburl.value); // task-specific - pidTPC.init(ccdb, ccdbApi, initContext, pidTPCopts, metadataInfo); + pidTPC.init(ccdb, initContext, pidTPCopts, metadataInfo); } void processTracks(soa::Join const& collisions, soa::Join const& tracks, aod::BCsWithTimestamps const& bcs) { - pidTPC.process(ccdb, ccdbApi, bcs, collisions, tracks, static_cast(nullptr), products); + pidTPC.process(ccdb, bcs, collisions, tracks, static_cast(nullptr), products); } void processTracksMC(soa::Join const& collisions, soa::Join const& tracks, aod::BCsWithTimestamps const& bcs, aod::McParticles const&) { - pidTPC.process(ccdb, ccdbApi, bcs, collisions, tracks, static_cast(nullptr), products); + pidTPC.process(ccdb, bcs, collisions, tracks, static_cast(nullptr), products); } PROCESS_SWITCH(pidTpcServiceRun2, processTracks, "Process Tracks", true); diff --git a/Common/Tools/PID/pidTPCModule.h b/Common/Tools/PID/pidTPCModule.h index 990ab5b7266..efe9dc56ded 100644 --- a/Common/Tools/PID/pidTPCModule.h +++ b/Common/Tools/PID/pidTPCModule.h @@ -209,7 +209,6 @@ class pidTPCModule // Network correction for TPC PID response ml::OnnxModel network; std::map metadata; - std::map nullmetadata; std::map headers; std::vector speciesNetworkFlags = std::vector(9); std::string networkVersion; @@ -226,8 +225,8 @@ class pidTPCModule Str_dEdx_correction str_dedx_correction; //__________________________________________________ - template - void init(TCCDB& ccdb, TCCDBApi& ccdbApi, TContext& context, TpidTPCOpts const& external_pidtpcopts, TMetadataInfo const& metadataInfo) + template + void init(TCCDB& ccdb, TContext& context, TpidTPCOpts const& external_pidtpcopts, TMetadataInfo const& metadataInfo) { // read in configurations from the task where it's used pidTPCopts = external_pidtpcopts; @@ -369,17 +368,15 @@ class pidTPCModule if (time != 0) { LOGP(info, "Initialising TPC PID response for fixed timestamp {} and reco pass {}:", time, pidTPCopts.recoPass.value); ccdb->setTimestamp(time); - response = ccdb->template getSpecific(path, time, metadata); - headers = ccdbApi.retrieveHeaders(path, metadata, time); + response = ccdb->template getSpecific(path, time, metadata, &headers); if (!response) { LOGF(warning, "Unable to find TPC parametrisation for specified pass name - falling back to latest object"); - response = ccdb->template getForTimeStamp(path, time); - headers = ccdbApi.retrieveHeaders(path, metadata, time); - networkVersion = headers["NN-Version"]; + response = ccdb->template getForTimeStamp(path, time, &headers); if (!response) { LOGF(fatal, "Unable to find any TPC object corresponding to timestamp {}!", time); } } + networkVersion = headers["NN-Version"]; LOG(info) << "Successfully retrieved TPC PID object from CCDB for timestamp " << time << ", period " << headers["LPMProductionTag"] << ", recoPass " << headers["RecoPassName"]; metadata["RecoPassName"] = headers["RecoPassName"]; // Force pass number for NN request to match retrieved BB o2::parameters::GRPLHCIFData* grpo = ccdb->template getForTimeStamp(pidTPCopts.cfgPathGrpLhcIf.value, time); @@ -407,8 +404,7 @@ class pidTPCModule if (pidTPCopts.ccdbTimestamp > 0) { /// Fetching network for specific timestamp LOG(info) << "Fetching network for timestamp: " << pidTPCopts.ccdbTimestamp.value; - bool retrieveSuccess = ccdbApi.retrieveBlob(pidTPCopts.networkPathCCDB.value, ".", metadata, pidTPCopts.ccdbTimestamp.value, false, pidTPCopts.networkPathLocally.value); - headers = ccdbApi.retrieveHeaders(pidTPCopts.networkPathCCDB.value, metadata, pidTPCopts.ccdbTimestamp.value); + bool retrieveSuccess = ccdb->getCCDBAccessor().retrieveBlob(pidTPCopts.networkPathCCDB.value, ".", metadata, pidTPCopts.ccdbTimestamp.value, false, pidTPCopts.networkPathLocally.value, "", "", &headers); networkVersion = headers["NN-Version"]; if (retrieveSuccess) { network.initModel(pidTPCopts.networkPathLocally.value, pidTPCopts.enableNetworkOptimizations.value, pidTPCopts.networkSetNumThreads.value, strtoul(headers["Valid-From"].c_str(), NULL, 0), strtoul(headers["Valid-Until"].c_str(), NULL, 0)); @@ -439,8 +435,8 @@ class pidTPCModule } // end init //__________________________________________________ - template - std::vector createNetworkPrediction(TCCDB& ccdb, TCCDBApi& ccdbApi, soa::Join const& collisions, M const& mults, T const& tracks, B const& bcs, const size_t size) + template + std::vector createNetworkPrediction(TCCDB& ccdb, soa::Join const& collisions, M const& mults, T const& tracks, B const& bcs, const size_t size) { std::vector network_prediction; @@ -455,13 +451,11 @@ class pidTPCModule } else { LOGP(info, "Retrieving TPC Response for timestamp {} and recoPass {}:", bc.timestamp(), pidTPCopts.recoPass.value); } - response = ccdb->template getSpecific(pidTPCopts.ccdbPath.value, bc.timestamp(), metadata); - headers = ccdbApi.retrieveHeaders(pidTPCopts.ccdbPath.value, metadata, bc.timestamp()); + response = ccdb->template getSpecific(pidTPCopts.ccdbPath.value, bc.timestamp(), metadata, &headers); networkVersion = headers["NN-Version"]; if (!response) { LOGP(warning, "!! Could not find a valid TPC response object for specific pass name {}! Falling back to latest uploaded object.", metadata["RecoPassName"]); - headers = ccdbApi.retrieveHeaders(pidTPCopts.ccdbPath.value, nullmetadata, bc.timestamp()); - response = ccdb->template getForTimeStamp(pidTPCopts.ccdbPath.value, bc.timestamp()); + response = ccdb->template getForTimeStamp(pidTPCopts.ccdbPath.value, bc.timestamp(), &headers); if (!response) { LOGP(fatal, "Could not find ANY TPC response object for the timestamp {}!", bc.timestamp()); } @@ -485,14 +479,13 @@ class pidTPCModule if (bc.timestamp() < network.getValidityFrom() || bc.timestamp() > network.getValidityUntil()) { // fetches network only if the runnumbers change LOG(info) << "Fetching network for timestamp: " << bc.timestamp(); - bool retrieveSuccess = ccdbApi.retrieveBlob(pidTPCopts.networkPathCCDB.value, ".", metadata, bc.timestamp(), false, pidTPCopts.networkPathLocally.value); - headers = ccdbApi.retrieveHeaders(pidTPCopts.networkPathCCDB.value, metadata, bc.timestamp()); + bool retrieveSuccess = ccdb->getCCDBAccessor().retrieveBlob(pidTPCopts.networkPathCCDB.value, ".", metadata, bc.timestamp(), false, pidTPCopts.networkPathLocally.value, "", "", &headers); networkVersion = headers["NN-Version"]; if (retrieveSuccess) { network.initModel(pidTPCopts.networkPathLocally.value, pidTPCopts.enableNetworkOptimizations.value, pidTPCopts.networkSetNumThreads.value, strtoul(headers["Valid-From"].c_str(), NULL, 0), strtoul(headers["Valid-Until"].c_str(), NULL, 0)); std::vector dummyInput(network.getNumInputNodes(), 1.); network.evalModel(dummyInput); - LOGP(info, "Retrieved NN corrections for production tag {}, pass number {}, NN-Version number{}", headers["LPMProductionTag"], headers["RecoPassName"], headers["NN-Version"]); + LOGP(info, "Retrieved NN corrections for production tag {}, pass number {}, NN-Version number {}", headers["LPMProductionTag"], headers["RecoPassName"], headers["NN-Version"]); } else { LOG(fatal) << "No valid NN object found matching retrieved Bethe-Bloch parametrisation for pass " << metadata["RecoPassName"] << ". Please ensure that the requested pass has dedicated NN corrections available"; } @@ -677,7 +670,7 @@ class pidTPCModule nSigma = (tpcSignal / expSignal - network_prediction[NumOutputNodesAsymmetricSigma * (count_tracks + tracksForNet_size * pid)]) / (network_prediction[NumOutputNodesAsymmetricSigma * (count_tracks + tracksForNet_size * pid)] - network_prediction[NumOutputNodesAsymmetricSigma * (count_tracks + tracksForNet_size * pid) + 2]); } } else { - LOGF(fatal, "Network output-dimensions incompatible!"); + LOGF(fatal, "Network output dimensions incompatible!"); } } else { nSigma = response->GetNumberOfSigmaMCTunedAtMultiplicity(multTPC, trk, pid, tpcSignal); @@ -689,8 +682,8 @@ class pidTPCModule }; //__________________________________________________ - template - void process(TCCDB& ccdb, TCCDBApi& ccdbApi, TBCs const& bcs, soa::Join const& cols, TTracks const& tracks, TTracksQA const& tracksQA, TProducts& products) + template + void process(TCCDB& ccdb, TBCs const& bcs, soa::Join const& cols, TTracks const& tracks, TTracksQA const& tracksQA, TProducts& products) { if (tracks.size() == 0) { return; // empty protection @@ -753,7 +746,7 @@ class pidTPCModule std::vector network_prediction; if (pidTPCopts.useNetworkCorrection) { - network_prediction = createNetworkPrediction(ccdb, ccdbApi, cols, pidmults, tracks, bcs, tracksForNet_size); + network_prediction = createNetworkPrediction(ccdb, cols, pidmults, tracks, bcs, tracksForNet_size); } uint64_t count_tracks = 0; @@ -883,12 +876,10 @@ class pidTPCModule } else { LOGP(info, "Retrieving TPC Response for timestamp {} and recoPass {}:", bc.timestamp(), pidTPCopts.recoPass.value); } - response = ccdb->template getSpecific(pidTPCopts.ccdbPath.value, bc.timestamp(), metadata); - headers = ccdbApi.retrieveHeaders(pidTPCopts.ccdbPath.value, metadata, bc.timestamp()); + response = ccdb->template getSpecific(pidTPCopts.ccdbPath.value, bc.timestamp(), metadata, &headers); if (!response) { LOGP(warning, "!! Could not find a valid TPC response object for specific pass name {}! Falling back to latest uploaded object.", metadata["RecoPassName"]); - response = ccdb->template getForTimeStamp(pidTPCopts.ccdbPath.value, bc.timestamp()); - headers = ccdbApi.retrieveHeaders(pidTPCopts.ccdbPath.value, nullmetadata, bc.timestamp()); + response = ccdb->template getForTimeStamp(pidTPCopts.ccdbPath.value, bc.timestamp(), &headers); if (!response) { LOGP(fatal, "Could not find ANY TPC response object for the timestamp {}!", bc.timestamp()); } From 8c14235d49f276c8fccc8e38f3faa73ce5e53a0f Mon Sep 17 00:00:00 2001 From: amatyja Date: Mon, 2 Mar 2026 20:42:45 +0100 Subject: [PATCH 137/347] [PWGUD] Few generator ID LOGs added (#15216) --- PWGUD/DataModel/TauThreeProngEventTables.h | 4 +- PWGUD/TableProducer/SGCandProducer.cxx | 9 +- .../tauThreeProngEventTableProducer.cxx | 416 ++++++++++-------- 3 files changed, 250 insertions(+), 179 deletions(-) diff --git a/PWGUD/DataModel/TauThreeProngEventTables.h b/PWGUD/DataModel/TauThreeProngEventTables.h index b670e8b7f69..61cc184cbdb 100644 --- a/PWGUD/DataModel/TauThreeProngEventTables.h +++ b/PWGUD/DataModel/TauThreeProngEventTables.h @@ -84,7 +84,7 @@ DECLARE_SOA_COLUMN(TrkTOFnSigmaMu, trkTOFnSigmaMu, float[6]); DECLARE_SOA_COLUMN(TrkTOFchi2, trkTOFchi2, float[6]); // truth event DECLARE_SOA_COLUMN(TrueChannel, trueChannel, int); -DECLARE_SOA_COLUMN(TrueHasRecoColl, trueHasRecoColl, bool); +// DECLARE_SOA_COLUMN(TrueHasRecoColl, trueHasRecoColl, bool); // DECLARE_SOA_COLUMN(TruePosX, truePosX, float); // DECLARE_SOA_COLUMN(TruePosY, truePosY, float); DECLARE_SOA_COLUMN(TruePosZ, truePosZ, float); @@ -145,7 +145,7 @@ DECLARE_SOA_TABLE(TrueTauFourTracks, "AOD", "TRUETAU", tautree::TrkTOFbeta, tautree::TrkTOFnSigmaEl, tautree::TrkTOFnSigmaPi, tautree::TrkTOFnSigmaKa, tautree::TrkTOFnSigmaPr, tautree::TrkTOFnSigmaMu, tautree::TrkTOFchi2, tautree::TrueChannel, - tautree::TrueHasRecoColl, + // tautree::TrueHasRecoColl, tautree::TruePosZ, tautree::TrueTauPx, tautree::TrueTauPy, tautree::TrueTauPz, tautree::TrueDaugPx, tautree::TrueDaugPy, tautree::TrueDaugPz, diff --git a/PWGUD/TableProducer/SGCandProducer.cxx b/PWGUD/TableProducer/SGCandProducer.cxx index c3cb33cb43e..888dbfb608e 100644 --- a/PWGUD/TableProducer/SGCandProducer.cxx +++ b/PWGUD/TableProducer/SGCandProducer.cxx @@ -285,6 +285,7 @@ struct SGCandProducer { { if (verboseInfo) LOGF(debug, " collision %d", collision.globalIndex()); + getHist(TH1, histdir + "/Stat")->Fill(0., 1.); // reject collisions at TF boundaries if (rejectAtTFBoundary && !collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) { @@ -389,6 +390,8 @@ struct SGCandProducer { fitInfo.BBFV0Apf, fitInfo.BGFV0Apf, fitInfo.BBFDDApf, fitInfo.BBFDDCpf, fitInfo.BGFDDApf, fitInfo.BGFDDCpf); outputCollisionSelExtras(chFT0A, chFT0C, chFDDA, chFDDC, chFV0A, occ, ir, trs, trofs, hmpr, tfb, itsROFb, sbp, zVtxFT0vPv, vtxITSTPC, collision.rct_raw()); + if (verboseInfo) + LOGF(info, "%s Coll GID %d", histdir, collision.globalIndex()); outputCollsLabels(collision.globalIndex()); if (newbc.has_zdc()) { auto zdc = newbc.zdc(); @@ -481,7 +484,7 @@ struct SGCandProducer { if (std::find(generatorIds->begin(), generatorIds->end(), mccol.getGeneratorId()) != generatorIds->end()) { if (verboseInfo) - LOGF(info, "Event with good generatorId"); + LOGF(info, "Event with good generatorId %d", mccol.getGeneratorId()); processReco(std::string("MCreco"), collision, bcs, tracks, fwdtracks, fv0as, ft0s, fdds); } } @@ -688,6 +691,8 @@ struct McSGCandProducer { // loop over McCollisions and UDCCs simultaneously auto mccol = mccols.iteratorAt(0); auto mcOfInterest = std::find(generatorIds->begin(), generatorIds->end(), mccol.getGeneratorId()) != generatorIds->end(); + if (verboseInfoMC) + LOGF(info, "Is Generator ID OK %d, MCcoll GenId %d, SubGenID %d, SourceId %d, Set in json ID %d", mcOfInterest, mccol.getGeneratorId(), mccol.getSubGeneratorId(), mccol.getSourceId(), *(generatorIds->begin())); auto lastmccol = mccols.iteratorAt(mccols.size() - 1); auto mccolAtEnd = false; @@ -701,6 +706,7 @@ struct McSGCandProducer { bool goon = true; while (goon) { auto globBC = mccol.bc_as().globalBC(); + // check if dgcand has an associated McCollision if (sgcand.has_collision()) { auto sgcandCol = sgcand.collision_as(); @@ -875,6 +881,7 @@ struct McSGCandProducer { LOGF(info, "Number of McCollisions %d", mccols.size()); LOGF(info, "Number of SG candidates %d", sgcands.size()); LOGF(info, "Number of UD tracks %d", udtracks.size()); + LOGF(info, "Number of McParticles %d", mcparts.size()); } if (mccols.size() > 0) { if (sgcands.size() > 0) { diff --git a/PWGUD/TableProducer/tauThreeProngEventTableProducer.cxx b/PWGUD/TableProducer/tauThreeProngEventTableProducer.cxx index baea03e1d59..1900e1a1232 100644 --- a/PWGUD/TableProducer/tauThreeProngEventTableProducer.cxx +++ b/PWGUD/TableProducer/tauThreeProngEventTableProducer.cxx @@ -67,7 +67,8 @@ enum MyRecoProblem { NO_PROBLEM = 0, // no problem MANY_RECO = 1, // more than 1 reconstructed collision TOO_MANY_DAUGHTERS = 2, // more than 6 daughters from 2 taus - TWO_TRACKS = 3 // more than 1 associated track to MC particle (tau daughter) + TWO_TRACKS = 3, // more than 1 associated track to MC particle (tau daughter) + NO_TRACK = 4 // No associated track to MC particle (tau daughter) }; enum MyParticle { @@ -1019,9 +1020,10 @@ struct TauThreeProngEventTableProducer { const int sixTracks = 6; const int oneProng = 1; const int threeProng = 3; + const float epsilon = 0.000001; if (verbose) - LOGF(info, "0. UDMcCollision size %d, Collisions size %d, UDtracks %d, UDMcParticles %d", mcCollisions.size(), collisions.size(), tracks.size(), mcParticles.size()); + LOGF(info, " UDMcCollision size %d, Collisions size %d, UDtracks %d, UDMcParticles %d", mcCollisions.size(), collisions.size(), tracks.size(), mcParticles.size()); // temporary variables float tmpRapidity = -999.; @@ -1038,6 +1040,8 @@ struct TauThreeProngEventTableProducer { // start loop over generated collisions for (const auto& mccoll : mcCollisions) { + if (verbose) + LOGF(info, "-- McColl GID %d", mccoll.globalIndex()); registrySkim.get(HIST("skim/efficiencyMC"))->Fill(0., 1.); // all MC collisions // set up default values per colission @@ -1052,14 +1056,16 @@ struct TauThreeProngEventTableProducer { partFromTauInEta = true; // get particles associated to generated collision + // auto const& tmpPartsFromMcColl = mcParticles.sliceBy(partPerMcCollision, (int64_t)mccoll.globalIndex()); auto const& tmpPartsFromMcColl = mcParticles.sliceBy(partPerMcCollision, mccoll.globalIndex()); + if (verbose) - LOGF(info, "1. part from MC coll %d", tmpPartsFromMcColl.size()); + LOGF(info, "- part from MC coll %d", tmpPartsFromMcColl.size()); int countMothers = 0; const int desiredNMothers = 2; for (const auto& particle : tmpPartsFromMcColl) { if (verbose) - LOGF(info, "2. MC part pdg %d", particle.pdgCode()); + LOGF(info, "-- MC part pdg %d", particle.pdgCode()); if (std::abs(particle.pdgCode()) != kTauMinus) continue; // 15 = tau_minus // if (std::abs(particle.pdgCode()) != 15) continue; // 15 = tau_minus @@ -1073,7 +1079,7 @@ struct TauThreeProngEventTableProducer { trueTauPhi[countMothers] = RecoDecay::phi(particle.px(), particle.py()); if (verbose) - LOGF(info, "tau P(%f,%f,%f), e %f, y %f", particle.px(), particle.py(), particle.pz(), particle.e(), tmpRapidity); + LOGF(info, "-- tau P(%f,%f,%f), e %f, y %f", particle.px(), particle.py(), particle.pz(), particle.e(), tmpRapidity); registrySkim.get(HIST("skim/tauRapidityMC"))->Fill(tmpRapidity); registrySkim.get(HIST("skim/tauPhiMC"))->Fill(trueTauPhi[countMothers]); registrySkim.get(HIST("skim/tauEtaMC"))->Fill(trueTauEta[countMothers]); @@ -1081,15 +1087,16 @@ struct TauThreeProngEventTableProducer { if (std::abs(tmpRapidity) > trkEtacut) { // 0.9 tauInRapidity = false; if (verbose) - LOGF(info, "tau y %f", tmpRapidity); + LOGF(info, "--- tau y %f", tmpRapidity); } // rapidity check } // number of taus countMothers++; } // end of loop over MC paricles + // LOGF(info, "1b. countMothers %d", countMothers); registrySkim.get(HIST("skim/nTauMC"))->Fill(countMothers); if (countMothers != desiredNMothers) { // 2 if (verbose) - LOGF(info, "Truth collision has number of mother particles (taus) %d different than 2. Jump to the next MC event.", countMothers); + LOGF(info, "-- Truth collision has number of mother particles (taus) %d different than 2. Jump to the next MC event.", countMothers); continue; } @@ -1097,7 +1104,7 @@ struct TauThreeProngEventTableProducer { if (!tauInRapidity) { // tau NOT in rapidity -> continue if (verbose) - LOGF(info, "At least one mother particle (taus) out of rapidity (|y|<0.9). Jump to the next MC event."); + LOGF(info, "-- At least one mother particle (taus) out of rapidity (|y|<0.9). Jump to the next MC event."); continue; } @@ -1149,9 +1156,10 @@ struct TauThreeProngEventTableProducer { // check number of charged particles in MC event if ((nChargedDaughtersTau[0] + nChargedDaughtersTau[1] != fourTracks) && (nChargedDaughtersTau[0] + nChargedDaughtersTau[1] != sixTracks)) { if (verbose) - LOGF(info, "Different from 4/6 charged particles (%d) from both taus. Jump to the next MC event.", nChargedDaughtersTau[0] + nChargedDaughtersTau[1]); + LOGF(info, "-- Different from 4/6 charged particles (%d) from both taus. Jump to the next MC event.", nChargedDaughtersTau[0] + nChargedDaughtersTau[1]); continue; } + registrySkim.get(HIST("skim/efficiencyMC"))->Fill(3., 1.); // 1+3 (3+3) topology if (nChargedDaughtersTau[0] + nChargedDaughtersTau[1] == fourTracks) { // 4 registrySkim.get(HIST("skim/efficiencyMC"))->Fill(4., 1.); @@ -1161,9 +1169,10 @@ struct TauThreeProngEventTableProducer { if (!partFromTauInEta) { if (verbose) - LOGF(info, "At least one daughter particle from taus out of pseudo-rapidity (|eta|<0.9). Jump to the next MC event."); + LOGF(info, "-- At least one daughter particle from taus out of pseudo-rapidity (|eta|<0.9). Jump to the next MC event."); continue; } + registrySkim.get(HIST("skim/efficiencyMC"))->Fill(6., 1.); // particles from tau in |eta|<0.9 if (nChargedDaughtersTau[0] + nChargedDaughtersTau[1] == fourTracks) { // 4 registrySkim.get(HIST("skim/efficiencyMC"))->Fill(7., 1.); @@ -1179,12 +1188,12 @@ struct TauThreeProngEventTableProducer { zerothTau = 0; // prepare local variables for output table - int32_t runNumber = -999; + int32_t runNumber = -999; // when no reconstructed collisions is associated to MCcoll it should remain = -999 int bc = -999; // int nTrks[3] = {-999, -999, -999}; // totalTracks, numContrib, globalNonPVtracks int totalTracks = -999; int8_t nPVcontrib = -99; - int rct = -999; + int rct = -99; // float vtxPos[3] = {-999., -999., -999.}; float zVertex = -999; @@ -1232,10 +1241,10 @@ struct TauThreeProngEventTableProducer { // float tofEP[2] = {-999, -999}; float chi2TOF[6] = {-999., -999., -999., -999., -999., -999.}; - bool trueHasRecoColl = false; - float trueDaugX[6] = {-999., -999., -999., -999., -999., -999.}; - float trueDaugY[6] = {-999., -999., -999., -999., -999., -999.}; - float trueDaugZ[6] = {-999., -999., -999., -999., -999., -999.}; + // bool trueHasRecoColl = false; + float trueDaugX[6] = {-998., -998., -998., -998., -998., -998.}; + float trueDaugY[6] = {-998., -998., -998., -998., -998., -998.}; + float trueDaugZ[6] = {-998., -998., -998., -998., -998., -998.}; int trueDaugPdgCode[6] = {-999, -999, -999, -999, -999, -999}; // bool problem = false; MyRecoProblem problem = NO_PROBLEM; @@ -1256,180 +1265,233 @@ struct TauThreeProngEventTableProducer { else if (nPi == sixTracks) // 6 trueChannel = 4; + // LOGF(info, "MC Coll global index %d", mccoll.globalIndex()); + // LOGF(info, "2. UDMcCollision size %d, Collisions size %d, UDtracks %d, UDMcParticles %d", mcCollisions.size(), collisions.size(), tracks.size(), mcParticles.size()); + // for (const auto& coll : collisions) { + // LOGF(info, "coll global index %d", coll.globalIndex()); + // } + // find reconstructed collisions associated to the generated collision auto const& collFromMcColls = collisions.sliceBy(colPerMcCollision, mccoll.globalIndex()); if (verbose) - LOGF(info, "coll from MC Coll %d", collFromMcColls.size()); + LOGF(info, "-- coll from MC Coll %d", collFromMcColls.size()); // check the generated collision was reconstructed if (collFromMcColls.size() > 0) { // get the truth and reco-level info if (verbose) - LOGF(info, "MC Collision has reconstructed collision!"); - trueHasRecoColl = true; + LOGF(info, "--- MC Collision has reconstructed collision!"); + // trueHasRecoColl = true; // check there is exactly one reco-level collision associated to generated collision if (collFromMcColls.size() > 1) { if (verbose) - LOGF(info, "Truth collision has more than 1 reco collision. Skipping this event."); - // histos.get(HIST("Truth/hTroubles"))->Fill(1); - // problem = true; + LOGF(info, "---- Truth collision has more than 1 reco collision. Event remains."); + // LOGF(info, "Truth collision has more than 1 reco collision. Skipping this event."); + // histos.get(HIST("Truth/hTroubles"))->Fill(1); + // problem = true; problem = MANY_RECO; registrySkim.get(HIST("skim/problemMC"))->Fill(MANY_RECO); - continue; + // continue; + } else { + if (verbose) + LOGF(info, "---- Truth collision has 1 reco collision. Record event."); } - // grap reco-level collision - auto const& collFromMcColl = collFromMcColls.iteratorAt(0); - // grab tracks from the reco-level collision to get info to match measured data tables (processDataSG function) - auto const& trksFromColl = tracks.sliceBy(trackPerCollision, collFromMcColl.globalIndex()); - // int countTracksPerCollision = 0; - // int countGoodNonPVtracks = 0; - // for (auto const& trkFromColl : trksFromColl) { - // // countTracksPerCollision++; - // if (!trkFromColl.isPVContributor()) { - // countGoodNonPVtracks++; - // continue; - // } - // } - - // fill info for reconstructed collision - runNumber = collFromMcColl.runNumber(); - bc = collFromMcColl.globalBC(); - totalTracks = trksFromColl.size(); - // nTrks[0] = countTracksPerCollision; - nPVcontrib = collFromMcColl.numContrib(); - // nTrks[1] = collFromMcColl.numContrib(); - // nTrks[2] = countGoodNonPVtracks; - rct = isGoodRCTflag(collFromMcColl); - zVertex = collFromMcColl.posZ(); - // vtxPos[0] = collFromMcColl.posX(); - // vtxPos[1] = collFromMcColl.posY(); - // vtxPos[2] = collFromMcColl.posZ(); - - recoMode = collFromMcColl.flags(); - occupancy = collFromMcColl.occupancyInTime(); - hadronicRate = collFromMcColl.hadronicRate(); - bcSels[0] = collFromMcColl.trs(); - bcSels[1] = collFromMcColl.trofs(); - bcSels[2] = collFromMcColl.hmpr(); - bcSels[3] = collFromMcColl.tfb(); - bcSels[4] = collFromMcColl.itsROFb(); - bcSels[5] = collFromMcColl.sbp(); - bcSels[6] = collFromMcColl.zVtxFT0vPV(); - bcSels[7] = collFromMcColl.vtxITSTPC(); - // energyZNA = collFromMcColl.energyCommonZNA(); - // energyZNC = collFromMcColl.energyCommonZNC(); - // if (energyZNA < 0) - // energyZNA = -1.; - // if (energyZNC < 0) - // energyZNC = -1.; - - amplitudesFIT[0] = collFromMcColl.totalFT0AmplitudeA(); - amplitudesFIT[1] = collFromMcColl.totalFT0AmplitudeC(); - amplitudesFIT[2] = collFromMcColl.totalFV0AmplitudeA(); - // timesFIT[0] = collFromMcColl.timeFT0A(); - // timesFIT[1] = collFromMcColl.timeFT0C(); - // timesFIT[2] = collFromMcColl.timeFV0A(); - // get particles associated to generated collision - auto const& partsFromMcColl = mcParticles.sliceBy(partPerMcCollision, mccoll.globalIndex()); - if (verbose) - LOGF(info, "part from MC coll %d", partsFromMcColl.size()); - // int countMothers = 0; - int countDaughters = 0; - countPi0 = 0; - for (const auto& particle : partsFromMcColl) { - if (verbose) - LOGF(info, "Reco coll; part pdg %d", particle.pdgCode()); - // select only tauons with checking if particle has no mother - // in UPC MC taus have mothers - // if (particle.has_mothers()) - if (std::abs(particle.pdgCode()) != kTauMinus) - continue; // 15 = tau_minus + // grab reco-level collision + for (const auto& collFromMcColl : collFromMcColls) { + if (verbose) { + LOGF(info, "---- ###### Collision %d #########", collFromMcColl.index()); + LOGF(info, "---- Coll GID %d, Vertex (%f,%f,%f)", collFromMcColl.globalIndex(), collFromMcColl.posX(), collFromMcColl.posY(), collFromMcColl.posZ()); + } + // auto const& collFromMcColl = collFromMcColls.iteratorAt(0); + // grab tracks from the reco-level collision to get info to match measured data tables (processDataSG function) + auto const& trksFromColl = tracks.sliceBy(trackPerCollision, collFromMcColl.globalIndex()); + // int countTracksPerCollision = 0; + // int countGoodNonPVtracks = 0; + // for (auto const& trkFromColl : trksFromColl) { + // // countTracksPerCollision++; + // if (!trkFromColl.isPVContributor()) { + // countGoodNonPVtracks++; + // continue; + // } + // } - // get daughters of the tau - const auto& daughters = particle.daughters_as(); - // int countDaughters = 0; - for (const auto& daughter : daughters) { + // fill info for reconstructed collision + runNumber = collFromMcColl.runNumber(); + bc = collFromMcColl.globalBC(); + totalTracks = trksFromColl.size(); + // nTrks[0] = countTracksPerCollision; + nPVcontrib = collFromMcColl.numContrib(); + // nTrks[1] = collFromMcColl.numContrib(); + // nTrks[2] = countGoodNonPVtracks; + rct = isGoodRCTflag(collFromMcColl); + zVertex = collFromMcColl.posZ(); + // vtxPos[0] = collFromMcColl.posX(); + // vtxPos[1] = collFromMcColl.posY(); + // vtxPos[2] = collFromMcColl.posZ(); + + recoMode = collFromMcColl.flags(); + occupancy = collFromMcColl.occupancyInTime(); + hadronicRate = collFromMcColl.hadronicRate(); + bcSels[0] = collFromMcColl.trs(); + bcSels[1] = collFromMcColl.trofs(); + bcSels[2] = collFromMcColl.hmpr(); + bcSels[3] = collFromMcColl.tfb(); + bcSels[4] = collFromMcColl.itsROFb(); + bcSels[5] = collFromMcColl.sbp(); + bcSels[6] = collFromMcColl.zVtxFT0vPV(); + bcSels[7] = collFromMcColl.vtxITSTPC(); + // energyZNA = collFromMcColl.energyCommonZNA(); + // energyZNC = collFromMcColl.energyCommonZNC(); + // if (energyZNA < 0) + // energyZNA = -1.; + // if (energyZNC < 0) + // energyZNC = -1.; + + amplitudesFIT[0] = collFromMcColl.totalFT0AmplitudeA(); + amplitudesFIT[1] = collFromMcColl.totalFT0AmplitudeC(); + amplitudesFIT[2] = collFromMcColl.totalFV0AmplitudeA(); + // timesFIT[0] = collFromMcColl.timeFT0A(); + // timesFIT[1] = collFromMcColl.timeFT0C(); + // timesFIT[2] = collFromMcColl.timeFV0A(); + + // get particles associated to generated collision + auto const& partsFromMcColl = mcParticles.sliceBy(partPerMcCollision, mccoll.globalIndex()); + if (verbose) + LOGF(info, "---- part from MC coll %d", partsFromMcColl.size()); + // int countMothers = 0; + int countDaughters = 0; + countPi0 = 0; + for (const auto& particle : partsFromMcColl) { if (verbose) - LOGF(info, "With Coll; daug pdg %d", daughter.pdgCode()); - // check if it is the charged particle (= no pi0 or neutrino) - if (enumMyParticle(daughter.pdgCode()) == MyOtherParticle) // -1 - continue; - countDaughters++; - if (daughter.pdgCode() == kPi0) - countPi0++; - - // check whether 1+3 or 3+3 topology is present - if (countDaughters > sixTracks) { // 6 + LOGF(info, "----- Reco coll; part pdg %d, GID %d", particle.pdgCode(), particle.globalIndex()); + // select only tauons with checking if particle has no mother + // in UPC MC taus have mothers + // if (particle.has_mothers()) + if (std::abs(particle.pdgCode()) != kTauMinus) + continue; // 15 = tau_minus + + // get daughters of the tau + const auto& daughters = particle.daughters_as(); + // int countDaughters = 0; + for (const auto& daughter : daughters) { if (verbose) - LOGF(info, "Truth collision has more than 6 charged daughters from 2 taus. Breaking the daughter loop."); - // histos.get(HIST("Truth/hTroubles"))->Fill(3); - // problem = true; - problem = TOO_MANY_DAUGHTERS; - registrySkim.get(HIST("skim/problemMC"))->Fill(TOO_MANY_DAUGHTERS); - - break; - } - - // fill info for each daughter - trueDaugX[countDaughters - 1] = daughter.px(); - trueDaugY[countDaughters - 1] = daughter.py(); - trueDaugZ[countDaughters - 1] = daughter.pz(); - trueDaugPdgCode[countDaughters - 1] = daughter.pdgCode(); - - // get tracks associated to MC daughter (how well the daughter was reconstructed) - auto const& tracksFromDaughter = tracks.sliceBy(trackPerMcParticle, daughter.globalIndex()); - // check there is exactly 1 track per 1 particle - if (tracksFromDaughter.size() > 1) { + LOGF(info, "----- With Coll; daug pdg %d, GID %d", daughter.pdgCode(), daughter.globalIndex()); + + if (daughter.pdgCode() == kPi0) + countPi0++; + + // check if it is the charged particle (= no pi0 or neutrino) + if (enumMyParticle(daughter.pdgCode()) == MyOtherParticle) // -1 + continue; + countDaughters++; + + // check whether 1+3 or 3+3 topology is present + if (countDaughters > sixTracks) { // 6 + if (verbose) + LOGF(info, "------ Truth collision has more than 6 charged daughters from 2 taus. Breaking the daughter loop."); + // histos.get(HIST("Truth/hTroubles"))->Fill(3); + // problem = true; + problem = TOO_MANY_DAUGHTERS; + registrySkim.get(HIST("skim/problemMC"))->Fill(TOO_MANY_DAUGHTERS); + + break; + } + + // fill info for each daughter + trueDaugX[countDaughters - 1] = daughter.px(); + trueDaugY[countDaughters - 1] = daughter.py(); + trueDaugZ[countDaughters - 1] = daughter.pz(); + trueDaugPdgCode[countDaughters - 1] = daughter.pdgCode(); if (verbose) - LOGF(info, "Daughter has more than 1 associated track. Skipping this daughter."); - // histos.get(HIST("Truth/hTroubles"))->Fill(4); - // problem = true; - problem = TWO_TRACKS; - registrySkim.get(HIST("skim/problemMC"))->Fill(TWO_TRACKS); - continue; - } - // grab the track and fill info for reconstructed track (should be done 4 or 6 times) - const auto& trk = tracksFromDaughter.iteratorAt(0); - if (verbose) - LOGF(info, "p(%f,%f,%f)", trk.px(), trk.py(), trk.pz()); - px[countDaughters - 1] = trk.px(); - py[countDaughters - 1] = trk.py(); - pz[countDaughters - 1] = trk.pz(); - sign[countDaughters - 1] = trk.sign(); - dcaXY[countDaughters - 1] = trk.dcaXY(); - dcaZ[countDaughters - 1] = trk.dcaZ(); - // trkTimeRes[countMothers - 1] = trk.trackTimeRes(); - // if (countMothers == 1) { - // itsClusterSizesTrk1 = trk.itsClusterSizes(); - // } else { - // itsClusterSizesTrk2 = trk.itsClusterSizes(); - // } - - nclTPCcrossedRows[countDaughters - 1] = trk.tpcNClsCrossedRows(); - nclTPCfind[countDaughters - 1] = trk.tpcNClsFindable(); - nclTPCchi2[countDaughters - 1] = trk.tpcChi2NCl(); - trkITSchi2[countDaughters - 1] = trk.itsChi2NCl(); - trkITScl[countDaughters - 1] = numberOfItsClustersCheck(trk); - - tpcSignal[countDaughters - 1] = trk.tpcSignal(); - tpcEl[countDaughters - 1] = trk.tpcNSigmaEl(); - tpcMu[countDaughters - 1] = trk.tpcNSigmaMu(); - tpcPi[countDaughters - 1] = trk.tpcNSigmaPi(); - tpcKa[countDaughters - 1] = trk.tpcNSigmaKa(); - tpcPr[countDaughters - 1] = trk.tpcNSigmaPr(); - // tpcIP[countDaughters - 1] = trk.tpcInnerParam(); - - tofSignal[countDaughters - 1] = trk.beta(); - tofEl[countDaughters - 1] = trk.tofNSigmaEl(); - tofMu[countDaughters - 1] = trk.tofNSigmaMu(); - tofPi[countDaughters - 1] = trk.tofNSigmaPi(); - tofKa[countDaughters - 1] = trk.tofNSigmaKa(); - tofPr[countDaughters - 1] = trk.tofNSigmaPr(); - // tofEP[countMothers - 1] = trk.tofExpMom(); - if (trk.hasTOF()) - chi2TOF[countDaughters - 1] = trk.tofChi2(); - - } // daughters - } // particles + LOGF(info, "----- tau daug pxpypz (%f, %f, %f) pdg %d", daughter.px(), daughter.py(), daughter.pz(), daughter.pdgCode()); + // get tracks associated to MC daughter (how well the daughter was reconstructed) + auto const& tracksFromDaughter = tracks.sliceBy(trackPerMcParticle, daughter.globalIndex()); + // check there is exactly 1 track per 1 particle + if (tracksFromDaughter.size() > 1) { + if (verbose) + LOGF(info, "------ Daughter has more than 1 associated track. Ntracks = %d.", tracksFromDaughter.size()); + // LOGF(info, "Daughter has more than 1 associated track. Ntracks = %d. Skipping this daughter.", tracksFromDaughter.size()); + + // make sure that track momentum is the same (difference is smaller than epsilon=0.000001) for multiple reconstructed tracks, if not reject + // tracks are accocated to 2 different collisions (!?) + float tmptrk[3]; + bool firstObject = true; + int counter = 0; + for (const auto& trk : tracksFromDaughter) { + if (verbose) + LOGF(info, "------- track GID %d, p(%f,%f,%f)", trk.globalIndex(), trk.px(), trk.py(), trk.pz()); + if (firstObject) { + tmptrk[0] = trk.px(); + tmptrk[1] = trk.py(); + tmptrk[2] = trk.pz(); + firstObject = false; + counter++; + } else { + if ((std::abs(tmptrk[0] - trk.px()) > epsilon) || (std::abs(tmptrk[1] - trk.py()) > epsilon) || (std::abs(tmptrk[2] - trk.pz()) > epsilon)) + counter++; + } + } // end of loop over tracks from 1 McParticle + if (verbose) + LOGF(info, "------ Corrected number of associated tracks to MC particle %d", counter); + + if (counter > 1) { + if (verbose) + LOGF(info, "------ Daughter has more than 1 associated track. Ntracks = %d. Skipping this daughter.", counter); + problem = TWO_TRACKS; + registrySkim.get(HIST("skim/problemMC"))->Fill(TWO_TRACKS); + continue; + } + } else if (tracksFromDaughter.size() < 1) { + // what if no track is associated to mc particle??? + if (verbose) + LOGF(info, "----- Daughter has no associated track. Ntracks = %d. Skipping this daughter.", tracksFromDaughter.size()); + problem = NO_TRACK; + registrySkim.get(HIST("skim/problemMC"))->Fill(NO_TRACK); + continue; + } + + // grab the track and fill info for reconstructed track (should be done 4 or 6 times) + const auto& trk = tracksFromDaughter.iteratorAt(0); + + px[countDaughters - 1] = trk.px(); + py[countDaughters - 1] = trk.py(); + pz[countDaughters - 1] = trk.pz(); + sign[countDaughters - 1] = trk.sign(); + dcaXY[countDaughters - 1] = trk.dcaXY(); + dcaZ[countDaughters - 1] = trk.dcaZ(); + // trkTimeRes[countMothers - 1] = trk.trackTimeRes(); + // if (countMothers == 1) { + // itsClusterSizesTrk1 = trk.itsClusterSizes(); + // } else { + // itsClusterSizesTrk2 = trk.itsClusterSizes(); + // } + + nclTPCcrossedRows[countDaughters - 1] = trk.tpcNClsCrossedRows(); + nclTPCfind[countDaughters - 1] = trk.tpcNClsFindable(); + nclTPCchi2[countDaughters - 1] = trk.tpcChi2NCl(); + trkITSchi2[countDaughters - 1] = trk.itsChi2NCl(); + trkITScl[countDaughters - 1] = numberOfItsClustersCheck(trk); + + tpcSignal[countDaughters - 1] = trk.tpcSignal(); + tpcEl[countDaughters - 1] = trk.tpcNSigmaEl(); + tpcMu[countDaughters - 1] = trk.tpcNSigmaMu(); + tpcPi[countDaughters - 1] = trk.tpcNSigmaPi(); + tpcKa[countDaughters - 1] = trk.tpcNSigmaKa(); + tpcPr[countDaughters - 1] = trk.tpcNSigmaPr(); + // tpcIP[countDaughters - 1] = trk.tpcInnerParam(); + + tofSignal[countDaughters - 1] = trk.beta(); + tofEl[countDaughters - 1] = trk.tofNSigmaEl(); + tofMu[countDaughters - 1] = trk.tofNSigmaMu(); + tofPi[countDaughters - 1] = trk.tofNSigmaPi(); + tofKa[countDaughters - 1] = trk.tofNSigmaKa(); + tofPr[countDaughters - 1] = trk.tofNSigmaPr(); + // tofEP[countMothers - 1] = trk.tofExpMom(); + if (trk.hasTOF()) + chi2TOF[countDaughters - 1] = trk.tofChi2(); + + } // end of loop over daughters of taus + } // end of loop over MC particles + } // end of loop over collisions associated to MC collision } else { // get only the truth information. The reco-level info is left on default if (verbose) LOGF(info, "MC Collision has NO reconstructed collision!"); @@ -1470,12 +1532,14 @@ struct TauThreeProngEventTableProducer { for (const auto& daughter : daughters) { if (verbose) LOGF(info, "NO Coll; daug id %d, pdg %d", daughter.globalIndex(), daughter.pdgCode()); + + if (daughter.pdgCode() == kPi0) + countPi0++; + // select only the charged particle (= no pi0 or neutrino) if (enumMyParticle(daughter.pdgCode()) == -1) continue; countDaughters++; - if (daughter.pdgCode() == kPi0) - countPi0++; // check whether 1+3 or 3+3 topology is present if (countDaughters > sixTracks) { // 6 @@ -1526,7 +1590,7 @@ struct TauThreeProngEventTableProducer { chi2TOF, // trueChannel, - trueHasRecoColl, + // trueHasRecoColl, mccoll.posZ(), trueTauX, trueTauY, trueTauZ, trueDaugX, trueDaugY, trueDaugZ, From 008d35a03dd96b315467cfefedcee6b556fa2b23 Mon Sep 17 00:00:00 2001 From: "Q.Y. Xia" <91366503+huinaibing@users.noreply.github.com> Date: Tue, 3 Mar 2026 04:05:08 +0800 Subject: [PATCH 138/347] [PWGCF] Add pt spectra hist for QA (#15215) Co-authored-by: ALICE Action Bot --- PWGCF/Flow/Tasks/pidFlowPtCorr.cxx | 96 +++++++++++++++++++++++++++++- 1 file changed, 94 insertions(+), 2 deletions(-) diff --git a/PWGCF/Flow/Tasks/pidFlowPtCorr.cxx b/PWGCF/Flow/Tasks/pidFlowPtCorr.cxx index 6680d402942..ea938dd55a8 100644 --- a/PWGCF/Flow/Tasks/pidFlowPtCorr.cxx +++ b/PWGCF/Flow/Tasks/pidFlowPtCorr.cxx @@ -137,6 +137,8 @@ struct PidFlowPtCorr { O2_DEFINE_CONFIGURABLE(cfgUsePtCentNUECorr, bool, true, "do NUA NUE, Using Eff(pt, cent) to do NUE") O2_DEFINE_CONFIGURABLE(cfgDebugMyCode, bool, false, "output some graph for code debug") + O2_DEFINE_CONFIGURABLE(cfgOutPutPtSpectra, bool, false, "output pt spectra for data, MC and RECO") + /** * @brief cfg for PID pt range * @details default datas are from run2, note that separate pi-k and k-p needs to use difference pt range @@ -197,7 +199,7 @@ struct PidFlowPtCorr { Filter particleFilter = (nabs(aod::mcparticle::eta) < trkQualityOpts.cfgCutEta.value); using FilteredMcParticles = soa::Filtered; - using FilteredTracksWithMCLabel = soa::Filtered>; + using FilteredTracksWithMCLabel = soa::Filtered>; using FilteredCollisionsWithMCLabel = soa::Filtered>; // end using and filter @@ -382,7 +384,7 @@ struct PidFlowPtCorr { TH1* hPhiRunByRunBefore = registry.add(Form("RunByRunQA%d/hPhiBefore", oneRun), "", {HistType::kTH1D, {cfgaxisPhi}}).get(); TH1* hPhiRunByRunAfter = registry.add(Form("RunByRunQA%d/hPhiAfter", oneRun), "", {HistType::kTH1D, {cfgaxisPhi}}).get(); - TH2* hITSnclsVsPhi = registry.add(Form("RunByRunQA%d/hITSnclsVsPhi", oneRun), "", {HistType::kTH2D, {cfgaxisPhi, {7, 0, 7}}}).get(); + TH2* hITSnclsVsPhi = registry.add(Form("RunByRunQA%d/hITSnclsVsPhi", oneRun), "", {HistType::kTH2D, {cfgaxisPhi, {8, 0, 8}}}).get(); TH2* hITSChi2VsPhi = registry.add(Form("RunByRunQA%d/hITSChi2VsPhi", oneRun), "", {HistType::kTH2D, {cfgaxisPhi, {100, 0, 10}}}).get(); qaHistVector.emplace_back(qaHist(hPhiRunByRunBefore, hPhiRunByRunAfter, hITSnclsVsPhi, hITSChi2VsPhi)); @@ -394,6 +396,16 @@ struct PidFlowPtCorr { // hist for NUE correction registry.add("correction/hPtCentMcRec", "", {HistType::kTH2D, {cfgaxisPt, axisMultiplicity}}); registry.add("correction/hPtCentMcGen", "", {HistType::kTH2D, {cfgaxisPt, axisMultiplicity}}); + + // hist for Pi eff + registry.add("correction/hPtCentMcRecPi", "", {HistType::kTH2D, {cfgaxisPt, axisMultiplicity}}); + registry.add("correction/hPtCentMcGenPi", "", {HistType::kTH2D, {cfgaxisPt, axisMultiplicity}}); + // hist for Ka eff + registry.add("correction/hPtCentMcRecKa", "", {HistType::kTH2D, {cfgaxisPt, axisMultiplicity}}); + registry.add("correction/hPtCentMcGenKa", "", {HistType::kTH2D, {cfgaxisPt, axisMultiplicity}}); + // hist for Pr eff + registry.add("correction/hPtCentMcRecPr", "", {HistType::kTH2D, {cfgaxisPt, axisMultiplicity}}); + registry.add("correction/hPtCentMcGenPr", "", {HistType::kTH2D, {cfgaxisPt, axisMultiplicity}}); } // cfgoutputMC // debug hists @@ -406,6 +418,26 @@ struct PidFlowPtCorr { } } // cfgdebugmycode + if (cfgOutPutPtSpectra) { + registry.add("ptSpectra/hPtCentData", "", {HistType::kTH2D, {cfgaxisPt, axisMultiplicity}}); + registry.add("ptSpectra/hCentEventCountData", "", {HistType::kTH1D, {axisMultiplicity}}); + registry.add("ptSpectra/hCentEventCountMcGen", "", {HistType::kTH1D, {axisMultiplicity}}); + registry.add("ptSpectra/hCentEventCountMcRec", "", {HistType::kTH1D, {axisMultiplicity}}); + + // (PosEta)(PosCh) + registry.add("ptSpectra/hPtCentDataPosEtaPosCh", "", {HistType::kTH2D, {cfgaxisPt, axisMultiplicity}}); + + // (PosEta)(NegCh) + registry.add("ptSpectra/hPtCentDataPosEtaNegCh", "", {HistType::kTH2D, {cfgaxisPt, axisMultiplicity}}); + + // (NegEta(PosCh) + registry.add("ptSpectra/hPtCentDataNegEtaPosCh", "", {HistType::kTH2D, {cfgaxisPt, axisMultiplicity}}); + + // (NegEta)(NegCh) + registry.add("ptSpectra/hPtCentDataNegEtaNegCh", "", {HistType::kTH2D, {cfgaxisPt, axisMultiplicity}}); + + } // cfgoutputptspectra + if (cfgOutputrunbyrun) { // hist for NUA registry.add("correction/hRunNumberPhiEtaVertex", "", {HistType::kTHnSparseF, {cfgaxisRun, cfgaxisPhi, cfgaxisEta, cfgaxisVertex}}); @@ -1262,6 +1294,11 @@ struct PidFlowPtCorr { return; // end collision cut + // pt spectra + if (cfgOutPutPtSpectra) { + registry.fill(HIST("ptSpectra/hCentEventCountData"), cent); + } // cfgOutPutPtSpectra + // correction loadCorrections(bc.timestamp()); float vtxz = collision.posZ(); @@ -1388,6 +1425,27 @@ struct PidFlowPtCorr { registry.fill(HIST("hPt"), track.pt()); // end fill QA hist + // pt spectra + if (cfgOutPutPtSpectra) { + registry.fill(HIST("ptSpectra/hPtCentData"), track.pt(), cent); + + // region 1 +eta +ch + if (track.eta() > 0.05 && track.sign() > 0) + registry.fill(HIST("ptSpectra/hPtCentDataPosEtaPosCh"), track.pt(), cent); + + // region 2 +eta -ch + if (track.eta() > 0.05 && track.sign() < 0) + registry.fill(HIST("ptSpectra/hPtCentDataPosEtaNegCh"), track.pt(), cent); + + // region 3 -eta +ch + if (track.eta() < -0.05 && track.sign() > 0) + registry.fill(HIST("ptSpectra/hPtCentDataNegEtaPosCh"), track.pt(), cent); + + // region 4 -eta -ch + if (track.eta() < -0.05 && track.sign() < 0) + registry.fill(HIST("ptSpectra/hPtCentDataNegEtaNegCh"), track.pt(), cent); + } + // track pt cut if (!((track.pt() > trkQualityOpts.cfgCutPtMin.value) && (track.pt() < trkQualityOpts.cfgCutPtMax.value))) continue; @@ -1694,6 +1752,10 @@ struct PidFlowPtCorr { return; // end init && cut + if (cfgOutPutPtSpectra) { + registry.fill(HIST("ptSpectra/hCentEventCountMcRec"), cent); + } // cfgoutputptspectra + // loop tracks for (const auto& track : tracks) { // track cut @@ -1706,7 +1768,20 @@ struct PidFlowPtCorr { auto mcParticle = track.mcParticle(); // fill graph if (particleSelected(mcParticle)) { + // graph for all particles registry.fill(HIST("correction/hPtCentMcRec"), track.pt(), cent); + + // identify particle and fill graph + if (isPion(track)) { + registry.fill(HIST("correction/hPtCentMcRecPi"), track.pt(), cent); + } + if (isKaon(track)) { + registry.fill(HIST("correction/hPtCentMcRecKa"), track.pt(), cent); + } + if (isProton(track)) { + registry.fill(HIST("correction/hPtCentMcRecPr"), track.pt(), cent); + } + // end identify particle and fill graph } // end fill graph } @@ -1755,11 +1830,28 @@ struct PidFlowPtCorr { continue; // end collision cut + if (cfgOutPutPtSpectra) { + registry.fill(HIST("ptSpectra/hCentEventCountMcGen"), cent); + } // cfgoutputptspectra + // loop mc particles for (const auto& mcParticle : mcParticles) { // fill graph if (particleSelected(mcParticle)) { + // graph for all particles registry.fill(HIST("correction/hPtCentMcGen"), mcParticle.pt(), cent); + + // identify particle and fill graph + if (std::abs(mcParticle.pdgCode()) == PDG_t::kPiPlus) { + registry.fill(HIST("correction/hPtCentMcGenPi"), mcParticle.pt(), cent); + } + if (std::abs(mcParticle.pdgCode()) == PDG_t::kKPlus) { + registry.fill(HIST("correction/hPtCentMcGenKa"), mcParticle.pt(), cent); + } + if (std::abs(mcParticle.pdgCode()) == PDG_t::kProton) { + registry.fill(HIST("correction/hPtCentMcGenPr"), mcParticle.pt(), cent); + } + // end identify particle and fill graph } // end fill graph } From 40a2abe78c9668d1a9d4c9b31dea86061e0fe0cc Mon Sep 17 00:00:00 2001 From: Neelkamal Mallick <104082831+nmallick19@users.noreply.github.com> Date: Mon, 2 Mar 2026 22:06:28 +0200 Subject: [PATCH 139/347] [PWGCF] process MultSet and track selection bit check added (#15180) Co-authored-by: ALICE Action Bot --- PWGCF/JCorran/Tasks/flowJSPCAnalysis.cxx | 78 ++++++++++++++++++++++-- 1 file changed, 72 insertions(+), 6 deletions(-) diff --git a/PWGCF/JCorran/Tasks/flowJSPCAnalysis.cxx b/PWGCF/JCorran/Tasks/flowJSPCAnalysis.cxx index 111e1f8e92b..380de913181 100644 --- a/PWGCF/JCorran/Tasks/flowJSPCAnalysis.cxx +++ b/PWGCF/JCorran/Tasks/flowJSPCAnalysis.cxx @@ -8,15 +8,19 @@ // In applying this license CERN does not waive the privileges and immunities // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. - -// \brief Task for the calculation of SPC with filtered data. -// \author Maxim Virta (maxim.virta@cern.ch), Cindy Mordasini (cindy.mordasini@cern.ch) +/// +/// \file flowJSPCAnalysis.cxx +/// \brief Task for the calculation of SPC with filtered data. +/// \author Maxim Virta (maxim.virta@cern.ch), Cindy Mordasini (cindy.mordasini@cern.ch), Neelkamal Mallick (neelkamal.mallick@cern.ch) // Standard headers. +#include +#include + #include +#include #include #include -#include // O2 headers. // // The first two are mandatory. @@ -46,6 +50,8 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; +#define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable NAME{#NAME, DEFAULT, HELP}; + using MyCollisions = soa::Join().weightNUA()); template using HasWeightEff = decltype(std::declval().weightEff()); + template + using HasTrackType = decltype(std::declval().trackType()); HistogramRegistry qaHistRegistry{"qaHistRegistry", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; FlowJHistManager histManager; @@ -84,12 +92,20 @@ struct flowJSPCAnalysis { Configurable cfgMultMin{"cfgMultMin", 10, "Minimum number of particles required for the event to have."}; } cfgEventCuts; + O2_DEFINE_CONFIGURABLE(cfgTrackBitMask, uint16_t, 0, "Track selection bitmask to use as defined in the filterCorrelations.cxx task"); + O2_DEFINE_CONFIGURABLE(cfgMultCorrelationsMask, uint16_t, 0, "Selection bitmask for the multiplicity correlations. This should match the filter selection cfgEstimatorBitMask.") + O2_DEFINE_CONFIGURABLE(cfgMultCutFormula, std::string, "", "Multiplicity correlations cut formula. A result greater than zero results in accepted event. Parameters: [cFT0C] FT0C centrality, [mFV0A] V0A multiplicity, [mGlob] global track multiplicity, [mPV] PV track multiplicity, [cFT0M] FT0M centrality") + // // Filters to be applied to the received data. // // The analysis assumes the data has been subjected to a QA of its selection, // // and thus only the final distributions of the data for analysis are saved. Filter collFilter = (nabs(aod::collision::posZ) < cfgEventCuts.cfgZvtxMax); + Filter trackFilter = (aod::track::pt > cfgTrackCuts.cfgPtMin) && (aod::track::pt < cfgTrackCuts.cfgPtMax) && (nabs(aod::track::eta) < cfgTrackCuts.cfgEtaMax); - Filter cftrackFilter = (aod::cftrack::pt > cfgTrackCuts.cfgPtMin) && (aod::cftrack::pt < cfgTrackCuts.cfgPtMax); // eta cuts done by jfluc + Filter cftrackFilter = (nabs(aod::cftrack::eta) < cfgTrackCuts.cfgEtaMax) && (aod::cftrack::pt > cfgTrackCuts.cfgPtMin) && (aod::cftrack::pt < cfgTrackCuts.cfgPtMax) && ncheckbit(aod::track::trackType, as(cfgTrackBitMask)); + + std::unique_ptr multCutFormula; + std::array multCutFormulaParamIndex; void init(InitContext const&) { @@ -103,6 +119,26 @@ struct flowJSPCAnalysis { histManager.setHistRegistryQA(&qaHistRegistry); histManager.setDebugLog(false); histManager.createHistQA(); + + if (!cfgMultCutFormula.value.empty()) { + multCutFormula = std::make_unique("multCutFormula", cfgMultCutFormula.value.c_str()); + std::fill_n(multCutFormulaParamIndex.begin(), std::size(multCutFormulaParamIndex), ~0u); + std::array pars = {"cFT0C", "mFV0A", "mPV", "mGlob", "cFT0M"}; // must correspond the order of MultiplicityEstimators + for (uint i = 0, n = multCutFormula->GetNpar(); i < n; ++i) { + auto m = std::find(pars.begin(), pars.end(), multCutFormula->GetParName(i)); + if (m == pars.end()) { + LOGF(warning, "Unknown parameter in cfgMultCutFormula: %s", multCutFormula->GetParName(i)); + continue; + } + const uint estIdx = std::distance(pars.begin(), m); + if ((cfgMultCorrelationsMask.value & (1u << estIdx)) == 0) { + LOGF(warning, "The centrality/multiplicity estimator %s is not available to be used in cfgMultCutFormula. Ensure cfgMultCorrelationsMask is correct and matches the CFMultSets in derived data.", m->c_str()); + } else { + multCutFormulaParamIndex[estIdx] = i; + LOGF(info, "Multiplicity cut parameter %s in use.", m->c_str()); + } + } + } } template @@ -119,6 +155,7 @@ struct flowJSPCAnalysis { int cBin = histManager.getCentBin(cent); spcHistograms.fill(HIST("FullCentrality"), cent); int nTracks = tracks.size(); + double wNUA = 1.0; double wEff = 1.0; for (const auto& track : tracks) { @@ -135,6 +172,11 @@ struct flowJSPCAnalysis { if constexpr (std::experimental::is_detected::value) { spcAnalysis.fillQAHistograms(cBin, track.phi(), 1. / track.weightNUA()); } + if constexpr (std::experimental::is_detected::value) { + if (track.trackType() != cfgTrackBitMask.value) { + LOGF(warning, "trackType %d (expected %d) is passed to the analysis", track.trackType(), cfgTrackBitMask.value); + } + } } } @@ -146,6 +188,20 @@ struct flowJSPCAnalysis { spcAnalysis.calculateCorrelators(cBin); } + template + bool passOutlier(CollType const& collision) + { + if (cfgMultCutFormula.value.empty()) + return true; + for (uint i = 0; i < aod::cfmultset::NMultiplicityEstimators; ++i) { + if ((cfgMultCorrelationsMask.value & (1u << i)) == 0 || multCutFormulaParamIndex[i] == ~0u) + continue; + auto estIndex = std::popcount(static_cast(cfgMultCorrelationsMask.value & ((1u << i) - 1))); + multCutFormula->SetParameter(multCutFormulaParamIndex[i], collision.multiplicities()[estIndex]); + } + return multCutFormula->Eval() > 0.0f; + } + void processJDerived(aod::JCollision const& collision, soa::Filtered const& tracks) { analyze(collision, tracks); @@ -164,11 +220,21 @@ struct flowJSPCAnalysis { } PROCESS_SWITCH(flowJSPCAnalysis, processCFDerived, "Process CF derived data", false); - void processCFDerivedCorrected(aod::CFCollision const& collision, soa::Filtered> const& tracks) + void processCFDerivedCorrected(soa::Filtered::iterator const& collision, soa::Filtered> const& tracks) { analyze(collision, tracks); } PROCESS_SWITCH(flowJSPCAnalysis, processCFDerivedCorrected, "Process CF derived data with corrections", true); + + void processCFDerivedMultSetCorrected(soa::Filtered>::iterator const& collision, soa::Filtered> const& tracks) + { + if (std::popcount(static_cast(cfgMultCorrelationsMask.value)) != static_cast(collision.multiplicities().size())) + LOGF(fatal, "Multiplicity selections (cfgMultCorrelationsMask = 0x%x) do not match the size of the table column (%ld).", cfgMultCorrelationsMask.value, collision.multiplicities().size()); + if (!passOutlier(collision)) + return; + analyze(collision, tracks); + } + PROCESS_SWITCH(flowJSPCAnalysis, processCFDerivedMultSetCorrected, "Process CF derived data with corrections and multiplicity sets", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) From 170b85455abff8ec104ab304c5ef1559bcc5b256 Mon Sep 17 00:00:00 2001 From: Zhiyong <71517277+Luzhiyongg@users.noreply.github.com> Date: Mon, 2 Mar 2026 21:07:13 +0100 Subject: [PATCH 140/347] [PWGCF] Add pT dis QA for subevents (#15220) Co-authored-by: ALICE Action Bot --- PWGCF/Flow/Tasks/flowTask.cxx | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/PWGCF/Flow/Tasks/flowTask.cxx b/PWGCF/Flow/Tasks/flowTask.cxx index 5403fb99ad4..53b84b5f849 100644 --- a/PWGCF/Flow/Tasks/flowTask.cxx +++ b/PWGCF/Flow/Tasks/flowTask.cxx @@ -192,6 +192,7 @@ struct FlowTask { // for deltaPt/ vs centrality O2_DEFINE_CONFIGURABLE(cfgDptDisEnable, bool, false, "Produce deltaPt/meanPt vs centrality") O2_DEFINE_CONFIGURABLE(cfgDptDisSelectionSwitch, int, 0, "0: disable, 1: use low cut, 2:use high cut") + O2_DEFINE_CONFIGURABLE(cfgDptDisEtaGapQA, float, 0.5, "QA plot for pT dis in eta gap") TH1D* hEvAvgMeanPt = nullptr; TH1D* fDptDisCutLow = nullptr; TH1D* fDptDisCutHigh = nullptr; @@ -397,6 +398,8 @@ struct FlowTask { registry.add("hNormDeltaPt_X", "; #delta p_{T}/[p_{T}]; X", {HistType::kTH2D, {cfgAdditionObs.cfgDptDisAxisNormal, axisIndependent}}); registry.add("hNormDeltaPt_X_afterCut", "; #delta p_{T}/[p_{T}]; X", {HistType::kTH2D, {cfgAdditionObs.cfgDptDisAxisNormal, axisIndependent}}); registry.add("hPt_afterDptCut", "p_{T} distribution", {HistType::kTH1D, {axisPt}}); + registry.add("hPtA_afterDptCut", "p_{T} distribution", {HistType::kTH1D, {axisPt}}); + registry.add("hPtB_afterDptCut", "p_{T} distribution", {HistType::kTH1D, {axisPt}}); } if (doprocessMCGen) { registry.add("MCGen/MChPhi", "#phi distribution", {HistType::kTH1D, {axisPhi}}); @@ -1225,7 +1228,7 @@ struct FlowTask { std::vector consistentEventVector = cfgUserIO.cfgConsistentEventVector; if (cfgUserIO.cfgConsistentEventFlag) LOGF(info, "consistentEventVector.size = %u", consistentEventVector.size()); - std::vector ptVec; + std::vector> ptEtaVec; double psi2Est = 0, psi3Est = 0, psi4Est = 0; float wEPeff = 1; @@ -1295,7 +1298,7 @@ struct FlowTask { } registry.fill(HIST("hPt"), track.pt()); if (cfgAdditionObs.cfgDptDisEnable) - ptVec.push_back(track.pt()); + ptEtaVec.push_back({track.pt(), track.eta()}); if (!cfgUserIO.cfgUseSmallMemory) { registry.fill(HIST("hEtaPtCent"), track.eta(), track.pt(), cent); } @@ -1383,9 +1386,14 @@ struct FlowTask { return; } registry.fill(HIST("hNormDeltaPt_X_afterCut"), normDeltaPt, independent, weffEvent); - if (ptVec.size() > 0) { - for (auto trpt : ptVec) - registry.fill(HIST("hPt_afterDptCut"), trpt); + if (ptEtaVec.size() > 0) { + for (auto trptEta : ptEtaVec) { + registry.fill(HIST("hPt_afterDptCut"), trptEta.first); + if (trptEta.second < -1. * cfgAdditionObs.cfgDptDisEtaGapQA) + registry.fill(HIST("hPtA_afterDptCut"), trptEta.first); + if (trptEta.second > cfgAdditionObs.cfgDptDisEtaGapQA) + registry.fill(HIST("hPtB_afterDptCut"), trptEta.first); + } } } From c2b5c3a149e0390a79fb01ff826ba25c88d11296 Mon Sep 17 00:00:00 2001 From: Junlee Kim Date: Tue, 3 Mar 2026 04:08:25 +0800 Subject: [PATCH 141/347] [PWGCF] modularization of functions for event selection and filling histograms (#15223) Co-authored-by: ALICE Action Bot --- PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx | 267 ++++++++++++------------ 1 file changed, 129 insertions(+), 138 deletions(-) diff --git a/PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx b/PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx index c7e2386d409..2853dd5d089 100644 --- a/PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx +++ b/PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx @@ -117,6 +117,8 @@ struct jEPFlowAnalysis { int currentRunNumber = -999; int lastRunNumber = -999; + float cent; + std::vector shiftprofile{}; std::string fullCCDBShiftCorrPath; @@ -144,6 +146,37 @@ struct jEPFlowAnalysis { } } + template + bool eventSel(const Col& coll) + { + if (std::abs(coll.posZ()) > cfgVertexZ) + return false; + switch (cfgEvtSel) { + case 0: // Sel8 + if (!coll.sel8()) + return false; + break; + case 1: // PbPb standard + if (!coll.sel8() || !coll.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) || !coll.selection_bit(aod::evsel::kNoSameBunchPileup)) + return false; + break; + case 2: // PbPb with pileup + if (!coll.sel8() || !coll.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard) || + !coll.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) || !coll.selection_bit(aod::evsel::kNoSameBunchPileup)) + return false; + break; + case 3: // Small systems (OO, NeNe, pp) + if (!coll.sel8() || !coll.selection_bit(aod::evsel::kNoSameBunchPileup)) + return false; + break; + } + // Check occupancy + if (coll.trackOccupancyInTimeRange() > cfgMaxOccupancy || coll.trackOccupancyInTimeRange() < cfgMinOccupancy) + return false; + + return true; + } + template uint8_t trackSel(const Trk& track) { @@ -173,6 +206,97 @@ struct jEPFlowAnalysis { return tracksel; } + template + void fillvn(const Col& coll, const Trk& tracks) + { + float eps[3] = {0.}; + float qx_shifted[3] = {0.}; + float qy_shifted[3] = {0.}; + + for (int i = 0; i < cfgnMode; i++) { // loop over different harmonic orders + harmInd = cfgnTotalSystem * 4 * (i) + 3; // harmonic index to access corresponding Q-vector as all Q-vectors are in same vector + eps[0] = helperEP.GetEventPlane(coll.qvecRe()[4 * detId + harmInd], coll.qvecIm()[4 * detId + harmInd], i + 2); + eps[1] = helperEP.GetEventPlane(coll.qvecRe()[4 * refAId + harmInd], coll.qvecIm()[4 * refAId + harmInd], i + 2); + eps[2] = helperEP.GetEventPlane(coll.qvecRe()[4 * refBId + harmInd], coll.qvecIm()[4 * refBId + harmInd], i + 2); + + auto deltapsiDet = 0.0; + auto deltapsiRefA = 0.0; + auto deltapsiRefB = 0.0; + + float weight = 1.0; + + qx_shifted[0] = coll.qvecRe()[4 * detId + harmInd]; + qy_shifted[0] = coll.qvecIm()[4 * detId + harmInd]; + qx_shifted[1] = coll.qvecRe()[4 * refAId + harmInd]; + qy_shifted[1] = coll.qvecIm()[4 * refAId + harmInd]; + qx_shifted[2] = coll.qvecRe()[4 * refBId + harmInd]; + qy_shifted[2] = coll.qvecIm()[4 * refBId + harmInd]; + + if (cfgManShiftCorr) { + constexpr int kShiftBins = 10; + for (int ishift = 1; ishift <= kShiftBins; ishift++) { + auto coeffshiftxDet = shiftprofile.at(i)->GetBinContent(shiftprofile.at(i)->FindBin(cent, 2.0 * detId + 0.5, ishift - 0.5)); + auto coeffshiftyDet = shiftprofile.at(i)->GetBinContent(shiftprofile.at(i)->FindBin(cent, 2.0 * detId + 1.5, ishift - 0.5)); + auto coeffshiftxRefA = shiftprofile.at(i)->GetBinContent(shiftprofile.at(i)->FindBin(cent, 2.0 * refAId + 0.5, ishift - 0.5)); + auto coeffshiftyRefA = shiftprofile.at(i)->GetBinContent(shiftprofile.at(i)->FindBin(cent, 2.0 * refAId + 1.5, ishift - 0.5)); + auto coeffshiftxRefB = shiftprofile.at(i)->GetBinContent(shiftprofile.at(i)->FindBin(cent, 2.0 * refBId + 0.5, ishift - 0.5)); + auto coeffshiftyRefB = shiftprofile.at(i)->GetBinContent(shiftprofile.at(i)->FindBin(cent, 2.0 * refBId + 1.5, ishift - 0.5)); + + deltapsiDet += ((2. / (1.0 * ishift)) * (-coeffshiftxDet * std::cos(ishift * static_cast(i + 2) * eps[0]) + coeffshiftyDet * std::sin(ishift * static_cast(i + 2) * eps[0]))) / static_cast(i + 2); + deltapsiRefA += ((2. / (1.0 * ishift)) * (-coeffshiftxRefA * std::cos(ishift * static_cast(i + 2) * eps[1]) + coeffshiftyRefA * std::sin(ishift * static_cast(i + 2) * eps[1]))) / static_cast(i + 2); + deltapsiRefB += ((2. / (1.0 * ishift)) * (-coeffshiftxRefB * std::cos(ishift * static_cast(i + 2) * eps[2]) + coeffshiftyRefB * std::sin(ishift * static_cast(i + 2) * eps[2]))) / static_cast(i + 2); + } + + eps[0] += deltapsiDet; + eps[1] += deltapsiRefA; + eps[2] += deltapsiRefB; + + qx_shifted[0] = coll.qvecRe()[4 * detId + harmInd] * std::cos(deltapsiDet) - coll.qvecIm()[4 * detId + harmInd] * std::sin(deltapsiDet); + qy_shifted[0] = coll.qvecRe()[4 * detId + harmInd] * std::sin(deltapsiDet) + coll.qvecIm()[4 * detId + harmInd] * std::cos(deltapsiDet); + qx_shifted[1] = coll.qvecRe()[4 * refAId + harmInd] * std::cos(deltapsiRefA) - coll.qvecIm()[4 * refAId + harmInd] * std::sin(deltapsiRefA); + qy_shifted[1] = coll.qvecRe()[4 * refAId + harmInd] * std::sin(deltapsiRefA) + coll.qvecIm()[4 * refAId + harmInd] * std::cos(deltapsiRefA); + qx_shifted[2] = coll.qvecRe()[4 * refBId + harmInd] * std::cos(deltapsiRefB) - coll.qvecIm()[4 * refBId + harmInd] * std::sin(deltapsiRefB); + qy_shifted[2] = coll.qvecRe()[4 * refBId + harmInd] * std::sin(deltapsiRefB) + coll.qvecIm()[4 * refBId + harmInd] * std::cos(deltapsiRefB); + } + float resNumA = helperEP.GetResolution(eps[0], eps[1], i + 2); + float resNumB = helperEP.GetResolution(eps[0], eps[2], i + 2); + float resDenom = helperEP.GetResolution(eps[1], eps[2], i + 2); + + epFlowHistograms.fill(HIST("EpDet"), i + 2, cent, eps[0]); + epFlowHistograms.fill(HIST("EpRefA"), i + 2, cent, eps[1]); + epFlowHistograms.fill(HIST("EpRefB"), i + 2, cent, eps[2]); + + epFlowHistograms.fill(HIST("EpResDetRefA"), i + 2, cent, resNumA); + epFlowHistograms.fill(HIST("EpResDetRefB"), i + 2, cent, resNumB); + epFlowHistograms.fill(HIST("EpResRefARefB"), i + 2, cent, resDenom); + + epFlowHistograms.fill(HIST("EpResQvecDetRefAxx"), i + 2, cent, qx_shifted[0] * qx_shifted[1] + qy_shifted[0] * qy_shifted[1]); + epFlowHistograms.fill(HIST("EpResQvecDetRefAxy"), i + 2, cent, qx_shifted[1] * qy_shifted[0] - qx_shifted[0] * qy_shifted[1]); + epFlowHistograms.fill(HIST("EpResQvecDetRefBxx"), i + 2, cent, qx_shifted[0] * qx_shifted[2] + qy_shifted[0] * qy_shifted[2]); + epFlowHistograms.fill(HIST("EpResQvecDetRefBxy"), i + 2, cent, qx_shifted[2] * qy_shifted[0] - qx_shifted[0] * qy_shifted[2]); + epFlowHistograms.fill(HIST("EpResQvecRefARefBxx"), i + 2, cent, qx_shifted[1] * qx_shifted[2] + qy_shifted[1] * qy_shifted[2]); + epFlowHistograms.fill(HIST("EpResQvecRefARefBxy"), i + 2, cent, qx_shifted[2] * qy_shifted[1] - qx_shifted[1] * qy_shifted[2]); + + for (const auto& track : tracks) { + if (trackSel(track)) + continue; + + if (cfgEffCor) { + weight = getEfficiencyCorrection(effMap, track.eta(), track.pt(), cent, coll.posZ()); + } + + float vn = std::cos((i + 2) * (track.phi() - eps[0])); + float vnSin = std::sin((i + 2) * (track.phi() - eps[0])); + + epFlowHistograms.fill(HIST("vncos"), i + 2, cent, track.pt(), vn, weight); + epFlowHistograms.fill(HIST("vnsin"), i + 2, cent, track.pt(), vnSin, weight); + + epFlowHistograms.fill(HIST("SPvnxx"), i + 2, cent, track.pt(), (std::cos(track.phi() * static_cast(i + 2)) * qx_shifted[0] + std::sin(track.phi() * static_cast(i + 2)) * qy_shifted[0]), weight); + epFlowHistograms.fill(HIST("SPvnxy"), i + 2, cent, track.pt(), (std::sin(track.phi() * static_cast(i + 2)) * qx_shifted[0] - std::cos(track.phi() * static_cast(i + 2)) * qy_shifted[0]), weight); + } + } + } + double getEfficiencyCorrection(THn* eff, float eta, float pt, float multiplicity, float posZ) { int effVars[4]; @@ -243,31 +367,7 @@ struct jEPFlowAnalysis { void processDefault(MyCollisions::iterator const& coll, soa::Filtered const& tracks, aod::BCsWithTimestamps const&) { if (cfgAddEvtSel) { - if (std::abs(coll.posZ()) > cfgVertexZ) - return; - switch (cfgEvtSel) { - case 0: // Sel8 - if (!coll.sel8()) - return; - break; - case 1: // PbPb standard - if (!coll.sel8() || !coll.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) || !coll.selection_bit(aod::evsel::kNoSameBunchPileup)) - return; - break; - case 2: // PbPb with pileup - if (!coll.sel8() || !coll.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard) || - !coll.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) || !coll.selection_bit(aod::evsel::kNoSameBunchPileup)) - return; - break; - case 3: // Small systems (OO, NeNe, pp) - if (!coll.sel8() || !coll.selection_bit(aod::evsel::kNoSameBunchPileup)) - return; - break; - default: - LOGF(warning, "Event selection flag was not found, continuing without basic event selections!\n"); - } - // Check occupancy - if (coll.trackOccupancyInTimeRange() > cfgMaxOccupancy || coll.trackOccupancyInTimeRange() < cfgMinOccupancy) + if (!eventSel(coll)) return; } @@ -280,12 +380,9 @@ struct jEPFlowAnalysis { } } - float cent = coll.cent(); + cent = coll.cent(); epFlowHistograms.fill(HIST("hCentrality"), cent); epFlowHistograms.fill(HIST("hVertex"), coll.posZ()); - float eps[3] = {0.}; - float qx_shifted[3] = {0.}; - float qy_shifted[3] = {0.}; if (cfgManShiftCorr) { auto bc = coll.bc_as(); @@ -306,89 +403,7 @@ struct jEPFlowAnalysis { if (coll.qvecAmp()[detId] < 1e-5 || coll.qvecAmp()[refAId] < 1e-5 || coll.qvecAmp()[refBId] < 1e-5) return; - for (int i = 0; i < cfgnMode; i++) { // loop over different harmonic orders - harmInd = cfgnTotalSystem * 4 * (i) + 3; // harmonic index to access corresponding Q-vector as all Q-vectors are in same vector - eps[0] = helperEP.GetEventPlane(coll.qvecRe()[4 * detId + harmInd], coll.qvecIm()[4 * detId + harmInd], i + 2); - eps[1] = helperEP.GetEventPlane(coll.qvecRe()[4 * refAId + harmInd], coll.qvecIm()[4 * refAId + harmInd], i + 2); - eps[2] = helperEP.GetEventPlane(coll.qvecRe()[4 * refBId + harmInd], coll.qvecIm()[4 * refBId + harmInd], i + 2); - - auto deltapsiDet = 0.0; - auto deltapsiRefA = 0.0; - auto deltapsiRefB = 0.0; - - float weight = 1.0; - - qx_shifted[0] = coll.qvecRe()[4 * detId + harmInd]; - qy_shifted[0] = coll.qvecIm()[4 * detId + harmInd]; - qx_shifted[1] = coll.qvecRe()[4 * refAId + harmInd]; - qy_shifted[1] = coll.qvecIm()[4 * refAId + harmInd]; - qx_shifted[2] = coll.qvecRe()[4 * refBId + harmInd]; - qy_shifted[2] = coll.qvecIm()[4 * refBId + harmInd]; - - if (cfgManShiftCorr) { - constexpr int kShiftBins = 10; - for (int ishift = 1; ishift <= kShiftBins; ishift++) { - auto coeffshiftxDet = shiftprofile.at(i)->GetBinContent(shiftprofile.at(i)->FindBin(cent, 2.0 * detId + 0.5, ishift - 0.5)); - auto coeffshiftyDet = shiftprofile.at(i)->GetBinContent(shiftprofile.at(i)->FindBin(cent, 2.0 * detId + 1.5, ishift - 0.5)); - auto coeffshiftxRefA = shiftprofile.at(i)->GetBinContent(shiftprofile.at(i)->FindBin(cent, 2.0 * refAId + 0.5, ishift - 0.5)); - auto coeffshiftyRefA = shiftprofile.at(i)->GetBinContent(shiftprofile.at(i)->FindBin(cent, 2.0 * refAId + 1.5, ishift - 0.5)); - auto coeffshiftxRefB = shiftprofile.at(i)->GetBinContent(shiftprofile.at(i)->FindBin(cent, 2.0 * refBId + 0.5, ishift - 0.5)); - auto coeffshiftyRefB = shiftprofile.at(i)->GetBinContent(shiftprofile.at(i)->FindBin(cent, 2.0 * refBId + 1.5, ishift - 0.5)); - - deltapsiDet += ((2. / (1.0 * ishift)) * (-coeffshiftxDet * std::cos(ishift * static_cast(i + 2) * eps[0]) + coeffshiftyDet * std::sin(ishift * static_cast(i + 2) * eps[0]))) / static_cast(i + 2); - deltapsiRefA += ((2. / (1.0 * ishift)) * (-coeffshiftxRefA * std::cos(ishift * static_cast(i + 2) * eps[1]) + coeffshiftyRefA * std::sin(ishift * static_cast(i + 2) * eps[1]))) / static_cast(i + 2); - deltapsiRefB += ((2. / (1.0 * ishift)) * (-coeffshiftxRefB * std::cos(ishift * static_cast(i + 2) * eps[2]) + coeffshiftyRefB * std::sin(ishift * static_cast(i + 2) * eps[2]))) / static_cast(i + 2); - } - - eps[0] += deltapsiDet; - eps[1] += deltapsiRefA; - eps[2] += deltapsiRefB; - - qx_shifted[0] = coll.qvecRe()[4 * detId + harmInd] * std::cos(deltapsiDet) - coll.qvecIm()[4 * detId + harmInd] * std::sin(deltapsiDet); - qy_shifted[0] = coll.qvecRe()[4 * detId + harmInd] * std::sin(deltapsiDet) + coll.qvecIm()[4 * detId + harmInd] * std::cos(deltapsiDet); - qx_shifted[1] = coll.qvecRe()[4 * refAId + harmInd] * std::cos(deltapsiRefA) - coll.qvecIm()[4 * refAId + harmInd] * std::sin(deltapsiRefA); - qy_shifted[1] = coll.qvecRe()[4 * refAId + harmInd] * std::sin(deltapsiRefA) + coll.qvecIm()[4 * refAId + harmInd] * std::cos(deltapsiRefA); - qx_shifted[2] = coll.qvecRe()[4 * refBId + harmInd] * std::cos(deltapsiRefB) - coll.qvecIm()[4 * refBId + harmInd] * std::sin(deltapsiRefB); - qy_shifted[2] = coll.qvecRe()[4 * refBId + harmInd] * std::sin(deltapsiRefB) + coll.qvecIm()[4 * refBId + harmInd] * std::cos(deltapsiRefB); - } - - float resNumA = helperEP.GetResolution(eps[0], eps[1], i + 2); - float resNumB = helperEP.GetResolution(eps[0], eps[2], i + 2); - float resDenom = helperEP.GetResolution(eps[1], eps[2], i + 2); - - epFlowHistograms.fill(HIST("EpDet"), i + 2, cent, eps[0]); - epFlowHistograms.fill(HIST("EpRefA"), i + 2, cent, eps[1]); - epFlowHistograms.fill(HIST("EpRefB"), i + 2, cent, eps[2]); - - epFlowHistograms.fill(HIST("EpResDetRefA"), i + 2, cent, resNumA); - epFlowHistograms.fill(HIST("EpResDetRefB"), i + 2, cent, resNumB); - epFlowHistograms.fill(HIST("EpResRefARefB"), i + 2, cent, resDenom); - - epFlowHistograms.fill(HIST("EpResQvecDetRefAxx"), i + 2, cent, qx_shifted[0] * qx_shifted[1] + qy_shifted[0] * qy_shifted[1]); - epFlowHistograms.fill(HIST("EpResQvecDetRefAxy"), i + 2, cent, qx_shifted[1] * qy_shifted[0] - qx_shifted[0] * qy_shifted[1]); - epFlowHistograms.fill(HIST("EpResQvecDetRefBxx"), i + 2, cent, qx_shifted[0] * qx_shifted[2] + qy_shifted[0] * qy_shifted[2]); - epFlowHistograms.fill(HIST("EpResQvecDetRefBxy"), i + 2, cent, qx_shifted[2] * qy_shifted[0] - qx_shifted[0] * qy_shifted[2]); - epFlowHistograms.fill(HIST("EpResQvecRefARefBxx"), i + 2, cent, qx_shifted[1] * qx_shifted[2] + qy_shifted[1] * qy_shifted[2]); - epFlowHistograms.fill(HIST("EpResQvecRefARefBxy"), i + 2, cent, qx_shifted[2] * qy_shifted[1] - qx_shifted[1] * qy_shifted[2]); - - for (const auto& track : tracks) { - if (trackSel(track)) - continue; - - if (cfgEffCor) { - weight = getEfficiencyCorrection(effMap, track.eta(), track.pt(), cent, coll.posZ()); - } - - float vn = std::cos((i + 2) * (track.phi() - eps[0])); - float vnSin = std::sin((i + 2) * (track.phi() - eps[0])); - - epFlowHistograms.fill(HIST("vncos"), i + 2, cent, track.pt(), vn, weight); - epFlowHistograms.fill(HIST("vnsin"), i + 2, cent, track.pt(), vnSin, weight); - - epFlowHistograms.fill(HIST("SPvnxx"), i + 2, cent, track.pt(), (std::cos(track.phi() * static_cast(i + 2)) * qx_shifted[0] + std::sin(track.phi() * static_cast(i + 2)) * qy_shifted[0]), weight); - epFlowHistograms.fill(HIST("SPvnxy"), i + 2, cent, track.pt(), (std::sin(track.phi() * static_cast(i + 2)) * qx_shifted[0] - std::cos(track.phi() * static_cast(i + 2)) * qy_shifted[0]), weight); - } - } + fillvn(coll, tracks); } PROCESS_SWITCH(jEPFlowAnalysis, processDefault, "default process", true); @@ -399,31 +414,7 @@ struct jEPFlowAnalysis { } if (cfgAddEvtSel) { - if (std::abs(coll.posZ()) > cfgVertexZ) - return; - switch (cfgEvtSel) { - case 0: // Sel8 - if (!coll.sel8()) - return; - break; - case 1: // PbPb standard - if (!coll.sel8() || !coll.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) || !coll.selection_bit(aod::evsel::kNoSameBunchPileup)) - return; - break; - case 2: // PbPb with pileup - if (!coll.sel8() || !coll.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard) || - !coll.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) || !coll.selection_bit(aod::evsel::kNoSameBunchPileup)) - return; - break; - case 3: // Small systems (OO, NeNe, pp) - if (!coll.sel8() || !coll.selection_bit(aod::evsel::kNoSameBunchPileup)) - return; - break; - default: - LOGF(warning, "Event selection flag was not found, continuing without basic event selections!\n"); - } - // Check occupancy - if (coll.trackOccupancyInTimeRange() > cfgMaxOccupancy || coll.trackOccupancyInTimeRange() < cfgMinOccupancy) + if (!eventSel(coll)) return; } @@ -450,7 +441,7 @@ struct jEPFlowAnalysis { epFlowHistograms.fill(HIST("MC/hPartRec"), cent, coll.posZ(), trk.eta(), trk.phi(), trk.pt()); auto mctrk = trk.mcParticle(); if (mctrk.isPhysicalPrimary()) { - epFlowHistograms.fill(HIST("MChPartRecPr"), cent, coll.posZ(), trk.eta(), trk.phi(), trk.pt()); + epFlowHistograms.fill(HIST("MC/hPartRecPr"), cent, coll.posZ(), trk.eta(), trk.phi(), trk.pt()); } } } From 50968b2f94d756f4f2033d005514d259d7710be7 Mon Sep 17 00:00:00 2001 From: Neelkamal Mallick <104082831+nmallick19@users.noreply.github.com> Date: Mon, 2 Mar 2026 22:09:37 +0200 Subject: [PATCH 142/347] [PWGCF] Choice to drop step 6 (reco) when efficiency is loaded (#15229) --- PWGCF/Tasks/correlations.cxx | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/PWGCF/Tasks/correlations.cxx b/PWGCF/Tasks/correlations.cxx index aef81415c26..6044510a562 100644 --- a/PWGCF/Tasks/correlations.cxx +++ b/PWGCF/Tasks/correlations.cxx @@ -86,6 +86,7 @@ struct CorrelationTask { O2_DEFINE_CONFIGURABLE(cfgTwoTrackCut, float, -1, "Two track cut: -1 = off; >0 otherwise distance value (suggested: 0.02)"); O2_DEFINE_CONFIGURABLE(cfgTwoTrackCutMinRadius, float, 0.8f, "Two track cut: radius in m from which two track cuts are applied"); O2_DEFINE_CONFIGURABLE(cfgLocalEfficiency, int, 0, "0 = OFF and 1 = ON for local efficiency"); + O2_DEFINE_CONFIGURABLE(cfgDropStepRECO, bool, false, "choice to drop step RECO if efficiency correction is used") O2_DEFINE_CONFIGURABLE(cfgCentBinsForMC, int, 0, "0 = OFF and 1 = ON for data like multiplicity/centrality bins for MC steps"); O2_DEFINE_CONFIGURABLE(cfgTrackBitMask, uint16_t, 0, "BitMask for track selection systematics; refer to the enum TrackSelectionCuts in filtering task"); O2_DEFINE_CONFIGURABLE(cfgMultCorrelationsMask, uint16_t, 0, "Selection bitmask for the multiplicity correlations. This should match the filter selection cfgEstimatorBitMask.") @@ -862,10 +863,14 @@ struct CorrelationTask { else fillQA(collision, multiplicity, tracks1); - same->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); - fillCorrelations(same, tracks1, tracks2, multiplicity, collision.posZ(), field, 1.0f); + const bool hasEfficiency = (cfg.mEfficiencyAssociated != nullptr || cfg.mEfficiencyTrigger != nullptr); + const bool fillReco = !(cfgDropStepRECO && hasEfficiency); - if (cfg.mEfficiencyAssociated || cfg.mEfficiencyTrigger) { + if (fillReco) { + same->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); + fillCorrelations(same, tracks1, tracks2, multiplicity, collision.posZ(), field, 1.0f); + } + if (hasEfficiency) { same->fillEvent(multiplicity, CorrelationContainer::kCFStepCorrected); fillCorrelations(same, tracks1, tracks2, multiplicity, collision.posZ(), field, 1.0f); } @@ -988,19 +993,28 @@ struct CorrelationTask { LOGF(info, "processMixedDerived: Mixed collisions bin: %d pair: [%d, %d] %d (%.3f, %.3f), %d (%.3f, %.3f)", bin, it.isNewWindow(), it.currentWindowNeighbours(), collision1.globalIndex(), collision1.posZ(), collision1.multiplicity(), collision2.globalIndex(), collision2.posZ(), collision2.multiplicity()); } + bool hasEfficiencyMixed = (cfg.mEfficiencyAssociated != nullptr || cfg.mEfficiencyTrigger != nullptr); + bool fillRecoMixed = !(cfgDropStepRECO && hasEfficiencyMixed); + if (it.isNewWindow()) { loadEfficiency(collision1.timestamp()); + hasEfficiencyMixed = (cfg.mEfficiencyAssociated != nullptr || cfg.mEfficiencyTrigger != nullptr); + fillRecoMixed = !(cfgDropStepRECO && hasEfficiencyMixed); - mixed->fillEvent(collision1.multiplicity(), CorrelationContainer::kCFStepReconstructed); + if (fillRecoMixed) { + mixed->fillEvent(collision1.multiplicity(), CorrelationContainer::kCFStepReconstructed); + } } // LOGF(info, "Tracks: %d and %d entries", tracks1.size(), tracks2.size()); registry.fill(HIST("eventcount_mixed"), bin); registry.fill(HIST("trackcount_mixed"), bin, tracks1.size(), tracks2.size()); - fillCorrelations(mixed, tracks1, tracks2, collision1.multiplicity(), collision1.posZ(), field, eventWeight); + if (fillRecoMixed) { + fillCorrelations(mixed, tracks1, tracks2, collision1.multiplicity(), collision1.posZ(), field, eventWeight); + } - if (cfg.mEfficiencyAssociated || cfg.mEfficiencyTrigger) { + if (hasEfficiencyMixed) { if (it.isNewWindow()) { mixed->fillEvent(collision1.multiplicity(), CorrelationContainer::kCFStepCorrected); } From 6843b0bef731c622a92fb5741b68a8ad07ef5db7 Mon Sep 17 00:00:00 2001 From: omvazque Date: Mon, 2 Mar 2026 14:19:43 -0600 Subject: [PATCH 143/347] [PWGLF] Event Selection: Splits sel8 into their components (#15228) --- PWGLF/Tasks/Nuspex/piKpRAA.cxx | 99 +++++++++++++++++++++++----------- 1 file changed, 69 insertions(+), 30 deletions(-) diff --git a/PWGLF/Tasks/Nuspex/piKpRAA.cxx b/PWGLF/Tasks/Nuspex/piKpRAA.cxx index 9d046f974db..c28ce0955db 100644 --- a/PWGLF/Tasks/Nuspex/piKpRAA.cxx +++ b/PWGLF/Tasks/Nuspex/piKpRAA.cxx @@ -212,6 +212,11 @@ struct PiKpRAA { Configurable isCentSel{"isCentSel", true, "Centrality selection?"}; Configurable selHasFT0{"selHasFT0", true, "Has FT0?"}; Configurable isT0Ccent{"isT0Ccent", true, "Use T0C-based centrality?"}; + + Configurable useSel8{"useSel8", false, "Use sel8?"}; + Configurable selTriggerTVX{"selTriggerTVX", true, "selTriggerTVX?"}; + Configurable selNoITSROFrameBorder{"selNoITSROFrameBorder", true, "selNoITSROFrameBorder?"}; + Configurable selNoTimeFrameBorder{"selNoTimeFrameBorder", true, "selNoTimeFrameBorder?"}; Configurable isZvtxPosSel{"isZvtxPosSel", true, "Zvtx position selection?"}; Configurable isZvtxPosSelMC{"isZvtxPosSelMC", true, "Zvtx position selection for MC events?"}; Configurable selTVXMC{"selTVXMC", true, "apply TVX selection in MC?"}; @@ -271,8 +276,12 @@ struct PiKpRAA { enum EvCutLabel { All = 1, SelEigth, - NoSameBunchPileup, + SelTriggerTVX, + SelNoITSROFrameBorder, + SelNoTimeFrameBorder, + VtxZ, IsGoodZvtxFT0vsPV, + NoSameBunchPileup, NoCollInTimeRangeStrict, NoCollInTimeRangeStandard, NoCollInRofStrict, @@ -282,7 +291,6 @@ struct PiKpRAA { OccuCut, HasFT0, Centrality, - VtxZ, NchSel, INELgt0 }; @@ -379,7 +387,7 @@ struct PiKpRAA { // define axes you want to use const std::string titlePorPt{v0Selections.usePinPhiSelection ? "#it{p} (GeV/#it{c})" : "#it{p}_{T} (GeV/#it{c})"}; const AxisSpec axisZpos{binsZpos, "Vtx_{z} (cm)"}; - const AxisSpec axisEvent{17, 0.5, 17.5, ""}; + const AxisSpec axisEvent{22, 0.5, 22.5, ""}; const AxisSpec axisNcl{161, -0.5, 160.5, "#it{N}_{cl} TPC"}; const AxisSpec axisPt{binsPt, "#it{p}_{T} (GeV/#it{c})"}; const AxisSpec axisPtV0s{binsPtV0s, "#it{p}_{T} (GeV/#it{c})"}; @@ -403,20 +411,23 @@ struct PiKpRAA { auto* x = hstat->GetXaxis(); x->SetBinLabel(1, "All"); x->SetBinLabel(2, "SelEigth"); - x->SetBinLabel(3, "NoSameBunchPileup"); - x->SetBinLabel(4, "GoodZvtxFT0vsPV"); - x->SetBinLabel(5, "NoCollInTimeRangeStrict"); - x->SetBinLabel(6, "NoCollInTimeRangeStandard"); - x->SetBinLabel(7, "NoCollInRofStrict"); - x->SetBinLabel(8, "NoCollInRofStandard"); - x->SetBinLabel(9, "NoHighMultCollInPrevRof"); - x->SetBinLabel(10, "NoCollInTimeRangeNarrow"); - x->SetBinLabel(11, "Occupancy Cut"); - x->SetBinLabel(12, "Has FT0?"); - x->SetBinLabel(13, "Cent. Sel."); - x->SetBinLabel(14, "VtxZ Sel."); - x->SetBinLabel(15, "Nch Sel."); - x->SetBinLabel(16, "INEL > 0"); + x->SetBinLabel(3, "SelTriggerTVX"); + x->SetBinLabel(4, "SelNoITSROFrameBorder"); + x->SetBinLabel(5, "SelNoTimeFrameBorder"); + x->SetBinLabel(6, "VtxZ Sel."); + x->SetBinLabel(7, "GoodZvtxFT0vsPV"); + x->SetBinLabel(8, "NoSameBunchPileup"); + x->SetBinLabel(9, "NoCollInTimeRangeStrict"); + x->SetBinLabel(10, "NoCollInTimeRangeStandard"); + x->SetBinLabel(11, "NoCollInRofStrict"); + x->SetBinLabel(12, "NoCollInRofStandard"); + x->SetBinLabel(13, "NoHighMultCollInPrevRof"); + x->SetBinLabel(14, "NoCollInTimeRangeNarrow"); + x->SetBinLabel(15, "Occupancy Cut"); + x->SetBinLabel(16, "Has FT0?"); + x->SetBinLabel(17, "Cent. Sel."); + x->SetBinLabel(18, "Nch Sel."); + x->SetBinLabel(19, "INEL > 0"); if (doprocessCalibrationAndV0s) { registry.add("T0CcentVsRCTSel", "Bad RCT(=0.5) Good RCT(=1.5) Good RCT & Good PID RCT(=2.5);;RCT Status;", kTH2F, {{{axisCent}, {3, 0, 3}}}); @@ -1979,16 +1990,44 @@ struct PiKpRAA { bool isEventSelected(CheckCol const& col) { registry.fill(HIST("EventCounter"), EvCutLabel::All); - if (!col.sel8()) { - return false; + + if (useSel8) { + if (!col.sel8()) { + return false; + } + registry.fill(HIST("EventCounter"), EvCutLabel::SelEigth); } - registry.fill(HIST("EventCounter"), EvCutLabel::SelEigth); - if (selNoSameBunchPileup) { - if (!col.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + // kIsTriggerTVX + if (selTriggerTVX) { + if (!col.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { return false; } - registry.fill(HIST("EventCounter"), EvCutLabel::NoSameBunchPileup); + registry.fill(HIST("EventCounter"), EvCutLabel::SelTriggerTVX); + } + + // kNoITSROFrameBorder + if (selNoITSROFrameBorder) { + if (!col.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + return false; + } + registry.fill(HIST("EventCounter"), EvCutLabel::SelNoITSROFrameBorder); + } + + // kNoTimeFrameBorder + if (selNoTimeFrameBorder) { + if (!col.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + return false; + } + registry.fill(HIST("EventCounter"), EvCutLabel::SelNoTimeFrameBorder); + } + + // Zvtx + if (isZvtxPosSel) { + if (std::fabs(col.posZ()) > posZcut) { + return false; + } + registry.fill(HIST("EventCounter"), EvCutLabel::VtxZ); } if (selIsGoodZvtxFT0vsPV) { @@ -1998,6 +2037,13 @@ struct PiKpRAA { registry.fill(HIST("EventCounter"), EvCutLabel::IsGoodZvtxFT0vsPV); } + if (selNoSameBunchPileup) { + if (!col.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + return false; + } + registry.fill(HIST("EventCounter"), EvCutLabel::NoSameBunchPileup); + } + if (isNoCollInTimeRangeStrict) { if (!col.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStrict)) { return false; @@ -2064,13 +2110,6 @@ struct PiKpRAA { registry.fill(HIST("EventCounter"), EvCutLabel::Centrality); } - if (isZvtxPosSel) { - if (std::fabs(col.posZ()) > posZcut) { - return false; - } - registry.fill(HIST("EventCounter"), EvCutLabel::VtxZ); - } - if (selINELgt0) { if (!col.isInelGt0()) { return false; From 3956d70d4f03302c48f06b03ac1d29707306cac0 Mon Sep 17 00:00:00 2001 From: skundu692 <86804743+skundu692@users.noreply.github.com> Date: Mon, 2 Mar 2026 23:16:30 +0100 Subject: [PATCH 144/347] [PWGLF] Add new process function for MC spin correlation, fix systematic selection for f1-p correlation (#15230) --- .../Resonances/f1protonreducedtable.cxx | 62 +- .../Tasks/Resonances/f1protoncorrelation.cxx | 156 ++--- PWGLF/Tasks/Resonances/phipbpb.cxx | 52 +- .../Strangeness/lambdaspincorrderived.cxx | 545 +++++++++++++++++- 4 files changed, 726 insertions(+), 89 deletions(-) diff --git a/PWGLF/TableProducer/Resonances/f1protonreducedtable.cxx b/PWGLF/TableProducer/Resonances/f1protonreducedtable.cxx index 4cbdecef436..90cfd3f4d5f 100644 --- a/PWGLF/TableProducer/Resonances/f1protonreducedtable.cxx +++ b/PWGLF/TableProducer/Resonances/f1protonreducedtable.cxx @@ -84,6 +84,7 @@ struct f1protonreducedtable { Configurable trackSphMin{"trackSphMin", 10, "Number of tracks for Spherocity Calculation"}; // Configs for track PID + Configurable Confglobaltrackcheck{"Confglobaltrackcheck", true, "Global track check"}; Configurable cfgSkimmedProcessing{"cfgSkimmedProcessing", true, "Analysed skimmed events"}; Configurable ConfUseManualPIDproton{"ConfUseManualPIDproton", true, "True: use home-made PID solution for proton "}; Configurable ConfUseManualPIDkaon{"ConfUseManualPIDkaon", true, "True: use home-made PID solution for kaon "}; @@ -161,8 +162,8 @@ struct f1protonreducedtable { {"hInvMassf1Like", "hInvMassf1Like", {HistType::kTH2F, {{400, 1.1f, 1.9f}, {100, 0.0f, 10.0f}}}}, {"hInvMassf1kstar", "hInvMassf1kstar", {HistType::kTH3F, {{400, 1.1f, 1.9f}, {100, 0.0f, 10.0f}, {8, 0.0f, 0.8f}}}}, {"hkstarDist", "hkstarDist", {HistType::kTH1F, {{300, 0.0f, 3.0f}}}}, - {"hDCAxy", "hDCAxy", {HistType::kTH1F, {{100, -5.0f, 5.0f}}}}, - {"hDCAz", "hDCAz", {HistType::kTH1F, {{100, -5.0f, 5.0f}}}}, + {"hDCAxy", "hDCAxy", {HistType::kTH3F, {{100, -0.05f, 0.05f}, {5, -2.5, 2.5}, {40, 0.0, 4.0}}}}, + {"hDCAz", "hDCAz", {HistType::kTH3F, {{100, -0.05f, 0.05f}, {2, 0, 2}, {40, 0.0, 4.0}}}}, {"hPhi", "hPhi", {HistType::kTH1F, {{1400, -7.0f, 7.0f}}}}, {"hPhiSphero", "hPhiSphero", {HistType::kTH1F, {{1400, -7.0f, 7.0f}}}}, {"hEta", "hEta", {HistType::kTH1F, {{20, -1.0f, 1.0f}}}}, @@ -170,7 +171,7 @@ struct f1protonreducedtable { {"hNsigmaPtpionTOF", "hNsigmaPtpionTOF", {HistType::kTH2F, {{200, -10.0f, 10.0f}, {100, 0.0f, 10.0f}}}}, {"hNsigmaPtkaonTPC", "hNsigmaPtkaonTPC", {HistType::kTH3F, {{200, -10.0f, 10.0f}, {200, -20.0f, 20.0f}, {100, 0.0f, 10.0f}}}}, {"hNsigmaPtkaonTOF", "hNsigmaPtkaonTOF", {HistType::kTH2F, {{200, -10.0f, 10.0f}, {100, 0.0f, 10.0f}}}}, - {"hNsigmaPtprotonTPC", "hNsigmaPtprotonTPC", {HistType::kTH2F, {{200, -10.0f, 10.0f}, {100, 0.0f, 10.0f}}}}, + {"hNsigmaPtprotonTPC", "hNsigmaPtprotonTPC", {HistType::kTH3F, {{100, -5.0f, 5.0f}, {100, -5.0f, 5.0f}, {100, 0.0f, 10.0f}}}}, {"hNsigmaPtprotonTOF", "hNsigmaPtprotonTOF", {HistType::kTH2F, {{200, -10.0f, 10.0f}, {100, 0.0f, 10.0f}}}}, {"hInvMassk0", "hInvMassk0", {HistType::kTH2F, {{200, 0.4f, 0.6f}, {100, 0.0f, 10.0f}}}}, }, @@ -265,7 +266,7 @@ struct f1protonreducedtable { template bool selectionGlobalTrack(const T& candidate) { - if (!(candidate.isGlobalTrack() && candidate.isPVContributor())) { + if (Confglobaltrackcheck && !(candidate.isGlobalTrack() && candidate.isPVContributor())) { return false; } return true; @@ -348,6 +349,32 @@ struct f1protonreducedtable { return false; } + inline bool passProtonPID(float nsigmaTPC, float nsigmaTOF, float TOFHit, ROOT::Math::PtEtaPhiMVector proton) + { + // pidMode: + // 0 = default: p < thr -> |TPC| < 2.5 ; p >= thr -> TOF mandatory AND circular(TPC,TOF) < 2.0 + // 1 = syst-1: p < thr -> |TPC| < 2.0 ; p >= thr -> TOF mandatory AND circular(TPC,TOF) < 2.0 + // 2 = syst-2: p < thr -> |TPC| < 2.5 ; p >= thr -> TOF mandatory AND circular(TPC,TOF) < 2.5 + + if (proton.Pt() > 4.0 || proton.Pt() < 0.15) { + return false; + } + + if (proton.P() < 0.7) { + return (std::abs(nsigmaTPC) < 2.5); + } + + // above threshold: TOF must exist + if (TOFHit != 1) { + return false; + } + + const float nsTPC = nsigmaTPC; + const float nsTOF = nsigmaTOF; + const float comb = std::sqrt(nsTPC * nsTPC + nsTOF * nsTOF); + return (comb < 2.5); + } + template bool SelectionV0(Collision const& collision, V0 const& candidate) { @@ -682,8 +709,6 @@ struct f1protonreducedtable { if (!selectionGlobalTrack(track)) { continue; } - qaRegistry.fill(HIST("hDCAxy"), track.dcaXY()); - qaRegistry.fill(HIST("hDCAz"), track.dcaZ()); qaRegistry.fill(HIST("hEta"), track.eta()); qaRegistry.fill(HIST("hPhi"), track.phi()); double nTPCSigmaP[3]{track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr()}; @@ -778,17 +803,15 @@ struct f1protonreducedtable { ProtonIndex.push_back(track.globalIndex()); ProtonCharge.push_back(track.sign()); - ProtonDcaxy.push_back(std::abs(track.dcaXY())); - ProtonDcaz.push_back(std::abs(track.dcaZ())); + ProtonDcaxy.push_back(track.dcaXY()); + ProtonDcaz.push_back(track.dcaZ()); ProtonTPCNcls.push_back(std::abs(track.tpcNClsFound())); ProtonTPCNcrs.push_back(std::abs(track.tpcNClsCrossedRows())); if (track.sign() > 0) { - qaRegistry.fill(HIST("hNsigmaPtprotonTPC"), nTPCSigmaP[2], track.pt()); ProtonTPCNsigma.push_back(nTPCSigmaP[2]); } if (track.sign() < 0) { - qaRegistry.fill(HIST("hNsigmaPtprotonTPC"), nTPCSigmaN[2], track.pt()); ProtonTPCNsigma.push_back(nTPCSigmaN[2]); } if (track.hasTOF()) { @@ -961,6 +984,25 @@ struct f1protonreducedtable { } } qaRegistry.fill(HIST("hEventstat"), 0.5); + if (keepEventF1Proton) { + for (auto iproton = protons.begin(); iproton != protons.end(); ++iproton) { + auto i6 = std::distance(protons.begin(), iproton); + ProtonVectorDummy2 = protons.at(i6); + if (std::abs(ProtonDcaxy.at(i6)) < 0.05 && std::abs(ProtonDcaz.at(i6)) < 0.05) { + if (ProtonTOFHit.at(i6) && ProtonVectorDummy2.P() > 0.7) { + qaRegistry.fill(HIST("hNsigmaPtprotonTPC"), ProtonTPCNsigma.at(i6), ProtonTOFNsigma.at(i6), ProtonVectorDummy2.Pt()); + } + if (ProtonVectorDummy2.P() < 0.7) { + qaRegistry.fill(HIST("hNsigmaPtprotonTPC"), ProtonTPCNsigma.at(i6), 4.999, ProtonVectorDummy2.Pt()); + } + } + if (passProtonPID(ProtonTPCNsigma.at(i6), ProtonTOFNsigma.at(i6), ProtonTOFHit.at(i6), ProtonVectorDummy2)) { + qaRegistry.fill(HIST("hDCAxy"), ProtonDcaxy.at(i6), ProtonCharge.at(i6), ProtonVectorDummy2.Pt()); + qaRegistry.fill(HIST("hDCAz"), ProtonDcaz.at(i6), ProtonCharge.at(i6), ProtonVectorDummy2.Pt()); + } + } + } + if (numberF1 > 0 && (f1resonance.size() == f1signal.size()) && (f1resonance.size() == f1kaonkshortmass.size()) && (f1resonance.size() == f1resonanced1.size()) && (f1resonance.size() == f1resonanced2.size()) && (f1resonance.size() == f1resonanced3.size())) { qaRegistry.fill(HIST("hEventstat"), 1.5); if (keepEventF1Proton) { diff --git a/PWGLF/Tasks/Resonances/f1protoncorrelation.cxx b/PWGLF/Tasks/Resonances/f1protoncorrelation.cxx index e09cdfde1a4..63568887fab 100644 --- a/PWGLF/Tasks/Resonances/f1protoncorrelation.cxx +++ b/PWGLF/Tasks/Resonances/f1protoncorrelation.cxx @@ -44,6 +44,7 @@ #include #include #include +#include #include using namespace o2; @@ -140,86 +141,94 @@ struct f1protoncorrelation { // ------------------------- void buildSystematicCuts() { - // choices from your table/picture - const std::array optDcaxy{0.01f, 0.03f}; - const std::array optDcaz{0.01f, 0.03f}; - const std::array optNcrs{90, 100}; - const std::array optNcls{90, 100}; - - const std::array optCPA{0.99f, 0.995f}; - const std::array optRad{0.8f, 1.0f}; - const std::array optDcaDD{0.9f, 0.8f}; - const std::array optDcaV0{0.2f, 0.15f}; - const std::array optLife{16.f, 18.f}; - const std::array optDcaD1{0.06f, 0.08f}; - const std::array optDcaD2{0.06f, 0.08f}; - - // bit layout: - // primary: 4 bits (0..3) - // v0: 7 bits (4..10) - // pid: 3 bits (11..13) - // total: 14 bits -> 16384 combos - auto buildFromMask = [&](uint32_t m) -> SysCuts { + // 3 options per cut: index 0 = DEFAULT, index 1/2 = variations + // Fill these with the exact values you want (I used your def as index 0 + your old options as 1/2) + const std::array optDcaxy{0.05f, 0.01f, 0.03f}; + const std::array optDcaz{0.05f, 0.01f, 0.03f}; + const std::array optNcrs{80, 90, 100}; + const std::array optNcls{80, 90, 100}; + + const std::array optCPA{0.985f, 0.99f, 0.995f}; + const std::array optRad{0.50f, 0.80f, 1.00f}; + const std::array optDcaDD{1.00f, 0.90f, 0.80f}; + const std::array optDcaV0{0.30f, 0.20f, 0.15f}; + const std::array optLife{20.f, 16.f, 18.f}; + const std::array optDcaD1{0.05f, 0.06f, 0.08f}; + const std::array optDcaD2{0.05f, 0.06f, 0.08f}; + + // PID modes: also allow default (0) to appear in random variations + const std::array optPidPi{0, 1, 2}; + const std::array optPidK{0, 1, 2}; + const std::array optPidP{0, 1, 2}; + + // Helper: build SysCuts from chosen indices (0..2) + auto buildFromIdx = [&](int i0, int i1, int i2, int i3, + int i4, int i5, int i6, int i7, int i8, int i9, int i10, + int i11, int i12, int i13) -> SysCuts { SysCuts c{}; - c.maxDcaxy = optDcaxy[(m >> 0) & 1u]; - c.maxDcaz = optDcaz[(m >> 1) & 1u]; - c.minTPCCrossedRows = optNcrs[(m >> 2) & 1u]; - c.minTPCClusters = optNcls[(m >> 3) & 1u]; - - c.minCPA = optCPA[(m >> 4) & 1u]; - c.minRadius = optRad[(m >> 5) & 1u]; - c.maxDcaDaughters = optDcaDD[(m >> 6) & 1u]; - c.maxDcaV0 = optDcaV0[(m >> 7) & 1u]; - c.maxLifetime = optLife[(m >> 8) & 1u]; - c.minDcaD1 = optDcaD1[(m >> 9) & 1u]; - c.minDcaD2 = optDcaD2[(m >> 10) & 1u]; - - c.pidPi = (m >> 11) & 1u; - c.pidK = (m >> 12) & 1u; - c.pidP = (m >> 13) & 1u; + c.maxDcaxy = optDcaxy[i0]; + c.maxDcaz = optDcaz[i1]; + c.minTPCCrossedRows = optNcrs[i2]; + c.minTPCClusters = optNcls[i3]; + + c.minCPA = optCPA[i4]; + c.minRadius = optRad[i5]; + c.maxDcaDaughters = optDcaDD[i6]; + c.maxDcaV0 = optDcaV0[i7]; + c.maxLifetime = optLife[i8]; + c.minDcaD1 = optDcaD1[i9]; + c.minDcaD2 = optDcaD2[i10]; + + c.pidPi = optPidPi[i11]; + c.pidK = optPidK[i12]; + c.pidP = optPidP[i13]; return c; }; - // DEFAULT (sysId=0): set to your baseline - SysCuts def{}; - def.maxDcaxy = 0.05f; - def.maxDcaz = 0.05f; - def.minTPCCrossedRows = 80; - def.minTPCClusters = 80; - - def.minCPA = 0.985f; - def.minRadius = 0.5f; - def.maxDcaDaughters = 1.0f; - def.maxDcaV0 = 0.3f; - def.maxLifetime = 20.f; - def.minDcaD1 = 0.05f; - def.minDcaD2 = 0.05f; - - def.pidPi = 0; - def.pidK = 0; - def.pidP = 0; - - std::vector masks; - masks.reserve(16384); - for (uint32_t m = 0; m < 16384; ++m) { - masks.push_back(m); - } + // sysId=0 must be strict default (all indices = 0) + SysCuts def = buildFromIdx(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); std::mt19937 rng(sysSeed); - std::shuffle(masks.begin(), masks.end(), rng); + std::uniform_int_distribution pick012(0, 2); + + // Optional: keep unique combinations (by packing indices in 2 bits each) + auto packCode = [&](const std::array& idx) -> uint32_t { + uint32_t code = 0u; + for (int k = 0; k < 14; ++k) { + code |= (uint32_t(idx[k] & 0x3) << (2 * k)); + } + return code; + }; sysCuts.clear(); - sysCuts.reserve(1 + nSysRand); - sysCuts.push_back(def); + sysCuts.reserve(1 + (size_t)nSysRand); + sysCuts.push_back(def); // sysId=0 + + std::unordered_set used; + used.reserve((size_t)nSysRand * 2); + used.insert(0u); // all-default code + + const int nPick = std::max(0, (int)nSysRand); + while ((int)sysCuts.size() < 1 + nPick) { + + std::array idx{}; + for (int k = 0; k < 14; ++k) + idx[k] = pick012(rng); + + uint32_t code = packCode(idx); + if (!used.insert(code).second) + continue; // already have this combination - const int nPick = std::min(nSysRand, (int)masks.size()); - for (int i = 0, picked = 0; picked < nPick && i < (int)masks.size(); ++i) { - if (masks[i] == 0u) { // avoid trivial mask that can reproduce default + // (optional) avoid generating exactly default again + if (code == 0u) continue; - } - sysCuts.push_back(buildFromMask(masks[i])); - ++picked; + + sysCuts.push_back(buildFromIdx( + idx[0], idx[1], idx[2], idx[3], + idx[4], idx[5], idx[6], idx[7], idx[8], idx[9], idx[10], + idx[11], idx[12], idx[13])); } + nSysTotal = (int)sysCuts.size(); } @@ -598,7 +607,7 @@ struct f1protoncorrelation { } auto relative_momentum = getkstar(F1, Proton); if (relative_momentum <= 0.5) { - histos.fill(HIST("hNsigmaProtonTPC"), protontrack.protonNsigmaTPC(), Proton.Pt()); + histos.fill(HIST("hNsigmaProtonTPC"), protontrack.protonNsigmaTPC(), protontrack.protonNsigmaTOF(), Proton.Pt()); } histos.fill(HIST("h2SameEventPtCorrelation"), relative_momentum, F1.Pt(), Proton.Pt()); @@ -968,7 +977,8 @@ struct f1protoncorrelation { Kaon.SetXYZM(f1track.f1d2Px(), f1track.f1d2Py(), f1track.f1d2Pz(), 0.493); Kshort.SetXYZM(f1track.f1d3Px(), f1track.f1d3Py(), f1track.f1d3Pz(), 0.497); KaonKshortPair = Kaon + Kshort; - + if (F1.Pt() < lowPtF1 || F1.Pt() > 50.0) + continue; std::vector activeSys; activeSys.reserve((size_t)nSysTotal); @@ -1014,7 +1024,7 @@ struct f1protoncorrelation { const auto& sc0 = sysCuts[0]; - if (countf1 && passPrimary(protontrack.protonDcaxy(), protontrack.protonDcaz(), protontrack.protonTPCNcrs(), protontrack.protonTPCNcls(), sc0)) { + if (countf1 && passPrimary(protontrack.protonDcaxy(), protontrack.protonDcaz(), protontrack.protonTPCNcrs(), protontrack.protonTPCNcls(), sc0) && passProtonPID(0, protontrack, Proton, pMinP, pMaxP, pTofP)) { histos.fill(HIST("hNsigmaProtonTPC"), protontrack.protonNsigmaTPC(), protontrack.protonNsigmaTOF(), Proton.Pt()); } @@ -1110,6 +1120,8 @@ struct f1protoncorrelation { Kshort.SetXYZM(t1.f1d3Px(), t1.f1d3Py(), t1.f1d3Pz(), 0.497); KaonKshortPair = Kaon + Kshort; Proton.SetXYZM(t2.protonPx(), t2.protonPy(), t2.protonPz(), 0.938); + if (F1.Pt() < lowPtF1 || F1.Pt() > 50.0) + continue; auto relative_momentum = getkstar(F1, Proton); auto mT = getmT(F1, Proton); // sys list for this (F1, p) pair diff --git a/PWGLF/Tasks/Resonances/phipbpb.cxx b/PWGLF/Tasks/Resonances/phipbpb.cxx index 2468059b1de..87d75fc8a2a 100644 --- a/PWGLF/Tasks/Resonances/phipbpb.cxx +++ b/PWGLF/Tasks/Resonances/phipbpb.cxx @@ -93,7 +93,7 @@ struct phipbpb { Configurable fillSA{"fillSA", false, "fill spin alignment"}; // events Configurable cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted z-vertex range"}; - Configurable cfgCutCentrality{"cfgCutCentrality", 80.0f, "Accepted maximum Centrality"}; + Configurable cfgCutCentrality{"cfgCutCentrality", 100.0f, "Accepted maximum Centrality"}; Configurable cfgCutOccupancy{"cfgCutOccupancy", 3000, "Occupancy cut"}; // track Configurable cqvas{"cqvas", false, "change q vectors after shift correction"}; @@ -198,6 +198,9 @@ struct phipbpb { AxisSpec centAxis = {8, 0, 80, "V0M (%)"}; AxisSpec occupancyAxis = {occupancyBinning, "Occupancy"}; AxisSpec spAxis = {spNbins, lbinsp, hbinsp, "Sp"}; + histos.add("hImpactParameterVsEvrStatusGen", "hImpactParameterVsEvrStatusGen", HistType::kTH2F, {{200, 0.0, 20.0}, {5, 0.0, 5.0}}, true); + histos.add("hImpactParameterVsEvrStatusRec", "hImpactParameterVsEvrStatusRec", HistType::kTH3F, {{200, 0.0, 20.0}, {100, 0.0, 100.0}, {10, 0.0, 10.0}}, true); + histos.add("hINumRecCollisionVsEvrStatusRec", "hINumRecCollisionVsEvrStatusRec", HistType::kTH3F, {{21, -0.5, 20.5}, {100, 0.0, 100.0}, {10, 0.0, 10.0}}, true); if (fillv1) { histos.add("hpQxtQxpvscent", "hpQxtQxpvscent", HistType::kTHnSparseF, {cnfgaxis.configThnAxisCentrality, spAxis}, true); @@ -792,7 +795,7 @@ struct phipbpb { Npostrack = Npostrack + 1; } } - PROCESS_SWITCH(phipbpb, processSameEvent, "Process Same event", true); + PROCESS_SWITCH(phipbpb, processSameEvent, "Process Same event", false); void processSameEventv1(EventCandidatesv1::iterator const& collision, TrackCandidates const& /*tracks, aod::BCs const&*/, aod::BCsWithTimestamps const&) { @@ -1045,7 +1048,7 @@ struct phipbpb { } } } - PROCESS_SWITCH(phipbpb, processMEAcc, "Process ME Acceptance", true); + PROCESS_SWITCH(phipbpb, processMEAcc, "Process ME Acceptance", false); void processMEAccv1(EventCandidatesv1 const& collisions, TrackCandidates const& tracks) { @@ -1303,7 +1306,7 @@ struct phipbpb { } } } - PROCESS_SWITCH(phipbpb, processMixedEventOpti, "Process Mixed event new", true); + PROCESS_SWITCH(phipbpb, processMixedEventOpti, "Process Mixed event new", false); void processMixedEventOptiv1(EventCandidatesv1 const& collisions, TrackCandidates const& tracks) { @@ -1877,6 +1880,47 @@ struct phipbpb { } // process MC PROCESS_SWITCH(phipbpb, processMCPhiWeight, "Process MC Phi Weight", false); + + using McCollisionMults = soa::Join; + using EventCandidatesMC = soa::Join; + void processEvtLossMC(McCollisionMults::iterator const& mcCollision, const soa::SmallGroups& recCollisions) + { + auto impactPar = mcCollision.impactParameter(); + histos.fill(HIST("hImpactParameterVsEvrStatusGen"), impactPar, 0.5); + if (mcCollision.isInelGt0()) { + histos.fill(HIST("hImpactParameterVsEvrStatusGen"), impactPar, 1.5); + } + auto numberRecCollision = recCollisions.size(); + for (const auto& RecCollision : recCollisions) { + auto isTVX = RecCollision.selection_bit(o2::aod::evsel::kIsTriggerTVX); + auto vz = TMath::Abs(RecCollision.posZ()); + auto issel8 = RecCollision.sel8(); + auto isITSGoodLayer = RecCollision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll); + auto isGoodVtxzFT0vsPV = RecCollision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV); + auto isSameBunchPileup = RecCollision.selection_bit(o2::aod::evsel::kNoSameBunchPileup); + auto centrality = RecCollision.centFT0C(); + histos.fill(HIST("hImpactParameterVsEvrStatusRec"), impactPar, centrality, 0.5); + histos.fill(HIST("hINumRecCollisionVsEvrStatusRec"), numberRecCollision, centrality, 0.5); + if (isTVX) { + histos.fill(HIST("hImpactParameterVsEvrStatusRec"), impactPar, centrality, 1.5); + histos.fill(HIST("hINumRecCollisionVsEvrStatusRec"), numberRecCollision, centrality, 1.5); + } + if (isTVX && vz < 7) { + histos.fill(HIST("hImpactParameterVsEvrStatusRec"), impactPar, centrality, 2.5); + histos.fill(HIST("hINumRecCollisionVsEvrStatusRec"), numberRecCollision, centrality, 2.5); + } + if (isTVX && vz < 7 && issel8) { + histos.fill(HIST("hImpactParameterVsEvrStatusRec"), impactPar, centrality, 3.5); + histos.fill(HIST("hINumRecCollisionVsEvrStatusRec"), numberRecCollision, centrality, 3.5); + } + if (isTVX && vz < 7 && issel8 && isITSGoodLayer && isGoodVtxzFT0vsPV && isSameBunchPileup) { + histos.fill(HIST("hImpactParameterVsEvrStatusRec"), impactPar, centrality, 4.5); + histos.fill(HIST("hINumRecCollisionVsEvrStatusRec"), numberRecCollision, centrality, 4.5); + } + } + //} + } + PROCESS_SWITCH(phipbpb, processEvtLossMC, "Process to calculate Event Loss", true); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { diff --git a/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx b/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx index c2d50cfbc87..51e13a779f1 100644 --- a/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx +++ b/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx @@ -59,6 +59,118 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::soa; +namespace mcacc +{ +// event +template +static inline float cent(const Coll& c) +{ + return c.centmc(); +} + +template +static inline float posz(const Coll& c) +{ + return c.poszmc(); +} + +// pair / v0 candidate +template +static inline int v0Status(const T& t) +{ + return t.v0Statusmc(); +} + +template +static inline bool doubleStatus(const T& t) +{ + return t.doubleStatusmc(); +} + +template +static inline float v0CosPA(const T& t) +{ + return t.v0Cospamc(); +} + +template +static inline float v0Radius(const T& t) +{ + return t.v0Radiusmc(); +} + +template +static inline float dcaPos(const T& t) +{ + return t.dcaPositivemc(); +} + +template +static inline float dcaNeg(const T& t) +{ + return t.dcaNegativemc(); +} + +template +static inline float dcaDau(const T& t) +{ + return t.dcaBetweenDaughtermc(); +} + +template +static inline float lamPt(const T& t) +{ + return t.lambdaPtmc(); +} + +template +static inline float lamEta(const T& t) +{ + return t.lambdaEtamc(); +} + +template +static inline float lamPhi(const T& t) +{ + return t.lambdaPhimc(); +} + +template +static inline float lamMass(const T& t) +{ + return t.lambdaMassmc(); +} + +template +static inline float prPt(const T& t) +{ + return t.protonPtmc(); +} + +template +static inline float prEta(const T& t) +{ + return t.protonEtamc(); +} + +template +static inline float prPhi(const T& t) +{ + return t.protonPhimc(); +} + +template +static inline int prIdx(const T& t) +{ + return t.protonIndexmc(); +} + +template +static inline int piIdx(const T& t) +{ + return t.pionIndexmc(); +} +} // namespace mcacc struct lambdaspincorrderived { // BinningType colBinning; @@ -91,6 +203,7 @@ struct lambdaspincorrderived { Configurable ConfWeightPathALL2{"ConfWeightPathALL2", "Users/s/skundu/My/Object/spincorr/cent010LL", "Weight path 2"}; // event sel///////// + Configurable maxMatchesPerPair{"maxMatchesPerPair", 25, "Max mixed candidates per (t1,t2)"}; Configurable centMin{"centMin", 0, "Minimum Centrality"}; Configurable centMax{"centMax", 80, "Maximum Centrality"}; Configurable rngSeed{"rngSeed", 12345, "Seed for random mixing (reproducible)"}; @@ -928,6 +1041,7 @@ struct lambdaspincorrderived { std::sort(out.begin(), out.end()); out.erase(std::unique(out.begin(), out.end()), out.end()); } + // ===================== Main mixing (with mass-bin + random unique sampling) ===================== void processMEV4(EventCandidates const& collisions, AllTrackCandidates const& V0s) { @@ -1041,7 +1155,6 @@ struct lambdaspincorrderived { matches.push_back(MatchRef{bc.collisionIdx, bc.rowIndex}); } }; - // 1) nominal φ-bin collectFrom(phiB); @@ -1065,9 +1178,7 @@ struct lambdaspincorrderived { if (matches.empty()) { continue; } - const float wBase = 1.0f / static_cast(matches.size()); - for (const auto& m : matches) { auto tX = V0s.iteratorAt(static_cast(m.rowIndex)); @@ -1087,6 +1198,434 @@ struct lambdaspincorrderived { } } PROCESS_SWITCH(lambdaspincorrderived, processMEV4, "Process data ME (5d buffer)", false); + + // ------------------------------------- + // 2) MC-only selection + kinematics cuts + // ------------------------------------- + template + bool selectionV0MC(T const& candidate) + { + auto particle = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(candidate), + mcacc::lamEta(candidate), + mcacc::lamPhi(candidate), + mcacc::lamMass(candidate)); + if (std::abs(particle.Rapidity()) > rapidity || std::abs(particle.Eta()) > v0eta) { + return false; + } + if (mcacc::lamMass(candidate) < MassMin || mcacc::lamMass(candidate) > MassMax) { + return false; + } + if (mcacc::v0CosPA(candidate) < cosPA) { + return false; + } + if (checkDoubleStatus && mcacc::doubleStatus(candidate)) { + return false; + } + if (mcacc::v0Radius(candidate) > radiusMax) { + return false; + } + if (mcacc::v0Radius(candidate) < radiusMin) { + return false; + } + if (mcacc::dcaDau(candidate) > dcaDaughters) { + return false; + } + if (mcacc::v0Status(candidate) == 0 && (std::abs(mcacc::dcaPos(candidate)) < dcaProton || std::abs(mcacc::dcaNeg(candidate)) < dcaPion)) { + return false; + } + if (mcacc::v0Status(candidate) == 1 && (std::abs(mcacc::dcaPos(candidate)) < dcaPion || std::abs(mcacc::dcaNeg(candidate)) < dcaProton)) { + return false; + } + if (mcacc::lamPt(candidate) < ptMin) { + return false; + } + if (mcacc::lamPt(candidate) > ptMax) { + return false; + } + return true; + } + + template + bool checkKinematicsMC(T1 const& c1, T2 const& c2) + { + if (mcacc::v0Status(c1) != mcacc::v0Status(c2)) { + return false; + } + if (std::abs(mcacc::lamPt(c1) - mcacc::lamPt(c2)) > ptMix) { + return false; + } + if (std::abs(mcacc::lamEta(c1) - mcacc::lamEta(c2)) > etaMix) { + return false; + } + if (std::abs(RecoDecay::constrainAngle( + RecoDecay::constrainAngle(mcacc::lamPhi(c1), 0.f, harmonic) - + RecoDecay::constrainAngle(mcacc::lamPhi(c2), 0.f, harmonic), + -TMath::Pi(), 1)) > phiMix) { + return false; + } + if (std::abs(mcacc::lamMass(c1) - mcacc::lamMass(c2)) > massMix) { + return false; + } + return true; + } + + // ----------------------------------------- + // 3) MC filter + aliases (distinct from data) + // ----------------------------------------- + Filter centralityFilterMC = (nabs(aod::lambdaeventmc::centmc) < centMax && nabs(aod::lambdaeventmc::centmc) > centMin); + + using EventCandidatesMC = soa::Filtered; + using AllTrackCandidatesMC = aod::LambdaPairmcs; + + // IMPORTANT: MC preslice uses the MC event index column + Preslice tracksPerCollisionV0mc = aod::lambdapairmc::lambdaeventmcId; + + // ----------------------------------------- + // 4) MC Same-event processing (like processData) + // ----------------------------------------- + void processMC(EventCandidatesMC::iterator const& collision, AllTrackCandidatesMC const& V0sMC) + { + const float centrality = mcacc::cent(collision); + + for (const auto& v0 : V0sMC) { + if (!selectionV0MC(v0)) { + continue; + } + + histos.fill(HIST("ptCent"), mcacc::lamPt(v0), centrality); + histos.fill(HIST("etaCent"), mcacc::lamEta(v0), centrality); + + proton = ROOT::Math::PtEtaPhiMVector(mcacc::prPt(v0), mcacc::prEta(v0), mcacc::prPhi(v0), + o2::constants::physics::MassProton); + lambda = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(v0), mcacc::lamEta(v0), mcacc::lamPhi(v0), + mcacc::lamMass(v0)); + + for (const auto& v02 : V0sMC) { + if (v02.index() <= v0.index()) { + continue; + } + if (!selectionV0MC(v02)) { + continue; + } + + // no shared daughters + if (mcacc::prIdx(v0) == mcacc::prIdx(v02)) { + continue; + } + if (mcacc::piIdx(v0) == mcacc::piIdx(v02)) { + continue; + } + if (mcacc::prIdx(v0) == mcacc::piIdx(v02)) { + continue; + } + if (mcacc::piIdx(v0) == mcacc::prIdx(v02)) { + continue; + } + + proton2 = ROOT::Math::PtEtaPhiMVector(mcacc::prPt(v02), mcacc::prEta(v02), mcacc::prPhi(v02), + o2::constants::physics::MassProton); + lambda2 = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(v02), mcacc::lamEta(v02), mcacc::lamPhi(v02), + mcacc::lamMass(v02)); + + histos.fill(HIST("deltaPhiSame"), + RecoDecay::constrainAngle(mcacc::lamPhi(v0) - mcacc::lamPhi(v02), + -TMath::Pi(), harmonicDphi)); + + // datatype=0 (same event) + fillHistograms(mcacc::v0Status(v0), mcacc::v0Status(v02), + lambda, lambda2, proton, proton2, + /*datatype=*/0, /*mixpairweight=*/1.0f); + } + } + } + PROCESS_SWITCH(lambdaspincorrderived, processMC, "Process MC (SE)", false); + + void processMCMEV3(EventCandidatesMC const& collisions, AllTrackCandidatesMC const& V0sMC) + { + auto nBins = colBinning.getAllBinsCount(); + std::vector>> eventPools(nBins); + + for (auto& collision1 : collisions) { + const int bin = colBinning.getBin(std::make_tuple(collision1.poszmc(), collision1.centmc())); + + // if pool empty, push and continue + if (eventPools[bin].empty()) { + auto sliced = V0sMC.sliceBy(tracksPerCollisionV0mc, collision1.index()); + eventPools[bin].emplace_back(collision1.index(), std::move(sliced)); + if ((int)eventPools[bin].size() > nEvtMixing) { + eventPools[bin].pop_front(); + } + continue; + } + + // current event slice + auto poolA = V0sMC.sliceBy(tracksPerCollisionV0mc, collision1.index()); + + // loop over SE unordered pairs (t1,t2) + for (auto& [t1, t2] : soa::combinations(o2::soa::CombinationsFullIndexPolicy(poolA, poolA))) { + + // ---- selections ---- + if (!selectionV0MC(t1) || !selectionV0MC(t2)) { + continue; + } + if (t2.index() <= t1.index()) { + continue; + } + + // no shared daughters (use global indices stored in your MC table) + if (t1.protonIndexmc() == t2.protonIndexmc()) + continue; + if (t1.pionIndexmc() == t2.pionIndexmc()) + continue; + if (t1.protonIndexmc() == t2.pionIndexmc()) + continue; + if (t1.pionIndexmc() == t2.protonIndexmc()) + continue; + + // scan prior events for replacements for t1 + struct PV { + AllTrackCandidatesMC* pool; + int nRepl; + }; + std::vector usable; + int totalRepl = 0; + + int mixes = 0; + for (auto it = eventPools[bin].rbegin(); + it != eventPools[bin].rend() && mixes < nEvtMixing; ++it, ++mixes) { + + const int collision2idx = it->first; + auto& poolB = it->second; + if (collision2idx == collision1.index()) { + continue; + } + + int nRepl = 0; + for (auto& tX : poolB) { + if (!selectionV0MC(tX)) + continue; + if (checkKinematicsMC(t1, tX)) + ++nRepl; + } + if (nRepl > 0) { + usable.push_back(PV{&poolB, nRepl}); + totalRepl += nRepl; + } + } + + if (totalRepl == 0) { + continue; + } + const float wBase = 1.0f / static_cast(totalRepl); + + // emit mixed pairs: tX replaces t1; t2 stays + for (auto& pv : usable) { + auto& poolB = *pv.pool; + for (auto& tX : poolB) { + if (!selectionV0MC(tX)) + continue; + if (!checkKinematicsMC(t1, tX)) + continue; + + // build 4-vectors + auto proton = ROOT::Math::PtEtaPhiMVector(tX.protonPtmc(), tX.protonEtamc(), tX.protonPhimc(), o2::constants::physics::MassProton); + auto lambda = ROOT::Math::PtEtaPhiMVector(tX.lambdaPtmc(), tX.lambdaEtamc(), tX.lambdaPhimc(), tX.lambdaMassmc()); + auto proton2 = ROOT::Math::PtEtaPhiMVector(t2.protonPtmc(), t2.protonEtamc(), t2.protonPhimc(), o2::constants::physics::MassProton); + auto lambda2 = ROOT::Math::PtEtaPhiMVector(t2.lambdaPtmc(), t2.lambdaEtamc(), t2.lambdaPhimc(), t2.lambdaMassmc()); + + const float dPhi = RecoDecay::constrainAngle( + RecoDecay::constrainAngle(lambda.Phi(), 0.0F, harmonic) - + RecoDecay::constrainAngle(lambda2.Phi(), 0.0F, harmonic), + -TMath::Pi(), harmonicDphi); + + histos.fill(HIST("deltaPhiMix"), dPhi, wBase); + fillHistograms(tX.v0Statusmc(), t2.v0Statusmc(), lambda, lambda2, proton, proton2, 1, wBase); + } + } + } // end SE pair loop + + // push current event into pool + auto sliced = V0sMC.sliceBy(tracksPerCollisionV0mc, collision1.index()); + eventPools[bin].emplace_back(collision1.index(), std::move(sliced)); + if ((int)eventPools[bin].size() > nEvtMixing) { + eventPools[bin].pop_front(); + } + } // end events + } + + // enable it + PROCESS_SWITCH(lambdaspincorrderived, processMCMEV3, "Process MC ME (MEV3)", false); + // ----------------------------------------------------- + // 5) MC Event Mixing using your MEV4 6D-buffer approach + // ----------------------------------------------------- + void processMCMEV4(EventCandidatesMC const& collisions, AllTrackCandidatesMC const& V0sMC) + { + // Same binner as in data MEV4 + MixBinner mb{ + ptMin.value, ptMax.value, ptMix.value, + v0eta.value, etaMix.value, + phiMix.value}; + + const int nCol = colBinning.getAllBinsCount(); + const int nStat = N_STATUS; + const int nPt = mb.nPt(); + const int nEta = mb.nEta(); + const int nPhi = mb.nPhi(); + const int nM = mb.nM(); + + const size_t nKeys = static_cast(nCol) * nStat * nPt * nEta * nPhi * nM; + std::vector> buffer(nKeys); + + // ---- PASS 1: fill 6D buffer from MC tables ---- + for (auto const& col : collisions) { + const int colBin = colBinning.getBin(std::make_tuple(mcacc::posz(col), mcacc::cent(col))); + auto slice = V0sMC.sliceBy(tracksPerCollisionV0mc, col.index()); + + for (auto const& t : slice) { + if (!selectionV0MC(t)) { + continue; + } + + const int status = mcacc::v0Status(t); + if (status < 0 || status >= nStat) { + continue; + } + + const int ptB = mb.ptBin(mcacc::lamPt(t)); + const int etaB = mb.etaBin(mcacc::lamEta(t)); + const int phiB = mb.phiBin(RecoDecay::constrainAngle(mcacc::lamPhi(t), 0.0F, harmonic)); + const int mB = mb.massBin(mcacc::lamMass(t)); + if (ptB < 0 || etaB < 0 || phiB < 0 || mB < 0) { + continue; + } + + const size_t key = linearKey(colBin, status, ptB, etaB, phiB, mB, + nStat, nPt, nEta, nPhi, nM); + + // rowIndex storage: use globalIndex like your data MEV4 + // If your build doesn't support globalIndex() for this table, replace with t.index() + buffer[key].push_back(BufferCand{ + .collisionIdx = static_cast(col.index()), + .rowIndex = static_cast(t.globalIndex()), + .v0Status = static_cast(status), + .ptBin = static_cast(ptB), + .etaBin = static_cast(etaB), + .phiBin = static_cast(phiB), + .mBin = static_cast(mB)}); + } + } + + // ---- PASS 2: build mixed pairs for each same-event pair (t1,t2) ---- + for (auto const& collision1 : collisions) { + const int colBin = colBinning.getBin(std::make_tuple(mcacc::posz(collision1), mcacc::cent(collision1))); + auto poolA = V0sMC.sliceBy(tracksPerCollisionV0mc, collision1.index()); + + for (auto const& [t1, t2] : + soa::combinations(o2::soa::CombinationsFullIndexPolicy(poolA, poolA))) { + + if (!selectionV0MC(t1) || !selectionV0MC(t2)) { + continue; + } + if (t2.index() <= t1.index()) { + continue; + } + + // no shared daughters + if (mcacc::prIdx(t1) == mcacc::prIdx(t2)) + continue; + if (mcacc::piIdx(t1) == mcacc::piIdx(t2)) + continue; + if (mcacc::prIdx(t1) == mcacc::piIdx(t2)) + continue; + if (mcacc::piIdx(t1) == mcacc::prIdx(t2)) + continue; + + const int status = mcacc::v0Status(t1); + if (status < 0 || status >= nStat) { + continue; + } + + const int ptB = mb.ptBin(mcacc::lamPt(t1)); + const int etaB = mb.etaBin(mcacc::lamEta(t1)); + const int phiB = mb.phiBin(RecoDecay::constrainAngle(mcacc::lamPhi(t1), 0.0F, harmonic)); + const int mB = mb.massBin(mcacc::lamMass(t1)); + if (ptB < 0 || etaB < 0 || phiB < 0 || mB < 0) { + continue; + } + std::vector matches; + matches.reserve(128); + const int64_t curColIdx = static_cast(collision1.index()); + auto collectFrom = [&](int phiBinUse) { + const size_t keyUse = linearKey(colBin, status, ptB, etaB, phiBinUse, mB, + nStat, nPt, nEta, nPhi, nM); + auto const& vec = buffer[keyUse]; + for (const auto& bc : vec) { + if (bc.collisionIdx == curColIdx) { + continue; // different event + } + auto tX = V0sMC.iteratorAt(static_cast(bc.rowIndex)); + if (!selectionV0MC(tX)) { + continue; + } + if (!checkKinematicsMC(t1, tX)) { + continue; + } + matches.push_back(MatchRef{bc.collisionIdx, bc.rowIndex}); + } + }; + + // nominal φ-bin + wrap neighbors only at edges + collectFrom(phiB); + if (phiB == 0) { + collectFrom(nPhi - 1); + } else if (phiB == nPhi - 1) { + collectFrom(0); + } + + if (matches.empty()) { + continue; + } + + // dedupe identical (collision,row) + std::sort(matches.begin(), matches.end(), + [](auto& a, auto& b) { return std::tie(a.collisionIdx, a.rowIndex) < std::tie(b.collisionIdx, b.rowIndex); }); + matches.erase(std::unique(matches.begin(), matches.end(), + [](auto& a, auto& b) { return a.collisionIdx == b.collisionIdx && a.rowIndex == b.rowIndex; }), + matches.end()); + if (matches.empty()) { + continue; + } + + const float wBase = 1.0f / static_cast(matches.size()); + + for (const auto& m : matches) { + auto tX = V0sMC.iteratorAt(static_cast(m.rowIndex)); + + auto pX = ROOT::Math::PtEtaPhiMVector(mcacc::prPt(tX), mcacc::prEta(tX), mcacc::prPhi(tX), + o2::constants::physics::MassProton); + auto lX = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(tX), mcacc::lamEta(tX), mcacc::lamPhi(tX), + mcacc::lamMass(tX)); + auto p2 = ROOT::Math::PtEtaPhiMVector(mcacc::prPt(t2), mcacc::prEta(t2), mcacc::prPhi(t2), + o2::constants::physics::MassProton); + auto l2 = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(t2), mcacc::lamEta(t2), mcacc::lamPhi(t2), + mcacc::lamMass(t2)); + + const float dPhi = RecoDecay::constrainAngle( + RecoDecay::constrainAngle(lX.Phi(), 0.0F, harmonic) - + RecoDecay::constrainAngle(l2.Phi(), 0.0F, harmonic), + -TMath::Pi(), harmonicDphi); + + histos.fill(HIST("deltaPhiMix"), dPhi, wBase); + + // datatype=1 (mixed event) + fillHistograms(mcacc::v0Status(tX), mcacc::v0Status(t2), + lX, l2, pX, p2, + /*datatype=*/1, /*mixpairweight=*/wBase); + } + } + } + } + PROCESS_SWITCH(lambdaspincorrderived, processMCMEV4, "Process MC ME (5d buffer)", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { From 8aa55a9a5a32ffbc4e78b1c029617763b51c158e Mon Sep 17 00:00:00 2001 From: dyx-11 <1260971129@qq.com> Date: Tue, 3 Mar 2026 14:42:34 +0800 Subject: [PATCH 145/347] [PWGUD] filtered table (#15231) --- PWGUD/Tasks/flowCorrelationsUpc.cxx | 115 +++++++++++++--------------- 1 file changed, 55 insertions(+), 60 deletions(-) diff --git a/PWGUD/Tasks/flowCorrelationsUpc.cxx b/PWGUD/Tasks/flowCorrelationsUpc.cxx index 26c4e7cfc09..010bc11e3ee 100644 --- a/PWGUD/Tasks/flowCorrelationsUpc.cxx +++ b/PWGUD/Tasks/flowCorrelationsUpc.cxx @@ -111,8 +111,8 @@ struct FlowCorrelationsUpc { O2_DEFINE_CONFIGURABLE(cfgRadiusLow, float, 0.8, "Low radius for merging cut") O2_DEFINE_CONFIGURABLE(cfgRadiusHigh, float, 2.5, "High radius for merging cut") O2_DEFINE_CONFIGURABLE(cfgIsGoodItsLayers, bool, false, "whether choose itslayers") - O2_DEFINE_CONFIGURABLE(cfgGapSideA, bool, true, "choose gapside A") - O2_DEFINE_CONFIGURABLE(cfgGapSideC, bool, false, "choose gapside C") + O2_DEFINE_CONFIGURABLE(cfgGapSide, int, 0, "0: gapside A;1:C") + O2_DEFINE_CONFIGURABLE(cfgGapSideMerge, bool, false, "whether merge A and C side together") O2_DEFINE_CONFIGURABLE(cfgDcaxy, bool, true, "choose dcaxy") O2_DEFINE_CONFIGURABLE(cfgDcaz, bool, false, "choose dcaz") O2_DEFINE_CONFIGURABLE(cfgDcazCut, float, 10.0, "dcaz cut") @@ -147,12 +147,14 @@ struct FlowCorrelationsUpc { Configurable cfgCutZDC{"cfgCutZDC", 10., "ZDC threshold"}; // make the filters and cuts. + Filter trackFilter = (aod::udtrack::isPVContributor == true); + Filter collisionFilter = (cfgGapSideMerge == false && aod::udcollision::gapSide == (uint8_t)cfgGapSide); // Filter collisionFilter = (nabs(aod::collision::posZ) < cfgZVtxCut) && (aod::flowcorrupc::multiplicity) > cfgMinMult && (aod::flowcorrupc::multiplicity) < cfgMaxMult && (aod::evsel::sel8) == true; // Filter trackFilter = (nabs(aod::track::eta) < cfgEtaCut) && (aod::track::pt > cfgPtCutMin) && (aod::track::pt < cfgPtCutMax) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)); - using UdTracks = soa::Join; - using UdTracksFull = soa::Join; - using UDCollisionsFull = soa::Join; + using UdTracks = soa::Filtered>; + using UdTracksFull = soa::Filtered>; + using UDCollisionsFull = soa::Filtered>; // Define the outputs OutputObj same{Form("sameEvent_%i_%i", static_cast(cfgMinMult), static_cast(cfgMaxMult))}; @@ -175,7 +177,7 @@ struct FlowCorrelationsUpc { registry.add("Trig_hist", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisPtTrigger}}}); - registry.add("eventcount", "bin", {HistType::kTH1F, {{4, 0, 4, "bin"}}}); // histogram to see how many events are in the same and mixed event + registry.add("eventcount", "bin", {HistType::kTH1F, {{10, 0, 10, "bin"}}}); // histogram to see how many events are in the same and mixed event std::vector corrAxis = {{axisSample, "Sample"}, {axisVertex, "z-vtx (cm)"}, @@ -195,7 +197,8 @@ struct FlowCorrelationsUpc { } enum EventType { SameEvent = 1, - MixedEvent = 3 + MixedEvent = 3, + MixedFinal = 9 }; template @@ -229,6 +232,9 @@ struct FlowCorrelationsUpc { { // registry.fill(HIST("hTrackCount"), 0.5); // UPC selection + if (track.pt() < cfgPtCutMin || track.pt() > cfgPtCutMax) { + return false; + } if (!track.isPVContributor()) { return false; } @@ -343,35 +349,24 @@ struct FlowCorrelationsUpc { return; } - int gapSide = collision.gapSide(); - if (gapSide == 0) { - if (!cfgGapSideA) { - return; - } - } - if (gapSide == 1) { - if (!cfgGapSideC) { + if (cfgGapSideMerge) { + int gapSide = collision.gapSide(); + if (gapSide != 0 && gapSide != 1) { return; } - } - if (gapSide != 0 && gapSide != 1) { - return; - } - int trueGapSide = sgSelector.trueGap(collision, cfgCutFV0, cfgCutFT0A, cfgCutFT0C, cfgCutZDC); - gapSide = trueGapSide; - if (gapSide == 0) { - if (!cfgGapSideA) { + int trueGapSide = sgSelector.trueGap(collision, cfgCutFV0, cfgCutFT0A, cfgCutFT0C, cfgCutZDC); + int gapSide1 = trueGapSide; + if (gapSide1 != 0 && gapSide1 != 1) { return; } } - if (gapSide == 1) { - if (!cfgGapSideC) { + if (!cfgGapSideMerge) { + int trueGapSide = sgSelector.trueGap(collision, cfgCutFV0, cfgCutFT0A, cfgCutFT0C, cfgCutZDC); + int gapSide1 = trueGapSide; + if (gapSide1 != cfgGapSide) { return; } } - if (gapSide != 0 && gapSide != 1) { - return; - } float vtxz = collision.posZ(); if (cfgIfVertex && abs(vtxz) > cfgZVtxCut) { return; @@ -392,80 +387,80 @@ struct FlowCorrelationsUpc { // event mixing SliceCache cache; + // using MixedBinning = FlexibleBinningPolicy, aod::collision::PosZ, aod::flowcorrupc::Multiplicity>; using MixedBinning = ColumnBinningPolicy; // the process for filling the mixed events void processMixed(UDCollisionsFull const& collisions, UdTracksFull const& tracks) { MixedBinning binningOnVtxAndMult{{vtxMix, multMix}, true}; // true is for 'ignore overflows' (true by default) - auto tracksTuple = std::make_tuple(tracks); - SameKindPair pairs{binningOnVtxAndMult, cfgMinMixEventNum, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip + auto tracksTuple = std::make_tuple(tracks, tracks); + Pair pairs{binningOnVtxAndMult, cfgMinMixEventNum, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip for (auto const& [collision1, tracks1, collision2, tracks2] : pairs) { + registry.fill(HIST("eventcount"), MixedEvent); // fill the mixed event in the 3 bin if (tracks1.size() < cfgMinMult || tracks1.size() > cfgMaxMult || tracks2.size() < cfgMinMult || tracks2.size() > cfgMaxMult) { continue; } + registry.fill(HIST("eventcount"), 4.5); if (cfgIsGoodItsLayers && (collision1.trs() == 0 || collision2.trs() == 0)) { continue; } - - int gapSide1 = collision1.gapSide(); - if (gapSide1 == 0) { - if (!cfgGapSideA) { + registry.fill(HIST("eventcount"), 5.5); + if (cfgGapSideMerge) { + int gapSide = collision1.gapSide(); + if (gapSide != 0 && gapSide != 1) { continue; } - } - if (gapSide1 == 1) { - if (!cfgGapSideC) { + int trueGapSide = sgSelector.trueGap(collision1, cfgCutFV0, cfgCutFT0A, cfgCutFT0C, cfgCutZDC); + int gapSide1 = trueGapSide; + if (gapSide1 != 0 && gapSide1 != 1) { continue; } } - int gapSide2 = collision2.gapSide(); - if (gapSide2 == 0) { - if (!cfgGapSideA) { + if (!cfgGapSideMerge) { + int trueGapSide = sgSelector.trueGap(collision1, cfgCutFV0, cfgCutFT0A, cfgCutFT0C, cfgCutZDC); + int gapSide1 = trueGapSide; + if (gapSide1 != cfgGapSide) { continue; } } - if (gapSide2 == 1) { - if (!cfgGapSideC) { + if (cfgGapSideMerge) { + int gapSide = collision2.gapSide(); + if (gapSide != 0 && gapSide != 1) { continue; } - } - int trueGapSide1 = sgSelector.trueGap(collision1, cfgCutFV0, cfgCutFT0A, cfgCutFT0C, cfgCutZDC); - int trueGapSide2 = sgSelector.trueGap(collision2, cfgCutFV0, cfgCutFT0A, cfgCutFT0C, cfgCutZDC); - if (trueGapSide1 != trueGapSide2) { - continue; - } - if (trueGapSide1 == 0) { - if (!cfgGapSideA) { + int trueGapSide = sgSelector.trueGap(collision2, cfgCutFV0, cfgCutFT0A, cfgCutFT0C, cfgCutZDC); + int gapSide2 = trueGapSide; + if (gapSide2 != 0 && gapSide2 != 1) { continue; } } - if (trueGapSide2 == 1) { - if (!cfgGapSideC) { + if (!cfgGapSideMerge) { + int trueGapSide = sgSelector.trueGap(collision2, cfgCutFV0, cfgCutFT0A, cfgCutFT0C, cfgCutZDC); + int gapSide2 = trueGapSide; + if (gapSide2 != cfgGapSide) { continue; } } - if ((gapSide1 != 0 && gapSide1 != 1) || (gapSide2 != 0 && gapSide2 != 1)) { - continue; - } + registry.fill(HIST("eventcount"), 6.5); float vtxz = collision1.posZ(); if (cfgIfVertex && abs(vtxz) > cfgZVtxCut) { - return; + continue; } int occupancy = collision1.occupancyInTime(); if (cfgEvSelOccupancy && (occupancy < cfgCutOccupancyLow || occupancy > cfgCutOccupancyHigh)) { - return; + continue; } vtxz = collision2.posZ(); if (cfgIfVertex && abs(vtxz) > cfgZVtxCut) { - return; + continue; } occupancy = collision2.occupancyInTime(); if (cfgEvSelOccupancy && (occupancy < cfgCutOccupancyLow || occupancy > cfgCutOccupancyHigh)) { - return; + continue; } - registry.fill(HIST("eventcount"), MixedEvent); // fill the mixed event in the 3 bin + registry.fill(HIST("eventcount"), MixedFinal); fillCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent, collision1.runNumber()); // fill the ME histogram and Sparse } } From 39794623b8204eb8d427996d52856637c7c661a9 Mon Sep 17 00:00:00 2001 From: Jesper Karlsson Gumprecht <113693781+jesgum@users.noreply.github.com> Date: Tue, 3 Mar 2026 09:50:28 +0100 Subject: [PATCH 146/347] [ALICE3] Move fitter settings to configurables and fix for cascade kink reco (#15219) --- ALICE3/Core/FastTracker.cxx | 37 ++-- ALICE3/Core/FastTracker.h | 2 +- ALICE3/TableProducer/OTF/onTheFlyTracker.cxx | 168 ++++++++++++------ .../TableProducer/alice3MulticharmFinder.cxx | 89 ++++++---- 4 files changed, 195 insertions(+), 101 deletions(-) diff --git a/ALICE3/Core/FastTracker.cxx b/ALICE3/Core/FastTracker.cxx index a74858cfe02..be4ef7d2a12 100644 --- a/ALICE3/Core/FastTracker.cxx +++ b/ALICE3/Core/FastTracker.cxx @@ -288,7 +288,7 @@ float FastTracker::ProbGoodChiSqHit(float radius, float searchRadiusRPhi, float // function to provide a reconstructed track from a perfect input track // returns number of intercepts (generic for now) -int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackParCov& outputTrack, const float nch) +int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackParCov& outputTrack, const float nch, const float maxRadius) { dNdEtaCent = nch; // set the number of charged particles per unit rapidity hits.clear(); @@ -335,6 +335,14 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa continue; // this layer should not be attempted, but go ahead } + if (layers[il].getRadius() > maxRadius) { + if (lastLayerReached == -1) { + // This means that we didn't reach the first layer + return -9; + } + break; // could not reach + } + // check if layer is reached float targetX = 1e+3; inputTrack.getXatLabR(layers[il].getRadius(), targetX, magneticField); @@ -367,6 +375,7 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa break; } } + if (std::abs(inputTrack.getZ()) > layers[il].getZ() && mApplyZacceptance) { break; // out of acceptance bounds } @@ -405,8 +414,9 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa static constexpr float kLargeErr2Dir = 0.7 * 0.7; static constexpr float kLargeErr2PtI = 30.5 * 30.5; std::array largeCov = {0.}; - for (int ic = o2::track::kCovMatSize; ic--;) + for (int ic = o2::track::kCovMatSize; ic--;) { largeCov[ic] = 0.; + } largeCov[o2::track::CovLabels::kSigY2] = largeCov[o2::track::CovLabels::kSigZ2] = kLargeErr2Coord; largeCov[o2::track::CovLabels::kSigSnp2] = largeCov[o2::track::CovLabels::kSigTgl2] = kLargeErr2Dir; largeCov[o2::track::CovLabels::kSigQ2Pt2] = kLargeErr2PtI * trPars[o2::track::ParLabels::kQ2Pt] * trPars[o2::track::ParLabels::kQ2Pt]; @@ -442,8 +452,10 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa std::cos(alpha) * spacePoint[0] + std::sin(alpha) * spacePoint[1], -std::sin(alpha) * spacePoint[0] + std::cos(alpha) * spacePoint[1], spacePoint[2]}; - if (!inwardTrack.propagateTo(xyz1[0], magneticField)) + + if (!inwardTrack.propagateTo(xyz1[0], magneticField)) { continue; + } if (!layers[il].isInert()) { // only update covm for tracker hits const o2::track::TrackParametrization::dim2_t hitpoint = { @@ -474,13 +486,14 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa } } - if (layers[il].isSilicon()) + if (layers[il].isSilicon()) { nSiliconPoints++; // count silicon hits - if (layers[il].isGas()) + } + if (layers[il].isGas()) { nGasPoints++; // count TPC/gas hits + } hits.push_back(thisHit); - if (!layers[il].isInert()) { // good hit probability calculation float sigYCmb = o2::math_utils::sqrt(inwardTrack.getSigmaY2() + layers[il].getResolutionRPhi() * layers[il].getResolutionRPhi()); float sigZCmb = o2::math_utils::sqrt(inwardTrack.getSigmaZ2() + layers[il].getResolutionZ() * layers[il].getResolutionZ()); @@ -502,21 +515,24 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa } // only attempt to continue if intercepts are at least four - if (nIntercepts < 4) + if (nIntercepts < 4) { return nIntercepts; + } // generate efficiency float eff = 1.; for (size_t i = 0; i < layers.size(); i++) { float iGoodHit = goodHitProbability[i]; - if (iGoodHit <= 0) + if (iGoodHit <= 0) { continue; + } eff *= iGoodHit; } if (mApplyEffCorrection) { - if (gRandom->Uniform() > eff) + if (gRandom->Uniform() > eff) { return -8; + } } outputTrack.setCov(inwardTrack.getCov()); @@ -524,8 +540,9 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa // Use covariance matrix based smearing std::array covMat = {0.}; - for (int ii = 0; ii < o2::track::kCovMatSize; ii++) + for (int ii = 0; ii < o2::track::kCovMatSize; ii++) { covMat[ii] = outputTrack.getCov()[ii]; + } TMatrixDSym m(5); double fcovm[5][5]; // double precision is needed for regularisation diff --git a/ALICE3/Core/FastTracker.h b/ALICE3/Core/FastTracker.h index 5b8fa150c4c..d361e261603 100644 --- a/ALICE3/Core/FastTracker.h +++ b/ALICE3/Core/FastTracker.h @@ -92,7 +92,7 @@ class FastTracker * @param nch Charged particle multiplicity (used for hit density calculations). * @return int i.e. number of intercepts (implementation-defined). */ - int FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackParCov& outputTrack, const float nch); + int FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackParCov& outputTrack, const float nch, const float maxRadius = 100.f); // For efficiency calculation float Dist(float z, float radius); diff --git a/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx b/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx index 814b55623fe..14ab69f0dab 100644 --- a/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx +++ b/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx @@ -181,6 +181,19 @@ struct OnTheFlyTracker { Configurable doV0QA{"doV0QA", false, "QA plots for when treating V0"}; } v0DecaySettings; + struct : ConfigurableGroup { + std::string prefix = "cfgFitter"; + Configurable propagateToPCA{"propagateToPCA", false, "create tracks version propagated to PCA"}; + Configurable maxR{"maxR", 200., "reject PCA's above this radius"}; + Configurable minParamChange{"minParamChange", 1.e-3, "stop iterations if largest change of any X is smaller than this"}; + Configurable minRelChi2Change{"minRelChi2Change", 0.9, "stop iterations is chi2/chi2old > this"}; + Configurable maxDZIni{"maxDZIni", 1e9, "reject (if>0) PCA candidate if tracks DZ exceeds threshold"}; + Configurable maxDXYIni{"maxDXYIni", 4, "reject (if>0) PCA candidate if tracks DXY exceeds threshold"}; + Configurable maxVtxChi2{"maxVtxChi2", 1e9, "reject (if>0) vtx. chi2 above this value"}; + Configurable useAbsDCA{"useAbsDCA", true, "Minimise abs. distance rather than chi2"}; + Configurable useWeightedFinalPCA{"useWeightedFinalPCA", false, "Recalculate vertex position using track covariances, effective only if useAbsDCA is true"}; + } cfgFitter; + using PVertex = o2::dataformats::PrimaryVertex; // for secondary vertex finding @@ -465,6 +478,7 @@ struct OnTheFlyTracker { getHist(TH1, histPath + "hFastTrackerQA")->GetXaxis()->SetBinLabel(6, "multiple scattering"); getHist(TH1, histPath + "hFastTrackerQA")->GetXaxis()->SetBinLabel(7, "energy loss"); getHist(TH1, histPath + "hFastTrackerQA")->GetXaxis()->SetBinLabel(8, "efficiency"); + getHist(TH1, histPath + "hFastTrackerQA")->GetXaxis()->SetBinLabel(9, "no layers hit"); } } @@ -491,6 +505,27 @@ struct OnTheFlyTracker { hCovMatOK->GetXaxis()->SetBinLabel(1, "Not OK"); hCovMatOK->GetXaxis()->SetBinLabel(2, "OK"); + auto hFitterStatusCode = histos.add("hFitterStatusCode", "hFitterStatusCode", kTH1D, {{15, -0.5, 14.5}}); + hFitterStatusCode->GetXaxis()->SetBinLabel(1, "None"); // no status set (should not be possible!) + + /* Good Conditions */ + hFitterStatusCode->GetXaxis()->SetBinLabel(2, "Converged"); // fit converged + hFitterStatusCode->GetXaxis()->SetBinLabel(3, "MaxIter"); // max iterations reached before fit convergence + + /* Error Conditions */ + hFitterStatusCode->GetXaxis()->SetBinLabel(4, "NoCrossing"); // no reasaonable crossing was found + hFitterStatusCode->GetXaxis()->SetBinLabel(5, "RejRadius"); // radius of crossing was not acceptable + hFitterStatusCode->GetXaxis()->SetBinLabel(6, "RejTrackX"); // one candidate track x was below the mimimum required radius + hFitterStatusCode->GetXaxis()->SetBinLabel(7, "RejTrackRoughZ"); // rejected by rough cut on tracks Z difference + hFitterStatusCode->GetXaxis()->SetBinLabel(8, "RejChi2Max"); // rejected by maximum chi2 cut + hFitterStatusCode->GetXaxis()->SetBinLabel(9, "FailProp"); // propagation of at least prong to PCA failed + hFitterStatusCode->GetXaxis()->SetBinLabel(10, "FailInvCov"); // inversion of cov.-matrix failed + hFitterStatusCode->GetXaxis()->SetBinLabel(11, "FailInvWeight"); // inversion of Ti weight matrix failed + hFitterStatusCode->GetXaxis()->SetBinLabel(12, "FailInv2ndDeriv"); // inversion of 2nd derivatives failed + hFitterStatusCode->GetXaxis()->SetBinLabel(13, "FailCorrTracks"); // correction of tracks to updated x failed + hFitterStatusCode->GetXaxis()->SetBinLabel(14, "FailCloserAlt"); // alternative PCA is closer + hFitterStatusCode->GetXaxis()->SetBinLabel(15, "NStatusesDefined"); + if (doExtraQA) { histos.add("h2dVerticesVsContributors", "h2dVerticesVsContributors;Multiplicity;N vertices", kTH2F, {axes.axisMultiplicity, axes.axisNVertices}); histos.add("h1dVerticesNotReco", "h1dVerticesNotReco;Multiplicity;Vertices Not Reco", kTH1F, {axes.axisMultiplicity}); @@ -515,6 +550,7 @@ struct OnTheFlyTracker { h->GetXaxis()->SetBinLabel(6, "multiple scattering"); h->GetXaxis()->SetBinLabel(7, "energy loss"); h->GetXaxis()->SetBinLabel(8, "efficiency"); + h->GetXaxis()->SetBinLabel(8, "no layers hit"); histPointers.insert({v0histPath + "hFastTrackerQA", h}); // K0s insertHist(v0histPath + "K0/hGen", "hGen", kTH2F, {axes.axisDecayRadius, axes.axisMomentum}); @@ -583,15 +619,16 @@ struct OnTheFlyTracker { o2::vertexing::PVertexerParams::Instance().printKeyValues(); // initialize O2 2-prong fitter - fitter.setPropagateToPCA(true); - fitter.setMaxR(200.); - fitter.setMinParamChange(1e-3); - fitter.setMinRelChi2Change(0.9); - fitter.setMaxDZIni(1e9); - fitter.setMaxDXYIni(4); - fitter.setMaxChi2(1e9); - fitter.setUseAbsDCA(true); - fitter.setWeightedFinalPCA(false); + fitter.setPropagateToPCA(cfgFitter.propagateToPCA); + fitter.setMaxR(cfgFitter.maxR); + fitter.setMinParamChange(cfgFitter.minParamChange); + fitter.setMinRelChi2Change(cfgFitter.minRelChi2Change); + fitter.setMaxDZIni(cfgFitter.maxDZIni); + fitter.setMaxDXYIni(cfgFitter.maxDXYIni); + fitter.setMaxChi2(cfgFitter.maxVtxChi2); + fitter.setUseAbsDCA(cfgFitter.useAbsDCA); + fitter.setWeightedFinalPCA(cfgFitter.useWeightedFinalPCA); + fitter.setBz(mMagneticField); fitter.setMatCorrType(o2::base::Propagator::MatCorrType::USEMatCorrNONE); // such a light detector here // Set seed for TGenPhaseSpace @@ -987,6 +1024,12 @@ struct OnTheFlyTracker { if (nCand == 0) { dcaFitterOK_V0 = false; } + + fitter.propagateTracksToVertex(); + if (!fitter.isPropagateTracksToVertexDone()) { + dcaFitterOK_V0 = false; + } + // V0 found successfully if (dcaFitterOK_V0) { if (cascadeDecaySettings.doXiQA) { @@ -1026,6 +1069,7 @@ struct OnTheFlyTracker { covV[MomInd[i]] = 1e-6; covV[i] = 1e-6; } + o2::track::TrackParCov v0Track = o2::track::TrackParCov( {pos[0], pos[1], pos[2]}, {posP[0] + negP[0], posP[1] + negP[1], posP[2] + negP[2]}, @@ -1046,6 +1090,13 @@ struct OnTheFlyTracker { dcaFitterOK_Cascade = false; } + fitter.propagateTracksToVertex(); + if (!fitter.isPropagateTracksToVertexDone()) { + dcaFitterOK_Cascade = false; + } + + const u_int8_t fitterStatusCode = fitter.getFitStatus(); + histos.fill(HIST("hFitterStatusCode"), fitterStatusCode); // Cascade found successfully if (dcaFitterOK_Cascade) { if (cascadeDecaySettings.doXiQA) { @@ -1098,8 +1149,9 @@ struct OnTheFlyTracker { // find perfect intercept XYZ float targetX = 1e+3; trackParCov.getXatLabR(layer.getRadius(), targetX, mMagneticField); - if (targetX > 999) + if (targetX > 999) { continue; // failed to find intercept + } if (!trackParCov.propagateTo(targetX, mMagneticField)) { continue; // failed to propagate @@ -1118,8 +1170,9 @@ struct OnTheFlyTracker { posClusterCandidate[2] = gRandom->Gaus(posClusterCandidate[2], layer.getResolutionZ()); } - if (std::isnan(phi)) + if (std::isnan(phi)) { continue; // Catch when getXatLabR misses layer[i] + } // towards adding cluster: move to track alpha double alpha = cascadeTrack.getAlpha(); @@ -1128,8 +1181,10 @@ struct OnTheFlyTracker { -TMath::Sin(alpha) * posClusterCandidate[0] + TMath::Cos(alpha) * posClusterCandidate[1], posClusterCandidate[2]}; - if (!(cascadeTrack.propagateTo(xyz1[0], mMagneticField))) + if (!(cascadeTrack.propagateTo(xyz1[0], mMagneticField))) { continue; + } + const o2::track::TrackParametrization::dim2_t hitpoint = {static_cast(xyz1[1]), static_cast(xyz1[2])}; const o2::track::TrackParametrization::dim3_t hitpointcov = {layer.getResolutionRPhi() * layer.getResolutionRPhi(), 0.f, layer.getResolutionZ() * layer.getResolutionZ()}; if (layer.isInDeadPhiRegion(phi)) { @@ -1139,10 +1194,10 @@ struct OnTheFlyTracker { cascadeTrack.update(hitpoint, hitpointcov); thisCascade.foundClusters++; // add to findable } - } - if (thisCascade.foundClusters < cascadeDecaySettings.minStraTrackHits) { - continue; // We didn't find enough hits for strangeness tracking + if (thisCascade.foundClusters < cascadeDecaySettings.minStraTrackHits) { + continue; // We didn't find enough hits for strangeness tracking + } } // add cascade track @@ -1156,20 +1211,19 @@ struct OnTheFlyTracker { } // end cascade building if (isReco[0] && ((cascadeDecaySettings.doKinkReco == 1 && tryKinkReco) || cascadeDecaySettings.doKinkReco == 2)) { // mode 1 or 2 - o2::track::TrackParCov prefectCascadeTrack, trackedCasc; + o2::track::TrackParCov prefectCascadeTrack, trackedCascade; const o2::track::TrackParCov& trackedBach = xiDaughterTrackParCovsTracked[0]; o2::upgrade::convertMCParticleToO2Track(mcParticle, prefectCascadeTrack, pdgDB); // back track is already smeared prefectCascadeTrack.setPID(pdgCodeToPID(PDG_t::kXiMinus)); // FIXME: not OK for omegas - int nCascHits = fastTracker[icfg]->FastTrack(prefectCascadeTrack, trackedCasc, dNdEta); - reconstructedCascade = (fastTrackerSettings.minSiliconHitsForKinkReco < nCascHits) ? false : true; - + const int nCascHits = fastTracker[icfg]->FastTrack(prefectCascadeTrack, trackedCascade, dNdEta, xiDecayRadius2D); + reconstructedCascade = (fastTrackerSettings.minSiliconHitsForKinkReco < nCascHits) ? true : false; if (reconstructedCascade) { std::array pCasc; std::array pBach; std::array pV0; - trackedCasc.getPxPyPzGlo(pCasc); + trackedCascade.getPxPyPzGlo(pCasc); trackedBach.getPxPyPzGlo(pBach); for (size_t i = 0; i < pCasc.size(); ++i) { pV0[i] = pCasc[i] - pBach[i]; @@ -1192,7 +1246,7 @@ struct OnTheFlyTracker { int nCand = 0; bool kinkFitterOK = true; try { - nCand = fitter.process(trackedCasc, trackedBach); + nCand = fitter.process(trackedCascade, trackedBach); } catch (...) { kinkFitterOK = false; } @@ -1201,43 +1255,43 @@ struct OnTheFlyTracker { kinkFitterOK = false; } + fitter.propagateTracksToVertex(); + if (!fitter.isPropagateTracksToVertexDone()) { + kinkFitterOK = false; + } + + const u_int8_t fitterStatusCode = fitter.getFitStatus(); + histos.fill(HIST("hFitterStatusCode"), fitterStatusCode); if (kinkFitterOK) { if (cascadeDecaySettings.doXiQA) { getHist(TH1, histPath + "hXiBuilding")->Fill(6.0f); } - } - fitter.propagateTracksToVertex(); // propagate e and K to D vertex - if (!fitter.isPropagateTracksToVertexDone()) { - kinkFitterOK = false; - } + o2::track::TrackParCov newCascadeTrack = fitter.getTrack(0); // (cascade) + std::array kinkVtx = {-999, -999, -999}; + kinkVtx = fitter.getPCACandidatePos(); + thisCascade.bachelorId = lastTrackIndex + tracksAlice3.size() - isReco.size(); + thisCascade.cascadeTrackId = lastTrackIndex + tracksAlice3.size(); // this should be ok + thisCascade.dcaV0dau = -1.f; // unknown + thisCascade.v0radius = -1.f; // unknown + thisCascade.dcacascdau = std::sqrt(fitter.getChi2AtPCACandidate()); + thisCascade.cascradius = std::hypot(kinkVtx[0], kinkVtx[1]); + thisCascade.cascradiusMC = xiDecayRadius2D; + thisCascade.mLambda = o2::constants::physics::MassLambda; + thisCascade.findableClusters = nCascHits; + thisCascade.foundClusters = nCascHits; + thisCascade.pt = newCascadeTrack.getPt(); + thisCascade.eta = newCascadeTrack.getEta(); + thisCascade.mXi = RecoDecay::m(std::array{std::array{pBach[0], pBach[1], pBach[2]}, std::array{pV0[0], pV0[1], pV0[2]}}, + std::array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassLambda}); - o2::track::TrackParCov newCascadeTrack = fitter.getTrack(0); // (cascade) - std::array kinkVtx = {-999, -999, -999}; - kinkVtx = fitter.getPCACandidatePos(); - - thisCascade.bachelorId = lastTrackIndex + tracksAlice3.size() - isReco.size(); - thisCascade.cascadeTrackId = lastTrackIndex + tracksAlice3.size(); // this should be ok - thisCascade.dcaV0dau = -1.f; // unknown - thisCascade.v0radius = -1.f; // unknown - thisCascade.dcacascdau = std::sqrt(fitter.getChi2AtPCACandidate()); - thisCascade.cascradius = std::hypot(kinkVtx[0], kinkVtx[1]); - thisCascade.cascradiusMC = xiDecayRadius2D; - thisCascade.mLambda = o2::constants::physics::MassLambda; - thisCascade.findableClusters = nCascHits; - thisCascade.foundClusters = nCascHits; - thisCascade.pt = newCascadeTrack.getPt(); - thisCascade.eta = newCascadeTrack.getEta(); - thisCascade.mXi = RecoDecay::m(std::array{std::array{pBach[0], pBach[1], pBach[2]}, - std::array{pV0[0], pV0[1], pV0[2]}}, - std::array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassLambda}); - - newCascadeTrack.setPID(pdgCodeToPID(PDG_t::kXiMinus)); // FIXME: not OK for omegas - tracksAlice3.push_back(TrackAlice3{newCascadeTrack, mcParticle.globalIndex(), time, timeResolutionUs, false, false, 1, thisCascade.foundClusters}); - - // add this cascade to vector (will fill cursor later with collision ID) - cascadesAlice3.push_back(thisCascade); - } + newCascadeTrack.setPID(pdgCodeToPID(PDG_t::kXiMinus)); // FIXME: not OK for omegas + tracksAlice3.push_back(TrackAlice3{newCascadeTrack, mcParticle.globalIndex(), time, timeResolutionUs, false, false, 1, thisCascade.foundClusters}); + + // add this cascade to vector (will fill cursor later with collision ID) + cascadesAlice3.push_back(thisCascade); + } // end fitter OK + } // end cascade found } // end cascade kink building // +-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+ @@ -1247,7 +1301,7 @@ struct OnTheFlyTracker { getHist(TH1, histPath + "hMassLambda")->Fill(thisCascade.mLambda); getHist(TH1, histPath + "hMassXi")->Fill(thisCascade.mXi); getHist(TH2, histPath + "h2dMassXi")->Fill(thisCascade.mXi, thisCascade.pt); - getHist(TH2, histPath + "h2dDeltaPtVsPt")->Fill(thisCascade.pt, mcParticle.pt() - thisCascade.pt); + getHist(TH2, histPath + "h2dDeltaPtVsPt")->Fill(thisCascade.pt, (mcParticle.pt() - thisCascade.pt) / thisCascade.pt); getHist(TH2, histPath + "h2dDeltaEtaVsPt")->Fill(thisCascade.pt, mcParticle.eta() - thisCascade.eta); getHist(TH2, histPath + "hFoundVsFindable")->Fill(thisCascade.findableClusters, thisCascade.foundClusters); } @@ -1382,6 +1436,14 @@ struct OnTheFlyTracker { if (nCand == 0) { dcaFitterOK_V0 = false; } + + fitter.propagateTracksToVertex(); + if (!fitter.isPropagateTracksToVertexDone()) { + dcaFitterOK_V0 = false; + } + + const u_int8_t fitterStatusCode = fitter.getFitStatus(); + histos.fill(HIST("hFitterStatusCode"), fitterStatusCode); // V0 found successfully if (dcaFitterOK_V0) { if (v0DecaySettings.doV0QA) { diff --git a/ALICE3/TableProducer/alice3MulticharmFinder.cxx b/ALICE3/TableProducer/alice3MulticharmFinder.cxx index 79437c2a1a2..16e0e9571c7 100644 --- a/ALICE3/TableProducer/alice3MulticharmFinder.cxx +++ b/ALICE3/TableProducer/alice3MulticharmFinder.cxx @@ -87,7 +87,20 @@ struct Alice3MulticharmFinder { Configurable fillMCharmIdx{"fillMCharmIdx", true, "fill MCharmIdx[] tables (careful: memory)"}; Configurable fillMCharmCore{"fillMCharmCore", true, "fill MCharmCores[] tables (careful: memory)"}; Configurable fillMCharmExtra{"fillMCharmExtra", false, "fill MCharmExtra[] tables (careful: memory)"}; - } derivedTable; // allows for gap between peak and bg in case someone wants to + } derivedTable; + + struct : ConfigurableGroup { + std::string prefix = "cfgFitter"; + Configurable propagateToPCA{"propagateToPCA", false, "create tracks version propagated to PCA"}; + Configurable maxR{"maxR", 200., "reject PCA's above this radius"}; + Configurable minParamChange{"minParamChange", 1.e-3, "stop iterations if largest change of any X is smaller than this"}; + Configurable minRelChi2Change{"minRelChi2Change", 0.9, "stop iterations is chi2/chi2old > this"}; + Configurable maxDZIni{"maxDZIni", 1e9, "reject (if>0) PCA candidate if tracks DZ exceeds threshold"}; + Configurable maxDXYIni{"maxDXYIni", 4, "reject (if>0) PCA candidate if tracks DXY exceeds threshold"}; + Configurable maxVtxChi2{"maxVtxChi2", 1e9, "reject (if>0) vtx. chi2 above this value"}; + Configurable useAbsDCA{"useAbsDCA", true, "Minimise abs. distance rather than chi2"}; + Configurable useWeightedFinalPCA{"useWeightedFinalPCA", false, "Recalculate vertex position using track covariances, effective only if useAbsDCA is true"}; + } cfgFitter; Configurable cfgMagneticField{"cfgMagneticField", 20.0f, "Magnetic field (in kilogauss) if value not found from geo provider"}; Configurable doDCAplots{"doDCAplots", true, "do daughter prong DCA plots for D mesons"}; @@ -164,7 +177,6 @@ struct Alice3MulticharmFinder { // filter expressions for pions static constexpr uint32_t TrackSelectionPic = 1 << kInnerTOFPion | 1 << kOuterTOFPion | 1 << kRICHPion | 1 << kTruePiFromXiC; static constexpr uint32_t TrackSelectionPicc = 1 << kInnerTOFPion | 1 << kOuterTOFPion | 1 << kRICHPion | 1 << kTruePiFromXiCC; - float magneticField{}; // partitions Partition trueXi = aod::mcparticle::pdgCode == static_cast(PDG_t::kXiMinus); @@ -224,14 +236,19 @@ struct Alice3MulticharmFinder { } catch (...) { return false; } + + const u_int8_t fitterStatusCode = fitter.getFitStatus(); + histos.fill(HIST("hFitterStatusCode"), fitterStatusCode); if (nCand == 0) { return false; } - const u_int8_t fitterStatusCode = fitter.getFitStatus(); - histos.fill(HIST("hFitterStatusCode"), fitterStatusCode); - //}-{}-{}-{}-{}-{}-{}-{}-{}-{} + fitter.propagateTracksToVertex(); + if (!fitter.isPropagateTracksToVertexDone()) { + return false; + } + //}-{}-{}-{}-{}-{}-{}-{}-{}-{} o2::track::TrackParCov t0new = fitter.getTrack(0); o2::track::TrackParCov t1new = fitter.getTrack(1); t0new.getPxPyPzGlo(thisXiccCandidate.prong0mom); @@ -298,12 +315,17 @@ struct Alice3MulticharmFinder { } catch (...) { return false; } + + const u_int8_t fitter3StatusCode = fitter3.getFitStatus(); + histos.fill(HIST("hFitter3StatusCode"), fitter3StatusCode); if (nCand == 0) { return false; } - const u_int8_t fitter3StatusCode = fitter3.getFitStatus(); - histos.fill(HIST("hFitter3StatusCode"), fitter3StatusCode); + fitter3.propagateTracksToVertex(); + if (!fitter3.isPropagateTracksToVertexDone()) { + return false; + } //}-{}-{}-{}-{}-{}-{}-{}-{}-{} t0 = fitter3.getTrack(0); @@ -405,38 +427,31 @@ struct Alice3MulticharmFinder { return returnValue; } - void init(o2::framework::InitContext& initContext) + void init(o2::framework::InitContext&) { - const bool foundMagneticField = common::core::getTaskOptionValue(initContext, "on-the-fly-detector-geometry-provider", "magneticField", magneticField, false); - if (!foundMagneticField) { - LOG(info) << "Could not retrieve magnetic field from geometry provider."; - LOG(info) << "Using value from configurable cfgMagneticField: " << cfgMagneticField; - magneticField = cfgMagneticField; - } else { - LOG(info) << "Using magnetic field form geometry provider with value: " << magneticField; - } - // initialize O2 2-prong fitter (only once) - fitter.setPropagateToPCA(true); - fitter.setMaxR(200.); - fitter.setMinParamChange(1e-3); - fitter.setMinRelChi2Change(0.9); - fitter.setMaxDZIni(1e9); - fitter.setMaxChi2(1e9); - fitter.setUseAbsDCA(true); - fitter.setWeightedFinalPCA(false); - fitter.setBz(magneticField); + fitter.setPropagateToPCA(cfgFitter.propagateToPCA); + fitter.setMaxR(cfgFitter.maxR); + fitter.setMinParamChange(cfgFitter.minParamChange); + fitter.setMinRelChi2Change(cfgFitter.minRelChi2Change); + fitter.setMaxDZIni(cfgFitter.maxDZIni); + fitter.setMaxDXYIni(cfgFitter.maxDXYIni); + fitter.setMaxChi2(cfgFitter.maxVtxChi2); + fitter.setUseAbsDCA(cfgFitter.useAbsDCA); + fitter.setWeightedFinalPCA(cfgFitter.useWeightedFinalPCA); + fitter.setBz(cfgMagneticField); fitter.setMatCorrType(o2::base::Propagator::MatCorrType::USEMatCorrNONE); - fitter3.setPropagateToPCA(true); - fitter3.setMaxR(200.); - fitter3.setMinParamChange(1e-3); - fitter3.setMinRelChi2Change(0.9); - fitter3.setMaxDZIni(1e9); - fitter3.setMaxChi2(1e9); - fitter3.setUseAbsDCA(true); - fitter3.setWeightedFinalPCA(false); - fitter3.setBz(magneticField); + fitter3.setPropagateToPCA(cfgFitter.propagateToPCA); + fitter3.setMaxR(cfgFitter.maxR); + fitter3.setMinParamChange(cfgFitter.minParamChange); + fitter3.setMinRelChi2Change(cfgFitter.minRelChi2Change); + fitter3.setMaxDZIni(cfgFitter.maxDZIni); + fitter3.setMaxDZIni(cfgFitter.maxDXYIni); + fitter3.setMaxChi2(cfgFitter.maxVtxChi2); + fitter3.setUseAbsDCA(cfgFitter.useAbsDCA); + fitter3.setWeightedFinalPCA(cfgFitter.useWeightedFinalPCA); + fitter3.setBz(cfgMagneticField); fitter3.setMatCorrType(o2::base::Propagator::MatCorrType::USEMatCorrNONE); auto hFitterStatusCode = histos.add("hFitterStatusCode", "hFitterStatusCode", kTH1D, {{15, -0.5, 14.5}}); @@ -713,7 +728,7 @@ struct Alice3MulticharmFinder { o2::vertexing::PVertex primaryVertex; primaryVertex.setXYZ(collision.posX(), collision.posY(), collision.posZ()); - if (xicTrackCopy.propagateToDCA(primaryVertex, magneticField, &dcaInfo)) { + if (xicTrackCopy.propagateToDCA(primaryVertex, cfgMagneticField, &dcaInfo)) { xicdcaXY = dcaInfo.getY(); xicdcaZ = dcaInfo.getZ(); } @@ -808,7 +823,7 @@ struct Alice3MulticharmFinder { GET_HIST(TH1, histPath + "hMultiCharmBuilding")->Fill(6.0f); GET_HIST(TH2, histPath + "hXicRadiusVsXiccRadius")->Fill(xicDecayRadius2D * ToMicrons, xiccDecayRadius2D * ToMicrons); float xiccdcaXY = 1e+10, xiccdcaZ = 1e+10; - if (xiccTrack.propagateToDCA(primaryVertex, magneticField, &dcaInfo)) { + if (xiccTrack.propagateToDCA(primaryVertex, cfgMagneticField, &dcaInfo)) { xiccdcaXY = dcaInfo.getY(); xiccdcaZ = dcaInfo.getZ(); } From a4b6a86e948450be4aa00b5276ba7f7e3008a301 Mon Sep 17 00:00:00 2001 From: SCHOTTER Romain <47983209+romainschotter@users.noreply.github.com> Date: Tue, 3 Mar 2026 16:55:15 +0100 Subject: [PATCH 147/347] [Infrastructure] Update CODEOWNERS (#15236) --- CODEOWNERS | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/CODEOWNERS b/CODEOWNERS index 1ab937857ca..5f06bf0fdc7 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -43,18 +43,18 @@ /PWGHF @alibuild @vkucera @fcolamar @fgrosa @fcatalan92 @mfaggin @mmazzilli @deepathoms @NicoleBastid @hahassan7 @jpxrk @apalasciano @zhangbiao-phy @gluparel @stefanopolitano @xinyepeng @singhra1994 # PWG-LF /PWGLF @alibuild @omvazque @skundu692 @mpuccio -/PWGLF/DataModel @alibuild @omvazque @skundu692 @mpuccio @gbencedi @abmodak @fmazzasc @maciacco @HorstMa @dmallick2 @smaff92 @ercolessi @romainschotter @prottayCMT +/PWGLF/DataModel @alibuild @omvazque @skundu692 @mpuccio @gbencedi @abmodak @fmazzasc @maciacco @HorstMa @dmallick2 @smaff92 @ercolessi @romainschotter @prottayCMT @lhusova /PWGLF/Tasks/GlobalEventProperties @alibuild @omvazque @skundu692 @mpuccio @gbencedi @abmodak @omvazque /PWGLF/TableProducer/GlobalEventProperties @alibuild @omvazque @skundu692 @mpuccio @gbencedi @abmodak @omvazque /PWGLF/Tasks/Nuspex @alibuild @omvazque @skundu692 @mpuccio @fmazzasc @maciacco @HorstMa /PWGLF/TableProducer/Nuspex @alibuild @omvazque @skundu692 @mpuccio @fmazzasc @maciacco @HorstMa /PWGLF/Tasks/Resonances @alibuild @omvazque @skundu692 @mpuccio @dmallick2 @smaff92 @prottayCMT /PWGLF/TableProducer/Resonances @alibuild @omvazque @skundu692 @mpuccio @dmallick2 @smaff92 @prottayCMT -/PWGLF/Tasks/Strangeness @alibuild @omvazque @skundu692 @mpuccio @ercolessi @romainschotter -/PWGLF/TableProducer/Strangeness @alibuild @omvazque @mpuccio @skundu692 @ercolessi @romainschotter -/PWGLF/TableProducer/QC @alibuild @omvazque @skundu692 @mpuccio @gbencedi @abmodak @fmazzasc @maciacco @HorstMa @dmallick2 @smaff92 @ercolessi @romainschotter @prottayCMT -/PWGLF/Tasks/QC @alibuild @omvazque @skundu692 @mpuccio @gbencedi @abmodak @fmazzasc @maciacco @HorstMa @dmallick2 @smaff92 @ercolessi @romainschotter @prottayCMT -/PWGLF/Utils @alibuild @omvazque @skundu692 @mpuccio @gbencedi @abmodak @fmazzasc @maciacco @HorstMa @dmallick2 @smaff92 @ercolessi @romainschotter @prottayCMT +/PWGLF/Tasks/Strangeness @alibuild @omvazque @skundu692 @mpuccio @ercolessi @romainschotter @lhusova +/PWGLF/TableProducer/Strangeness @alibuild @omvazque @mpuccio @skundu692 @ercolessi @romainschotter @lhusova +/PWGLF/TableProducer/QC @alibuild @omvazque @skundu692 @mpuccio @gbencedi @abmodak @fmazzasc @maciacco @HorstMa @dmallick2 @smaff92 @ercolessi @romainschotter @prottayCMT @lhusova +/PWGLF/Tasks/QC @alibuild @omvazque @skundu692 @mpuccio @gbencedi @abmodak @fmazzasc @maciacco @HorstMa @dmallick2 @smaff92 @ercolessi @romainschotter @prottayCMT @lhusova +/PWGLF/Utils @alibuild @omvazque @skundu692 @mpuccio @gbencedi @abmodak @fmazzasc @maciacco @HorstMa @dmallick2 @smaff92 @ercolessi @romainschotter @prottayCMT @lhusova # PWG-MM (fused with LF, LF conveners included. Directories to be merged in the future) /PWGMM @alibuild @omvazque @mpuccio @skundu692 @aalkin @jgcn @@ -71,6 +71,6 @@ /Tutorials/PWGEM @alibuild @mikesas @rbailhac @dsekihat @ivorobye @feisenhu /Tutorials/PWGHF @alibuild @vkucera @fcolamar @fgrosa @gluparel @xinyepeng /Tutorials/PWGJE @alibuild @lhavener @maoyx @nzardosh @raymondEhlers @mfasDa @fjonasALICE -/Tutorials/PWGLF @alibuild @alcaliva @lbariogl @chiarapinto @BongHwi @lbarnby @ercolessi @iravasen @njacazio @romainschotter @skundu692 +/Tutorials/PWGLF @alibuild @alcaliva @lbariogl @chiarapinto @BongHwi @lbarnby @ercolessi @iravasen @njacazio @romainschotter @skundu692 @lhusova /Tutorials/PWGMM @alibuild @aalkin @ddobrigk /Tutorials/PWGUD @alibuild @pbuehler @amatyja From 5dd9f93edd0889cf7a99833acd72424c35328f71 Mon Sep 17 00:00:00 2001 From: aimeric-landou <46970521+aimeric-landou@users.noreply.github.com> Date: Tue, 3 Mar 2026 21:55:16 +0100 Subject: [PATCH 148/347] [PWGJE] jetFinderQA fixes, new debug process; trackEff/jetSpectraCharged: fixes, cleaning and new process (#15227) --- PWGJE/Tasks/jetFinderQA.cxx | 184 +++++++++++++++++++++++++++++- PWGJE/Tasks/jetSpectraCharged.cxx | 59 ++-------- PWGJE/Tasks/trackEfficiency.cxx | 54 ++++++++- 3 files changed, 239 insertions(+), 58 deletions(-) diff --git a/PWGJE/Tasks/jetFinderQA.cxx b/PWGJE/Tasks/jetFinderQA.cxx index 878083b557f..f42c1dad41b 100644 --- a/PWGJE/Tasks/jetFinderQA.cxx +++ b/PWGJE/Tasks/jetFinderQA.cxx @@ -83,6 +83,14 @@ struct JetFinderQATask { Configurable intRateMax{"intRateMax", 50000.0, "maximum value of interaction rate axis"}; Configurable kappa{"kappa", 1.0, "angularity kappa"}; Configurable alpha{"alpha", 1.0, "angularity alpha"}; + Configurable checkCentFT0M{"checkCentFT0M", false, "0: centFT0C as default, 1: use centFT0M estimator"}; + + // Configurable qcCutOnJetMultVsPt{"qcCutOnJetMultVsPt", false, "debug configurable for LHC26a7 10% test production with strange high mult jet pupulation"}; + Configurable multCutCheck_proportionalFactor{"multCut_proportionalFactor", 0.5, "debug cut value for LHC26a7 10% test production with strange high mult jet pupulation"}; + Configurable multCutCheck_abscissaAtOrigin{"multCut_abscissaAtOrigin", 5, "debug cut value LHC26a7 10% test production with strange high mult jet pupulation"}; + Configurable multCutCheck_analyseMBGapEvents{"multCutCheck_analyseMBGapEvents", 0, "flag to choose to reject min. bias gap events; -1: MBGap only, 0: skip MBGap events, 1: analyse all events"}; + Configurable doMultCutCheck{"doMultCutCheck", false, "decide to apply multCutCheck or not"}; + Configurable multCutCheck_applyRCTSelections{"multCutCheck_applyRCTSelections", true, "decide to apply RCT selections"}; std::vector filledJetR_Both; std::vector filledJetR_Low; @@ -373,7 +381,7 @@ struct JetFinderQATask { registry.add("h_xsecErrSumWeighted", "Summed Cross section error per collision in pb with weights; Summed Cross section error per collision in pb with weights; entries", {HistType::kTH1F, {{1, 0., 1.}}}); } - AxisSpec occupancyAxis = {142, -1.5, 14000.5, "occupancy"}; + AxisSpec occupancyAxis = {140, -0.5, 13999.5, "occupancy"}; AxisSpec nTracksAxis = {16001, -1., 16000, "n tracks"}; if (doprocessOccupancyQA) { @@ -384,10 +392,61 @@ struct JetFinderQATask { registry.add("h2_occupancy_ntracksselptetacuts_presel", "occupancy vs N_{tracks}; occupancy; N_{tracks}", {HistType::kTH2I, {occupancyAxis, nTracksAxis}}); registry.add("h2_occupancy_ntracksselptetacuts_postsel", "occupancy vs N_{tracks}; occupancy; N_{tracks}", {HistType::kTH2I, {occupancyAxis, nTracksAxis}}); } + + if (doprocessQcMultCutCheck) { + std::vector centralityBinning{0., 10., 50., 70., 100}; + AxisSpec centAxis = {centralityBinning, "centrality (%)"}; + bool doSumw2 = true; + + AxisSpec centralityAxis = {1200, -10., 110., "Centrality"}; + AxisSpec trackPtAxis = {200, -0.5, 199.5, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec trackEtaAxis = {nBinsEta, -1.0, 1.0, "#eta"}; + AxisSpec phiAxis = {160, -1.0, 7.0, "#varphi"}; + AxisSpec jetPtAxis = {200, 0., 200., "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec jetPtAxisRhoAreaSub = {400, -200., 200., "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec jetEtaAxis = {nBinsEta, -1.0, 1.0, "#eta"}; + + registry.add("h_collisions", "event status;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}); + registry.add("h2_centrality_collisions", "centrality vs collisions; centrality; collisions", {HistType::kTH2F, {centAxis, {4, 0.0, 4.0}}}); + // registry.add("h2_mccollision_pthardfromweight_pthardfromhepmcxsection", "ptHard from weight vs ptHard from HepMCXSections; ptHard_weight; ptHard_hepmcxsections", {HistType::kTH2F, {{200, 0.0, 200.0}, {200, 0.0, 200.0}}}); + + registry.add("h_collisions_weighted", "event status;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}, doSumw2); + registry.add("h2_centrality_collisions_weighted", "centrality vs collisions; centrality; collisions", {HistType::kTH2F, {centAxis, {4, 0.0, 4.0}}}, doSumw2); + // registry.add("h2_mccollision_pthardfromweight_pthardfromhepmcxsection_weighted", "ptHard from weight vs ptHard from HepMCXSections; ptHard_weight; ptHard_hepmcxsections", {HistType::kTH2F, {{200, 0.0, 200.0}, {200, 0.0, 200.0}}}, doSumw2); + + registry.add("h_collisions_zvertex", "position of collision ;#it{Z} (cm)", {HistType::kTH1F, {{300, -15.0, 15.0}}}, doSumw2); + registry.add("h_collisions_ntracks", "N_{tracks};", {HistType::kTH1F, {{10000, 0.0, 10000.0}}}, doSumw2); + registry.add("h_collisions_njets", "N_{jets};", {HistType::kTH1F, {{10000, 0.0, 10000.0}}}, doSumw2); + + registry.add("h2_centrality_ntracks", "; centrality; N_{tracks};", {HistType::kTH2F, {{1100, 0., 110.0}, {10000, 0.0, 10000.0}}}); + registry.add("h2_centrality_njets", "; centrality; N_{jets};", {HistType::kTH2F, {{1100, 0., 110.0}, {10000, 0.0, 10000.0}}}); + registry.add("h2_ntracks_rho", "; N_{tracks}; #it{rho} (GeV/area);", {HistType::kTH2F, {{10000, 0.0, 10000.0}, {400, 0.0, 400.0}}}); + registry.add("h2_centrality_rho", "; centrality; #it{rho} (GeV/area);", {HistType::kTH2F, {{1100, 0., 110.}, {400, 0., 400.0}}}); + + registry.add("h2_centrality_track_pt", "centrality vs track pT; centrality; #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH2F, {centAxis, {200, 0., 200.}}}); + registry.add("h2_centrality_track_eta", "centrality vs track #eta; centrality; #eta_{track}", {HistType::kTH2F, {centAxis, {100, -1.0, 1.0}}}); + registry.add("h2_track_pt_track_sigmapt", "#sigma(#it{p}_{T})/#it{p}_{T}; #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH2F, {{100, 0., 10.}, {100000, 0.0, 10.0}}}); + registry.add("h2_track_pt_high_track_sigmapt", "#sigma(#it{p}_{T})/#it{p}_{T}; #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH2F, {{90, 10., 100.}, {100000, 0.0, 10.0}}}); + registry.add("h2_track_pt_track_sigma1overpt", "#sigma(1/#it{p}_{T}); #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH2F, {{100, 0., 10.}, {10000, 0.0, 1.0}}}); + registry.add("h2_track_pt_high_track_sigma1overpt", "#sigma(1/#it{p}_{T}); #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH2F, {{90, 10., 100.}, {10000, 0.0, 1.0}}}); + + registry.add("h_jet_pt", "jet pT;#it{p}_{T,jet} (GeV/#it{c}); counts", {HistType::kTH1F, {jetPtAxis}}, doSumw2); + registry.add("h_jet_eta", "jet eta;#eta; counts", {HistType::kTH1F, {jetEtaAxis}}, doSumw2); + registry.add("h_jet_phi", "jet phi;#phi; counts", {HistType::kTH1F, {phiAxis}}, doSumw2); + registry.add("h2_centrality_jet_pt", "centrality vs. jet pT;centrality; #it{p}_{T,jet} (GeV/#it{c}); counts", {HistType::kTH2F, {centralityAxis, jetPtAxis}}, doSumw2); + registry.add("h2_centrality_jet_eta", "centrality vs. jet eta;centrality; #eta; counts", {HistType::kTH2F, {centralityAxis, jetEtaAxis}}, doSumw2); + registry.add("h2_centrality_jet_phi", "centrality vs. jet phi;centrality; #varphi; counts", {HistType::kTH2F, {centralityAxis, phiAxis}}, doSumw2); + registry.add("h2_jet_pt_jet_area", "jet #it{p}_{T,jet} vs. Area_{jet}; #it{p}_{T,jet} (GeV/#it{c}); Area_{jet}", {HistType::kTH2F, {jetPtAxis, {150, 0., 1.5}}}, doSumw2); + registry.add("h2_jet_pt_jet_ntracks", "jet #it{p}_{T,jet} vs. N_{jet tracks}; #it{p}_{T,jet} (GeV/#it{c}); N_{jet, tracks}", {HistType::kTH2F, {jetPtAxis, {200, -0.5, 199.5}}}, doSumw2); + registry.add("h2_jet_pt_track_pt", "jet #it{p}_{T,jet} vs. #it{p}_{T,track}; #it{p}_{T,jet} (GeV/#it{c}); #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxis, trackPtAxis}}, doSumw2); + registry.add("h3_jet_pt_jet_eta_jet_phi", "jet pt vs. eta vs. phi", {HistType::kTH3F, {jetPtAxis, jetEtaAxis, phiAxis}}, doSumw2); + } } Filter trackCuts = (aod::jtrack::pt >= trackPtMin && aod::jtrack::pt < trackPtMax && aod::jtrack::eta > trackEtaMin && aod::jtrack::eta < trackEtaMax); - Filter eventCuts = (nabs(aod::jcollision::posZ) < vertexZCut && aod::jcollision::centFT0M >= centralityMin && aod::jcollision::centFT0M < centralityMax); + Filter eventCuts = (nabs(aod::jcollision::posZ) < vertexZCut && + ((checkCentFT0M ? aod::jcollision::centFT0M : aod::jcollision::centFT0C) >= centralityMin) && + ((checkCentFT0M ? aod::jcollision::centFT0M : aod::jcollision::centFT0C) < centralityMax)); PresliceUnsorted> CollisionsPerMCPCollision = aod::jmccollisionlb::mcCollisionId; PresliceUnsorted> McCollisionsPerMCPCollision = aod::jmccollision::mcCollisionId; @@ -810,6 +869,64 @@ struct JetFinderQATask { registry.fill(HIST("h2_centrality_rhorandomconerandomtrackdirectionwithouttwoleadingjets"), collision.centFT0M(), randomConePtWithoutTwoLeadJet - M_PI * randomConeR * randomConeR * collision.rho()); } + enum mbGapSelectionRequirement { + mbGapOnly = -1, + mbGapSkip = 0, + mbGapAndSignal = 1 + }; + + template + bool applyCollisionCuts_multCutCheck(TColl const& collision, bool fillHistograms = false, bool isWeighted = false, float eventWeight = 1.0) + { + float centrality = -1.0; + checkCentFT0M ? centrality = collision.centFT0M() : centrality = collision.centFT0C(); + + if (fillHistograms) { + registry.fill(HIST("h_collisions"), 0.5); + registry.fill(HIST("h2_centrality_collisions"), centrality, 0.5, eventWeight); + if (isWeighted) + registry.fill(HIST("h_collisions_weighted"), 0.5, eventWeight); + } + + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, multCutCheck_applyRCTSelections)) { + return false; + } + if (fillHistograms) { + registry.fill(HIST("h_collisions"), 1.5); + registry.fill(HIST("h2_centrality_collisions"), centrality, 1.5, eventWeight); + if (isWeighted) + registry.fill(HIST("h_collisions_weighted"), 1.5, eventWeight); + } + + if (centrality < centralityMin || centralityMax < centrality) { + return false; + } + if (fillHistograms) { + registry.fill(HIST("h_collisions"), 2.5); + registry.fill(HIST("h2_centrality_collisions"), centrality, 2.5, eventWeight); + if (isWeighted) + registry.fill(HIST("h_collisions_weighted"), 2.5, eventWeight); + } + + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return false; + } + if (fillHistograms) { + registry.fill(HIST("h_collisions"), 3.5); + registry.fill(HIST("h2_centrality_collisions"), centrality, 3.5, eventWeight); + if (isWeighted) + registry.fill(HIST("h_collisions_weighted"), 3.5, eventWeight); + } + + if (multCutCheck_analyseMBGapEvents == mbGapSelectionRequirement::mbGapOnly && collision.getSubGeneratorId() != jetderiveddatautilities::JCollisionSubGeneratorId::mbGap) { + return false; + } else if (multCutCheck_analyseMBGapEvents == mbGapSelectionRequirement::mbGapSkip && collision.getSubGeneratorId() == jetderiveddatautilities::JCollisionSubGeneratorId::mbGap) { + return false; + } + + return true; + } + void processJetsData(soa::Filtered::iterator const& collision, soa::Join const& jets, aod::JetTracks const&) { if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { @@ -1357,12 +1474,69 @@ struct JetFinderQATask { registry.fill(HIST("h2_occupancy_ntrackssel_presel"), occupancy, nTracksAllAcceptanceAndSelected); registry.fill(HIST("h2_occupancy_ntracksselptetacuts_presel"), occupancy, nTracksInAcceptanceAndSelected); if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { - registry.fill(HIST("h2_occupancy_ntracksall_postsel"), occupancy, nTracksAll); - registry.fill(HIST("h2_occupancy_ntrackssel_postsel"), occupancy, nTracksAllAcceptanceAndSelected); - registry.fill(HIST("h2_occupancy_ntracksselptetacuts_postsel"), occupancy, nTracksInAcceptanceAndSelected); + return; } + registry.fill(HIST("h2_occupancy_ntracksall_postsel"), occupancy, nTracksAll); + registry.fill(HIST("h2_occupancy_ntrackssel_postsel"), occupancy, nTracksAllAcceptanceAndSelected); + registry.fill(HIST("h2_occupancy_ntracksselptetacuts_postsel"), occupancy, nTracksInAcceptanceAndSelected); } PROCESS_SWITCH(JetFinderQATask, processOccupancyQA, "occupancy QA on jet derived data", false); + + void processQcMultCutCheck(soa::Filtered>::iterator const& collision, + soa::Join const& mcdjets, + soa::Filtered> const& tracks) + { + bool fillHistograms = true; + bool isWeighted = true; + float eventWeight = collision.weight(); + if (!applyCollisionCuts_multCutCheck(collision, fillHistograms, isWeighted, eventWeight)) { + return; + } + registry.fill(HIST("h_collisions_zvertex"), collision.posZ(), eventWeight); + + bool hasJetAboveMultCut = false; + for (auto const& mcdjet : mcdjets) { + if (mcdjet.tracksIds().size() > multCutCheck_proportionalFactor * mcdjet.pt() + multCutCheck_abscissaAtOrigin) { + hasJetAboveMultCut = true; + } + } + if (doMultCutCheck && hasJetAboveMultCut == false) { + return; + } + + registry.fill(HIST("h_collisions_ntracks"), tracks.size(), eventWeight); + registry.fill(HIST("h2_centrality_ntracks"), collision.centFT0M(), tracks.size(), eventWeight); + registry.fill(HIST("h_collisions_njets"), mcdjets.size(), eventWeight); + registry.fill(HIST("h2_centrality_njets"), collision.centFT0M(), mcdjets.size(), eventWeight); + registry.fill(HIST("h2_ntracks_rho"), tracks.size(), collision.rho(), eventWeight); + registry.fill(HIST("h2_centrality_rho"), collision.centFT0M(), collision.rho(), eventWeight); + + for (auto const& track : tracks) { + registry.fill(HIST("h2_centrality_track_pt"), collision.centFT0M(), track.pt(), eventWeight); + registry.fill(HIST("h2_centrality_track_eta"), collision.centFT0M(), track.eta(), eventWeight); + registry.fill(HIST("h2_track_pt_track_sigma1overpt"), track.pt(), track.sigma1Pt(), eventWeight); + registry.fill(HIST("h2_track_pt_track_sigmapt"), track.pt(), track.sigma1Pt() * track.pt(), eventWeight); + registry.fill(HIST("h2_track_pt_high_track_sigma1overpt"), track.pt(), track.sigma1Pt(), eventWeight); + registry.fill(HIST("h2_track_pt_high_track_sigmapt"), track.pt(), track.sigma1Pt() * track.pt(), eventWeight); + } + + for (auto const& mcdjet : mcdjets) { + registry.fill(HIST("h_jet_pt"), mcdjet.pt(), eventWeight); + registry.fill(HIST("h_jet_eta"), mcdjet.eta(), eventWeight); + registry.fill(HIST("h_jet_phi"), mcdjet.phi(), eventWeight); + registry.fill(HIST("h2_centrality_jet_pt"), collision.centFT0M(), mcdjet.pt(), eventWeight); + registry.fill(HIST("h2_centrality_jet_eta"), collision.centFT0M(), mcdjet.eta(), eventWeight); + registry.fill(HIST("h2_centrality_jet_phi"), collision.centFT0M(), mcdjet.phi(), eventWeight); + registry.fill(HIST("h3_jet_pt_jet_eta_jet_phi"), mcdjet.pt(), mcdjet.eta(), mcdjet.phi(), eventWeight); + + registry.fill(HIST("h2_jet_pt_jet_area"), mcdjet.pt(), mcdjet.area(), eventWeight); + registry.fill(HIST("h2_jet_pt_jet_ntracks"), mcdjet.pt(), mcdjet.tracksIds().size(), eventWeight); + for (const auto& constituent : mcdjet.template tracks_as>>()) { + registry.fill(HIST("h2_jet_pt_track_pt"), mcdjet.pt(), constituent.pt(), eventWeight); + } + } + } + PROCESS_SWITCH(JetFinderQATask, processQcMultCutCheck, "processing QC on collision, track and jet quantities after cut on collision based on jet quantities;", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/Tasks/jetSpectraCharged.cxx b/PWGJE/Tasks/jetSpectraCharged.cxx index 8af8e45e7cc..3812e1a08ff 100644 --- a/PWGJE/Tasks/jetSpectraCharged.cxx +++ b/PWGJE/Tasks/jetSpectraCharged.cxx @@ -78,6 +78,7 @@ struct JetSpectraCharged { Configurable acceptSplitCollisions{"acceptSplitCollisions", 0, "0: only look at mcCollisions that are not split; 1: accept split mcCollisions, 2: accept split mcCollisions but only look at the first reco collision associated with it"}; Configurable skipMBGapEvents{"skipMBGapEvents", false, "flag to choose to reject min. bias gap events; jet-level rejection can also be applied at the jet finder level for jets only, here rejection is applied for collision and track process functions for the first time, and on jets in case it was set to false at the jet finder level"}; Configurable checkLeadConstituentPtForMcpJets{"checkLeadConstituentPtForMcpJets", false, "flag to choose whether particle level jets should have their lead track pt above leadingConstituentPtMin to be accepted; off by default, as leadingConstituentPtMin cut is only applied on MCD jets for the Pb-Pb analysis using pp MC anchored to Pb-Pb for the response matrix"}; + Configurable isMCGenOnly{"isMCGenOnly", false, "analysis is run over mcGen only"}; std::vector eventSelectionBits; int trackSelection = -1; @@ -106,11 +107,6 @@ struct JetSpectraCharged { AxisSpec jetPtAxisRhoAreaSub = {400, -200., 200., "#it{p}_{T} (GeV/#it{c})"}; AxisSpec jetEtaAxis = {nBinsEta, -1.0, 1.0, "#eta"}; - if (doprocessTracksQC || doprocessTracksQCWeighted) { - registry.add("h_track_pt", "track #it{p}_{T} ; #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH1F, {trackPtAxis}}, doSumw2); - registry.add("h2_track_eta_track_phi", "track eta vs. track phi; #eta; #phi; counts", {HistType::kTH2F, {trackEtaAxis, phiAxis}}, doSumw2); - } - if (doprocessCollisions || doprocessCollisionsWeighted) { registry.add("h_collisions", "number of events;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}, doSumw2); registry.get(HIST("h_collisions"))->GetXaxis()->SetBinLabel(1, "allColl"); @@ -154,7 +150,7 @@ struct JetSpectraCharged { } registry.add("h2_centrality_mccollisions", "mc event status vs. centrality;entries;centrality", {HistType::kTH2F, {centralityAxis, {4, 0.0, 4.0}}}, doSumw2); } - if (doprocessSpectraMCP || doprocessSpectraMCPWeighted || doprocessMCCollisions || doprocessMCCollisionsWeighted) { + if (doprocessMCCollisions || doprocessMCCollisionsWeighted) { registry.add("h_mccollisions_zvertex", "position of mc collision ;#it{Z} (cm)", {HistType::kTH1F, {{300, -15.0, 15.0}}}, doSumw2); } @@ -318,6 +314,13 @@ struct JetSpectraCharged { template bool applyMCCollisionCuts(TMCColl const& mccollision, TCollisions const& collisions, bool fillHistograms = false, bool isWeighted = false, float eventWeight = 1.0) { + if (isMCGenOnly) { + if (fillHistograms) { + registry.fill(HIST("h_mccollisions"), 0.5); + } + return true; + } // if isMCGenOnly is true, skip MC selection and accept all of them + float centrality = -1.0; // checkCentFT0M ? centrality = mccollision.centFT0M() : centrality = mccollision.centFT0C(); centrality = mccollision.centFT0M(); @@ -568,13 +571,6 @@ struct JetSpectraCharged { } } - template - void fillTrackHistograms(TTracks const& track, float weight = 1.0) - { - registry.fill(HIST("h_track_pt"), track.pt(), weight); - registry.fill(HIST("h2_track_eta_track_phi"), track.eta(), track.phi(), weight); - } - template void fillMatchedHistograms(TBase const& jetMCD, float weight = 1.0) { @@ -698,42 +694,6 @@ struct JetSpectraCharged { } } - void processTracksQC(soa::Filtered::iterator const& collision, - soa::Filtered> const& tracks) - { - if (!applyCollisionCuts(collision)) { - return; - } - - for (auto const& track : tracks) { - if (!jetderiveddatautilities::selectTrack(track, trackSelection)) { - continue; - } - fillTrackHistograms(track); - } - } - PROCESS_SWITCH(JetSpectraCharged, processTracksQC, "collisions and track QC for Data and MCD", false); - - void processTracksQCWeighted(soa::Filtered>::iterator const& collision, - aod::JetMcCollisions const&, - soa::Filtered> const& tracks) - { - bool fillHistograms = false; - bool isWeighted = true; - float eventWeight = collision.weight(); - if (!applyCollisionCuts(collision, fillHistograms, isWeighted, eventWeight)) { - return; - } - - for (auto const& track : tracks) { - if (!jetderiveddatautilities::selectTrack(track, trackSelection)) { - continue; - } - fillTrackHistograms(track, eventWeight); - } - } - PROCESS_SWITCH(JetSpectraCharged, processTracksQCWeighted, "weighted collsions and tracks QC for MC", false); - void processCollisions(soa::Filtered::iterator const& collision) { bool fillHistograms = true; @@ -950,7 +910,6 @@ struct JetSpectraCharged { if (!applyMCCollisionCuts(mccollision, collisions)) { return; } - registry.fill(HIST("h_mccollisions_zvertex"), mccollision.posZ()); for (auto const& jet : jets) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { diff --git a/PWGJE/Tasks/trackEfficiency.cxx b/PWGJE/Tasks/trackEfficiency.cxx index 943aeae3dca..9b908a8c951 100644 --- a/PWGJE/Tasks/trackEfficiency.cxx +++ b/PWGJE/Tasks/trackEfficiency.cxx @@ -80,9 +80,9 @@ struct TrackEfficiency { Configurable phiEffNBins{"phiEffNBins", 200, "number of bins for phi axis in efficiency plots"}; Configurable etaEffNBins{"etaEffNBins", 200, "number of bins for eta axis in efficiency plots"}; - Configurable ptHatMin{"ptHatMin", 5, "min pT hat of collisions"}; - Configurable ptHatMax{"ptHatMax", 300, "max pT hat of collisions"}; - Configurable pTHatExponent{"pTHatExponent", 6.0, "exponent of the event weight for the calculation of pTHat"}; + Configurable ptHatMin{"ptHatMin", -999, "min pT hat of collisions"}; + Configurable ptHatMax{"ptHatMax", 999, "max pT hat of collisions"}; + Configurable pTHatExponent{"pTHatExponent", 4.0, "exponent of the event weight for the calculation of pTHat"}; Configurable pTHatMaxFractionMCD{"pTHatMaxFractionMCD", 999.0, "maximum fraction of hard scattering for reconstructed track acceptance in MC"}; Configurable getPtHatFromHepMCXSection{"getPtHatFromHepMCXSection", true, "test configurable, configurable should be removed once well tested"}; @@ -92,6 +92,7 @@ struct TrackEfficiency { TrackSelection customTrackSelection; Configurable useCustomTrackSelection{"useCustomTrackSelection", false, "whether to use the custom cuts (used for cut variation for tracking efficiency systematics)"}; Configurable effSystMinNCrossedRowsTPC{"effSystMinNCrossedRowsTPC", 70, "min number of crossed rows TPC"}; + Configurable effSystMinNCrossedRowsTPCUseAlternateCut{"effSystMinNCrossedRowsTPCUseAlternateCut", false, "min number of crossed rows TPC - alternate cut of 120 - 5./pt"}; Configurable effSystMinNCrossedRowsOverFindableClustersTPC{"effSystMinNCrossedRowsOverFindableClustersTPC", 0.8, "min ratio of crossed rows over findable clusters TPC"}; Configurable effSystMaxChi2PerClusterTPC{"effSystMaxChi2PerClusterTPC", 4.0, "max chi2 per cluster TPC"}; Configurable effSystMaxChi2PerClusterITS{"effSystMaxChi2PerClusterITS", 36.0, "max chi2 per cluster ITS"}; @@ -118,6 +119,9 @@ struct TrackEfficiency { } } else { const auto& aodTrack = jetTrack.template track_as>(); + if (effSystMinNCrossedRowsTPCUseAlternateCut) { + customTrackSelection.SetMinNCrossedRowsTPC(120 - 5. / jetTrack.pt()); + } if (customTrackSelection.IsSelected(aodTrack)) { return true; } @@ -372,6 +376,18 @@ struct TrackEfficiency { registry.add("h2_trackselplot_pt_dcaxy", "track selection variable: pt vs dca XY", {HistType::kTH2F, {{200, 0., 200.}, {1000, -1.0, 1.0}}}); registry.add("h2_trackselplot_pt_dcaz", "track selection variable: pt vs dca Z", {HistType::kTH2F, {{200, 0., 200.}, {4000, -4.0, 4.0}}}); } + + AxisSpec occupancyAxis = {140, -0.5, 13999.5, "occupancy"}; + AxisSpec nTracksAxis = {16001, -1., 16000, "n tracks"}; + + if (doprocessOccupancyQA) { + registry.add("h2_occupancy_ntracksall_presel", "occupancy vs N_{tracks}; occupancy; N_{tracks}", {HistType::kTH2I, {occupancyAxis, nTracksAxis}}); + registry.add("h2_occupancy_ntracksall_postsel", "occupancy vs N_{tracks}; occupancy; N_{tracks}", {HistType::kTH2I, {occupancyAxis, nTracksAxis}}); + registry.add("h2_occupancy_ntrackssel_presel", "occupancy vs N_{tracks}; occupancy; N_{tracks}", {HistType::kTH2I, {occupancyAxis, nTracksAxis}}); + registry.add("h2_occupancy_ntrackssel_postsel", "occupancy vs N_{tracks}; occupancy; N_{tracks}", {HistType::kTH2I, {occupancyAxis, nTracksAxis}}); + registry.add("h2_occupancy_ntracksselptetacuts_presel", "occupancy vs N_{tracks}; occupancy; N_{tracks}", {HistType::kTH2I, {occupancyAxis, nTracksAxis}}); + registry.add("h2_occupancy_ntracksselptetacuts_postsel", "occupancy vs N_{tracks}; occupancy; N_{tracks}", {HistType::kTH2I, {occupancyAxis, nTracksAxis}}); + } } Preslice tracksPerJCollision = o2::aod::jtrack::collisionId; @@ -1235,6 +1251,38 @@ struct TrackEfficiency { } } PROCESS_SWITCH(TrackEfficiency, processTrackSelectionHistograms, "plots distributions of variables that are cut on during track selection", false); + + void processOccupancyQA(soa::Filtered::iterator const& collision, aod::JetTracks const& tracks) + { + float centrality = checkCentFT0M ? collision.centFT0M() : collision.centFT0C(); + if (cutCentrality && (centrality < centralityMin || centralityMax < centrality)) { + return; + } + + int occupancy = collision.trackOccupancyInTimeRange(); + int nTracksAll = tracks.size(); + int nTracksAllAcceptanceAndSelected = 0; + int nTracksInAcceptanceAndSelected = 0; + for (auto const& track : tracks) { + if (jetderiveddatautilities::selectTrack(track, trackSelection)) { + nTracksAllAcceptanceAndSelected += 1; + if (track.pt() >= trackQAPtMin && track.pt() < trackQAPtMax && track.eta() > trackQAEtaMin && track.eta() < trackQAEtaMax) { + nTracksInAcceptanceAndSelected += 1; + } + } + } + + registry.fill(HIST("h2_occupancy_ntracksall_presel"), occupancy, nTracksAll); + registry.fill(HIST("h2_occupancy_ntrackssel_presel"), occupancy, nTracksAllAcceptanceAndSelected); + registry.fill(HIST("h2_occupancy_ntracksselptetacuts_presel"), occupancy, nTracksInAcceptanceAndSelected); + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { + return; + } + registry.fill(HIST("h2_occupancy_ntracksall_postsel"), occupancy, nTracksAll); + registry.fill(HIST("h2_occupancy_ntrackssel_postsel"), occupancy, nTracksAllAcceptanceAndSelected); + registry.fill(HIST("h2_occupancy_ntracksselptetacuts_postsel"), occupancy, nTracksInAcceptanceAndSelected); + } + PROCESS_SWITCH(TrackEfficiency, processOccupancyQA, "occupancy QA on jet derived data", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) From 0e3de97c4196e924f07295a51ddaf68bc8e4f241 Mon Sep 17 00:00:00 2001 From: mcoquet642 <74600025+mcoquet642@users.noreply.github.com> Date: Tue, 3 Mar 2026 22:37:13 +0100 Subject: [PATCH 149/347] [Common] Fix for fwdtrackextension crash (#15238) Co-authored-by: Maurice Coquet --- Common/TableProducer/fwdtrackextension.cxx | 58 ++++++++++++---------- 1 file changed, 32 insertions(+), 26 deletions(-) diff --git a/Common/TableProducer/fwdtrackextension.cxx b/Common/TableProducer/fwdtrackextension.cxx index 18a038c323d..5ffdf73bf7a 100644 --- a/Common/TableProducer/fwdtrackextension.cxx +++ b/Common/TableProducer/fwdtrackextension.cxx @@ -50,7 +50,7 @@ struct FwdTrackExtension { Configurable geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; Configurable configCcdbUrl{"configCcdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; - Configurable refitGlobalMuon{"refitGlobalMuon", true, "Recompute parameters of global muons"}; + Configurable refitGlobalMuon{"refitGlobalMuon", false, "Recompute parameters of global muons"}; Service fCCDB; o2::parameters::GRPMagField* grpmag = nullptr; // for run 3, we access GRPMagField from GLO/Config/GRPMagField @@ -69,35 +69,41 @@ struct FwdTrackExtension { } } - void process(aod::Collisions::iterator const& collision, o2::aod::BCsWithTimestamps const& /*...*/, MuonsWithCov const& tracks, aod::MFTTracks const& /*...*/) + void process(MuonsWithCov const& tracks, aod::MFTTracks const& /*...*/, o2::aod::BCsWithTimestamps const& /*...*/, aod::Collisions const& /*...*/) { - auto bc = collision.template bc_as(); - if (fCurrentRun != bc.runNumber()) { - grpmag = fCCDB->getForTimeStamp(grpmagPath, bc.timestamp()); - if (grpmag != nullptr) { - LOGF(info, "Init field from GRP"); - o2::base::Propagator::initFieldFromGRP(grpmag); - } - LOGF(info, "Set field for muons"); - o2::mch::TrackExtrap::setField(); - fCurrentRun = bc.runNumber(); - } - const float zField = grpmag->getNominalL3Field(); for (const auto& track : tracks) { const auto trackType = track.trackType(); - o2::dataformats::GlobalFwdTrack fwdtrack = o2::aod::fwdtrackutils::getTrackParCovFwd(track, track); - if (refitGlobalMuon && (trackType == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack || trackType == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalForwardTrack)) { - auto muontrack = track.template matchMCHTrack_as(); - auto mfttrack = track.template matchMFTTrack_as(); - o2::dataformats::GlobalFwdTrack propmuon = o2::aod::fwdtrackutils::propagateMuon(muontrack, muontrack, collision, o2::aod::fwdtrackutils::propagationPoint::kToVertex, 0.f, zField); - SMatrix5 tpars(mfttrack.x(), mfttrack.y(), mfttrack.phi(), mfttrack.tgl(), mfttrack.signed1Pt()); - SMatrix55 tcovs{}; - o2::track::TrackParCovFwd mft{mfttrack.z(), tpars, tcovs, mfttrack.chi2()}; - fwdtrack = o2::aod::fwdtrackutils::refitGlobalMuonCov(propmuon, mft); + float dcaX = -999; + float dcaY = -999; + if (track.has_collision()) { + auto const& collision = track.collision(); + auto bc = collision.template bc_as(); + if (fCurrentRun != bc.runNumber()) { + grpmag = fCCDB->getForTimeStamp(grpmagPath, bc.timestamp()); + if (grpmag != nullptr) { + LOGF(info, "Init field from GRP"); + o2::base::Propagator::initFieldFromGRP(grpmag); + } + LOGF(info, "Set field for muons"); + o2::mch::TrackExtrap::setField(); + fCurrentRun = bc.runNumber(); + } + const float zField = grpmag->getNominalL3Field(); + + o2::track::TrackParCovFwd fwdtrack = o2::aod::fwdtrackutils::getTrackParCovFwdShift(track, 0.0); + if (refitGlobalMuon && (trackType == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack || trackType == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalForwardTrack)) { + auto muontrack = track.template matchMCHTrack_as(); + auto mfttrack = track.template matchMFTTrack_as(); + o2::dataformats::GlobalFwdTrack propmuon = o2::aod::fwdtrackutils::propagateMuon(muontrack, muontrack, collision, o2::aod::fwdtrackutils::propagationPoint::kToVertex, 0.f, zField); + SMatrix5 tpars(mfttrack.x(), mfttrack.y(), mfttrack.phi(), mfttrack.tgl(), mfttrack.signed1Pt()); + SMatrix55 tcovs{}; + o2::track::TrackParCovFwd mft{mfttrack.z(), tpars, tcovs, mfttrack.chi2()}; + fwdtrack = o2::aod::fwdtrackutils::refitGlobalMuonCov(propmuon, mft); + } + auto proptrack = o2::aod::fwdtrackutils::propagateTrackParCovFwd(fwdtrack, trackType, collision, o2::aod::fwdtrackutils::propagationPoint::kToDCA, 0.f, zField); + dcaX = (proptrack.getX() - collision.posX()); + dcaY = (proptrack.getY() - collision.posY()); } - const auto proptrack = o2::aod::fwdtrackutils::propagateTrackParCovFwd(fwdtrack, trackType, collision, o2::aod::fwdtrackutils::propagationPoint::kToDCA, 0.f, zField); - const float dcaX = (proptrack.getX() - collision.posX()); - const float dcaY = (proptrack.getY() - collision.posY()); fwdDCA(dcaX, dcaY); } } From 2fc5a219fe593d12d8de90032f50e40665cb477e Mon Sep 17 00:00:00 2001 From: Mattia Faggin Date: Tue, 3 Mar 2026 22:39:30 +0100 Subject: [PATCH 150/347] [PWGHF] Add Lc(<-Sc) pt in the tree. (#15234) --- PWGHF/TableProducer/treeCreatorSigmacCorrBkg.cxx | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/PWGHF/TableProducer/treeCreatorSigmacCorrBkg.cxx b/PWGHF/TableProducer/treeCreatorSigmacCorrBkg.cxx index 57af86a8a16..a3670cf6dfc 100644 --- a/PWGHF/TableProducer/treeCreatorSigmacCorrBkg.cxx +++ b/PWGHF/TableProducer/treeCreatorSigmacCorrBkg.cxx @@ -59,6 +59,7 @@ enum Reflections { NotReflected = 0, Reflected }; DECLARE_SOA_COLUMN(Y, y, float); DECLARE_SOA_COLUMN(Pt, pt, float); +DECLARE_SOA_COLUMN(PtLc, ptLc, float); DECLARE_SOA_COLUMN(Mass, mass, float); DECLARE_SOA_COLUMN(DeltaMass, deltaMass, float); DECLARE_SOA_COLUMN(Charge, charge, int8_t); @@ -72,6 +73,7 @@ DECLARE_SOA_COLUMN(IsReflected, isReflected, int8_t); DECLARE_SOA_TABLE(HfCorrBkgSc, "AOD", "HFCORRBKGSC", hf_sigmac_bkg::Y, hf_sigmac_bkg::Pt, + hf_sigmac_bkg::PtLc, hf_sigmac_bkg::Mass, hf_sigmac_bkg::DeltaMass, hf_sigmac_bkg::Charge, @@ -110,6 +112,8 @@ struct HfTreeCreatorSigmacCorrBkg { const int8_t isCandPKPiPiKP = hf_sigmac_utils::isDecayToPKPiToPiKP(candLcDauSc, candidateSc); std::array outputMlLcPKPi{-1., -1.}; std::array outputMlLcPiKP{-1., -1.}; + const float ptSc = candidateSc.pt(); + const float ptLcDauSc = candLcDauSc.pt(); /// rapidity selection on Σc0,++ if (yCandRecoMax >= 0. && std::abs(rapidity) > yCandRecoMax) { return; @@ -138,10 +142,10 @@ struct HfTreeCreatorSigmacCorrBkg { if (pdgCodeProng0Abs == kProton) { /// candidates with reconstructed Λc± → pK-π+ decay that are generated Λc± → pK-π+ (not reflected) - rowCorrBkgSc(rapidity, candidateSc.pt(), massSc, deltaMass, chargeSc, motherPdg, motherDecay, aod::hf_sigmac_bkg::DecaysLambdac::PKPi, outputMlLcPKPi.at(0), outputMlLcPKPi.at(1), aod::hf_sigmac_bkg::Reflections::NotReflected); + rowCorrBkgSc(rapidity, ptSc, ptLcDauSc, massSc, deltaMass, chargeSc, motherPdg, motherDecay, aod::hf_sigmac_bkg::DecaysLambdac::PKPi, outputMlLcPKPi.at(0), outputMlLcPKPi.at(1), aod::hf_sigmac_bkg::Reflections::NotReflected); } else if (keepReflectedSignals && pdgCodeProng0Abs == kPiPlus) { /// candidates with reconstructed Λc± → pK-π+ decay that are actually generated Λc± → π+K-p (reflected) - rowCorrBkgSc(rapidity, candidateSc.pt(), massSc, deltaMass, chargeSc, motherPdg, motherDecay, aod::hf_sigmac_bkg::DecaysLambdac::PKPi, outputMlLcPKPi.at(0), outputMlLcPKPi.at(1), aod::hf_sigmac_bkg::Reflections::Reflected); + rowCorrBkgSc(rapidity, ptSc, ptLcDauSc, massSc, deltaMass, chargeSc, motherPdg, motherDecay, aod::hf_sigmac_bkg::DecaysLambdac::PKPi, outputMlLcPKPi.at(0), outputMlLcPKPi.at(1), aod::hf_sigmac_bkg::Reflections::Reflected); } } /// candidates with Λc± reconstructed in the π+K-p decay @@ -153,10 +157,10 @@ struct HfTreeCreatorSigmacCorrBkg { if (pdgCodeProng0Abs == kPiPlus) { /// candidates with reconstructed Λc± → π+K-p decay that are generated Λc± → π+K-p (not reflected) - rowCorrBkgSc(rapidity, candidateSc.pt(), massSc, deltaMass, chargeSc, motherPdg, motherDecay, aod::hf_sigmac_bkg::DecaysLambdac::PiKP, outputMlLcPiKP.at(0), outputMlLcPiKP.at(1), aod::hf_sigmac_bkg::Reflections::NotReflected); + rowCorrBkgSc(rapidity, ptSc, ptLcDauSc, massSc, deltaMass, chargeSc, motherPdg, motherDecay, aod::hf_sigmac_bkg::DecaysLambdac::PiKP, outputMlLcPiKP.at(0), outputMlLcPiKP.at(1), aod::hf_sigmac_bkg::Reflections::NotReflected); } else if (keepReflectedSignals && pdgCodeProng0Abs == kProton) { /// candidates with reconstructed Λc± → π+K-p decay that are actually generated Λc± → pK-π+ (reflected) - rowCorrBkgSc(rapidity, candidateSc.pt(), massSc, deltaMass, chargeSc, motherPdg, motherDecay, aod::hf_sigmac_bkg::DecaysLambdac::PiKP, outputMlLcPiKP.at(0), outputMlLcPiKP.at(1), aod::hf_sigmac_bkg::Reflections::Reflected); + rowCorrBkgSc(rapidity, ptSc, ptLcDauSc, massSc, deltaMass, chargeSc, motherPdg, motherDecay, aod::hf_sigmac_bkg::DecaysLambdac::PiKP, outputMlLcPiKP.at(0), outputMlLcPiKP.at(1), aod::hf_sigmac_bkg::Reflections::Reflected); } } } From bb0d806467c2703a30d08948f8f97db10a5ae587 Mon Sep 17 00:00:00 2001 From: Jesper Karlsson Gumprecht <113693781+jesgum@users.noreply.github.com> Date: Tue, 3 Mar 2026 23:58:09 +0100 Subject: [PATCH 151/347] [ALICE3] Set ccdb manager in geocontainer for otf tracker pid (#15233) --- ALICE3/TableProducer/OTF/onTheFlyTrackerPid.cxx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ALICE3/TableProducer/OTF/onTheFlyTrackerPid.cxx b/ALICE3/TableProducer/OTF/onTheFlyTrackerPid.cxx index 391b99553e9..78db04bba62 100644 --- a/ALICE3/TableProducer/OTF/onTheFlyTrackerPid.cxx +++ b/ALICE3/TableProducer/OTF/onTheFlyTrackerPid.cxx @@ -433,12 +433,13 @@ struct OnTheFlyTrackerPid { float mMagneticField = 0.0f; void init(o2::framework::InitContext& initContext) { - mGeoContainer.init(initContext); - mMagneticField = mGeoContainer.getFloatValue(0, "global", "magneticfield"); - ccdb->setURL("http://alice-ccdb.cern.ch"); ccdb->setTimestamp(-1); + mGeoContainer.setCcdbManager(ccdb.operator->()); + mGeoContainer.init(initContext); + mMagneticField = mGeoContainer.getFloatValue(0, "global", "magneticfield"); + if (static_cast(maxBarrelLayers.value) > kTrackerRadii.size()) { LOG(fatal) << "Configured maxBarrelLayers (" << maxBarrelLayers.value << ") exceeds the size of kTrackerRadii (" << kTrackerRadii.size() From cf8621e201f971d0f91292d7976f22562bde635f Mon Sep 17 00:00:00 2001 From: Shirajum Monira <38348689+Eloviyo@users.noreply.github.com> Date: Wed, 4 Mar 2026 01:48:43 +0200 Subject: [PATCH 152/347] [PWGCF] FemtoUniverse V0 Task -- implemented bitmask and strangeness TOF for v0 mc reco (#15156) Co-authored-by: Shirajum Monira --- .../femtoUniversePairTaskTrackV0Extended.cxx | 128 +++++++++++++----- 1 file changed, 95 insertions(+), 33 deletions(-) diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx index bcc85d0acc2..91c5826fbec 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx @@ -58,6 +58,8 @@ struct FemtoUniversePairTaskTrackV0Extended { using FemtoRecoParticles = soa::Join; Preslice perColMC = aod::femtouniverseparticle::fdCollisionId; + using FemtoBasicParticles = soa::Join; + /// To apply narrow cut Configurable confZVertexCut{"confZVertexCut", 10.f, "Event sel: Maximum z-Vertex (cm)"}; Configurable confEta{"confEta", 0.8, "Eta cut for the global track"}; @@ -1533,7 +1535,8 @@ struct FemtoUniversePairTaskTrackV0Extended { } PROCESS_SWITCH(FemtoUniversePairTaskTrackV0Extended, processPairFractionsMCTruthV0, "Process MC data to obtain pair fractions for V0V0 MC truth pairs", false); - void processMCReco(FemtoRecoParticles const& parts, aod::FdMCParticles const& mcparts) + template + void doMCReco(PartType const& parts, aod::FdMCParticles const& mcparts) { for (const auto& part : parts) { auto mcPartId = part.fdMCParticleId(); @@ -1543,54 +1546,103 @@ struct FemtoUniversePairTaskTrackV0Extended { // if (part.partType() == aod::femtouniverseparticle::ParticleType::kV0) { if (mcpart.pdgMCTruth() == kLambda0) { - const auto& posChild = parts.iteratorAt(part.globalIndex() - 2); - const auto& negChild = parts.iteratorAt(part.globalIndex() - 1); - /// Daughters that do not pass this condition are not selected - if (isParticleTPC(posChild, 0) && isParticleTPC(negChild, 1)) { - registryMCreco.fill(HIST("plus/MCrecoLambda"), mcpart.pt(), mcpart.eta()); // lambda - if (auto mcpartIdChild = posChild.fdMCParticleId(); mcpartIdChild != -1) { - const auto& mcpartChild = mcparts.iteratorAt(mcpartIdChild); - registryMCreco.fill(HIST("plus/MCrecoLambdaChildPr"), mcpartChild.pt(), mcpartChild.eta()); // lambda proton child - } - if (auto mcpartIdChild = negChild.fdMCParticleId(); mcpartIdChild != -1) { - const auto& mcpartChild = mcparts.iteratorAt(mcpartIdChild); - registryMCreco.fill(HIST("plus/MCrecoLambdaChildPi"), mcpartChild.pt(), mcpartChild.eta()); // lambda pion child + if (!invMLambda(part.mLambda(), part.mAntiLambda(), 0)) + continue; + const auto& posChild = parts.iteratorAt(part.globalIndex() - 2 - parts.begin().globalIndex()); + const auto& negChild = parts.iteratorAt(part.globalIndex() - 1 - parts.begin().globalIndex()); + if constexpr (std::experimental::is_detected::value) { + /// Daughters that do not pass this condition are not selected + if (!isParticleTPC(posChild, 0) || !isParticleTPC(negChild, 1)) + continue; + + if (!isParticleTOF(posChild, 0) || !isParticleTOF(negChild, 1)) + continue; + + } else { + if ((posChild.pidCut() & (1u << 0)) == 0 || (negChild.pidCut() & (1u << 1)) == 0) + continue; + + if (ConfV0Selection.confUseStrangenessTOF) { + if ((part.pidCut() & 3) != 3) + continue; + } else { + if ((posChild.pidCut() & (8u << 0)) == 0 || (negChild.pidCut() & (8u << 1)) == 0) + continue; } } + registryMCreco.fill(HIST("plus/MCrecoLambda"), mcpart.pt(), mcpart.eta()); // lambda + } else if (mcpart.pdgMCTruth() == kLambda0Bar) { - const auto& posChild = parts.iteratorAt(part.globalIndex() - 2); - const auto& negChild = parts.iteratorAt(part.globalIndex() - 1); - /// Daughters that do not pass this condition are not selected - if (isParticleTPC(posChild, 1) && isParticleTPC(negChild, 0)) { - registryMCreco.fill(HIST("minus/MCrecoLambda"), mcpart.pt(), mcpart.eta()); // anti-lambda - if (auto mcpartIdChild = posChild.fdMCParticleId(); mcpartIdChild != -1) { - const auto& mcpartChild = mcparts.iteratorAt(mcpartIdChild); - registryMCreco.fill(HIST("minus/MCrecoLambdaChildPi"), mcpartChild.pt(), mcpartChild.eta()); // anti-lambda pion child - } - if (auto mcpartIdChild = negChild.fdMCParticleId(); mcpartIdChild != -1) { - const auto& mcpartChild = mcparts.iteratorAt(mcpartIdChild); - registryMCreco.fill(HIST("minus/MCrecoLambdaChildPr"), mcpartChild.pt(), mcpartChild.eta()); // anti-lambda proton child + if (!invMLambda(part.mLambda(), part.mAntiLambda(), 1)) + continue; + const auto& posChild = parts.iteratorAt(part.globalIndex() - 2 - parts.begin().globalIndex()); + const auto& negChild = parts.iteratorAt(part.globalIndex() - 1 - parts.begin().globalIndex()); + if constexpr (std::experimental::is_detected::value) { + /// Daughters that do not pass this condition are not selected + if (!isParticleTPC(posChild, 1) || !isParticleTPC(negChild, 0)) + continue; + + if (!isParticleTOF(posChild, 1) || !isParticleTOF(negChild, 0)) + continue; + + } else { + if ((posChild.pidCut() & (1u << 1)) == 0 || (negChild.pidCut() & (1u << 0)) == 0) + continue; + + if (ConfV0Selection.confUseStrangenessTOF) { + if ((part.pidCut() & 12) != 12) + continue; + } else { + if ((posChild.pidCut() & (8u << 1)) == 0 || (negChild.pidCut() & (8u << 0)) == 0) + continue; } } + registryMCreco.fill(HIST("minus/MCrecoLambda"), mcpart.pt(), mcpart.eta()); // anti-lambda } } else if (part.partType() == aod::femtouniverseparticle::ParticleType::kTrack) { - if (part.sign() > 0) { + if (part.mAntiLambda() > 0) { // mAntiLambda is the sign here registryMCreco.fill(HIST("plus/MCrecoAllPt"), mcpart.pt()); - if (mcpart.pdgMCTruth() == kPiPlus && isNSigmaCombined(part.p(), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePi()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePi()))) { + if (mcpart.pdgMCTruth() == kPiPlus) { + if constexpr (std::experimental::is_detected::value) { + if (!isNSigmaCombined(part.p(), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePi()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePi()))) + continue; + } else { + if ((part.pidCut() & 128u) == 0) // 128 for pion combined + continue; + } registryMCreco.fill(HIST("plus/MCrecoPi"), mcpart.pt(), mcpart.eta()); registryMCreco.fill(HIST("plus/MCrecoPiPt"), mcpart.pt()); - } else if (mcpart.pdgMCTruth() == kProton && isNSigmaCombined(part.p(), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePr()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePr()))) { + } else if (mcpart.pdgMCTruth() == kProton) { + if constexpr (std::experimental::is_detected::value) { + if (!isNSigmaCombined(part.p(), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePr()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePr()))) + continue; + } else { + if ((part.pidCut() & 64u) == 0) // 64 for proton combined + continue; + } registryMCreco.fill(HIST("plus/MCrecoPr"), mcpart.pt(), mcpart.eta()); registryMCreco.fill(HIST("plus/MCrecoPrPt"), mcpart.pt()); } - } - - if (part.sign() < 0) { + } else if (part.mAntiLambda() < 0) { registryMCreco.fill(HIST("minus/MCrecoAllPt"), mcpart.pt()); - if (mcpart.pdgMCTruth() == kPiMinus && isNSigmaCombined(part.p(), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePi()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePi()))) { + if (mcpart.pdgMCTruth() == kPiMinus) { + if constexpr (std::experimental::is_detected::value) { + if (!isNSigmaCombined(part.p(), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePi()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePi()))) + continue; + } else { + if ((part.pidCut() & 128u) == 0) // 128 for pion combined + continue; + } registryMCreco.fill(HIST("minus/MCrecoPi"), mcpart.pt(), mcpart.eta()); registryMCreco.fill(HIST("minus/MCrecoPiPt"), mcpart.pt()); - } else if (mcpart.pdgMCTruth() == kProtonBar && isNSigmaCombined(part.p(), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePr()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePr()))) { + } else if (mcpart.pdgMCTruth() == kProtonBar) { + if constexpr (std::experimental::is_detected::value) { + if (!isNSigmaCombined(part.p(), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePr()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePr()))) + continue; + } else { + if ((part.pidCut() & 64u) == 0) // 64 for proton combined + continue; + } registryMCreco.fill(HIST("minus/MCrecoPr"), mcpart.pt(), mcpart.eta()); registryMCreco.fill(HIST("minus/MCrecoPrPt"), mcpart.pt()); } @@ -1599,7 +1651,17 @@ struct FemtoUniversePairTaskTrackV0Extended { } } + void processMCReco(FemtoRecoParticles const& parts, aod::FdMCParticles const& mcparts) + { + doMCReco(parts, mcparts); + } PROCESS_SWITCH(FemtoUniversePairTaskTrackV0Extended, processMCReco, "Process MC reco data", false); + + void processMCRecoBitmask(FemtoBasicParticles const& parts, aod::FdMCParticles const& mcparts) + { + doMCReco(parts, mcparts); + } + PROCESS_SWITCH(FemtoUniversePairTaskTrackV0Extended, processMCRecoBitmask, "Process MC reco data using bitmask for PID", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) From 43a136a129d3b13d2071cb673ac6150ce40932eb Mon Sep 17 00:00:00 2001 From: dyx-11 <1260971129@qq.com> Date: Wed, 4 Mar 2026 08:13:13 +0800 Subject: [PATCH 153/347] [PWGUD] truegap filtered (#15239) --- PWGUD/Tasks/flowCorrelationsUpc.cxx | 198 +++++++++++++++------------- 1 file changed, 104 insertions(+), 94 deletions(-) diff --git a/PWGUD/Tasks/flowCorrelationsUpc.cxx b/PWGUD/Tasks/flowCorrelationsUpc.cxx index 010bc11e3ee..30d3bdd60aa 100644 --- a/PWGUD/Tasks/flowCorrelationsUpc.cxx +++ b/PWGUD/Tasks/flowCorrelationsUpc.cxx @@ -46,10 +46,11 @@ namespace o2::aod namespace flowcorrupc { DECLARE_SOA_COLUMN(Multiplicity, multiplicity, int); -} +DECLARE_SOA_COLUMN(Truegapside, truegapside, int); +} // namespace flowcorrupc DECLARE_SOA_TABLE(Multiplicity, "AOD", "MULTIPLICITY", flowcorrupc::Multiplicity); - +DECLARE_SOA_TABLE(Truegapside, "AOD", "TRUEGAPSIDE", flowcorrupc::Truegapside); } // namespace o2::aod using namespace o2; @@ -66,6 +67,13 @@ struct CalcNchUpc { O2_DEFINE_CONFIGURABLE(cfgEtaCut, float, 0.8f, "Eta cut") O2_DEFINE_CONFIGURABLE(cfgMinMixEventNum, int, 5, "Minimum number of events to mix") + // Added UPC Cuts + SGSelector sgSelector; + Configurable cfgCutFV0{"cfgCutFV0", 50., "FV0A threshold"}; + Configurable cfgCutFT0A{"cfgCutFT0A", 150., "FT0A threshold"}; + Configurable cfgCutFT0C{"cfgCutFT0C", 50., "FT0C threshold"}; + Configurable cfgCutZDC{"cfgCutZDC", 10., "ZDC threshold"}; + // Filter trackFilter = (nabs(aod::track::eta) < cfgEtaCut) && (aod::track::pt > cfgPtCutMin) && (aod::track::pt < cfgPtCutMax) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)); using UdTracks = soa::Join; @@ -73,6 +81,7 @@ struct CalcNchUpc { using UDCollisionsFull = soa::Join; Produces multiplicityNch; + Produces truegapside; HistogramRegistry registry{"registry"}; @@ -80,16 +89,20 @@ struct CalcNchUpc { { AxisSpec axisNch = {100, 0, 100}; AxisSpec axisVrtx = {10, -10, 10}; + AxisSpec axisgap = {12, -6, 6}; registry.add("Ncharge", "N_{charge}", {HistType::kTH1D, {axisNch}}); registry.add("zVtx_all", "zVtx_all", {HistType::kTH1D, {axisVrtx}}); registry.add("Nch_vs_zVtx", "Nch vs zVtx", {HistType::kTH2D, {axisVrtx, axisNch}}); + registry.add("truegap", "truegap", {HistType::kTH1D, {axisgap}}); } void process(UDCollisionsFull::iterator const& collision, UdTracksFull const& tracks) { multiplicityNch(tracks.size()); + truegapside(sgSelector.trueGap(collision, cfgCutFV0, cfgCutFT0A, cfgCutFT0C, cfgCutZDC)); registry.fill(HIST("Ncharge"), tracks.size()); + registry.fill(HIST("truegap"), sgSelector.trueGap(collision, cfgCutFV0, cfgCutFT0A, cfgCutFT0C, cfgCutZDC)); registry.fill(HIST("zVtx_all"), collision.posZ()); registry.fill(HIST("Nch_vs_zVtx"), collision.posZ(), tracks.size()); } @@ -148,13 +161,13 @@ struct FlowCorrelationsUpc { // make the filters and cuts. Filter trackFilter = (aod::udtrack::isPVContributor == true); - Filter collisionFilter = (cfgGapSideMerge == false && aod::udcollision::gapSide == (uint8_t)cfgGapSide); + Filter collisionFilter = (((cfgGapSideMerge == true && (aod::udcollision::gapSide == (uint8_t)1 || aod::udcollision::gapSide == (uint8_t)0)) || aod::udcollision::gapSide == (uint8_t)cfgGapSide) && (cfgIfVertex == false || aod::collision::posZ < cfgZVtxCut) && (aod::udcollision::occupancyInTime > 0 && aod::udcollision::occupancyInTime < cfgCutOccupancyHigh) && ((cfgGapSideMerge == true && (aod::flowcorrupc::truegapside == 0 || aod::flowcorrupc::truegapside == 1)) || aod::flowcorrupc::truegapside == cfgGapSide)); // Filter collisionFilter = (nabs(aod::collision::posZ) < cfgZVtxCut) && (aod::flowcorrupc::multiplicity) > cfgMinMult && (aod::flowcorrupc::multiplicity) < cfgMaxMult && (aod::evsel::sel8) == true; // Filter trackFilter = (nabs(aod::track::eta) < cfgEtaCut) && (aod::track::pt > cfgPtCutMin) && (aod::track::pt < cfgPtCutMax) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)); using UdTracks = soa::Filtered>; using UdTracksFull = soa::Filtered>; - using UDCollisionsFull = soa::Filtered>; + using UDCollisionsFull = soa::Filtered>; // Define the outputs OutputObj same{Form("sameEvent_%i_%i", static_cast(cfgMinMult), static_cast(cfgMaxMult))}; @@ -235,9 +248,6 @@ struct FlowCorrelationsUpc { if (track.pt() < cfgPtCutMin || track.pt() > cfgPtCutMax) { return false; } - if (!track.isPVContributor()) { - return false; - } // registry.fill(HIST("hTrackCount"), 1.5); if (cfgDcaz && !(std::fabs(track.dcaZ()) < cfgDcazCut)) { return false; @@ -345,36 +355,36 @@ struct FlowCorrelationsUpc { if (tracks.size() < cfgMinMult || tracks.size() > cfgMaxMult) { return; } - if (cfgIsGoodItsLayers && collision.trs() == 0) { - return; - } - - if (cfgGapSideMerge) { - int gapSide = collision.gapSide(); - if (gapSide != 0 && gapSide != 1) { - return; - } - int trueGapSide = sgSelector.trueGap(collision, cfgCutFV0, cfgCutFT0A, cfgCutFT0C, cfgCutZDC); - int gapSide1 = trueGapSide; - if (gapSide1 != 0 && gapSide1 != 1) { - return; - } - } - if (!cfgGapSideMerge) { - int trueGapSide = sgSelector.trueGap(collision, cfgCutFV0, cfgCutFT0A, cfgCutFT0C, cfgCutZDC); - int gapSide1 = trueGapSide; - if (gapSide1 != cfgGapSide) { - return; - } - } - float vtxz = collision.posZ(); - if (cfgIfVertex && abs(vtxz) > cfgZVtxCut) { - return; - } - int occupancy = collision.occupancyInTime(); - if (cfgEvSelOccupancy && (occupancy < cfgCutOccupancyLow || occupancy > cfgCutOccupancyHigh)) { - return; - } + // if (cfgIsGoodItsLayers && collision.trs() == 0) { + // return; + // } + + // if (cfgGapSideMerge) { + // int gapSide = collision.gapSide(); + // if (gapSide != 0 && gapSide != 1) { + // return; + // } + // int trueGapSide = sgSelector.trueGap(collision, cfgCutFV0, cfgCutFT0A, cfgCutFT0C, cfgCutZDC); + // int gapSide1 = trueGapSide; + // if (gapSide1 != 0 && gapSide1 != 1) { + // return; + // } + // } + // if (!cfgGapSideMerge) { + // int trueGapSide = sgSelector.trueGap(collision, cfgCutFV0, cfgCutFT0A, cfgCutFT0C, cfgCutZDC); + // int gapSide1 = trueGapSide; + // if (gapSide1 != cfgGapSide) { + // return; + // } + // } + // float vtxz = collision.posZ(); + // if (cfgIfVertex && abs(vtxz) > cfgZVtxCut) { + // return; + // } + // int occupancy = collision.occupancyInTime(); + // if (cfgEvSelOccupancy && (occupancy < cfgCutOccupancyLow || occupancy > cfgCutOccupancyHigh)) { + // return; + // } int runIndex = collision.runNumber(); registry.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin @@ -402,64 +412,64 @@ struct FlowCorrelationsUpc { if (tracks1.size() < cfgMinMult || tracks1.size() > cfgMaxMult || tracks2.size() < cfgMinMult || tracks2.size() > cfgMaxMult) { continue; } - registry.fill(HIST("eventcount"), 4.5); - if (cfgIsGoodItsLayers && (collision1.trs() == 0 || collision2.trs() == 0)) { - continue; - } - registry.fill(HIST("eventcount"), 5.5); - if (cfgGapSideMerge) { - int gapSide = collision1.gapSide(); - if (gapSide != 0 && gapSide != 1) { - continue; - } - int trueGapSide = sgSelector.trueGap(collision1, cfgCutFV0, cfgCutFT0A, cfgCutFT0C, cfgCutZDC); - int gapSide1 = trueGapSide; - if (gapSide1 != 0 && gapSide1 != 1) { - continue; - } - } - if (!cfgGapSideMerge) { - int trueGapSide = sgSelector.trueGap(collision1, cfgCutFV0, cfgCutFT0A, cfgCutFT0C, cfgCutZDC); - int gapSide1 = trueGapSide; - if (gapSide1 != cfgGapSide) { - continue; - } - } - if (cfgGapSideMerge) { - int gapSide = collision2.gapSide(); - if (gapSide != 0 && gapSide != 1) { - continue; - } - int trueGapSide = sgSelector.trueGap(collision2, cfgCutFV0, cfgCutFT0A, cfgCutFT0C, cfgCutZDC); - int gapSide2 = trueGapSide; - if (gapSide2 != 0 && gapSide2 != 1) { - continue; - } - } - if (!cfgGapSideMerge) { - int trueGapSide = sgSelector.trueGap(collision2, cfgCutFV0, cfgCutFT0A, cfgCutFT0C, cfgCutZDC); - int gapSide2 = trueGapSide; - if (gapSide2 != cfgGapSide) { - continue; - } - } + // registry.fill(HIST("eventcount"), 4.5); + // if (cfgIsGoodItsLayers && (collision1.trs() == 0 || collision2.trs() == 0)) { + // continue; + // } + // registry.fill(HIST("eventcount"), 5.5); + // if (cfgGapSideMerge) { + // int gapSide = collision1.gapSide(); + // if (gapSide != 0 && gapSide != 1) { + // continue; + // } + // int trueGapSide = sgSelector.trueGap(collision1, cfgCutFV0, cfgCutFT0A, cfgCutFT0C, cfgCutZDC); + // int gapSide1 = trueGapSide; + // if (gapSide1 != 0 && gapSide1 != 1) { + // continue; + // } + // } + // if (!cfgGapSideMerge) { + // int trueGapSide = sgSelector.trueGap(collision1, cfgCutFV0, cfgCutFT0A, cfgCutFT0C, cfgCutZDC); + // int gapSide1 = trueGapSide; + // if (gapSide1 != cfgGapSide) { + // continue; + // } + // } + // if (cfgGapSideMerge) { + // int gapSide = collision2.gapSide(); + // if (gapSide != 0 && gapSide != 1) { + // continue; + // } + // int trueGapSide = sgSelector.trueGap(collision2, cfgCutFV0, cfgCutFT0A, cfgCutFT0C, cfgCutZDC); + // int gapSide2 = trueGapSide; + // if (gapSide2 != 0 && gapSide2 != 1) { + // continue; + // } + // } + // if (!cfgGapSideMerge) { + // int trueGapSide = sgSelector.trueGap(collision2, cfgCutFV0, cfgCutFT0A, cfgCutFT0C, cfgCutZDC); + // int gapSide2 = trueGapSide; + // if (gapSide2 != cfgGapSide) { + // continue; + // } + // } registry.fill(HIST("eventcount"), 6.5); - float vtxz = collision1.posZ(); - if (cfgIfVertex && abs(vtxz) > cfgZVtxCut) { - continue; - } - int occupancy = collision1.occupancyInTime(); - if (cfgEvSelOccupancy && (occupancy < cfgCutOccupancyLow || occupancy > cfgCutOccupancyHigh)) { - continue; - } - vtxz = collision2.posZ(); - if (cfgIfVertex && abs(vtxz) > cfgZVtxCut) { - continue; - } - occupancy = collision2.occupancyInTime(); - if (cfgEvSelOccupancy && (occupancy < cfgCutOccupancyLow || occupancy > cfgCutOccupancyHigh)) { - continue; - } + // float vtxz = collision1.posZ(); + // if (cfgIfVertex && abs(vtxz) > cfgZVtxCut) { + // continue; + // } + // int occupancy = collision1.occupancyInTime(); + // if (cfgEvSelOccupancy && (occupancy < cfgCutOccupancyLow || occupancy > cfgCutOccupancyHigh)) { + // continue; + // } + // vtxz = collision2.posZ(); + // if (cfgIfVertex && abs(vtxz) > cfgZVtxCut) { + // continue; + // } + // occupancy = collision2.occupancyInTime(); + // if (cfgEvSelOccupancy && (occupancy < cfgCutOccupancyLow || occupancy > cfgCutOccupancyHigh)) { + // continue; + // } registry.fill(HIST("eventcount"), MixedFinal); fillCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent, collision1.runNumber()); // fill the ME histogram and Sparse } From e8585c1475b91423b7fe1a871c663575c9de7ee8 Mon Sep 17 00:00:00 2001 From: ariedel-cern <85537041+ariedel-cern@users.noreply.github.com> Date: Wed, 4 Mar 2026 01:49:40 +0100 Subject: [PATCH 154/347] [PWGCF] Update Femto framework (#15246) --- PWGCF/Femto/Core/baseSelection.h | 265 +++++++------ PWGCF/Femto/Core/partitions.h | 28 +- PWGCF/Femto/Core/selectionContainer.h | 551 +++++++++++++++++--------- PWGCF/Femto/Core/trackBuilder.h | 261 +++++------- 4 files changed, 628 insertions(+), 477 deletions(-) diff --git a/PWGCF/Femto/Core/baseSelection.h b/PWGCF/Femto/Core/baseSelection.h index ceb2184a96a..fcce0c11c13 100644 --- a/PWGCF/Femto/Core/baseSelection.h +++ b/PWGCF/Femto/Core/baseSelection.h @@ -40,9 +40,9 @@ namespace o2::analysis::femto /// It evaluates which selections are fulfilled, assembles a final bitmask, and tracks required vs. optional cuts. /// /// \tparam T Type of observable values (mostly floats). -/// \tparam BitmaskType Type used for internal bitmask operations (e.g., uint32_t, uint64_t). +/// \tparam BitmaskType Integer type used for bitmask operations (e.g., uint32_t, uint64_t). /// \tparam NumObservables Total number of observables handled. -template +template class BaseSelection { public: @@ -53,57 +53,41 @@ class BaseSelection virtual ~BaseSelection() = default; /// \brief Add a static-value based selection for a specific observable. - /// \param selectionValues Vector of threshold values. /// \param observableIndex Index of the observable. + /// \param selectionName Name of the selection. + /// \param selectionValues Vector of threshold values. /// \param limitType Type of limit (from limits::LimitType). - /// \param skipMostPermissiveBit Whether to skip the loosest threshold in the bitmask. - /// \param isMinimalCut Whether this cut is mandatory or optional. + /// \param skipMostPermissiveBit Whether to skip the loosest threshold when assembling the bitmask. + /// \param isMinimalCut Whether this cut is mandatory (must be passed for the candidate to be accepted). + /// \param isOptionalCut Whether this cut is optional (candidate is accepted if any optional cut passes). void addSelection(int observableIndex, std::string const& selectionName, std::vector const& selectionValues, limits::LimitType limitType, bool skipMostPermissiveBit, bool isMinimalCut, - bool isOptionCut) + bool isOptionalCut) { // check index - if (static_cast(observableIndex) >= NumObservables) { + if (static_cast(observableIndex) >= NumObservables) { LOG(fatal) << "Observable is not valid. Observable (index) has to be smaller than " << NumObservables; } // init selection container for selection at given index - mSelectionContainers.at(observableIndex) = SelectionContainer(selectionName, selectionValues, limitType, skipMostPermissiveBit, isMinimalCut, isOptionCut); - - // check if any selections are configured - if (mSelectionContainers.at(observableIndex).isEmpty()) { - return; - } - - // keep track of selections and bits - mNSelectionBits += mSelectionContainers.at(observableIndex).getShift(); - mNSelection += mSelectionContainers.at(observableIndex).getNSelections(); + mSelectionContainers.at(observableIndex) = SelectionContainer(selectionName, selectionValues, limitType, skipMostPermissiveBit, isMinimalCut, isOptionalCut); - if (mNSelectionBits > sizeof(BitmaskType) * CHAR_BIT) { - LOG(fatal) << "Too many selections. At most " << sizeof(BitmaskType) * CHAR_BIT << " number of bits are supported"; - } - // check if any selection is minimal - if (mSelectionContainers.at(observableIndex).isMinimalCut()) { - mHasMinimalSelection = true; - } - // check if selection is optional - if (mSelectionContainers.at(observableIndex).isOptionalCut()) { - mHasOptionalSelection = true; - } + init(observableIndex); } /// \brief Add a function-based selection for a specific observable. - /// \param baseName Base name for TF1 functions. - /// \param lowerLimit Lower bound for the TF1 domain. - /// \param upperLimit Upper bound for the TF1 domain. - /// \param selectionValues Function definitions as strings. /// \param observableIndex Index of the observable. - /// \param limitType Type of limit. - /// \param skipMostPermissiveBit Whether to skip the loosest threshold in the bitmask. - /// \param isMinimalCut Whether this cut is mandatory or optional. + /// \param selectionName Name of the selection. + /// \param lowerLimit Lower bound of the TF1 domain. + /// \param upperLimit Upper bound of the TF1 domain. + /// \param functions Selection threshold functions as strings (parsed as TF1 expressions). + /// \param limitType Type of limit (from limits::LimitType). + /// \param skipMostPermissiveBit Whether to skip the loosest threshold when assembling the bitmask. + /// \param isMinimalCut Whether this cut is mandatory (must be passed for the candidate to be accepted). + /// \param isOptionalCut Whether this cut is optional (candidate is accepted if any optional cut passes). void addSelection(int observableIndex, std::string const& selectionName, T lowerLimit, @@ -114,73 +98,75 @@ class BaseSelection bool isMinimalCut, bool isOptionalCut) { - if (static_cast(observableIndex) >= NumObservables) { + if (static_cast(observableIndex) >= NumObservables) { LOG(fatal) << "Observable is not valid. Observable (index) has to be smaller than " << NumObservables; } mSelectionContainers.at(observableIndex) = SelectionContainer(selectionName, lowerLimit, upperLimit, functions, limitType, skipMostPermissiveBit, isMinimalCut, isOptionalCut); - // check if any selections are configured - if (mSelectionContainers.at(observableIndex).isEmpty()) { - return; - } - - // advance mNSelections so we can use it as offset for next selection - mNSelectionBits += mSelectionContainers.at(observableIndex).getShift(); - mNSelection += mSelectionContainers.at(observableIndex).getNSelections(); + init(observableIndex); + } - if (mNSelectionBits > sizeof(BitmaskType) * CHAR_BIT) { - LOG(fatal) << "Too many selections. At most " << sizeof(BitmaskType) * CHAR_BIT << " are supported"; - } - // keep track of selection selections - // check if any cut is minimal - if (mSelectionContainers.at(observableIndex).isMinimalCut()) { - mHasMinimalSelection = true; - } - // check if any selection is optional - if (mSelectionContainers.at(observableIndex).isOptionalCut()) { - mHasOptionalSelection = true; + /// \brief Add a static-value based selection for a specific observable. + /// \param observableIndex Index of the observable. + /// \param selectionName Name of the selection. + /// \param selectionValues Vector of threshold values. + /// \param limitType Type of limit (from limits::LimitType). + /// \param skipMostPermissiveBit Whether to skip the loosest threshold when assembling the bitmask. + /// \param isMinimalCut Whether this cut is mandatory (must be passed for the candidate to be accepted). + /// \param isOptionalCut Whether this cut is optional (candidate is accepted if any optional cut passes). + void addSelection(int observableIndex, + std::string const& selectionName, + std::vector const& selectionRanges, + bool skipMostPermissiveBit, + bool isMinimalCut, + bool isOptionalCut) + { + // check index + if (static_cast(observableIndex) >= NumObservables) { + LOG(fatal) << "Observable is not valid. Observable (index) has to be smaller than " << NumObservables; } + // init selection container for selection at given index + mSelectionContainers.at(observableIndex) = SelectionContainer(selectionName, selectionRanges, skipMostPermissiveBit, isMinimalCut, isOptionalCut); + + init(observableIndex); } - /// \brief Add a boolean based selection for a specific observable. - /// \param mode Whether the selection is not applied, minimal or optional cut + /// \brief Add a boolean-based selection for a specific observable. /// \param observableIndex Index of the observable. + /// \param selectionName Name of the selection. + /// \param mode Controls how the cut is applied: + /// -1 = optional cut, bit is stored in bitmask; + /// 0 = cut is disabled, no bit stored; + /// 1 = minimal (mandatory) cut, no extra bit stored since only one threshold exists. void addSelection(int observableIndex, std::string const& selectionName, int mode) { switch (mode) { - case -1: // cut is optional and we store bit for the cut + case -1: // cut is optional and we store a bit for it mSelectionContainers.at(observableIndex) = SelectionContainer(selectionName, std::vector{1}, limits::LimitType::kEqual, false, false, true); - mHasOptionalSelection = true; - mNSelectionBits += 1; - mNSelection += 1; break; - case 0: // cut is not applied, initalize with empty vector, so we bail out later + case 0: // cut is disabled; initialize with empty vector so evaluation bails out early mSelectionContainers.at(observableIndex) = SelectionContainer(selectionName, std::vector{}, limits::LimitType::kEqual, false, false, false); break; - case 1: // cut is added as mininal selection (since it is only one value, no extra bit is stored) + case 1: // mandatory cut; only one threshold so the most permissive bit is skipped and no extra bit is stored mSelectionContainers.at(observableIndex) = SelectionContainer(selectionName, std::vector{1}, limits::LimitType::kEqual, true, true, false); - mHasMinimalSelection = true; - mNSelection += 1; break; default: LOG(fatal) << "Invalid switch for boolean selection"; } - if (mNSelectionBits > sizeof(BitmaskType) * CHAR_BIT) { - LOG(fatal) << "Too many selections. At most " << sizeof(BitmaskType) * CHAR_BIT << " are supported"; - } + init(observableIndex); } /// \brief Update the limits of a function-based selection for a specific observable. /// \param observable Index of the observable. - /// \param value Value at which to evaluate the selection functions. + /// \param value Value at which to re-evaluate the selection functions. void updateLimits(int observable, T value) { mSelectionContainers.at(observable).updateLimits(value); } - /// \brief Reset the internal bitmask and evaluation flags before evaluating a new event. + /// \brief Reset the internal bitmask and evaluation flags before processing a new candidate. void reset() { mFinalBitmask.reset(); @@ -195,6 +181,8 @@ class BaseSelection } } + /// \brief Reset the selection container for a single observable. + /// \param observableIndex Index of the observable to reset. void reset(int observableIndex) { mSelectionContainers.at(observableIndex).reset(); } /// \brief Evaluate a single observable against its configured selections. @@ -206,22 +194,20 @@ class BaseSelection if (mSelectionContainers.at(observableIndex).isEmpty()) { return; } - // if any previous observable did not pass minimal selections, there is no point in setting bitmask for other observables - // minimal selection for each observable is computed after adding it + // if a previous observable already failed a minimal selection, + // there is no point in evaluating further observables if (!mPassesMinimalSelections) { return; } // set bitmask for given observable mSelectionContainers.at(observableIndex).evaluate(value); - // check if minimal selction for this observable holds - // if one minimal selection is not fullfilled, the condition failes + // if any minimal selection is not fulfilled, the candidate is rejected if (mHasMinimalSelection) { if (!mSelectionContainers.at(observableIndex).passesAsMinimalCut()) { mPassesMinimalSelections = false; } } - // check if any optional selection holds - // if one optional selection is fullfilled, the condition succeeds + // if any optional selection is fulfilled, the candidate is accepted if (mHasOptionalSelection) { if (mSelectionContainers.at(observableIndex).passesAsOptionalCut()) { mPassesOptionalSelections = true; @@ -231,39 +217,41 @@ class BaseSelection /// \brief Evaluate a single observable against its configured selections. /// \param observableIndex Index of the observable. - /// \param values vector of values of the observable. + /// \param values Vector of values of the observable. void evaluateObservable(int observableIndex, std::vector values) { // if there are no selections configured, bail out if (mSelectionContainers.at(observableIndex).isEmpty()) { return; } - // if any previous observable did not pass minimal selections, there is no point in setting bitmask for other observables - // minimal selection for each observable is computed after adding it + // if a previous observable already failed a minimal selection, + // there is no point in evaluating further observables if (!mPassesMinimalSelections) { return; } // set bitmask for given observable mSelectionContainers.at(observableIndex).evaluate(values); - // check if minimal selction for this observable holds + // if any minimal selection is not fulfilled, the candidate is rejected if (mHasMinimalSelection) { - if (mSelectionContainers.at(observableIndex).passesAsMinimalCut() == false) { + if (!mSelectionContainers.at(observableIndex).passesAsMinimalCut()) { mPassesMinimalSelections = false; } } - // check if any optional selection holds + // if any optional selection is fulfilled, the candidate is accepted if (mHasOptionalSelection) { - if (mSelectionContainers.at(observableIndex).passesAsOptionalCut() == true) { + if (mSelectionContainers.at(observableIndex).passesAsOptionalCut()) { mPassesOptionalSelections = true; } } } - /// \brief Add comments to specific observabel + /// \brief Add comments to the selections of a specific observable. + /// \param observableIndex Index of the observable. + /// \param comments Vector of comment strings, one per selection threshold. void addComments(int observableIndex, std::vector const& comments) { mSelectionContainers.at(observableIndex).addComments(comments); } - /// \brief Check if all required (minimal) and optional cuts are passed. - /// \return True if all required and at least one optional cut (if present) is passed. + /// \brief Check whether all required and optional cuts are passed. + /// \return True if all minimal cuts pass and, if optional cuts are present, at least one of them passes. bool passesAllRequiredSelections() const { if (mHasMinimalSelection && !mHasOptionalSelection) { @@ -275,23 +263,25 @@ class BaseSelection if (mHasMinimalSelection && mHasOptionalSelection) { return mPassesMinimalSelections && mPassesOptionalSelections; } + // if there are no minimal or optional selections, we pass let it pass with true return true; } - /// \brief Check if the optional selection for a specific observable is passed. + /// \brief Check whether the optional selection for a specific observable is passed. /// \param observableIndex Index of the observable. - /// \return True if at least one optional selection is fulfilled. + /// \return True if at least one optional selection for this observable is fulfilled. bool passesOptionalSelection(int observableIndex) const { return mSelectionContainers.at(observableIndex).passesAsOptionalCut(); } - /// \brief Assemble the global selection bitmask from individual observable selections. + /// \brief Assemble the global selection bitmask from all individual observable selections. + /// \tparam HistName Name of the histogram used to track selection statistics. template void assembleBitmask() { mHistRegistry->fill(HIST(HistName), mNSelection); - // if the required selections are not passed, we can break early + // if the required selections are not passed, clear the bitmask and return early if (!this->passesAllRequiredSelections()) { mFinalBitmask.reset(); return; @@ -299,17 +289,16 @@ class BaseSelection mHistRegistry->fill(HIST(HistName), mNSelection + 1); int binCenter = 0; - // to assemble bitmask, convert all bitmask into integers - // shift the current one and add the new bits + // assemble the final bitmask by shifting each container's bitmask to its offset and OR-ing it in for (auto const& selectionContainer : mSelectionContainers) { - // if there are no selections for a certain observable, skip + // skip observables with no configured selections if (selectionContainer.isEmpty()) { continue; } - // Shift the result to its offset and add the new values + // shift the container's bitmask to its offset and merge mFinalBitmask |= (selectionContainer.getBitmask() << selectionContainer.getOffset()); - for (int j = 0; j < selectionContainer.getNSelections(); ++j) { + for (std::size_t j = 0; j < selectionContainer.getNSelections(); ++j) { if (j == 0 && selectionContainer.isMinimalCut()) { // minimal cuts are always filled mHistRegistry->fill(HIST(HistName), binCenter); @@ -325,28 +314,36 @@ class BaseSelection } /// \brief Retrieve the assembled bitmask as an integer value. - /// \return The combined selection bitmask. + /// \return The combined selection bitmask for all observables. BitmaskType getBitmask() const { return static_cast(mFinalBitmask.to_ullong()); } - /// \brief Retrieve the assembled bitmask as an integer value. - /// \return The combined selection bitmask. + /// \brief Retrieve the bitmask for a single observable as an integer value. + /// \param observableIndex Index of the observable. + /// \return The selection bitmask for the specified observable. BitmaskType getBitmask(int observableIndex) const { return static_cast(mSelectionContainers.at(observableIndex).getBitmask().to_ullong()); } - /// \brief Set the assembled bitmask for on observable - /// \return The combined selection bitmask. + /// \brief Manually set the bitmask for a specific observable. + /// \tparam R Integer type of the bitmask value. + /// \param observableIndex Index of the observable. + /// \param bitmask Bitmask value to set. template void setBitmask(int observableIndex, R bitmask) { mSelectionContainers.at(observableIndex).setBitmask(bitmask); } + /// \brief Retrieve the loosest (most permissive) selection threshold for a specific observable. + /// \param observableIndex Index of the observable. + /// \return The loosest threshold value configured for this observable. T getLoosestSelection(int observableIndex) const { return mSelectionContainers.at(observableIndex).getLoosestSelection(); } + /// \brief Print the full configuration of all selections to the log. + /// \param objectName Name of the object owning this selection (used as label in the log output). void printSelections(const std::string& objectName) const { LOG(info) << "Printing Configuration of " << objectName; for (size_t idx = 0; idx < mSelectionContainers.size(); ++idx) { - const auto& container = mSelectionContainers[idx]; + const auto& container = mSelectionContainers.at(idx); if (container.isEmpty()) { continue; } @@ -360,15 +357,11 @@ class BaseSelection LOG(info) << " Bitmask shift : " << container.getShift(); LOG(info) << " Selections:"; - const bool useFunctions = container.isUsingFunctions(); - const auto& values = container.getSelectionValues(); - const auto& functions = container.getSelectionFunction(); - const auto& comments = container.getComments(); - - for (int j = 0; j < container.getNSelections(); ++j) { + for (std::size_t j = 0; j < container.getNSelections(); ++j) { std::stringstream line; - std::string sel = useFunctions ? std::string(functions[j].GetExpFormula().Data()) : std::to_string(values[j]); + std::string sel = container.getValueAsString(j); + std::string comment = container.getComment(j); line << " " << std::left << std::setw(25) << sel; @@ -379,8 +372,8 @@ class BaseSelection line << "-> Bit: 0x" << std::hex << std::uppercase << (1ULL << bit) << std::dec; } - if (!comments.empty()) { - line << " (" << comments.at(j) << ")"; + if (!comment.empty()) { + line << " (" << comment << ")"; } LOG(info) << line.str(); } @@ -390,24 +383,27 @@ class BaseSelection LOG(info) << "Printing done"; } + /// \brief Initialize histograms and set bitmask offsets for all configured observables. + /// \tparam HistName Name of the histogram to create in the registry. + /// \param registry Pointer to the histogram registry. template void setupContainers(o2::framework::HistogramRegistry* registry) { mHistRegistry = registry; - // Create histogram with correct number of bins + // create histogram with one bin per selection, plus two summary bins (all analyzed, all passed) int nBins = mNSelection + 2; mHistRegistry->add(HistName, "; Selection Bits; Entries", o2::framework::kTH1F, {{nBins, -0.5, nBins - 0.5}}); - size_t binIndex = 0; + int binIndex = 0; int offset = 0; - for (size_t idx = 0; idx < mSelectionContainers.size(); ++idx) { + for (std::size_t idx = 0; idx < mSelectionContainers.size(); ++idx) { auto& container = mSelectionContainers[idx]; if (container.isEmpty()) { continue; } container.setOffset(offset); offset += container.getShift(); - for (int j = 0; j < container.getNSelections(); j++) { + for (std::size_t j = 0; j < container.getNSelections(); j++) { std::string label = container.getBinLabel(j); mHistRegistry->get(HIST(HistName))->GetXaxis()->SetBinLabel(binIndex + 1, label.c_str()); binIndex++; @@ -418,15 +414,40 @@ class BaseSelection } protected: + void init(int observableIndex) + { + // check if any selections are configured + if (mSelectionContainers.at(observableIndex).isEmpty()) { + return; + } + + // track the number of occupied bits and total selections + mNSelectionBits += mSelectionContainers.at(observableIndex).getShift(); + mNSelection += mSelectionContainers.at(observableIndex).getNSelections(); + + // check if any selection is minimal + if (mSelectionContainers.at(observableIndex).isMinimalCut()) { + mHasMinimalSelection = true; + } + // check if selection is optional + if (mSelectionContainers.at(observableIndex).isOptionalCut()) { + mHasOptionalSelection = true; + } + + if (mNSelectionBits > sizeof(BitmaskType) * CHAR_BIT) { + LOG(fatal) << "Too many selections. At most " << sizeof(BitmaskType) * CHAR_BIT << " number of bits are supported"; + } + } + o2::framework::HistogramRegistry* mHistRegistry = nullptr; - std::array, NumObservables> mSelectionContainers = {}; ///< Array containing all selections - std::bitset mFinalBitmask = {}; ///< final bitmaks - std::size_t mNSelectionBits = 0; ///< Number of selections (all - minimal selections) - int mNSelection = 0; ///< Number of selections all selections - bool mHasMinimalSelection = false; ///< Set to true if all minimal (mandatory) selections are passed - bool mPassesMinimalSelections = true; ///< Set to true if all minimal (mandatory) selections are passed - bool mHasOptionalSelection = false; ///< Set to true if at least one selections is optional - bool mPassesOptionalSelections = false; ///< Set to true if at least one optional (non-mandatory) selections is passed + std::array, NumObservables> mSelectionContainers = {}; ///< Array of selection containers, one per observable + std::bitset mFinalBitmask = {}; ///< Assembled bitmask combining all observable selections + std::size_t mNSelectionBits = 0; ///< Number of bits occupied in the bitmask (excludes skipped most-permissive bits) + std::size_t mNSelection = 0; ///< Total number of configured selection thresholds across all observables + bool mHasMinimalSelection = false; ///< True if at least one observable has a mandatory (minimal) cut configured + bool mPassesMinimalSelections = true; ///< True if all mandatory (minimal) cuts have been passed so far + bool mHasOptionalSelection = false; ///< True if at least one observable has an optional cut configured + bool mPassesOptionalSelections = false; ///< True if at least one optional cut has been passed }; } // namespace o2::analysis::femto diff --git a/PWGCF/Femto/Core/partitions.h b/PWGCF/Femto/Core/partitions.h index d14bbf76196..c4b039e8c05 100644 --- a/PWGCF/Femto/Core/partitions.h +++ b/PWGCF/Femto/Core/partitions.h @@ -24,18 +24,24 @@ (o2::aod::femtocollisions::magField >= static_cast(selection.magFieldMin) && o2::aod::femtocollisions::magField <= static_cast(selection.magFieldMax)) && \ ncheckbit(o2::aod::femtocollisions::mask, selection.collisionMask) +// macro for track momentum, i.e. ||q|*pT/q| * cosh(eta) +// there is no ncosh function, so we have to make our own, i.e. cosh(x) = (exp(x)+exp(-x))/2 +#define TRACK_MOMENTUM(chargeAbs, signedPt, eta) nabs((chargeAbs) * (signedPt)) * (nexp(eta) + nexp(-1.f * (eta))) / 2.f + // standard track partition -#define MAKE_TRACK_PARTITION(selection) \ - ifnode(selection.chargeSign.node() != 0, ifnode(selection.chargeSign.node() > 0, o2::aod::femtobase::stored::signedPt > 0.f, o2::aod::femtobase::stored::signedPt < 0.f), true) && \ - (nabs(selection.chargeAbs.node() * o2::aod::femtobase::stored::signedPt) > selection.ptMin) && \ - (nabs(selection.chargeAbs.node() * o2::aod::femtobase::stored::signedPt) < selection.ptMax) && \ - (o2::aod::femtobase::stored::eta > selection.etaMin) && \ - (o2::aod::femtobase::stored::eta < selection.etaMax) && \ - (o2::aod::femtobase::stored::phi > selection.phiMin) && \ - (o2::aod::femtobase::stored::phi < selection.phiMax) && \ - ifnode(nabs(selection.chargeAbs.node() * o2::aod::femtobase::stored::signedPt) * (nexp(o2::aod::femtobase::stored::eta) + nexp(-1.f * o2::aod::femtobase::stored::eta)) / (2.f) <= selection.pidThres, \ - ncheckbit(o2::aod::femtotracks::mask, selection.maskLowMomentum), \ - ncheckbit(o2::aod::femtotracks::mask, selection.maskHighMomentum)) +#define MAKE_TRACK_PARTITION(selection) \ + ifnode(selection.chargeSign.node() != 0, ifnode(selection.chargeSign.node() > 0, o2::aod::femtobase::stored::signedPt > 0.f, o2::aod::femtobase::stored::signedPt < 0.f), true) && \ + (nabs(selection.chargeAbs * o2::aod::femtobase::stored::signedPt) > selection.ptMin) && \ + (nabs(selection.chargeAbs * o2::aod::femtobase::stored::signedPt) < selection.ptMax) && \ + (o2::aod::femtobase::stored::eta > selection.etaMin) && \ + (o2::aod::femtobase::stored::eta < selection.etaMax) && \ + (o2::aod::femtobase::stored::phi > selection.phiMin) && \ + (o2::aod::femtobase::stored::phi < selection.phiMax) && \ + ifnode(TRACK_MOMENTUM(selection.chargeAbs, o2::aod::femtobase::stored::signedPt, o2::aod::femtobase::stored::eta) <= selection.pidThres, \ + ncheckbit(o2::aod::femtotracks::mask, selection.maskLowMomentum) && \ + (o2::aod::femtotracks::mask & selection.rejectionMaskLowMomentum) == static_cast(0), \ + ncheckbit(o2::aod::femtotracks::mask, selection.maskHighMomentum) && \ + (o2::aod::femtotracks::mask & selection.rejectionMaskHighMomentum) == static_cast(0)) // partition for phis and rhos, i.e. resonance that are their own antiparticle #define MAKE_RESONANCE_0_PARTITON(selection) \ diff --git a/PWGCF/Femto/Core/selectionContainer.h b/PWGCF/Femto/Core/selectionContainer.h index e9d67e6354a..d67819b6f8d 100644 --- a/PWGCF/Femto/Core/selectionContainer.h +++ b/PWGCF/Femto/Core/selectionContainer.h @@ -27,8 +27,10 @@ #include #include #include +#include #include #include +#include #include namespace o2::analysis::femto @@ -37,20 +39,21 @@ namespace o2::analysis::femto /// Limit type for selections namespace limits { -enum LimitType { kUpperLimit, ///< simple upper limit for the value, e.g. p_T < 1 GeV/c - kAbsUpperLimit, ///< upper limit of the absolute value, e.g. |eta| < 0.8 - kLowerLimit, ///< simple lower limit for the value, e.g. p_T > 0.2 GeV/c - kAbsLowerLimit, ///< lower limit of the absolute value, e.g. |DCA_xyz| > 0.05 cm - kUpperFunctionLimit, ///< simple upper limit of a function value, e.g. DCA_xy > f(pt) - kAbsUpperFunctionLimit, ///< upper limit of an absolute value given by a function, e.g. |DCA_xy| > f(pt) - kLowerFunctionLimit, ///< simple lower limit of a function value, e.g. DCA_xy < f(pt) - kAbsLowerFunctionLimit, ///< lower limit of an absolute value given by a function, e.g. |DCA_xy| < f(pt) - kEqual, ///< values need to be equal, e.g. sign = 1 - kEqualArray, ///< values inside an array need to be equal +enum LimitType { kUpperLimit, ///< simple upper limit, e.g. p_T < 1 GeV/c + kAbsUpperLimit, ///< upper limit on the absolute value, e.g. |eta| < 0.8 + kLowerLimit, ///< simple lower limit, e.g. p_T > 0.2 GeV/c + kAbsLowerLimit, ///< lower limit on the absolute value, e.g. |DCA_xy| > 0.05 cm + kUpperFunctionLimit, ///< upper limit given by a function, e.g. DCA_xy < f(pt) + kAbsUpperFunctionLimit, ///< upper limit on the absolute value given by a function, e.g. |DCA_xy| < f(pt) + kLowerFunctionLimit, ///< lower limit given by a function, e.g. DCA_xy > f(pt) + kAbsLowerFunctionLimit, ///< lower limit on the absolute value given by a function, e.g. |DCA_xy| > f(pt) + kEqual, ///< value must equal a fixed threshold, e.g. sign == 1 + kEqualArray, ///< each element of a value array must equal the corresponding threshold + kRange, ///< value must fall within [lower, upper]; either bound can be omitted (open interval) kLimitTypeLast }; -std::unordered_map limitTypeAsStrings = { +inline const std::unordered_map limitTypeAsStrings = { {kUpperLimit, "Upper Limit"}, {kAbsUpperLimit, "Absolute Upper Limit"}, {kLowerLimit, "Lower Limit"}, @@ -61,283 +64,358 @@ std::unordered_map limitTypeAsStrings = { {kAbsLowerFunctionLimit, "Absolute Lower Function Limit"}, {kEqual, "Equal"}, {kEqualArray, "EqualArray"}, - + {kRange, "Range"}, + {kLimitTypeLast, "Last Limit Type"}, }; }; // namespace limits /// \class SelectionContainer -/// \brief Class for storing and evaluating multiple selection thresholds for a single observable. -/// \tparam T Data type for selection values (mostly floats) -/// \tparam BitmaskType Type used for bitmask storage (e.g., uint8_t, uint32_t). +/// \brief Stores and evaluates multiple selection thresholds for a single observable. +/// +/// Selections can be based on static threshold values or dynamically evaluated TF1 functions. +/// Thresholds are sorted from most permissive to most restrictive so that evaluation can bail +/// out early once a threshold fails. +/// +/// \tparam T Data type for selection values (mostly floats). +/// \tparam BitmaskType Integer type used for bitmask storage (e.g., uint8_t, uint32_t). template class SelectionContainer { public: - /// Default constructor + /// \brief Default constructor. SelectionContainer() = default; + + /// \brief Destructor. ~SelectionContainer() = default; - /// \brief Constructor for static value-based selection. - /// \param SelectionValues Vector of values for the selection. + /// \brief Constructor for static value-based selections. + /// \param selectionName Name of the observable this container manages. + /// \param selectionValues Vector of threshold values. /// \param limitType Type of limit (from limits::LimitType). - /// \param SkipMostPermissiveBit Whether to skip the most permissive bit in the bitmask. - /// \param IsMinimalCut Whether this selection should be treated as a minimal required cut. - SelectionContainer(std::string const& SelectionName, - std::vector const& SelectionValues, + /// \param skipMostPermissiveBit Whether to skip the most permissive threshold when assembling the bitmask. + /// \param isMinimalCut Whether this selection is mandatory (candidate is rejected if it fails). + /// \param isOptionalCut Whether this selection is optional (candidate is accepted if any optional cut passes). + SelectionContainer(std::string const& selectionName, + std::vector const& selectionValues, limits::LimitType limitType, - bool SkipMostPermissiveBit, - bool IsMinimalCut, + bool skipMostPermissiveBit, + bool isMinimalCut, bool isOptionalCut) - : mSelectionName(SelectionName), - mSelectionValues(SelectionValues), + : mSelectionName(selectionName), + mSelectionValues(selectionValues), mLimitType(limitType), - mSkipMostPermissiveBit(SkipMostPermissiveBit), - mIsMinimalCut(IsMinimalCut), + mSkipMostPermissiveBit(skipMostPermissiveBit), + mIsMinimalCut(isMinimalCut), mIsOptionalCut(isOptionalCut) { if (mSelectionValues.size() > sizeof(BitmaskType) * CHAR_BIT) { LOG(fatal) << "Too many selections for single a observable. Limit is " << sizeof(BitmaskType) * CHAR_BIT; } + if (isMinimalCut && isOptionalCut) { + LOG(fatal) << "A selection cannot be both minimal and optional"; + } // values for selection are not necessarily ordered correctly sortSelections(); } - /// \brief Constructor for function-based dynamic selection. - /// \param baseName Base name for TF1 functions. - /// \param lowerLimit Lower bound for TF1 domain. - /// \param upperLimit Upper bound for TF1 domain. - /// \param functions Vector of strings defining TF1 functions. - /// \param limitType Type of limit. - /// \param skipMostPermissiveBit Whether to skip the most permissive bit in the bitmask. - /// \param IsMinimalCut Whether this selection should be treated as a minimal required cut. - SelectionContainer(std::string const& SelectionName, + /// \brief Constructor for range-based selections defined as "lower;upper" strings. + /// Either bound may be omitted to represent an open interval, e.g. ";1.0" means value < 1.0. + /// \param selectionName Name of the observable this container manages. + /// \param rangeStrings Vector of range strings, each of the form "lower;upper". + /// \param skipMostPermissiveBit Whether to skip the most permissive threshold when assembling the bitmask. + /// \param isMinimalCut Whether this selection is mandatory (candidate is rejected if it fails). + /// \param isOptionalCut Whether this selection is optional (candidate is accepted if any optional cut passes). + SelectionContainer(std::string const& selectionName, + std::vector const& rangeStrings, + bool skipMostPermissiveBit, + bool isMinimalCut, + bool isOptionalCut) + : mSelectionName(selectionName), + mLimitType(limits::kRange), + mSkipMostPermissiveBit(skipMostPermissiveBit), + mIsMinimalCut(isMinimalCut), + mIsOptionalCut(isOptionalCut) + { + if (rangeStrings.size() > sizeof(BitmaskType) * CHAR_BIT) { + LOG(fatal) << "Too many selections for a single observable. Limit is " << sizeof(BitmaskType) * CHAR_BIT; + } + if (isMinimalCut && isOptionalCut) { + LOG(fatal) << "A selection cannot be both minimal and optional"; + } + for (auto const& rangeStr : rangeStrings) { + T lower, upper; + parseRangeString(rangeStr, lower, upper); + mSelectionRanges.emplace_back(lower, upper); + } + // ranges are sorted by their lenghts, i.e. from widest range to tightest range + // in principle the ranges do not have to include each other, exepct this is configured as minimal cut, check is added at the end + // to cover both cases, this also means we always check all ranges, when assembling the bit mask + sortSelections(); + // init mSelectionValues to be the widths of the intervals + for (std::size_t i = 0; i < mSelectionRanges.size(); i++) { + mSelectionValues.push_back(mSelectionRanges[i].second - mSelectionRanges[i].first); + } + + // for minimal range cut, ranges must be strictly nested (each range contains all narrower ones) + // this is required for the early-exit logic in passesAsMinimalCut() to be correct + if (isMinimalCut) { + for (std::size_t i = 0; i + 1 < mSelectionRanges.size(); i++) { + if (mSelectionRanges[i].first > mSelectionRanges[i + 1].first || + mSelectionRanges[i].second < mSelectionRanges[i + 1].second) { + LOG(fatal) << "Ranges for minimal cut " << selectionName + << " are not nested. Range [" << mSelectionRanges[i].first << ";" << mSelectionRanges[i].second + << "] does not contain [" << mSelectionRanges[i + 1].first << ";" << mSelectionRanges[i + 1].second << "]"; + } + } + } + } + + /// \brief Constructor for function-based dynamic selections. + /// \param selectionName Name of the observable this container manages. + /// \param lowerLimit Lower bound of the TF1 domain. + /// \param upperLimit Upper bound of the TF1 domain. + /// \param functions Vector of strings defining TF1 threshold functions. + /// \param limitType Type of limit (from limits::LimitType). + /// \param skipMostPermissiveBit Whether to skip the most permissive threshold when assembling the bitmask. + /// \param isMinimalCut Whether this selection is mandatory (candidate is rejected if it fails). + /// \param isOptionalCut Whether this selection is optional (candidate is accepted if any optional cut passes). + SelectionContainer(std::string const& selectionName, T lowerLimit, T upperLimit, std::vector const& functions, limits::LimitType limitType, bool skipMostPermissiveBit, - bool IsMinimalCut, + bool isMinimalCut, bool isOptionalCut) - : mSelectionName(SelectionName), + : mSelectionName(selectionName), mLimitType(limitType), mSkipMostPermissiveBit(skipMostPermissiveBit), - mIsMinimalCut(IsMinimalCut), + mIsMinimalCut(isMinimalCut), mIsOptionalCut(isOptionalCut) { if (functions.size() > sizeof(BitmaskType) * CHAR_BIT) { LOG(fatal) << "Too many selections for single a observable. Limit is " << sizeof(BitmaskType) * CHAR_BIT; } + if (isMinimalCut && isOptionalCut) { + LOG(fatal) << "A selection cannot be both minimal and optional"; + } for (std::size_t i = 0; i < functions.size(); i++) { mSelectionFunctions.emplace_back((mSelectionName + std::to_string(i)).c_str(), functions.at(i).c_str(), lowerLimit, upperLimit); } - // functions for selection are not necessarily ordered correctly - // use value at midpoint to order them - // here we rely on the user that the functions can be ordered like this over the whole interval + // functions are not necessarily ordered correctly; + // use the midpoint of the domain to establish their order. + // this relies on the user ensuring the ordering is consistent across the whole interval. T midPoint = (lowerLimit + upperLimit) / 2.; sortFunctions(midPoint); - // initialize the values also to the midpoint + // initialize threshold values to the functions evaluated at the midpoint for (std::size_t i = 0; i < functions.size(); i++) { mSelectionValues.push_back(mSelectionFunctions.at(i).Eval(midPoint)); } } - /// \brief Sort static selection values based on the limit type. - void sortSelections() + /// \brief Attach comments to the selection thresholds, one per threshold in the same order as the input values. + /// \param comments Vector of comment strings. + void addComments(std::vector const& comments) { - switch (mLimitType) { - case (limits::kUpperLimit): - case (limits::kAbsUpperLimit): - std::sort(mSelectionValues.begin(), mSelectionValues.end(), [](T a, T b) { return a > b; }); - break; - case (limits::kLowerLimit): - case (limits::kAbsLowerLimit): - std::sort(mSelectionValues.begin(), mSelectionValues.end(), [](T a, T b) { return a < b; }); - break; - default: - break; + // note: threshold values may be reordered by sortSelections() or sortFunctions(), + // so comments must be provided in the already-sorted order + if (comments.size() != getNSelections()) { + LOG(fatal) << "Number of comments and number of selections are inconsistent"; } + mComments = comments; } - /// \brief Sort selection functions based on evaluation at a given point. - /// \param value Point at which to evaluate the functions for ordering. - void sortFunctions(T value) + /// \brief Get comments attached to the selection thresholds. + /// \return Vector of comment strings. + std::string getComment(int selectionIndex) const { - switch (mLimitType) { - case (limits::kUpperFunctionLimit): - case (limits::kAbsUpperFunctionLimit): - std::sort(mSelectionFunctions.begin(), mSelectionFunctions.end(), [value](TF1 const& a, TF1 const& b) { return a.Eval(value) > b.Eval(value); }); - break; - case (limits::kLowerFunctionLimit): - case (limits::kAbsLowerFunctionLimit): - std::sort(mSelectionFunctions.begin(), mSelectionFunctions.end(), [value](TF1 const& a, TF1 const& b) { return a.Eval(value) < b.Eval(value); }); - break; - default: - break; + if (mComments.empty()) { + return std::string(""); } + return mComments.at(selectionIndex); } - /// \brief Add comments to the selection values - /// \param comments Vector of comments - void addComments(std::vector const& comments) - { - // make sure that the comments are in correct order - // the values passed to the selection container can be reordered based on the limit type - mComments = comments; - } - - std::vector const& getComments() const { return mComments; } + /// \brief Get the name of this selection. + /// \return Selection name string. std::string const& getSelectionName() const { return mSelectionName; } - /// \brief Update selection limits using internal functions evaluated at a given value. - /// \param value Input value to evaluate functions at. + /// \brief Update threshold values by re-evaluating the internal TF1 functions at a given point. + /// \param value Input value at which to evaluate the functions. void updateLimits(T value) { - // functions are ordered so just add the values in the same order + // functions are already sorted, so evaluate in the same order as mSelectionValues for (std::size_t i = 0; i < mSelectionValues.size(); i++) { mSelectionValues.at(i) = mSelectionFunctions.at(i).Eval(value); } } - /// \brief Evaluate which selection criteria are fulfilled for a given value. + /// \brief Evaluate which selection thresholds are passed for a given observable value. /// \param value Value of the observable to evaluate. void evaluate(T value) { - // better safe than sorry and reset the bitmask before you evaluate and set minimal selection to true + // reset the bitmask before evaluating mBitmask.reset(); - // the values are ordered, from most loose to most tight, as soon as one comparison is not true, we can break out of the loop - bool breakLoop = false; - // iterate over all limits and set the corresponding bit if we pass the selection, otherwise break out as soon as we can - // only break if the observable is used for the minimal selection - for (size_t i = 0; i < mSelectionValues.size(); i++) { - switch (mLimitType) { - case (limits::kUpperLimit): - case (limits::kUpperFunctionLimit): + + // switch on limit type once outside the loop; + // thresholds are sorted from most permissive to most restrictive, + // so we can break early as soon as one comparison fails + switch (mLimitType) { + case (limits::kUpperLimit): + case (limits::kUpperFunctionLimit): + for (std::size_t i = 0; i < mSelectionValues.size(); i++) { if (value <= mSelectionValues.at(i)) { mBitmask.set(i); } else { - breakLoop = true; + break; } - break; - case (limits::kAbsUpperLimit): - case (limits::kAbsUpperFunctionLimit): + } + break; + case (limits::kAbsUpperLimit): + case (limits::kAbsUpperFunctionLimit): + for (std::size_t i = 0; i < mSelectionValues.size(); i++) { if (std::abs(value) <= mSelectionValues.at(i)) { mBitmask.set(i); } else { - breakLoop = true; + break; } - break; - case (limits::kLowerLimit): - case (limits::kLowerFunctionLimit): + } + break; + case (limits::kLowerLimit): + case (limits::kLowerFunctionLimit): + for (std::size_t i = 0; i < mSelectionValues.size(); i++) { if (value >= mSelectionValues.at(i)) { mBitmask.set(i); } else { - breakLoop = true; + break; } - break; - case (limits::kAbsLowerLimit): - case (limits::kAbsLowerFunctionLimit): + } + break; + case (limits::kAbsLowerLimit): + case (limits::kAbsLowerFunctionLimit): + for (std::size_t i = 0; i < mSelectionValues.size(); i++) { if (std::abs(value) >= mSelectionValues.at(i)) { mBitmask.set(i); } else { - breakLoop = true; + break; } - break; - case (limits::kEqual): - // special case for kEqual since here we cannot really establish an order so we need to check all cases explicitly and we cannot bail early + } + break; + case (limits::kRange): + // ranges are sorted widest-first but a narrower range passing does not imply a wider one fails (no check on boundries), + // so all ranges must be checked explicitly — no early exit + for (std::size_t i = 0; i < mSelectionRanges.size(); i++) { + if (value >= mSelectionRanges.at(i).first && value <= mSelectionRanges.at(i).second) { + mBitmask.set(i); + } + } + break; + case (limits::kEqual): + // kEqual has no natural ordering, so all thresholds must be checked and we cannot bail early + for (std::size_t i = 0; i < mSelectionValues.size(); i++) { if (std::fabs(value - mSelectionValues.at(i)) < constants::math::Epsilon) { mBitmask.set(i); } - break; - default: - breakLoop = true; - } - // bail early if a comparison fails - // the values are ordered, so all following we also fail, there there is no point in contiuing - if (breakLoop) { + } break; - } + default: + LOG(warn) << "Limit type not known, no selection is applied"; } } - /// \brief Evaluate which selection criteria are fulfilled for a given value. - /// \param values Values of the observable to evaluate + /// \brief Evaluate which selection thresholds are passed for a vector of observable values. + /// Only kEqualArray is supported for now; each element is compared against the corresponding threshold. + /// \param values Values of the observable to evaluate. void evaluate(std::vector const& values) { if (values.size() != mSelectionValues.size()) { LOG(fatal) << "Wrong number of values have been passed"; } - for (size_t i = 0; i < mSelectionValues.size(); i++) { - switch (mLimitType) { - case (limits::kEqualArray): + // reset the bitmask before evaluating + mBitmask.reset(); + + switch (mLimitType) { + case (limits::kEqualArray): + for (std::size_t i = 0; i < mSelectionValues.size(); i++) { if (std::fabs(values.at(i) - mSelectionValues.at(i)) < constants::math::Epsilon) { mBitmask.set(i); } - break; - default: - continue; - } + } + break; + default: + LOG(warn) << "Limit type not known, no selection is applied"; } } - /// \brief Retrieve the bitmask indicating which selections were passed. + /// \brief Retrieve the bitmask indicating which thresholds were passed. + /// If mSkipMostPermissiveBit is set, the bit for the loosest threshold is removed by shifting. /// \return Bitset representing passed selections. std::bitset getBitmask() const { - // if we do not skip the last bit, return full bitmask - if (mSkipMostPermissiveBit == false) { + if (!mSkipMostPermissiveBit) { return mBitmask; } else { - // for the other selections we can remove the first bit since it is the minimal selection and therefore always true + // remove the first (most permissive) bit since it corresponds to the minimal selection and is always true return mBitmask >> 1; } } + + /// \brief Manually set the internal bitmask. + /// \tparam R Integer type of the bitmask value. + /// \param bitmask Bitmask value to set. template void setBitmask(R bitmask) { mBitmask = std::bitset(bitmask); } - /// \brief Check whether the minimal cut condition is fulfilled. - /// \return True if minimal selection is fulfilled, false otherwise. + /// \brief Reset the internal bitmask to zero. + void reset() { mBitmask.reset(); } + + /// \brief Check whether the mandatory (minimal) cut condition is fulfilled. + /// \return True if the minimal selection passes or if this container is not marked as a minimal cut. bool passesAsMinimalCut() const { if (mIsMinimalCut) { - // check if any bit is set - // in case were bits are evaluted in order, if the loosests fails, all fail, so testing any is safe here - return mBitmask.any(); + // if any bit is set the loosest threshold passed; since thresholds are ordered, + // the loosest passing implies all looser ones also pass + return mBitmask.test(0); } - // if a selection is not marked as minimal cut we return true by default + // not a minimal cut — return true by default so it does not block the candidate return true; } - /// \brief Check whether any optional cuts are fulfilled. - /// \return True if at least one optional cut is passed. + /// \brief Check whether any optional cut is fulfilled. + /// \return True if at least one optional threshold is passed, false if this container is not marked as optional. bool passesAsOptionalCut() const { if (mIsOptionalCut) { - // check if any bit is set - // in case were bits are evaluted in order, if the loosests fails, all fail, so testing any is safe here + // if any bit is set the loosest threshold passed return mBitmask.any(); } - // if a selection is not marked as optional cut we return false by default + // not an optional cut — return false by default so it does not accidentally accept the candidate return false; } - /// \brief Get the loosest (most permissive) selection value. - /// \return First (loosest) selection value. - T getLoosestSelection() const { return mSelectionValues.at(0); } + /// \brief Get the loosest (most permissive) selection threshold value. + /// \return The first element of the sorted threshold vector. + T getLoosestSelection() const + { + if (mSelectionValues.empty()) { + LOG(fatal) << "No selections configured"; + } + return mSelectionValues.at(0); + } - /// \brief Check if there are any selection values configured. We also init values in case of function so this is safe - /// \return True if no selections are configured. + /// \brief Check whether any selection thresholds are configured. + /// For function-based selections, mSelectionValues is always populated (initialised at the midpoint), + /// so this check is safe for both static and function-based containers. + /// \return True if no thresholds are configured. bool isEmpty() const { return mSelectionValues.empty(); } - /// \brief Check if there are any selection values configured. - /// \return True if no selections are configured. - bool isUsingFunctions() const { return !mSelectionFunctions.empty(); } - - /// \brief Get the number of bits to shift for the final bitmask. - /// \return Number of bits to shift. + /// \brief Get the number of bits this container contributes to the global bitmask. + /// If the most permissive bit is skipped, the contribution is reduced by one. + /// \return Number of bits to add to the global bitmask offset. int getShift() const { if (mSelectionValues.empty()) { @@ -345,22 +423,47 @@ class SelectionContainer } if (mSkipMostPermissiveBit) { return static_cast(mSelectionValues.size() - 1); - } else { - return static_cast(mSelectionValues.size()); } + return static_cast(mSelectionValues.size()); } + /// \brief Set the bit offset of this container within the global bitmask. + /// \param offset Bit position at which this container's bits start. void setOffset(int offset) { mOffset = offset; } + + /// \brief Get the bit offset of this container within the global bitmask. + /// \return Bit offset. int getOffset() const { return mOffset; } - int getNSelections() const { return mSelectionValues.size(); } + /// \brief Get the total number of configured selection thresholds. + /// \return Number of thresholds. + std::size_t getNSelections() const { return mSelectionValues.size(); } + /// \brief Build a histogram bin label string encoding the full configuration of a single threshold. + /// \param selectionIndex Index of the threshold within this container. + /// \return Encoded label string. std::string getBinLabel(int selectionIndex) const { std::ostringstream oss; std::string sectionDelimiter = ":::"; std::string valueDelimiter = "___"; std::string noValue = "X"; + + // Determine value string + std::string valueStr; + + if (mLimitType == limits::kRange) { + // Print actual lower;upper interval + const auto& range = mSelectionRanges.at(selectionIndex); + std::ostringstream rangeStream; + rangeStream << range.first << ";" << range.second; + valueStr = rangeStream.str(); + } else if (mSelectionFunctions.empty()) { + valueStr = std::to_string(mSelectionValues.at(selectionIndex)); + } else { + valueStr = mSelectionFunctions.at(selectionIndex).GetExpFormula().Data(); + } + oss << "SelectionName" << valueDelimiter << mSelectionName << sectionDelimiter << "LimitType" << valueDelimiter << getLimitTypeAsString() << sectionDelimiter << "MinimalCut" << valueDelimiter << (mIsMinimalCut ? "1" : "0") << sectionDelimiter @@ -368,12 +471,32 @@ class SelectionContainer << "OptionalCut" << valueDelimiter << (mIsOptionalCut ? "1" : "0") << sectionDelimiter << "Shift" << valueDelimiter << getShift() << sectionDelimiter << "Offset" << valueDelimiter << mOffset << sectionDelimiter - << "Value" << valueDelimiter << (mSelectionFunctions.empty() ? std::to_string(mSelectionValues.at(selectionIndex)) : mSelectionFunctions.at(selectionIndex).GetExpFormula().Data()) << sectionDelimiter + << "Value" << valueDelimiter << valueStr << sectionDelimiter << "BitPosition" << valueDelimiter << (mSkipMostPermissiveBit ? (selectionIndex == 0 ? noValue : std::to_string(mOffset + selectionIndex - 1)) : std::to_string(mOffset + selectionIndex)) << sectionDelimiter << "Comment" << valueDelimiter << (mComments.empty() ? noValue : mComments.at(selectionIndex)); return oss.str(); } + std::string getValueAsString(int selectionIndex) const + { + if (this->isEmpty()) { + return std::string("No value configured"); + } + if (!mSelectionFunctions.empty()) { + return std::string(mSelectionFunctions.at(selectionIndex).GetExpFormula().Data()); + } + if (!mSelectionRanges.empty()) { + std::ostringstream oss; + oss << mSelectionRanges.at(selectionIndex).first << ";" << mSelectionRanges.at(selectionIndex).second; + return oss.str(); + } + return std::to_string(mSelectionValues.at(selectionIndex)); + } + + /// \brief Get the global bit position of a threshold within the final bitmask. + /// Calling this for the skipped most-permissive threshold is a fatal error. + /// \param selectionIndex Index of the threshold within this container. + /// \return Global bit position. int getBitPosition(int selectionIndex) const { if (selectionIndex == 0 && mSkipMostPermissiveBit) { @@ -387,43 +510,107 @@ class SelectionContainer } } - /// \brief Get string representation of the limit type. - /// \return String name of the limit type. - std::string getLimitTypeAsString() const { return limits::limitTypeAsStrings[mLimitType]; } + /// \brief Get the string representation of the configured limit type. + /// \return Human-readable limit type name. + std::string getLimitTypeAsString() const { return limits::limitTypeAsStrings.at(mLimitType); } - /// \brief Get a copy of all selection values. - /// \return Vector of selection values. + /// \brief Get the configured static threshold values. + /// \return Const reference to the vector of threshold values. std::vector const& getSelectionValues() const { return mSelectionValues; } - /// \brief Get a copy of all selection values. - /// \return Vector of selection values. + /// \brief Get the configured TF1 threshold functions. + /// \return Const reference to the vector of TF1 functions. std::vector const& getSelectionFunction() const { return mSelectionFunctions; } - /// \brief Check if this container is marked as minimal cut - /// \return True if minimal cut, false otherwise. + /// \brief Check whether this container is marked as a mandatory (minimal) cut. + /// \return True if this is a minimal cut. bool isMinimalCut() const { return mIsMinimalCut; } - /// \brief Check if this container is marked as optional cut - /// \return True if minimal cut, false otherwise. + /// \brief Check whether this container is marked as an optional cut. + /// \return True if this is an optional cut. bool isOptionalCut() const { return mIsOptionalCut; } - /// \brief Check whether the most permissive bit is skipped. - /// \return True if skipped, false otherwise. + /// \brief Check whether the most permissive threshold bit is skipped when assembling the bitmask. + /// \return True if the most permissive bit is skipped. bool skipMostPermissiveBit() const { return mSkipMostPermissiveBit; } - void reset() { mBitmask.reset(); } - private: - std::string mSelectionName = std::string(""); - std::vector mSelectionValues = {}; ///< Values used for the selection - std::vector mSelectionFunctions = {}; ///< Function used for the selection - limits::LimitType mLimitType = limits::kLimitTypeLast; ///< Limit type of selection - bool mSkipMostPermissiveBit = false; ///< whether to skip the last bit or not - bool mIsMinimalCut = false; ///< whether to use this observable for minimal selection or not - bool mIsOptionalCut = false; ///< whether to use this observable for minimal selection or not - std::vector mComments = {}; ///< Comments for the values - std::bitset mBitmask = {}; ///< bitmask for the observable - int mOffset = 0; + /// \brief Sort static threshold values from most permissive to most restrictive based on the limit type. + void sortSelections() + { + switch (mLimitType) { + case (limits::kUpperLimit): + case (limits::kAbsUpperLimit): + std::sort(mSelectionValues.begin(), mSelectionValues.end(), [](T a, T b) { return a > b; }); + break; + case (limits::kLowerLimit): + case (limits::kAbsLowerLimit): + std::sort(mSelectionValues.begin(), mSelectionValues.end(), [](T a, T b) { return a < b; }); + break; + case (limits::kRange): + // sort by range width descending so the most permissive (widest) range comes first + std::sort(mSelectionRanges.begin(), mSelectionRanges.end(), + [](std::pair const& a, std::pair const& b) { + return (a.second - a.first) > (b.second - b.first); + }); + break; + default: + break; + } + } + + /// \brief Sort selection functions from most permissive to most restrictive, evaluated at a given point. + /// \param value Point at which to evaluate the functions for ordering. + void sortFunctions(T value) + { + switch (mLimitType) { + case (limits::kUpperFunctionLimit): + case (limits::kAbsUpperFunctionLimit): + std::sort(mSelectionFunctions.begin(), mSelectionFunctions.end(), [value](TF1 const& a, TF1 const& b) { return a.Eval(value) > b.Eval(value); }); + break; + case (limits::kLowerFunctionLimit): + case (limits::kAbsLowerFunctionLimit): + std::sort(mSelectionFunctions.begin(), mSelectionFunctions.end(), [value](TF1 const& a, TF1 const& b) { return a.Eval(value) < b.Eval(value); }); + break; + default: + break; + } + } + + /// \brief Parse a range string of the form "lower;upper" into a lower and upper bound. + /// Either bound may be omitted (e.g. ";1.0" or "0.5;"), in which case + /// -/+ numeric_limits::max() is used respectively. + /// \param rangeStr Input string to parse. + /// \param lower Output lower bound. + /// \param upper Output upper bound. + void parseRangeString(std::string const& rangeStr, T& lower, T& upper) const + { + auto pos = rangeStr.find(';'); + if (pos == std::string::npos) { + LOG(fatal) << "Range string '" << rangeStr << "' is missing ';' separator. Expected format: 'lower;upper'"; + } + std::string lowerStr = rangeStr.substr(0, pos); + std::string upperStr = rangeStr.substr(pos + 1); + + lower = lowerStr.empty() ? -std::numeric_limits::max() : static_cast(std::stod(lowerStr)); + upper = upperStr.empty() ? std::numeric_limits::max() : static_cast(std::stod(upperStr)); + + if (lower >= upper) { + LOG(fatal) << "Range string '" << rangeStr << "' has lower bound >= upper bound"; + } + } + + std::string mSelectionName = ""; + std::vector mSelectionValues = {}; ///< Threshold values, sorted from most permissive to most restrictive + std::vector mSelectionFunctions = {}; ///< TF1 threshold functions (empty for static selections) + std::vector> mSelectionRanges = {}; ///< Lower and upper bounds for kRange selections, one pair per threshold + limits::LimitType mLimitType = limits::kLimitTypeLast; ///< Comparison type applied during evaluation + bool mSkipMostPermissiveBit = false; ///< If true, the most permissive threshold does not occupy a bit in the global bitmask + bool mIsMinimalCut = false; ///< If true, this selection is mandatory; failing it rejects the candidate + bool mIsOptionalCut = false; ///< If true, this selection is optional; passing it accepts the candidate + std::vector mComments = {}; ///< Optional comments per threshold, in the same order as mSelectionValues + std::bitset mBitmask = {}; ///< Bitmask indicating which thresholds were passed during the last evaluation + int mOffset = 0; ///< Bit offset of this container within the global bitmask }; } // namespace o2::analysis::femto diff --git a/PWGCF/Femto/Core/trackBuilder.h b/PWGCF/Femto/Core/trackBuilder.h index c33b5850468..ffb5df80c37 100644 --- a/PWGCF/Femto/Core/trackBuilder.h +++ b/PWGCF/Femto/Core/trackBuilder.h @@ -67,65 +67,65 @@ struct ConfTrackBits : o2::framework::ConfigurableGroup { // Electron PID cuts o2::framework::Configurable requirePidElectron{"requirePidElectron", false, "Make election PID optional"}; o2::framework::Configurable minMomTofElectron{"minMomTofElectron", 0.3, "Minimum momentum to required TOF PID for Electron"}; - o2::framework::Configurable> itsElectron{"itsElectron", {}, "Maximum |nsigma| for Electron PID"}; - o2::framework::Configurable> tpcElectron{"tpcElectron", {}, "Maximum |nsigma| for Electron PID"}; - o2::framework::Configurable> tofElectron{"tofElectron", {}, "Maximum |nsigma| for Electron PID"}; - o2::framework::Configurable> tpcitsElectron{"tpcitsElectron", {}, "Maximum |nsigma| for Electron PID"}; - o2::framework::Configurable> tpctofElectron{"tpctofElectron", {}, "Maximum |nsigma| for Electron PID"}; + o2::framework::Configurable> itsElectron{"itsElectron", {}, "Ranges LowerLimit;UpperLimit for nsigma_ITS for Electron PID"}; + o2::framework::Configurable> tpcElectron{"tpcElectron", {}, "Ranges LowerLimit;UpperLimit for nsigma_TPC for Electron PID"}; + o2::framework::Configurable> tofElectron{"tofElectron", {}, "Ranges LowerLimit;UpperLimit for nsigma_TOF for Electron PID"}; + o2::framework::Configurable> tpcitsElectron{"tpcitsElectron", {}, "Maximum nsigma_TPCITS for Electron PID"}; + o2::framework::Configurable> tpctofElectron{"tpctofElectron", {}, "Maximum nsigma_TPCTOF for Electron PID"}; // Pion PID cuts o2::framework::Configurable requirePidPion{"requirePidPion", false, "Make election PID optional"}; o2::framework::Configurable minMomTofPion{"minMomTofPion", 0.5, "Minimum momentum to required TOF PID for Pion"}; - o2::framework::Configurable> itsPion{"itsPion", {}, "Maximum |nsigma| for Pion PID"}; - o2::framework::Configurable> tpcPion{"tpcPion", {}, "Maximum |nsigma| for Pion PID"}; - o2::framework::Configurable> tofPion{"tofPion", {}, "Maximum |nsigma| for Pion PID"}; - o2::framework::Configurable> tpcitsPion{"tpcitsPion", {}, "Maximum |nsigma| for Pion PID"}; - o2::framework::Configurable> tpctofPion{"tpctofPion", {}, "Maximum |nsigma| for Pion PID"}; + o2::framework::Configurable> itsPion{"itsPion", {}, "Ranges LowerLimit;UpperLimit for nsigma_ITS for Pion PID"}; + o2::framework::Configurable> tpcPion{"tpcPion", {}, "Ranges LowerLimit;UpperLimit for nsigma_TPC for Pion PID"}; + o2::framework::Configurable> tofPion{"tofPion", {}, "Ranges LowerLimit;UpperLimit for nsigma_TOF for Pion PID"}; + o2::framework::Configurable> tpcitsPion{"tpcitsPion", {}, "Maximum nsigma_TPCITS for Pion PID"}; + o2::framework::Configurable> tpctofPion{"tpctofPion", {}, "Maximum nsigma_TPCTOF for Pion PID"}; // Kaon PID cuts o2::framework::Configurable requirePidKaon{"requirePidKaon", false, "Make election PID optional"}; o2::framework::Configurable minMomTofKaon{"minMomTofKaon", 0.4, "Minimum momentum to required TOF PID for Kaon"}; - o2::framework::Configurable> itsKaon{"itsKaon", {}, "Maximum |nsigma| for Kaon PID"}; - o2::framework::Configurable> tpcKaon{"tpcKaon", {}, "Maximum |nsigma| for Kaon PID"}; - o2::framework::Configurable> tofKaon{"tofKaon", {}, "Maximum |nsigma| for Kaon PID"}; - o2::framework::Configurable> tpcitsKaon{"tpcitsKaon", {}, "Maximum |nsigma| for Kaon PID"}; - o2::framework::Configurable> tpctofKaon{"tpctofKaon", {}, "Maximum |nsigma| for Kaon PID"}; + o2::framework::Configurable> itsKaon{"itsKaon", {}, "Ranges LowerLimit;UpperLimit for nsigma_ITS for Kaon PID"}; + o2::framework::Configurable> tpcKaon{"tpcKaon", {}, "Ranges LowerLimit;UpperLimit for nsigma_TPC for Kaon PID"}; + o2::framework::Configurable> tofKaon{"tofKaon", {}, "Ranges LowerLimit;UpperLimit for nsigma_TOF for Kaon PID"}; + o2::framework::Configurable> tpcitsKaon{"tpcitsKaon", {}, "Maximum nsigma_TPCITS for Kaon PID"}; + o2::framework::Configurable> tpctofKaon{"tpctofKaon", {}, "Maximum nsigma_TPCTOF for Kaon PID"}; // Proton PID cuts o2::framework::Configurable requirePidProton{"requirePidProton", true, "Make election PID optional"}; o2::framework::Configurable minMomTofProton{"minMomTofProton", 0.75, "Minimum momentum to required TOF PID for Proton"}; - o2::framework::Configurable> itsProton{"itsProton", {}, "Maximum |nsigma| for Proton PID"}; - o2::framework::Configurable> tpcProton{"tpcProton", {}, "Maximum |nsigma| for Proton PID"}; - o2::framework::Configurable> tofProton{"tofProton", {}, "Maximum |nsigma| for Proton PID"}; - o2::framework::Configurable> tpcitsProton{"tpcitsProton", {}, "Maximum |nsigma| for Proton PID"}; - o2::framework::Configurable> tpctofProton{"tpctofProton", {}, "Maximum |nsigma| for Proton PID"}; + o2::framework::Configurable> itsProton{"itsProton", {}, "Ranges LowerLimit;UpperLimit for nsigma_ITS for Proton PID"}; + o2::framework::Configurable> tpcProton{"tpcProton", {}, "Ranges LowerLimit;UpperLimit for nsigma_TPC for Proton PID"}; + o2::framework::Configurable> tofProton{"tofProton", {}, "Ranges LowerLimit;UpperLimit for nsigma_TOF for Proton PID"}; + o2::framework::Configurable> tpcitsProton{"tpcitsProton", {}, "Maximum nsigma_TPCITS for Proton PID"}; + o2::framework::Configurable> tpctofProton{"tpctofProton", {}, "Maximum nsigma_TPCTOF for Proton PID"}; // Deuteron PID cuts o2::framework::Configurable requirePidDeuteron{"requirePidDeuteron", false, "Make election PID optional"}; o2::framework::Configurable minMomTofDeuteron{"minMomTofDeuteron", 1.2, "Minimum momentum to required TOF PID for Deuteron"}; - o2::framework::Configurable> itsDeuteron{"itsDeuteron", {}, "Maximum |nsigma| for Deuteron PID"}; - o2::framework::Configurable> tpcDeuteron{"tpcDeuteron", {}, "Maximum |nsigma| for Deuteron PID"}; - o2::framework::Configurable> tofDeuteron{"tofDeuteron", {}, "Maximum |nsigma| for Deuteron PID"}; - o2::framework::Configurable> tpcitsDeuteron{"tpcitsDeuteron", {}, "Maximum |nsigma| for Deuteron PID"}; - o2::framework::Configurable> tpctofDeuteron{"tpctofDeuteron", {}, "Maximum |nsigma| for Deuteron PID"}; + o2::framework::Configurable> itsDeuteron{"itsDeuteron", {}, "Ranges LowerLimit;UpperLimit for nsigma_ITS for Deuteron PID"}; + o2::framework::Configurable> tpcDeuteron{"tpcDeuteron", {}, "Ranges LowerLimit;UpperLimit for nsigma_TPC for Deuteron PID"}; + o2::framework::Configurable> tofDeuteron{"tofDeuteron", {}, "Ranges LowerLimit;UpperLimit for nsigma_TOF for Deuteron PID"}; + o2::framework::Configurable> tpcitsDeuteron{"tpcitsDeuteron", {}, "Maximum nsigma_TPCITS for Deuteron PID"}; + o2::framework::Configurable> tpctofDeuteron{"tpctofDeuteron", {}, "Maximum nsigma_TPCTOF for Deuteron PID"}; // Triton PID cuts o2::framework::Configurable requirePidTriton{"requirePidTriton", false, "Make election PID optional"}; o2::framework::Configurable minMomTofTriton{"minMomTofTriton", 1.4, "Minimum momentum to required TOF PID for Triton"}; - o2::framework::Configurable> itsTriton{"itsTriton", {}, "Maximum |nsigma| for Triton PID"}; - o2::framework::Configurable> tpcTriton{"tpcTriton", {}, "Maximum |nsigma| for Triton PID"}; - o2::framework::Configurable> tofTriton{"tofTriton", {}, "Maximum |nsigma| for Triton PID"}; - o2::framework::Configurable> tpcitsTriton{"tpcitsTriton", {}, "Maximum |nsigma| for Triton PID"}; - o2::framework::Configurable> tpctofTriton{"tpctofTriton", {}, "Maximum |nsigma| for Triton PID"}; + o2::framework::Configurable> itsTriton{"itsTriton", {}, "Ranges LowerLimit;UpperLimit for nsigma_ITS for Triton PID"}; + o2::framework::Configurable> tpcTriton{"tpcTriton", {}, "Ranges LowerLimit;UpperLimit for nsigma_TPC for Triton PID"}; + o2::framework::Configurable> tofTriton{"tofTriton", {}, "Ranges LowerLimit;UpperLimit for nsigma_TOF for Triton PID"}; + o2::framework::Configurable> tpcitsTriton{"tpcitsTriton", {}, "Maximum nsigma_TPCITS for Triton PID"}; + o2::framework::Configurable> tpctofTriton{"tpctofTriton", {}, "Maximum nsigma_TPCTOF for Triton PID"}; // Helium PID cuts o2::framework::Configurable requirePidHelium{"requirePidHelium", false, "Make election PID optional"}; o2::framework::Configurable minMomTofHelium{"minMomTofHelium", 1.6, "Minimum momentum to required TOF PID for Helium"}; - o2::framework::Configurable> itsHelium{"itsHelium", {}, "Maximum |nsigma| for Helium PID"}; - o2::framework::Configurable> tpcHelium{"tpcHelium", {}, "Maximum |nsigma| for Helium PID"}; - o2::framework::Configurable> tofHelium{"tofHelium", {}, "Maximum |nsigma| for Helium PID"}; - o2::framework::Configurable> tpcitsHelium{"tpcitsHelium", {}, "Maximum |nsigma| for Helium PID"}; - o2::framework::Configurable> tpctofHelium{"tpctofHelium", {}, "Maximum |nsigma| for Helium PID"}; + o2::framework::Configurable> itsHelium{"itsHelium", {}, "Ranges LowerLimit;UpperLimit for nsigma_ITS for Helium PID"}; + o2::framework::Configurable> tpcHelium{"tpcHelium", {}, "Ranges LowerLimit;UpperLimit for nsigma_TPC for Helium PID"}; + o2::framework::Configurable> tofHelium{"tofHelium", {}, "Ranges LowerLimit;UpperLimit for nsigma_TOF for Helium PID"}; + o2::framework::Configurable> tpcitsHelium{"tpcitsHelium", {}, "Maximum nsigma_TPCITS for Helium PID"}; + o2::framework::Configurable> tpctofHelium{"tpctofHelium", {}, "Maximum nsigma_TPCTOF for Helium PID"}; }; // define the template structure for TrackSelection @@ -144,8 +144,11 @@ struct ConfTrackSelection : public o2::framework::ConfigurableGroup { o2::framework::Configurable phiMin{"phiMin", 0.f, "Minimum phi"}; o2::framework::Configurable phiMax{"phiMax", 1.f * o2::constants::math::TwoPI, "Maximum phi"}; // track selection masks - o2::framework::Configurable maskLowMomentum{"maskLowMomentum", 0x2u, "Bitmask for selections below momentum threshold"}; - o2::framework::Configurable maskHighMomentum{"maskHighMomentum", 0x1u, "Bitmask for selections above momentum threshold"}; + o2::framework::Configurable maskLowMomentum{"maskLowMomentum", 1ul, "Bitmask for selections below momentum threshold"}; + o2::framework::Configurable maskHighMomentum{"maskHighMomentum", 2ul, "Bitmask for selections above momentum threshold"}; + // track rejection masks + o2::framework::Configurable rejectionMaskLowMomentum{"rejectionMaskLowMomentum", 0ul, "Bitmask for rejections below momentum threshold"}; + o2::framework::Configurable rejectionMaskHighMomentum{"rejectionMaskHighMomentum", 0ul, "Bitmask for rejections above momentum threshold"}; // momentum threshold for PID usage o2::framework::Configurable pidThres{"pidThres", 1.2f, "Momentum threshold for using TPCTOF/TOF pid for tracks with large momentum (GeV/c)"}; }; @@ -283,12 +286,12 @@ class TrackSelection : public BaseSelection void configure(o2::framework::HistogramRegistry* registry, T1& config, T2& filter) { - mPtMin = filter.ptMin; - mPtMax = filter.ptMax; - mEtaMin = filter.etaMin; - mEtaMax = filter.etaMax; - mPhiMin = filter.phiMin; - mPhiMax = filter.phiMax; + mPtMin = filter.ptMin.value; + mPtMax = filter.ptMax.value; + mEtaMin = filter.etaMin.value; + mEtaMax = filter.etaMax.value; + mPhiMin = filter.phiMin.value; + mPhiMax = filter.phiMax.value; // add selections for track quality this->addSelection(kTPCnClsMin, trackSelectionNames.at(kTPCnClsMin), config.tpcClustersMin.value, limits::kLowerLimit, true, true, false); @@ -298,61 +301,61 @@ class TrackSelection : public BaseSelectionaddSelection(kTPCsClsFracMax, trackSelectionNames.at(kTPCsClsFracMax), config.tpcSharedClusterFractionMax.value, limits::kUpperLimit, true, true, false); this->addSelection(kITSnClsMin, trackSelectionNames.at(kITSnClsMin), config.itsClustersMin.value, limits::kLowerLimit, true, true, false); this->addSelection(kITSnClsIbMin, trackSelectionNames.at(kITSnClsIbMin), config.itsIbClustersMin.value, limits::kLowerLimit, true, true, false); - this->addSelection(kDCAxyMax, trackSelectionNames.at(kDCAxyMax), filter.ptMin, filter.ptMax.value, config.dcaxyMax.value, limits::kAbsUpperFunctionLimit, true, true, false); + this->addSelection(kDCAxyMax, trackSelectionNames.at(kDCAxyMax), filter.ptMin.value, filter.ptMax.value, config.dcaxyMax.value, limits::kAbsUpperFunctionLimit, true, true, false); this->addSelection(kDCAzMax, trackSelectionNames.at(kDCAzMax), filter.ptMin.value, filter.ptMax.value, config.dcazMax.value, limits::kAbsUpperFunctionLimit, true, true, false); // add selections for Electron pid - this->addSelection(kItsElectron, trackSelectionNames.at(kItsElectron), config.itsElectron.value, limits::kAbsUpperLimit, false, false, config.requirePidElectron); - this->addSelection(kTpcElectron, trackSelectionNames.at(kTpcElectron), config.tpcElectron.value, limits::kAbsUpperLimit, false, false, config.requirePidElectron); - this->addSelection(kTofElectron, trackSelectionNames.at(kTofElectron), config.tofElectron.value, limits::kAbsUpperLimit, false, false, config.requirePidElectron); + this->addSelection(kItsElectron, trackSelectionNames.at(kItsElectron), config.itsElectron.value, false, false, config.requirePidElectron); + this->addSelection(kTpcElectron, trackSelectionNames.at(kTpcElectron), config.tpcElectron.value, false, false, config.requirePidElectron); + this->addSelection(kTofElectron, trackSelectionNames.at(kTofElectron), config.tofElectron.value, false, false, config.requirePidElectron); this->addSelection(kTpcitsElectron, trackSelectionNames.at(kTpcitsElectron), config.tpcitsElectron.value, limits::kUpperLimit, false, false, config.requirePidElectron); this->addSelection(kTpctofElectron, trackSelectionNames.at(kTpctofElectron), config.tpctofElectron.value, limits::kUpperLimit, false, false, config.requirePidElectron); mElectronTofThres = config.minMomTofElectron.value; // add selections for Pion pid - this->addSelection(kItsPion, trackSelectionNames.at(kItsPion), config.itsPion.value, limits::kAbsUpperLimit, false, false, config.requirePidPion); - this->addSelection(kTpcPion, trackSelectionNames.at(kTpcPion), config.tpcPion.value, limits::kAbsUpperLimit, false, false, config.requirePidPion); - this->addSelection(kTofPion, trackSelectionNames.at(kTofPion), config.tofPion.value, limits::kAbsUpperLimit, false, false, config.requirePidPion); + this->addSelection(kItsPion, trackSelectionNames.at(kItsPion), config.itsPion.value, false, false, config.requirePidPion); + this->addSelection(kTpcPion, trackSelectionNames.at(kTpcPion), config.tpcPion.value, false, false, config.requirePidPion); + this->addSelection(kTofPion, trackSelectionNames.at(kTofPion), config.tofPion.value, false, false, config.requirePidPion); this->addSelection(kTpcitsPion, trackSelectionNames.at(kTpcitsPion), config.tpcitsPion.value, limits::kUpperLimit, false, false, config.requirePidPion); this->addSelection(kTpctofPion, trackSelectionNames.at(kTpctofPion), config.tpctofPion.value, limits::kUpperLimit, false, false, config.requirePidPion); mPionTofThres = config.minMomTofPion.value; // add selections for Kaon pid - this->addSelection(kItsKaon, trackSelectionNames.at(kItsKaon), config.itsKaon.value, limits::kAbsUpperLimit, false, false, config.requirePidKaon); - this->addSelection(kTpcKaon, trackSelectionNames.at(kTpcKaon), config.tpcKaon.value, limits::kAbsUpperLimit, false, false, config.requirePidKaon); - this->addSelection(kTofKaon, trackSelectionNames.at(kTofKaon), config.tofKaon.value, limits::kAbsUpperLimit, false, false, config.requirePidKaon); + this->addSelection(kItsKaon, trackSelectionNames.at(kItsKaon), config.itsKaon.value, false, false, config.requirePidKaon); + this->addSelection(kTpcKaon, trackSelectionNames.at(kTpcKaon), config.tpcKaon.value, false, false, config.requirePidKaon); + this->addSelection(kTofKaon, trackSelectionNames.at(kTofKaon), config.tofKaon.value, false, false, config.requirePidKaon); this->addSelection(kTpcitsKaon, trackSelectionNames.at(kTpcitsKaon), config.tpcitsKaon.value, limits::kUpperLimit, false, false, config.requirePidKaon); this->addSelection(kTpctofKaon, trackSelectionNames.at(kTpctofKaon), config.tpctofKaon.value, limits::kUpperLimit, false, false, config.requirePidKaon); mKaonTofThres = config.minMomTofKaon.value; // add selections for Proton pid - this->addSelection(kItsProton, trackSelectionNames.at(kItsProton), config.itsProton.value, limits::kAbsUpperLimit, false, false, config.requirePidProton); - this->addSelection(kTpcProton, trackSelectionNames.at(kTpcProton), config.tpcProton.value, limits::kAbsUpperLimit, false, false, config.requirePidProton); - this->addSelection(kTofProton, trackSelectionNames.at(kTofProton), config.tofProton.value, limits::kAbsUpperLimit, false, false, config.requirePidProton); + this->addSelection(kItsProton, trackSelectionNames.at(kItsProton), config.itsProton.value, false, false, config.requirePidProton); + this->addSelection(kTpcProton, trackSelectionNames.at(kTpcProton), config.tpcProton.value, false, false, config.requirePidProton); + this->addSelection(kTofProton, trackSelectionNames.at(kTofProton), config.tofProton.value, false, false, config.requirePidProton); this->addSelection(kTpcitsProton, trackSelectionNames.at(kTpcitsProton), config.tpcitsProton.value, limits::kUpperLimit, false, false, config.requirePidProton); this->addSelection(kTpctofProton, trackSelectionNames.at(kTpctofProton), config.tpctofProton.value, limits::kUpperLimit, false, false, config.requirePidProton); mProtonTofThres = config.minMomTofProton.value; // add selections for Deuteron pid - this->addSelection(kItsDeuteron, trackSelectionNames.at(kItsDeuteron), config.itsDeuteron.value, limits::kAbsUpperLimit, false, false, config.requirePidDeuteron); - this->addSelection(kTpcDeuteron, trackSelectionNames.at(kTpcDeuteron), config.tpcDeuteron.value, limits::kAbsUpperLimit, false, false, config.requirePidDeuteron); - this->addSelection(kTofDeuteron, trackSelectionNames.at(kTofDeuteron), config.tofDeuteron.value, limits::kAbsUpperLimit, false, false, config.requirePidDeuteron); + this->addSelection(kItsDeuteron, trackSelectionNames.at(kItsDeuteron), config.itsDeuteron.value, false, false, config.requirePidDeuteron); + this->addSelection(kTpcDeuteron, trackSelectionNames.at(kTpcDeuteron), config.tpcDeuteron.value, false, false, config.requirePidDeuteron); + this->addSelection(kTofDeuteron, trackSelectionNames.at(kTofDeuteron), config.tofDeuteron.value, false, false, config.requirePidDeuteron); this->addSelection(kTpcitsDeuteron, trackSelectionNames.at(kTpcitsDeuteron), config.tpcitsDeuteron.value, limits::kUpperLimit, false, false, config.requirePidDeuteron); this->addSelection(kTpctofDeuteron, trackSelectionNames.at(kTpctofDeuteron), config.tpctofDeuteron.value, limits::kUpperLimit, false, false, config.requirePidDeuteron); mDeuteronTofThres = config.minMomTofDeuteron.value; // add selections for Triton pid - this->addSelection(kItsTriton, trackSelectionNames.at(kItsTriton), config.itsTriton.value, limits::kAbsUpperLimit, false, false, config.requirePidTriton); - this->addSelection(kTpcTriton, trackSelectionNames.at(kTpcTriton), config.tpcTriton.value, limits::kAbsUpperLimit, false, false, config.requirePidTriton); - this->addSelection(kTofTriton, trackSelectionNames.at(kTofTriton), config.tofTriton.value, limits::kAbsUpperLimit, false, false, config.requirePidTriton); + this->addSelection(kItsTriton, trackSelectionNames.at(kItsTriton), config.itsTriton.value, false, false, config.requirePidTriton); + this->addSelection(kTpcTriton, trackSelectionNames.at(kTpcTriton), config.tpcTriton.value, false, false, config.requirePidTriton); + this->addSelection(kTofTriton, trackSelectionNames.at(kTofTriton), config.tofTriton.value, false, false, config.requirePidTriton); this->addSelection(kTpcitsTriton, trackSelectionNames.at(kTpcitsTriton), config.tpcitsTriton.value, limits::kUpperLimit, false, false, config.requirePidTriton); this->addSelection(kTpctofTriton, trackSelectionNames.at(kTpctofTriton), config.tpctofTriton.value, limits::kUpperLimit, false, false, config.requirePidTriton); mTritonTofThres = config.minMomTofTriton.value; // add selections for Helium pid - this->addSelection(kItsHelium, trackSelectionNames.at(kItsHelium), config.itsHelium.value, limits::kAbsUpperLimit, false, false, config.requirePidHelium); - this->addSelection(kTpcHelium, trackSelectionNames.at(kTpcHelium), config.tpcHelium.value, limits::kAbsUpperLimit, false, false, config.requirePidHelium); - this->addSelection(kTofHelium, trackSelectionNames.at(kTofHelium), config.tofHelium.value, limits::kAbsUpperLimit, false, false, config.requirePidHelium); + this->addSelection(kItsHelium, trackSelectionNames.at(kItsHelium), config.itsHelium.value, false, false, config.requirePidHelium); + this->addSelection(kTpcHelium, trackSelectionNames.at(kTpcHelium), config.tpcHelium.value, false, false, config.requirePidHelium); + this->addSelection(kTofHelium, trackSelectionNames.at(kTofHelium), config.tofHelium.value, false, false, config.requirePidHelium); this->addSelection(kTpcitsHelium, trackSelectionNames.at(kTpcitsHelium), config.tpcitsHelium.value, limits::kUpperLimit, false, false, config.requirePidHelium); this->addSelection(kTpctofHelium, trackSelectionNames.at(kTpctofHelium), config.tpctofHelium.value, limits::kUpperLimit, false, false, config.requirePidHelium); mHeliumTofThres = config.minMomTofHelium.value; @@ -378,30 +381,20 @@ class TrackSelection : public BaseSelectionevaluateObservable(its, nsigmaIts); - this->evaluateObservable(tpc, nsigmaTpc); - this->evaluateObservable(tpcits, std::hypot(nsigmaTpc, nsigmaIts)); - this->evaluateObservable(tof, nsigmaTof); - this->evaluateObservable(tpctof, std::hypot(nsigmaTpc, nsigmaTof)); + // above threshold without TOF: skip entirely unless forced + // forced evaluation is used in the second pass to populate rejection bits + if (!ignoreThreshold && Track.p() >= tofThreshold && !Track.hasTOF()) { return; } - // if track is above threshold, check if TOF PID is available - // if not, we dont check any selection and they stay at reseted values, i.e. the cut fails + this->evaluateObservable(its, nsigmaIts); + this->evaluateObservable(tpc, nsigmaTpc); + this->evaluateObservable(tpcits, std::hypot(nsigmaTpc, nsigmaIts)); if (Track.hasTOF()) { - // if tof inforamtion is available, check them first this->evaluateObservable(tof, nsigmaTof); this->evaluateObservable(tpctof, std::hypot(nsigmaTpc, nsigmaTof)); - // if both failed, the bitmask will be 0 and there is no need to check tpc and its information since we do not want to have this track - // so if we just bail out here, the PID for this particle type will failed for its, tpc and tof - if (this->passesOptionalSelection(tof) || this->passesOptionalSelection(tpctof)) { - this->evaluateObservable(its, nsigmaIts); - this->evaluateObservable(tpc, nsigmaTpc); - this->evaluateObservable(tpcits, std::hypot(nsigmaTpc, nsigmaIts)); - } } } @@ -416,90 +409,34 @@ class TrackSelection : public BaseSelectionevaluateObservable(kTPCsClsFracMax, static_cast(Track.tpcNClsShared()) / static_cast(Track.tpcNClsFound())); this->evaluateObservable(kITSnClsMin, Track.itsNCls()); this->evaluateObservable(kITSnClsIbMin, Track.itsNClsInnerBarrel()); - - // evalue bitmask for pt dependent dca cuts this->updateLimits(kDCAxyMax, Track.pt()); this->evaluateObservable(kDCAxyMax, Track.dcaXY()); - this->updateLimits(kDCAzMax, Track.pt()); this->evaluateObservable(kDCAzMax, Track.dcaZ()); - this->evaluatePid(Track, - mElectronTofThres, - Track.itsNSigmaEl(), - Track.tpcNSigmaEl(), - Track.tofNSigmaEl(), - kItsElectron, - kTpcElectron, - kTofElectron, - kTpcitsElectron, - kTpctofElectron); - - this->evaluatePid(Track, - mPionTofThres, - Track.itsNSigmaPi(), - Track.tpcNSigmaPi(), - Track.tofNSigmaPi(), - kItsPion, - kTpcPion, - kTofPion, - kTpcitsPion, - kTpctofPion); - - this->evaluatePid(Track, - mKaonTofThres, - Track.itsNSigmaKa(), - Track.tpcNSigmaKa(), - Track.tofNSigmaKa(), - kItsKaon, - kTpcKaon, - kTofKaon, - kTpcitsKaon, - kTpctofKaon); - - this->evaluatePid(Track, - mProtonTofThres, - Track.itsNSigmaPr(), - Track.tpcNSigmaPr(), - Track.tofNSigmaPr(), - kItsProton, - kTpcProton, - kTofProton, - kTpcitsProton, - kTpctofProton); - - this->evaluatePid(Track, - mDeuteronTofThres, - Track.itsNSigmaDe(), - Track.tpcNSigmaDe(), - Track.tofNSigmaDe(), - kItsDeuteron, - kTpcDeuteron, - kTofDeuteron, - kTpcitsDeuteron, - kTpctofDeuteron); - - this->evaluatePid(Track, - mTritonTofThres, - Track.itsNSigmaTr(), - Track.tpcNSigmaTr(), - Track.tofNSigmaTr(), - kItsTriton, - kTpcTriton, - kTofTriton, - kTpcitsTriton, - kTpctofTriton); - - this->evaluatePid(Track, - mHeliumTofThres, - Track.itsNSigmaHe(), - Track.tpcNSigmaHe(), - Track.tofNSigmaHe(), - kItsHelium, - kTpcHelium, - kTofHelium, - kTpcitsHelium, - kTpctofHelium); + // first pass: threshold-aware PID evaluation + // determines if the track passes any optional selection and should be stored + this->evaluatePid(Track, mElectronTofThres, Track.itsNSigmaEl(), Track.tpcNSigmaEl(), Track.tofNSigmaEl(), kItsElectron, kTpcElectron, kTofElectron, kTpcitsElectron, kTpctofElectron); + this->evaluatePid(Track, mPionTofThres, Track.itsNSigmaPi(), Track.tpcNSigmaPi(), Track.tofNSigmaPi(), kItsPion, kTpcPion, kTofPion, kTpcitsPion, kTpctofPion); + this->evaluatePid(Track, mKaonTofThres, Track.itsNSigmaKa(), Track.tpcNSigmaKa(), Track.tofNSigmaKa(), kItsKaon, kTpcKaon, kTofKaon, kTpcitsKaon, kTpctofKaon); + this->evaluatePid(Track, mProtonTofThres, Track.itsNSigmaPr(), Track.tpcNSigmaPr(), Track.tofNSigmaPr(), kItsProton, kTpcProton, kTofProton, kTpcitsProton, kTpctofProton); + this->evaluatePid(Track, mDeuteronTofThres, Track.itsNSigmaDe(), Track.tpcNSigmaDe(), Track.tofNSigmaDe(), kItsDeuteron, kTpcDeuteron, kTofDeuteron, kTpcitsDeuteron, kTpctofDeuteron); + this->evaluatePid(Track, mTritonTofThres, Track.itsNSigmaTr(), Track.tpcNSigmaTr(), Track.tofNSigmaTr(), kItsTriton, kTpcTriton, kTofTriton, kTpcitsTriton, kTpctofTriton); + this->evaluatePid(Track, mHeliumTofThres, Track.itsNSigmaHe(), Track.tpcNSigmaHe(), Track.tofNSigmaHe(), kItsHelium, kTpcHelium, kTofHelium, kTpcitsHelium, kTpctofHelium); + + // second pass: if the track passes minimal and any optional selection, + // re-evaluate all species ignoring thresholds so rejection bits are fully + // populated for all competing hypotheses. evaluate() resets each container + // before writing, so no explicit reset is needed before this pass. + if (this->passesAllRequiredSelections()) { + this->evaluatePid(Track, mElectronTofThres, Track.itsNSigmaEl(), Track.tpcNSigmaEl(), Track.tofNSigmaEl(), kItsElectron, kTpcElectron, kTofElectron, kTpcitsElectron, kTpctofElectron, true); + this->evaluatePid(Track, mPionTofThres, Track.itsNSigmaPi(), Track.tpcNSigmaPi(), Track.tofNSigmaPi(), kItsPion, kTpcPion, kTofPion, kTpcitsPion, kTpctofPion, true); + this->evaluatePid(Track, mKaonTofThres, Track.itsNSigmaKa(), Track.tpcNSigmaKa(), Track.tofNSigmaKa(), kItsKaon, kTpcKaon, kTofKaon, kTpcitsKaon, kTpctofKaon, true); + this->evaluatePid(Track, mProtonTofThres, Track.itsNSigmaPr(), Track.tpcNSigmaPr(), Track.tofNSigmaPr(), kItsProton, kTpcProton, kTofProton, kTpcitsProton, kTpctofProton, true); + this->evaluatePid(Track, mDeuteronTofThres, Track.itsNSigmaDe(), Track.tpcNSigmaDe(), Track.tofNSigmaDe(), kItsDeuteron, kTpcDeuteron, kTofDeuteron, kTpcitsDeuteron, kTpctofDeuteron, true); + this->evaluatePid(Track, mTritonTofThres, Track.itsNSigmaTr(), Track.tpcNSigmaTr(), Track.tofNSigmaTr(), kItsTriton, kTpcTriton, kTofTriton, kTpcitsTriton, kTpctofTriton, true); + this->evaluatePid(Track, mHeliumTofThres, Track.itsNSigmaHe(), Track.tpcNSigmaHe(), Track.tofNSigmaHe(), kItsHelium, kTpcHelium, kTofHelium, kTpcitsHelium, kTpctofHelium, true); + } this->assembleBitmask(); } From a7d3a89f20d2299727d30ad78a26e4a5091c20b0 Mon Sep 17 00:00:00 2001 From: altsybee Date: Wed, 4 Mar 2026 06:08:30 +0100 Subject: [PATCH 155/347] [Common] remove ROF border cut from sel8 for 2026 runs (#15237) --- Common/Tools/EventSelectionModule.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Common/Tools/EventSelectionModule.h b/Common/Tools/EventSelectionModule.h index 344ad7578da..f808b70fb85 100644 --- a/Common/Tools/EventSelectionModule.h +++ b/Common/Tools/EventSelectionModule.h @@ -1514,10 +1514,14 @@ class EventSelectionModule // apply int7-like selections bool sel7 = 0; - // TODO apply other cuts for sel8 - // TODO introduce sel1 etc? + // Combination of bits for Run 3 event selection decisions + // TODO apply other cuts for sel8? // TODO introduce array of sel[0]... sel[8] or similar? - bool sel8 = bitcheck64(bcselEntry.selection, aod::evsel::kIsTriggerTVX) && bitcheck64(bcselEntry.selection, aod::evsel::kNoTimeFrameBorder) && bitcheck64(bcselEntry.selection, aod::evsel::kNoITSROFrameBorder); + bool sel8 = false; + if (lastRun < 568873) // pre-2026 data & MC: require all three bits: TVX, TF and ROF border cuts + sel8 = bitcheck64(bcselEntry.selection, aod::evsel::kIsTriggerTVX) && bitcheck64(bcselEntry.selection, aod::evsel::kNoTimeFrameBorder) && bitcheck64(bcselEntry.selection, aod::evsel::kNoITSROFrameBorder); + else // for pp 2026: sel8 without kNoITSROFrameBorder bit, because the cross-ROF reconstruction for ITS will be On (the switch by a runNumber is a temporary solution) + sel8 = bitcheck64(bcselEntry.selection, aod::evsel::kIsTriggerTVX) && bitcheck64(bcselEntry.selection, aod::evsel::kNoTimeFrameBorder); // fill counters histos.template get(HIST("eventselection/hColCounterAll"))->Fill(Form("%d", bc.runNumber()), 1); From 1b9756bc3cc78ad8d409ad4669a4cfadd09cb40d Mon Sep 17 00:00:00 2001 From: Paola Vargas Torres <88360333+PaolaVT@users.noreply.github.com> Date: Wed, 4 Mar 2026 02:47:27 -0600 Subject: [PATCH 156/347] [PWGLF] Correct logical condition in DCA to PV cuts (#15232) Co-authored-by: Paola Vargas Torres --- PWGLF/Tasks/Nuspex/dedxPidAnalysis.cxx | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/PWGLF/Tasks/Nuspex/dedxPidAnalysis.cxx b/PWGLF/Tasks/Nuspex/dedxPidAnalysis.cxx index a8ff711af76..0966ad1a97d 100644 --- a/PWGLF/Tasks/Nuspex/dedxPidAnalysis.cxx +++ b/PWGLF/Tasks/Nuspex/dedxPidAnalysis.cxx @@ -797,7 +797,9 @@ struct DedxPidAnalysis { if (fillHist) registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::V0TypeK0s); - if (std::fabs(v0.dcapostopv()) < dcaPionsFromK0s && std::fabs(v0.dcanegtopv()) < dcaPionsFromK0s) // DCA selection + if (std::fabs(v0.dcapostopv()) < dcaPionsFromK0s) // DCA selection + return false; + if (std::fabs(v0.dcanegtopv()) < dcaPionsFromK0s) // DCA selection return false; if (fillHist) registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::DCAtoVtxK0s); @@ -876,7 +878,9 @@ struct DedxPidAnalysis { if (fillHist) registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::V0TypeLambda); - if (std::fabs(v0.dcapostopv()) < dcaProtonsFromLambda && std::fabs(v0.dcanegtopv()) < dcaPionsFromLambda) // DCA selection + if (std::fabs(v0.dcapostopv()) < dcaProtonsFromLambda) // DCA selection + return false; + if (std::fabs(v0.dcanegtopv()) < dcaPionsFromLambda) // DCA selection return false; if (fillHist) registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::DCAtoVtxLambda); @@ -949,7 +953,9 @@ struct DedxPidAnalysis { if (fillHist) registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::V0TypeAntiLambda); - if (std::fabs(v0.dcapostopv()) < dcaPionsFromLambda && std::fabs(v0.dcanegtopv()) < dcaProtonsFromLambda) // DCA selection + if (std::fabs(v0.dcapostopv()) < dcaPionsFromLambda) // DCA selection + return false; + if (std::fabs(v0.dcanegtopv()) < dcaProtonsFromLambda) // DCA selection return false; if (fillHist) registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::DCAtoVtxAntiLambda); From 26bf1378922fcea7c90e2a460ec1524ed7d84244 Mon Sep 17 00:00:00 2001 From: dyx-11 <1260971129@qq.com> Date: Wed, 4 Mar 2026 17:37:24 +0800 Subject: [PATCH 157/347] [PWGUD] filter Nch (#15250) --- PWGUD/Tasks/flowCorrelationsUpc.cxx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/PWGUD/Tasks/flowCorrelationsUpc.cxx b/PWGUD/Tasks/flowCorrelationsUpc.cxx index 30d3bdd60aa..fd64d11702a 100644 --- a/PWGUD/Tasks/flowCorrelationsUpc.cxx +++ b/PWGUD/Tasks/flowCorrelationsUpc.cxx @@ -161,7 +161,7 @@ struct FlowCorrelationsUpc { // make the filters and cuts. Filter trackFilter = (aod::udtrack::isPVContributor == true); - Filter collisionFilter = (((cfgGapSideMerge == true && (aod::udcollision::gapSide == (uint8_t)1 || aod::udcollision::gapSide == (uint8_t)0)) || aod::udcollision::gapSide == (uint8_t)cfgGapSide) && (cfgIfVertex == false || aod::collision::posZ < cfgZVtxCut) && (aod::udcollision::occupancyInTime > 0 && aod::udcollision::occupancyInTime < cfgCutOccupancyHigh) && ((cfgGapSideMerge == true && (aod::flowcorrupc::truegapside == 0 || aod::flowcorrupc::truegapside == 1)) || aod::flowcorrupc::truegapside == cfgGapSide)); + Filter collisionFilter = (((cfgGapSideMerge == true && (aod::udcollision::gapSide == (uint8_t)1 || aod::udcollision::gapSide == (uint8_t)0)) || aod::udcollision::gapSide == (uint8_t)cfgGapSide) && (cfgIfVertex == false || aod::collision::posZ < cfgZVtxCut) && (aod::udcollision::occupancyInTime > 0 && aod::udcollision::occupancyInTime < cfgCutOccupancyHigh) && ((cfgGapSideMerge == true && (aod::flowcorrupc::truegapside == 0 || aod::flowcorrupc::truegapside == 1)) || aod::flowcorrupc::truegapside == cfgGapSide) && (aod::flowcorrupc::multiplicity > cfgMinMult) && (aod::flowcorrupc::multiplicity < cfgMaxMult)); // Filter collisionFilter = (nabs(aod::collision::posZ) < cfgZVtxCut) && (aod::flowcorrupc::multiplicity) > cfgMinMult && (aod::flowcorrupc::multiplicity) < cfgMaxMult && (aod::evsel::sel8) == true; // Filter trackFilter = (nabs(aod::track::eta) < cfgEtaCut) && (aod::track::pt > cfgPtCutMin) && (aod::track::pt < cfgPtCutMax) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)); @@ -352,9 +352,9 @@ struct FlowCorrelationsUpc { void processSame(UDCollisionsFull::iterator const& collision, UdTracksFull const& tracks) { - if (tracks.size() < cfgMinMult || tracks.size() > cfgMaxMult) { - return; - } + // if (tracks.size() < cfgMinMult || tracks.size() > cfgMaxMult) { + // return; + // } // if (cfgIsGoodItsLayers && collision.trs() == 0) { // return; // } @@ -409,9 +409,9 @@ struct FlowCorrelationsUpc { for (auto const& [collision1, tracks1, collision2, tracks2] : pairs) { registry.fill(HIST("eventcount"), MixedEvent); // fill the mixed event in the 3 bin - if (tracks1.size() < cfgMinMult || tracks1.size() > cfgMaxMult || tracks2.size() < cfgMinMult || tracks2.size() > cfgMaxMult) { - continue; - } + // if (tracks1.size() < cfgMinMult || tracks1.size() > cfgMaxMult || tracks2.size() < cfgMinMult || tracks2.size() > cfgMaxMult) { + // continue; + // } // registry.fill(HIST("eventcount"), 4.5); // if (cfgIsGoodItsLayers && (collision1.trs() == 0 || collision2.trs() == 0)) { // continue; From 1b68ee6530a8c91096553d8c9793f88687bfca70 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Wed, 4 Mar 2026 13:04:33 +0100 Subject: [PATCH 158/347] [Trigger] Boost::system does not exist any more in new boost versions (#15249) --- EventFiltering/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EventFiltering/CMakeLists.txt b/EventFiltering/CMakeLists.txt index b8f6e14a9d8..8d5bf4622dc 100644 --- a/EventFiltering/CMakeLists.txt +++ b/EventFiltering/CMakeLists.txt @@ -69,7 +69,7 @@ o2physics_add_dpl_workflow(je-hf-filter o2physics_add_dpl_workflow(fje-filter SOURCES PWGJE/fullJetFilter.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::PWGJECore FastJet::FastJet FastJet::Contrib Boost::system + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::PWGJECore FastJet::FastJet FastJet::Contrib COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(lf-strangeness-filter From 151de2b37572b6dfd549d685ce7bd53d83093f1d Mon Sep 17 00:00:00 2001 From: aferrero2707 Date: Wed, 4 Mar 2026 13:50:33 +0100 Subject: [PATCH 159/347] [PWGDQ] matchingQA: added match attempts analysis (#15235) --- PWGDQ/Tasks/qaMatching.cxx | 78 +++++++++++++++++++++++++++++++++----- 1 file changed, 69 insertions(+), 9 deletions(-) diff --git a/PWGDQ/Tasks/qaMatching.cxx b/PWGDQ/Tasks/qaMatching.cxx index fadcd6eb6fb..c4e88a46d2b 100644 --- a/PWGDQ/Tasks/qaMatching.cxx +++ b/PWGDQ/Tasks/qaMatching.cxx @@ -95,6 +95,7 @@ struct qaMatching { double matchScoreProd{-1}; double matchChi2Prod{-1}; int matchRankingProd{-1}; + int mftMchMatchAttempts{0}; MuonMatchType matchType{kMatchTypeUndefined}; }; @@ -442,6 +443,7 @@ struct qaMatching { o2::framework::HistPtr histVsPt; o2::framework::HistPtr histVsMcParticleDz; o2::framework::HistPtr histVsMftTrackMult; + o2::framework::HistPtr histVsMatchAttempts; o2::framework::HistPtr histVsMftTrackType; o2::framework::HistPtr histVsDeltaChi2; o2::framework::HistPtr histVsProdRanking; @@ -450,8 +452,9 @@ struct qaMatching { { AxisSpec pAxis = {100, 0, 100, "p (GeV/c)"}; AxisSpec ptAxis = {100, 0, 10, "p_{T} (GeV/c)"}; - AxisSpec dzAxis = {100, 0, 50, "#Deltaz (cm)"}; + AxisSpec dzAxis = {100, -1, 4, "#Deltaz (cm)"}; AxisSpec trackMultAxis = {static_cast(mftMultMax) / 10, 0, static_cast(mftMultMax), "MFT track mult."}; + AxisSpec matchAttemptsAxis = {static_cast(mftMultMax) / 10, 0, static_cast(mftMultMax), "match attempts"}; AxisSpec trackTypeAxis = {2, 0, 2, "MFT track type"}; int matchTypeMax = static_cast(kMatchTypeUndefined); AxisSpec matchTypeAxis = {matchTypeMax, 0, static_cast(matchTypeMax), "match type"}; @@ -465,6 +468,7 @@ struct qaMatching { histVsPt = registry->add((histName + "VsPt").c_str(), (histTitle + " vs. p_{T}").c_str(), {HistType::kTH2F, {ptAxis, indexAxis}}); histVsMcParticleDz = registry->add((histName + "VsMcParticleDz").c_str(), (histTitle + " vs. MC particle #Deltaz").c_str(), {HistType::kTH2F, {dzAxis, indexAxis}}); histVsMftTrackMult = registry->add((histName + "VsMftTrackMult").c_str(), (histTitle + " vs. MFT track multiplicity").c_str(), {HistType::kTH2F, {trackMultAxis, indexAxis}}); + histVsMatchAttempts = registry->add((histName + "VsMatchAttempts").c_str(), (histTitle + " vs. MFT track multiplicity").c_str(), {HistType::kTH2F, {matchAttemptsAxis, indexAxis}}); histVsMftTrackType = registry->add((histName + "VsMftTrackType").c_str(), (histTitle + " vs. MFT track type").c_str(), {HistType::kTH2F, {trackTypeAxis, indexAxis}}); std::get>(histVsMftTrackType)->GetXaxis()->SetBinLabel(1, "Kalman"); std::get>(histVsMftTrackType)->GetXaxis()->SetBinLabel(2, "CA"); @@ -1757,6 +1761,41 @@ struct qaMatching { return dimuon.M(); } + template + int GetMftMchMatchAttempts(EVT const& collisions, + BC const& bcs, + TMUON const& mchTrack, + TMFTS const& mftTracks) + { + if (!mchTrack.has_collision()) { + return 0; + } + const auto& collMch = collisions.rawIteratorAt(mchTrack.collisionId()); + const auto& bcMch = bcs.rawIteratorAt(collMch.bcId()); + + int attempts{0}; + for (const auto& mftTrack : mftTracks) { + if (!mftTrack.has_collision()) { + continue; + } + + const auto& collMft = collisions.rawIteratorAt(mftTrack.collisionId()); + const auto& bcMft = bcs.rawIteratorAt(collMft.bcId()); + + int64_t deltaBc = static_cast(bcMft.globalBC()) - static_cast(bcMch.globalBC()); + double deltaBcNS = o2::constants::lhc::LHCBunchSpacingNS * deltaBc; + double deltaTrackTime = mftTrack.trackTime() - mchTrack.trackTime() + deltaBcNS; + double trackTimeResTot = mftTrack.trackTimeRes() + mchTrack.trackTimeRes(); + + if (std::fabs(deltaTrackTime) > trackTimeResTot) { + continue; + } + attempts += 1; + } + + return attempts; + } + template void FillCollisions(EVT const& collisions, BC const& bcs, @@ -1838,6 +1877,7 @@ struct qaMatching { matchScore, matchChi2, -1, + 0, kMatchTypeUndefined}); } else { collisionInfo.matchingCandidates[mchTrackIndex].emplace_back(MatchingCandidate{ @@ -1851,6 +1891,7 @@ struct qaMatching { matchScore, matchChi2, -1, + 0, kMatchTypeUndefined}); } } @@ -1885,6 +1926,8 @@ struct qaMatching { for (auto& [mchIndex, globalTracksVector] : collisionInfo.matchingCandidates) { std::sort(globalTracksVector.begin(), globalTracksVector.end(), compareMatchingScore); + const auto& mchTrack = muonTracks.rawIteratorAt(mchIndex); + auto mftMchMatchAttempts = GetMftMchMatchAttempts(collisions, bcs, mchTrack, mftTracks); int ranking = 1; for (auto& candidate : globalTracksVector) { const auto& muonTrack = muonTracks.rawIteratorAt(candidate.globalTrackId); @@ -1892,6 +1935,7 @@ struct qaMatching { candidate.matchRanking = ranking; candidate.matchRankingProd = ranking; candidate.matchType = GetMatchType(muonTrack, muonTracks, mftTracks, collisionInfo.matchablePairs, ranking); + candidate.mftMchMatchAttempts = mftMchMatchAttempts; ranking += 1; } } @@ -1950,11 +1994,14 @@ struct qaMatching { mcParticleDz = collision.posZ() - mchMcParticle.vz(); } + int matchAttempts = globalTracksVector[0].mftMchMatchAttempts; + std::get>(plotter->fMatchRanking->hist)->Fill(trueMatchIndex); std::get>(plotter->fMatchRanking->histVsP)->Fill(mchMom, trueMatchIndex); std::get>(plotter->fMatchRanking->histVsPt)->Fill(mchPt, trueMatchIndex); std::get>(plotter->fMatchRanking->histVsMcParticleDz)->Fill(mcParticleDz, trueMatchIndex); std::get>(plotter->fMatchRanking->histVsMftTrackMult)->Fill(mftTrackMult, trueMatchIndex); + std::get>(plotter->fMatchRanking->histVsMatchAttempts)->Fill(matchAttempts, trueMatchIndex); std::get>(plotter->fMatchRanking->histVsMftTrackType)->Fill(mftTrackType, trueMatchIndex); std::get>(plotter->fMatchRanking->histVsProdRanking)->Fill(trueMatchIndexProd, trueMatchIndex); if (dchi2 >= 0) @@ -1966,6 +2013,7 @@ struct qaMatching { std::get>(plotter->fMatchRankingGoodMCH->histVsPt)->Fill(mchPt, trueMatchIndex); std::get>(plotter->fMatchRankingGoodMCH->histVsMcParticleDz)->Fill(mcParticleDz, trueMatchIndex); std::get>(plotter->fMatchRankingGoodMCH->histVsMftTrackMult)->Fill(mftTrackMult, trueMatchIndex); + std::get>(plotter->fMatchRankingGoodMCH->histVsMatchAttempts)->Fill(matchAttempts, trueMatchIndex); std::get>(plotter->fMatchRankingGoodMCH->histVsMftTrackType)->Fill(mftTrackType, trueMatchIndex); std::get>(plotter->fMatchRankingGoodMCH->histVsProdRanking)->Fill(trueMatchIndexProd, trueMatchIndex); if (dchi2 >= 0) @@ -1978,6 +2026,7 @@ struct qaMatching { std::get>(plotter->fMatchRankingPaired->histVsPt)->Fill(mchPt, trueMatchIndex); std::get>(plotter->fMatchRankingPaired->histVsMcParticleDz)->Fill(mcParticleDz, trueMatchIndex); std::get>(plotter->fMatchRankingPaired->histVsMftTrackMult)->Fill(mftTrackMult, trueMatchIndex); + std::get>(plotter->fMatchRankingPaired->histVsMatchAttempts)->Fill(matchAttempts, trueMatchIndex); std::get>(plotter->fMatchRankingPaired->histVsMftTrackType)->Fill(mftTrackType, trueMatchIndex); std::get>(plotter->fMatchRankingPaired->histVsProdRanking)->Fill(trueMatchIndexProd, trueMatchIndex); if (dchi2 >= 0) @@ -1990,6 +2039,7 @@ struct qaMatching { std::get>(plotter->fMatchRankingPairedGoodMCH->histVsPt)->Fill(mchPt, trueMatchIndex); std::get>(plotter->fMatchRankingPairedGoodMCH->histVsMcParticleDz)->Fill(mcParticleDz, trueMatchIndex); std::get>(plotter->fMatchRankingPairedGoodMCH->histVsMftTrackMult)->Fill(mftTrackMult, trueMatchIndex); + std::get>(plotter->fMatchRankingPairedGoodMCH->histVsMatchAttempts)->Fill(matchAttempts, trueMatchIndex); std::get>(plotter->fMatchRankingPairedGoodMCH->histVsMftTrackType)->Fill(mftTrackType, trueMatchIndex); std::get>(plotter->fMatchRankingPairedGoodMCH->histVsProdRanking)->Fill(trueMatchIndexProd, trueMatchIndex); if (dchi2 >= 0) @@ -2311,8 +2361,9 @@ struct qaMatching { } } - template + template void RunChi2Matching(C const& collisions, + BC const& bcs, TMUON const& muonTracks, TMFT const& mftTracks, CMFT const& mftCovs, @@ -2410,19 +2461,23 @@ struct qaMatching { for (auto& [mchIndex, globalTracksVector] : newMatchingCandidates) { std::sort(globalTracksVector.begin(), globalTracksVector.end(), compareMatchingScore); + const auto& mchTrack = muonTracks.rawIteratorAt(mchIndex); + auto mftMchMatchAttempts = GetMftMchMatchAttempts(collisions, bcs, mchTrack, mftTracks); int ranking = 1; for (auto& candidate : globalTracksVector) { const auto& muonTrack = muonTracks.rawIteratorAt(candidate.globalTrackId); candidate.matchRanking = ranking; candidate.matchType = GetMatchType(muonTrack, muonTracks, mftTracks, matchablePairs, ranking); + candidate.mftMchMatchAttempts = mftMchMatchAttempts; ranking += 1; } } } - template + template void RunChi2Matching(C const& collisions, + BC const& bcs, TMUON const& muonTracks, TMFT const& mftTracks, CMFT const& mftCovs, @@ -2451,11 +2506,12 @@ struct qaMatching { auto matchingPlaneZ = matchingPlanesZ[label]; auto extrapMethod = matchingExtrapMethod[label]; - RunChi2Matching(collisions, muonTracks, mftTracks, mftCovs, funcName, matchingPlaneZ, extrapMethod, matchablePairs, matchingCandidates, newMatchingCandidates); + RunChi2Matching(collisions, bcs, muonTracks, mftTracks, mftCovs, funcName, matchingPlaneZ, extrapMethod, matchablePairs, matchingCandidates, newMatchingCandidates); } - template + template void RunMLMatching(C const& collisions, + BC const& bcs, TMUON const& muonTracks, TMFT const& mftTracks, CMFT const& mftCovs, @@ -2550,20 +2606,24 @@ struct qaMatching { for (auto& [mchIndex, globalTracksVector] : newMatchingCandidates) { std::sort(globalTracksVector.begin(), globalTracksVector.end(), compareMatchingScore); + const auto& mchTrack = muonTracks.rawIteratorAt(mchIndex); + auto mftMchMatchAttempts = GetMftMchMatchAttempts(collisions, bcs, mchTrack, mftTracks); int ranking = 1; for (auto& candidate : globalTracksVector) { const auto& muonTrack = muonTracks.rawIteratorAt(candidate.globalTrackId); candidate.matchRanking = ranking; candidate.matchType = GetMatchType(muonTrack, muonTracks, mftTracks, matchablePairs, ranking); + candidate.mftMchMatchAttempts = mftMchMatchAttempts; ranking += 1; } } } - template + template void ProcessCollisionMC(const CollisionInfo& collisionInfo, C const& collisions, + BC const& bcs, TMUON const& muonTracks, TMFT const& mftTracks, CMFT const& mftCovs) @@ -2577,7 +2637,7 @@ struct qaMatching { FillMatchingPlotsMC(collision, collisionInfo, muonTracks, mftTracks, collisionInfo.matchingCandidates, collisionInfo.matchingCandidates, collisionInfo.matchablePairs, fMatchingChi2ScoreMftMchLow, fChi2MatchingPlotter.get(), false); for (auto& [label, func] : matchingChi2Functions) { MatchingCandidates matchingCandidates; - RunChi2Matching(collisions, muonTracks, mftTracks, mftCovs, label, collisionInfo.matchablePairs, collisionInfo.matchingCandidates, matchingCandidates); + RunChi2Matching(collisions, bcs, muonTracks, mftTracks, mftCovs, label, collisionInfo.matchablePairs, collisionInfo.matchingCandidates, matchingCandidates); auto* plotter = fMatchingPlotters.at(label).get(); double matchingScoreCut = matchingScoreCuts.at(label); @@ -2588,7 +2648,7 @@ struct qaMatching { // ML-based matching analysis for (auto& [label, mlResponse] : matchingMlResponses) { MatchingCandidates matchingCandidates; - RunMLMatching(collisions, muonTracks, mftTracks, mftCovs, label, collisionInfo.matchablePairs, collisionInfo.matchingCandidates, matchingCandidates); + RunMLMatching(collisions, bcs, muonTracks, mftTracks, mftCovs, label, collisionInfo.matchablePairs, collisionInfo.matchingCandidates, matchingCandidates); auto* plotter = fMatchingPlotters.at(label).get(); double matchingScoreCut = matchingScoreCuts.at(label); @@ -2668,7 +2728,7 @@ struct qaMatching { } for (auto const& [collisionIndex, collisionInfo] : fCollisionInfos) { - ProcessCollisionMC(collisionInfo, collisions, muonTracks, mftTracks, mftCovs); + ProcessCollisionMC(collisionInfo, collisions, bcs, muonTracks, mftTracks, mftCovs); } } From d455423f55da49ab865e2145fd06b76668b04beb Mon Sep 17 00:00:00 2001 From: Sandeep Dudi <69388148+sdudi123@users.noreply.github.com> Date: Wed, 4 Mar 2026 13:59:19 +0100 Subject: [PATCH 160/347] [PWGUD] UPC tag logic change for generated event MC (#15252) Co-authored-by: sandeep dudi --- PWGUD/Tasks/sginclusivePhiKstarSD.cxx | 105 +++++++++++++------------- 1 file changed, 52 insertions(+), 53 deletions(-) diff --git a/PWGUD/Tasks/sginclusivePhiKstarSD.cxx b/PWGUD/Tasks/sginclusivePhiKstarSD.cxx index 4aeb475109b..ea7c42308a2 100644 --- a/PWGUD/Tasks/sginclusivePhiKstarSD.cxx +++ b/PWGUD/Tasks/sginclusivePhiKstarSD.cxx @@ -368,6 +368,7 @@ struct SginclusivePhiKstarSD { "All Events", "has_udMcCollision", Form("generatorsID = %d", generatedId.value), + Form("upcFlag = %d%s", upcflag.value, check(upcflag.value != -1)), Form("GapsideMC = %d", gapsideMC.value), Form("|Vz| < %.1f", vzCut.value), Form("Occupancy < %.0f%s", confgOccCut.value, check(useOccCut.value)), @@ -381,7 +382,6 @@ struct SginclusivePhiKstarSD { std::string("kIsGoodZvtxFT0vsPV") + check(useZvtxftovpv.value), std::string("kIsVertexITSTPC") + check(useVtxItsTpc.value), Form("RCTFlag = %d%s", cutRCTflag.value, check(cutRCTflag.value > 0)), - Form("upcFlag = %d%s", upcflag.value, check(upcflag.value != -1)), Form("%d < numContrib < %d%s", mintrack.value, maxtrack.value, check(usenumContrib.value))}; for (size_t i = 0; i < eveCutLabelsMC.size(); ++i) { @@ -1421,71 +1421,70 @@ struct SginclusivePhiKstarSD { registry.get(HIST("Reco/Stat"))->Fill(4.0, 1.); registry.get(HIST("Reco/Stat"))->Fill(truegapSide, 1.); - if (upcflag != -1 && collision.flags() == upcflag) { - auto partSlice = McParts.sliceBy(partPerMcCollision, mccoll.globalIndex()); - for (const auto& trk1 : partSlice) { - if (std::abs(trk1.pdgCode()) == o2::constants::physics::Pdg::kK0Star892) { - vkstar.SetCoordinates(trk1.px(), trk1.py(), trk1.pz(), o2::constants::physics::MassK0Star892); - auto kDaughters = trk1.daughters_as(); - const size_t kExpectedNumberOfDaughters = 2; - if (kDaughters.size() != kExpectedNumberOfDaughters) { + auto partSlice = McParts.sliceBy(partPerMcCollision, mccoll.globalIndex()); + for (const auto& trk1 : partSlice) { + if (std::abs(trk1.pdgCode()) == o2::constants::physics::Pdg::kK0Star892) { + vkstar.SetCoordinates(trk1.px(), trk1.py(), trk1.pz(), o2::constants::physics::MassK0Star892); + auto kDaughters = trk1.daughters_as(); + const size_t kExpectedNumberOfDaughters = 2; + if (kDaughters.size() != kExpectedNumberOfDaughters) { + continue; + } + auto daughtp = false; + auto daughtm = false; + for (const auto& kCurrentDaughter : kDaughters) { + if (!kCurrentDaughter.isPhysicalPrimary()) { continue; } - auto daughtp = false; - auto daughtm = false; - for (const auto& kCurrentDaughter : kDaughters) { - if (!kCurrentDaughter.isPhysicalPrimary()) { - continue; - } - if (std::abs(kCurrentDaughter.pdgCode()) == PDG_t::kKPlus) { - daughtp = true; - } else if (std::abs(kCurrentDaughter.pdgCode()) == PDG_t::kPiPlus) { - daughtm = true; - } + if (std::abs(kCurrentDaughter.pdgCode()) == PDG_t::kKPlus) { + daughtp = true; + } else if (std::abs(kCurrentDaughter.pdgCode()) == PDG_t::kPiPlus) { + daughtm = true; } - if (daughtp && daughtm) { - if (std::abs(vkstar.Rapidity()) < 0.5) { - registry.get(HIST("MC/accMPtRap_kstar_G1"))->Fill(vkstar.M(), vkstar.Pt(), vkstar.Rapidity(), 1.); - if (truegapSide == gapsideMC) { - registry.get(HIST("MC/accMPtRap_kstar_G11"))->Fill(vkstar.M(), vkstar.Pt(), vkstar.Rapidity(), 1.); - } + } + if (daughtp && daughtm) { + if (std::abs(vkstar.Rapidity()) < 0.5) { + registry.get(HIST("MC/accMPtRap_kstar_G1"))->Fill(vkstar.M(), vkstar.Pt(), vkstar.Rapidity(), 1.); + if (truegapSide == gapsideMC) { + registry.get(HIST("MC/accMPtRap_kstar_G11"))->Fill(vkstar.M(), vkstar.Pt(), vkstar.Rapidity(), 1.); } } } - // phi - if (std::abs(trk1.pdgCode()) == o2::constants::physics::Pdg::kPhi) { - if (trk1.has_mothers()) { - continue; - } - vphi.SetCoordinates(trk1.px(), trk1.py(), trk1.pz(), o2::constants::physics::MassPhi); - auto kDaughters = trk1.daughters_as(); - const size_t kExpectedNumberOfDaughters1 = 2; - if (kDaughters.size() != kExpectedNumberOfDaughters1) { + } + // phi + if (std::abs(trk1.pdgCode()) == o2::constants::physics::Pdg::kPhi) { + if (trk1.has_mothers()) { + continue; + } + vphi.SetCoordinates(trk1.px(), trk1.py(), trk1.pz(), o2::constants::physics::MassPhi); + auto kDaughters = trk1.daughters_as(); + const size_t kExpectedNumberOfDaughters1 = 2; + if (kDaughters.size() != kExpectedNumberOfDaughters1) { + continue; + } + auto daughtp1 = false; + auto daughtm1 = false; + for (const auto& kCurrentDaughter : kDaughters) { + if (!kCurrentDaughter.isPhysicalPrimary()) { continue; } - auto daughtp1 = false; - auto daughtm1 = false; - for (const auto& kCurrentDaughter : kDaughters) { - if (!kCurrentDaughter.isPhysicalPrimary()) { - continue; - } - if (kCurrentDaughter.pdgCode() == PDG_t::kKPlus) { - daughtp1 = true; - } else if (kCurrentDaughter.pdgCode() == PDG_t::kKMinus) { - daughtm1 = true; - } + if (kCurrentDaughter.pdgCode() == PDG_t::kKPlus) { + daughtp1 = true; + } else if (kCurrentDaughter.pdgCode() == PDG_t::kKMinus) { + daughtm1 = true; } - if (daughtp1 && daughtm1) { - if (std::abs(vphi.Rapidity()) < 0.5) { - registry.get(HIST("MC/accMPtRap_phi_G1"))->Fill(vphi.M(), vphi.Pt(), vphi.Rapidity(), 1.); - if (truegapSide == gapsideMC) { - registry.get(HIST("MC/accMPtRap_phi_G11"))->Fill(vphi.M(), vphi.Pt(), vphi.Rapidity(), 1.); - } + } + if (daughtp1 && daughtm1) { + if (std::abs(vphi.Rapidity()) < 0.5) { + registry.get(HIST("MC/accMPtRap_phi_G1"))->Fill(vphi.M(), vphi.Pt(), vphi.Rapidity(), 1.); + if (truegapSide == gapsideMC) { + registry.get(HIST("MC/accMPtRap_phi_G11"))->Fill(vphi.M(), vphi.Pt(), vphi.Rapidity(), 1.); } } } } } + if (truegapSide != gapsideMC) return; registry.fill(HIST("Reco/hEventCutFlowMC"), 4); @@ -1516,7 +1515,7 @@ struct SginclusivePhiKstarSD { if (useTfb && collision.tfb() != 1) return; - registry.fill(HIST("Reco/hEventCutFlowMC"), 1); + registry.fill(HIST("Reco/hEventCutFlowMC"), 11); if (useItsrofb && collision.itsROFb() != 1) return; From 603a0de2d8901ec6f50337dc555b53b290fbc868 Mon Sep 17 00:00:00 2001 From: wenyaCern <31894577+wenyaCern@users.noreply.github.com> Date: Wed, 4 Mar 2026 14:35:18 +0100 Subject: [PATCH 161/347] [PWGCF] Add mc3d femtodream (#15160) Co-authored-by: ALICE Action Bot --- .../Core/femtoDreamCollisionSelection.h | 56 ++++++++-- PWGCF/FemtoDream/Core/femtoDreamContainer.h | 57 +++++++++- PWGCF/FemtoDream/Core/femtoDreamMath.h | 92 ++++++++++++++++ .../TableProducer/femtoDreamProducerTask.cxx | 46 ++++++-- .../Tasks/femtoDreamPairTaskTrackTrack.cxx | 104 ++++++++++++++---- 5 files changed, 312 insertions(+), 43 deletions(-) diff --git a/PWGCF/FemtoDream/Core/femtoDreamCollisionSelection.h b/PWGCF/FemtoDream/Core/femtoDreamCollisionSelection.h index 538675f3a9d..8a455f073eb 100644 --- a/PWGCF/FemtoDream/Core/femtoDreamCollisionSelection.h +++ b/PWGCF/FemtoDream/Core/femtoDreamCollisionSelection.h @@ -223,6 +223,10 @@ class FemtoDreamCollisionSelection mHistogramQn->add("Event/centVsqnVsSpher", "; cent; qn; Sphericity", kTH3F, {{10, 0, 100}, {100, 0, 1000}, {100, 0, 1}}); mHistogramQn->add("Event/qnBin", "; qnBin; entries", kTH1F, {{20, 0, 20}}); mHistogramQn->add("Event/psiEP", "; #Psi_{EP} (deg); entries", kTH1F, {{100, 0, 180}}); + mHistogramQn->add("Event/epReso_FT0CTPC", "; cent; qnBin; reso_ft0c_tpc", kTH2F, {{10, 0, 100}, {10, 0, 10}}); + mHistogramQn->add("Event/epReso_FT0ATPC", "; cent; qnBin; reso_ft0a_tpc", kTH2F, {{10, 0, 100}, {10, 0, 10}}); + mHistogramQn->add("Event/epReso_FT0CFT0A", "; cent; qnBin; reso_ft0c_ft0a", kTH2F, {{10, 0, 100}, {10, 0, 10}}); + mHistogramQn->add("Event/epReso_count", "; cent; qnBin; count", kTH2F, {{10, 0, 100}, {10, 0, 10}}); return; } @@ -330,9 +334,17 @@ class FemtoDreamCollisionSelection /// \param col Collision /// \return value of the qn-vector of FT0C of the event template - float computeqnVec(T const& col) + float computeqnVec(T const& col, int qvecMod = 0) { - double qn = std::sqrt(col.qvecFT0CReVec()[0] * col.qvecFT0CReVec()[0] + col.qvecFT0CImVec()[0] * col.qvecFT0CImVec()[0]) * std::sqrt(col.sumAmplFT0C()); + double qn = -999.f; + if (qvecMod == 0) { + qn = std::sqrt(col.qvecFT0CReVec()[0] * col.qvecFT0CReVec()[0] + col.qvecFT0CImVec()[0] * col.qvecFT0CImVec()[0]) * std::sqrt(col.sumAmplFT0C()); + } else if (qvecMod == 1) { + qn = std::sqrt(col.qvecFT0AReVec()[0] * col.qvecFT0AReVec()[0] + col.qvecFT0AImVec()[0] * col.qvecFT0AImVec()[0]) * std::sqrt(col.sumAmplFT0A()); + } else { + LOGP(error, "no selected detector of Qvec for ESE "); + return qn; + } return qn; } @@ -342,15 +354,43 @@ class FemtoDreamCollisionSelection /// \param nmode EP in which harmonic(default 2nd harmonic) /// \return angle of the event plane (rad) of FT0C of the event template - float computeEP(T const& col, int nmode) + float computeEP(T const& col, int nmode, int qvecMod) { - double EP = ((1. / nmode) * (TMath::ATan2(col.qvecFT0CImVec()[0], col.qvecFT0CReVec()[0]))); - if (EP < 0) + double EP = -999.f; + if (qvecMod == 0) { + EP = ((1. / nmode) * (TMath::ATan2(col.qvecFT0CImVec()[0], col.qvecFT0CReVec()[0]))); + } else if (qvecMod == 1) { + EP = ((1. / nmode) * (TMath::ATan2(col.qvecFT0AImVec()[0], col.qvecFT0AReVec()[0]))); + } else if (qvecMod == 2) { + EP = ((1. / nmode) * (TMath::ATan2(col.qvecTPCallImVec()[0], col.qvecTPCallReVec()[0]))); + } else { + LOGP(error, "no selected detector of Qvec for EP"); + return EP; + } + + if (EP < 0) { EP += TMath::Pi(); - // atan2 return in rad -pi/2-pi/2, then make it 0-pi + } // atan2 return in rad -pi/2-pi/2, then make it 0-pi return EP; } + /// Compute the event plane resolution of 3 sub-events + /// \tparam T type of the collision + /// \param col Collision + /// \param nmode EP in which harmonic(default 2nd harmonic) + template + void fillEPReso(T const& col, int nmode, float centrality) + { + const float psi_ft0c = ((1. / nmode) * (TMath::ATan2(col.qvecFT0CImVec()[0], col.qvecFT0CReVec()[0]))); + const float psi_ft0a = ((1. / nmode) * (TMath::ATan2(col.qvecFT0AImVec()[0], col.qvecFT0AReVec()[0]))); + const float psi_tpc = ((1. / nmode) * (TMath::ATan2(col.qvecTPCallImVec()[0], col.qvecTPCallReVec()[0]))); + + mHistogramQn->fill(HIST("Event/epReso_FT0CTPC"), centrality, mQnBin + 0.f, std::cos((psi_ft0c - psi_tpc) * nmode)); + mHistogramQn->fill(HIST("Event/epReso_FT0ATPC"), centrality, mQnBin + 0.f, std::cos((psi_ft0a - psi_tpc) * nmode)); + mHistogramQn->fill(HIST("Event/epReso_FT0CFT0A"), centrality, mQnBin + 0.f, std::cos((psi_ft0c - psi_ft0a) * nmode)); + mHistogramQn->fill(HIST("Event/epReso_count"), centrality, mQnBin + 0.f); + } + /// \return the 1-d qn-vector separator to 2-d std::vector> getQnBinSeparator2D(std::vector flat, const int numQnBins = 10) { @@ -413,13 +453,15 @@ class FemtoDreamCollisionSelection } /// \fill event-wise informations - void fillEPQA(float centrality, float fSpher, float qn, float psiEP) + template + void fillEPQA(T& col, float centrality, float fSpher, float qn, float psiEP, int nmode = 2) { mHistogramQn->fill(HIST("Event/centFT0CBeforeQn"), centrality); mHistogramQn->fill(HIST("Event/centVsqn"), centrality, qn); mHistogramQn->fill(HIST("Event/centVsqnVsSpher"), centrality, qn, fSpher); mHistogramQn->fill(HIST("Event/qnBin"), mQnBin + 0.f); mHistogramQn->fill(HIST("Event/psiEP"), psiEP); + fillEPReso(col, nmode, centrality); } /// \todo to be implemented! diff --git a/PWGCF/FemtoDream/Core/femtoDreamContainer.h b/PWGCF/FemtoDream/Core/femtoDreamContainer.h index a12b36fd8a2..4c3a5b24be0 100644 --- a/PWGCF/FemtoDream/Core/femtoDreamContainer.h +++ b/PWGCF/FemtoDream/Core/femtoDreamContainer.h @@ -223,10 +223,26 @@ class FemtoDreamContainer mHistogramRegistry->add((folderName + "/relPair3dRmTMultPercentileQnPairphi").c_str(), ("; " + femtoDKout + femtoDKside + femtoDKlong + "; #it{m}_{T} (GeV/#it{c}); Centrality; qn; #varphi_{pair} - #Psi_{EP}").c_str(), kTHnSparseF, {femtoDKoutAxis, femtoDKsideAxis, femtoDKlongAxis, mTAxi4D, multPercentileAxis4D, qnAxis, pairPhiAxis}); } + template + void init_3Dqn_MC(std::string folderName, std::string femtoDKout, std::string femtoDKside, std::string femtoDKlong, + T& femtoDKoutAxis, T& femtoDKsideAxis, T& femtoDKlongAxis, bool smearingByOrigin = false) + { + mHistogramRegistry->add((folderName + "/hNoMCtruthPairsCounter").c_str(), "; Counter; Entries", kTH1I, {{1, 0, 1}}); + mHistogramRegistry->add((folderName + "/hFakePairsCounter").c_str(), "; Counter; Entries", kTH1I, {{1, 0, 1}}); + if (smearingByOrigin) { + const int nOriginBins = o2::aod::femtodreamMCparticle::ParticleOriginMCTruth::kNOriginMCTruthTypes; + mHistogramRegistry->add((folderName + "/relPair3dresolution").c_str(), (";" + femtoDKout + "mctruth;" + femtoDKout + "_reco;" + femtoDKside + "mctruth;" + femtoDKside + "_reco;" + femtoDKlong + "mctruth;" + femtoDKlong + "_reco;" + "MC origin particle 1; MC origin particle 2;").c_str(), + kTHnSparseF, {femtoDKoutAxis, femtoDKoutAxis, femtoDKsideAxis, femtoDKsideAxis, femtoDKlongAxis, femtoDKlongAxis, {nOriginBins, 0, nOriginBins}, {nOriginBins, 0, nOriginBins}}); + } else { + mHistogramRegistry->add((folderName + "/relPair3dresolution").c_str(), (";" + femtoDKout + "mctruth;" + femtoDKside + "mctruth;" + femtoDKlong + "mctruth;" + femtoDKout + "_reco;" + femtoDKside + "_reco;" + femtoDKlong + "_reco;").c_str(), + kTHnSparseF, {femtoDKoutAxis, femtoDKoutAxis, femtoDKsideAxis, femtoDKsideAxis, femtoDKlongAxis, femtoDKlongAxis}); + } + } + template void init_3Dqn(HistogramRegistry* registry, T& DKoutBins, T& DKsideBins, T& DKlongBins, T& mTBins4D, T& multPercentileBins4D, - bool isMC, ConfigurableAxis qnBins = {"qnBins", {10, 0, 10}, "qn binning"}, ConfigurableAxis pairPhiBins = {"phiBins", {10, 0 - 0.05, TMath::Pi() + 0.05}, "pair phi binning"}) + bool isMC, ConfigurableAxis qnBins = {"qnBins", {10, 0, 10}, "qn binning"}, ConfigurableAxis pairPhiBins = {"phiBins", {10, 0 - 0.05, TMath::Pi() + 0.05}, "pair phi binning"}, bool smearingByOrigin = false) { mHistogramRegistry = registry; @@ -251,6 +267,8 @@ class FemtoDreamContainer folderName = static_cast(mFolderSuffix[mEventType]) + static_cast(o2::aod::femtodreamMCparticle::MCTypeName[o2::aod::femtodreamMCparticle::MCType::kTruth]) + static_cast("_3Dqn"); init_base_3Dqn(folderName, femtoObsDKout, femtoObsDKside, femtoObsDKlong, DKoutAxis, DKsideAxis, DKlongAxis, mTAxis4D, multPercentileAxis4D, qnAxis, pairPhiAxis); + init_3Dqn_MC(folderName, femtoObsDKout, femtoObsDKside, femtoObsDKlong, + DKoutAxis, DKsideAxis, DKlongAxis, smearingByOrigin); } } @@ -484,11 +502,26 @@ class FemtoDreamContainer mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("_3Dqn") + HIST("/relPair3dRmTMultPercentileQnPairphi"), femtoDKout, femtoDKside, femtoDKlong, mT, multPercentile, myQnBin, pairPhiEP); } + /// Called by setPair_3Dqn only in case of Monte Carlo truth + /// Fills resolution of DKout, DKside, DKlong + void setPair_3Dqn_MC(std::vector k3dMC, std::vector k3d, const int originPart1, const int originPart2, bool smearingByOrigin) + { + if (smearingByOrigin) { + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[o2::aod::femtodreamMCparticle::MCType::kTruth]) + HIST("_3Dqn") + HIST("/relPair3dresolution"), k3dMC[1], k3d[1], k3dMC[2], k3d[2], k3dMC[3], k3d[3], originPart1, originPart2); + } else { + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[o2::aod::femtodreamMCparticle::MCType::kTruth]) + HIST("_3Dqn") + HIST("/relPair3dresolution"), k3dMC[1], k3d[1], k3dMC[2], k3d[2], k3dMC[3], k3d[3]); + } + } + template - void setPair_3Dqn(T1 const& part1, T2 const& part2, const float multPercentile, bool IsSameSpecies, const float myQnBin, const float eventPlane) + void setPair_3Dqn(T1 const& part1, T2 const& part2, const float multPercentile, bool IsSameSpecies, const float myQnBin, const float eventPlane, bool smearingByOrigin = false) { std::vector k3d = FemtoDreamMath::newpairfunc(part1, mMassOne, part2, mMassTwo, IsSameSpecies); + if (k3d.size() < 4) { + LOG(error) << "newpairfunc returned size=" << k3d.size(); + return; + } float DKout = k3d[1]; float DKside = k3d[2]; float DKlong = k3d[3]; @@ -503,12 +536,17 @@ class FemtoDreamContainer if constexpr (isMC) { if (part1.has_fdMCParticle() && part2.has_fdMCParticle()) { - std::vector k3dMC = FemtoDreamMath::newpairfunc(part1.fdMCParticle(), mMassOne, part2.fdMCParticle(), mMassTwo, IsSameSpecies); + std::vector k3dMC = FemtoDreamMath::newpairfuncMC(part1.fdMCParticle(), mMassOne, part2.fdMCParticle(), mMassTwo, IsSameSpecies); + if (k3dMC.size() < 4) { + LOG(error) << "newpairfunc returned size=" << k3d.size(); + return; + } const float mTMC = FemtoDreamMath::getmT(part1.fdMCParticle(), mMassOne, part2.fdMCParticle(), mMassTwo); const float pairPhiEPMC = FemtoDreamMath::getPairPhiEP(part1.fdMCParticle(), mMassOne, part2.fdMCParticle(), mMassTwo, eventPlane); if (std::abs(part1.fdMCParticle().pdgMCTruth()) == mPDGOne && std::abs(part2.fdMCParticle().pdgMCTruth()) == mPDGTwo) { // Note: all pair-histogramms are filled with MC truth information ONLY in case of non-fake candidates setPair_3Dqn_base(k3dMC[1], k3dMC[2], k3dMC[3], mTMC, multPercentile, myQnBin, pairPhiEPMC); + setPair_3Dqn_MC(k3dMC, k3d, part1.fdMCParticle().partOriginMCTruth(), part2.fdMCParticle().partOriginMCTruth(), smearingByOrigin); } else { mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[o2::aod::femtodreamMCparticle::MCType::kTruth]) + HIST("/hFakePairsCounter"), 0); } @@ -521,10 +559,14 @@ class FemtoDreamContainer } template - void setPair_3Dqn(T1 const& part1, T2 const& part2, const float multPercentile, bool IsSameSpecies, const float myQnBin, const float EP1, const float EP2) + void setPair_3Dqn(T1 const& part1, T2 const& part2, const float multPercentile, bool IsSameSpecies, const float myQnBin, const float EP1, const float EP2, bool smearingByOrigin = false) { std::vector k3d = FemtoDreamMath::newpairfunc(part1, mMassOne, part2, mMassTwo, IsSameSpecies); + if (k3d.size() < 4) { + LOG(error) << "newpairfunc returned size=" << k3d.size(); + return; + } float DKout = k3d[1]; float DKside = k3d[2]; float DKlong = k3d[3]; @@ -539,12 +581,17 @@ class FemtoDreamContainer if constexpr (isMC) { if (part1.has_fdMCParticle() && part2.has_fdMCParticle()) { - std::vector k3dMC = FemtoDreamMath::newpairfunc(part1.fdMCParticle(), mMassOne, part2.fdMCParticle(), mMassTwo, IsSameSpecies); + std::vector k3dMC = FemtoDreamMath::newpairfuncMC(part1.fdMCParticle(), mMassOne, part2.fdMCParticle(), mMassTwo, IsSameSpecies); + if (k3dMC.size() < 4) { + LOG(error) << "newpairfunc returned size=" << k3d.size(); + return; + } const float mTMC = FemtoDreamMath::getmT(part1.fdMCParticle(), mMassOne, part2.fdMCParticle(), mMassTwo); const float pairPhiEPMC = FemtoDreamMath::getPairPhiEP(part1.fdMCParticle(), mMassOne, part2.fdMCParticle(), mMassTwo, EP1, EP2); if (std::abs(part1.fdMCParticle().pdgMCTruth()) == mPDGOne && std::abs(part2.fdMCParticle().pdgMCTruth()) == mPDGTwo) { // Note: all pair-histogramms are filled with MC truth information ONLY in case of non-fake candidates setPair_3Dqn_base(k3dMC[1], k3dMC[2], k3dMC[3], mTMC, multPercentile, myQnBin, pairPhiEPMC); + setPair_3Dqn_MC(k3dMC, k3d, part1.fdMCParticle().partOriginMCTruth(), part2.fdMCParticle().partOriginMCTruth(), smearingByOrigin); } else { mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[o2::aod::femtodreamMCparticle::MCType::kTruth]) + HIST("/hFakePairsCounter"), 0); } diff --git a/PWGCF/FemtoDream/Core/femtoDreamMath.h b/PWGCF/FemtoDream/Core/femtoDreamMath.h index 867f519ba79..cbb8257f590 100644 --- a/PWGCF/FemtoDream/Core/femtoDreamMath.h +++ b/PWGCF/FemtoDream/Core/femtoDreamMath.h @@ -249,6 +249,98 @@ class FemtoDreamMath return vect; } + /// Compute the 3d components of the pair momentum in LCMS and PRF + /// Copy from femto universe + /// \tparam T type of tracks + /// \param part1 Particle 1 + /// \param mass1 Mass of particle 1 + /// \param part2 Particle 2 + /// \param mass2 Mass of particle 2 + /// \param isiden Identical or non-identical particle pair + template + static std::vector newpairfuncMC(const T& part1, const float mass1, const T& part2, const float mass2, bool isiden) + { + const double trkPx1 = part1.pt() * std::cos(part1.phi()); + const double trkPy1 = part1.pt() * std::sin(part1.phi()); + const double trkPz1 = part1.pt() * std::sinh(part1.eta()); + + const double trkPx2 = part2.pt() * std::cos(part2.phi()); + const double trkPy2 = part2.pt() * std::sin(part2.phi()); + const double trkPz2 = part2.pt() * std::sinh(part2.eta()); + + const double e1 = std::sqrt(std::pow(trkPx1, 2) + std::pow(trkPy1, 2) + std::pow(trkPz1, 2) + std::pow(mass1, 2)); + const double e2 = std::sqrt(std::pow(trkPx2, 2) + std::pow(trkPy2, 2) + std::pow(trkPz2, 2) + std::pow(mass2, 2)); + + const ROOT::Math::PxPyPzEVector vecpart1(trkPx1, trkPy1, trkPz1, e1); + const ROOT::Math::PxPyPzEVector vecpart2(trkPx2, trkPy2, trkPz2, e2); + const ROOT::Math::PxPyPzEVector trackSum = vecpart1 + vecpart2; + + std::vector vect; + + const double tPx = trackSum.px(); + const double tPy = trackSum.py(); + const double tPz = trackSum.pz(); + const double tE = trackSum.E(); + + const double tPtSq = (tPx * tPx + tPy * tPy); + const double tMtSq = (tE * tE - tPz * tPz); + const double tM = std::sqrt(tMtSq - tPtSq); + const double tMt = std::sqrt(tMtSq); + const double tPt = std::sqrt(tPtSq); + + // Boost to LCMS + + const double beta_LCMS = tPz / tE; + const double gamma_LCMS = tE / tMt; + + const double fDKOut = (trkPx1 * tPx + trkPy1 * tPy) / tPt; + const double fDKSide = (-trkPx1 * tPy + trkPy1 * tPx) / tPt; + const double fDKLong = gamma_LCMS * (trkPz1 - beta_LCMS * e1); + const double fDE = gamma_LCMS * (e1 - beta_LCMS * trkPz1); + + const double px1LCMS = fDKOut; + const double py1LCMS = fDKSide; + const double pz1LCMS = fDKLong; + const double pE1LCMS = fDE; + + const double px2LCMS = (trkPx2 * tPx + trkPy2 * tPy) / tPt; + const double py2LCMS = (trkPy2 * tPx - trkPx2 * tPy) / tPt; + const double pz2LCMS = gamma_LCMS * (trkPz2 - beta_LCMS * e2); + const double pE2LCMS = gamma_LCMS * (e2 - beta_LCMS * trkPz2); + + const double fDKOutLCMS = px1LCMS - px2LCMS; + const double fDKSideLCMS = py1LCMS - py2LCMS; + const double fDKLongLCMS = pz1LCMS - pz2LCMS; + + // Boost to PRF + + const double betaOut = tPt / tMt; + const double gammaOut = tMt / tM; + + const double fDKOutPRF = gammaOut * (fDKOutLCMS - betaOut * (pE1LCMS - pE2LCMS)); + const double fDKSidePRF = fDKSideLCMS; + const double fDKLongPRF = fDKLongLCMS; + const double fKOut = gammaOut * (fDKOut - betaOut * fDE); + + const double qlcms = std::sqrt(fDKOutLCMS * fDKOutLCMS + fDKSideLCMS * fDKSideLCMS + fDKLongLCMS * fDKLongLCMS); + const double qinv = std::sqrt(fDKOutPRF * fDKOutPRF + fDKSidePRF * fDKSidePRF + fDKLongPRF * fDKLongPRF); + const double kstar = std::sqrt(fKOut * fKOut + fDKSide * fDKSide + fDKLong * fDKLong); + + if (isiden) { + vect.push_back(qinv); + vect.push_back(fDKOutLCMS); + vect.push_back(fDKSideLCMS); + vect.push_back(fDKLongLCMS); + vect.push_back(qlcms); + } else { + vect.push_back(kstar); + vect.push_back(fDKOut); + vect.push_back(fDKSide); + vect.push_back(fDKLong); + } + return vect; + } + /// Compute the phi angular of a pair with respect to the event plane /// \tparam T type of tracks /// \param part1 Particle 1 diff --git a/PWGCF/FemtoDream/TableProducer/femtoDreamProducerTask.cxx b/PWGCF/FemtoDream/TableProducer/femtoDreamProducerTask.cxx index b8c1f48be09..15686d79e9b 100644 --- a/PWGCF/FemtoDream/TableProducer/femtoDreamProducerTask.cxx +++ b/PWGCF/FemtoDream/TableProducer/femtoDreamProducerTask.cxx @@ -61,10 +61,11 @@ namespace o2::aod using FemtoFullCollision = soa::Join::iterator; using FemtoFullCollision_noCent = soa::Join::iterator; using FemtoFullCollision_CentPbPb = soa::Join::iterator; -using FemtoFullCollision_CentPbPb_qvec = soa::Join::iterator; +using FemtoFullCollision_CentPbPb_qvec = soa::Join::iterator; using FemtoFullCollisionMC = soa::Join::iterator; using FemtoFullCollision_noCent_MC = soa::Join::iterator; using FemtoFullCollisionMC_CentPbPb = soa::Join::iterator; +using FemtoFullCollisionMC_CentPbPb_qvec = soa::Join::iterator; using FemtoFullMCgenCollisions = soa::Join; using FemtoFullMCgenCollision = FemtoFullMCgenCollisions::iterator; @@ -281,6 +282,9 @@ struct femtoDreamProducerTask { Configurable ConfCentralityMax{"ConfCentralityMax", 100.f, "Evt sel: Maximum Centrality cut"}; Configurable ConfCentBinWidth{"ConfCentBinWidth", 1.f, "Centrality bin length for qn separator"}; Configurable ConfNumQnBins{"ConfNumQnBins", 10, "Number of qn bins"}; + Configurable ConfMCQvec{"ConfMCQvec", false, "Enable Q vector table for Monte Carlo"}; + Configurable ConfQvecDetector{"ConfQvecDetector", 0, "Q-vec detector selection; 0 : FT0C; 1 : FT0A"}; + Configurable ConfEPDetector{"ConfEPDetector", 0, "Event-plane detector selection; 0 : FT0C; 1 : FT0A; 2 : TPC"}; } epCal; struct : o2::framework::ConfigurableGroup { @@ -307,10 +311,10 @@ struct femtoDreamProducerTask { void init(InitContext&) { - if (doprocessData == false && doprocessData_noCentrality == false && doprocessData_CentPbPb == false && doprocessData_CentPbPb_EP == false && doprocessMC == false && doprocessMC_noCentrality == false && doprocessMC_CentPbPb == false) { + if (doprocessData == false && doprocessData_noCentrality == false && doprocessData_CentPbPb == false && doprocessData_CentPbPb_EP == false && doprocessMC == false && doprocessMC_noCentrality == false && doprocessMC_CentPbPb == false && doprocessMC_CentPbPb_EP == false) { LOGF(fatal, "Neither processData nor processMC enabled. Please choose one."); } - if ((doprocessData == true && doprocessMC == true) || (doprocessData == true && doprocessMC_noCentrality == true) || (doprocessMC == true && doprocessMC_noCentrality == true) || (doprocessData_noCentrality == true && doprocessData == true) || (doprocessData_noCentrality == true && doprocessMC == true) || (doprocessData_noCentrality == true && doprocessMC_noCentrality == true) || (doprocessData_CentPbPb == true && doprocessData == true) || (doprocessData_CentPbPb == true && doprocessData_noCentrality == true) || (doprocessData_CentPbPb == true && doprocessMC == true) || (doprocessData_CentPbPb == true && doprocessMC_noCentrality == true) || (doprocessData_CentPbPb == true && doprocessMC_CentPbPb == true) || (doprocessData_CentPbPb_EP == true && doprocessData == true) || (doprocessData_CentPbPb_EP == true && doprocessData_noCentrality == true) || (doprocessData_CentPbPb_EP == true && doprocessMC == true) || (doprocessData_CentPbPb_EP == true && doprocessMC_noCentrality == true) || (doprocessData_CentPbPb_EP == true && doprocessMC_CentPbPb == true) || (doprocessData_CentPbPb_EP == true && doprocessData_CentPbPb == true)) { + if ((doprocessData == true && doprocessMC == true) || (doprocessData == true && doprocessMC_noCentrality == true) || (doprocessMC == true && doprocessMC_noCentrality == true) || (doprocessData_noCentrality == true && doprocessData == true) || (doprocessData_noCentrality == true && doprocessMC == true) || (doprocessData_noCentrality == true && doprocessMC_noCentrality == true) || (doprocessData_CentPbPb == true && doprocessData == true) || (doprocessData_CentPbPb == true && doprocessData_noCentrality == true) || (doprocessData_CentPbPb == true && doprocessMC == true) || (doprocessData_CentPbPb == true && doprocessMC_noCentrality == true) || (doprocessData_CentPbPb == true && doprocessMC_CentPbPb == true) || (doprocessData_CentPbPb_EP == true && doprocessData == true) || (doprocessData_CentPbPb_EP == true && doprocessData_noCentrality == true) || (doprocessData_CentPbPb_EP == true && doprocessMC == true) || (doprocessData_CentPbPb_EP == true && doprocessMC_noCentrality == true) || (doprocessData_CentPbPb_EP == true && doprocessMC_CentPbPb == true) || (doprocessData_CentPbPb_EP == true && doprocessData_CentPbPb == true) || (doprocessData_CentPbPb_EP == true && doprocessMC_CentPbPb_EP == true) || (doprocessMC_CentPbPb_EP == true && doprocessData == true) || (doprocessMC_CentPbPb_EP == true && doprocessData_noCentrality == true) || (doprocessMC_CentPbPb_EP == true && doprocessMC == true) || (doprocessMC_CentPbPb_EP == true && doprocessMC_noCentrality == true) || (doprocessMC_CentPbPb_EP == true && doprocessMC_CentPbPb == true) || (doprocessMC_CentPbPb_EP == true && doprocessData_CentPbPb == true)) { LOGF(fatal, "Cannot enable more than one process switch at the same time. " "Please choose one."); @@ -771,7 +775,7 @@ struct femtoDreamProducerTask { } if constexpr (doFlow) { - fillCollisionsFlow(col, tracks, mult, spher, epCal.ConfHarmonicOrder); + fillCollisionsFlow(col, tracks, mult, spher, epCal.ConfHarmonicOrder); } std::vector childIDs = {0, 0}; // these IDs are necessary to keep track of the children @@ -1126,12 +1130,16 @@ struct femtoDreamProducerTask { } } - template + template void fillCollisionsFlow(CollisionType const& col, TrackType const& tracks, float mult, float spher, int EPHarmonic) { - float myqn = colCuts.computeqnVec(col); - float myEP = TMath::RadToDeg() * colCuts.computeEP(col, EPHarmonic); - // psi from rad(0-pi) to deg, in table psi would be in deg,from 0-180 + float myqn = 0.f; + float myEP = 0.f; + + if (!isMC || epCal.ConfMCQvec) { + myqn = colCuts.computeqnVec(col, epCal.ConfQvecDetector); + myEP = TMath::RadToDeg() * colCuts.computeEP(col, EPHarmonic, epCal.ConfEPDetector); // psi from rad(0-pi) to deg, in table psi would be in deg,from 0-180 + } if ((myqn >= 0 && myqn < 1e6) || (myEP >= 0 && myEP < 180)) { outputExtQnCollision(myqn, col.trackOccupancyInTimeRange()); @@ -1139,12 +1147,11 @@ struct femtoDreamProducerTask { } // Calculate flow via cumulant - - if (epCal.ConfQnSeparation) { + if (epCal.ConfQnSeparation && (!isMC || epCal.ConfMCQvec)) { colCuts.myqnBin(mult, epCal.ConfCentralityMax, epCal.ConfFillFlowQA, epCal.ConfQnBinSeparator, myqn, epCal.ConfNumQnBins, epCal.ConfCentBinWidth); } - if (epCal.ConfFillFlowQA) { - colCuts.fillEPQA(mult, spher, myqn, myEP); + if (epCal.ConfFillFlowQA && (!isMC || epCal.ConfMCQvec)) { + colCuts.fillEPQA(col, mult, spher, myqn, myEP, EPHarmonic); if (epCal.ConfDoCumlant) { colCuts.doCumulants(col, tracks, trackCuts, mult, epCal.ConfQnSeparation); } @@ -1277,6 +1284,21 @@ struct femtoDreamProducerTask { fillCollisionsAndTracksAndV0AndCascade(col, tracks, tracks, fullV0s, fullCascades); } PROCESS_SWITCH(femtoDreamProducerTask, processMC_CentPbPb, "Provide MC data with centrality information for PbPb collisions", false); + + void processMC_CentPbPb_EP(aod::FemtoFullCollisionMC_CentPbPb_qvec const& col, + aod::BCsWithTimestamps const&, + soa::Join const& tracks, + aod::FemtoFullMCgenCollisions const&, + aod::McParticles const&, + soa::Join const& fullV0s, /// \todo with FilteredFullV0s + soa::Join const& fullCascades) + { + // get magnetic field for run + initCCDB_Mag_Trig(col.bc_as()); + // fill the tables + fillCollisionsAndTracksAndV0AndCascade(col, tracks, tracks, fullV0s, fullCascades); + } + PROCESS_SWITCH(femtoDreamProducerTask, processMC_CentPbPb_EP, "Provide MC data with centrality and q-vector table for PbPb collisions", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { diff --git a/PWGCF/FemtoDream/Tasks/femtoDreamPairTaskTrackTrack.cxx b/PWGCF/FemtoDream/Tasks/femtoDreamPairTaskTrackTrack.cxx index f2100431efd..0d97ae5b676 100644 --- a/PWGCF/FemtoDream/Tasks/femtoDreamPairTaskTrackTrack.cxx +++ b/PWGCF/FemtoDream/Tasks/femtoDreamPairTaskTrackTrack.cxx @@ -95,6 +95,7 @@ struct femtoDreamPairTaskTrackTrack { Configurable storeEvtTrkInfo{"storeEvtTrkInfo", false, "Fill info of track1 and track2 while pariing in divided qn bins"}; Configurable doQnSeparation{"doQnSeparation", false, "Do qn separation"}; Configurable doEPReClibForMixing{"doEPReClibForMixing", false, "While mixing, using respective event plane for participating particles azimuthal angle caulculation"}; + Configurable mcQvec{"mcQvec", false, "Enable Q vector table for Monte Carlo"}; Configurable> qnBinSeparator{"qnBinSeparator", std::vector{-999.f, -999.f, -999.f}, "Qn bin separator"}; Configurable numQnBins{"numQnBins", 10, "Number of qn bins"}; Configurable qnBinMin{"qnBinMin", 0, "Number of qn bins"}; @@ -113,6 +114,8 @@ struct femtoDreamPairTaskTrackTrack { using FilteredMCCollision = FilteredMCCollisions::iterator; using FilteredQnCollisions = soa::Filtered>; using FilteredQnCollision = FilteredQnCollisions::iterator; + using FilteredMCQnCollisions = soa::Filtered>; + using FilteredMCQnCollision = FilteredMCQnCollisions::iterator; using FilteredMaskedCollisions = soa::Filtered>; using FilteredMaskedCollision = FilteredMaskedCollisions::iterator; @@ -322,9 +325,9 @@ struct femtoDreamPairTaskTrackTrack { if (EPCal.do3DFemto) { sameEventQnCont.init_3Dqn(&Registry, EPCal.DKout, EPCal.DKside, EPCal.DKlong, - Binning4D.mT, Binning4D.multPercentile, Option.IsMC, EPCal.qnBins, EPCal.pairPhiBins); + Binning4D.mT, Binning4D.multPercentile, Option.IsMC, EPCal.qnBins, EPCal.pairPhiBins, Option.SmearingByOrigin); mixedEventQnCont.init_3Dqn(&Registry, EPCal.DKout, EPCal.DKside, EPCal.DKlong, - Binning4D.mT, Binning4D.multPercentile, Option.IsMC, EPCal.qnBins, EPCal.pairPhiBins); + Binning4D.mT, Binning4D.multPercentile, Option.IsMC, EPCal.qnBins, EPCal.pairPhiBins, Option.SmearingByOrigin); sameEventQnCont.setPDGCodes(Track1.PDGCode, Track2.PDGCode); mixedEventQnCont.setPDGCodes(Track1.PDGCode, Track2.PDGCode); if (EPCal.fillFlowQA) { @@ -377,7 +380,10 @@ struct femtoDreamPairTaskTrackTrack { (doprocessMixedEvent && doprocessMixedEventEP) || (doprocessMixedEventMasked && doprocessMixedEventEP) || (doprocessSameEventMC && doprocessSameEventMCMasked) || - (doprocessMixedEventMC && doprocessMixedEventMCMasked)) { + (doprocessSameEventMC && doprocessSameEventEPMC) || + (doprocessMixedEventMC && doprocessMixedEventMCMasked) || + (doprocessMixedEventMC && doprocessMixedEventEPMC) || + (doprocessMixedEventMCMasked && doprocessMixedEventEPMC)) { LOG(fatal) << "Normal and masked processing cannot be activated simultaneously!"; } }; @@ -704,17 +710,20 @@ struct femtoDreamPairTaskTrackTrack { } } - auto myEP = TMath::DegToRad() * col.eventPlane(); + float myEP = -999.f; int myqnBin = -999; - if (EPCal.doQnSeparation || EPCal.do3DFemto) { - myqnBin = epCalculator.myqnBin(col.multV0M(), EPCal.centMax, EPCal.fillFlowQA, EPCal.qnBinSeparator, col.qnVal(), EPCal.numQnBins, EPCal.centBinWidth); - if (myqnBin < EPCal.qnBinMin || myqnBin > EPCal.numQnBins) { - myqnBin = -999; - } - } - if (EPCal.fillFlowQA) { - epCalculator.fillEPQA(col.multV0M(), col.sphericity(), col.qnVal(), col.eventPlane()); + if (!isMC || EPCal.mcQvec) { + myEP = TMath::DegToRad() * col.eventPlane(); + if (EPCal.doQnSeparation || EPCal.do3DFemto) { + myqnBin = epCalculator.myqnBin(col.multV0M(), EPCal.centMax, EPCal.fillFlowQA, EPCal.qnBinSeparator, col.qnVal(), EPCal.numQnBins, EPCal.centBinWidth); + if (myqnBin < EPCal.qnBinMin || myqnBin > EPCal.numQnBins) { + myqnBin = -999; + } + } + } else { + myEP = 0.f; + myqnBin = 0; } /// Now build the combinations @@ -738,14 +747,14 @@ struct femtoDreamPairTaskTrackTrack { sameEventQnCont.setPair_EP(p1, p2, col.multV0M(), EPCal.doQnSeparation, EPCal.doQnSeparation ? myqnBin + 0.f : myEP); } if (EPCal.do3DFemto) { - sameEventQnCont.setPair_3Dqn(p1, p2, col.multV0M(), Option.SameSpecies.value, myqnBin + 0.f, myEP); + sameEventQnCont.setPair_3Dqn(p1, p2, col.multV0M(), Option.SameSpecies.value, myqnBin + 0.f, myEP, Option.SmearingByOrigin); } } else { if (EPCal.do1DFemto) { sameEventQnCont.setPair_EP(p2, p1, col.multV0M(), EPCal.doQnSeparation, EPCal.doQnSeparation ? myqnBin + 0.f : myEP); } if (EPCal.do3DFemto) { - sameEventQnCont.setPair_3Dqn(p2, p1, col.multV0M(), Option.SameSpecies.value, myqnBin + 0.f, myEP); + sameEventQnCont.setPair_3Dqn(p2, p1, col.multV0M(), Option.SameSpecies.value, myqnBin + 0.f, myEP, Option.SmearingByOrigin); } } } @@ -764,7 +773,7 @@ struct femtoDreamPairTaskTrackTrack { sameEventQnCont.setPair_EP(p1, p2, col.multV0M(), EPCal.doQnSeparation, EPCal.doQnSeparation ? myqnBin + 0.f : myEP); } if (EPCal.do3DFemto) { - sameEventQnCont.setPair_3Dqn(p1, p2, col.multV0M(), Option.SameSpecies.value, myEP, myqnBin); + sameEventQnCont.setPair_3Dqn(p1, p2, col.multV0M(), Option.SameSpecies.value, myEP, myqnBin, Option.SmearingByOrigin); } } } @@ -789,6 +798,28 @@ struct femtoDreamPairTaskTrackTrack { } PROCESS_SWITCH(femtoDreamPairTaskTrackTrack, processSameEventEP, "Enable processing same event wrt azimuthal angle and event-plane ", false); + /// process function for to call doSameEventEP with MC Data + /// \param col subscribe to the collision table (Data) + /// \param parts subscribe to the femtoDreamParticleTable + void processSameEventEPMC(FilteredMCQnCollision& col, + o2::aod::FDMCCollisions&, + soa::Join& parts, + o2::aod::FDMCParticles&) + { + if (EPCal.storeEvtTrkInfo) { + fillCollision(col); + } + auto SliceTrk1 = PartitionMCTrk1->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + auto SliceTrk2 = PartitionMCTrk2->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + if (SliceTrk1.size() == 0 && SliceTrk2.size() == 0) { + return; + } + if (EPCal.do1DFemto || EPCal.do3DFemto) { + doSameEventEP(SliceTrk1, SliceTrk2, parts, col); + } + } + PROCESS_SWITCH(femtoDreamPairTaskTrackTrack, processSameEventEPMC, "Enable processing same event of 3D for Monte Carlo", false); + template void doMixedEvent_NotMaskedEP(CollisionType& cols, PartType& parts, PartitionType& part1, PartitionType& part2, BinningType policy) { @@ -799,8 +830,16 @@ struct femtoDreamPairTaskTrackTrack { continue; } - auto myEP_event1 = TMath::DegToRad() * collision1.eventPlane(); - auto myEP_event2 = TMath::DegToRad() * collision2.eventPlane(); + auto myEP_event1 = -999.f; + auto myEP_event2 = -999.f; + + if (!isMC || EPCal.mcQvec) { + myEP_event1 = TMath::DegToRad() * collision1.eventPlane(); + myEP_event2 = TMath::DegToRad() * collision2.eventPlane(); + } else { + myEP_event1 = 0.f; + myEP_event2 = 0.f; + } for (auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(SliceTrk1, SliceTrk2))) { if (Option.CPROn.value) { @@ -816,13 +855,13 @@ struct femtoDreamPairTaskTrackTrack { mixedEventQnCont.setPair_EP(p1, p2, collision1.multV0M(), EPCal.doQnSeparation, myEP_event1, myEP_event2); } if (EPCal.do3DFemto) { - mixedEventQnCont.setPair_3Dqn(p1, p2, collision1.multV0M(), Option.SameSpecies.value, 0.f, myEP_event1, myEP_event2); + mixedEventQnCont.setPair_3Dqn(p1, p2, collision1.multV0M(), Option.SameSpecies.value, 0.f, myEP_event1, myEP_event2, Option.SmearingByOrigin); } } else { if (EPCal.do1DFemto) mixedEventQnCont.setPair_EP(p1, p2, collision1.multV0M(), EPCal.doQnSeparation, EPCal.doQnSeparation ? 0.f : myEP_event1); if (EPCal.do3DFemto) { - mixedEventQnCont.setPair_3Dqn(p1, p2, collision1.multV0M(), Option.SameSpecies.value, 0.f, myEP_event1); + mixedEventQnCont.setPair_3Dqn(p1, p2, collision1.multV0M(), Option.SameSpecies.value, 0.f, myEP_event1, Option.SmearingByOrigin); } } } @@ -855,6 +894,33 @@ struct femtoDreamPairTaskTrackTrack { } } PROCESS_SWITCH(femtoDreamPairTaskTrackTrack, processMixedEventEP, "Enable processing mixed events wrt azimuthal angle and event-plane", false); + + /// process function for to call doMixedEvent with Data + /// @param cols subscribe to the collisions table (Data) + /// @param parts subscribe to the femtoDreamParticleTable + void processMixedEventEPMC(FilteredMCQnCollisions& cols, o2::aod::FDMCCollisions&, soa::Join& parts, o2::aod::FDMCParticles&) + { + switch (Mixing.Policy.value) { + case femtodreamcollision::kMult: + doMixedEvent_NotMaskedEP(cols, parts, PartitionMCTrk1, PartitionMCTrk2, colBinningMult); + break; + case femtodreamcollision::kMultPercentile: + doMixedEvent_NotMaskedEP(cols, parts, PartitionMCTrk1, PartitionMCTrk2, colBinningMultPercentile); + break; + case femtodreamcollision::kMultMultPercentile: + doMixedEvent_NotMaskedEP(cols, parts, PartitionMCTrk1, PartitionMCTrk2, colBinningMultMultPercentile); + break; + case femtodreamcollision::kMultPercentileQn: + doMixedEvent_NotMaskedEP(cols, parts, PartitionMCTrk1, PartitionMCTrk2, colBinningMultPercentileqn); + break; + case femtodreamcollision::kMultPercentileEP: + doMixedEvent_NotMaskedEP(cols, parts, PartitionMCTrk1, PartitionMCTrk2, colBinningMultPercentileEP); + break; + default: + LOG(fatal) << "Invalid binning policiy specifed. Breaking..."; + } + } + PROCESS_SWITCH(femtoDreamPairTaskTrackTrack, processMixedEventEPMC, "Enable processing mixed events wrt azimuthal angle and event-plane for Monte Carlo", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { From c9225af6e86e3b8438e4a727b244c5621aecfbc7 Mon Sep 17 00:00:00 2001 From: Swati <69241911+SwatiSaha-1997@users.noreply.github.com> Date: Wed, 4 Mar 2026 20:06:57 +0530 Subject: [PATCH 162/347] [PWGCF] Implementing multiplicity correlation cuts for event selection (#15251) --- .../Tasks/v0ptHadPiKaProt.cxx | 311 ++++++++++++++++-- 1 file changed, 283 insertions(+), 28 deletions(-) diff --git a/PWGCF/EbyEFluctuations/Tasks/v0ptHadPiKaProt.cxx b/PWGCF/EbyEFluctuations/Tasks/v0ptHadPiKaProt.cxx index 49c44591cf6..f79cb80298b 100644 --- a/PWGCF/EbyEFluctuations/Tasks/v0ptHadPiKaProt.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/v0ptHadPiKaProt.cxx @@ -47,6 +47,7 @@ #include #include #include +#include #include #include #include @@ -68,6 +69,8 @@ using namespace o2::framework::expressions; static constexpr float LongArrayFloat[3][20] = {{1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2}, {2.1, 2.2, 2.3, -2.1, -2.2, -2.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2}, {3.1, 3.2, 3.3, -3.1, -3.2, -3.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2}}; +#define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable NAME{#NAME, DEFAULT, HELP}; + struct V0ptHadPiKaProt { // ITS response @@ -75,7 +78,8 @@ struct V0ptHadPiKaProt { // Connect to ccdb Service ccdb; Configurable ccdbNoLaterThan{"ccdbNoLaterThan", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object"}; - Configurable ccdbUrl{"ccdbUrl", "http://ccdb-test.cern.ch:8080", "url of the ccdb repository"}; + Configurable ccdbUrl{"ccdbUrl", "https://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable ccdbPath{"ccdbPath", "Users/s/swati/PhiWeight", "CCDB path to ccdb object containing phi weight in a 3D histogram"}; enum Particles { PIONS = 0, @@ -116,6 +120,9 @@ struct V0ptHadPiKaProt { Configurable cfgnSigmaCutCombTPCTOF{"cfgnSigmaCutCombTPCTOF", 2.0f, "PID nSigma combined cut for TPC and TOF"}; ConfigurableAxis nchAxis{"nchAxis", {5000, 0.5, 5000.5}, ""}; ConfigurableAxis centAxis{"centAxis", {90, 0., 90.}, "Centrality/Multiplicity percentile bining"}; + ConfigurableAxis nchAxis1{"nchAxis1", {500, 0.5, 500.5}, "Axis for multiplicity of GlobalTracks/PVTracks"}; + ConfigurableAxis nchAxis2{"nchAxis2", {1000, 0.5, 30000.5}, "Axis for multiplicity of FT0A/FT0C/FV0A"}; + ConfigurableAxis nchAxis3{"nchAxis3", {1000, 0.5, 100000.5}, "Axis for multiplicity of FT0A/FT0C/FV0A"}; Configurable cfgCutPtLower{"cfgCutPtLower", 0.2f, "Lower pT cut"}; Configurable cfgCutPtLowerProt{"cfgCutPtLowerProt", 0.2f, "Lower pT cut"}; Configurable cfgCutPtUpper{"cfgCutPtUpper", 10.0f, "Higher pT cut for inclusive hadron analysis"}; @@ -123,7 +130,7 @@ struct V0ptHadPiKaProt { Configurable cfgCutEta{"cfgCutEta", 0.8f, "absolute Eta cut"}; Configurable cfgCutEtaLeft{"cfgCutEtaLeft", 0.8f, "Left end of eta gap"}; Configurable cfgCutEtaRight{"cfgCutEtaRight", 0.8f, "Right end of eta gap"}; - Configurable cfgNSubsample{"cfgNSubsample", 10, "Number of subsamples"}; + Configurable cfgNSubsample{"cfgNSubsample", 20, "Number of subsamples"}; Configurable cfgCentralityChoice{"cfgCentralityChoice", 0, "Which centrality estimator? 0-->FT0C, 1-->FT0A, 2-->FT0M, 3-->FV0A"}; Configurable cfgEvSelkNoSameBunchPileup{"cfgEvSelkNoSameBunchPileup", true, "Pileup removal"}; Configurable cfgUseGoodITSLayerAllCut{"cfgUseGoodITSLayerAllCut", true, "Remove time interval with dead ITS zone"}; @@ -137,12 +144,64 @@ struct V0ptHadPiKaProt { Configurable cfgNbinsV02pt{"cfgNbinsV02pt", 14, "No. of pT bins for v02(pT) analysis"}; Configurable cfgCutPtMaxForV02{"cfgCutPtMaxForV02", 3.0f, "Max. pT for v02(pT)"}; Configurable cfgCutEtaWindowB{"cfgCutEtaWindowB", 0.4f, "value of x in |eta| cfgLoadPhiWeights{"cfgLoadPhiWeights", false, "Load phi weights from CCDB to take care of non-uniform acceptance"}; + + // pT dep DCAxy and DCAz cuts + Configurable cfgUsePtDepDCAxy{"cfgUsePtDepDCAxy", true, "Use pt-dependent DCAxy cut"}; + Configurable cfgUsePtDepDCAz{"cfgUsePtDepDCAz", true, "Use pt-dependent DCAz cut"}; + O2_DEFINE_CONFIGURABLE(cfgDCAxyFunc, std::string, "(0.0026+0.005/(x^1.01))", "Functional form of pt-dependent DCAxy cut"); + O2_DEFINE_CONFIGURABLE(cfgDCAzFunc, std::string, "(0.0026+0.005/(x^1.01))", "Functional form of pt-dependent DCAz cut"); + TF1* fPtDepDCAxy = nullptr; + TF1* fPtDepDCAz = nullptr; + + O2_DEFINE_CONFIGURABLE(cfgUseSmallIonAdditionalEventCut, bool, true, "Use additional event cut on mult correlations for small ions") + O2_DEFINE_CONFIGURABLE(cfgEvSelMultCorrelation, bool, true, "Multiplicity correlation cut") + O2_DEFINE_CONFIGURABLE(cfgEvSelV0AT0ACut, bool, true, "V0A T0A 5 sigma cut") + struct : ConfigurableGroup { + O2_DEFINE_CONFIGURABLE(cfgMultCentHighCutFunction, std::string, "[0] + [1]*x + [2]*x*x + [3]*x*x*x + [4]*x*x*x*x + 10.*([5] + [6]*x + [7]*x*x + [8]*x*x*x + [9]*x*x*x*x)", "Functional for multiplicity correlation cut"); + O2_DEFINE_CONFIGURABLE(cfgMultCentLowCutFunction, std::string, "[0] + [1]*x + [2]*x*x + [3]*x*x*x + [4]*x*x*x*x - 3.*([5] + [6]*x + [7]*x*x + [8]*x*x*x + [9]*x*x*x*x)", "Functional for multiplicity correlation cut"); + O2_DEFINE_CONFIGURABLE(cfgMultT0CCutEnabled, bool, false, "Enable Global multiplicity vs T0C centrality cut") + Configurable> cfgMultT0CCutPars{"cfgMultT0CCutPars", std::vector{143.04, -4.58368, 0.0766055, -0.000727796, 2.86153e-06, 23.3108, -0.36304, 0.00437706, -4.717e-05, 1.98332e-07}, "Global multiplicity vs T0C centrality cut parameter values"}; + O2_DEFINE_CONFIGURABLE(cfgMultPVT0CCutEnabled, bool, false, "Enable PV multiplicity vs T0C centrality cut") + Configurable> cfgMultPVT0CCutPars{"cfgMultPVT0CCutPars", std::vector{195.357, -6.15194, 0.101313, -0.000955828, 3.74793e-06, 30.0326, -0.43322, 0.00476265, -5.11206e-05, 2.13613e-07}, "PV multiplicity vs T0C centrality cut parameter values"}; + + O2_DEFINE_CONFIGURABLE(cfgMultMultPVHighCutFunction, std::string, "[0]+[1]*x + 5.*([2]+[3]*x)", "Functional for multiplicity correlation cut"); + O2_DEFINE_CONFIGURABLE(cfgMultMultPVLowCutFunction, std::string, "[0]+[1]*x - 5.*([2]+[3]*x)", "Functional for multiplicity correlation cut"); + O2_DEFINE_CONFIGURABLE(cfgMultGlobalPVCutEnabled, bool, false, "Enable global multiplicity vs PV multiplicity cut") + Configurable> cfgMultGlobalPVCutPars{"cfgMultGlobalPVCutPars", std::vector{-0.140809, 0.734344, 2.77495, 0.0165935}, "PV multiplicity vs T0C centrality cut parameter values"}; + + O2_DEFINE_CONFIGURABLE(cfgMultMultV0AHighCutFunction, std::string, "[0] + [1]*x + [2]*x*x + [3]*x*x*x + [4]*x*x*x*x + 4.*([5] + [6]*x + [7]*x*x + [8]*x*x*x + [9]*x*x*x*x)", "Functional for multiplicity correlation cut"); + O2_DEFINE_CONFIGURABLE(cfgMultMultV0ALowCutFunction, std::string, "[0] + [1]*x + [2]*x*x + [3]*x*x*x + [4]*x*x*x*x - 3.*([5] + [6]*x + [7]*x*x + [8]*x*x*x + [9]*x*x*x*x)", "Functional for multiplicity correlation cut"); + O2_DEFINE_CONFIGURABLE(cfgMultMultV0ACutEnabled, bool, false, "Enable global multiplicity vs V0A multiplicity cut") + Configurable> cfgMultMultV0ACutPars{"cfgMultMultV0ACutPars", std::vector{534.893, 184.344, 0.423539, -0.00331436, 5.34622e-06, 871.239, 53.3735, -0.203528, 0.000122758, 5.41027e-07}, "Global multiplicity vs V0A multiplicity cut parameter values"}; + + std::vector multT0CCutPars; + std::vector multPVT0CCutPars; + std::vector multGlobalPVCutPars; + std::vector multMultV0ACutPars; + TF1* fMultPVT0CCutLow = nullptr; + TF1* fMultPVT0CCutHigh = nullptr; + TF1* fMultT0CCutLow = nullptr; + TF1* fMultT0CCutHigh = nullptr; + TF1* fMultGlobalPVCutLow = nullptr; + TF1* fMultGlobalPVCutHigh = nullptr; + TF1* fMultMultV0ACutLow = nullptr; + TF1* fMultMultV0ACutHigh = nullptr; + TF1* fT0AV0AMean = nullptr; + TF1* fT0AV0ASigma = nullptr; + + } cfgFuncParas; + + // Output HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry histosAnalysis{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; std::vector>> subSample; std::vector>> subSampleV02; TRandom3* funRndm = new TRandom3(0); + // Phi weight histograms initialization + TH2F* hWeightPhiFunctionVzEtaPhi = nullptr; + // Filter command*********** Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && (aod::track::pt > cfgCutPtLower) && (aod::track::pt < cfgCutPtUpper) && (requireGlobalTrackInFilter()) && (aod::track::tpcChi2NCl < cfgCutTpcChi2NCl) && (aod::track::itsChi2NCl < cfgCutItsChi2NCl) && (nabs(aod::track::dcaZ) < cfgCutTrackDcaZ); @@ -180,6 +239,24 @@ struct V0ptHadPiKaProt { itsNsigmaCut[kKaonLowCut] = nSigmas->getData()[kITS][kKaonLowCut]; itsNsigmaCut[kProtonLowCut] = nSigmas->getData()[kITS][kProtonLowCut]; + // Loading phi weight histograms from CCDB + if (cfgLoadPhiWeights) { + + // Accessing eff histograms + ccdb->setURL(ccdbUrl.value); + // Enabling object caching, otherwise each call goes to the CCDB server + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + // Not later than now, will be replaced by the value of the train creation + // This avoids that users can replace objects **while** a train is running + ccdb->setCreatedNotAfter(ccdbNoLaterThan.value); + LOGF(info, "Getting object %s", ccdbPath.value.data()); + TList* lst = ccdb->getForTimeStamp(ccdbPath.value, ccdbNoLaterThan.value); + hWeightPhiFunctionVzEtaPhi = reinterpret_cast(lst->FindObject("hWeightPhiFunctionVzEtaPhi")); + if (!hWeightPhiFunctionVzEtaPhi) + LOGF(info, "FATAL!! could not get phi weights---------> check"); + } + // Define axes std::vector ptBin = {0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.5, 4.0, 5.0, 6.0, 8.0, 10.0}; AxisSpec ptAxis = {ptBin, "#it{p}_{T} (GeV/#it{c})"}; @@ -189,18 +266,39 @@ struct V0ptHadPiKaProt { // Add histograms to histogram manager (as in the output object of in AliPhysics) // QA hists + histos.add("hEventStatData", "Data Event statistics", kTH1F, {{10, 0.0f, 10.0f}}); histos.add("hZvtx_after_sel", ";Z (cm)", kTH1F, {{240, -12, 12}}); histos.add("hCentrality", ";centrality (%)", kTH1F, {{90, 0, 90}}); + // before selection + histos.add("MultCorrelationPlots/BeforeSelection/His2D_globalTracks_PVTracks_beforeSel", "", {HistType::kTH2D, {nchAxis1, nchAxis1}}); + histos.add("MultCorrelationPlots/BeforeSelection/His2D_globalTracks_centFT0C_beforeSel", "", {HistType::kTH2D, {centAxis, nchAxis1}}); + histos.add("MultCorrelationPlots/BeforeSelection/His2D_PVTracks_centFT0C_beforeSel", "", {HistType::kTH2D, {centAxis, nchAxis1}}); + histos.add("MultCorrelationPlots/BeforeSelection/His2D_globalTracks_V0ATracks_beforeSel", "", {HistType::kTH2D, {nchAxis3, nchAxis1}}); + histos.add("MultCorrelationPlots/BeforeSelection/His2D_globalTracks_T0ATracks_beforeSel", "", {HistType::kTH2D, {nchAxis2, nchAxis1}}); + histos.add("MultCorrelationPlots/BeforeSelection/His2D_V0ATracks_T0CTracks_beforeSel", "", {HistType::kTH2D, {nchAxis2, nchAxis3}}); + // after selection + if (cfgUseSmallIonAdditionalEventCut) { + histos.add("MultCorrelationPlots/AfterSelection/His2D_globalTracks_PVTracks_afterSel", "", {HistType::kTH2D, {nchAxis1, nchAxis1}}); + histos.add("MultCorrelationPlots/AfterSelection/His2D_globalTracks_centFT0C_afterSel", "", {HistType::kTH2D, {centAxis, nchAxis1}}); + histos.add("MultCorrelationPlots/AfterSelection/His2D_PVTracks_centFT0C_afterSel", "", {HistType::kTH2D, {centAxis, nchAxis1}}); + histos.add("MultCorrelationPlots/AfterSelection/His2D_globalTracks_V0ATracks_afterSel", "", {HistType::kTH2D, {nchAxis3, nchAxis1}}); + histos.add("MultCorrelationPlots/AfterSelection/His2D_globalTracks_T0ATracks_afterSel", "", {HistType::kTH2D, {nchAxis2, nchAxis1}}); + histos.add("MultCorrelationPlots/AfterSelection/His2D_V0ATracks_T0CTracks_afterSel", "", {HistType::kTH2D, {nchAxis2, nchAxis3}}); + } + histos.add("Hist2D_globalTracks_PVTracks", "", {HistType::kTH2D, {nchAxis, nchAxis}}); histos.add("Hist2D_cent_nch", "", {HistType::kTH2D, {nchAxis, centAxis}}); histos.add("hP", ";#it{p} (GeV/#it{c})", kTH1F, {{35, 0.2, 4.}}); histos.add("hPt", ";#it{p}_{T} (GeV/#it{c})", kTH1F, {ptAxis}); histos.add("hPhi", ";#phi", kTH1F, {{100, 0., o2::constants::math::TwoPI}}); histos.add("hEta", ";#eta", kTH1F, {{100, -2.01, 2.01}}); - histos.add("hDcaXY", ";#it{dca}_{XY}", kTH1F, {{1000, -5, 5}}); - histos.add("hDcaZ", ";#it{dca}_{Z}", kTH1F, {{1000, -5, 5}}); + histos.add("hDcaXY", ";#it{dca}_{XY}", kTH1F, {{1000, -0.5, 0.5}}); + histos.add("hDcaZ", ";#it{dca}_{Z}", kTH1F, {{1000, -0.5, 0.5}}); histos.add("hMeanPt", "", kTProfile, {centAxis}); + // phi weight hist for non-uniform acceptance correction + histos.add("h3DVtxZetaPhi", "", kTH3D, {{20, -10, 10}, {16, -0.8, +0.8}, {100, 0., o2::constants::math::TwoPI}}); + // 2D histograms of nSigma // before cut histos.add("h2DnsigmaPionTpcVsPtBeforeCut", "2D hist of nSigmaTPC vs. pT (pion)", kTH2F, {ptAxis, nSigmaAxis}); @@ -265,7 +363,7 @@ struct V0ptHadPiKaProt { subSampleV02.resize(cfgNSubsample); for (int i = 0; i < cfgNSubsample; i++) { subSample[i].resize(20); - subSampleV02[i].resize(20); + subSampleV02[i].resize(9); } for (int i = 0; i < cfgNSubsample; i++) { subSample[i][0] = std::get>(histos.add(Form("subSample_%d/Prof_A_had", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); @@ -292,16 +390,51 @@ struct V0ptHadPiKaProt { subSample[i][18] = std::get>(histos.add(Form("subSample_%d/Prof_Bone_prot", i), "", {HistType::kTProfile2D, {centAxis, noAxis}})); subSample[i][19] = std::get>(histos.add(Form("subSample_%d/Prof_Btwo_prot", i), "", {HistType::kTProfile2D, {centAxis, noAxis}})); - subSampleV02[i][0] = std::get>(histos.add(Form("subSampleV02_%d/Prof_XY", i), "", {HistType::kTProfile2D, {centAxis, noAxis}})); - subSampleV02[i][1] = std::get>(histos.add(Form("subSampleV02_%d/Prof_XYZ_had", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); - subSampleV02[i][2] = std::get>(histos.add(Form("subSampleV02_%d/Prof_Z_had", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); - subSampleV02[i][3] = std::get>(histos.add(Form("subSampleV02_%d/Prof_XYZ_pi", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); - subSampleV02[i][4] = std::get>(histos.add(Form("subSampleV02_%d/Prof_Z_pi", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); - subSampleV02[i][5] = std::get>(histos.add(Form("subSampleV02_%d/Prof_XYZ_ka", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); - subSampleV02[i][6] = std::get>(histos.add(Form("subSampleV02_%d/Prof_Z_ka", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); - subSampleV02[i][1] = std::get>(histos.add(Form("subSampleV02_%d/Prof_XYZ_prot", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); - subSampleV02[i][2] = std::get>(histos.add(Form("subSampleV02_%d/Prof_Z_prot", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); + subSampleV02[i][0] = std::get>(histosAnalysis.add(Form("subSampleV02_%d/Prof_XY", i), "", {HistType::kTProfile2D, {centAxis, noAxis}})); + subSampleV02[i][1] = std::get>(histosAnalysis.add(Form("subSampleV02_%d/Prof_XYZ_had", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); + subSampleV02[i][2] = std::get>(histosAnalysis.add(Form("subSampleV02_%d/Prof_Z_had", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); + subSampleV02[i][3] = std::get>(histosAnalysis.add(Form("subSampleV02_%d/Prof_XYZ_pi", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); + subSampleV02[i][4] = std::get>(histosAnalysis.add(Form("subSampleV02_%d/Prof_Z_pi", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); + subSampleV02[i][5] = std::get>(histosAnalysis.add(Form("subSampleV02_%d/Prof_XYZ_ka", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); + subSampleV02[i][6] = std::get>(histosAnalysis.add(Form("subSampleV02_%d/Prof_Z_ka", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); + subSampleV02[i][7] = std::get>(histosAnalysis.add(Form("subSampleV02_%d/Prof_XYZ_prot", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); + subSampleV02[i][8] = std::get>(histosAnalysis.add(Form("subSampleV02_%d/Prof_Z_prot", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); + } + + if (cfgEvSelMultCorrelation) { + cfgFuncParas.multT0CCutPars = cfgFuncParas.cfgMultT0CCutPars; + cfgFuncParas.multPVT0CCutPars = cfgFuncParas.cfgMultPVT0CCutPars; + cfgFuncParas.multGlobalPVCutPars = cfgFuncParas.cfgMultGlobalPVCutPars; + cfgFuncParas.multMultV0ACutPars = cfgFuncParas.cfgMultMultV0ACutPars; + cfgFuncParas.fMultPVT0CCutLow = new TF1("fMultPVT0CCutLow", cfgFuncParas.cfgMultCentLowCutFunction->c_str(), 0, 100); + cfgFuncParas.fMultPVT0CCutLow->SetParameters(&(cfgFuncParas.multPVT0CCutPars[0])); + cfgFuncParas.fMultPVT0CCutHigh = new TF1("fMultPVT0CCutHigh", cfgFuncParas.cfgMultCentHighCutFunction->c_str(), 0, 100); + cfgFuncParas.fMultPVT0CCutHigh->SetParameters(&(cfgFuncParas.multPVT0CCutPars[0])); + cfgFuncParas.fMultT0CCutLow = new TF1("fMultT0CCutLow", cfgFuncParas.cfgMultCentLowCutFunction->c_str(), 0, 100); + cfgFuncParas.fMultT0CCutLow->SetParameters(&(cfgFuncParas.multT0CCutPars[0])); + cfgFuncParas.fMultT0CCutHigh = new TF1("fMultT0CCutHigh", cfgFuncParas.cfgMultCentHighCutFunction->c_str(), 0, 100); + cfgFuncParas.fMultT0CCutHigh->SetParameters(&(cfgFuncParas.multT0CCutPars[0])); + cfgFuncParas.fMultGlobalPVCutLow = new TF1("fMultGlobalPVCutLow", cfgFuncParas.cfgMultMultPVLowCutFunction->c_str(), 0, 4000); + cfgFuncParas.fMultGlobalPVCutLow->SetParameters(&(cfgFuncParas.multGlobalPVCutPars[0])); + cfgFuncParas.fMultGlobalPVCutHigh = new TF1("fMultGlobalPVCutHigh", cfgFuncParas.cfgMultMultPVHighCutFunction->c_str(), 0, 4000); + cfgFuncParas.fMultGlobalPVCutHigh->SetParameters(&(cfgFuncParas.multGlobalPVCutPars[0])); + cfgFuncParas.fMultMultV0ACutLow = new TF1("fMultMultV0ACutLow", cfgFuncParas.cfgMultMultV0ALowCutFunction->c_str(), 0, 4000); + cfgFuncParas.fMultMultV0ACutLow->SetParameters(&(cfgFuncParas.multMultV0ACutPars[0])); + cfgFuncParas.fMultMultV0ACutHigh = new TF1("fMultMultV0ACutHigh", cfgFuncParas.cfgMultMultV0AHighCutFunction->c_str(), 0, 4000); + cfgFuncParas.fMultMultV0ACutHigh->SetParameters(&(cfgFuncParas.multMultV0ACutPars[0])); + cfgFuncParas.fT0AV0AMean = new TF1("fT0AV0AMean", "[0]+[1]*x", 0, 200000); + cfgFuncParas.fT0AV0AMean->SetParameters(-1601.0581, 9.417652e-01); + cfgFuncParas.fT0AV0ASigma = new TF1("fT0AV0ASigma", "[0]+[1]*x+[2]*x*x+[3]*x*x*x+[4]*x*x*x*x", 0, 200000); + cfgFuncParas.fT0AV0ASigma->SetParameters(463.4144, 6.796509e-02, -9.097136e-07, 7.971088e-12, -2.600581e-17); } + + if (cfgUsePtDepDCAxy) { + fPtDepDCAxy = new TF1("ptDepDCAxy", Form("%s", cfgDCAxyFunc->c_str()), 0.001, 1000); + } + if (cfgUsePtDepDCAz) { + fPtDepDCAz = new TF1("ptDepDCAz", Form("%s", cfgDCAzFunc->c_str()), 0.001, 1000); + } + } // end init //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ @@ -472,28 +605,139 @@ struct V0ptHadPiKaProt { return pid; // 0 = not identified, 1 = pion, 2 = kaon, 3 = proton } - // process Data - void process(AodCollisions::iterator const& coll, aod::BCsWithTimestamps const&, AodTracks const& inputTracks) + // additional multiplicity correlation based event selection cuts + template + bool eventSelectedSmallion(TCollision collision, const int multTrk, const float centrality) + { + auto multNTracksPV = collision.multNTracksPV(); + + if (cfgEvSelMultCorrelation) { + if (cfgFuncParas.cfgMultPVT0CCutEnabled) { + if (multNTracksPV < cfgFuncParas.fMultPVT0CCutLow->Eval(centrality)) + return 0; + if (multNTracksPV > cfgFuncParas.fMultPVT0CCutHigh->Eval(centrality)) + return 0; + } + + if (cfgFuncParas.cfgMultT0CCutEnabled) { + if (multTrk < cfgFuncParas.fMultT0CCutLow->Eval(centrality)) + return 0; + if (multTrk > cfgFuncParas.fMultT0CCutHigh->Eval(centrality)) + return 0; + } + + if (cfgFuncParas.cfgMultGlobalPVCutEnabled) { + if (multTrk < cfgFuncParas.fMultGlobalPVCutLow->Eval(multNTracksPV)) + return 0; + if (multTrk > cfgFuncParas.fMultGlobalPVCutHigh->Eval(multNTracksPV)) + return 0; + } + + if (cfgFuncParas.cfgMultMultV0ACutEnabled) { + if (collision.multFV0A() < cfgFuncParas.fMultMultV0ACutLow->Eval(multTrk)) + return 0; + if (collision.multFV0A() > cfgFuncParas.fMultMultV0ACutHigh->Eval(multTrk)) + return 0; + } + } + + float sigma = 5.0; + if (cfgEvSelV0AT0ACut && (std::fabs(collision.multFV0A() - cfgFuncParas.fT0AV0AMean->Eval(collision.multFT0A())) > sigma * cfgFuncParas.fT0AV0ASigma->Eval(collision.multFT0A()))) + return 0; + + return 1; + } + + template + bool eventSelectionDefaultCuts(TCollision coll) { + histos.fill(HIST("hEventStatData"), 0.5); if (!coll.sel8()) { - return; + return 0; } + + histos.fill(HIST("hEventStatData"), 1.5); if (cfgUseGoodITSLayerAllCut && !(coll.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll))) { - return; + return 0; } + + histos.fill(HIST("hEventStatData"), 2.5); if (cfgEvSelkNoSameBunchPileup && !(coll.selection_bit(o2::aod::evsel::kNoSameBunchPileup))) { - return; + return 0; } + + histos.fill(HIST("hEventStatData"), 3.5); if (cfgEvSelkNoITSROFrameBorder && !(coll.selection_bit(o2::aod::evsel::kNoITSROFrameBorder))) { - return; + return 0; } + + histos.fill(HIST("hEventStatData"), 4.5); if (cfgEvSelkNoTimeFrameBorder && !(coll.selection_bit(o2::aod::evsel::kNoTimeFrameBorder))) { - return; + return 0; } + + histos.fill(HIST("hEventStatData"), 5.5); if (cfgEvSelUseGoodZvtxFT0vsPV && !(coll.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV))) { + return 0; + } + + histos.fill(HIST("hEventStatData"), 6.5); + return 1; + } + + template + void fillMultCorrPlotsBeforeSel(C const& coll, T const& inputTracks) + { + histos.fill(HIST("MultCorrelationPlots/BeforeSelection/His2D_globalTracks_PVTracks_beforeSel"), coll.multNTracksPV(), inputTracks.size()); + histos.fill(HIST("MultCorrelationPlots/BeforeSelection/His2D_globalTracks_centFT0C_beforeSel"), coll.centFT0C(), inputTracks.size()); + histos.fill(HIST("MultCorrelationPlots/BeforeSelection/His2D_PVTracks_centFT0C_beforeSel"), coll.centFT0C(), coll.multNTracksPV()); + histos.fill(HIST("MultCorrelationPlots/BeforeSelection/His2D_globalTracks_V0ATracks_beforeSel"), coll.multFV0A(), inputTracks.size()); + histos.fill(HIST("MultCorrelationPlots/BeforeSelection/His2D_globalTracks_T0ATracks_beforeSel"), coll.multFT0A(), inputTracks.size()); + histos.fill(HIST("MultCorrelationPlots/BeforeSelection/His2D_V0ATracks_T0CTracks_beforeSel"), coll.multFT0C(), coll.multFV0A()); + } + + template + void fillMultCorrPlotsAfterSel(C const& coll, T const& inputTracks) + { + histos.fill(HIST("MultCorrelationPlots/AfterSelection/His2D_globalTracks_PVTracks_afterSel"), coll.multNTracksPV(), inputTracks.size()); + histos.fill(HIST("MultCorrelationPlots/AfterSelection/His2D_globalTracks_centFT0C_afterSel"), coll.centFT0C(), inputTracks.size()); + histos.fill(HIST("MultCorrelationPlots/AfterSelection/His2D_PVTracks_centFT0C_afterSel"), coll.centFT0C(), coll.multNTracksPV()); + histos.fill(HIST("MultCorrelationPlots/AfterSelection/His2D_globalTracks_V0ATracks_afterSel"), coll.multFV0A(), inputTracks.size()); + histos.fill(HIST("MultCorrelationPlots/AfterSelection/His2D_globalTracks_T0ATracks_afterSel"), coll.multFT0A(), inputTracks.size()); + histos.fill(HIST("MultCorrelationPlots/AfterSelection/His2D_V0ATracks_T0CTracks_afterSel"), coll.multFT0C(), coll.multFV0A()); + } + + template + float getPhiWeight(const T& candidate, float vtxz) + { + if (!cfgLoadPhiWeights || !hWeightPhiFunctionVzEtaPhi) { + return 1.0; + } + int bin = hWeightPhiFunctionVzEtaPhi->FindBin(vtxz, candidate.eta(), candidate.phi()); + float weight = hWeightPhiFunctionVzEtaPhi->GetBinContent(bin); + if (!std::isfinite(weight) || weight <= 0) { + return 1.0; + } + return weight; + } + + // process Data + void process(AodCollisions::iterator const& coll, aod::BCsWithTimestamps const&, AodTracks const& inputTracks) + { + if (!eventSelectionDefaultCuts(coll)) { return; } + fillMultCorrPlotsBeforeSel(coll, inputTracks); + + const auto centralityFT0C = coll.centFT0C(); + if (cfgUseSmallIonAdditionalEventCut && !eventSelectedSmallion(coll, inputTracks.size(), centralityFT0C)) + return; + + if (cfgUseSmallIonAdditionalEventCut) { + fillMultCorrPlotsAfterSel(coll, inputTracks); + } + // Centrality double cent = 0.0; if (cfgCentralityChoice == kFT0C) @@ -552,6 +796,13 @@ struct V0ptHadPiKaProt { continue; } + if (cfgUsePtDepDCAxy && !(std::abs(track.dcaXY()) < fPtDepDCAxy->Eval(track.pt()))) { + continue; + } + if (cfgUsePtDepDCAz && !(std::abs(track.dcaZ()) < fPtDepDCAz->Eval(track.pt()))) { + continue; + } + histos.fill(HIST("hP"), track.p()); histos.fill(HIST("hPt"), track.pt()); histos.fill(HIST("hEta"), track.eta()); @@ -584,8 +835,12 @@ struct V0ptHadPiKaProt { } } double phiweight = 1.0; + if (cfgLoadPhiWeights) { + phiweight = getPhiWeight(track, coll.posZ()); + } // fill subevent C for v2^2 in v02(pT) if (track.sign() != 0 && trkPt < cfgCutPtMaxForV02) { + histos.fill(HIST("h3DVtxZetaPhi"), coll.posZ(), trkEta, trkPhi); if (cfgCutEtaWindowB < trkEta && trkEta < 0.8) { vecQInWinC += phiweight * TComplex(TMath::Cos(2. * trkPhi), TMath::Sin(2. * trkPhi)); nSumInWinC += phiweight; @@ -780,8 +1035,8 @@ struct V0ptHadPiKaProt { histos.get(HIST("Prof_XYZ_pi"))->Fill(cent, fPtProfilePiInWinB->GetBinCenter(i + 1), threeParCorrPi); histos.get(HIST("Prof_Z_pi"))->Fill(cent, fPtProfilePiInWinB->GetBinCenter(i + 1), (fPtProfilePiInWinB->GetBinContent(i + 1) / nSumInWinB)); - subSampleV02[sampleIndex][1]->Fill(cent, fPtProfilePiInWinB->GetBinCenter(i + 1), threeParCorrPi); - subSampleV02[sampleIndex][2]->Fill(cent, fPtProfilePiInWinB->GetBinCenter(i + 1), (fPtProfilePiInWinB->GetBinContent(i + 1) / nSumInWinB)); + subSampleV02[sampleIndex][3]->Fill(cent, fPtProfilePiInWinB->GetBinCenter(i + 1), threeParCorrPi); + subSampleV02[sampleIndex][4]->Fill(cent, fPtProfilePiInWinB->GetBinCenter(i + 1), (fPtProfilePiInWinB->GetBinContent(i + 1) / nSumInWinB)); } // kaons @@ -791,8 +1046,8 @@ struct V0ptHadPiKaProt { histos.get(HIST("Prof_XYZ_ka"))->Fill(cent, fPtProfileKaInWinB->GetBinCenter(i + 1), threeParCorrKa); histos.get(HIST("Prof_Z_ka"))->Fill(cent, fPtProfileKaInWinB->GetBinCenter(i + 1), (fPtProfileKaInWinB->GetBinContent(i + 1) / nSumInWinB)); - subSampleV02[sampleIndex][1]->Fill(cent, fPtProfileKaInWinB->GetBinCenter(i + 1), threeParCorrKa); - subSampleV02[sampleIndex][2]->Fill(cent, fPtProfileKaInWinB->GetBinCenter(i + 1), (fPtProfileKaInWinB->GetBinContent(i + 1) / nSumInWinB)); + subSampleV02[sampleIndex][5]->Fill(cent, fPtProfileKaInWinB->GetBinCenter(i + 1), threeParCorrKa); + subSampleV02[sampleIndex][6]->Fill(cent, fPtProfileKaInWinB->GetBinCenter(i + 1), (fPtProfileKaInWinB->GetBinContent(i + 1) / nSumInWinB)); } // protons @@ -802,8 +1057,8 @@ struct V0ptHadPiKaProt { histos.get(HIST("Prof_XYZ_prot"))->Fill(cent, fPtProfileProtInWinB->GetBinCenter(i + 1), threeParCorrProt); histos.get(HIST("Prof_Z_prot"))->Fill(cent, fPtProfileProtInWinB->GetBinCenter(i + 1), (fPtProfileProtInWinB->GetBinContent(i + 1) / nSumInWinB)); - subSampleV02[sampleIndex][1]->Fill(cent, fPtProfileProtInWinB->GetBinCenter(i + 1), threeParCorrProt); - subSampleV02[sampleIndex][2]->Fill(cent, fPtProfileProtInWinB->GetBinCenter(i + 1), (fPtProfileProtInWinB->GetBinContent(i + 1) / nSumInWinB)); + subSampleV02[sampleIndex][7]->Fill(cent, fPtProfileProtInWinB->GetBinCenter(i + 1), threeParCorrProt); + subSampleV02[sampleIndex][8]->Fill(cent, fPtProfileProtInWinB->GetBinCenter(i + 1), (fPtProfileProtInWinB->GetBinContent(i + 1) / nSumInWinB)); } } From 45d80d669421807fb011bdaf235c5cf5eef1334a Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 4 Mar 2026 16:26:35 +0100 Subject: [PATCH 163/347] [Infrastructure,PWGJE] Fix RECC vs PCH interference (#15255) --- PWGJE/Tasks/CMakeLists.txt | 2 ++ cmake/O2PhysicsAddWorkflow.cmake | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/PWGJE/Tasks/CMakeLists.txt b/PWGJE/Tasks/CMakeLists.txt index f05c735ef21..68fd3e9bdfb 100644 --- a/PWGJE/Tasks/CMakeLists.txt +++ b/PWGJE/Tasks/CMakeLists.txt @@ -11,6 +11,7 @@ add_library(JetSubstructureHFPCH OBJECT jetSubstructureHFPCH.cxx) target_link_libraries(JetSubstructureHFPCH PUBLIC O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore) +if(NOT DEFINED ENV{USE_RECC}) target_precompile_headers(JetSubstructureHFPCH PRIVATE [["PWGJE/DataModel/Jet.h"]] [["PWGJE/DataModel/JetSubstructure.h"]] @@ -25,6 +26,7 @@ target_precompile_headers(JetSubstructureHFPCH PRIVATE ) +endif() o2physics_add_dpl_workflow(emc-cellmonitor SOURCES emcCellMonitor.cxx diff --git a/cmake/O2PhysicsAddWorkflow.cmake b/cmake/O2PhysicsAddWorkflow.cmake index 39d98b2db76..d2d599c4406 100644 --- a/cmake/O2PhysicsAddWorkflow.cmake +++ b/cmake/O2PhysicsAddWorkflow.cmake @@ -47,7 +47,7 @@ function(o2physics_add_dpl_workflow baseTargetName) set_property(TARGET ${targetExeName} PROPERTY JOB_POOL_COMPILE analysis) set_property(TARGET ${targetExeName} PROPERTY JOB_POOL_LINK analysis) - if(A_REUSE_FROM) + if(A_REUSE_FROM AND NOT DEFINED ENV{USE_RECC}) target_precompile_headers(${targetExeName} REUSE_FROM ${A_REUSE_FROM}) endif() From 1d76185b1d0324ec4e22f2ab3535627c74a0e6fe Mon Sep 17 00:00:00 2001 From: Junlee Kim Date: Thu, 5 Mar 2026 01:14:12 +0800 Subject: [PATCH 164/347] [PWGLF] adding CentFT0CVariant2s (#15258) --- PWGLF/Tasks/Strangeness/lambdapolarization.cxx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/PWGLF/Tasks/Strangeness/lambdapolarization.cxx b/PWGLF/Tasks/Strangeness/lambdapolarization.cxx index 772b5d04e7f..e098bc622e4 100644 --- a/PWGLF/Tasks/Strangeness/lambdapolarization.cxx +++ b/PWGLF/Tasks/Strangeness/lambdapolarization.cxx @@ -63,7 +63,7 @@ using namespace o2::constants::physics; struct lambdapolarization { // using EventCandidates = soa::Filtered>; - using EventCandidates = soa::Join; + using EventCandidates = soa::Join; using TrackCandidates = soa::Join; using V0TrackCandidate = aod::V0Datas; @@ -84,6 +84,7 @@ struct lambdapolarization { Configurable cfgCentSel{"cfgCentSel", 80., "Centrality selection"}; Configurable cfgCentEst{"cfgCentEst", 1, "Centrality estimator, 1: FT0C, 2: FT0M"}; + Configurable cfgCentEstFT0CVariant2{"cfgCentEstFT0CVariant2", false, "flag to replace the estimator with centFT0CVariant2"}; Configurable cfgPVSel{"cfgPVSel", false, "Additional PV selection flag for syst"}; Configurable cfgPV{"cfgPV", 8.0, "Additional PV selection range for syst"}; @@ -918,6 +919,9 @@ struct lambdapolarization { { if (cfgCentEst == 1) { centrality = collision.centFT0C(); + if (cfgCentEstFT0CVariant2) { + centrality = collision.centFT0CVariant2(); + } } else if (cfgCentEst == 2) { centrality = collision.centFT0M(); } From 0616363eb1d271e90f18ff00e44010a854a88fe6 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Wed, 4 Mar 2026 18:47:36 +0100 Subject: [PATCH 165/347] [PWGEM/Dilepton] update muon analyses (#15260) --- PWGEM/Dilepton/DataModel/lmeeMLTables.h | 3 +- PWGEM/Dilepton/TableProducer/CMakeLists.txt | 5 + .../Converters/muonSelfIdConverter1.cxx | 2 +- .../TableProducer/skimmerPrimaryMuon.cxx | 2 +- .../TableProducer/skimmerPrimaryMuonQC.cxx | 788 ++++++++++++++++++ .../TableProducer/treeCreatorMuonML.cxx | 3 +- 6 files changed, 799 insertions(+), 4 deletions(-) create mode 100644 PWGEM/Dilepton/TableProducer/skimmerPrimaryMuonQC.cxx diff --git a/PWGEM/Dilepton/DataModel/lmeeMLTables.h b/PWGEM/Dilepton/DataModel/lmeeMLTables.h index 86a8ad1a7eb..9803a79ac62 100644 --- a/PWGEM/Dilepton/DataModel/lmeeMLTables.h +++ b/PWGEM/Dilepton/DataModel/lmeeMLTables.h @@ -140,7 +140,8 @@ DECLARE_SOA_TABLE_VERSIONED(EMFwdTracksForML_000, "AOD", "EMFWDTRKML", 0, //! fwdtrack::NClusters, fwdtrack::PDca, fwdtrack::RAtAbsorberEnd, fwdtrack::Chi2, fwdtrack::Chi2MatchMCHMID, fwdtrack::Chi2MatchMCHMFT, // fwdtrack::MCHBitMap, fwdtrack::MIDBitMap, fwdtrack::MIDBoards, - fwdtrack::MFTClusterSizesAndTrackFlags, emmlfwdtrack::Chi2MFT, emmlfwdtrack::NClustersMFT, mcparticle::PdgCode, emmlfwdtrack::IsPrimary, emmlfwdtrack::IsCorrectMatchMFTMCH); + fwdtrack::MFTClusterSizesAndTrackFlags, emmlfwdtrack::Chi2MFT, emmlfwdtrack::NClustersMFT, mcparticle::PdgCode, emmlfwdtrack::IsPrimary, emmlfwdtrack::IsCorrectMatchMFTMCH, + mcparticle::Pt, mcparticle::Eta, mcparticle::Phi); using EMFwdTracksForML = EMFwdTracksForML_000; // iterators diff --git a/PWGEM/Dilepton/TableProducer/CMakeLists.txt b/PWGEM/Dilepton/TableProducer/CMakeLists.txt index 109248797d6..dd7b21fa91f 100644 --- a/PWGEM/Dilepton/TableProducer/CMakeLists.txt +++ b/PWGEM/Dilepton/TableProducer/CMakeLists.txt @@ -41,6 +41,11 @@ o2physics_add_dpl_workflow(skimmer-primary-muon PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::GlobalTracking COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(skimmer-primary-muon-qc + SOURCES skimmerPrimaryMuonQC.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::GlobalTracking + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(skimmer-primary-track SOURCES skimmerPrimaryTrack.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore diff --git a/PWGEM/Dilepton/TableProducer/Converters/muonSelfIdConverter1.cxx b/PWGEM/Dilepton/TableProducer/Converters/muonSelfIdConverter1.cxx index fbfdcf5cd6f..abbbe47695a 100644 --- a/PWGEM/Dilepton/TableProducer/Converters/muonSelfIdConverter1.cxx +++ b/PWGEM/Dilepton/TableProducer/Converters/muonSelfIdConverter1.cxx @@ -39,5 +39,5 @@ struct muonSelfIdConverter1 { WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"muon-selfif-converter1"})}; + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"muon-selfid-converter1"})}; } diff --git a/PWGEM/Dilepton/TableProducer/skimmerPrimaryMuon.cxx b/PWGEM/Dilepton/TableProducer/skimmerPrimaryMuon.cxx index 80747036f22..bba65c5e5d7 100644 --- a/PWGEM/Dilepton/TableProducer/skimmerPrimaryMuon.cxx +++ b/PWGEM/Dilepton/TableProducer/skimmerPrimaryMuon.cxx @@ -171,7 +171,7 @@ struct skimmerPrimaryMuon { hMuonType->GetXaxis()->SetBinLabel(4, "MCH-MID"); hMuonType->GetXaxis()->SetBinLabel(5, "MCH standalone"); - fRegistry.add("MFTMCHMID/hPt", "pT;p_{T} (GeV/c)", kTH1F, {{100, 0.0f, 10}}, false); + fRegistry.add("MFTMCHMID/hPt", "pT;p_{T} (GeV/c)", kTH1F, {{200, 0.0f, 10}}, false); fRegistry.add("MFTMCHMID/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{180, 0, 2 * M_PI}, {80, -4.f, -2.f}}, false); fRegistry.add("MFTMCHMID/hEtaPhi_MatchedMCHMID", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{180, 0, 2 * M_PI}, {80, -4.f, -2.f}}, false); fRegistry.add("MFTMCHMID/hDeltaPt_Pt", "#Deltap_{T}/p_{T} vs. p_{T};p_{T}^{gl} (GeV/c);(p_{T}^{sa} - p_{T}^{gl})/p_{T}^{gl}", kTH2F, {{100, 0, 10}, {200, -0.5, +0.5}}, false); diff --git a/PWGEM/Dilepton/TableProducer/skimmerPrimaryMuonQC.cxx b/PWGEM/Dilepton/TableProducer/skimmerPrimaryMuonQC.cxx new file mode 100644 index 00000000000..3ad5171301c --- /dev/null +++ b/PWGEM/Dilepton/TableProducer/skimmerPrimaryMuonQC.cxx @@ -0,0 +1,788 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \brief write relevant information for muons. +/// \author daiki.sekihata@cern.ch + +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" + +#include "Common/Core/TableHelper.h" +#include "Common/Core/fwdtrackUtilities.h" +#include "Common/DataModel/CollisionAssociationTables.h" + +#include "CCDB/BasicCCDBManager.h" +#include "CommonConstants/PhysicsConstants.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DetectorsBase/Propagator.h" +#include "Field/MagneticField.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/DataTypes.h" +#include "Framework/runDataProcessing.h" +#include "GlobalTracking/MatchGlobalFwd.h" +#include "MCHTracking/TrackExtrap.h" +#include "MCHTracking/TrackParam.h" +#include "ReconstructionDataFormats/TrackFwd.h" + +#include "Math/SMatrix.h" +#include "Math/Vector4D.h" +#include "TGeoGlobalMagField.h" + +#include +#include +#include +#include + +using namespace o2; +using namespace o2::soa; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::constants::physics; +using namespace o2::aod::fwdtrackutils; + +struct skimmerPrimaryMuonQC { + using MyCollisions = soa::Join; + using MyCollisionsWithSWT = soa::Join; + + using MyFwdTracks = soa::Join; // muon tracks are repeated. i.e. not exclusive. + using MyFwdTrack = MyFwdTracks::iterator; + + using MyFwdTracksMC = soa::Join; + using MyFwdTrackMC = MyFwdTracksMC::iterator; + + using MFTTracksMC = soa::Join; + using MFTTrackMC = MFTTracksMC::iterator; + + Produces emprimarymuons; + Produces emprimarymuonscov; + + // Configurables + Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + Configurable geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; + Configurable fillQAHistograms{"fillQAHistograms", false, "flag to fill QA histograms"}; + + // for z shift for propagation + Configurable cfgApplyZShiftFromCCDB{"cfgApplyZShiftFromCCDB", false, "flag to apply z shift"}; + Configurable cfgZShiftPath{"cfgZShiftPath", "Users/m/mcoquet/ZShift", "CCDB path for z shift to apply to forward tracks"}; + Configurable cfgManualZShift{"cfgManualZShift", 0, "manual z-shift for propagation of global muon to PV"}; + Configurable matchingZ{"matchingZ", -77.5, "z position where matching is performed"}; + Configurable refitGlobalMuon{"refitGlobalMuon", true, "flag to refit global muon"}; + + struct : ConfigurableGroup { // tight cut + std::string prefix = "tagMuonCut"; + Configurable minPt{"minPt", 0.8, "min pt for muon"}; + Configurable maxPt{"maxPt", 1e+10, "max pt for muon"}; + Configurable minEta{"minEta", -3.6, "min. eta acceptance for MFT-MCH-MID"}; + Configurable maxEta{"maxEta", -2.5, "max. eta acceptance for MFT-MCH-MID"}; + Configurable minRabs{"minRabs", 27.6, "min. R at absorber end for global muon (min. eta = -3.6)"}; // std::tan(2.f * std::atan(std::exp(- -3.6)) ) * -505. = 27.6 + Configurable maxRabs{"maxRabs", 89.5, "max. R at absorber end"}; + Configurable maxDCAxy{"maxDCAxy", 0.06, "max. DCAxy for global muons"}; + Configurable maxMatchingChi2MCHMFT{"maxMatchingChi2MCHMFT", 40.f, "max. chi2 for MCH-MFT matching"}; + Configurable maxChi2{"maxChi2", 4.f, "max. chi2/ndf for global muon"}; + // Configurable minNclsMFT{"minNclsMFT", 5, "min ncluster of MFT"}; + // Configurable minNclsMCH{"minNclsMCH", 5, "min ncluster of MCH"}; + Configurable maxDEta{"maxDEta", 0.08, "max. deta between MFT-MCH-MID and MCH-MID"}; + Configurable maxDPhi{"maxDPhi", 0.08, "max. dphi between MFT-MCH-MID and MCH-MID"}; + } tagMuonCut; + + struct : ConfigurableGroup { // loose cut + std::string prefix = "probeMuonCut"; + Configurable minPt{"minPt", 0.01, "min pt for muon"}; + Configurable maxPt{"maxPt", 1e+10, "max pt for muon"}; + Configurable minEtaSA{"minEtaSA", -4.0, "min. eta acceptance for MFT-MCH"}; + Configurable maxEtaSA{"maxEtaSA", -2.5, "max. eta acceptance for MFT-MCH"}; + Configurable minEtaGL{"minEtaGL", -3.6, "min. eta acceptance for MFT-MCH-MID"}; + Configurable maxEtaGL{"maxEtaGL", -2.5, "max. eta acceptance for MFT-MCH-MID"}; + Configurable minRabs{"minRabs", 17.6, "min. R at absorber end for global muon (min. eta = -3.6)"}; // std::tan(2.f * std::atan(std::exp(- -3.6)) ) * -505. = 27.6 + Configurable midRabs{"midRabs", 26.5, "middle R at absorber end for pDCA cut"}; + Configurable maxRabs{"maxRabs", 89.5, "max. R at absorber end"}; + Configurable maxDCAxy{"maxDCAxy", 1.f, "max. DCAxy for global muons"}; + Configurable maxPDCAforLargeR{"maxPDCAforLargeR", 324.f, "max. pDCA for large R at absorber end"}; + Configurable maxPDCAforSmallR{"maxPDCAforSmallR", 594.f, "max. pDCA for small R at absorber end"}; + Configurable maxMatchingChi2MCHMFT{"maxMatchingChi2MCHMFT", 100, "max. chi2 for MCH-MFT matching"}; + Configurable maxChi2{"maxChi2", 1e+10, "max. chi2/ndf for global muon"}; + // Configurable minNclsMFT{"minNclsMFT", 5, "min ncluster of MFT"}; + // Configurable minNclsMCH{"minNclsMCH", 5, "min ncluster of MCH"}; + Configurable maxDEta{"maxDEta", 1e+10, "max. deta between MFT-MCH-MID and MCH-MID"}; + Configurable maxDPhi{"maxDPhi", 1e+10, "max. dphi between MFT-MCH-MID and MCH-MID"}; + } probeMuonCut; + + struct : ConfigurableGroup { + std::string prefix = "pairCuts"; + Configurable minMass{"minMass", 0.21, "min mass"}; + Configurable maxMass{"maxMass", 0.30, "max mass"}; + } pairCuts; + + o2::ccdb::CcdbApi ccdbApi; + Service ccdb; + int mRunNumber = 0; + float mBz = 0; + float mZShift = 0; + + HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; + // static constexpr std::string_view muon_types[5] = {"MFTMCHMID/", "MFTMCHMIDOtherMatch/", "MFTMCH/", "MCHMID/", "MCH/"}; + + void init(InitContext&) + { + ccdb->setURL(ccdburl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + ccdbApi.init(ccdburl); + + if (fillQAHistograms) { + addHistograms(); + } + mRunNumber = 0; + mBz = 0; + mZShift = 0; + } + + void initCCDB(aod::BCsWithTimestamps::iterator const& bc) + { + if (mRunNumber == bc.runNumber()) { + return; + } + mRunNumber = bc.runNumber(); + + std::map metadata; + auto soreor = o2::ccdb::BasicCCDBManager::getRunDuration(ccdbApi, mRunNumber); + auto ts = soreor.first; + auto grpmag = ccdbApi.retrieveFromTFileAny(grpmagPath, metadata, ts); + o2::base::Propagator::initFieldFromGRP(grpmag); + if (!o2::base::GeometryManager::isGeometryLoaded()) { + ccdb->get(geoPath); + } + o2::mch::TrackExtrap::setField(); + const double centerMFT[3] = {0, 0, -61.4}; + o2::field::MagneticField* field = static_cast(TGeoGlobalMagField::Instance()->GetField()); + mBz = field->getBz(centerMFT); // Get field at centre of MFT + LOGF(info, "Bz at center of MFT = %f kZG", mBz); + + if (cfgApplyZShiftFromCCDB) { + auto* zShift = ccdb->getForTimeStamp>(cfgZShiftPath, bc.timestamp()); + if (zShift != nullptr && !zShift->empty()) { + LOGF(info, "reading z shift %f from %s", (*zShift)[0], cfgZShiftPath.value); + mZShift = (*zShift)[0]; + } else { + LOGF(info, "z shift is not found in ccdb path %s. set to 0 cm", cfgZShiftPath.value); + mZShift = 0; + } + } else { + LOGF(info, "z shift is manually set to %f cm", cfgManualZShift.value); + mZShift = cfgManualZShift; + } + } + + void addHistograms() + { + // auto hMuonType = fRegistry.add("hMuonType", "muon type", kTH1F, {{5, -0.5f, 4.5f}}, false); + // hMuonType->GetXaxis()->SetBinLabel(1, "MFT-MCH-MID (global muon)"); + // hMuonType->GetXaxis()->SetBinLabel(2, "MFT-MCH-MID (global muon other match)"); + // hMuonType->GetXaxis()->SetBinLabel(3, "MFT-MCH"); + // hMuonType->GetXaxis()->SetBinLabel(4, "MCH-MID"); + // hMuonType->GetXaxis()->SetBinLabel(5, "MCH standalone"); + + // fRegistry.add("MFTMCHMID/hPt", "pT;p_{T} (GeV/c)", kTH1F, {{200, 0.0f, 10}}, false); + // fRegistry.add("MFTMCHMID/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{180, 0, 2 * M_PI}, {80, -4.f, -2.f}}, false); + // fRegistry.add("MFTMCHMID/hEtaPhi_MatchedMCHMID", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{180, 0, 2 * M_PI}, {80, -4.f, -2.f}}, false); + // fRegistry.add("MFTMCHMID/hDeltaPt_Pt", "#Deltap_{T}/p_{T} vs. p_{T};p_{T}^{gl} (GeV/c);(p_{T}^{sa} - p_{T}^{gl})/p_{T}^{gl}", kTH2F, {{100, 0, 10}, {200, -0.5, +0.5}}, false); + // fRegistry.add("MFTMCHMID/hDeltaEta_Pt", "#Delta#eta vs. p_{T};p_{T}^{gl} (GeV/c);#Delta#eta", kTH2F, {{100, 0, 10}, {200, -0.5, +0.5}}, false); + // fRegistry.add("MFTMCHMID/hDeltaPhi_Pt", "#Delta#varphi vs. p_{T};p_{T}^{gl} (GeV/c);#Delta#varphi (rad.)", kTH2F, {{100, 0, 10}, {200, -0.5, +0.5}}, false); + // fRegistry.add("MFTMCHMID/hSign", "sign;sign", kTH1F, {{3, -1.5, +1.5}}, false); + // fRegistry.add("MFTMCHMID/hNclusters", "Nclusters;Nclusters", kTH1F, {{21, -0.5f, 20.5}}, false); + // fRegistry.add("MFTMCHMID/hNclustersMFT", "NclustersMFT;Nclusters MFT", kTH1F, {{11, -0.5f, 10.5}}, false); + // fRegistry.add("MFTMCHMID/hRatAbsorberEnd", "R at absorber end;R at absorber end (cm)", kTH1F, {{100, 0.0f, 100}}, false); + // fRegistry.add("MFTMCHMID/hPDCA_Rabs", "pDCA vs. Rabs;R at absorber end (cm);p #times DCA (GeV/c #upoint cm)", kTH2F, {{100, 0, 100}, {100, 0.0f, 1000}}, false); + // fRegistry.add("MFTMCHMID/hChi2", "chi2;chi2/ndf", kTH1F, {{200, 0.0f, 20}}, false); + // fRegistry.add("MFTMCHMID/hChi2MFT", "chi2 MFT;chi2 MFT/ndf", kTH1F, {{200, 0.0f, 20}}, false); + // fRegistry.add("MFTMCHMID/hChi2MatchMCHMID", "chi2 match MCH-MID;chi2", kTH1F, {{200, 0.0f, 20}}, false); + // fRegistry.add("MFTMCHMID/hChi2MatchMCHMFT", "chi2 match MCH-MFT;chi2", kTH1F, {{200, 0.0f, 100}}, false); + // fRegistry.add("MFTMCHMID/hDCAxy2D", "DCA x vs. y;DCA_{x} (cm);DCA_{y} (cm)", kTH2F, {{200, -1, 1}, {200, -1, +1}}, false); + // fRegistry.add("MFTMCHMID/hDCAxy2DinSigma", "DCA x vs. y in sigma;DCA_{x} (#sigma);DCA_{y} (#sigma)", kTH2F, {{200, -10, 10}, {200, -10, +10}}, false); + // fRegistry.add("MFTMCHMID/hDCAxy", "DCAxy;DCA_{xy} (cm);", kTH1F, {{100, 0, 1}}, false); + // fRegistry.add("MFTMCHMID/hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", kTH2F, {{100, 0, 1}, {200, -0.1, 0.1}}, false); + // fRegistry.add("MFTMCHMID/hDCAxyinSigma", "DCAxy in sigma;DCA_{xy} (#sigma);", kTH1F, {{100, 0, 10}}, false); + // fRegistry.add("MFTMCHMID/hDCAx_PosZ", "DCAx vs. posZ;Z_{vtx} (cm);DCA_{x} (cm)", kTH2F, {{200, -10, +10}, {400, -0.2, +0.2}}, false); + // fRegistry.add("MFTMCHMID/hDCAy_PosZ", "DCAy vs. posZ;Z_{vtx} (cm);DCA_{y} (cm)", kTH2F, {{200, -10, +10}, {400, -0.2, +0.2}}, false); + // fRegistry.add("MFTMCHMID/hDCAx_Phi", "DCAx vs. #varphi;#varphi (rad.);DCA_{x} (cm)", kTH2F, {{90, 0, 2 * M_PI}, {400, -0.2, +0.2}}, false); + // fRegistry.add("MFTMCHMID/hDCAy_Phi", "DCAy vs. #varphi;#varphi (rad.);DCA_{y} (cm)", kTH2F, {{90, 0, 2 * M_PI}, {400, -0.2, +0.2}}, false); + // fRegistry.add("MFTMCHMID/hNmu", "#mu multiplicity;N_{#mu} per collision", kTH1F, {{21, -0.5, 20.5}}, false); + + // fRegistry.addClone("MFTMCHMID/", "MCHMID/"); + // fRegistry.add("MFTMCHMID/hDCAxResolutionvsPt", "DCA_{x} vs. p_{T};p_{T} (GeV/c);DCA_{x} resolution (#mum);", kTH2F, {{100, 0, 10.f}, {500, 0, 500}}, false); + // fRegistry.add("MFTMCHMID/hDCAyResolutionvsPt", "DCA_{y} vs. p_{T};p_{T} (GeV/c);DCA_{y} resolution (#mum);", kTH2F, {{100, 0, 10.f}, {500, 0, 500}}, false); + // fRegistry.add("MFTMCHMID/hDCAxyResolutionvsPt", "DCA_{xy} vs. p_{T};p_{T} (GeV/c);DCA_{y} resolution (#mum);", kTH2F, {{100, 0, 10.f}, {500, 0, 500}}, false); + // fRegistry.add("MCHMID/hDCAxResolutionvsPt", "DCA_{x} vs. p_{T};p_{T} (GeV/c);DCA_{x} resolution (#mum);", kTH2F, {{100, 0, 10.f}, {500, 0, 5e+5}}, false); + // fRegistry.add("MCHMID/hDCAyResolutionvsPt", "DCA_{y} vs. p_{T};p_{T} (GeV/c);DCA_{y} resolution (#mum);", kTH2F, {{100, 0, 10.f}, {500, 0, 5e+5}}, false); + // fRegistry.add("MCHMID/hDCAxyResolutionvsPt", "DCA_{xy} vs. p_{T};p_{T} (GeV/c);DCA_{y} resolution (#mum);", kTH2F, {{100, 0, 10.f}, {500, 0, 5e+5}}, false); + + fRegistry.add("Pair/uls/gl_gl/hMvsPt", "dimuon;m_{#mu#mu} (GeV/c^{2});p_{T,#mu} (GeV/c);", kTH2F, {{380, 0.2, 4.f}, {100, 0, 10}}, false); + fRegistry.add("Pair/uls/gl_sa/hMvsPt", "dimuon;m_{#mu#mu} (GeV/c^{2});p_{T,#mu} (GeV/c);", kTH2F, {{380, 0.2, 4.f}, {100, 0, 10}}, false); + } + + struct Muon { + int globalIndex = -1; + int collisionId = -1; + int matchMCHTrackId = -1; + int matchMFTTrackId = -1; + uint8_t trackType = 99; + int8_t sign = 0; + float pt = 0; + float eta = 0; + float phi = 0; + float dcaX = 0; // in cm + float dcaY = 0; // in cm + float dcaXY = 0; // in cm + float cXX = 0; + float cYY = 0; + float cXY = 0; + float rAtAbsorberEnd = 0; + float pDCA = 0; + float chi2ndf = 0; + float chi2MatchMCHMID = 0; + + // only for global muons + float ptMatchedMCHMID = 0; + float etaMatchedMCHMID = 0; + float phiMatchedMCHMID = 0; + float chi2MatchMCHMFT = 0; + float chi2mft = -999.f; + uint64_t mftClusterSizesAndTrackFlags = 0; + }; + + bool isSelected(Muon const& muon) + { + if (muon.pt < probeMuonCut.minPt || probeMuonCut.maxPt < muon.pt) { + return false; + } + + if (muon.rAtAbsorberEnd < probeMuonCut.minRabs || probeMuonCut.maxRabs < muon.rAtAbsorberEnd) { + return false; + } + + if (muon.trackType == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack)) { + if (muon.eta < probeMuonCut.minEtaGL || probeMuonCut.maxEtaGL < muon.eta) { + return false; + } + if (probeMuonCut.maxDCAxy < muon.dcaXY) { + return false; + } + if (probeMuonCut.maxMatchingChi2MCHMFT < muon.chi2MatchMCHMFT) { + return false; + } + } else if (muon.trackType == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack)) { + if (muon.eta < probeMuonCut.minEtaSA || probeMuonCut.maxEtaSA < muon.eta) { + return false; + } + if (muon.rAtAbsorberEnd < probeMuonCut.midRabs ? muon.pDCA > probeMuonCut.maxPDCAforSmallR : muon.pDCA > probeMuonCut.maxPDCAforLargeR) { + return false; + } + } else { + return false; + } + + return true; + } + + bool isSelectedTight(Muon const& muon) + { + if (muon.trackType != static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack)) { // tag muon should be tight. + return false; + } + + if (muon.pt < tagMuonCut.minPt || tagMuonCut.maxPt < muon.pt) { + return false; + } + + if (muon.rAtAbsorberEnd < tagMuonCut.minRabs || tagMuonCut.maxRabs < muon.rAtAbsorberEnd) { + return false; + } + + if (muon.chi2ndf < 0.f || tagMuonCut.maxChi2 < muon.chi2ndf) { + return false; + } + + if (muon.eta < tagMuonCut.minEta || tagMuonCut.maxEta < muon.eta) { + return false; + } + + if (tagMuonCut.maxDCAxy < muon.dcaXY) { + return false; + } + + if (tagMuonCut.maxMatchingChi2MCHMFT < muon.chi2MatchMCHMFT) { + return false; + } + + float deta = muon.etaMatchedMCHMID - muon.eta; + float dphi = muon.phiMatchedMCHMID - muon.phi; + // LOGF(info, "muon.trackType = %d, deta = %f, dphi = %f", muon.trackType, deta, dphi); + if (std::sqrt(std::pow(deta / tagMuonCut.maxDEta, 2) + std::pow(dphi / tagMuonCut.maxDPhi, 2)) > 1.f) { + return false; + } + + return true; + } + + template + bool fillMuonInfo(TCollision const& collision, TFwdTrack fwdtrack) + { + if (fwdtrack.trackType() != static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) && fwdtrack.trackType() != static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack)) { + return false; + } + + if (fwdtrack.chi2MatchMCHMID() < 0.f) { // this should never happen. only for protection. + return false; + } + + if (fwdtrack.chi2() < 0.f) { // this should never happen. only for protection. + return false; + } + + o2::dataformats::GlobalFwdTrack propmuonAtPV = propagateMuon(fwdtrack, fwdtrack, collision, propagationPoint::kToVertex, matchingZ, mBz, mZShift); + float pt = propmuonAtPV.getPt(); + float eta = propmuonAtPV.getEta(); + float phi = propmuonAtPV.getPhi(); + o2::math_utils::bringTo02Pi(phi); + + float dcaX = propmuonAtPV.getX() - collision.posX(); + float dcaY = propmuonAtPV.getY() - collision.posY(); + float dcaXY = std::sqrt(dcaX * dcaX + dcaY * dcaY); + float rAtAbsorberEnd = fwdtrack.rAtAbsorberEnd(); // this works only for GlobalMuonTrack + float cXX = propmuonAtPV.getSigma2X(); + float cYY = propmuonAtPV.getSigma2Y(); + float cXY = propmuonAtPV.getSigmaXY(); + + float pDCA = propmuonAtPV.getP() * dcaXY; + int nClustersMFT = 0; + float ptMatchedMCHMID = propmuonAtPV.getPt(); + float etaMatchedMCHMID = propmuonAtPV.getEta(); + float phiMatchedMCHMID = propmuonAtPV.getPhi(); + o2::math_utils::bringTo02Pi(phiMatchedMCHMID); + float chi2mft = -999.f; + uint64_t mftClusterSizesAndTrackFlags = 0; + int ndf_mchmft = 1; + + if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { + if (fwdtrack.chi2MatchMCHMFT() < 0.f) { + return false; + } // Users have to decide the best match between MFT and MCH-MID at analysis level. The same global muon is repeatedly stored. + + auto mchtrack = fwdtrack.template matchMCHTrack_as(); // MCH-MID + auto mfttrack = fwdtrack.template matchMFTTrack_as(); // MFTsa + if (mfttrack.chi2() < 0.f) { + return false; + } + + if constexpr (isMC) { + if (!mfttrack.has_mcParticle() || !mchtrack.has_mcParticle() || !fwdtrack.has_mcParticle()) { + return false; + } + // auto mcParticle_MFTMCHMID = fwdtrack.template mcParticle_as(); // this is identical to mcParticle_MCHMID + auto mcParticle_MCHMID = mchtrack.template mcParticle_as(); // this is identical to mcParticle_MFTMCHMID + auto mcParticle_MFT = mfttrack.template mcParticle_as(); + } + + nClustersMFT = mfttrack.nClusters(); + mftClusterSizesAndTrackFlags = mfttrack.mftClusterSizesAndTrackFlags(); + ndf_mchmft = 2.f * (mchtrack.nClusters() + nClustersMFT) - 5.f; + chi2mft = mfttrack.chi2(); + + o2::dataformats::GlobalFwdTrack propmuonAtPV_Matched = propagateMuon(mchtrack, mchtrack, collision, propagationPoint::kToVertex, matchingZ, mBz, mZShift); + ptMatchedMCHMID = propmuonAtPV_Matched.getPt(); + etaMatchedMCHMID = propmuonAtPV_Matched.getEta(); + phiMatchedMCHMID = propmuonAtPV_Matched.getPhi(); + o2::math_utils::bringTo02Pi(phiMatchedMCHMID); + + o2::dataformats::GlobalFwdTrack propmuonAtDCA_Matched = propagateMuon(mchtrack, mchtrack, collision, propagationPoint::kToDCA, matchingZ, mBz, mZShift); + float dcaX_Matched = propmuonAtDCA_Matched.getX() - collision.posX(); + float dcaY_Matched = propmuonAtDCA_Matched.getY() - collision.posY(); + float dcaXY_Matched = std::sqrt(dcaX_Matched * dcaX_Matched + dcaY_Matched * dcaY_Matched); + pDCA = mchtrack.p() * dcaXY_Matched; + + if (refitGlobalMuon) { + pt = propmuonAtPV_Matched.getP() * std::sin(2.f * std::atan(std::exp(-eta))); + } + } else if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { + o2::dataformats::GlobalFwdTrack propmuonAtRabs = propagateMuon(fwdtrack, fwdtrack, collision, propagationPoint::kToRabs, matchingZ, mBz, mZShift); // this is necessary only for MuonStandaloneTrack + float xAbs = propmuonAtRabs.getX(); + float yAbs = propmuonAtRabs.getY(); + rAtAbsorberEnd = std::sqrt(xAbs * xAbs + yAbs * yAbs); // Redo propagation only for muon tracks // propagation of MFT tracks alredy done in reconstruction + ndf_mchmft = 1; // chi2 is already normalized by ndf for MCH-MID tracks. + + o2::dataformats::GlobalFwdTrack propmuonAtDCA = propagateMuon(fwdtrack, fwdtrack, collision, propagationPoint::kToDCA, matchingZ, mBz, mZShift); + cXX = propmuonAtDCA.getSigma2X(); + cYY = propmuonAtDCA.getSigma2Y(); + cXY = propmuonAtDCA.getSigmaXY(); + dcaX = propmuonAtDCA.getX() - collision.posX(); + dcaY = propmuonAtDCA.getY() - collision.posY(); + dcaXY = std::sqrt(dcaX * dcaX + dcaY * dcaY); + pDCA = fwdtrack.p() * dcaXY; + } else { + return false; + } + + Muon muon; + muon.globalIndex = fwdtrack.globalIndex(); + muon.collisionId = collision.globalIndex(); + muon.trackType = fwdtrack.trackType(); + muon.sign = fwdtrack.sign(); + muon.pt = pt; + muon.eta = eta; + muon.phi = phi; + muon.dcaX = dcaX; + muon.dcaY = dcaY; + muon.dcaXY = dcaXY; + muon.cXX = cXX; + muon.cYY = cYY; + muon.cXY = cXY; + muon.rAtAbsorberEnd = rAtAbsorberEnd; + muon.pDCA = pDCA; + muon.chi2ndf = fwdtrack.chi2() / ndf_mchmft; + muon.ptMatchedMCHMID = ptMatchedMCHMID; + muon.etaMatchedMCHMID = etaMatchedMCHMID; + muon.phiMatchedMCHMID = phiMatchedMCHMID; + muon.chi2mft = chi2mft; + muon.matchMCHTrackId = fwdtrack.matchMCHTrackId(); + muon.matchMFTTrackId = fwdtrack.matchMFTTrackId(); + muon.mftClusterSizesAndTrackFlags = mftClusterSizesAndTrackFlags; + + vecMuons.emplace_back(muon); + return true; + } + + template + bool fillFwdTrackTable(TCollision const& collision, TMuon const& muon, TFwdTrack const& fwdtrack) + { + emprimarymuons(collision.globalIndex(), fwdtrack.globalIndex(), fwdtrack.matchMFTTrackId(), fwdtrack.matchMCHTrackId(), fwdtrack.trackType(), + muon.pt, muon.eta, muon.phi, fwdtrack.sign(), muon.dcaX, muon.dcaY, muon.cXX, muon.cYY, muon.cXY, muon.ptMatchedMCHMID, muon.etaMatchedMCHMID, muon.phiMatchedMCHMID, + fwdtrack.nClusters(), muon.pDCA, muon.rAtAbsorberEnd, fwdtrack.chi2(), fwdtrack.chi2MatchMCHMID(), fwdtrack.chi2MatchMCHMFT(), + fwdtrack.mchBitMap(), fwdtrack.midBitMap(), fwdtrack.midBoards(), muon.mftClusterSizesAndTrackFlags, muon.chi2mft, true, false); + + // if (fillQAHistograms) { + // fRegistry.fill(HIST("hMuonType"), fwdtrack.trackType()); + // if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { + // fRegistry.fill(HIST("MFTMCHMID/hPt"), pt); + // fRegistry.fill(HIST("MFTMCHMID/hEtaPhi"), phi, eta); + // fRegistry.fill(HIST("MFTMCHMID/hEtaPhi_MatchedMCHMID"), phiMatchedMCHMID, etaMatchedMCHMID); + // fRegistry.fill(HIST("MFTMCHMID/hDeltaPt_Pt"), pt, dpt); + // fRegistry.fill(HIST("MFTMCHMID/hDeltaEta_Pt"), pt, deta); + // fRegistry.fill(HIST("MFTMCHMID/hDeltaPhi_Pt"), pt, dphi); + // fRegistry.fill(HIST("MFTMCHMID/hSign"), fwdtrack.sign()); + // fRegistry.fill(HIST("MFTMCHMID/hNclusters"), fwdtrack.nClusters()); + // fRegistry.fill(HIST("MFTMCHMID/hNclustersMFT"), nClustersMFT); + // fRegistry.fill(HIST("MFTMCHMID/hPDCA_Rabs"), rAtAbsorberEnd, pDCA); + // fRegistry.fill(HIST("MFTMCHMID/hRatAbsorberEnd"), rAtAbsorberEnd); + // fRegistry.fill(HIST("MFTMCHMID/hChi2"), fwdtrack.chi2() / ndf_mchmft); + // fRegistry.fill(HIST("MFTMCHMID/hChi2MFT"), chi2mft / ndf_mft); + // fRegistry.fill(HIST("MFTMCHMID/hChi2MatchMCHMID"), fwdtrack.chi2MatchMCHMID()); + // fRegistry.fill(HIST("MFTMCHMID/hChi2MatchMCHMFT"), fwdtrack.chi2MatchMCHMFT()); + // fRegistry.fill(HIST("MFTMCHMID/hDCAxy2D"), dcaX, dcaY); + // fRegistry.fill(HIST("MFTMCHMID/hDCAxy2DinSigma"), dcaX / std::sqrt(cXX), dcaY / std::sqrt(cYY)); + // fRegistry.fill(HIST("MFTMCHMID/hDCAxy"), dcaXY); + // fRegistry.fill(HIST("MFTMCHMID/hDCAxyz"), dcaXY, dcaZ); + // fRegistry.fill(HIST("MFTMCHMID/hDCAxyinSigma"), dcaXYinSigma); + // fRegistry.fill(HIST("MFTMCHMID/hDCAxResolutionvsPt"), pt, std::sqrt(cXX) * 1e+4); // convert cm to um + // fRegistry.fill(HIST("MFTMCHMID/hDCAyResolutionvsPt"), pt, std::sqrt(cYY) * 1e+4); // convert cm to um + // fRegistry.fill(HIST("MFTMCHMID/hDCAxyResolutionvsPt"), pt, sigma_dcaXY * 1e+4); // convert cm to um + // fRegistry.fill(HIST("MFTMCHMID/hDCAx_PosZ"), collision.posZ(), dcaX); + // fRegistry.fill(HIST("MFTMCHMID/hDCAy_PosZ"), collision.posZ(), dcaY); + // fRegistry.fill(HIST("MFTMCHMID/hDCAx_Phi"), phi, dcaX); + // fRegistry.fill(HIST("MFTMCHMID/hDCAy_Phi"), phi, dcaY); + // } else if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { + // fRegistry.fill(HIST("MCHMID/hPt"), pt); + // fRegistry.fill(HIST("MCHMID/hEtaPhi"), phi, eta); + // fRegistry.fill(HIST("MCHMID/hEtaPhi_MatchedMCHMID"), phiMatchedMCHMID, etaMatchedMCHMID); + // fRegistry.fill(HIST("MCHMID/hDeltaPt_Pt"), pt, dpt); + // fRegistry.fill(HIST("MCHMID/hDeltaEta_Pt"), pt, deta); + // fRegistry.fill(HIST("MCHMID/hDeltaPhi_Pt"), pt, dphi); + // fRegistry.fill(HIST("MCHMID/hSign"), fwdtrack.sign()); + // fRegistry.fill(HIST("MCHMID/hNclusters"), fwdtrack.nClusters()); + // fRegistry.fill(HIST("MCHMID/hNclustersMFT"), nClustersMFT); + // fRegistry.fill(HIST("MCHMID/hPDCA_Rabs"), rAtAbsorberEnd, pDCA); + // fRegistry.fill(HIST("MCHMID/hRatAbsorberEnd"), rAtAbsorberEnd); + // fRegistry.fill(HIST("MCHMID/hChi2"), fwdtrack.chi2()); + // fRegistry.fill(HIST("MCHMID/hChi2MFT"), chi2mft / ndf_mft); + // fRegistry.fill(HIST("MCHMID/hChi2MatchMCHMID"), fwdtrack.chi2MatchMCHMID()); + // fRegistry.fill(HIST("MCHMID/hChi2MatchMCHMFT"), fwdtrack.chi2MatchMCHMFT()); + // fRegistry.fill(HIST("MCHMID/hDCAxy2D"), dcaX, dcaY); + // fRegistry.fill(HIST("MCHMID/hDCAxy2DinSigma"), dcaX / std::sqrt(cXX), dcaY / std::sqrt(cYY)); + // fRegistry.fill(HIST("MCHMID/hDCAxy"), dcaXY); + // fRegistry.fill(HIST("MCHMID/hDCAxyz"), dcaXY, dcaZ); + // fRegistry.fill(HIST("MCHMID/hDCAxyinSigma"), dcaXYinSigma); + // fRegistry.fill(HIST("MCHMID/hDCAxResolutionvsPt"), pt, std::sqrt(cXX) * 1e+4); // convert cm to um + // fRegistry.fill(HIST("MCHMID/hDCAyResolutionvsPt"), pt, std::sqrt(cYY) * 1e+4); // convert cm to um + // fRegistry.fill(HIST("MCHMID/hDCAxyResolutionvsPt"), pt, sigma_dcaXY * 1e+4); // convert cm to um + // } + // } + return true; + } + + SliceCache cache; + Preslice perCollision = o2::aod::fwdtrack::collisionId; + Preslice fwdtrackIndicesPerCollision = aod::track_association::collisionId; + PresliceUnsorted fwdtrackIndicesPerFwdTrack = aod::track_association::fwdtrackId; + PresliceUnsorted fwdtracksPerMCHTrack = aod::fwdtrack::matchMCHTrackId; + + // Filter trackFilter = o2::aod::fwdtrack::trackType == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) || o2::aod::fwdtrack::trackType == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack); + // using filteredMyFwdTracks = soa::Filtered; + // Partition posTracks = o2::aod::fwdtrack::signed1Pt > 0.f; + // Partition negTracks = o2::aod::fwdtrack::signed1Pt < 0.f; + + std::vector vecMuons; + + void processRec(MyCollisions const& collisions, MyFwdTracks const& fwdtracks, aod::MFTTracks const&, aod::BCsWithTimestamps const&) + { + vecMuons.reserve(fwdtracks.size()); + + for (const auto& collision : collisions) { + auto bc = collision.template bc_as(); + initCCDB(bc); + + if (!collision.isSelected()) { + continue; + } + + auto fwdtracks_per_coll = fwdtracks.sliceBy(perCollision, collision.globalIndex()); + for (const auto& fwdtrack : fwdtracks_per_coll) { + fillMuonInfo(collision, fwdtrack); + } + + auto pos_muons_per_col = std::views::filter(vecMuons, [](Muon muon) { return muon.sign > 0; }); + auto neg_muons_per_col = std::views::filter(vecMuons, [](Muon muon) { return muon.sign < 0; }); + + // ULS + for (const auto& pos : pos_muons_per_col) { + if (!isSelectedTight(pos)) { // pos is tag, neg is probe + continue; + } + for (const auto& neg : neg_muons_per_col) { + if (!isSelected(neg)) { + continue; + } + ROOT::Math::PtEtaPhiMVector v1(pos.pt, pos.eta, pos.phi, o2::constants::physics::MassMuon); // tag + ROOT::Math::PtEtaPhiMVector v2(neg.pt, neg.eta, neg.phi, o2::constants::physics::MassMuon); // probe + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + if (neg.trackType == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack)) { + if (pos.matchMCHTrackId == neg.matchMCHTrackId || pos.matchMFTTrackId == neg.matchMFTTrackId) { // this should not happen in ULS. only for protection. + continue; + } + fRegistry.fill(HIST("Pair/uls/gl_gl/hMvsPt"), v12.M(), v2.Pt()); + } else if (neg.trackType == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack)) { + if (pos.matchMCHTrackId == neg.globalIndex) { // this should not happen in ULS. only for protection. + continue; + } + fRegistry.fill(HIST("Pair/uls/gl_sa/hMvsPt"), v12.M(), v2.Pt()); + } + if (pairCuts.minMass < v12.M() && v12.M() < pairCuts.maxMass) { + fillFwdTrackTable(collision, neg, fwdtracks.rawIteratorAt(neg.globalIndex)); + } + } // end of neg + } // end of pos + + // ULS + for (const auto& neg : neg_muons_per_col) { + if (!isSelectedTight(neg)) { // neg is tag, pos is probe + continue; + } + for (const auto& pos : pos_muons_per_col) { + if (!isSelected(pos)) { + continue; + } + ROOT::Math::PtEtaPhiMVector v1(neg.pt, neg.eta, neg.phi, o2::constants::physics::MassMuon); // tag + ROOT::Math::PtEtaPhiMVector v2(pos.pt, pos.eta, pos.phi, o2::constants::physics::MassMuon); // probe + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + if (pos.trackType == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack)) { + if (pos.matchMCHTrackId == neg.matchMCHTrackId || pos.matchMFTTrackId == neg.matchMFTTrackId) { // this should not happen in ULS. only for protection. + continue; + } + fRegistry.fill(HIST("Pair/uls/gl_gl/hMvsPt"), v12.M(), v2.Pt()); + } else if (pos.trackType == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack)) { + if (neg.matchMCHTrackId == pos.globalIndex) { // this should not happen in ULS. only for protection. + continue; + } + fRegistry.fill(HIST("Pair/uls/gl_sa/hMvsPt"), v12.M(), v2.Pt()); + } + if (pairCuts.minMass < v12.M() && v12.M() < pairCuts.maxMass) { + fillFwdTrackTable(collision, pos, fwdtracks.rawIteratorAt(pos.globalIndex)); + } + } // end of pos + } // end of neg + + } // end of collision loop + + vecMuons.clear(); + vecMuons.shrink_to_fit(); + } + PROCESS_SWITCH(skimmerPrimaryMuonQC, processRec, "process reconstructed info", false); + + void processRec_SWT(MyCollisionsWithSWT const& collisions, MyFwdTracks const& fwdtracks, aod::MFTTracks const&, aod::BCsWithTimestamps const&) + { + vecMuons.reserve(fwdtracks.size()); + + for (const auto& collision : collisions) { + const auto& bc = collision.template bc_as(); + initCCDB(bc); + + if (!collision.isSelected()) { + continue; + } + + if (collision.swtaliastmp_raw() == 0) { + continue; + } + + // const auto& fwdtracks_per_coll = fwdtracks.sliceBy(perCollision, collision.globalIndex()); + // for (const auto& fwdtrack : fwdtracks_per_coll) { + // if (fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { + // continue; + // } + + // if (!fillFwdTrackTable(collision, fwdtrack, false)) { + // continue; + // } + + // } // end of fwdtrack loop + } // end of collision loop + + vecMuons.clear(); + vecMuons.shrink_to_fit(); + } + PROCESS_SWITCH(skimmerPrimaryMuonQC, processRec_SWT, "process reconstructed info only with standalone", false); + + using filteredMyFwdTracksMC = soa::Filtered; + void processMC(soa::Join const& collisions, MyFwdTracksMC const& fwdtracks, MFTTracksMC const&, aod::BCsWithTimestamps const&, aod::McParticles const&) + { + vecMuons.reserve(fwdtracks.size()); + + for (const auto& collision : collisions) { + auto bc = collision.template bc_as(); + initCCDB(bc); + if (!collision.isSelected()) { + continue; + } + if (!collision.has_mcCollision()) { + continue; + } + + // auto fwdtracks_per_coll = fwdtracks.sliceBy(perCollision, collision.globalIndex()); + // for (const auto& fwdtrack : fwdtracks_per_coll) { + // if (!fwdtrack.has_mcParticle()) { + // continue; + // } + // if (fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { + // continue; + // } + + // if (!fillFwdTrackTable(collision, fwdtrack, false)) { + // continue; + // } + + // } // end of fwdtrack loop + } // end of collision loop + + vecMuons.clear(); + vecMuons.shrink_to_fit(); + } + PROCESS_SWITCH(skimmerPrimaryMuonQC, processMC, "process reconstructed and MC info", false); + + void processDummy(aod::Collisions const&) {} + PROCESS_SWITCH(skimmerPrimaryMuonQC, processDummy, "process dummy", true); +}; +struct associateAmbiguousMuon { + Produces em_amb_muon_ids; + + SliceCache cache; + PresliceUnsorted perTrack = o2::aod::emprimarymuon::fwdtrackId; + std::vector ambmuon_self_Ids; + + void process(aod::EMPrimaryMuons const& muons) + { + for (const auto& muon : muons) { + auto muons_with_same_trackId = muons.sliceBy(perTrack, muon.fwdtrackId()); + ambmuon_self_Ids.reserve(muons_with_same_trackId.size()); + for (const auto& amb_muon : muons_with_same_trackId) { + if (amb_muon.globalIndex() == muon.globalIndex()) { // don't store myself. + continue; + } + ambmuon_self_Ids.emplace_back(amb_muon.globalIndex()); + } + em_amb_muon_ids(ambmuon_self_Ids); + ambmuon_self_Ids.clear(); + ambmuon_self_Ids.shrink_to_fit(); + } + } +}; + +struct associateSameMuonElement { + Produces glmuon_same_ids; + + SliceCache cache; + PresliceUnsorted perMFTTrack = o2::aod::emprimarymuon::mfttrackId; + PresliceUnsorted perMCHTrack = o2::aod::emprimarymuon::mchtrackId; + std::vector selfIds_per_MFT; + std::vector selfIds_per_MCHMID; + + // Multiple MCH-MID tracks can match with the same MFTsa. This function is to reject such global muons. + void process(aod::EMPrimaryMuons const& muons) + { + for (const auto& muon : muons) { + if (muon.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { + auto muons_with_same_mfttrackId = muons.sliceBy(perMFTTrack, muon.mfttrackId()); + auto muons_with_same_mchtrackId = muons.sliceBy(perMCHTrack, muon.mchtrackId()); + selfIds_per_MFT.reserve(muons_with_same_mfttrackId.size()); + selfIds_per_MCHMID.reserve(muons_with_same_mchtrackId.size()); + // LOGF(info, "muons_with_same_mchtrackId.size() = %d, muons_with_same_mfttrackId.size() = %d", muons_with_same_mchtrackId.size(), muons_with_same_mfttrackId.size()); + + for (const auto& global_muon : muons_with_same_mfttrackId) { + // LOGF(info, "same MFT: global_muon.globalIndex() = %d, global_muon.mchtrackId() = %d, global_muon.mfttrackId() = %d, global_muon.collisionId() = %d", global_muon.globalIndex(), global_muon.mchtrackId(), global_muon.mfttrackId(), global_muon.collisionId()); + if (global_muon.globalIndex() == muon.globalIndex()) { // don't store myself. + continue; + } + if (global_muon.collisionId() == muon.collisionId()) { // the same global muon is repeatedly stored and associated to different collisions if FTTCA is used. + selfIds_per_MFT.emplace_back(global_muon.globalIndex()); + } + } + + for (const auto& global_muon : muons_with_same_mchtrackId) { + // LOGF(info, "same MCH: global_muon.globalIndex() = %d, global_muon.mchtrackId() = %d, global_muon.mfttrackId() = %d, global_muon.collisionId() = %d", global_muon.globalIndex(), global_muon.mchtrackId(), global_muon.mfttrackId(), global_muon.collisionId()); + if (global_muon.globalIndex() == muon.globalIndex()) { // don't store myself. + continue; + } + if (global_muon.collisionId() == muon.collisionId()) { // the same global muon is repeatedly stored and associated to different collisions if FTTCA is used. + selfIds_per_MCHMID.emplace_back(global_muon.globalIndex()); + } + } + + glmuon_same_ids(selfIds_per_MCHMID, selfIds_per_MFT); + selfIds_per_MFT.clear(); + selfIds_per_MFT.shrink_to_fit(); + selfIds_per_MCHMID.clear(); + selfIds_per_MCHMID.shrink_to_fit(); + } else { + glmuon_same_ids(std::vector{}, std::vector{}); // empty for standalone muons + selfIds_per_MFT.clear(); + selfIds_per_MFT.shrink_to_fit(); + selfIds_per_MCHMID.clear(); + selfIds_per_MCHMID.shrink_to_fit(); + } + } // end of muon loop + } +}; +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc, TaskName{"skimmer-primary-muon-qc"}), + adaptAnalysisTask(cfgc, TaskName{"associate-ambiguous-muon"}), + adaptAnalysisTask(cfgc, TaskName{"associate-same-muon-element"})}; +} diff --git a/PWGEM/Dilepton/TableProducer/treeCreatorMuonML.cxx b/PWGEM/Dilepton/TableProducer/treeCreatorMuonML.cxx index 8415711a1dc..ed35f705f3a 100644 --- a/PWGEM/Dilepton/TableProducer/treeCreatorMuonML.cxx +++ b/PWGEM/Dilepton/TableProducer/treeCreatorMuonML.cxx @@ -350,7 +350,8 @@ struct TreeCreatorMuonML { xMatchedMCHMIDatMP, yMatchedMCHMIDatMP, xMatchedMFTatMP, yMatchedMFTatMP, fwdtrack.nClusters(), pDCA, rAtAbsorberEnd, chi2, fwdtrack.chi2MatchMCHMID(), fwdtrack.chi2MatchMCHMFT(), // fwdtrack.mchBitMap(), fwdtrack.midBitMap(), fwdtrack.midBoards(), - mfttrack.mftClusterSizesAndTrackFlags(), chi2mft, mfttrack.nClusters(), pdgCode, isPrimary, isMatched); + mfttrack.mftClusterSizesAndTrackFlags(), chi2mft, mfttrack.nClusters(), pdgCode, isPrimary, isMatched, + mcParticle_MCHMID.pt(), mcParticle_MCHMID.eta(), mcParticle_MCHMID.phi()); fRegistry.fill(HIST("hMuonType"), fwdtrack.trackType()); fRegistry.fill(HIST("MFTMCHMID/hPt"), pt); From b15cbdfbb6382eea27ebbb167e8f81a6b886b9f4 Mon Sep 17 00:00:00 2001 From: Mingze Li Date: Wed, 4 Mar 2026 18:51:32 +0100 Subject: [PATCH 166/347] [PWGHF] taskCharmPolarisation: Fill in the absolute vale of the rapidity (#15224) --- PWGHF/D2H/Tasks/taskCharmPolarisation.cxx | 208 +++++++++++----------- 1 file changed, 104 insertions(+), 104 deletions(-) diff --git a/PWGHF/D2H/Tasks/taskCharmPolarisation.cxx b/PWGHF/D2H/Tasks/taskCharmPolarisation.cxx index 4d02b0068a1..573a5ca3fcf 100644 --- a/PWGHF/D2H/Tasks/taskCharmPolarisation.cxx +++ b/PWGHF/D2H/Tasks/taskCharmPolarisation.cxx @@ -791,19 +791,19 @@ struct HfTaskCharmPolarisation { if constexpr (Channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ if (activateTrackingSys) { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + registry.fill(HIST("hRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); } else { - registry.fill(HIST("hPartRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + registry.fill(HIST("hPartRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); } } else { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons); + registry.fill(HIST("hRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons); } else { - registry.fill(HIST("hPartRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons); + registry.fill(HIST("hPartRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons); } } } else if constexpr (Channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ - registry.fill(HIST("hRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); + registry.fill(HIST("hRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassKPiLc, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); if (activateTHnEulerPhiMonitor) { registry.fill(HIST("hRecPromptEulerPhiHelicity"), invMassCharmHad, ptCharmHad, invMassKPiLc, phiEuler, outputMl[0], /*outputMl[1],*/ outputMl[2], resoChannelLc, charge); } @@ -812,19 +812,19 @@ struct HfTaskCharmPolarisation { if constexpr (Channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ if (activateTrackingSys) { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + registry.fill(HIST("hRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); } else { - registry.fill(HIST("hPartRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + registry.fill(HIST("hPartRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); } } else { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, ptBhadMother); + registry.fill(HIST("hRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, ptBhadMother); } else { - registry.fill(HIST("hPartRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, ptBhadMother); + registry.fill(HIST("hPartRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, ptBhadMother); } } } else if constexpr (Channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ - registry.fill(HIST("hRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); + registry.fill(HIST("hRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassKPiLc, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); if (activateTHnEulerPhiMonitor) { registry.fill(HIST("hRecNonPromptEulerPhiHelicity"), invMassCharmHad, ptCharmHad, invMassKPiLc, phiEuler, outputMl[0], /*outputMl[1],*/ outputMl[2], resoChannelLc, charge); } @@ -835,19 +835,19 @@ struct HfTaskCharmPolarisation { if constexpr (Channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ if (activateTrackingSys) { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + registry.fill(HIST("hRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons); } else { - registry.fill(HIST("hPartRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + registry.fill(HIST("hPartRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons); } } else { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, nMuons); + registry.fill(HIST("hRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, nMuons); } else { - registry.fill(HIST("hPartRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, nMuons); + registry.fill(HIST("hPartRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, nMuons); } } } else if constexpr (Channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ - registry.fill(HIST("hRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); + registry.fill(HIST("hRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassKPiLc, cosThetaStar, resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); if (activateTHnEulerPhiMonitor) { registry.fill(HIST("hRecPromptEulerPhiHelicity"), invMassCharmHad, ptCharmHad, invMassKPiLc, phiEuler, resoChannelLc, charge); } @@ -856,19 +856,19 @@ struct HfTaskCharmPolarisation { if constexpr (Channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ if (activateTrackingSys) { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + registry.fill(HIST("hRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); } else { - registry.fill(HIST("hPartRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + registry.fill(HIST("hPartRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); } } else { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, nMuons, ptBhadMother); + registry.fill(HIST("hRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, nMuons, ptBhadMother); } else { - registry.fill(HIST("hPartRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, nMuons, ptBhadMother); + registry.fill(HIST("hPartRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, nMuons, ptBhadMother); } } } else if constexpr (Channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ - registry.fill(HIST("hRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); + registry.fill(HIST("hRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassKPiLc, cosThetaStar, resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); if (activateTHnEulerPhiMonitor) { registry.fill(HIST("hRecNonPromptEulerPhiHelicity"), invMassCharmHad, ptCharmHad, invMassKPiLc, phiEuler, resoChannelLc, charge); } @@ -927,19 +927,19 @@ struct HfTaskCharmPolarisation { if constexpr (Channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ if (activateTrackingSys) { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + registry.fill(HIST("hRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); } else { - registry.fill(HIST("hPartRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + registry.fill(HIST("hPartRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); } } else { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons); + registry.fill(HIST("hRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons); } else { - registry.fill(HIST("hPartRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons); + registry.fill(HIST("hPartRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons); } } } else if constexpr (Channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ - registry.fill(HIST("hRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); + registry.fill(HIST("hRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassKPiLc, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); if (activateTHnEulerPhiMonitor) { registry.fill(HIST("hRecPromptEulerPhiProduction"), invMassCharmHad, ptCharmHad, invMassKPiLc, phiEuler, outputMl[0], /*outputMl[1],*/ outputMl[2], resoChannelLc, charge); } @@ -948,19 +948,19 @@ struct HfTaskCharmPolarisation { if constexpr (Channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ if (activateTrackingSys) { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + registry.fill(HIST("hRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); } else { - registry.fill(HIST("hPartRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + registry.fill(HIST("hPartRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); } } else { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, ptBhadMother); + registry.fill(HIST("hRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, ptBhadMother); } else { - registry.fill(HIST("hPartRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, ptBhadMother); + registry.fill(HIST("hPartRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, ptBhadMother); } } } else if constexpr (Channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ - registry.fill(HIST("hRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); + registry.fill(HIST("hRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassKPiLc, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); if (activateTHnEulerPhiMonitor) { registry.fill(HIST("hRecNonPromptEulerPhiProduction"), invMassCharmHad, ptCharmHad, invMassKPiLc, phiEuler, outputMl[0], /*outputMl[1],*/ outputMl[2], resoChannelLc, charge); } @@ -971,19 +971,19 @@ struct HfTaskCharmPolarisation { if constexpr (Channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ if (activateTrackingSys) { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + registry.fill(HIST("hRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons); } else { - registry.fill(HIST("hPartRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + registry.fill(HIST("hPartRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons); } } else { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, nMuons); + registry.fill(HIST("hRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, nMuons); } else { - registry.fill(HIST("hPartRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, nMuons); + registry.fill(HIST("hPartRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, nMuons); } } } else if constexpr (Channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ - registry.fill(HIST("hRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); + registry.fill(HIST("hRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassKPiLc, cosThetaStar, resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); if (activateTHnEulerPhiMonitor) { registry.fill(HIST("hRecPromptEulerPhiProduction"), invMassCharmHad, ptCharmHad, invMassKPiLc, phiEuler, resoChannelLc, charge); } @@ -992,19 +992,19 @@ struct HfTaskCharmPolarisation { if constexpr (Channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ if (activateTrackingSys) { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + registry.fill(HIST("hRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); } else { - registry.fill(HIST("hPartRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + registry.fill(HIST("hPartRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); } } else { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, nMuons, ptBhadMother); + registry.fill(HIST("hRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, nMuons, ptBhadMother); } else { - registry.fill(HIST("hPartRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, nMuons, ptBhadMother); + registry.fill(HIST("hPartRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, nMuons, ptBhadMother); } } } else if constexpr (Channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ - registry.fill(HIST("hRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); + registry.fill(HIST("hRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassKPiLc, cosThetaStar, resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); if (activateTHnEulerPhiMonitor) { registry.fill(HIST("hRecNonPromptEulerPhiProduction"), invMassCharmHad, ptCharmHad, invMassKPiLc, phiEuler, resoChannelLc, charge); } @@ -1063,19 +1063,19 @@ struct HfTaskCharmPolarisation { if constexpr (Channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ if (activateTrackingSys) { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + registry.fill(HIST("hRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); } else { - registry.fill(HIST("hPartRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + registry.fill(HIST("hPartRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); } } else { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons); + registry.fill(HIST("hRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons); } else { - registry.fill(HIST("hPartRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons); + registry.fill(HIST("hPartRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons); } } } else if constexpr (Channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ - registry.fill(HIST("hRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); + registry.fill(HIST("hRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassKPiLc, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); if (activateTHnEulerPhiMonitor) { registry.fill(HIST("hRecPromptEulerPhiBeam"), invMassCharmHad, ptCharmHad, invMassKPiLc, phiEuler, outputMl[0], /*outputMl[1],*/ outputMl[2], resoChannelLc, charge); } @@ -1084,19 +1084,19 @@ struct HfTaskCharmPolarisation { if constexpr (Channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ if (activateTrackingSys) { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + registry.fill(HIST("hRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); } else { - registry.fill(HIST("hPartRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + registry.fill(HIST("hPartRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); } } else { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, ptBhadMother); + registry.fill(HIST("hRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, ptBhadMother); } else { - registry.fill(HIST("hPartRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, ptBhadMother); + registry.fill(HIST("hPartRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, ptBhadMother); } } } else if constexpr (Channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ - registry.fill(HIST("hRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); + registry.fill(HIST("hRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassKPiLc, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); if (activateTHnEulerPhiMonitor) { registry.fill(HIST("hRecNonPromptEulerPhiBeam"), invMassCharmHad, ptCharmHad, invMassKPiLc, phiEuler, outputMl[0], /*outputMl[1],*/ outputMl[2], resoChannelLc, charge); } @@ -1107,19 +1107,19 @@ struct HfTaskCharmPolarisation { if constexpr (Channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ if (activateTrackingSys) { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + registry.fill(HIST("hRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons); } else { - registry.fill(HIST("hPartRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + registry.fill(HIST("hPartRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons); } } else { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, nMuons); + registry.fill(HIST("hRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, nMuons); } else { - registry.fill(HIST("hPartRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, nMuons); + registry.fill(HIST("hPartRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, nMuons); } } } else if constexpr (Channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ - registry.fill(HIST("hRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); + registry.fill(HIST("hRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassKPiLc, cosThetaStar, resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); if (activateTHnEulerPhiMonitor) { registry.fill(HIST("hRecPromptEulerPhiBeam"), invMassCharmHad, ptCharmHad, invMassKPiLc, phiEuler, resoChannelLc, charge); } @@ -1128,19 +1128,19 @@ struct HfTaskCharmPolarisation { if constexpr (Channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ if (activateTrackingSys) { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + registry.fill(HIST("hRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); } else { - registry.fill(HIST("hPartRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + registry.fill(HIST("hPartRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); } } else { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, nMuons, ptBhadMother); + registry.fill(HIST("hRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, nMuons, ptBhadMother); } else { - registry.fill(HIST("hPartRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, nMuons, ptBhadMother); + registry.fill(HIST("hPartRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, nMuons, ptBhadMother); } } } else if constexpr (Channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ - registry.fill(HIST("hRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); + registry.fill(HIST("hRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassKPiLc, cosThetaStar, resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); if (activateTHnEulerPhiMonitor) { registry.fill(HIST("hRecNonPromptEulerPhiBeam"), invMassCharmHad, ptCharmHad, invMassKPiLc, phiEuler, resoChannelLc, charge); } @@ -1193,59 +1193,59 @@ struct HfTaskCharmPolarisation { if constexpr (Channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ if (activateTrackingSys) { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + registry.fill(HIST("hRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); } else { - registry.fill(HIST("hPartRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + registry.fill(HIST("hPartRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); } } else { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons); + registry.fill(HIST("hRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons); } else { - registry.fill(HIST("hPartRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons); + registry.fill(HIST("hPartRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons); } } } else if constexpr (Channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ - registry.fill(HIST("hRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); + registry.fill(HIST("hRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassKPiLc, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); } } else { // non-prompt if constexpr (Channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ if (activateTrackingSys) { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + registry.fill(HIST("hRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); } else { - registry.fill(HIST("hPartRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + registry.fill(HIST("hPartRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); } } else { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, ptBhadMother); + registry.fill(HIST("hRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, ptBhadMother); } else { - registry.fill(HIST("hPartRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, ptBhadMother); + registry.fill(HIST("hPartRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, ptBhadMother); } } } else if constexpr (Channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ - registry.fill(HIST("hRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); + registry.fill(HIST("hRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassKPiLc, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); } } } else { // without ML if (origin == RecoDecay::OriginType::Prompt) { // prompt if constexpr (Channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ if (!isPartRecoDstar) { - registry.fill(HIST("hRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + registry.fill(HIST("hRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons); } else { - registry.fill(HIST("hPartRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + registry.fill(HIST("hPartRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons); } } else if constexpr (Channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ - registry.fill(HIST("hRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); + registry.fill(HIST("hRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassKPiLc, cosThetaStar, resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); } } else { // non-prompt if constexpr (Channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ if (!isPartRecoDstar) { - registry.fill(HIST("hRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + registry.fill(HIST("hRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); } else { - registry.fill(HIST("hPartRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + registry.fill(HIST("hPartRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); } } else if constexpr (Channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ - registry.fill(HIST("hRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); + registry.fill(HIST("hRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassKPiLc, cosThetaStar, resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); } } } @@ -1291,15 +1291,15 @@ struct HfTaskCharmPolarisation { if constexpr (Channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ if (activateTrackingSys) { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoPromptEP"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + registry.fill(HIST("hRecoPromptEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); } else { - registry.fill(HIST("hPartRecoPromptEP"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + registry.fill(HIST("hPartRecoPromptEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); } } else { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoPromptEP"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons); + registry.fill(HIST("hRecoPromptEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons); } else { - registry.fill(HIST("hPartRecoPromptEP"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons); + registry.fill(HIST("hPartRecoPromptEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons); } } } @@ -1307,15 +1307,15 @@ struct HfTaskCharmPolarisation { if constexpr (Channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ if (activateTrackingSys) { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoNonPromptEP"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + registry.fill(HIST("hRecoNonPromptEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); } else { - registry.fill(HIST("hPartRecoNonPromptEP"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + registry.fill(HIST("hPartRecoNonPromptEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); } } else { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoNonPromptEP"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, ptBhadMother); + registry.fill(HIST("hRecoNonPromptEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, ptBhadMother); } else { - registry.fill(HIST("hPartRecoNonPromptEP"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, ptBhadMother); + registry.fill(HIST("hPartRecoNonPromptEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, ptBhadMother); } } } @@ -1340,71 +1340,71 @@ struct HfTaskCharmPolarisation { if constexpr (CosThetaStarType == charm_polarisation::CosThetaStarType::Helicity) { // Helicity if (origin == RecoDecay::OriginType::Prompt) { // prompt if (!isPartRecoDstar) { - registry.fill(HIST("hGenPromptHelicity"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, areDausInAcc, resoChannelLc, charge); + registry.fill(HIST("hGenPromptHelicity"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, areDausInAcc, resoChannelLc, charge); } else { - registry.fill(HIST("hGenPartRecoPromptHelicity"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, areDausInAcc, resoChannelLc, charge); + registry.fill(HIST("hGenPartRecoPromptHelicity"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, areDausInAcc, resoChannelLc, charge); } } else { // non-prompt if (!isPartRecoDstar) { - registry.fill(HIST("hGenNonPromptHelicity"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); + registry.fill(HIST("hGenNonPromptHelicity"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); } else { - registry.fill(HIST("hGenPartRecoNonPromptHelicity"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); + registry.fill(HIST("hGenPartRecoNonPromptHelicity"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); } } } else if constexpr (CosThetaStarType == charm_polarisation::CosThetaStarType::Production) { // Production if (origin == RecoDecay::OriginType::Prompt) { // prompt if (!isPartRecoDstar) { - registry.fill(HIST("hGenPromptProduction"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, areDausInAcc, resoChannelLc, charge); + registry.fill(HIST("hGenPromptProduction"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, areDausInAcc, resoChannelLc, charge); } else { - registry.fill(HIST("hGenPartRecoPromptProduction"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, areDausInAcc, resoChannelLc, charge); + registry.fill(HIST("hGenPartRecoPromptProduction"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, areDausInAcc, resoChannelLc, charge); } } else { // non-prompt if (!isPartRecoDstar) { - registry.fill(HIST("hGenNonPromptProduction"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); + registry.fill(HIST("hGenNonPromptProduction"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); } else { - registry.fill(HIST("hGenPartRecoNonPromptProduction"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); + registry.fill(HIST("hGenPartRecoNonPromptProduction"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); } } } else if constexpr (CosThetaStarType == charm_polarisation::CosThetaStarType::Beam) { // Beam if (origin == RecoDecay::OriginType::Prompt) { // prompt if (!isPartRecoDstar) { - registry.fill(HIST("hGenPromptBeam"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, areDausInAcc, resoChannelLc, charge); + registry.fill(HIST("hGenPromptBeam"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, areDausInAcc, resoChannelLc, charge); } else { - registry.fill(HIST("hGenPartRecoPromptBeam"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, areDausInAcc, resoChannelLc, charge); + registry.fill(HIST("hGenPartRecoPromptBeam"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, areDausInAcc, resoChannelLc, charge); } } else { // non-prompt if (!isPartRecoDstar) { - registry.fill(HIST("hGenNonPromptBeam"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); + registry.fill(HIST("hGenNonPromptBeam"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); } else { - registry.fill(HIST("hGenPartRecoNonPromptBeam"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); + registry.fill(HIST("hGenPartRecoNonPromptBeam"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); } } } else if constexpr (CosThetaStarType == charm_polarisation::CosThetaStarType::Random) { // Random if (origin == RecoDecay::OriginType::Prompt) { // prompt if (!isPartRecoDstar) { - registry.fill(HIST("hGenPromptRandom"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, areDausInAcc, resoChannelLc, charge); + registry.fill(HIST("hGenPromptRandom"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, areDausInAcc, resoChannelLc, charge); } else { - registry.fill(HIST("hGenPartRecoPromptRandom"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, areDausInAcc, resoChannelLc, charge); + registry.fill(HIST("hGenPartRecoPromptRandom"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, areDausInAcc, resoChannelLc, charge); } } else { // non-prompt if (!isPartRecoDstar) { - registry.fill(HIST("hGenNonPromptRandom"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); + registry.fill(HIST("hGenNonPromptRandom"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); } else { - registry.fill(HIST("hGenPartRecoNonPromptRandom"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); + registry.fill(HIST("hGenPartRecoNonPromptRandom"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); } } } else if constexpr (CosThetaStarType == charm_polarisation::CosThetaStarType::EP) { // EP if (origin == RecoDecay::OriginType::Prompt) { // prompt if (!isPartRecoDstar) { - registry.fill(HIST("hGenPromptEP"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, areDausInAcc, resoChannelLc, charge); + registry.fill(HIST("hGenPromptEP"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, areDausInAcc, resoChannelLc, charge); } else { - registry.fill(HIST("hGenPartRecoPromptEP"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, areDausInAcc, resoChannelLc, charge); + registry.fill(HIST("hGenPartRecoPromptEP"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, areDausInAcc, resoChannelLc, charge); } } else { // non-prompt if (!isPartRecoDstar) { - registry.fill(HIST("hGenNonPromptEP"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); + registry.fill(HIST("hGenNonPromptEP"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); } else { - registry.fill(HIST("hGenPartRecoNonPromptEP"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); + registry.fill(HIST("hGenPartRecoNonPromptEP"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); } } } From 47af0a22df46f480f0ec3abf14cf2a656b45d1a0 Mon Sep 17 00:00:00 2001 From: ilikmeta <152337132+ilikmeta@users.noreply.github.com> Date: Wed, 4 Mar 2026 15:45:19 -0600 Subject: [PATCH 167/347] [PWGCF] Apply Global+ITS only tracks (#15262) Co-authored-by: ALICE Action Bot --- PWGCF/Flow/Tasks/flowGfwTask.cxx | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/PWGCF/Flow/Tasks/flowGfwTask.cxx b/PWGCF/Flow/Tasks/flowGfwTask.cxx index de1c2989a2c..e0c6616828d 100644 --- a/PWGCF/Flow/Tasks/flowGfwTask.cxx +++ b/PWGCF/Flow/Tasks/flowGfwTask.cxx @@ -82,7 +82,7 @@ struct FlowGfwTask { O2_DEFINE_CONFIGURABLE(cfgCutDCAz, float, 2.0f, "Custom DCA Z cut") O2_DEFINE_CONFIGURABLE(cfgCutDCAxy, float, 1.0f, "Custom DCA XY cut") O2_DEFINE_CONFIGURABLE(cfgNbootstrap, int, 10, "Number of subsamples") - O2_DEFINE_CONFIGURABLE(cfgCentEstFt0c, bool, false, "Centrality estimator based on FT0C signal") + O2_DEFINE_CONFIGURABLE(cfgCentEstFt0c, bool, true, "Centrality estimator based on FT0C signal") O2_DEFINE_CONFIGURABLE(cfgCentEstFt0a, bool, false, "Centrality estimator based on FT0A signal") O2_DEFINE_CONFIGURABLE(cfgCentEstFt0m, bool, false, " A centrality estimator based on FT0A+FT0C signals.") O2_DEFINE_CONFIGURABLE(cfgCentEstFv0a, bool, false, "Centrality estimator based on FV0A signal") @@ -93,20 +93,20 @@ struct FlowGfwTask { O2_DEFINE_CONFIGURABLE(cfgMagnetField, std::string, "GLO/Config/GRPMagField", "CCDB path to Magnet field object") O2_DEFINE_CONFIGURABLE(cfgDCAzPt, bool, false, "switch for DCAz pt dependent") O2_DEFINE_CONFIGURABLE(cfgTrackSelRun3ITSMatch, bool, false, "Track selection for ITS matches") - O2_DEFINE_CONFIGURABLE(cfgUseAdditionalEventCut, bool, false, "Use additional event cut on mult correlations") - O2_DEFINE_CONFIGURABLE(cfgUseAdditionalTrackCut, bool, false, "Use additional track cut on phi") + O2_DEFINE_CONFIGURABLE(cfgUseAdditionalEventCut, bool, true, "Use additional event cut on mult correlations") + O2_DEFINE_CONFIGURABLE(cfgUseAdditionalTrackCut, bool, true, "Use additional track cut on phi") O2_DEFINE_CONFIGURABLE(cfgOccupancy, bool, false, "Bool for event selection on detector occupancy"); O2_DEFINE_CONFIGURABLE(cfgNoTimeFrameBorder, bool, false, "kNoTimeFrameBorder"); O2_DEFINE_CONFIGURABLE(cfgNoITSROFrameBorder, bool, false, "kNoITSROFrameBorder"); O2_DEFINE_CONFIGURABLE(cfgNoSameBunchPileup, bool, false, "kNoSameBunchPileup"); O2_DEFINE_CONFIGURABLE(cfgIsGoodZvtxFT0vsPV, bool, false, "kIsGoodZvtxFT0vsPV"); - O2_DEFINE_CONFIGURABLE(cfgIsVertexITSTPC, bool, false, "kIsVertexITSTPC"); + O2_DEFINE_CONFIGURABLE(cfgIsVertexITSTPC, bool, true, "kIsVertexITSTPC"); O2_DEFINE_CONFIGURABLE(cfgNoCollInTimeRangeStandard, bool, false, "kNoCollInTimeRangeStandard"); O2_DEFINE_CONFIGURABLE(cfgEvSelkIsGoodITSLayersAll, bool, false, "kIsGoodITSLayersAll") O2_DEFINE_CONFIGURABLE(cfgMultCut, bool, false, "Use additional event cut on mult correlations"); O2_DEFINE_CONFIGURABLE(cfgV0AT0ANSigma, bool, false, "V0A T0A n sigma cut") O2_DEFINE_CONFIGURABLE(cfgNSigma, float, 5.0f, "N sigma cut") - O2_DEFINE_CONFIGURABLE(cfgGlobalTracks, bool, false, "Global tracks") + O2_DEFINE_CONFIGURABLE(cfgGlobalTracks, bool, true, "Global tracks") O2_DEFINE_CONFIGURABLE(cfgGlobalplusITS, bool, false, "Global and ITS tracks") O2_DEFINE_CONFIGURABLE(cfgGlobalonly, bool, false, "Global only tracks") O2_DEFINE_CONFIGURABLE(cfgITSonly, bool, false, "ITS only tracks") @@ -894,9 +894,15 @@ struct FlowGfwTask { } } - // Apply process filters GlobalTracks + // Apply process filters Global+ITS_only sample Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex && (aod::cent::centFT0C > cfgMinCentFT0C) && (aod::cent::centFT0C < cfgMaxCentFT0C); - Filter trackFilter = ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)) && (nabs(aod::track::eta) < cfgCutEta) && (aod::track::pt > cfgCutPtMin) && (aod::track::pt < cfgCutPtMax) && (nabs(aod::track::dcaZ) < cfgCutDCAz) && (nabs(aod::track::dcaXY) < cfgCutDCAxy); + Filter trackFilter = ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) && + ncheckbit(aod::track::trackCutFlag, TrackSelectionITS) && + ifnode(ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::TPC), + ncheckbit(aod::track::trackCutFlag, TrackSelectionTPC), true) && + ifnode(dcaZ > 0.f, nabs(aod::track::dcaZ) <= dcaZ && ncheckbit(aod::track::trackCutFlag, TrackSelectionDCAXYonly), + ncheckbit(aod::track::trackCutFlag, TrackSelectionDCA)) && + (nabs(aod::track::eta) < cfgCutEta) && (aod::track::pt > cfgCutPtMin) && (aod::track::pt < cfgCutPtMax) && (nabs(aod::track::dcaZ) < cfgCutDCAz) && (nabs(aod::track::dcaXY) < cfgCutDCAxy); void processData(Colls::iterator const& collision, aod::BCsWithTimestamps const&, AodTracks const& tracks, aod::FT0s const&, BCsRun3 const&) { @@ -1239,7 +1245,7 @@ struct FlowGfwTask { } } // End of process - PROCESS_SWITCH(FlowGfwTask, processData, "Process analysis for Run 3 data", false); + PROCESS_SWITCH(FlowGfwTask, processData, "Process analysis for Run 3 data", true); using TheFilteredMyTracks = soa::Filtered; using TheFilteredMyCollisions = soa::Filtered; From 393deac7922a26f49d98693cd60f03032e709238 Mon Sep 17 00:00:00 2001 From: lcernusa Date: Wed, 4 Mar 2026 22:48:41 +0100 Subject: [PATCH 168/347] [PWGCF] Added FV0-TPC correlations (#15254) --- .../Tasks/flowDecorrelation.cxx | 335 +++++++++++++++--- 1 file changed, 287 insertions(+), 48 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/flowDecorrelation.cxx b/PWGCF/TwoParticleCorrelations/Tasks/flowDecorrelation.cxx index efdf665692b..c8bde3aea57 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/flowDecorrelation.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/flowDecorrelation.cxx @@ -51,6 +51,7 @@ #include #include +#include #include using namespace o2; @@ -144,6 +145,7 @@ struct FlowDecorrelation { ConfigurableAxis axisDeltaEtaTpcFt0a{"axisDeltaEtaTpcFt0a", {32, -5.8, -2.6}, "delta eta axis, -5.8~-2.6 for TPC-FT0A,"}; ConfigurableAxis axisDeltaEtaTpcFt0c{"axisDeltaEtaTpcFt0c", {32, 1.2, 4.2}, "delta eta axis, 1.2~4.2 for TPC-FT0C"}; ConfigurableAxis axisDeltaEtaTpcMft{"axisDeltaEtaTpcMft", {32, 1.3, 4.8}, "delta eta axis, 1.3~4.8 for TPC-MFT"}; + ConfigurableAxis axisDeltaEtaTpcFv0{"axisDeltaEtaTpcFv0", {32, -1.2, -6.1}, "delta eta axis for TPC-FV0 histograms"}; ConfigurableAxis axisEtaTrigger{"axisEtaTrigger", {VARIABLE_WIDTH, -3.3, -2.1, -0.8, -0.6, -0.4, -0.2, 0, 0.2, 0.4, 0.6, 0.8, 3.5, 4.9}, "eta trigger axis for histograms"}; ConfigurableAxis axisEtaAssoc{"axisEtaAssoc", {VARIABLE_WIDTH, -3.3, -2.1, -0.8, -0.6, -0.4, -0.2, 0, 0.2, 0.4, 0.6, 0.8, 3.5, 4.9}, "eta associated axis for histograms"}; ConfigurableAxis axisVtxMix{"axisVtxMix", {VARIABLE_WIDTH, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "vertex axis for mixed event histograms"}; @@ -169,8 +171,10 @@ struct FlowDecorrelation { // FT0 geometry o2::ft0::Geometry ft0Det; + o2::fv0::Geometry* fv0Det{}; static constexpr uint64_t Ft0IndexA = 96; std::vector* offsetFT0; + std::vector* offsetFV0; std::vector cstFT0RelGain{}; // Corrections @@ -179,12 +183,8 @@ struct FlowDecorrelation { bool correctionsLoaded = false; // Define the outputs - OutputObj sameTpcFt0a{"sameEvent_TPC_FT0A"}; - OutputObj mixedTpcFt0a{"mixedEvent_TPC_FT0A"}; - OutputObj sameTpcFt0c{"sameEvent_TPC_FT0C"}; - OutputObj mixedTpcFt0c{"mixedEvent_TPC_FT0C"}; - OutputObj sameTpcMft{"sameEvent_TPC_MFT"}; - OutputObj mixedTpcMft{"mixedEvent_TPC_MFT"}; + OutputObj same{"sameEvent"}; + OutputObj mixed{"mixedEvent"}; HistogramRegistry registry{"registry"}; // define global variables @@ -203,7 +203,8 @@ struct FlowDecorrelation { }; enum FITIndex { kFT0A = 0, - kFT0C = 1 + kFT0C = 1, + kFV0 = 2 }; enum ParticleNsigma { kPionUp = 0, @@ -245,6 +246,7 @@ struct FlowDecorrelation { ccdb->setCaching(true); auto now = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); ccdb->setCreatedNotAfter(now); + fv0Det = o2::fv0::Geometry::instance(o2::fv0::Geometry::eUninitialized); LOGF(info, "Starting init"); // Event Counter @@ -297,7 +299,7 @@ struct FlowDecorrelation { std::string hCentTitle = "Centrality distribution, Estimator " + std::to_string(cfgCentEstimator); // Make histograms to check the distributions after cuts - if (doprocessSameTpcFt0a || doprocessSameTpcFt0c || doprocessSameTpcMft) { + if (doprocessSameTpcFt0a || doprocessSameTpcFt0c || doprocessSameTpcMft || doprocessSameTpcFv0) { registry.add("Phi", "Phi", {HistType::kTH1D, {axisPhi}}); registry.add("Eta", "Eta", {HistType::kTH1D, {axisEta}}); registry.add("EtaCorrected", "EtaCorrected", {HistType::kTH1D, {axisEta}}); @@ -335,22 +337,32 @@ struct FlowDecorrelation { registry.add("deltaEta_deltaPhi_mixed_TPC_MFT", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaTpcMft}}); registry.add("Trig_hist_TPC_MFT", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisEtaTrigger}}}); } + if (doprocessSameTpcFv0) { + registry.add("deltaEta_deltaPhi_same_TPC_FV0", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaTpcFv0}}); // check to see the delta eta and delta phi distribution + registry.add("deltaEta_deltaPhi_mixed_TPC_FV0", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaTpcFv0}}); + registry.add("Assoc_amp_same_TPC_FV0", "", {HistType::kTH2D, {axisChannelFt0aAxis, axisAmplitudeFt0a}}); + registry.add("Assoc_amp_mixed_TPC_FV0", "", {HistType::kTH2D, {axisChannelFt0aAxis, axisAmplitudeFt0a}}); + registry.add("Trig_hist_TPC_FV0", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisEtaTrigger}}}); + registry.add("FV0Amp", "", {HistType::kTH2F, {axisChID, axisFit}}); + } registry.add("eventcount", "bin", {HistType::kTH1F, {{4, 0, 4, "bin"}}}); // histogram to see how many events are in the same and mixed event LOGF(info, "Initializing correlation container"); - std::vector corrAxisTpcFt0a = {{axisSample, "Sample"}, - {axisVertex, "z-vtx (cm)"}, - {axisEtaTrigger, "#eta"}, - {axisEtaAssoc, "#eta"}, - {axisDeltaPhi, "#Delta#varphi (rad)"}, - {axisDeltaEtaTpcFt0a, "#Delta#eta"}}; std::vector effAxis = { {axisEtaEfficiency, "#eta"}, {axisPtEfficiency, "p_{T} (GeV/c)"}, {axisVertexEfficiency, "z-vtx (cm)"}, }; std::vector userAxis; + + std::vector corrAxisTpcFt0a = {{axisSample, "Sample"}, + {axisVertex, "z-vtx (cm)"}, + {axisEtaTrigger, "#eta"}, + {axisEtaAssoc, "#eta"}, + {axisDeltaPhi, "#Delta#varphi (rad)"}, + {axisDeltaEtaTpcFt0a, "#Delta#eta"}}; + std::vector corrAxisTpcFt0c = {{axisSample, "Sample"}, {axisVertex, "z-vtx (cm)"}, {axisEtaTrigger, "#eta"}, @@ -365,17 +377,28 @@ struct FlowDecorrelation { {axisDeltaPhi, "#Delta#varphi (rad)"}, {axisDeltaEtaTpcMft, "#Delta#eta"}}; + std::vector corrAxisTpcFv0 = {{axisSample, "Sample"}, + {axisVertex, "z-vtx (cm)"}, + {axisEtaTrigger, "#eta"}, + {axisEtaAssoc, "#eta"}, + {axisDeltaPhi, "#Delta#varphi (rad)"}, + {axisDeltaEtaTpcFv0, "#Delta#eta"}}; + if (doprocessSameTpcFt0a) { - sameTpcFt0a.setObject(new CorrelationContainer("sameEvent_TPC_FT0A", "sameEvent_TPC_FT0A", corrAxisTpcFt0a, effAxis, userAxis)); - mixedTpcFt0a.setObject(new CorrelationContainer("mixedEvent_TPC_FT0A", "mixedEvent_TPC_FT0A", corrAxisTpcFt0a, effAxis, userAxis)); + same.setObject(new CorrelationContainer("sameEvent_TPC_FT0A", "sameEvent_TPC_FT0A", corrAxisTpcFt0a, effAxis, userAxis)); + mixed.setObject(new CorrelationContainer("mixedEvent_TPC_FT0A", "mixedEvent_TPC_FT0A", corrAxisTpcFt0a, effAxis, userAxis)); } if (doprocessSameTpcFt0c) { - sameTpcFt0c.setObject(new CorrelationContainer("sameEvent_TPC_FT0C", "sameEvent_TPC_FT0C", corrAxisTpcFt0c, effAxis, userAxis)); - mixedTpcFt0c.setObject(new CorrelationContainer("mixedEvent_TPC_FT0C", "mixedEvent_TPC_FT0C", corrAxisTpcFt0c, effAxis, userAxis)); + same.setObject(new CorrelationContainer("sameEvent_TPC_FT0C", "sameEvent_TPC_FT0C", corrAxisTpcFt0c, effAxis, userAxis)); + mixed.setObject(new CorrelationContainer("mixedEvent_TPC_FT0C", "mixedEvent_TPC_FT0C", corrAxisTpcFt0c, effAxis, userAxis)); } if (doprocessSameTpcMft) { - sameTpcMft.setObject(new CorrelationContainer("sameEvent_TPC_MFT", "sameEvent_TPC_MFT", corrAxisTpcMft, effAxis, userAxis)); - mixedTpcMft.setObject(new CorrelationContainer("mixedEvent_TPC_MFT", "mixedEvent_TPC_MFT", corrAxisTpcMft, effAxis, userAxis)); + same.setObject(new CorrelationContainer("sameEvent_TPC_MFT", "sameEvent_TPC_MFT", corrAxisTpcMft, effAxis, userAxis)); + mixed.setObject(new CorrelationContainer("mixedEvent_TPC_MFT", "mixedEvent_TPC_MFT", corrAxisTpcMft, effAxis, userAxis)); + } + if (doprocessSameTpcFv0) { + same.setObject(new CorrelationContainer("sameEvent_TPC_FV0", "sameEvent_TPC_FV0", corrAxisTpcFv0, effAxis, userAxis)); + mixed.setObject(new CorrelationContainer("mixedEvent_TPC_FV0", "mixedEvent_TPC_FV0", corrAxisTpcFv0, effAxis, userAxis)); } LOGF(info, "End of init"); } @@ -396,6 +419,52 @@ struct FlowDecorrelation { return true; } + double getPhiFV0(uint64_t chno) + { + o2::fv0::Point3Dsimple chPos{}; + int const cellsInLeft[] = {0, 1, 2, 3, 8, 9, 10, 11, 16, 17, 18, 19, 24, 25, 26, 27, 32, 40, 33, 41, 34, 42, 35, 43}; + bool const isChnoInLeft = std::find(std::begin(cellsInLeft), std::end(cellsInLeft), chno) != std::end(cellsInLeft); + + if (isChnoInLeft) { + chPos = fv0Det->getReadoutCenter(chno); + return RecoDecay::phi(chPos.x + (*offsetFV0)[0].getX(), chPos.y + (*offsetFV0)[0].getY()); + } else { + chPos = fv0Det->getReadoutCenter(chno); + return RecoDecay::phi(chPos.x + (*offsetFV0)[1].getX(), chPos.y + (*offsetFV0)[1].getY()); + } + } + + double getEtaFV0(uint64_t chno) + { + + int const cellsInLeft[] = {0, 1, 2, 3, 8, 9, 10, 11, 16, 17, 18, 19, 24, 25, 26, 27, 32, 40, 33, 41, 34, 42, 35, 43}; + bool const isChnoInLeft = std::find(std::begin(cellsInLeft), std::end(cellsInLeft), chno) != std::end(cellsInLeft); + + o2::fv0::Point3Dsimple chPos{}; + chPos = fv0Det->getReadoutCenter(chno); + + float offsetX, offsetY, offsetZ; + + if (isChnoInLeft) { + offsetX = (*offsetFV0)[0].getX(); + offsetY = (*offsetFV0)[0].getY(); + offsetZ = (*offsetFV0)[0].getZ(); + } else { + offsetX = (*offsetFV0)[1].getX(); + offsetY = (*offsetFV0)[1].getY(); + offsetZ = (*offsetFV0)[1].getZ(); + } + + auto x = chPos.x + offsetX; + auto y = chPos.y + offsetY; + auto z = chPos.z + offsetZ; + + auto r = std::sqrt(x * x + y * y); + auto theta = std::atan2(r, z); + + return -std::log(std::tan(0.5 * theta)); + } + double getPhiFT0(uint64_t chno, int i) { // offsetFT0[0]: FT0A, offsetFT0[1]: FT0C @@ -458,9 +527,13 @@ struct FlowDecorrelation { void loadAlignParam(uint64_t timestamp) { offsetFT0 = ccdb->getForTimeStamp>("FT0/Calib/Align", timestamp); + offsetFV0 = ccdb->getForTimeStamp>("FV0/Calib/Align", timestamp); if (offsetFT0 == nullptr) { LOGF(fatal, "Could not load FT0/Calib/Align for timestamp %d", timestamp); } + if (offsetFV0 == nullptr) { + LOGF(fatal, "Could not load FV0/Calib/Align for timestamp %d", timestamp); + } } void loadGain(aod::BCsWithTimestamps::iterator const& bc) @@ -573,21 +646,29 @@ struct FlowDecorrelation { id = id + Ft0IndexA; ampl = ft0.amplitudeC()[iCh]; registry.fill(HIST("FT0Amp"), id, ampl); - ampl = ampl / cstFT0RelGain[iCh]; + ampl = ampl / cstFT0RelGain[id]; registry.fill(HIST("FT0AmpCorrect"), id, ampl); } else if (fitType == kFT0A) { id = ft0.channelA()[iCh]; ampl = ft0.amplitudeA()[iCh]; registry.fill(HIST("FT0Amp"), id, ampl); - ampl = ampl / cstFT0RelGain[iCh]; + ampl = ampl / cstFT0RelGain[id]; registry.fill(HIST("FT0AmpCorrect"), id, ampl); } else { LOGF(fatal, "Cor Index %d out of range", fitType); } } + template + void getChannelFV0(TFT0s const& fv0, std::size_t const& iCh, int& id, float& ampl) + { + id = fv0.channel()[iCh]; + ampl = fv0.amplitude()[iCh]; + registry.fill(HIST("FV0Amp"), id, ampl); + } + template - void fillCorrelationsTPCFT0(TTracks tracks1, TFT0s const& ft0, float posZ, int system, int corType, float cent, float eventWeight) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms + void fillCorrelationsTPCFIT(TTracks tracks1, TFT0s const& ft0, float posZ, int system, int corType, float cent, float eventWeight) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms { if (system == SameEvent) { if (!cfgCentTableUnavailable) @@ -606,24 +687,22 @@ struct FlowDecorrelation { if (!getEfficiencyCorrection(triggerWeight, track1.eta(), track1.pt(), posZ)) continue; if (system == SameEvent) { - if (corType == kFT0C) { + if (corType == kFT0C) registry.fill(HIST("Trig_hist_TPC_FT0C"), fSampleIndex, posZ, track1.eta(), eventWeight * triggerWeight); - } else if (corType == kFT0A) { + else if (corType == kFT0A) registry.fill(HIST("Trig_hist_TPC_FT0A"), fSampleIndex, posZ, track1.eta(), eventWeight * triggerWeight); - } - if (cfgDrawEtaPhiDis && corType == kFT0A) { + if (cfgDrawEtaPhiDis && corType == kFT0A) registry.fill(HIST("EtaPhi"), track1.eta(), track1.phi(), eventWeight * triggerWeight); - } } std::size_t channelSize = 0; - if (corType == kFT0C) { - channelSize = ft0.channelC().size(); - } else if (corType == kFT0A) { + if (corType == kFT0A) channelSize = ft0.channelA().size(); - } else { + else if (corType == kFT0C) + channelSize = ft0.channelC().size(); + else LOGF(fatal, "Cor Index %d out of range", corType); - } + for (std::size_t iCh = 0; iCh < channelSize; iCh++) { int chanelid = 0; float ampl = 0.; @@ -637,8 +716,9 @@ struct FlowDecorrelation { continue; } } - auto phi = getPhiFT0(chanelid, corType); - auto eta = getEtaFT0(chanelid, corType); + double phi = getPhiFT0(chanelid, corType); + double eta = getEtaFT0(chanelid, corType); + if (cfgDrawEtaPhiDis && system == SameEvent) { registry.fill(HIST("EtaPhi"), eta, phi, ampl * eventWeight); } @@ -648,21 +728,21 @@ struct FlowDecorrelation { if (system == SameEvent) { if (corType == kFT0A) { registry.fill(HIST("Assoc_amp_same_TPC_FT0A"), chanelid, ampl); - sameTpcFt0a->getPairHist()->Fill(step, fSampleIndex, posZ, track1.eta(), eta, deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); + same->getPairHist()->Fill(step, fSampleIndex, posZ, track1.eta(), eta, deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); registry.fill(HIST("deltaEta_deltaPhi_same_TPC_FT0A"), deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); } else if (corType == kFT0C) { registry.fill(HIST("Assoc_amp_same_TPC_FT0C"), chanelid, ampl); - sameTpcFt0c->getPairHist()->Fill(step, fSampleIndex, posZ, track1.eta(), eta, deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); + same->getPairHist()->Fill(step, fSampleIndex, posZ, track1.eta(), eta, deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); registry.fill(HIST("deltaEta_deltaPhi_same_TPC_FT0C"), deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); } } else if (system == MixedEvent) { if (corType == kFT0A) { registry.fill(HIST("Assoc_amp_mixed_TPC_FT0A"), chanelid, ampl); - mixedTpcFt0a->getPairHist()->Fill(step, fSampleIndex, posZ, track1.eta(), eta, deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); + mixed->getPairHist()->Fill(step, fSampleIndex, posZ, track1.eta(), eta, deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); registry.fill(HIST("deltaEta_deltaPhi_mixed_TPC_FT0A"), deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); } else if (corType == kFT0C) { registry.fill(HIST("Assoc_amp_mixed_TPC_FT0C"), chanelid, ampl); - mixedTpcFt0c->getPairHist()->Fill(step, fSampleIndex, posZ, track1.eta(), eta, deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); + mixed->getPairHist()->Fill(step, fSampleIndex, posZ, track1.eta(), eta, deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); registry.fill(HIST("deltaEta_deltaPhi_mixed_TPC_FT0C"), deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); } } @@ -670,6 +750,59 @@ struct FlowDecorrelation { } } + template + void fillCorrelationsTPCFV0(TTracks tracks1, TFT0s const& fv0, float posZ, int system, float cent, float eventWeight) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms + { + if (system == SameEvent) { + if (!cfgCentTableUnavailable) + registry.fill(HIST("Centrality_used"), cent); + registry.fill(HIST("Nch_used"), tracks1.size()); + } + + int fSampleIndex = gRandom->Uniform(0, cfgSampleSize); + + float triggerWeight = 1.0f; + // loop over all tracks + for (auto const& track1 : tracks1) { + + if (!trackSelected(track1)) + continue; + if (!getEfficiencyCorrection(triggerWeight, track1.eta(), track1.pt(), posZ)) + continue; + if (system == SameEvent) { + registry.fill(HIST("Trig_hist_TPC_FV0"), fSampleIndex, posZ, track1.eta(), eventWeight * triggerWeight); + } + + std::size_t channelSize = 0; + channelSize = fv0.channel().size(); + + for (std::size_t iCh = 0; iCh < channelSize; iCh++) { + int chanelid = 0; + float ampl = 0.; + getChannelFV0(fv0, iCh, chanelid, ampl); + + double phi = getPhiFV0(chanelid); + double eta = getEtaFV0(chanelid); + + if (cfgDrawEtaPhiDis && system == SameEvent) { + registry.fill(HIST("EtaPhi"), eta, phi, ampl * eventWeight); + } + float deltaPhi = RecoDecay::constrainAngle(track1.phi() - phi, -PIHalf); + float deltaEta = track1.eta() - eta; + // fill the right sparse and histograms + if (system == SameEvent) { + registry.fill(HIST("Assoc_amp_same_TPC_FV0"), chanelid, ampl); + same->getPairHist()->Fill(step, fSampleIndex, posZ, track1.eta(), eta, deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); + registry.fill(HIST("deltaEta_deltaPhi_same_TPC_FV0"), deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); + } else if (system == MixedEvent) { + registry.fill(HIST("Assoc_amp_mixed_TPC_FV0"), chanelid, ampl); + mixed->getPairHist()->Fill(step, fSampleIndex, posZ, track1.eta(), eta, deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); + registry.fill(HIST("deltaEta_deltaPhi_mixed_TPC_FV0"), deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); + } + } + } + } + template bool eventSelected(TCollision collision, const int multTrk, const float centrality, const bool fillCounter) { @@ -804,9 +937,9 @@ struct FlowDecorrelation { registry.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin fillYield(collision, tracks); - sameTpcFt0a->fillEvent(tracks.size(), CorrelationContainer::kCFStepReconstructed); + same->fillEvent(tracks.size(), CorrelationContainer::kCFStepReconstructed); const auto& ft0 = collision.foundFT0(); - fillCorrelationsTPCFT0(tracks, ft0, collision.posZ(), SameEvent, kFT0A, cent, weightCent); + fillCorrelationsTPCFIT(tracks, ft0, collision.posZ(), SameEvent, kFT0A, cent, weightCent); } PROCESS_SWITCH(FlowDecorrelation, processSameTpcFt0a, "Process same event for TPC-FT0 correlation", true); @@ -869,7 +1002,7 @@ struct FlowDecorrelation { if (!cfgCentTableUnavailable) getCentralityWeight(weightCent, cent1); const auto& ft0 = collision2.foundFT0(); - fillCorrelationsTPCFT0(tracks1, ft0, collision1.posZ(), MixedEvent, kFT0A, cent1, eventWeight * weightCent); + fillCorrelationsTPCFIT(tracks1, ft0, collision1.posZ(), MixedEvent, kFT0A, cent1, eventWeight * weightCent); } } PROCESS_SWITCH(FlowDecorrelation, processMixedTpcFt0a, "Process mixed events for TPC-FT0A correlation", true); @@ -909,9 +1042,9 @@ struct FlowDecorrelation { registry.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin fillYield(collision, tracks); - sameTpcFt0c->fillEvent(tracks.size(), CorrelationContainer::kCFStepReconstructed); + same->fillEvent(tracks.size(), CorrelationContainer::kCFStepReconstructed); const auto& ft0 = collision.foundFT0(); - fillCorrelationsTPCFT0(tracks, ft0, collision.posZ(), SameEvent, kFT0C, cent, weightCent); + fillCorrelationsTPCFIT(tracks, ft0, collision.posZ(), SameEvent, kFT0C, cent, weightCent); } PROCESS_SWITCH(FlowDecorrelation, processSameTpcFt0c, "Process same event for TPC-FT0C correlation", false); @@ -974,7 +1107,7 @@ struct FlowDecorrelation { if (!cfgCentTableUnavailable) getCentralityWeight(weightCent, cent1); const auto& ft0 = collision2.foundFT0(); - fillCorrelationsTPCFT0(tracks1, ft0, collision1.posZ(), MixedEvent, kFT0C, cent1, eventWeight * weightCent); + fillCorrelationsTPCFIT(tracks1, ft0, collision1.posZ(), MixedEvent, kFT0C, cent1, eventWeight * weightCent); } } PROCESS_SWITCH(FlowDecorrelation, processMixedTpcFt0c, "Process mixed events for TPC-FT0C correlation", false); @@ -1012,10 +1145,10 @@ struct FlowDecorrelation { float deltaEta = track1.eta() - track2.eta(); if (system == SameEvent) { - sameTpcMft->getPairHist()->Fill(step, fSampleIndex, posZ, track1.eta(), track2.eta(), deltaPhi, deltaEta, eventWeight * triggerWeight); + same->getPairHist()->Fill(step, fSampleIndex, posZ, track1.eta(), track2.eta(), deltaPhi, deltaEta, eventWeight * triggerWeight); registry.fill(HIST("deltaEta_deltaPhi_same_TPC_MFT"), deltaPhi, deltaEta, eventWeight * triggerWeight); } else if (system == MixedEvent) { - mixedTpcMft->getPairHist()->Fill(step, fSampleIndex, posZ, track1.eta(), track2.eta(), deltaPhi, deltaEta, eventWeight * triggerWeight); + mixed->getPairHist()->Fill(step, fSampleIndex, posZ, track1.eta(), track2.eta(), deltaPhi, deltaEta, eventWeight * triggerWeight); registry.fill(HIST("deltaEta_deltaPhi_mixed_TPC_MFT"), deltaPhi, deltaEta, eventWeight * triggerWeight); } } @@ -1062,7 +1195,7 @@ struct FlowDecorrelation { fillYield(collision, tracks); fillCorrelationsTPCMFT(tracks, mfts, collision.posZ(), SameEvent, cent, weightCent); - sameTpcMft->fillEvent(tracks.size(), CorrelationContainer::kCFStepReconstructed); + same->fillEvent(tracks.size(), CorrelationContainer::kCFStepReconstructed); } PROCESS_SWITCH(FlowDecorrelation, processSameTpcMft, "Process same events for TPC-MFT correlation", false); @@ -1134,6 +1267,112 @@ struct FlowDecorrelation { } } PROCESS_SWITCH(FlowDecorrelation, processMixedTpcMft, "Process same events for TPC-MFT correlation", false); + + void processSameTpcFv0(FilteredCollisions::iterator const& collision, FilteredTracks const& tracks, aod::FV0As const&, aod::BCsWithTimestamps const&) + { + if (!collision.sel8()) + return; + auto bc = collision.bc_as(); + float cent = -1.; + float weightCent = 1.0f; + if (!cfgCentTableUnavailable) { + cent = getCentrality(collision); + } + if (cfgUseAdditionalEventCut && !eventSelected(collision, tracks.size(), cent, true)) + return; + if (!collision.has_foundFV0()) + return; + loadAlignParam(bc.timestamp()); + loadGain(bc); + loadCorrection(bc.timestamp()); + + if (!cfgCentTableUnavailable) { + getCentralityWeight(weightCent, cent); + registry.fill(HIST("Centrality"), cent); + registry.fill(HIST("CentralityWeighted"), cent, weightCent); + } + registry.fill(HIST("Nch"), tracks.size()); + registry.fill(HIST("zVtx"), collision.posZ()); + + if (cfgSelCollByNch && (tracks.size() < cfgCutMultMin || tracks.size() >= cfgCutMultMax)) { + return; + } + if (!cfgSelCollByNch && !cfgCentTableUnavailable && (cent < cfgCutCentMin || cent >= cfgCutCentMax)) { + return; + } + + registry.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin + fillYield(collision, tracks); + + same->fillEvent(tracks.size(), CorrelationContainer::kCFStepReconstructed); + + same->fillEvent(tracks.size(), CorrelationContainer::kCFStepReconstructed); + const auto& fv0 = collision.foundFV0(); + fillCorrelationsTPCFV0(tracks, fv0, collision.posZ(), SameEvent, cent, weightCent); + } + PROCESS_SWITCH(FlowDecorrelation, processSameTpcFv0, "Process same events for TPC-FV0 correlation", false); + + void processMixedTpcFv0(FilteredCollisions const& collisions, FilteredTracks const& tracks, aod::FV0As const&, aod::BCsWithTimestamps const&) + { + auto getTracksSize = [&tracks, this](FilteredCollisions::iterator const& collision) { + auto associatedTracks = tracks.sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), this->cache); + auto mult = associatedTracks.size(); + return mult; + }; + + using MixedBinning = FlexibleBinningPolicy, aod::collision::PosZ, decltype(getTracksSize)>; + + MixedBinning binningOnVtxAndMult{{getTracksSize}, {axisVtxMix, axisMultMix}, true}; + + auto tracksTuple = std::make_tuple(tracks, tracks); + Pair pairs{binningOnVtxAndMult, cfgMixEventNumMin, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip + for (auto it = pairs.begin(); it != pairs.end(); it++) { + auto& [collision1, tracks1, collision2, tracks2] = *it; + if (!collision1.sel8() || !collision2.sel8()) + continue; + + if (cfgSelCollByNch && (tracks1.size() < cfgCutMultMin || tracks1.size() >= cfgCutMultMax)) + continue; + + if (cfgSelCollByNch && (tracks2.size() < cfgCutMultMin || tracks2.size() >= cfgCutMultMax)) + continue; + + float cent1 = -1; + float cent2 = -1; + if (!cfgCentTableUnavailable) { + cent1 = getCentrality(collision1); + cent2 = getCentrality(collision2); + } + if (cfgUseAdditionalEventCut && !eventSelected(collision1, tracks1.size(), cent1, false)) + continue; + if (cfgUseAdditionalEventCut && !eventSelected(collision2, tracks2.size(), cent2, false)) + continue; + + if (!cfgSelCollByNch && !cfgCentTableUnavailable && (cent1 < cfgCutCentMin || cent1 >= cfgCutCentMax)) + continue; + + if (!cfgSelCollByNch && !cfgCentTableUnavailable && (cent2 < cfgCutCentMin || cent2 >= cfgCutCentMax)) + continue; + + if (!(collision1.has_foundFV0() && collision2.has_foundFV0())) + continue; + + registry.fill(HIST("eventcount"), MixedEvent); // fill the mixed event in the 3 bin + auto bc = collision1.bc_as(); + loadAlignParam(bc.timestamp()); + loadCorrection(bc.timestamp()); + float eventWeight = 1.0f; + if (cfgUseEventWeights) { + eventWeight = 1.0f / it.currentWindowNeighbours(); + } + float weightCent = 1.0f; + if (!cfgCentTableUnavailable) + getCentralityWeight(weightCent, cent1); + const auto& fv0 = collision2.foundFV0(); + fillCorrelationsTPCFV0(tracks1, fv0, collision1.posZ(), MixedEvent, cent1, eventWeight * weightCent); + } + } + PROCESS_SWITCH(FlowDecorrelation, processMixedTpcFv0, "Process mixed events for TPC-FV0 correlation", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) From f83195a7212f7e7200ec9f2906b12cb2352d0a7a Mon Sep 17 00:00:00 2001 From: Oton Vazquez Doce Date: Wed, 4 Mar 2026 23:23:20 +0100 Subject: [PATCH 169/347] [Infrastructure] Update CODEOWNERS (#15267) --- CODEOWNERS | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/CODEOWNERS b/CODEOWNERS index 5f06bf0fdc7..89a96d4faea 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -31,11 +31,24 @@ /EventFiltering/PWGJE @alibuild @fkrizek @nzardosh @raymondEhlers @mpuccio @lietava @fgrosa @ariedel-cern /EventFiltering/PWGEM @alibuild @dsekihat @nstrangm @mpuccio @lietava @fgrosa @ariedel-cern -/PWGCF @alibuild @victor-gonzalez @zchochul @lgraczykCern @prchakra @lauraser @ariedel-cern @EmilGorm @otonvd @shouqiye @glromane -/PWGCF/Core @alibuild @jgrosseo @victor-gonzalez @zchochul @lgraczykCern @prchakra @lauraser @ariedel-cern @EmilGorm @otonvd @shouqiye @glromane -/PWGCF/DataModel @alibuild @jgrosseo @victor-gonzalez @zchochul @lgraczykCern @prchakra @lauraser @ariedel-cern @EmilGorm @otonvd @shouqiye @glromane -/PWGCF/TableProducer @alibuild @jgrosseo @victor-gonzalez @zchochul @lgraczykCern @prchakra @lauraser @ariedel-cern @EmilGorm @otonvd @shouqiye @glromane -/PWGCF/Tasks @alibuild @jgrosseo @victor-gonzalez @zchochul @lgraczykCern @prchakra @lauraser @ariedel-cern @EmilGorm @otonvd @shouqiye @glromane +/PWGCF @alibuild @victor-gonzalez @otonvd @shouqiye +/PWGCF/Core @alibuild @jgrosseo +/PWGCF/DataModel @alibuild @jgrosseo @victor-gonzalez @otonvd @shouqiye +/PWGCF/TableProducer @alibuild @jgrosseo @victor-gonzalez @otonvd @shouqiye +/PWGCF/Tasks @alibuild @jgrosseo @victor-gonzalez @otonvd @shouqiye +/PWGCF/EbyEFluctuations @alibuild @SwatiSaha-1997 @isputows @victor-gonzalez @otonvd @shouqiye +/PWGCF/Femto @alibuild @lauraser @ariedel-cern @dimihayl @victor-gonzalez @otonvd @shouqiye +/PWGCF/FemtoDream @alibuild @lauraser @ariedel-cern @dimihayl @victor-gonzalez @otonvd @shouqiye +/PWGCF/Femto3D @alibuild @glromane @sofiatomassini @lauraser @dimihayl @victor-gonzalez @otonvd @shouqiye +/PWGCF/FemtoUniverse @alibuild @prchakra @lgraczykCern @majanik @lauraser @dimihayl @victor-gonzalez @otonvd @shouqiye +/PWGCF/FemtoWorld @alibuild @prchakra @lgraczykCern @majanik @lauraser @dimihayl @victor-gonzalez @otonvd @shouqiye +/PWGCF/Flow @alibuild @majanik @EmilGorm @jaelpark @wenyaCern @victor-gonzalez @otonvd @shouqiye +/PWGCF/GenericFramework @alibuild @EmilGorm @jaelpark @wenyaCern @victor-gonzalez @otonvd @shouqiye +/PWGCF/MultiparticleCorrelations @alibuild @abilandz @jaelpark @wenyaCern @victor-gonzalez @otonvd @shouqiye +/PWGCF/JCorran @alibuild @jaelpark @wenyaCern @victor-gonzalez @otonvd @shouqiye +/PWGCF/TwoParticleCorrelations @alibuild @Luzhiyongg @jaelpark @wenyaCern @victor-gonzalez @otonvd @shouqiye +/PWGCF/Tutorial @alibuild @ariedel-cern @victor-gonzalez @otonvd @shouqiye + /PWGDQ @alibuild @iarsene @mcoquet642 @lucamicheletti93 @XiaozhiBai /PWGEM @alibuild @feisenhu @dsekihat @ivorobye @jokonig /PWGEM/Dilepton @alibuild @mikesas @rbailhac @dsekihat @ivorobye @feisenhu @hscheid @jokonig From b0b26f1cc0563f76d3d837d715d2cf16b564d576 Mon Sep 17 00:00:00 2001 From: "Cicero D. Muncinelli" <88810740+cmuncinelli@users.noreply.github.com> Date: Wed, 4 Mar 2026 19:29:53 -0300 Subject: [PATCH 170/347] [PWGLF] Add HI Lambda/AntiLambda polarization around jets workflow (#15263) Co-authored-by: ALICE Action Bot --- PWGLF/DataModel/lambdaJetPolarizationIons.h | 150 ++ .../TableProducer/Strangeness/CMakeLists.txt | 5 + .../Strangeness/lambdaJetPolarizationIons.cxx | 2002 +++++++++++++++++ PWGLF/Tasks/Strangeness/CMakeLists.txt | 5 + .../lambdaJetPolarizationIonsDerived.cxx | 776 +++++++ 5 files changed, 2938 insertions(+) create mode 100644 PWGLF/DataModel/lambdaJetPolarizationIons.h create mode 100644 PWGLF/TableProducer/Strangeness/lambdaJetPolarizationIons.cxx create mode 100644 PWGLF/Tasks/Strangeness/lambdaJetPolarizationIonsDerived.cxx diff --git a/PWGLF/DataModel/lambdaJetPolarizationIons.h b/PWGLF/DataModel/lambdaJetPolarizationIons.h new file mode 100644 index 00000000000..fef233231c0 --- /dev/null +++ b/PWGLF/DataModel/lambdaJetPolarizationIons.h @@ -0,0 +1,150 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +/// +/// \file lambdaJetPolarizationIons.h +/// \brief Derived Data table for Jet-induced polarization analysis (HI) +/// \author Cicero Domenico Muncinelli (cicero.domenico.muncinelli@cern.ch) +// Comments, questions, complaints, suggestions? +// Please write to: +// cicero.domenico.muncinelli@cern.ch +// + +#ifndef PWGLF_DATAMODEL_LAMBDAJETPOL_H_ +#define PWGLF_DATAMODEL_LAMBDAJETPOL_H_ + +#include + +namespace o2::aod +{ + +namespace lambdajetpol +{ + +// DECLARE_SOA_COLUMN(CollIdx, collIdx, uint64_t); // Using a regular SOA column instead of an index column for convenience +// Collision information: +DECLARE_SOA_INDEX_COLUMN(Collision, collision); +DECLARE_SOA_COLUMN(CentFT0M, centFT0M, float); +DECLARE_SOA_COLUMN(CentFT0C, centFT0C, float); +DECLARE_SOA_COLUMN(CentFT0CVariant1, centFT0CVariant1, float); +DECLARE_SOA_COLUMN(CentMFT, centMFT, float); +DECLARE_SOA_COLUMN(CentNGlobal, centNGlobal, float); +DECLARE_SOA_COLUMN(CentFV0A, centFV0A, float); + +// Jet (and jet proxies) information: +DECLARE_SOA_COLUMN(JetPt, jetPt, float); +DECLARE_SOA_COLUMN(JetEta, jetEta, float); +DECLARE_SOA_COLUMN(JetPhi, jetPhi, float); +DECLARE_SOA_COLUMN(JetNConstituents, jetNConstituents, uint64_t); + +DECLARE_SOA_COLUMN(LeadParticlePt, leadParticlePt, float); +DECLARE_SOA_COLUMN(LeadParticleEta, leadParticleEta, float); +DECLARE_SOA_COLUMN(LeadParticlePhi, leadParticlePhi, float); + +// V0 information: +DECLARE_SOA_COLUMN(V0Pt, v0Pt, float); +DECLARE_SOA_COLUMN(V0Eta, v0Eta, float); +DECLARE_SOA_COLUMN(V0Phi, v0Phi, float); + +DECLARE_SOA_COLUMN(IsLambda, isLambda, bool); +DECLARE_SOA_COLUMN(IsAntiLambda, isAntiLambda, bool); +DECLARE_SOA_COLUMN(MassLambda, massLambda, float); +DECLARE_SOA_COLUMN(MassAntiLambda, massAntiLambda, float); + +DECLARE_SOA_COLUMN(PosPt, posPt, float); +DECLARE_SOA_COLUMN(PosEta, posEta, float); +DECLARE_SOA_COLUMN(PosPhi, posPhi, float); +DECLARE_SOA_COLUMN(NegPt, negPt, float); +DECLARE_SOA_COLUMN(NegEta, negEta, float); +DECLARE_SOA_COLUMN(NegPhi, negPhi, float); + +DECLARE_SOA_COLUMN(PosTPCNSigmaPr, posTPCNSigmaPr, float); +DECLARE_SOA_COLUMN(PosTPCNSigmaPi, posTPCNSigmaPi, float); +DECLARE_SOA_COLUMN(NegTPCNSigmaPr, negTPCNSigmaPr, float); +DECLARE_SOA_COLUMN(NegTPCNSigmaPi, negTPCNSigmaPi, float); + +DECLARE_SOA_COLUMN(V0CosPA, v0cosPA, float); +DECLARE_SOA_COLUMN(V0Radius, v0radius, float); +DECLARE_SOA_COLUMN(DcaV0Daughters, dcaV0daughters, float); +DECLARE_SOA_COLUMN(DcaPosToPV, dcaPosToPV, float); +DECLARE_SOA_COLUMN(DcaNegToPV, dcaNegToPV, float); + +// Dynamic columns for jets (Px,Py,Pz): +DECLARE_SOA_DYNAMIC_COLUMN(JetPx, jetPx, //! Jet px + [](float jetPt, float jetPhi) -> float { return jetPt * std::cos(jetPhi); }); +DECLARE_SOA_DYNAMIC_COLUMN(JetPy, jetPy, //! Jet py + [](float jetPt, float jetPhi) -> float { return jetPt * std::sin(jetPhi); }); +DECLARE_SOA_DYNAMIC_COLUMN(JetPz, jetPz, //! Jet pz + [](float jetPt, float jetEta) -> float { return jetPt * std::sinh(jetEta); }); +// Same for leading particles: +DECLARE_SOA_DYNAMIC_COLUMN(LeadParticlePx, leadParticlePx, //! Leading particle px + [](float leadParticlePt, float leadParticlePhi) -> float { return leadParticlePt * std::cos(leadParticlePhi); }); +DECLARE_SOA_DYNAMIC_COLUMN(LeadParticlePy, leadParticlePy, //! Leading particle py + [](float leadParticlePt, float leadParticlePhi) -> float { return leadParticlePt * std::sin(leadParticlePhi); }); +DECLARE_SOA_DYNAMIC_COLUMN(LeadParticlePz, leadParticlePz, //! Leading particle pz + [](float leadParticlePt, float leadParticleEta) -> float { return leadParticlePt * std::sinh(leadParticleEta); }); + +} // namespace lambdajetpol + +DECLARE_SOA_TABLE(RingJets, "AOD", "RINGJETS", // Renamed to follow convention on "s" at the end of table name. + lambdajetpol::CollisionId, // Changed to an internal O2 index, slightly different from usual o2::soa::Index<> though + lambdajetpol::JetPt, + lambdajetpol::JetEta, + lambdajetpol::JetPhi, + lambdajetpol::JetNConstituents, + // Dynamic columns + lambdajetpol::JetPx, // Explicitly binding to static columns + lambdajetpol::JetPy, + lambdajetpol::JetPz); + +DECLARE_SOA_TABLE(RingLeadP, "AOD", "RINGLEADP", // Leading particle table + lambdajetpol::CollisionId, + lambdajetpol::LeadParticlePt, + lambdajetpol::LeadParticleEta, + lambdajetpol::LeadParticlePhi, + // Dynamic columns + lambdajetpol::LeadParticlePx, + lambdajetpol::LeadParticlePy, + lambdajetpol::LeadParticlePz); + +DECLARE_SOA_TABLE(RingLaV0s, "AOD", "RINGLAV0S", + lambdajetpol::CollisionId, + lambdajetpol::V0Pt, + lambdajetpol::V0Eta, + lambdajetpol::V0Phi, + lambdajetpol::IsLambda, + lambdajetpol::IsAntiLambda, + lambdajetpol::MassLambda, + lambdajetpol::MassAntiLambda, + lambdajetpol::PosPt, + lambdajetpol::PosEta, + lambdajetpol::PosPhi, + lambdajetpol::NegPt, + lambdajetpol::NegEta, + lambdajetpol::NegPhi, + lambdajetpol::PosTPCNSigmaPr, + lambdajetpol::PosTPCNSigmaPi, + lambdajetpol::NegTPCNSigmaPr, + lambdajetpol::NegTPCNSigmaPi, + lambdajetpol::V0CosPA, + lambdajetpol::V0Radius, + lambdajetpol::DcaV0Daughters, + lambdajetpol::DcaPosToPV, + lambdajetpol::DcaNegToPV); + +DECLARE_SOA_TABLE(RingCollisions, "AOD", "RINGCOLLISIONS", + lambdajetpol::CollisionId, + lambdajetpol::CentFT0M, + lambdajetpol::CentFT0C, + lambdajetpol::CentFV0A); + +} // namespace o2::aod + +#endif // PWGLF_DATAMODEL_LAMBDAJETPOL_H_ diff --git a/PWGLF/TableProducer/Strangeness/CMakeLists.txt b/PWGLF/TableProducer/Strangeness/CMakeLists.txt index 43c6331ae07..9a6e18ac944 100644 --- a/PWGLF/TableProducer/Strangeness/CMakeLists.txt +++ b/PWGLF/TableProducer/Strangeness/CMakeLists.txt @@ -147,6 +147,11 @@ o2physics_add_dpl_workflow(lambdajetpolarizationbuilder PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(lambdajetpolarizationions + SOURCES lambdaJetPolarizationIons.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGJECore FastJet::FastJet O2Physics::AnalysisCCDB + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(stracents SOURCES stracents.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore diff --git a/PWGLF/TableProducer/Strangeness/lambdaJetPolarizationIons.cxx b/PWGLF/TableProducer/Strangeness/lambdaJetPolarizationIons.cxx new file mode 100644 index 00000000000..14a1f4da3c4 --- /dev/null +++ b/PWGLF/TableProducer/Strangeness/lambdaJetPolarizationIons.cxx @@ -0,0 +1,2002 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +// +/// \file lambdaJetPolarizationIons.cxx +/// \brief Lambda and antiLambda polarization analysis task using raw data +/// +/// \author Cicero Domenico Muncinelli , Campinas State University +// +// Jet Polarization Ions task +// ================ +// +// This code loops over a V0Cores table and produces standard derived +// data as output. In the post-processing stage, this analysis aims +// to measure the formation of vorticity rings in HI collisions. +// +// Comments, questions, complaints, suggestions? +// Please write to: +// cicero.domenico.muncinelli@cern.ch +// + +// O2 Framework +#include +#include +#include +#include +#include +#include + +// O2 CCDB / Conditions +#include "DataFormatsParameters/GRPMagField.h" +#include +#include + +// O2 Reconstruction Data Formats +#include + +// O2 Common Core +#include "Common/Core/RecoDecay.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/trackUtilities.h" + +// O2 Common DataModel +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/CollisionAssociationTables.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/McCollisionExtra.h" +#include "Common/DataModel/Multiplicity.h" // for pp +#include "Common/DataModel/PIDResponseTPC.h" +// For PID in raw data: +// #include "Common/DataModel/PIDResponseTOF.h" // Maybe switch this around with LFStrangenessPIDTables? +// #include "Common/DataModel/Qvectors.h" +#include "Common/DataModel/TrackSelectionTables.h" + +// PWGJE +#include "PWGJE/Core/JetBkgSubUtils.h" +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" + +// PWGLF +#include "PWGLF/DataModel/LFStrangenessPIDTables.h" +// For V0TOFPIDs and NSigmas getters. Better for considering the daughters as coming from V0s instead of from PV? +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGLF/DataModel/lambdaJetPolarizationIons.h" +#include "PWGLF/DataModel/mcCentrality.h" + +// External Libraries (FastJet) +#include +#include +#include +#include +#include +#include +#include +#include + +// ROOT Math +#include "Math/GenVector/Boost.h" +#include "Math/Vector3D.h" +#include "Math/Vector4D.h" + +// Standard Library +#include +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using std::array; +using namespace o2::aod::rctsel; + +///// Aliases for joined tables +/// Collisions: +using SelCollisions = soa::Join; // Added PVMults to get MultNTracksPVeta1 as centrality estimator +using SelCollisionsSimple = soa::Join; // Simpler, for jets + +/// V0s and Daughter tracks: +// using V0Candidates = soa::Join; +// using V0CandidatesSimple = soa::Join; // No TOF +/// To run in RAW data: +// using V0Candidates = aod::V0Datas; // TODO: possible quicker subscription for analysis that do not require TOF. +using V0CandidatesWithTOF = soa::Join; // Tables created by o2-analysis-lf-strangenesstofpid +// using DauTracks = soa::Join; +// Actually used subscriptions (smaller memory usage): +using DauTracks = soa::Join; + +/// Jets: +using PseudoJetTracks = soa::Join; // Simpler tracks access. (Not using TracksIU and TracksCovIU. Did not use their info for now) + // , aod::pidTOFFullPi, aod::pidTOFFullKa, aod::pidTOFFullPr>; // Not using TOF right now due to some possible mismatches + +/// MC: +// using SimCollisions = soa::Join; +// using DauTracksMC = soa::Join; + +enum CentEstimator { + kCentFT0C = 0, + kCentFT0M, + kCentFV0A +}; + +enum JetAlgorithm { + kKt = 0, + kCambridgeAachen, + kAntiKt +}; + +enum JetRecombScheme { + kEScheme = 0, + kPtScheme = 1, + kPt2Scheme = 2, + kWTAScheme = 7 +}; + +enum JetType { + kChargedJet = 0, + kFullJet, + kPhotonJet, + kZJet +}; + +enum BkgSubtraction { + kNoSubtraction = 0, + kAreaBased, + kConstituentBased +}; + +////////////////////////////////////////////// +struct lambdajetpolarizationions { + + // struct : ProducesGroup { + // } products; + Produces tableV0s; + Produces tableJets; + Produces tableLeadParticles; + Produces tableCollisions; + + // Define histogram registries: + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + // master analysis switches + Configurable analyseLambda{"analyseLambda", true, "process Lambda-like candidates"}; + Configurable analyseAntiLambda{"analyseAntiLambda", false, "process AntiLambda-like candidates"}; // Will work only with Lambdas, in a first analysis + + Configurable doPPAnalysis{"doPPAnalysis", false, "if in pp, set to true. Default is HI"}; + Configurable irSource{"irSource", "ZNChadronic", "Estimator of the interaction rate (Recommended: pp --> T0VTX, Pb-Pb --> ZNChadronic)"}; // Renamed David's "ZNC hadronic" to the proper code "ZNChadronic" + Configurable centralityEstimatorForQA{"centralityEstimatorForQA", kCentFT0M, "Run 3 centrality estimator (0:CentFT0C, 1:CentFT0M, 2:CentFV0A)"}; // Default is FT0M + // (Now saving all centralities at the derived data level -- Makes them all available for consumer) + // (But still using this variable for QA histograms) + + ///////////////////////////////////////////// + Configurable doEventQA{"doEventQA", false, "do event QA histograms"}; + // Configurable qaCentrality{"qaCentrality", false, "qa centrality flag: check base raw values"}; + Configurable doCompleteTopoQA{"doCompleteTopoQA", false, "do topological variables QA histograms"}; // Includes doPlainTopoQA from derivedlambdakzeroanalysis + Configurable doV0KinematicQA{"doV0KinematicQA", false, "do kinematic variables QA histograms"}; + Configurable doArmenterosQA{"doArmenterosQA", false, "do Armenteros QA histograms"}; + Configurable doTPCQA{"doTPCQA", false, "do TPC QA histograms"}; + Configurable doTOFQA{"doTOFQA", false, "do TOF QA histograms"}; + Configurable doEtaPhiQA{"doEtaPhiQA", false, "do Eta/Phi QA histograms for V0s and daughters"}; + Configurable doJetKinematicsQA{"doJetKinematicsQA", false, "do pT,Eta,Phi QA histograms for jets"}; + ///////////////////////////////////////////// + + // ///////////////////////////////////////////// + // MC block -- not implemented! (TODO) + // Configurable doMCAssociation{"doMCAssociation", true, "if MC, do MC association"}; + // Configurable doTreatPiToMuon{"doTreatPiToMuon", false, "Take pi decay into muon into account in MC"}; + // Configurable doCollisionAssociationQA{"doCollisionAssociationQA", true, "check collision association"}; + // ///////////////////////////////////////////// + + // TODO: COMPLEMENTARY ANALYSES TO STUDY SPURIOUS POLARIZATION SOURCES! + // TODO: add an event plane selection procedure to get an angle between the global polarization axis and the jet axis to uncouple polarizations? + // TODO: (related to previous comment) if we already have event plane, also estimate v_2-caused polarization. Hydro papers indicate observable is unsensitive to this spurious polarization, but this is a perfect consistency check. + // TODO: add a longitudinal polarization block of code to estimate other sources of polarization (and possibly study their differential dependence on the angle wrlt the jets and their rings)? + // TODO: add a block of code that calculates polarization from Lambda fragmentation to estimate the contamination of this third source of polarization + + // Configurable groups: + struct : ConfigurableGroup { + std::string prefix = "eventSelections"; // JSON group name + Configurable requireSel8{"requireSel8", true, "require sel8 event selection"}; + Configurable requireTriggerTVX{"requireTriggerTVX", true, "require FT0 vertex (acceptable FT0C-FT0A time difference) at trigger level"}; // part of sel8, actually + Configurable rejectITSROFBorder{"rejectITSROFBorder", true, "reject events at ITS ROF border (Run 3 only)"}; // part of sel8, actually + Configurable rejectTFBorder{"rejectTFBorder", true, "reject events at TF border (Run 3 only)"}; // part of sel8, actually + Configurable requireIsVertexITSTPC{"requireIsVertexITSTPC", false, "require events with at least one ITS-TPC track (Run 3 only)"}; + Configurable requireIsGoodZvtxFT0VsPV{"requireIsGoodZvtxFT0VsPV", true, "require events with PV position along z consistent (within 1 cm) between PV reconstructed using tracks and PV using FT0 A-C time difference (Run 3 only)"}; // o2::aod::evsel::kIsGoodZvtxFT0vsPV. Recommended for OO + Configurable requireIsVertexTOFmatched{"requireIsVertexTOFmatched", false, "require events with at least one of vertex contributors matched to TOF (Run 3 only)"}; + Configurable requireIsVertexTRDmatched{"requireIsVertexTRDmatched", false, "require events with at least one of vertex contributors matched to TRD (Run 3 only)"}; + Configurable rejectSameBunchPileup{"rejectSameBunchPileup", true, "reject collisions in case of pileup with another collision in the same foundBC (Run 3 only)"}; // o2::aod::evsel::kNoSameBunchPileup. Recommended for OO + Configurable requireNoCollInTimeRangeStd{"requireNoCollInTimeRangeStd", false, "reject collisions corrupted by the cannibalism, with other collisions within +/- 2 microseconds or mult above a certain threshold in -4 - -2 microseconds (Run 3 only)"}; + Configurable requireNoCollInTimeRangeStrict{"requireNoCollInTimeRangeStrict", false, "reject collisions corrupted by the cannibalism, with other collisions within +/- 10 microseconds (Run 3 only)"}; + Configurable requireNoCollInTimeRangeNarrow{"requireNoCollInTimeRangeNarrow", false, "reject collisions corrupted by the cannibalism, with other collisions within +/- 2 microseconds (Run 3 only)"}; + Configurable requireNoCollInROFStd{"requireNoCollInROFStd", false, "reject collisions corrupted by the cannibalism, with other collisions within the same ITS ROF with mult. above a certain threshold (Run 3 only)"}; + Configurable requireNoCollInROFStrict{"requireNoCollInROFStrict", false, "reject collisions corrupted by the cannibalism, with other collisions within the same ITS ROF (Run 3 only)"}; + Configurable requireINEL0{"requireINEL0", true, "require INEL>0 event selection"}; // Only truly useful in pp + Configurable requireINEL1{"requireINEL1", false, "require INEL>1 event selection"}; + + Configurable maxZVtxPosition{"maxZVtxPosition", 10., "max Z vtx position"}; + + Configurable useEvtSelInDenomEff{"useEvtSelInDenomEff", false, "Consider event selections in the recoed <-> gen collision association for the denominator (or numerator) of the acc. x eff. (or signal loss)?"}; + Configurable applyZVtxSelOnMCPV{"applyZVtxSelOnMCPV", true, "Apply Z-vtx cut on the PV of the generated collision?"}; // I see no reason as to not do this by default + Configurable useFT0CbasedOccupancy{"useFT0CbasedOccupancy", false, "Use sum of FT0-C amplitudes for estimating occupancy? (if not, use track-based definition)"}; + // fast check on occupancy + Configurable minOccupancy{"minOccupancy", -1, "minimum occupancy from neighbouring collisions"}; + Configurable maxOccupancy{"maxOccupancy", -1, "maximum occupancy from neighbouring collisions"}; + // fast check on interaction rate + Configurable minIR{"minIR", -1, "minimum IR collisions"}; + Configurable maxIR{"maxIR", -1, "maximum IR collisions"}; + } eventSelections; + + struct : ConfigurableGroup { + std::string prefix = "v0Selections"; // JSON group name + Configurable v0TypeSelection{"v0TypeSelection", 1, "select on a certain V0 type (leave negative if no selection desired)"}; + + // Selection criteria: acceptance + Configurable rapidityCut{"rapidityCut", 1.0f, "rapidity"}; + Configurable v0EtaCut{"v0EtaCut", 0.9f, "eta cut for v0"}; + Configurable daughterEtaCut{"daughterEtaCut", 0.9f, "max eta for daughters"}; // Default is 0.8. Changed to 0.9 to agree with jet selection. TODO: test the impact/biasing of this! + + // Standard 5 topological criteria -- Closed a bit more for the Lambda analysis + Configurable v0cospa{"v0cospa", 0.995, "min V0 CosPA"}; // Default is 0.97 + Configurable dcav0dau{"dcav0dau", 1.0, "max DCA V0 Daughters (cm)"}; // Default is 1.0 + // Configurable dcanegtopv{"dcanegtopv", .2, "min DCA Neg To PV (cm)"}; // Default is .05 + // Configurable dcapostopv{"dcapostopv", .05, "min DCA Pos To PV (cm)"}; // Default is .05 + // Renamed for better consistency of candidate selection (the cut is not determined by charge, but by mass and how deflected the daughter is): + Configurable dcaPionToPV{"dcaPionToPV", .2, "min DCA pion-like daughter To PV (cm)"}; // Default is .05. Suppresses pion background. + Configurable dcaProtonToPV{"dcaProtonToPV", .05, "min DCA proton-like daughter To PV (cm)"}; // Default is .05 + Configurable v0radius{"v0radius", 1.2, "minimum V0 radius (cm)"}; // Default is 1.2 + Configurable v0radiusMax{"v0radiusMax", 1E5, "maximum V0 radius (cm)"}; + Configurable lambdaLifetimeCut{"lambdaLifetimeCut", 30., "lifetime cut (c*tau) for Lambda (cm)"}; + + // invariant mass selection + Configurable compMassRejection{"compMassRejection", -1, "Competing mass rejection (GeV/#it{c}^{2})"}; // This was creating bumps in the pp analysis code's invariant mass. Turned off for now. + + // Track quality + Configurable minTPCrows{"minTPCrows", 70, "minimum TPC crossed rows"}; + Configurable minITSclusters{"minITSclusters", 3, "minimum ITS clusters"}; // Default is off + Configurable minTPCrowsOverFindableClusters{"minTPCrowsOverFindableClusters", -1, "minimum nbr of TPC crossed rows over findable clusters"}; + Configurable minTPCfoundOverFindableClusters{"minTPCfoundOverFindableClusters", -1, "minimum nbr of found over findable TPC clusters"}; + Configurable maxFractionTPCSharedClusters{"maxFractionTPCSharedClusters", 1e+09, "maximum fraction of TPC shared clusters"}; + Configurable maxITSchi2PerNcls{"maxITSchi2PerNcls", 36.0f, "maximum ITS chi2 per clusters"}; // Default is 1e+09. New values from StraInJets recommendations + Configurable maxTPCchi2PerNcls{"maxTPCchi2PerNcls", 4.0f, "maximum TPC chi2 per clusters"}; // Default is 1e+09 + Configurable skipTPConly{"skipTPConly", false, "skip V0s comprised of at least one TPC only prong"}; + Configurable requirePosITSonly{"requirePosITSonly", false, "require that positive track is ITSonly (overrides TPC quality)"}; + Configurable requireNegITSonly{"requireNegITSonly", false, "require that negative track is ITSonly (overrides TPC quality)"}; + Configurable rejectPosITSafterburner{"rejectPosITSafterburner", false, "reject positive track formed out of afterburner ITS tracks"}; + Configurable rejectNegITSafterburner{"rejectNegITSafterburner", false, "reject negative track formed out of afterburner ITS tracks"}; + Configurable requirePosITSafterburnerOnly{"requirePosITSafterburnerOnly", false, "require positive track formed out of afterburner ITS tracks"}; + Configurable requireNegITSafterburnerOnly{"requireNegITSafterburnerOnly", false, "require negative track formed out of afterburner ITS tracks"}; + Configurable rejectTPCsectorBoundary{"rejectTPCsectorBoundary", false, "reject tracks close to the TPC sector boundaries"}; + Configurable phiLowCut{"phiLowCut", "0.06/x+pi/18.0-0.06", "Low azimuth cut parametrisation"}; + Configurable phiHighCut{"phiHighCut", "0.1/x+pi/18.0+0.06", "High azimuth cut parametrisation"}; + + // PID (TPC/TOF) + Configurable tpcPidNsigmaCut{"tpcPidNsigmaCut", 3, "tpcPidNsigmaCut"}; // Default is 5. Reduced to agree with strangenessInJetsIons + Configurable tofPidNsigmaCutLaPr{"tofPidNsigmaCutLaPr", 1e+6, "tofPidNsigmaCutLaPr"}; + Configurable tofPidNsigmaCutLaPi{"tofPidNsigmaCutLaPi", 1e+6, "tofPidNsigmaCutLaPi"}; + + // PID (TOF) + Configurable maxDeltaTimeProton{"maxDeltaTimeProton", 1e+9, "check maximum allowed time"}; + Configurable maxDeltaTimePion{"maxDeltaTimePion", 1e+9, "check maximum allowed time"}; + } v0Selections; + + // Helpers for the "isTrackFarFromTPCBoundary" function: + TF1* fPhiCutLow = new TF1("fPhiCutLow", v0Selections.phiLowCut.value.data(), 0, 100); + TF1* fPhiCutHigh = new TF1("fPhiCutHigh", v0Selections.phiHighCut.value.data(), 0, 100); + + // Run Condition Table (RCT) configurables + struct : ConfigurableGroup { + std::string prefix = "rctConfigurations"; // JSON group name + Configurable cfgRCTLabel{"cfgRCTLabel", "", "Which detector condition requirements? (CBT, CBT_hadronPID, CBT_electronPID, CBT_calo, CBT_muon, CBT_muon_glo)"}; + Configurable cfgCheckZDC{"cfgCheckZDC", false, "Include ZDC flags in the bit selection (for Pb-Pb only)"}; + Configurable cfgTreatLimitedAcceptanceAsBad{"cfgTreatLimitedAcceptanceAsBad", false, "reject all events where the detectors relevant for the specified Runlist are flagged as LimitedAcceptance"}; + } rctConfigurations; + RCTFlagsChecker rctFlagsChecker{rctConfigurations.cfgRCTLabel.value}; + + // ML SELECTIONS BLOCK -- NOT IMPLEMENTED! (TODO) + + // CCDB options + struct : ConfigurableGroup { + std::string prefix = "ccdbConfigurations"; // JSON group name + Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; + Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + Configurable lutPath{"lutPath", "GLO/Param/MatLUT", "Path of the Lut parametrization"}; + Configurable geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; + Configurable mVtxPath{"mVtxPath", "GLO/Calib/MeanVertex", "Path of the mean vertex file"}; + + // manual magnetic field: + Configurable useCustomMagField{"useCustomMagField", false, "Use custom magnetic field value"}; + Configurable customMagField{"customMagField", 5.0f, "Manually set magnetic field"}; + } ccdbConfigurations; + + // Instantiating CCDB: + o2::ccdb::CcdbApi ccdbApi; + Service ccdb; + + // Other useful variables: + ctpRateFetcher rateFetcher; + int mRunNumber; + float magField; + std::map metadata; + o2::parameters::GRPMagField* grpmag = nullptr; + + // Histogram axes configuration: + struct : ConfigurableGroup { + std::string prefix = "axisConfigurations"; // JSON group name + ConfigurableAxis axisPt{"axisPt", {VARIABLE_WIDTH, 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f, 1.1f, 1.2f, 1.3f, 1.4f, 1.5f, 1.6f, 1.7f, 1.8f, 1.9f, 2.0f, 2.2f, 2.4f, 2.6f, 2.8f, 3.0f, 3.2f, 3.4f, 3.6f, 3.8f, 4.0f, 4.4f, 4.8f, 5.2f, 5.6f, 6.0f, 6.5f, 7.0f, 7.5f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 17.0f, 19.0f, 21.0f, 23.0f, 25.0f, 30.0f, 35.0f, 40.0f, 50.0f}, "pt axis for analysis"}; + ConfigurableAxis axisPtXi{"axisPtXi", {VARIABLE_WIDTH, 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f, 1.1f, 1.2f, 1.3f, 1.4f, 1.5f, 1.6f, 1.7f, 1.8f, 1.9f, 2.0f, 2.2f, 2.4f, 2.6f, 2.8f, 3.0f, 3.2f, 3.4f, 3.6f, 3.8f, 4.0f, 4.4f, 4.8f, 5.2f, 5.6f, 6.0f, 6.5f, 7.0f, 7.5f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 17.0f, 19.0f, 21.0f, 23.0f, 25.0f, 30.0f, 35.0f, 40.0f, 50.0f}, "pt axis for feeddown from Xi"}; + ConfigurableAxis axisPtCoarse{"axisPtCoarse", {VARIABLE_WIDTH, 0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 7.0f, 10.0f, 15.0f}, "pt axis for QA"}; + ConfigurableAxis axisLambdaMass{"axisLambdaMass", {450, 1.08f, 1.15f}, ""}; // Default is {200, 1.101f, 1.131f} + ConfigurableAxis axisCentrality{"axisCentrality", {VARIABLE_WIDTH, 0.0f, 5.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f}, "Centrality"}; + ConfigurableAxis axisNch{"axisNch", {500, 0.0f, +5000.0f}, "Number of charged particles"}; + ConfigurableAxis axisIRBinning{"axisIRBinning", {500, 0, 50}, "Binning for the interaction rate (kHz)"}; + ConfigurableAxis axisMultFT0M{"axisMultFT0M", {500, 0.0f, +100000.0f}, "Multiplicity FT0M"}; + ConfigurableAxis axisMultFT0C{"axisMultFT0C", {500, 0.0f, +10000.0f}, "Multiplicity FT0C"}; + ConfigurableAxis axisMultFV0A{"axisMultFV0A", {500, 0.0f, +100000.0f}, "Multiplicity FV0A"}; + + ConfigurableAxis axisRawCentrality{"axisRawCentrality", {VARIABLE_WIDTH, 0.000f, 52.320f, 75.400f, 95.719f, 115.364f, 135.211f, 155.791f, 177.504f, 200.686f, 225.641f, 252.645f, 281.906f, 313.850f, 348.302f, 385.732f, 426.307f, 470.146f, 517.555f, 568.899f, 624.177f, 684.021f, 748.734f, 818.078f, 892.577f, 973.087f, 1058.789f, 1150.915f, 1249.319f, 1354.279f, 1465.979f, 1584.790f, 1710.778f, 1844.863f, 1985.746f, 2134.643f, 2291.610f, 2456.943f, 2630.653f, 2813.959f, 3006.631f, 3207.229f, 3417.641f, 3637.318f, 3865.785f, 4104.997f, 4354.938f, 4615.786f, 4885.335f, 5166.555f, 5458.021f, 5762.584f, 6077.881f, 6406.834f, 6746.435f, 7097.958f, 7462.579f, 7839.165f, 8231.629f, 8635.640f, 9052.000f, 9484.268f, 9929.111f, 10389.350f, 10862.059f, 11352.185f, 11856.823f, 12380.371f, 12920.401f, 13476.971f, 14053.087f, 14646.190f, 15258.426f, 15890.617f, 16544.433f, 17218.024f, 17913.465f, 18631.374f, 19374.983f, 20136.700f, 20927.783f, 21746.796f, 22590.880f, 23465.734f, 24372.274f, 25314.351f, 26290.488f, 27300.899f, 28347.512f, 29436.133f, 30567.840f, 31746.818f, 32982.664f, 34276.329f, 35624.859f, 37042.588f, 38546.609f, 40139.742f, 41837.980f, 43679.429f, 45892.130f, 400000.000f}, "raw centrality signal"}; // for QA + + ConfigurableAxis axisOccupancy{"axisOccupancy", {VARIABLE_WIDTH, 0.0f, 250.0f, 500.0f, 750.0f, 1000.0f, 1500.0f, 2000.0f, 3000.0f, 4500.0f, 6000.0f, 8000.0f, 10000.0f, 50000.0f}, "Occupancy"}; + + // topological variable QA axes + ConfigurableAxis axisDCAtoPV{"axisDCAtoPV", {20, 0.0f, 1.0f}, "DCA (cm)"}; + ConfigurableAxis axisDCAdau{"axisDCAdau", {20, 0.0f, 2.0f}, "DCA (cm)"}; + ConfigurableAxis axisPointingAngle{"axisPointingAngle", {20, 0.0f, 2.0f}, "pointing angle (rad)"}; + ConfigurableAxis axisV0Radius{"axisV0Radius", {20, 0.0f, 60.0f}, "V0 2D radius (cm)"}; + ConfigurableAxis axisNsigmaTPC{"axisNsigmaTPC", {200, -10.0f, 10.0f}, "N sigma TPC"}; + ConfigurableAxis axisTPCsignal{"axisTPCsignal", {200, 0.0f, 200.0f}, "TPC signal"}; + ConfigurableAxis axisNsigmaTOF{"axisNsigmaTOF", {200, -10.0f, 10.0f}, "N sigma TOF"}; + ConfigurableAxis axisTOFdeltaT{"axisTOFdeltaT", {200, -5000.0f, 5000.0f}, "TOF Delta T (ps)"}; + ConfigurableAxis axisPhi{"axisPhi", {50, 0.0f, constants::math::TwoPI}, "Azimuth angle (rad)"}; + ConfigurableAxis axisPhiMod{"axisPhiMod", {100, 0.0f, constants::math::TwoPI / 18}, "Azimuth angle wrt TPC sector (rad.)"}; + ConfigurableAxis axisEta{"axisEta", {50, -1.0f, 1.0f}, "#eta"}; + ConfigurableAxis axisRapidity{"axisRapidity", {50, -1.0f, 1.0f}, "y"}; + ConfigurableAxis axisITSchi2{"axisITSchi2", {100, 0.0f, 100.0f}, "#chi^{2} per ITS clusters"}; + ConfigurableAxis axisTPCchi2{"axisTPCchi2", {100, 0.0f, 100.0f}, "#chi^{2} per TPC clusters"}; + ConfigurableAxis axisTPCrowsOverFindable{"axisTPCrowsOverFindable", {120, 0.0f, 1.2f}, "Fraction of TPC crossed rows over findable clusters"}; + ConfigurableAxis axisTPCfoundOverFindable{"axisTPCfoundOverFindable", {120, 0.0f, 1.2f}, "Fraction of TPC found over findable clusters"}; + ConfigurableAxis axisTPCsharedClusters{"axisTPCsharedClusters", {101, -0.005f, 1.005f}, "Fraction of TPC shared clusters"}; + + // AP plot axes + ConfigurableAxis axisAPAlpha{"axisAPAlpha", {220, -1.1f, 1.1f}, "V0 AP alpha"}; + ConfigurableAxis axisAPQt{"axisAPQt", {220, 0.0f, 0.5f}, "V0 AP alpha"}; + + // Track quality axes + ConfigurableAxis axisTPCrows{"axisTPCrows", {160, 0.0f, 160.0f}, "N TPC rows"}; + ConfigurableAxis axisITSclus{"axisITSclus", {7, 0.0f, 7.0f}, "N ITS Clusters"}; + ConfigurableAxis axisITScluMap{"axisITScluMap", {128, -0.5f, 127.5f}, "ITS Cluster map"}; + ConfigurableAxis axisDetMap{"axisDetMap", {16, -0.5f, 15.5f}, "Detector use map"}; + ConfigurableAxis axisITScluMapCoarse{"axisITScluMapCoarse", {16, -3.5f, 12.5f}, "ITS Coarse cluster map"}; + ConfigurableAxis axisDetMapCoarse{"axisDetMapCoarse", {5, -0.5f, 4.5f}, "Detector Coarse user map"}; + + // MC coll assoc QA axis + ConfigurableAxis axisMonteCarloNch{"axisMonteCarloNch", {300, 0.0f, 3000.0f}, "N_{ch} MC"}; + + // Jet QA axes: + ConfigurableAxis JetsPerEvent{"JetsPerEvent", {20, 0, 20}, "Jets per event"}; + + ConfigurableAxis axisLeadingParticlePt{"axisLeadingParticlePt", {200, 0.f, 200.f}, "Leading particle p_{T} (GeV/c)"}; // Simpler version! + ConfigurableAxis axisJetPt{"axisJetPt", {200, 0.f, 200.f}, "Jet p_{t} (GeV)"}; + ConfigurableAxis axisCosTheta{"axisCosTheta", {50, -1.f, 1.f}, "cos(#Delta #theta_{jet})"}; + ConfigurableAxis axisDeltaPhi{"axisDeltaPhi", {50, -constants::math::PI, constants::math::PI}, "#Delta #phi"}; + ConfigurableAxis axisDeltaEta{"axisDeltaEta", {50, -1.5f, 1.5f}, "#Delta #phi"}; // Calculated as twice the subtraction "eta_max=0.9 - R_min=0.2", with a margin + ConfigurableAxis axisDeltaR{"axisDeltaR", {50, 0, 3.5f}, "#Delta R"}; // From 0 to about the maximum Delta R possible with R = 0.2 + ConfigurableAxis axisEnergy{"axisEnergy", {200, 0.f, 200.f}, "E_{jet} (GeV) (#pi mass hypothesis)"}; // Jet energy is not that well defined here, due to track mass hypothesis being of pions! This is just to include px,py,pz in full! + } axisConfigurations; + + // Jet selection configuration: + // (TODO: create a reasonable track selection for full, photon, and Z-tagged jet tracks, including detector angular acceptance parameters for EMCal) + struct : ConfigurableGroup { + std::string prefix = "jetConfigurations"; // JSON group name + Configurable minJetPt{"minJetPt", 30.0f, "Minimum reconstructed pt of the jet (GeV/c)"}; // Something in between pp and PbPb minima. Change for bkgSubtraction true or false! + Configurable radiusJet{"radiusJet", 0.4f, "Jet resolution parameter (R)"}; // (TODO: check if the JE people don't define this as a rescaled int to not lose precision for stricter selections) + // Notice that the maximum Eta of the jet will then be 0.9 - R to keep the jet contained within the ITS+TPC barrel. + + Configurable jetAlgorithm{"jetAlgorithm", kAntiKt, "jet clustering algorithm. 0 = kT, 1 = C/A, 2 = Anti-kT"}; + Configurable jetRecombScheme{"jetRecombScheme", kEScheme, "Jet recombination scheme: 0: E_scheme, 1: pT-scheme, 2: pt2-scheme, 7: WTA_pt_scheme"}; // See PWGJE/JetFinders/jetFinder.h for more info. + Configurable bkgSubtraction{"bkgSubtraction", kNoSubtraction, "Jet background subtraction: No subtraction (false), Area (true), Constituent (TODO)"}; // Selection bool for background subtraction strategy + Configurable GhostedAreaSpecRapidity{"GhostedAreaSpecRapidity", 1.1, "Max ghost particle rapidity for jet area estimates"}; // At least 1.0 for tracks and jets within the |eta| < 0.9 window of ITS+TPC + // Using an enum for readability: + Configurable jetType{"jetType", kChargedJet, "Jet type: 0: Charged Jet, 1: Full Jet, 2: Photon-tagged, 3: Z-tagged"}; // TODO: implement full, photon and Z jets + // (TODO: check the maximum pT of jets used in my analyses! If it is way too hard, it might not be the best jet to use!) + + // (TODO: Check which of these configurables might be useful for the photon-tagged and regular analyses) + // // Configurables from JE PWG: + // Configurable jetEWSPtMin{"jetEWSPtMin", 0.0, "minimum event-wise subtracted jet pT"}; + // Configurable jetEWSPtMax{"jetEWSPtMax", 1000.0, "maximum event-wise subtracted jet pT"}; + // Configurable jetGhostArea{"jetGhostArea", 0.005, "jet ghost area"}; + // Configurable ghostRepeat{"ghostRepeat", 0, "set to 0 to gain speed if you dont need area calculation"}; + // Configurable DoTriggering{"DoTriggering", false, "used for the charged jet trigger to remove the eta constraint on the jet axis"}; + // Configurable jetAreaFractionMin{"jetAreaFractionMin", -99.0, "used to make a cut on the jet areas"}; + // // cluster level configurables + // Configurable clusterDefinitionS{"clusterDefinition", "kV3Default", "cluster definition to be selected, e.g. V3Default"}; + // Configurable clusterEtaMin{"clusterEtaMin", -0.71, "minimum cluster eta"}; // For ECMAL: |eta| < 0.7, phi = 1.40 - 3.26 + // Configurable clusterEtaMax{"clusterEtaMax", 0.71, "maximum cluster eta"}; // For ECMAL: |eta| < 0.7, phi = 1.40 - 3.26 + // Configurable clusterPhiMin{"clusterPhiMin", 1.39, "minimum cluster phi"}; + // Configurable clusterPhiMax{"clusterPhiMax", 3.27, "maximum cluster phi"}; + // Configurable clusterEnergyMin{"clusterEnergyMin", 0.5, "minimum cluster energy in EMCAL (GeV)"}; + // Configurable clusterTimeMin{"clusterTimeMin", -25., "minimum Cluster time (ns)"}; + // Configurable clusterTimeMax{"clusterTimeMax", 25., "maximum Cluster time (ns)"}; + // Configurable clusterRejectExotics{"clusterRejectExotics", true, "Reject exotic clusters"}; + // Configurable hadronicCorrectionType{"hadronicCorrectionType", 0, "0 = no correction, 1 = CorrectedOneTrack1, 2 = CorrectedOneTrack2, 3 = CorrectedAllTracks1, 4 = CorrectedAllTracks2"}; + // Configurable doEMCALEventSelection{"doEMCALEventSelection", true, "apply the selection to the event alias_bit for full and neutral jets"}; + // Configurable doEMCALEventSelectionChargedJets{"doEMCALEventSelectionChargedJets", false, "apply the selection to the event alias_bit for charged jets"}; + + Configurable minLeadParticlePt{"minLeadParticlePt", 2.0f, "Minimum Pt for a lead track to be considered a valid proxy for a jet"}; // For OO, about 2 or 3 should be enough (z~0.3 of jet), and for PbPb maybe 8 GeV + } jetConfigurations; + + // Creating a short map to make sure the proper FastJet enums are used (safeguard against possible updates in FastJet indices): + fastjet::JetAlgorithm mapFJAlgorithm(int algoIdx) + { + switch (algoIdx) { + case 0: + return fastjet::kt_algorithm; + case 1: + return fastjet::cambridge_algorithm; + case 2: + return fastjet::antikt_algorithm; + default: + throw std::invalid_argument("Unknown jet algorithm"); + } + } + fastjet::RecombinationScheme mapFJRecombScheme(int schemeIdx) + { + switch (schemeIdx) { + case 0: + return fastjet::E_scheme; + case 1: + return fastjet::pt_scheme; + case 2: + return fastjet::pt2_scheme; + case 7: + return fastjet::WTA_pt_scheme; + default: + throw std::invalid_argument("Unknown recombination scheme"); + } + } + + // Track analysis parameters -- A specific group that is different from the v0Selections. In jet analyses we need to control our PseudoJet candidates! + // (TODO: include minimal selection criteria for electrons, muons and photons) + // Notice you do NOT need any PID for the PseudoJet candidates! Only need is to know the 4-momentum appropriately. Thus removed nsigma checks on PID + struct : ConfigurableGroup { + std::string prefix = "pseudoJetCandidateTrackSelections"; // JSON group name + Configurable minNCrossedRowsTPC{"minNCrossedRowsTPC", 70, "Minimum number of TPC crossed rows"}; + Configurable minITSnCls{"minITSnCls", -1, "Minimum number of ITS clusters"}; + Configurable maxChi2TPC{"maxChi2TPC", 5.0f, "Maximum chi2 per cluster TPC"}; // Loose cuts for pseudojet candidate selection + Configurable maxChi2ITS{"maxChi2ITS", 40.0f, "Maximum chi2 per cluster ITS"}; + Configurable etaCut{"etaCut", 0.9f, "Maximum eta absolute value"}; // (TODO: same test as the previous 0.8 eta cut) + + Configurable minCandidatePt{"minCandidatePt", 0.15f, "Minimum track pt for pseudojet candidate (GeV/c)"}; // Reduces number of pseudojet candidates from IR radiation + // (TODO: test these minimal ratios to suppress split tracks in high occupancy PbPb or OO) + // Configurable minTPCrowsOverFindableClusters{"minTPCrowsOverFindableClusters", -1, "minimum nbr of TPC crossed rows over findable clusters"}; + // Configurable minTPCfoundOverFindableClusters{"minTPCfoundOverFindableClusters", 0.8f, "minimum nbr of found over findable TPC clusters"}; + + // Jets typical cuts (suppress non-primary candidates): + Configurable doDCAcuts{"doDCAcuts", false, "Apply DCA cuts to jet candidates (biases towards primary-vertex/prompt hadron jets)"}; + Configurable maxDCAz{"maxDCAz", 3.2f, "Max DCAz to primary vertex [cm] (remove pileup influence)"}; + + // Configurable maxDCAxy{"maxDCAxy", 2.4f,"Max DCAxy to primary vertex [cm]"}; + // Using same cuts as the StrangenessInJets analysis, with a pt dependence (which may bias high pt, so use with care): + Configurable dcaxyMaxTrackPar0{"dcaxyMaxTrackPar0", 0.0105f, "Asymptotic DCA resolution at high pt [cm]"}; + Configurable dcaxyMaxTrackPar1{"dcaxyMaxTrackPar1", 0.035f, "Low pt multiple-scattering term for DCA resolution [cm*(GeV/c)^Par2]"}; + Configurable dcaxyMaxTrackPar2{"dcaxyMaxTrackPar2", 1.1f, "Exponent of pt dependence of DCA resolution"}; + } pseudoJetCandidateTrackSelections; + + JetBkgSubUtils backgroundSub; + + void init(InitContext const&) + { + // setting CCDB service + ccdb->setURL(ccdbConfigurations.ccdbUrl); + ccdb->setCaching(true); + ccdb->setFatalWhenNull(false); + + // Initialise the RCTFlagsChecker + rctFlagsChecker.init(rctConfigurations.cfgRCTLabel.value, rctConfigurations.cfgCheckZDC, rctConfigurations.cfgTreatLimitedAcceptanceAsBad); + + // Event Counters + histos.add("hEventSelection", "hEventSelection", kTH1D, {{23, -0.5f, +20.5f}}); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(1, "All collisions"); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(2, "sel8 cut"); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(3, "kIsTriggerTVX"); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(4, "kNoITSROFrameBorder"); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(5, "kNoTimeFrameBorder"); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(6, "posZ cut"); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(7, "kIsVertexITSTPC"); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(8, "kIsGoodZvtxFT0vsPV"); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(9, "kIsVertexTOFmatched"); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(10, "kIsVertexTRDmatched"); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(11, "kNoSameBunchPileup"); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(12, "kNoCollInTimeRangeStd"); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(13, "kNoCollInTimeRangeStrict"); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(14, "kNoCollInTimeRangeNarrow"); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(15, "kNoCollInRofStd"); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(16, "kNoCollInRofStrict"); + if (doPPAnalysis) { + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(17, "INEL>0"); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(18, "INEL>1"); + } else { + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(17, "Below min occup."); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(18, "Above max occup."); + } + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(19, "Below min IR"); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(20, "Above max IR"); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(21, "RCT flags"); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(22, "hasRingJet"); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(23, "hasRingV0"); + // (notice we lack a hasRingJet AND hasRingV0 bin because the tasks run separately on all events!) + // (this QA number can be obtained at derived data level with ease) + + histos.add("Centrality/hEventCentrality", "hEventCentrality", kTH1D, {{101, 0.0f, 101.0f}}); + histos.add("Centrality/hCentralityVsNch", "hCentralityVsNch", kTH2D, {{101, 0.0f, 101.0f}, axisConfigurations.axisNch}); + if (doEventQA) { + histos.add("hEventSelectionVsCentrality", "hEventSelectionVsCentrality", kTH2D, {{23, -0.5f, +20.5f}, {101, 0.0f, 101.0f}}); + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(1, "All collisions"); + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(2, "sel8 cut"); + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(3, "kIsTriggerTVX"); + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(4, "kNoITSROFrameBorder"); + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(5, "kNoTimeFrameBorder"); + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(6, "posZ cut"); + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(7, "kIsVertexITSTPC"); + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(8, "kIsGoodZvtxFT0vsPV"); + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(9, "kIsVertexTOFmatched"); + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(10, "kIsVertexTRDmatched"); + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(11, "kNoSameBunchPileup"); + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(12, "kNoCollInTimeRangeStd"); + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(13, "kNoCollInTimeRangeStrict"); + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(14, "kNoCollInTimeRangeNarrow"); + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(15, "kNoCollInRofStd"); + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(16, "kNoCollInRofStrict"); + if (doPPAnalysis) { + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(17, "INEL>0"); + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(18, "INEL>1"); + } else { + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(17, "Below min occup."); + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(18, "Above max occup."); + } + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(19, "Below min IR"); + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(20, "Above max IR"); + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(21, "RCT flags"); + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(22, "hasRingJet"); + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(23, "hasRingV0"); + + // Centrality: + histos.add("Centrality/hEventCentVsMultFT0M", "hEventCentVsMultFT0M", kTH2D, {{101, 0.0f, 101.0f}, axisConfigurations.axisMultFT0M}); + histos.add("Centrality/hEventCentVsMultFT0C", "hEventCentVsMultFT0C", kTH2D, {{101, 0.0f, 101.0f}, axisConfigurations.axisMultFT0C}); + histos.add("Centrality/hEventCentVsMultFV0A", "hEventCentVsMultFV0A", kTH2D, {{101, 0.0f, 101.0f}, axisConfigurations.axisMultFV0A}); + histos.add("Centrality/hEventMultFT0CvsMultFV0A", "hEventMultFT0CvsMultFV0A", kTH2D, {axisConfigurations.axisMultFT0C, axisConfigurations.axisMultFV0A}); + } + + histos.add("hEventPVz", "hEventPVz", kTH1D, {{100, -20.0f, +20.0f}}); + histos.add("hCentralityVsPVz", "hCentralityVsPVz", kTH2D, {{101, 0.0f, 101.0f}, {100, -20.0f, +20.0f}}); + + // (TODO: add MC centrality vs PVz histos) + + histos.add("hEventOccupancy", "hEventOccupancy", kTH1D, {axisConfigurations.axisOccupancy}); + histos.add("hCentralityVsOccupancy", "hCentralityVsOccupancy", kTH2D, {{101, 0.0f, 101.0f}, axisConfigurations.axisOccupancy}); + histos.add("hInteractionRate", "hInteractionRate", kTH1D, {axisConfigurations.axisIRBinning}); + histos.add("hCentralityVsInteractionRate", "hCentralityVsInteractionRate", kTH2D, {{101, 0.0f, 101.0f}, axisConfigurations.axisIRBinning}); + histos.add("hInteractionRateVsOccupancy", "hInteractionRateVsOccupancy", kTH2D, {axisConfigurations.axisIRBinning, axisConfigurations.axisOccupancy}); + + // for QA and test purposes + // auto hRawCentrality = histos.add("Centrality/hRawCentrality", "hRawCentrality", kTH1D, {axisConfigurations.axisRawCentrality}); + + // for (int ii = 1; ii < 101; ii++) { + // float value = 100.5f - static_cast(ii); + // hRawCentrality->SetBinContent(ii, value); + // } + + ////////////////////////////////////////////////////////////// + /// Lambda / AntiLambda V0 selection QA + ////////////////////////////////////////////////////////////// + struct CutLabel { + std::string label; + bool enabled; + }; // A method of hiding labels of selections which were not used! + std::vector v0LambdaSelectionLabels = { + {"All V0 candidates", true}, + {"V0 radius (min)", true}, + {"V0 radius (max)", true}, + {"V0 cosPA", true}, + {"DCA_{V0 daughters}", true}, + {"|y_{#Lambda}|", v0Selections.rapidityCut > 0.f}, + {"K^{0}_{S} mass rejection", v0Selections.compMassRejection >= 0.f}, + {"ITS clusters (pos)", v0Selections.minITSclusters > 0}, + {"ITS #chi^{2}/N_{cls} (pos)", v0Selections.maxITSchi2PerNcls < 1e8}, + {"Reject ITS afterburner (pos)", v0Selections.rejectPosITSafterburner}, + {"Require ITS afterburner (pos)", v0Selections.requirePosITSafterburnerOnly}, + {"ITS clusters (neg)", v0Selections.minITSclusters > 0}, + {"ITS #chi^{2}/N_{cls} (neg)", v0Selections.maxITSchi2PerNcls < 1e8}, + {"Reject ITS afterburner (neg)", v0Selections.rejectNegITSafterburner}, + {"Require ITS afterburner (neg)", v0Selections.requireNegITSafterburnerOnly}, + {"TPC crossed rows (pos)", v0Selections.minTPCrows > 0}, + {"TPC #chi^{2}/N_{cls} (pos)", v0Selections.maxTPCchi2PerNcls < 1e8}, + {"TPC rows / findable (pos)", v0Selections.minTPCrowsOverFindableClusters >= 0}, + {"TPC found / findable (pos)", v0Selections.minTPCfoundOverFindableClusters >= 0}, + {"TPC shared clusters (pos)", v0Selections.maxFractionTPCSharedClusters < 1e8}, + {"TPC sector boundary (pos)", v0Selections.rejectTPCsectorBoundary}, + {"TPC crossed rows (neg)", v0Selections.minTPCrows > 0}, + {"TPC #chi^{2}/N_{cls} (neg)", v0Selections.maxTPCchi2PerNcls < 1e8}, + {"TPC rows / findable (neg)", v0Selections.minTPCrowsOverFindableClusters >= 0}, + {"TPC found / findable (neg)", v0Selections.minTPCfoundOverFindableClusters >= 0}, + {"TPC shared clusters (neg)", v0Selections.maxFractionTPCSharedClusters < 1e8}, + {"TPC sector boundary (neg)", v0Selections.rejectTPCsectorBoundary}, + {"Require ITS-only (pos)", v0Selections.requirePosITSonly}, + {"Require ITS-only (neg)", v0Selections.requireNegITSonly}, + {"Reject TPC-only (pos)", v0Selections.skipTPConly}, + {"Reject TPC-only (neg)", v0Selections.skipTPConly}, + }; // First, the labels that are hypothesis-agnostic + // Adding the Lambda or AntiLambda hypothesis labels as needed: + auto addHypothesis = [&](bool isLambda, bool analysisEnabled) { + if (!analysisEnabled) + return; // i.e., don't add these labels if not analyzing said particle type + std::string p = isLambda ? "#Lambda: " : "#bar{#Lambda}: "; + v0LambdaSelectionLabels.insert(v0LambdaSelectionLabels.end(), {{p + "DCA_{p} to PV", true}, + {p + "DCA_{#pi} to PV", true}, + {p + "TPC PID p", v0Selections.tpcPidNsigmaCut > 0}, + {p + "TPC PID #pi", v0Selections.tpcPidNsigmaCut > 0}, + {p + "TOF #Delta t p", v0Selections.maxDeltaTimeProton < 1e+9}, + {p + "TOF #Delta t #pi", v0Selections.maxDeltaTimePion < 1e+9}, + {p + "TOF PID p", v0Selections.tofPidNsigmaCutLaPr < 1e+6}, + {p + "TOF PID #pi", v0Selections.tofPidNsigmaCutLaPi < 1e+6}, + {p + "c#tau", v0Selections.lambdaLifetimeCut > 0}}); + }; + constexpr bool Lambda = true; // Some constexpr to make it more readable (works at compile level) + constexpr bool AntiLambda = false; // "false" is just a flag for this addHypothesis function! It just means fill "AntiLambda" labels + addHypothesis(Lambda, analyseLambda); + addHypothesis(AntiLambda, analyseAntiLambda); + + auto hSelectionV0s = histos.add("GeneralQA/hSelectionV0s", "V0 #rightarrow #Lambda / #bar{#Lambda} selection flow", kTH1D, + {{(int)v0LambdaSelectionLabels.size(), -0.5, (double)v0LambdaSelectionLabels.size() - 0.5}}); + for (size_t i = 0; i < v0LambdaSelectionLabels.size(); ++i) { + auto lbl = v0LambdaSelectionLabels[i].label; + if (!v0LambdaSelectionLabels[i].enabled) + lbl = "#color[16]{(off) " + lbl + "}"; + hSelectionV0s->GetXaxis()->SetBinLabel(i + 1, lbl.c_str()); // First non-underflow bin is bin 1 + } + //////////////////////////////////////////////// + // Jet track candidate selection flow (analogous to hSelectionV0s): + // Each label's "enabled" flag reflects whether the corresponding configurable + // makes that cut active, so disabled stages are shown in grey in the output. + std::vector jetTrackSelectionLabels = { + {"All track candidates", true}, + {"ITS clusters (min)", pseudoJetCandidateTrackSelections.minITSnCls >= 0}, + {"TPC crossed rows (min)", pseudoJetCandidateTrackSelections.minNCrossedRowsTPC > 0}, + {"TPC #chi^{2}/N_{cls} (max)", pseudoJetCandidateTrackSelections.maxChi2TPC < 1.e8f}, + {"ITS #chi^{2}/N_{cls} (max)", pseudoJetCandidateTrackSelections.maxChi2ITS < 1.e8f}, + {"p_{T} min", pseudoJetCandidateTrackSelections.minCandidatePt > 0.f}, + {"|#eta| cut", pseudoJetCandidateTrackSelections.etaCut < 1.5f}, + {"DCA_{z} to PV", pseudoJetCandidateTrackSelections.doDCAcuts.value}, + {"DCA_{xy} to PV (parametric)", pseudoJetCandidateTrackSelections.doDCAcuts.value}, + }; + auto hSelectionJetTracks = histos.add("GeneralQA/hSelectionJetTracks", "Charged pseudojet candidate selection flow", kTH1D, + {{(int)jetTrackSelectionLabels.size(), -0.5, (double)jetTrackSelectionLabels.size() - 0.5}}); + for (size_t i = 0; i < jetTrackSelectionLabels.size(); ++i) { + auto lbl = jetTrackSelectionLabels[i].label; + if (!jetTrackSelectionLabels[i].enabled) + lbl = "#color[16]{(off) " + lbl + "}"; + hSelectionJetTracks->GetXaxis()->SetBinLabel(i + 1, lbl.c_str()); + } + //////////////////////////////////////////////// + + // Histograms versus mass: + if (analyseLambda) { + histos.add("Lambda/h2dNbrOfLambdaVsCentrality", "h2dNbrOfLambdaVsCentrality", kTH2D, {axisConfigurations.axisCentrality, {10, -0.5f, 9.5f}}); + histos.add("Lambda/h3dMassLambda", "h3dMassLambda", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPt, axisConfigurations.axisLambdaMass}); + // Non-UPC info + histos.add("Lambda/h3dMassLambdaHadronic", "h3dMassLambdaHadronic", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPt, axisConfigurations.axisLambdaMass}); + if (doTPCQA) { + histos.add("Lambda/h3dPosNsigmaTPC", "h3dPosNsigmaTPC", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTPC}); + histos.add("Lambda/h3dNegNsigmaTPC", "h3dNegNsigmaTPC", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTPC}); + histos.add("Lambda/h3dPosTPCsignal", "h3dPosTPCsignal", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisTPCsignal}); + histos.add("Lambda/h3dNegTPCsignal", "h3dNegTPCsignal", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisTPCsignal}); + histos.add("Lambda/h3dPosNsigmaTPCvsTrackPtot", "h3dPosNsigmaTPCvsTrackPtot", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTPC}); + histos.add("Lambda/h3dNegNsigmaTPCvsTrackPtot", "h3dNegNsigmaTPCvsTrackPtot", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTPC}); + histos.add("Lambda/h3dPosTPCsignalVsTrackPtot", "h3dPosTPCsignalVsTrackPtot", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisTPCsignal}); + histos.add("Lambda/h3dNegTPCsignalVsTrackPtot", "h3dNegTPCsignalVsTrackPtot", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisTPCsignal}); + histos.add("Lambda/h3dPosNsigmaTPCvsTrackPt", "h3dPosNsigmaTPCvsTrackPt", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTPC}); + histos.add("Lambda/h3dNegNsigmaTPCvsTrackPt", "h3dNegNsigmaTPCvsTrackPt", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTPC}); + histos.add("Lambda/h3dPosTPCsignalVsTrackPt", "h3dPosTPCsignalVsTrackPt", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisTPCsignal}); + histos.add("Lambda/h3dNegTPCsignalVsTrackPt", "h3dNegTPCsignalVsTrackPt", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisTPCsignal}); + } + if (doTOFQA) { + histos.add("Lambda/h3dPosNsigmaTOF", "h3dPosNsigmaTOF", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTOF}); + histos.add("Lambda/h3dNegNsigmaTOF", "h3dNegNsigmaTOF", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTOF}); + histos.add("Lambda/h3dPosTOFdeltaT", "h3dPosTOFdeltaT", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisTOFdeltaT}); + histos.add("Lambda/h3dNegTOFdeltaT", "h3dNegTOFdeltaT", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisTOFdeltaT}); + histos.add("Lambda/h3dPosNsigmaTOFvsTrackPtot", "h3dPosNsigmaTOFvsTrackPtot", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTOF}); + histos.add("Lambda/h3dNegNsigmaTOFvsTrackPtot", "h3dNegNsigmaTOFvsTrackPtot", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTOF}); + histos.add("Lambda/h3dPosTOFdeltaTvsTrackPtot", "h3dPosTOFdeltaTvsTrackPtot", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisTOFdeltaT}); + histos.add("Lambda/h3dNegTOFdeltaTvsTrackPtot", "h3dNegTOFdeltaTvsTrackPtot", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisTOFdeltaT}); + histos.add("Lambda/h3dPosNsigmaTOFvsTrackPt", "h3dPosNsigmaTOFvsTrackPt", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTOF}); + histos.add("Lambda/h3dNegNsigmaTOFvsTrackPt", "h3dNegNsigmaTOFvsTrackPt", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTOF}); + histos.add("Lambda/h3dPosTOFdeltaTvsTrackPt", "h3dPosTOFdeltaTvsTrackPt", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisTOFdeltaT}); + histos.add("Lambda/h3dNegTOFdeltaTvsTrackPt", "h3dNegTOFdeltaTvsTrackPt", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisTOFdeltaT}); + } + // (TODO: add collision association capabilities in MC) + if (doEtaPhiQA) { + histos.add("Lambda/h5dV0PhiVsEta", "h5dV0PhiVsEta", kTHnD, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisLambdaMass, axisConfigurations.axisPhi, axisConfigurations.axisEta}); + histos.add("Lambda/h5dPosPhiVsEta", "h5dPosPhiVsEta", kTHnD, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisLambdaMass, axisConfigurations.axisPhi, axisConfigurations.axisEta}); + histos.add("Lambda/h5dNegPhiVsEta", "h5dNegPhiVsEta", kTHnD, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisLambdaMass, axisConfigurations.axisPhi, axisConfigurations.axisEta}); + } + } + if (analyseAntiLambda) { + histos.add("AntiLambda/h2dNbrOfAntiLambdaVsCentrality", "h2dNbrOfAntiLambdaVsCentrality", kTH2D, {axisConfigurations.axisCentrality, {10, -0.5f, 9.5f}}); + histos.add("AntiLambda/h3dMassAntiLambda", "h3dMassAntiLambda", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPt, axisConfigurations.axisLambdaMass}); + // Non-UPC info + histos.add("AntiLambda/h3dMassAntiLambdaHadronic", "h3dMassAntiLambdaHadronic", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPt, axisConfigurations.axisLambdaMass}); + if (doTPCQA) { + histos.add("AntiLambda/h3dPosNsigmaTPC", "h3dPosNsigmaTPC", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTPC}); + histos.add("AntiLambda/h3dNegNsigmaTPC", "h3dNegNsigmaTPC", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTPC}); + histos.add("AntiLambda/h3dPosTPCsignal", "h3dPosTPCsignal", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisTPCsignal}); + histos.add("AntiLambda/h3dNegTPCsignal", "h3dNegTPCsignal", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisTPCsignal}); + histos.add("AntiLambda/h3dPosNsigmaTPCvsTrackPtot", "h3dPosNsigmaTPCvsTrackPtot", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTPC}); + histos.add("AntiLambda/h3dNegNsigmaTPCvsTrackPtot", "h3dNegNsigmaTPCvsTrackPtot", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTPC}); + histos.add("AntiLambda/h3dPosTPCsignalVsTrackPtot", "h3dPosTPCsignalVsTrackPtot", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisTPCsignal}); + histos.add("AntiLambda/h3dNegTPCsignalVsTrackPtot", "h3dNegTPCsignalVsTrackPtot", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisTPCsignal}); + histos.add("AntiLambda/h3dPosNsigmaTPCvsTrackPt", "h3dPosNsigmaTPCvsTrackPt", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTPC}); + histos.add("AntiLambda/h3dNegNsigmaTPCvsTrackPt", "h3dNegNsigmaTPCvsTrackPt", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTPC}); + histos.add("AntiLambda/h3dPosTPCsignalVsTrackPt", "h3dPosTPCsignalVsTrackPt", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisTPCsignal}); + histos.add("AntiLambda/h3dNegTPCsignalVsTrackPt", "h3dNegTPCsignalVsTrackPt", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisTPCsignal}); + } + if (doTOFQA) { + histos.add("AntiLambda/h3dPosNsigmaTOF", "h3dPosNsigmaTOF", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTOF}); + histos.add("AntiLambda/h3dNegNsigmaTOF", "h3dNegNsigmaTOF", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTOF}); + histos.add("AntiLambda/h3dPosTOFdeltaT", "h3dPosTOFdeltaT", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisTOFdeltaT}); + histos.add("AntiLambda/h3dNegTOFdeltaT", "h3dNegTOFdeltaT", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisTOFdeltaT}); + histos.add("AntiLambda/h3dPosNsigmaTOFvsTrackPtot", "h3dPosNsigmaTOFvsTrackPtot", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTOF}); + histos.add("AntiLambda/h3dNegNsigmaTOFvsTrackPtot", "h3dNegNsigmaTOFvsTrackPtot", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTOF}); + histos.add("AntiLambda/h3dPosTOFdeltaTvsTrackPtot", "h3dPosTOFdeltaTvsTrackPtot", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisTOFdeltaT}); + histos.add("AntiLambda/h3dNegTOFdeltaTvsTrackPtot", "h3dNegTOFdeltaTvsTrackPtot", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisTOFdeltaT}); + histos.add("AntiLambda/h3dPosNsigmaTOFvsTrackPt", "h3dPosNsigmaTOFvsTrackPt", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTOF}); + histos.add("AntiLambda/h3dNegNsigmaTOFvsTrackPt", "h3dNegNsigmaTOFvsTrackPt", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTOF}); + histos.add("AntiLambda/h3dPosTOFdeltaTvsTrackPt", "h3dPosTOFdeltaTvsTrackPt", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisTOFdeltaT}); + histos.add("AntiLambda/h3dNegTOFdeltaTvsTrackPt", "h3dNegTOFdeltaTvsTrackPt", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisTOFdeltaT}); + } + if (doEtaPhiQA) { + histos.add("AntiLambda/h5dV0PhiVsEta", "h5dV0PhiVsEta", kTHnD, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisLambdaMass, axisConfigurations.axisPhi, axisConfigurations.axisEta}); + histos.add("AntiLambda/h5dPosPhiVsEta", "h5dPosPhiVsEta", kTHnD, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisLambdaMass, axisConfigurations.axisPhi, axisConfigurations.axisEta}); + histos.add("AntiLambda/h5dNegPhiVsEta", "h5dNegPhiVsEta", kTHnD, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisLambdaMass, axisConfigurations.axisPhi, axisConfigurations.axisEta}); + } + } + + if (analyseLambda) { + histos.add("hMassLambda", "hMassLambda", kTH1D, {axisConfigurations.axisLambdaMass}); + histos.add("Lambda/hLambdasPerEvent", "hLambdasPerEvent", kTH1D, {{15, 0, 15}}); + } + if (analyseAntiLambda) { + histos.add("hMassAntiLambda", "hMassAntiLambda", kTH1D, {axisConfigurations.axisLambdaMass}); + histos.add("AntiLambda/hAntiLambdasPerEvent", "hAntiLambdasPerEvent", kTH1D, {{15, 0, 15}}); + }; + if (analyseLambda && analyseAntiLambda) { + histos.add("hAmbiguousLambdaCandidates", "hAmbiguousLambdaCandidates", kTH1D, {{1, 0, 1}}); + histos.add("hAmbiguousPerEvent", "hAmbiguousPerEvent", kTH1D, {{15, 0, 15}}); + } + + // QA histograms if requested + if (doV0KinematicQA) { + if (analyseLambda) { + // --- Basic kinematics --- + histos.add("V0KinematicQA/Lambda/hPt", "Lambda p_{T}", kTH1D, {axisConfigurations.axisPt}); + histos.add("V0KinematicQA/Lambda/hY", "Lambda rapidity", kTH1D, {axisConfigurations.axisRapidity}); + histos.add("V0KinematicQA/Lambda/hPhi", "Lambda #varphi", kTH1D, {axisConfigurations.axisPhi}); + // --- Mass correlations --- + histos.add("V0KinematicQA/Lambda/hMassVsPt", "Lambda mass vs p_{T}", kTH2D, {axisConfigurations.axisPt, axisConfigurations.axisLambdaMass}); + histos.add("V0KinematicQA/Lambda/hMassVsY", "Lambda mass vs y", kTH2D, {axisConfigurations.axisRapidity, axisConfigurations.axisLambdaMass}); + histos.add("V0KinematicQA/Lambda/hMassVsPhi", "Lambda mass vs #varphi", kTH2D, {axisConfigurations.axisPhi, axisConfigurations.axisLambdaMass}); + // --- Kinematic correlations --- + histos.add("V0KinematicQA/Lambda/hYVsPt", "Lambda y vs p_{T}", kTH2D, {axisConfigurations.axisPt, axisConfigurations.axisRapidity}); + histos.add("V0KinematicQA/Lambda/hPhiVsPt", "Lambda #varphi vs p_{T}", kTH2D, {axisConfigurations.axisPt, axisConfigurations.axisPhi}); + } + if (analyseAntiLambda) { + // --- Basic kinematics --- + histos.add("V0KinematicQA/AntiLambda/hPt", "AntiLambda p_{T}", kTH1D, {axisConfigurations.axisPt}); + histos.add("V0KinematicQA/AntiLambda/hY", "AntiLambda rapidity", kTH1D, {axisConfigurations.axisRapidity}); + histos.add("V0KinematicQA/AntiLambda/hPhi", "AntiLambda #varphi", kTH1D, {axisConfigurations.axisPhi}); + // --- Mass correlations --- + histos.add("V0KinematicQA/AntiLambda/hMassVsPt", "AntiLambda mass vs p_{T}", kTH2D, {axisConfigurations.axisPt, axisConfigurations.axisLambdaMass}); + histos.add("V0KinematicQA/AntiLambda/hMassVsY", "AntiLambda mass vs y", kTH2D, {axisConfigurations.axisRapidity, axisConfigurations.axisLambdaMass}); + histos.add("V0KinematicQA/AntiLambda/hMassVsPhi", "AntiLambda mass vs #varphi", kTH2D, {axisConfigurations.axisPhi, axisConfigurations.axisLambdaMass}); + // --- Kinematic correlations --- + histos.add("V0KinematicQA/AntiLambda/hYVsPt", "AntiLambda y vs p_{T}", kTH2D, {axisConfigurations.axisPt, axisConfigurations.axisRapidity}); + histos.add("V0KinematicQA/AntiLambda/hPhiVsPt", "AntiLambda #varphi vs p_{T}", kTH2D, {axisConfigurations.axisPt, axisConfigurations.axisPhi}); + } + } + + if (doCompleteTopoQA) { + if (analyseLambda) { + histos.add("Lambda/h4dPosDCAToPV", "h4dPosDCAToPV", kTHnD, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisLambdaMass, axisConfigurations.axisDCAtoPV}); + histos.add("Lambda/h4dNegDCAToPV", "h4dNegDCAToPV", kTHnD, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisLambdaMass, axisConfigurations.axisDCAtoPV}); + histos.add("Lambda/h4dDCADaughters", "h4dDCADaughters", kTHnD, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisLambdaMass, axisConfigurations.axisDCAdau}); + histos.add("Lambda/h4dPointingAngle", "h4dPointingAngle", kTHnD, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisLambdaMass, axisConfigurations.axisPointingAngle}); + histos.add("Lambda/h4dV0Radius", "h4dV0Radius", kTHnD, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisLambdaMass, axisConfigurations.axisV0Radius}); + } + if (analyseAntiLambda) { + histos.add("AntiLambda/h4dPosDCAToPV", "h4dPosDCAToPV", kTHnD, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisLambdaMass, axisConfigurations.axisDCAtoPV}); + histos.add("AntiLambda/h4dNegDCAToPV", "h4dNegDCAToPV", kTHnD, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisLambdaMass, axisConfigurations.axisDCAtoPV}); + histos.add("AntiLambda/h4dDCADaughters", "h4dDCADaughters", kTHnD, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisLambdaMass, axisConfigurations.axisDCAdau}); + histos.add("AntiLambda/h4dPointingAngle", "h4dPointingAngle", kTHnD, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisLambdaMass, axisConfigurations.axisPointingAngle}); + histos.add("AntiLambda/h4dV0Radius", "h4dV0Radius", kTHnD, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisLambdaMass, axisConfigurations.axisV0Radius}); + } + + // For all received candidates: + histos.add("V0KinematicQA/hPosDCAToPV", "hPosDCAToPV", kTH1D, {axisConfigurations.axisDCAtoPV}); + histos.add("V0KinematicQA/hNegDCAToPV", "hNegDCAToPV", kTH1D, {axisConfigurations.axisDCAtoPV}); + histos.add("V0KinematicQA/hDCADaughters", "hDCADaughters", kTH1D, {axisConfigurations.axisDCAdau}); + histos.add("V0KinematicQA/hPointingAngle", "hPointingAngle", kTH1D, {axisConfigurations.axisPointingAngle}); + histos.add("V0KinematicQA/hV0Radius", "hV0Radius", kTH1D, {axisConfigurations.axisV0Radius}); + histos.add("V0KinematicQA/h2dPositiveITSvsTPCpts", "h2dPositiveITSvsTPCpts", kTH2D, {axisConfigurations.axisTPCrows, axisConfigurations.axisITSclus}); + histos.add("V0KinematicQA/h2dNegativeITSvsTPCpts", "h2dNegativeITSvsTPCpts", kTH2D, {axisConfigurations.axisTPCrows, axisConfigurations.axisITSclus}); + histos.add("V0KinematicQA/h2dPositivePtVsPhi", "h2dPositivePtVsPhi", kTH2D, {axisConfigurations.axisPtCoarse, axisConfigurations.axisPhiMod}); + histos.add("V0KinematicQA/h2dNegativePtVsPhi", "h2dNegativePtVsPhi", kTH2D, {axisConfigurations.axisPtCoarse, axisConfigurations.axisPhiMod}); + if (analyseLambda) { + histos.add("Lambda/hPosDCAToPV", "hPosDCAToPV", kTH1D, {axisConfigurations.axisDCAtoPV}); + histos.add("Lambda/hNegDCAToPV", "hNegDCAToPV", kTH1D, {axisConfigurations.axisDCAtoPV}); + histos.add("Lambda/hDCADaughters", "hDCADaughters", kTH1D, {axisConfigurations.axisDCAdau}); + histos.add("Lambda/hPointingAngle", "hPointingAngle", kTH1D, {axisConfigurations.axisPointingAngle}); + histos.add("Lambda/hV0Radius", "hV0Radius", kTH1D, {axisConfigurations.axisV0Radius}); + histos.add("Lambda/h2dPositiveITSvsTPCpts", "h2dPositiveITSvsTPCpts", kTH2D, {axisConfigurations.axisTPCrows, axisConfigurations.axisITSclus}); + histos.add("Lambda/h2dNegativeITSvsTPCpts", "h2dNegativeITSvsTPCpts", kTH2D, {axisConfigurations.axisTPCrows, axisConfigurations.axisITSclus}); + histos.add("Lambda/h2dPositivePtVsPhi", "h2dPositivePtVsPhi", kTH2D, {axisConfigurations.axisPtCoarse, axisConfigurations.axisPhiMod}); + histos.add("Lambda/h2dNegativePtVsPhi", "h2dNegativePtVsPhi", kTH2D, {axisConfigurations.axisPtCoarse, axisConfigurations.axisPhiMod}); + } + if (analyseAntiLambda) { + histos.add("AntiLambda/hPosDCAToPV", "hPosDCAToPV", kTH1D, {axisConfigurations.axisDCAtoPV}); + histos.add("AntiLambda/hNegDCAToPV", "hNegDCAToPV", kTH1D, {axisConfigurations.axisDCAtoPV}); + histos.add("AntiLambda/hDCADaughters", "hDCADaughters", kTH1D, {axisConfigurations.axisDCAdau}); + histos.add("AntiLambda/hPointingAngle", "hPointingAngle", kTH1D, {axisConfigurations.axisPointingAngle}); + histos.add("AntiLambda/hV0Radius", "hV0Radius", kTH1D, {axisConfigurations.axisV0Radius}); + histos.add("AntiLambda/h2dPositiveITSvsTPCpts", "h2dPositiveITSvsTPCpts", kTH2D, {axisConfigurations.axisTPCrows, axisConfigurations.axisITSclus}); + histos.add("AntiLambda/h2dNegativeITSvsTPCpts", "h2dNegativeITSvsTPCpts", kTH2D, {axisConfigurations.axisTPCrows, axisConfigurations.axisITSclus}); + histos.add("AntiLambda/h2dPositivePtVsPhi", "h2dPositivePtVsPhi", kTH2D, {axisConfigurations.axisPtCoarse, axisConfigurations.axisPhiMod}); + histos.add("AntiLambda/h2dNegativePtVsPhi", "h2dNegativePtVsPhi", kTH2D, {axisConfigurations.axisPtCoarse, axisConfigurations.axisPhiMod}); + } + } + + // Check ambiguous candidates in AP space: + histos.add("GeneralQA/h2dArmenterosAll", "h2dArmenterosAll", kTH2D, {axisConfigurations.axisAPAlpha, axisConfigurations.axisAPQt}); + histos.add("GeneralQA/h2dArmenterosKinematicSelected", "h2dArmenterosKinematicSelected", kTH2D, {axisConfigurations.axisAPAlpha, axisConfigurations.axisAPQt}); + histos.add("GeneralQA/h2dArmenterosFullSelected", "h2dArmenterosFullSelected", kTH2D, {axisConfigurations.axisAPAlpha, axisConfigurations.axisAPQt}); + histos.add("GeneralQA/h2dArmenterosFullSelectedLambda", "h2dArmenterosFullSelectedLambda", kTH2D, {axisConfigurations.axisAPAlpha, axisConfigurations.axisAPQt}); + histos.add("GeneralQA/h2dArmenterosFullSelectedAntiLambda", "h2dArmenterosFullSelectedAntiLambda", kTH2D, {axisConfigurations.axisAPAlpha, axisConfigurations.axisAPQt}); + histos.add("GeneralQA/h2dArmenterosFullSelectedAmbiguous", "h2dArmenterosFullSelectedAmbiguous", kTH2D, {axisConfigurations.axisAPAlpha, axisConfigurations.axisAPQt}); + + // Jets histograms: + // Histogram that needs to be present even out of QA: + histos.add("hEventsWithJet", "hEventsWithJet", kTH1D, {{1, 0, 1}}); + histos.add("hJetsPerEvent", "hJetsPerEvent", kTH1D, {axisConfigurations.JetsPerEvent}); + // counter of events with jet (could be interesting to compare with the minimum pT cut or between the background subtraction vs no background subtraction cases) + // number of jets per event + if (doJetKinematicsQA) { + histos.add("JetKinematicsQA/hJetPt", "hJetPt", kTH1D, {axisConfigurations.axisJetPt}); + histos.add("JetKinematicsQA/hJetEta", "hJetEta", kTH1D, {axisConfigurations.axisEta}); + histos.add("JetKinematicsQA/hJetPhi", "hJetPhi", kTH1D, {axisConfigurations.axisPhi}); + + histos.add("JetKinematicsQA/hCosThetaToLeadingJet", "hCosThetaToLeadingJet", kTH1D, {axisConfigurations.axisCosTheta}); + histos.add("JetKinematicsQA/hDeltaPhiToLeadingJet", "hDeltaPhiToLeadingJet", kTH1D, {axisConfigurations.axisDeltaPhi}); + histos.add("JetKinematicsQA/hDeltaEtaToLeadingJet", "hDeltaEtaToLeadingJet", kTH1D, {axisConfigurations.axisDeltaEta}); + histos.add("JetKinematicsQA/hDeltaRToLeadingJet", "hDeltaRToLeadingJet", kTH1D, {axisConfigurations.axisDeltaR}); + + histos.add("JetKinematicsQA/hLeadingJetPt", "hLeadingJetPt", kTH1D, {axisConfigurations.axisJetPt}); + histos.add("JetKinematicsQA/hLeadingJetEta", "hLeadingJetEta", kTH1D, {axisConfigurations.axisEta}); + histos.add("JetKinematicsQA/hLeadingJetPhi", "hLeadingJetPhi", kTH1D, {axisConfigurations.axisPhi}); + + // 2D correlations: + histos.add("JetKinematicsQA/h2dJetsPerEventvsLeadJetPt", "h2dJetsPerEventvsLeadJetPt", kTH2D, {axisConfigurations.JetsPerEvent, axisConfigurations.axisJetPt}); + histos.add("JetKinematicsQA/h2dJetsPerEventvsJetPt", "h2dJetsPerEventvsJetPt", kTH2D, {axisConfigurations.JetsPerEvent, axisConfigurations.axisJetPt}); + histos.add("JetKinematicsQA/h2dCosThetaToLeadvsDeltaPhiToLead", "h2dCosThetaToLeadvsDeltaPhiToLead", kTH2D, {axisConfigurations.axisCosTheta, axisConfigurations.axisDeltaPhi}); + histos.add("JetKinematicsQA/h2dCosThetaToLeadvsDeltaEtaToLead", "h2dCosThetaToLeadvsDeltaEtaToLead", kTH2D, {axisConfigurations.axisCosTheta, axisConfigurations.axisDeltaEta}); + histos.add("JetKinematicsQA/h2dCosThetaToLeadvsDeltaRToLead", "h2dCosThetaToLeadvsDeltaRToLead", kTH2D, {axisConfigurations.axisCosTheta, axisConfigurations.axisDeltaR}); + histos.add("JetKinematicsQA/h2dDeltaPhiToLeadvsDeltaEtaToLead", "h2dDeltaPhiToLeadvsDeltaEtaToLead", kTH2D, {axisConfigurations.axisDeltaPhi, axisConfigurations.axisDeltaEta}); // to see existence of back-to-back jets, and in which window + + // Comparisons to jet energy: + histos.add("JetKinematicsQA/h2dJetPtvsDeltaPhiToLead", "h2dJetPtvsDeltaPhiToLead", kTH2D, {axisConfigurations.axisJetPt, axisConfigurations.axisDeltaPhi}); + histos.add("JetKinematicsQA/h2dJetEnergyvsDeltaPhiToLead", "h2dJetEnergyvsDeltaPhiToLead", kTH2D, {axisConfigurations.axisEnergy, axisConfigurations.axisDeltaPhi}); + histos.add("JetKinematicsQA/h2dJetEnergyvsCosThetaToLead", "h2dJetEnergyvsCosThetaToLead", kTH2D, {axisConfigurations.axisEnergy, axisConfigurations.axisCosTheta}); + + // Jets per event vs correlation to lead jet + histos.add("JetKinematicsQA/h2dJetsPerEventvsDeltaPhiToLead", "h2dJetsPerEventvsDeltaPhiToLead", kTH2D, {axisConfigurations.JetsPerEvent, axisConfigurations.axisDeltaPhi}); + histos.add("JetKinematicsQA/h2dJetsPerEventvsDeltaEtaToLead", "h2dJetsPerEventvsDeltaEtaToLead", kTH2D, {axisConfigurations.JetsPerEvent, axisConfigurations.axisDeltaEta}); + histos.add("JetKinematicsQA/h2dJetsPerEventvsCosThetaToLead", "h2dJetsPerEventvsCosThetaToLead", kTH2D, {axisConfigurations.JetsPerEvent, axisConfigurations.axisCosTheta}); + + //////////////////////////// + // Leading particle 1D QA: + histos.add("JetVsLeadingParticleQA/hLeadingParticlePt", "hLeadingParticlePt", kTH1D, {axisConfigurations.axisLeadingParticlePt}); + histos.add("JetVsLeadingParticleQA/hLeadingParticleEta", "hLeadingParticleEta", kTH1D, {axisConfigurations.axisEta}); + histos.add("JetVsLeadingParticleQA/hLeadingParticlePhi", "hLeadingParticlePhi", kTH1D, {axisConfigurations.axisPhi}); + + // 1D correlations to lead jet: + histos.add("JetVsLeadingParticleQA/hCosThetaLeadParticleToJet", "hCosThetaLeadParticleToJet", kTH1D, {axisConfigurations.axisCosTheta}); + histos.add("JetVsLeadingParticleQA/hDeltaPhiLeadParticleToJet", "hDeltaPhiLeadParticleToJet", kTH1D, {axisConfigurations.axisDeltaPhi}); + histos.add("JetVsLeadingParticleQA/hDeltaEtaToLeadParticleToJet", "hDeltaEtaToLeadParticleToJet", kTH1D, {axisConfigurations.axisDeltaEta}); + + // Leading particle correlations: + histos.add("JetVsLeadingParticleQA/h2dDeltaPhiParticleToLeadvsDeltaEtaParticleToLead", "h2dDeltaPhiParticleToLeadvsDeltaEtaParticleToLead", kTH2D, {axisConfigurations.axisDeltaPhi, axisConfigurations.axisDeltaEta}); + + // Jets-per-event vs particle-to-lead correlations: + histos.add("JetVsLeadingParticleQA/h2dJetsPerEventvsDeltaPhiParticleToLead", "h2dJetsPerEventvsDeltaPhiParticleToLead", kTH2D, {axisConfigurations.JetsPerEvent, axisConfigurations.axisDeltaPhi}); + histos.add("JetVsLeadingParticleQA/h2dJetsPerEventvsDeltaEtaParticleToLead", "h2dJetsPerEventvsDeltaEtaParticleToLead", kTH2D, {axisConfigurations.JetsPerEvent, axisConfigurations.axisDeltaEta}); + histos.add("JetVsLeadingParticleQA/h2dJetsPerEventvsCosThetaParticleToLead", "h2dJetsPerEventvsCosThetaParticleToLead", kTH2D, {axisConfigurations.JetsPerEvent, axisConfigurations.axisCosTheta}); + + // Main "Leading jet vs leading particle" correlations: + histos.add("JetVsLeadingParticleQA/h2dJetsPerEventvsLeadParticlePt", "h2dJetsPerEventvsLeadParticlePt", kTH2D, {axisConfigurations.JetsPerEvent, axisConfigurations.axisLeadingParticlePt}); + histos.add("JetVsLeadingParticleQA/h2dLeadJetPtvsLeadParticlePt", "h2dLeadJetPtvsLeadParticlePt", kTH2D, {axisConfigurations.axisJetPt, axisConfigurations.axisLeadingParticlePt}); + histos.add("JetVsLeadingParticleQA/h2dLeadJetPtvsCosThetaParticleToLead", "h2dLeadJetPtvsCosThetaParticleToLead", kTH2D, {axisConfigurations.axisJetPt, axisConfigurations.axisCosTheta}); + histos.add("JetVsLeadingParticleQA/h2dLeadParticlePtvsCosThetaParticleToLead", "h2dLeadParticlePtvsCosThetaParticleToLead", kTH2D, {axisConfigurations.axisLeadingParticlePt, axisConfigurations.axisCosTheta}); + histos.add("JetVsLeadingParticleQA/h2dLeadJetPtvsDeltaPhiParticleToLead", "h2dLeadJetPtvsDeltaPhiParticleToLead", kTH2D, {axisConfigurations.axisJetPt, axisConfigurations.axisDeltaPhi}); + histos.add("JetVsLeadingParticleQA/h2dLeadParticlePtvsDeltaPhiParticleToLead", "h2dLeadParticlePtvsDeltaPhiParticleToLead", kTH2D, {axisConfigurations.axisLeadingParticlePt, axisConfigurations.axisDeltaPhi}); + } + + // inspect histogram sizes, please + histos.print(); + } + + template + auto getCentrality(TCollision const& collision) + { + if (centralityEstimatorForQA == kCentFT0M) + return collision.centFT0M(); + else if (centralityEstimatorForQA == kCentFT0C) + return collision.centFT0C(); + else if (centralityEstimatorForQA == kCentFV0A) + return collision.centFV0A(); + return -1.f; + } + + template + void initCCDB(TBC const& bc) + { + if (mRunNumber == bc.runNumber()) { + return; + } + + mRunNumber = bc.runNumber(); + + // Fetching magnetic field as requested + // In case override, don't proceed, please - no CCDB access required + if (ccdbConfigurations.useCustomMagField) { + magField = ccdbConfigurations.customMagField; + } else { + grpmag = ccdb->getForRun(ccdbConfigurations.grpmagPath, mRunNumber); + if (!grpmag) { + LOG(fatal) << "Got nullptr from CCDB for path " << ccdbConfigurations.grpmagPath << " of object GRPMagField and " << ccdbConfigurations.grpPath << " of object GRPObject for run " << mRunNumber; + } + // Fetch magnetic field from ccdb for current bc + magField = std::lround(5.f * grpmag->getL3Current() / 30000.f); + LOG(info) << "Retrieved GRP for run " << mRunNumber << " with magnetic field of " << magField << " kZG"; + } + } + + // Minimal helper to fill the hSelectionV0s histogram without having to deal with bins by myself + // (CAUTION! If you change selection order, change this too!) + struct V0SelectionFlowCounter { // Using struct to keep internal bin counter over different functions + int binValue = -1; // Starts at x=-1, which will go to bin 0 (underflow) in the definition of hSelectionV0s + // Made it like this because we use ++binValue when filling, so the first filled + // bin will always be x=0 due to operator precedence. + HistogramRegistry* histos = nullptr; // Had to pass the histos group to this struct, as it was not visible to the members of this struct + + void resetForNewV0() { binValue = -1; } + void fill() { histos->fill(HIST("GeneralQA/hSelectionV0s"), ++binValue); } // Hardcoded hSelectionV0s histogram, as it will not change. Increments before filling, by default + }; + V0SelectionFlowCounter V0SelCounter{0, &histos}; + + // Minimal helper to fill hSelectionJetTracks, mirroring V0SelectionFlowCounter. + // Reset once per track candidate, fill once per passed cut stage. + struct JetTrackSelectionFlowCounter { + int binValue = -1; // Same convention as V0: starts at -1, first fill goes to bin x=0 + HistogramRegistry* histos = nullptr; + void resetForNewTrack() { binValue = -1; } + void fill() { histos->fill(HIST("GeneralQA/hSelectionJetTracks"), ++binValue); } + }; + JetTrackSelectionFlowCounter JetTrackSelCounter{0, &histos}; + + // Short inlined helper to simplify QA + inline void fillEventSelectionQA(int bin, float centrality) + { + histos.fill(HIST("hEventSelection"), bin); + histos.fill(HIST("hEventSelectionVsCentrality"), bin, centrality); + } + + // Fill reconstructed event centrality information + // Based off fillReconstructedEventProperties, but optimized to avoid re-accessing information already present on isEventAccepted! + template + void fillCentralityProperties(TCollision const& collision, float centrality) + { + // if (qaCentrality) { + // auto hRawCentrality = histos.get(HIST("Centrality/hRawCentrality")); + // centrality = hRawCentrality->GetBinContent(hRawCentrality->FindBin(doPPAnalysis ? collision.multFT0A() + collision.multFT0C() : collision.multFT0C())); + // } + histos.fill(HIST("Centrality/hEventCentrality"), centrality); + histos.fill(HIST("Centrality/hCentralityVsNch"), centrality, collision.multNTracksPVeta1()); + if (doEventQA) { + histos.fill(HIST("Centrality/hEventCentVsMultFT0M"), collision.centFT0M(), collision.multFT0A() + collision.multFT0C()); + histos.fill(HIST("Centrality/hEventCentVsMultFT0C"), collision.centFT0C(), collision.multFT0C()); + histos.fill(HIST("Centrality/hEventCentVsMultFV0A"), collision.centFV0A(), collision.multFV0A()); + histos.fill(HIST("Centrality/hEventMultFT0CvsMultFV0A"), collision.multFT0C(), collision.multFV0A()); + } + return; + } + + ///////////////////////////////////////////// + // Computation helper functions: + double computePhiMod(double phi, int sign) + // Compute phi wrt to a TPC sector + // Calculation taken from CF: https://github.com/AliceO2Group/O2Physics/blob/376392cb87349886a300c75fa2492b50b7f46725/PWGCF/Flow/Tasks/flowAnalysisGF.cxx#L470 + { + if (magField < 0) // for negative polarity field + phi = o2::constants::math::TwoPI - phi; + if (sign < 0) // for negative charge + phi = o2::constants::math::TwoPI - phi; + if (phi < 0) + LOGF(warning, "phi < 0: %g", phi); + + phi += o2::constants::math::PI / 18.0; // to center gap in the middle + return fmod(phi, o2::constants::math::PI / 9.0); + } + + bool isTrackFarFromTPCBoundary(double trackPt, double trackPhi, int sign) + // check whether the track passes close to a TPC sector boundary + { + double phiModn = computePhiMod(trackPhi, sign); + if (phiModn > fPhiCutHigh->Eval(trackPt)) + return true; // keep track + if (phiModn < fPhiCutLow->Eval(trackPt)) + return true; // keep track + + return false; // reject track + } + + inline float cosThetaJets(const fastjet::PseudoJet& a, const fastjet::PseudoJet& b) + { + const double dot = a.px() * b.px() + a.py() * b.py() + a.pz() * b.pz(); + const double magA = std::sqrt(a.px() * a.px() + a.py() * a.py() + a.pz() * a.pz()); + const double magB = std::sqrt(b.px() * b.px() + b.py() * b.py() + b.pz() * b.pz()); + return dot / (magA * magB); + } + + ///////////////////////////////////////////// + // Helper functions for event and candidate selection: + template + bool isEventAccepted(TCollision const& collision, TBC const& bc, float centrality, bool fillHists) + { // check whether the collision passes our collision selections + int selectionIdx = 0; // To loop over QA histograms. First bin is already filled: first call will already increment this index (not actually the bin index, but a value in the X axis). + if (eventSelections.requireSel8 && !collision.sel8()) + return false; + if (fillHists) + fillEventSelectionQA(++selectionIdx, centrality); + if (eventSelections.requireTriggerTVX && !collision.selection_bit(aod::evsel::kIsTriggerTVX)) + return false; + if (fillHists) + fillEventSelectionQA(++selectionIdx, centrality); + if (eventSelections.rejectITSROFBorder && !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) + return false; + if (fillHists) + fillEventSelectionQA(++selectionIdx, centrality); + if (eventSelections.rejectTFBorder && !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) + return false; + if (fillHists) + fillEventSelectionQA(++selectionIdx, centrality); + + const float collisionPVz = collision.posZ(); + if (std::abs(collisionPVz) > eventSelections.maxZVtxPosition) + return false; + if (fillHists) + fillEventSelectionQA(++selectionIdx, centrality); + + if (eventSelections.requireIsVertexITSTPC && !collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) + return false; + if (fillHists) + fillEventSelectionQA(++selectionIdx, centrality); + if (eventSelections.requireIsGoodZvtxFT0VsPV && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) + return false; + if (fillHists) + fillEventSelectionQA(++selectionIdx, centrality); + if (eventSelections.requireIsVertexTOFmatched && !collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) + return false; + if (fillHists) + fillEventSelectionQA(++selectionIdx, centrality); + if (eventSelections.requireIsVertexTRDmatched && !collision.selection_bit(o2::aod::evsel::kIsVertexTRDmatched)) + return false; + if (fillHists) + fillEventSelectionQA(++selectionIdx, centrality); + if (eventSelections.rejectSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) + return false; + if (fillHists) + fillEventSelectionQA(++selectionIdx, centrality); + if (eventSelections.requireNoCollInTimeRangeStd && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) + return false; + if (fillHists) + fillEventSelectionQA(++selectionIdx, centrality); + if (eventSelections.requireNoCollInTimeRangeStrict && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStrict)) + return false; + if (fillHists) + fillEventSelectionQA(++selectionIdx, centrality); + if (eventSelections.requireNoCollInTimeRangeNarrow && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeNarrow)) + return false; + if (fillHists) + fillEventSelectionQA(++selectionIdx, centrality); + if (eventSelections.requireNoCollInROFStd && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) + return false; + if (fillHists) + fillEventSelectionQA(++selectionIdx, centrality); + if (eventSelections.requireNoCollInROFStrict && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStrict)) + return false; + if (fillHists) + fillEventSelectionQA(++selectionIdx, centrality); + + if (doPPAnalysis) { // we are in pp + if constexpr (requires { collision.multNTracksPVeta1(); }) { + // Only considers compiling this block when the collision type actually + // has multNTracksPVeta1(). This is done to reduce collision-table + // subscriptions in the jet processing function. + // This is a compile-time check: since the function is templated, it + // is instantiated separately for Jets and V0s, and this block will be + // properly compiled for each use case and table subscription automatically! + if (eventSelections.requireINEL0 && collision.multNTracksPVeta1() < 1) + return false; + if (fillHists) + fillEventSelectionQA(++selectionIdx, centrality); + if (eventSelections.requireINEL1 && collision.multNTracksPVeta1() < 2) + return false; + if (fillHists) + fillEventSelectionQA(++selectionIdx, centrality); + } + } else { // Performing selections as if in Pb-Pb: + const float collisionOccupancy = eventSelections.useFT0CbasedOccupancy ? collision.ft0cOccupancyInTimeRange() : collision.trackOccupancyInTimeRange(); + if (eventSelections.minOccupancy >= 0 && collisionOccupancy < eventSelections.minOccupancy) + return false; + if (fillHists) + fillEventSelectionQA(++selectionIdx, centrality); + if (eventSelections.maxOccupancy >= 0 && collisionOccupancy > eventSelections.maxOccupancy) + return false; + if (fillHists) + fillEventSelectionQA(++selectionIdx, centrality); + + // Fetch interaction rate only if required (in order to limit ccdb calls) + const double interactionRate = (eventSelections.minIR >= 0 || eventSelections.maxIR >= 0) ? rateFetcher.fetch(ccdb.service, bc.timestamp(), bc.runNumber(), irSource) * 1.e-3 : -1; + if (eventSelections.minIR >= 0 && interactionRate < eventSelections.minIR) + return false; + if (fillHists) + fillEventSelectionQA(++selectionIdx, centrality); + if (eventSelections.maxIR >= 0 && interactionRate > eventSelections.maxIR) + return false; + if (fillHists) + fillEventSelectionQA(++selectionIdx, centrality); + if (!rctConfigurations.cfgRCTLabel.value.empty() && !rctFlagsChecker(collision)) + return false; + if (fillHists) + fillEventSelectionQA(++selectionIdx, centrality); + + // Filling histograms previously filled in fillReconstructedEventProperties here, to avoid re-accessing data: + if (fillHists) { + histos.fill(HIST("hEventOccupancy"), collisionOccupancy); + histos.fill(HIST("hCentralityVsOccupancy"), centrality, collisionOccupancy); + histos.fill(HIST("hInteractionRate"), interactionRate); + histos.fill(HIST("hCentralityVsInteractionRate"), centrality, interactionRate); + histos.fill(HIST("hInteractionRateVsOccupancy"), interactionRate, collisionOccupancy); + } + } + + if (fillHists) { + histos.fill(HIST("hCentralityVsPVz"), centrality, collisionPVz); + histos.fill(HIST("hEventPVz"), collisionPVz); + } + return true; + } + + template + bool isCandidateForChargedPseudojetAccepted(JetCandidate const& track) + { // (TODO: add an equivalent for photon jets and Z jets, which don't consider charged particles) + // if (track.sign() == 0) return false; // Tracks are always either positive or negative, at least in TPC and ITS, which are the ones used (not looking at photon-jets right now) + // ITS/TPC cuts: + if (pseudoJetCandidateTrackSelections.minITSnCls >= 0) { + if (track.itsNCls() < pseudoJetCandidateTrackSelections.minITSnCls) + return false; + } + JetTrackSelCounter.fill(); // bin: ITS clusters (min) + + if (track.tpcNClsCrossedRows() < pseudoJetCandidateTrackSelections.minNCrossedRowsTPC) + return false; + JetTrackSelCounter.fill(); + + if (track.tpcChi2NCl() > pseudoJetCandidateTrackSelections.maxChi2TPC) + return false; + JetTrackSelCounter.fill(); + if (track.itsChi2NCl() > pseudoJetCandidateTrackSelections.maxChi2ITS) + return false; + JetTrackSelCounter.fill(); + + // Kinematics: + const float pt = track.pt(); + if (pt < pseudoJetCandidateTrackSelections.minCandidatePt) + return false; + JetTrackSelCounter.fill(); + if (std::fabs(track.eta()) > pseudoJetCandidateTrackSelections.etaCut) + return false; + JetTrackSelCounter.fill(); + + // DCA pseudojet candidate selections -- These select primary vertex particles for the jet: + if (pseudoJetCandidateTrackSelections.doDCAcuts) { + // if (std::fabs(track.dcaXY()) > pseudoJetCandidateTrackSelections.maxDCAxy) return false; + if (std::fabs(track.dcaZ()) > pseudoJetCandidateTrackSelections.maxDCAz) + return false; + JetTrackSelCounter.fill(); + // Slightly more physics-motivated cut (parametrizes the DCA resolution as function of pt) + if (std::fabs(track.dcaXY()) > (pseudoJetCandidateTrackSelections.dcaxyMaxTrackPar0 + + pseudoJetCandidateTrackSelections.dcaxyMaxTrackPar1 / std::pow(pt, pseudoJetCandidateTrackSelections.dcaxyMaxTrackPar2))) + return false; + JetTrackSelCounter.fill(); + } + return true; + } + + // Lambda selections: + template + bool passesGenericV0Cuts(TV0 const& v0) + { + // Base topological variables (high rejection, low cost checks) + if (v0.v0radius() < v0Selections.v0radius) + return false; + V0SelCounter.fill(); + if (v0.v0radius() > v0Selections.v0radiusMax) + return false; + V0SelCounter.fill(); + if (v0.v0cosPA() < v0Selections.v0cospa) + return false; + V0SelCounter.fill(); + if (v0.dcaV0daughters() > v0Selections.dcav0dau) + return false; + V0SelCounter.fill(); + + // pseudorapidity cuts: + if (std::fabs(v0.yLambda()) > v0Selections.rapidityCut) + return false; + // if (std::fabs(v0.eta()) > v0Selections.v0EtaCut) return false; + V0SelCounter.fill(); + // if (std::fabs(v0.eta()) > v0Selections.daughterEtaCut) return false; // (TODO: properly consider this in daughter selection!) + + // competing mass rejection (if compMassRejection < 0, this cut does nothing) + if (std::fabs(v0.mK0Short() - o2::constants::physics::MassK0Short) < v0Selections.compMassRejection) + return false; + V0SelCounter.fill(); + + const auto posTrackExtra = v0.template posTrack_as(); // (TODO: is it worth it to cache these transformations outside of the function? They are reused in the Lambda hypothesis checks) + const auto negTrackExtra = v0.template negTrack_as(); + + // ITS quality cuts + bool posIsFromAfterburner = posTrackExtra.isITSAfterburner(); + bool negIsFromAfterburner = negTrackExtra.isITSAfterburner(); + + // check minimum number of ITS clusters + maximum ITS chi2 per clusters + reject or select ITS afterburner tracks if requested + if (posTrackExtra.itsNCls() < v0Selections.minITSclusters) + return false; // check minimum ITS clusters + V0SelCounter.fill(); + if (posTrackExtra.itsChi2NCl() >= v0Selections.maxITSchi2PerNcls) + return false; // check maximum ITS chi2 per clusters + V0SelCounter.fill(); + if (v0Selections.rejectPosITSafterburner && posIsFromAfterburner) + return false; // reject afterburner track or not + V0SelCounter.fill(); + if (v0Selections.requirePosITSafterburnerOnly && !posIsFromAfterburner) + return false; // keep afterburner track or not + V0SelCounter.fill(); + + if (negTrackExtra.itsNCls() < v0Selections.minITSclusters) + return false; // check minimum ITS clusters + V0SelCounter.fill(); + if (negTrackExtra.itsChi2NCl() >= v0Selections.maxITSchi2PerNcls) + return false; // check maximum ITS chi2 per clusters + V0SelCounter.fill(); + if (v0Selections.rejectNegITSafterburner && negIsFromAfterburner) + return false; // reject afterburner track or not + V0SelCounter.fill(); + if (v0Selections.requireNegITSafterburnerOnly && !negIsFromAfterburner) + return false; // keep afterburner track or not + V0SelCounter.fill(); + + // TPC quality cuts + if (posTrackExtra.tpcNClsCrossedRows() < v0Selections.minTPCrows) + return false; // check minimum TPC crossed rows + V0SelCounter.fill(); + if (posTrackExtra.tpcChi2NCl() >= v0Selections.maxTPCchi2PerNcls) + return false; // check maximum TPC chi2 per clusters + V0SelCounter.fill(); + if (posTrackExtra.tpcCrossedRowsOverFindableCls() < v0Selections.minTPCrowsOverFindableClusters) + return false; // check minimum fraction of TPC rows over findable + V0SelCounter.fill(); + if (posTrackExtra.tpcFoundOverFindableCls() < v0Selections.minTPCfoundOverFindableClusters) + return false; // check minimum fraction of found over findable TPC clusters + V0SelCounter.fill(); + if (posTrackExtra.tpcFractionSharedCls() >= v0Selections.maxFractionTPCSharedClusters) + return false; // check the maximum fraction of allowed shared TPC clusters + V0SelCounter.fill(); + if (v0Selections.rejectTPCsectorBoundary && !isTrackFarFromTPCBoundary(v0.positivept(), v0.positivephi(), +1)) + return false; // reject track far from TPC sector boundary or not + V0SelCounter.fill(); + + if (negTrackExtra.tpcNClsCrossedRows() < v0Selections.minTPCrows) + return false; // check minimum TPC crossed rows + V0SelCounter.fill(); + if (negTrackExtra.tpcChi2NCl() >= v0Selections.maxTPCchi2PerNcls) + return false; // check maximum TPC chi2 per clusters + V0SelCounter.fill(); + if (negTrackExtra.tpcCrossedRowsOverFindableCls() < v0Selections.minTPCrowsOverFindableClusters) + return false; // check minimum fraction of TPC rows over findable + V0SelCounter.fill(); + if (negTrackExtra.tpcFoundOverFindableCls() < v0Selections.minTPCfoundOverFindableClusters) + return false; // check minimum fraction of found over findable TPC clusters + V0SelCounter.fill(); + if (negTrackExtra.tpcFractionSharedCls() >= v0Selections.maxFractionTPCSharedClusters) + return false; // check the maximum fraction of allowed shared TPC clusters + V0SelCounter.fill(); + if (v0Selections.rejectTPCsectorBoundary && !isTrackFarFromTPCBoundary(v0.negativept(), v0.negativephi(), -1)) + return false; // reject track far from TPC sector boundary or not + V0SelCounter.fill(); + + // ITS only tag + if (v0Selections.requirePosITSonly && posTrackExtra.tpcNClsCrossedRows() > 1) + return false; + V0SelCounter.fill(); + if (v0Selections.requireNegITSonly && negTrackExtra.tpcNClsCrossedRows() > 1) + return false; + V0SelCounter.fill(); + + // TPC only tag + if (v0Selections.skipTPConly && posTrackExtra.detectorMap() == o2::aod::track::TPC) + return false; + V0SelCounter.fill(); + if (v0Selections.skipTPConly && negTrackExtra.detectorMap() == o2::aod::track::TPC) + return false; + V0SelCounter.fill(); + + return true; + } + + // Tests the hypothesis of the V0 being a Lambda or of it being an antiLambda. + template + bool passesLambdaLambdaBarHypothesis(TV0 const& v0, TCollision const& collision, bool Lambda_hypothesis) + { + // Remaining topological cuts that were charge-dependent: + // (there is no real gain in doing a looser version of these in the passesGenericV0Cuts function. + // The DCA check will be done anyways and is very unexpensive) + // (even though they are high rejection, they demand a Lambda vs AntiLambda hypothesis, so they + // only appear here...) + const float dcaProtonToPV = Lambda_hypothesis ? std::abs(v0.dcapostopv()) : std::abs(v0.dcanegtopv()); + if (dcaProtonToPV < v0Selections.dcaProtonToPV) + return false; + V0SelCounter.fill(); + const float dcaPionToPV = Lambda_hypothesis ? std::abs(v0.dcanegtopv()) : std::abs(v0.dcapostopv()); // Checks Lambda_hypothesis twice, but compiler can handle it cleanly. + if (dcaPionToPV < v0Selections.dcaPionToPV) + return false; + V0SelCounter.fill(); + + const auto posTrackExtra = v0.template posTrack_as(); + const auto negTrackExtra = v0.template negTrack_as(); + + // For the PID cuts to be properly applied while also keeping this function + // general enough for Lambdas and AntiLambdas, we identify the roles of + // proton-like and pion-like for the pos and neg tracks accordingly: + auto const& protonTrack = Lambda_hypothesis ? posTrackExtra : negTrackExtra; + auto const& pionTrack = Lambda_hypothesis ? negTrackExtra : posTrackExtra; + + ///// Expensive PID checks come last: + // TPC PID + if (std::fabs(protonTrack.tpcNSigmaPr()) > v0Selections.tpcPidNsigmaCut) + return false; + V0SelCounter.fill(); + if (std::fabs(pionTrack.tpcNSigmaPi()) > v0Selections.tpcPidNsigmaCut) + return false; + V0SelCounter.fill(); + + // TOF PID in DeltaT (if TOF is not available, then uses the track. If is available, uses it. In this sense, TOF is optional) + // const bool posHasTOF = posTrackExtra.hasTOF(); // For the older version, which worked only for Lambdas + const bool protonHasTOF = protonTrack.hasTOF(); // Should work even without PIDResponseTOF.h, as it is a TracksExtra property + const bool pionHasTOF = pionTrack.hasTOF(); + + // Proton-like track + if (protonHasTOF && std::abs(Lambda_hypothesis ? v0.posTOFDeltaTLaPr() : v0.negTOFDeltaTLaPr()) > v0Selections.maxDeltaTimeProton) + return false; + V0SelCounter.fill(); + // Pion-like track + if (pionHasTOF && std::abs(Lambda_hypothesis ? v0.negTOFDeltaTLaPi() : v0.posTOFDeltaTLaPi()) > v0Selections.maxDeltaTimePion) + return false; + V0SelCounter.fill(); + + // TOF PID in NSigma (TODO: add asymmetric NSigma windows for purity tuning?) + // Proton-like track + if (protonHasTOF && std::fabs(v0.tofNSigmaLaPr()) > v0Selections.tofPidNsigmaCutLaPr) + return false; // (No need to select which candidate is which with the Lambda_hypothesis. Automatically done already!) + V0SelCounter.fill(); + // Pion-like track + if (pionHasTOF && std::fabs(v0.tofNSigmaLaPi()) > v0Selections.tofPidNsigmaCutLaPi) + return false; + V0SelCounter.fill(); + + // (CAUTION!) You cannot use the getter for raw data's PIDResponseTOF.h instead of LFStrangenessPIDTables.h (as below) + // If you do use, TOF will just try to identify that track as a proton, instead of using the correct path length from the + // V0s PV-DCA and the such! In other words, it is a naive estimator of TOF PID, because it does not correct for the V0 + // mother's travel time and considers all tracks as if they came from the PV! + // if (protonHasTOF && std::fabs(protonTrack.tofNSigmaPr()) > v0Selections.tofPidNsigmaCutLaPr) return false; + // To properly use the LFStrangenessPIDTables version, you need to call o2-analysis-lf-strangenesstofpid too. + + // proper lifetime + if (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassLambda0 > v0Selections.lambdaLifetimeCut) + return false; + V0SelCounter.fill(); + + return true; + } + + // Function to help distinguish ambiguous candidates (via Armenteros) that pass both + // the Lambda_hypothesis true (i.e., a Lambda) or false (i.e., an AntiLambda) checks + // (This function is only called in about 1-3% of the Lambda-Like V0s which remain ambiguous after all other cuts) + // int isCandidateArmenterosLambda(const float alpha, const float qt){ + // // Remove K0s band + // if (std::abs(alpha) < v0Selections.armK0AlphaThreshold && qt < v0Selections.armK0QtThreshold) return kIsArmenterosK0; + // // std::abs(alpha) < 0.2 && qt < 0.1 + // if (std::abs(alpha) < v0Selections.armMinAlpha) return kArmenterosAmbiguous; + // // std::abs(alpha) < 0.01f + // // Lambda selection + // if (alpha > 0) return kIsArmenterosLambda; + // else return kIsArmenterosAntiLambda; + // } + + // TODO: another possible check that could be done (if not implemented already inside mLambda() getters) + // template + // int isCandidateMassLambda(TV0 const& v0) { + // float m1 = v0.mLambda(); // proton=positive + // float m2 = v0.mAntiLambda(); // proton=negative + // float d = std::abs(m1 - mLambdaTrue) - std::abs(m2 - mLambdaTrue); + // if (d < 0.f) return +1; // Lambda + // else return -1; // AntiLambda + // } + + void processJetsData(SelCollisionsSimple::iterator const& collision, PseudoJetTracks const& tracks, aod::BCsWithTimestamps const& bcs) + { // Uses BCsWithTimestamps to get timestamps for rejectTPCsectorBoundary + float centrality = -1.0f; // Just a placeholder + + // For event QA the last two indices never change for NEv_withJets and NEv_withV0s + // (Not the best way to initialize this: runs once per collision! TODO: think of a better way to do it) + int lastBinEvSel = histos.get(HIST("hEventSelection"))->GetXaxis()->GetNbins(); + bool validJetAlreadyFound = false; // Do not fill Event QA more than once + + auto bc = bcs.iteratorAt(collision.bcId()); // Got the iteratorAt() idea from O2Physics/PWGUD/Core/UDHelpers.h + if (!isEventAccepted(collision, bc, centrality, false)) + return; // Uses return instead of continue, as there is no explicit loop here + const uint64_t collIdx = collision.globalIndex(); + + // Loop over reconstructed tracks: + std::vector fjParticles; + int leadingParticleIdx = -1; // Initialized as -1, but could leave it unitialized as well. We reject any invalid events where this could pose a problem (e.g., pT<=0) + float leadingParticlePt = 0; + for (auto const& track : tracks) { + JetTrackSelCounter.resetForNewTrack(); // reset bin counter for this candidate + JetTrackSelCounter.fill(); // bin: "All track candidates" + + // Require that tracks pass selection criteria + if (!isCandidateForChargedPseudojetAccepted(track)) + continue; + + // Constructing pseudojet candidates vector: + // Using pion mass as hypothesis for track energy estimate (before PID, all particles treated as if with the same invariant mass) + // (TODO: study the possibility of using identified PseudoJet candidates for this estimate) + fastjet::PseudoJet candidate(track.px(), track.py(), track.pz(), track.energy(o2::constants::physics::MassPionCharged)); + fjParticles.emplace_back(candidate); + + // Calculating leading particle + float pt = candidate.pt(); + if (pt > leadingParticlePt) { + leadingParticlePt = pt; + leadingParticleIdx = fjParticles.size() - 1; + } + } + // Reject empty events + if (fjParticles.size() < 1) + return; + + auto const& leadingParticle = fjParticles[leadingParticleIdx]; + if (leadingParticle.pt() > jetConfigurations.minLeadParticlePt) { // If not, leading particle is probably a bad proxy + tableLeadParticles(collIdx, leadingParticle.pt(), leadingParticle.eta(), leadingParticle.phi()); + } + + // Start jet clusterization: + // Cluster particles using the anti-kt algorithm + fastjet::JetDefinition jetDef(mapFJAlgorithm(jetConfigurations.jetAlgorithm), jetConfigurations.radiusJet, mapFJRecombScheme(jetConfigurations.jetRecombScheme)); + // std::vector jets_pt, jets_eta, jets_phi; // Not worth it to store 4-vectors: the tracks assume pion mass hypothesis, so energy and rapidity are not right. + if (jetConfigurations.bkgSubtraction == kAreaBased) { + fastjet::AreaDefinition areaDef(fastjet::active_area, fastjet::GhostedAreaSpec(jetConfigurations.GhostedAreaSpecRapidity)); + fastjet::ClusterSequenceArea clustSeq(fjParticles, jetDef, areaDef); // Attributes an area for each pseudojet in the list + std::vector jets = fastjet::sorted_by_pt(clustSeq.inclusive_jets()); // No minimum pt before background subtraction + if (jets.empty()) + return; + // Perpendicular cone area subtraction, not the traditional subtraction (TODO: include an option for traditional area subtraction) + auto [rhoPerp, rhoMPerp] = jetutilities::estimateRhoPerpCone(fjParticles, jets[0], jetConfigurations.radiusJet); // This uses a geometric, pi*R^2 area, not exactly a ghost-based area! + + // Loop over clustered jets: + int selectedJets = 0; + + fastjet::PseudoJet leadingJetSub; + // bool hasLeadingJet = false; // Not needed: if the event has any jet, that is the leading jet. Check is superseded by the selectedJets information + float leadingJetPt = -1.f; + for (const auto& jet : jets) { + // Jet must be fully contained in the acceptance (0.9 for ITS+TPC barrel) + const float jet_eta = jet.eta(); + if (std::fabs(jet_eta) > (0.9f - jetConfigurations.radiusJet)) + continue; + + auto jetForSub = jet; + // Subtracts same background estimated for highest pt jet, but every jet might have a slightly different area + // (TODO: check possible problems with OO and physics impacts of this particular cone method and choice of single background estimator based on leading jet) + // (TODO: improve for Pb-Pb, specially central!) + fastjet::PseudoJet jetMinusBkg = backgroundSub.doRhoAreaSub(jetForSub, rhoPerp, rhoMPerp); + // Jet pt must be larger than threshold: + if (jetMinusBkg.pt() < jetConfigurations.minJetPt) + continue; + selectedJets++; + + // Store jet: + tableJets(collIdx, + jetMinusBkg.pt(), + jetMinusBkg.eta(), // Using eta instead of rapidity + jetMinusBkg.phi(), + jetMinusBkg.constituents().size()); + + // Finding the leading jet after subtraction (leading jet is NOT known a priori!): + if (jetMinusBkg.pt() > leadingJetPt) { + leadingJetPt = jetMinusBkg.pt(); + leadingJetSub = jetMinusBkg; + } + } + histos.fill(HIST("hJetsPerEvent"), selectedJets); + if (selectedJets == 0) + return; + histos.fill(HIST("hEventsWithJet"), 0.5); + // Another version of this counter, which is already integrated in the Event Selection flow: + if (doEventQA && !validJetAlreadyFound) + fillEventSelectionQA(lastBinEvSel - 1, centrality); // hasRingJet passes + validJetAlreadyFound = true; + + if (doJetKinematicsQA) { + histos.fill(HIST("JetKinematicsQA/hLeadingJetPt"), leadingJetSub.pt()); + histos.fill(HIST("JetKinematicsQA/hLeadingJetEta"), leadingJetSub.eta()); + histos.fill(HIST("JetKinematicsQA/hLeadingJetPhi"), leadingJetSub.phi()); + + // Now looping through jets again to calculate the correlations: + for (const auto& jet : jets) { + // Will recalculated background subtraction during QA to avoid storing jets in memory when running in non-QA cases: + auto jetForSub = jet; + fastjet::PseudoJet jetMinusBkg = backgroundSub.doRhoAreaSub(jetForSub, rhoPerp, rhoMPerp); + + if (jetMinusBkg.pt() < jetConfigurations.minJetPt) + continue; + + float cosTheta = cosThetaJets(leadingJetSub, jetMinusBkg); + float deltaPhi = RecoDecay::constrainAngle(leadingJetSub.phi() - jetMinusBkg.phi(), -o2::constants::math::PI); + float deltaEta = leadingJetSub.eta() - jetMinusBkg.eta(); + float deltaR = std::sqrt(deltaPhi * deltaPhi + deltaEta * deltaEta); + + histos.fill(HIST("JetKinematicsQA/hCosThetaToLeadingJet"), cosTheta); + histos.fill(HIST("JetKinematicsQA/hDeltaPhiToLeadingJet"), deltaPhi); + histos.fill(HIST("JetKinematicsQA/hDeltaEtaToLeadingJet"), deltaEta); + histos.fill(HIST("JetKinematicsQA/hDeltaRToLeadingJet"), deltaR); + + // 2D correlations: + histos.fill(HIST("JetKinematicsQA/h2dJetsPerEventvsLeadJetPt"), selectedJets, leadingJetSub.pt()); + histos.fill(HIST("JetKinematicsQA/h2dJetsPerEventvsJetPt"), selectedJets, jetMinusBkg.pt()); + histos.fill(HIST("JetKinematicsQA/h2dCosThetaToLeadvsDeltaPhiToLead"), cosTheta, deltaPhi); + histos.fill(HIST("JetKinematicsQA/h2dCosThetaToLeadvsDeltaEtaToLead"), cosTheta, deltaEta); + histos.fill(HIST("JetKinematicsQA/h2dCosThetaToLeadvsDeltaRToLead"), cosTheta, deltaR); + histos.fill(HIST("JetKinematicsQA/h2dDeltaPhiToLeadvsDeltaEtaToLead"), deltaPhi, deltaEta); + + histos.fill(HIST("JetKinematicsQA/h2dJetPtvsDeltaPhiToLead"), jetMinusBkg.pt(), deltaPhi); // Can't really get the energy of the jet, just the pt to make this comparison + histos.fill(HIST("JetKinematicsQA/h2dJetEnergyvsDeltaPhiToLead"), jetMinusBkg.E(), deltaPhi); // Just a different scale + histos.fill(HIST("JetKinematicsQA/h2dJetEnergyvsCosThetaToLead"), jetMinusBkg.E(), cosTheta); + + histos.fill(HIST("JetKinematicsQA/h2dJetsPerEventvsDeltaPhiToLead"), selectedJets, deltaPhi); + histos.fill(HIST("JetKinematicsQA/h2dJetsPerEventvsDeltaEtaToLead"), selectedJets, deltaEta); + histos.fill(HIST("JetKinematicsQA/h2dJetsPerEventvsCosThetaToLead"), selectedJets, cosTheta); + } + // Leading particle comparisons: + histos.fill(HIST("JetVsLeadingParticleQA/hLeadingParticlePt"), leadingParticle.pt()); + histos.fill(HIST("JetVsLeadingParticleQA/hLeadingParticleEta"), leadingParticle.eta()); + histos.fill(HIST("JetVsLeadingParticleQA/hLeadingParticlePhi"), leadingParticle.phi()); + + float deltaPhiParticleToJet = RecoDecay::constrainAngle(leadingJetSub.phi() - leadingParticle.phi(), -o2::constants::math::PI); + float deltaEtaParticleToJet = leadingJetSub.eta() - leadingParticle.eta(); + float cosThetaParticleToJet = cosThetaJets(leadingJetSub, leadingParticle); // Takes advantage of the fact that this leading particle is a PseudoJet object + + histos.fill(HIST("JetVsLeadingParticleQA/hCosThetaLeadParticleToJet"), cosThetaParticleToJet); + histos.fill(HIST("JetVsLeadingParticleQA/hDeltaPhiLeadParticleToJet"), deltaPhiParticleToJet); + histos.fill(HIST("JetVsLeadingParticleQA/hDeltaEtaToLeadParticleToJet"), deltaEtaParticleToJet); + + histos.fill(HIST("JetVsLeadingParticleQA/h2dDeltaPhiParticleToLeadvsDeltaEtaParticleToLead"), deltaPhiParticleToJet, deltaEtaParticleToJet); + + histos.fill(HIST("JetVsLeadingParticleQA/h2dJetsPerEventvsDeltaPhiParticleToLead"), selectedJets, deltaPhiParticleToJet); + histos.fill(HIST("JetVsLeadingParticleQA/h2dJetsPerEventvsDeltaEtaParticleToLead"), selectedJets, deltaEtaParticleToJet); + histos.fill(HIST("JetVsLeadingParticleQA/h2dJetsPerEventvsCosThetaParticleToLead"), selectedJets, cosThetaParticleToJet); + + histos.fill(HIST("JetVsLeadingParticleQA/h2dJetsPerEventvsLeadParticlePt"), selectedJets, leadingParticle.pt()); + histos.fill(HIST("JetVsLeadingParticleQA/h2dLeadJetPtvsLeadParticlePt"), leadingJetSub.pt(), leadingParticle.pt()); + + histos.fill(HIST("JetVsLeadingParticleQA/h2dLeadJetPtvsCosThetaParticleToLead"), leadingJetSub.pt(), cosThetaParticleToJet); + histos.fill(HIST("JetVsLeadingParticleQA/h2dLeadParticlePtvsCosThetaParticleToLead"), leadingParticle.pt(), cosThetaParticleToJet); + + histos.fill(HIST("JetVsLeadingParticleQA/h2dLeadJetPtvsDeltaPhiParticleToLead"), leadingJetSub.pt(), deltaPhiParticleToJet); // To see if there is any backgound in phi due to soft jets (or soft particles below) + histos.fill(HIST("JetVsLeadingParticleQA/h2dLeadParticlePtvsDeltaPhiParticleToLead"), leadingParticle.pt(), deltaPhiParticleToJet); + } + } else { // Otherwise, simple jet clustering (TODO: this is the fall back for kConstituentBased while not implemented) + fastjet::ClusterSequence clustSeq(fjParticles, jetDef); + // Jet pt must be larger than threshold: + std::vector jets = fastjet::sorted_by_pt(clustSeq.inclusive_jets(jetConfigurations.minJetPt)); + + const int jetsInEvent = jets.size(); + histos.fill(HIST("hJetsPerEvent"), jetsInEvent); // Fills even in empty events, as this is a useful number to know! + + if (jetsInEvent == 0) + return; + histos.fill(HIST("hEventsWithJet"), 0.5); + // Another version of this counter, which is already integrated in the Event Selection flow: + if (doEventQA && !validJetAlreadyFound) + fillEventSelectionQA(lastBinEvSel - 1, centrality); // hasRingJet passes + validJetAlreadyFound = true; + + const auto& leadingJet = jets[0]; + for (const auto& jet : jets) { + // Jet must be fully contained in the acceptance (0.9 for ITS+TPC barrel) + const float jet_eta = jet.eta(); + if (std::fabs(jet_eta) > (0.9f - jetConfigurations.radiusJet)) + continue; + + tableJets(collIdx, + jet.pt(), + jet_eta, // Using eta instead of rapidity + jet.phi(), + jet.constituents().size()); + + if (doJetKinematicsQA) { + histos.fill(HIST("JetKinematicsQA/hJetPt"), jet.pt()); + histos.fill(HIST("JetKinematicsQA/hJetEta"), jet_eta); + histos.fill(HIST("JetKinematicsQA/hJetPhi"), jet.phi()); + + // Calculate angle to leading jet: + float cosTheta = cosThetaJets(leadingJet, jet); + + // Calculate angular separation in projected angles: + float deltaPhi = RecoDecay::constrainAngle(leadingJet.phi() - jet.phi(), -o2::constants::math::PI); + float deltaEta = leadingJet.eta() - jet_eta; + float deltaR = std::sqrt(deltaPhi * deltaPhi + deltaEta * deltaEta); // 2D angular distance in the eta-phi plane + + histos.fill(HIST("JetKinematicsQA/hCosThetaToLeadingJet"), cosTheta); // Measuring the cosine, not angle, because it is faster! + histos.fill(HIST("JetKinematicsQA/hDeltaPhiToLeadingJet"), deltaPhi); + histos.fill(HIST("JetKinematicsQA/hDeltaEtaToLeadingJet"), deltaEta); + histos.fill(HIST("JetKinematicsQA/hDeltaRToLeadingJet"), deltaR); + + // 2D correlations: + histos.fill(HIST("JetKinematicsQA/h2dJetsPerEventvsLeadJetPt"), jetsInEvent, leadingJet.pt()); + histos.fill(HIST("JetKinematicsQA/h2dJetsPerEventvsJetPt"), jetsInEvent, jet.pt()); + histos.fill(HIST("JetKinematicsQA/h2dCosThetaToLeadvsDeltaPhiToLead"), cosTheta, deltaPhi); + histos.fill(HIST("JetKinematicsQA/h2dCosThetaToLeadvsDeltaEtaToLead"), cosTheta, deltaEta); + histos.fill(HIST("JetKinematicsQA/h2dCosThetaToLeadvsDeltaRToLead"), cosTheta, deltaR); + histos.fill(HIST("JetKinematicsQA/h2dDeltaPhiToLeadvsDeltaEtaToLead"), deltaPhi, deltaEta); + + histos.fill(HIST("JetKinematicsQA/h2dJetPtvsDeltaPhiToLead"), jet.pt(), deltaPhi); // Can't really get the energy of the jet, just the pt to make this comparison + histos.fill(HIST("JetKinematicsQA/h2dJetEnergyvsDeltaPhiToLead"), jet.E(), deltaPhi); // Just a different scale + histos.fill(HIST("JetKinematicsQA/h2dJetEnergyvsCosThetaToLead"), jet.E(), cosTheta); + + histos.fill(HIST("JetKinematicsQA/h2dJetsPerEventvsDeltaPhiToLead"), jetsInEvent, deltaPhi); + histos.fill(HIST("JetKinematicsQA/h2dJetsPerEventvsDeltaEtaToLead"), jetsInEvent, deltaEta); + histos.fill(HIST("JetKinematicsQA/h2dJetsPerEventvsCosThetaToLead"), jetsInEvent, cosTheta); + } + } + if (doJetKinematicsQA) { + histos.fill(HIST("JetKinematicsQA/hLeadingJetPt"), leadingJet.pt()); + histos.fill(HIST("JetKinematicsQA/hLeadingJetEta"), leadingJet.eta()); + histos.fill(HIST("JetKinematicsQA/hLeadingJetPhi"), leadingJet.phi()); + + // Leading particle comparisons: + histos.fill(HIST("JetVsLeadingParticleQA/hLeadingParticlePt"), leadingParticle.pt()); + histos.fill(HIST("JetVsLeadingParticleQA/hLeadingParticleEta"), leadingParticle.eta()); + histos.fill(HIST("JetVsLeadingParticleQA/hLeadingParticlePhi"), leadingParticle.phi()); + + double deltaPhiParticleToJet = RecoDecay::constrainAngle(leadingJet.phi() - leadingParticle.phi(), -o2::constants::math::PI); + double deltaEtaParticleToJet = leadingJet.eta() - leadingParticle.eta(); + double cosThetaParticleToJet = cosThetaJets(leadingJet, leadingParticle); // Takes advantage of the fact that this leading particle is a PseudoJet object + + histos.fill(HIST("JetVsLeadingParticleQA/hCosThetaLeadParticleToJet"), cosThetaParticleToJet); + histos.fill(HIST("JetVsLeadingParticleQA/hDeltaPhiLeadParticleToJet"), deltaPhiParticleToJet); + histos.fill(HIST("JetVsLeadingParticleQA/hDeltaEtaToLeadParticleToJet"), deltaEtaParticleToJet); + + histos.fill(HIST("JetVsLeadingParticleQA/h2dDeltaPhiParticleToLeadvsDeltaEtaParticleToLead"), deltaPhiParticleToJet, deltaEtaParticleToJet); + + histos.fill(HIST("JetVsLeadingParticleQA/h2dJetsPerEventvsDeltaPhiParticleToLead"), jetsInEvent, deltaPhiParticleToJet); + histos.fill(HIST("JetVsLeadingParticleQA/h2dJetsPerEventvsDeltaEtaParticleToLead"), jetsInEvent, deltaEtaParticleToJet); + histos.fill(HIST("JetVsLeadingParticleQA/h2dJetsPerEventvsCosThetaParticleToLead"), jetsInEvent, cosThetaParticleToJet); + + histos.fill(HIST("JetVsLeadingParticleQA/h2dJetsPerEventvsLeadParticlePt"), jetsInEvent, leadingParticle.pt()); + histos.fill(HIST("JetVsLeadingParticleQA/h2dLeadJetPtvsLeadParticlePt"), leadingJet.pt(), leadingParticle.pt()); + + histos.fill(HIST("JetVsLeadingParticleQA/h2dLeadJetPtvsCosThetaParticleToLead"), leadingJet.pt(), cosThetaParticleToJet); + histos.fill(HIST("JetVsLeadingParticleQA/h2dLeadParticlePtvsCosThetaParticleToLead"), leadingParticle.pt(), cosThetaParticleToJet); + + histos.fill(HIST("JetVsLeadingParticleQA/h2dLeadJetPtvsDeltaPhiParticleToLead"), leadingJet.pt(), deltaPhiParticleToJet); // To see if there is any backgound in phi due to soft jets (or soft particles below) + histos.fill(HIST("JetVsLeadingParticleQA/h2dLeadParticlePtvsDeltaPhiParticleToLead"), leadingParticle.pt(), deltaPhiParticleToJet); + } + } + } + + // Had to include DauTracks in subscription, even though I don't loop in it, for the indices + // to resolve, avoiding " Exception while running: Index pointing to Tracks is not bound!" + // Added the compiler option [[maybe_unused]] to avoid triggering any warnings because of this + void processV0sData(SelCollisions::iterator const& collision, V0CandidatesWithTOF const& fullV0s, aod::BCsWithTimestamps const& bcs, [[maybe_unused]] DauTracks const& V0DauTracks) + { + float centrality = getCentrality(collision); // Strictly for QA. We save other types of centrality estimators in the derived data! + + // For event QA the last two indices never change for NEv_withJets and NEv_withV0s + // (Not the best way to initialize this: runs once per collision! TODO: think of a better way to do it) + int lastBinEvSel = histos.get(HIST("hEventSelection"))->GetXaxis()->GetNbins(); + bool validV0AlreadyFound = false; + + histos.fill(HIST("hEventSelection"), 0. /* all collisions */); + histos.fill(HIST("hEventSelectionVsCentrality"), 0. /* all collisions */, centrality); + + auto bc = bcs.iteratorAt(collision.bcId()); + if (!isEventAccepted(collision, bc, centrality, doEventQA)) + return; // Uses return instead of continue, as there is no explicit loop here + + if (doEventQA) + fillCentralityProperties(collision, centrality); + const uint64_t collIdx = collision.globalIndex(); + if (v0Selections.rejectTPCsectorBoundary) + initCCDB(bc); // Substituted call from collision to bc for raw data + + // Fill event table: + tableCollisions(collIdx, + collision.centFT0M(), + collision.centFT0C(), + collision.centFV0A()); // (TODO: add InteractionRate info and other useful cuts for later on in the analysis?) + + uint NLambdas = 0; // Counting particles per event + uint NAntiLambdas = 0; + uint NAmbiguous = 0; + for (auto const& v0 : fullV0s) { + V0SelCounter.resetForNewV0(); + V0SelCounter.fill(); // Fill for all v0 candidates + if (doArmenterosQA) + histos.fill(HIST("GeneralQA/h2dArmenterosAll"), v0.alpha(), v0.qtarm()); // fill AP plot for all V0s + if (!passesGenericV0Cuts(v0)) + continue; + + if (doArmenterosQA) + histos.fill(HIST("GeneralQA/h2dArmenterosKinematicSelected"), v0.alpha(), v0.qtarm()); + + // Else, just continue the loop: + bool isLambda = false; + bool isAntiLambda = false; + if (analyseLambda) + isLambda = passesLambdaLambdaBarHypothesis(v0, collision, true); + if (analyseAntiLambda) + isAntiLambda = passesLambdaLambdaBarHypothesis(v0, collision, false); + + if (!isLambda && !isAntiLambda) + continue; // Candidate is not considered to be a Lambda + + if (isLambda) + NLambdas++; + if (isAntiLambda) + NAntiLambdas++; + + if (doArmenterosQA) + histos.fill(HIST("GeneralQA/h2dArmenterosFullSelected"), v0.alpha(), v0.qtarm()); // cross-check + if (isLambda && !isAntiLambda) + histos.fill(HIST("GeneralQA/h2dArmenterosFullSelectedLambda"), v0.alpha(), v0.qtarm()); + if (!isLambda && isAntiLambda) + histos.fill(HIST("GeneralQA/h2dArmenterosFullSelectedAntiLambda"), v0.alpha(), v0.qtarm()); + + // int lambdaIdx = -1; // No need to pass armenteros + if (isLambda && isAntiLambda) { + NAmbiguous++; + histos.fill(HIST("hAmbiguousLambdaCandidates"), 0); + if (doArmenterosQA) + histos.fill(HIST("GeneralQA/h2dArmenterosFullSelectedAmbiguous"), v0.alpha(), v0.qtarm()); // To know the discerning power of Armenteros in an Ambiguous Lambda vs AntiLambda case + + // Armenteros cut is not worth it! From QA histograms, only about 0.05% of ambiguous candidates are in the regions probable to be Lamda/AntiLambdas! + // The statistics gain is not worth it. + // // Third and final check to distinguish between Lambda and AntiLambda ambiguous v0s: + // // (This check is only performed to recycle AMBIGUOUS candidates! Not a hard cut on all candidates!) + // lambdaIdx = isCandidateArmenterosLambda(v0.alpha(), v0.qtarm()); + } + // if (lambdaIdx == kIsArmenterosK0) continue; // Should just skip this step then! + + if (doEventQA) + fillEventSelectionQA(lastBinEvSel, centrality); // hasRingV0 passes + + // // Extra competing mass rejection of Lambdas // (TODO: test competing mass cuts) + // v0.mLambda() + + // Saving the Lambdas into a derived data column: + auto const v0pt = v0.pt(); + const auto posTrackExtra = v0.template posTrack_as(); + const auto negTrackExtra = v0.template negTrack_as(); + tableV0s(collIdx, + v0pt, v0.eta(), v0.phi(), // Using eta instead of rapidity + isLambda, isAntiLambda, + v0.mLambda(), v0.mAntiLambda(), + v0.positivept(), v0.positiveeta(), v0.positivephi(), + v0.negativept(), v0.negativeeta(), v0.negativephi(), + posTrackExtra.tpcNSigmaPr(), posTrackExtra.tpcNSigmaPi(), + negTrackExtra.tpcNSigmaPr(), negTrackExtra.tpcNSigmaPi(), + v0.v0cosPA(), v0.v0radius(), v0.dcaV0daughters(), v0.dcapostopv(), v0.dcanegtopv()); + if (doEventQA && !validV0AlreadyFound) + fillEventSelectionQA(lastBinEvSel, centrality); // hasRingV0 passes + validV0AlreadyFound = true; + + if (doV0KinematicQA) { + // Cache kinematics once + const float v0y = v0.yLambda(); + const float v0phi = v0.phi(); + const float mLambda = v0.mLambda(); + const float mAntiLambda = v0.mAntiLambda(); + if (analyseLambda && isLambda) { + // --- Basic kinematics --- + histos.fill(HIST("V0KinematicQA/Lambda/hPt"), v0pt); + histos.fill(HIST("V0KinematicQA/Lambda/hY"), v0y); + histos.fill(HIST("V0KinematicQA/Lambda/hPhi"), v0phi); + // --- Mass correlations --- + histos.fill(HIST("V0KinematicQA/Lambda/hMassVsPt"), v0pt, mLambda); + histos.fill(HIST("V0KinematicQA/Lambda/hMassVsY"), v0y, mLambda); + histos.fill(HIST("V0KinematicQA/Lambda/hMassVsPhi"), v0phi, mLambda); + // --- Kinematic correlations --- + histos.fill(HIST("V0KinematicQA/Lambda/hYVsPt"), v0pt, v0y); + histos.fill(HIST("V0KinematicQA/Lambda/hPhiVsPt"), v0pt, v0phi); + } + if (analyseAntiLambda && isAntiLambda) { + // --- Basic kinematics --- + histos.fill(HIST("V0KinematicQA/AntiLambda/hPt"), v0pt); + histos.fill(HIST("V0KinematicQA/AntiLambda/hY"), v0y); + histos.fill(HIST("V0KinematicQA/AntiLambda/hPhi"), v0phi); + // --- Mass correlations --- + histos.fill(HIST("V0KinematicQA/AntiLambda/hMassVsPt"), v0pt, mAntiLambda); + histos.fill(HIST("V0KinematicQA/AntiLambda/hMassVsY"), v0y, mAntiLambda); + histos.fill(HIST("V0KinematicQA/AntiLambda/hMassVsPhi"), v0phi, mAntiLambda); + // --- Kinematic correlations --- + histos.fill(HIST("V0KinematicQA/AntiLambda/hYVsPt"), v0pt, v0y); + histos.fill(HIST("V0KinematicQA/AntiLambda/hPhiVsPt"), v0pt, v0phi); + } + } + + if (doCompleteTopoQA) { + // Remaking these variables outside of the passesLambdaLambdaBarHypothesis. Loses performance, but that should be OK for QA + histos.fill(HIST("V0KinematicQA/hPosDCAToPV"), v0.dcapostopv()); + histos.fill(HIST("V0KinematicQA/hNegDCAToPV"), v0.dcanegtopv()); + histos.fill(HIST("V0KinematicQA/hDCADaughters"), v0.dcaV0daughters()); + histos.fill(HIST("V0KinematicQA/hPointingAngle"), std::acos(v0.v0cosPA())); + histos.fill(HIST("V0KinematicQA/hV0Radius"), v0.v0radius()); + histos.fill(HIST("V0KinematicQA/h2dPositiveITSvsTPCpts"), posTrackExtra.tpcNClsCrossedRows(), posTrackExtra.itsNCls()); + histos.fill(HIST("V0KinematicQA/h2dNegativeITSvsTPCpts"), negTrackExtra.tpcNClsCrossedRows(), negTrackExtra.itsNCls()); + histos.fill(HIST("V0KinematicQA/h2dPositivePtVsPhi"), v0.positivept(), computePhiMod(v0.positivephi(), 1)); + histos.fill(HIST("V0KinematicQA/h2dNegativePtVsPhi"), v0.negativept(), computePhiMod(v0.negativephi(), -1)); + if (isLambda && analyseLambda) { + histos.fill(HIST("hMassLambda"), v0.mLambda()); + histos.fill(HIST("Lambda/h3dMassLambda"), centrality, v0pt, v0.mLambda()); + histos.fill(HIST("Lambda/hPosDCAToPV"), v0.dcapostopv()); + histos.fill(HIST("Lambda/hNegDCAToPV"), v0.dcanegtopv()); + histos.fill(HIST("Lambda/hDCADaughters"), v0.dcaV0daughters()); + histos.fill(HIST("Lambda/hPointingAngle"), std::acos(v0.v0cosPA())); + histos.fill(HIST("Lambda/hV0Radius"), v0.v0radius()); + histos.fill(HIST("Lambda/h2dPositiveITSvsTPCpts"), posTrackExtra.tpcNClsCrossedRows(), posTrackExtra.itsNCls()); + histos.fill(HIST("Lambda/h2dNegativeITSvsTPCpts"), negTrackExtra.tpcNClsCrossedRows(), negTrackExtra.itsNCls()); + histos.fill(HIST("Lambda/h2dPositivePtVsPhi"), v0.positivept(), computePhiMod(v0.positivephi(), 1)); + histos.fill(HIST("Lambda/h2dNegativePtVsPhi"), v0.negativept(), computePhiMod(v0.negativephi(), -1)); + if (doTPCQA) { + histos.fill(HIST("Lambda/h3dPosNsigmaTPC"), centrality, v0pt, posTrackExtra.tpcNSigmaPr()); + histos.fill(HIST("Lambda/h3dNegNsigmaTPC"), centrality, v0pt, negTrackExtra.tpcNSigmaPi()); + histos.fill(HIST("Lambda/h3dPosTPCsignal"), centrality, v0pt, posTrackExtra.tpcSignal()); + histos.fill(HIST("Lambda/h3dNegTPCsignal"), centrality, v0pt, negTrackExtra.tpcSignal()); + histos.fill(HIST("Lambda/h3dPosNsigmaTPCvsTrackPtot"), centrality, v0.pfracpos() * v0.p(), posTrackExtra.tpcNSigmaPr()); + histos.fill(HIST("Lambda/h3dNegNsigmaTPCvsTrackPtot"), centrality, v0.pfracneg() * v0.p(), negTrackExtra.tpcNSigmaPi()); + histos.fill(HIST("Lambda/h3dPosTPCsignalVsTrackPtot"), centrality, v0.pfracpos() * v0.p(), posTrackExtra.tpcSignal()); + histos.fill(HIST("Lambda/h3dNegTPCsignalVsTrackPtot"), centrality, v0.pfracneg() * v0.p(), negTrackExtra.tpcSignal()); + histos.fill(HIST("Lambda/h3dPosNsigmaTPCvsTrackPt"), centrality, v0.positivept(), posTrackExtra.tpcNSigmaPr()); + histos.fill(HIST("Lambda/h3dNegNsigmaTPCvsTrackPt"), centrality, v0.negativept(), negTrackExtra.tpcNSigmaPi()); + histos.fill(HIST("Lambda/h3dPosTPCsignalVsTrackPt"), centrality, v0.positivept(), posTrackExtra.tpcSignal()); + histos.fill(HIST("Lambda/h3dNegTPCsignalVsTrackPt"), centrality, v0.negativept(), negTrackExtra.tpcSignal()); + } + if (doTOFQA) { + histos.fill(HIST("Lambda/h3dPosNsigmaTOF"), centrality, v0pt, v0.tofNSigmaLaPr()); + histos.fill(HIST("Lambda/h3dNegNsigmaTOF"), centrality, v0pt, v0.tofNSigmaLaPi()); + histos.fill(HIST("Lambda/h3dPosTOFdeltaT"), centrality, v0pt, v0.posTOFDeltaTLaPr()); + histos.fill(HIST("Lambda/h3dNegTOFdeltaT"), centrality, v0pt, v0.negTOFDeltaTLaPi()); + histos.fill(HIST("Lambda/h3dPosNsigmaTOFvsTrackPtot"), centrality, v0.pfracpos() * v0.p(), v0.tofNSigmaLaPr()); + histos.fill(HIST("Lambda/h3dNegNsigmaTOFvsTrackPtot"), centrality, v0.pfracneg() * v0.p(), v0.tofNSigmaLaPi()); + histos.fill(HIST("Lambda/h3dPosTOFdeltaTvsTrackPtot"), centrality, v0.pfracpos() * v0.p(), v0.posTOFDeltaTLaPr()); + histos.fill(HIST("Lambda/h3dNegTOFdeltaTvsTrackPtot"), centrality, v0.pfracneg() * v0.p(), v0.negTOFDeltaTLaPi()); + histos.fill(HIST("Lambda/h3dPosNsigmaTOFvsTrackPt"), centrality, v0.positivept(), v0.tofNSigmaLaPr()); + histos.fill(HIST("Lambda/h3dNegNsigmaTOFvsTrackPt"), centrality, v0.negativept(), v0.tofNSigmaLaPi()); + histos.fill(HIST("Lambda/h3dPosTOFdeltaTvsTrackPt"), centrality, v0.positivept(), v0.posTOFDeltaTLaPr()); + histos.fill(HIST("Lambda/h3dNegTOFdeltaTvsTrackPt"), centrality, v0.negativept(), v0.negTOFDeltaTLaPi()); + } + if (doEtaPhiQA) { + histos.fill(HIST("Lambda/h5dV0PhiVsEta"), centrality, v0pt, v0.mLambda(), v0.phi(), v0.eta()); + histos.fill(HIST("Lambda/h5dPosPhiVsEta"), centrality, v0.positivept(), v0.mLambda(), v0.positivephi(), v0.positiveeta()); + histos.fill(HIST("Lambda/h5dNegPhiVsEta"), centrality, v0.negativept(), v0.mLambda(), v0.negativephi(), v0.negativeeta()); + } + } + if (isAntiLambda && analyseAntiLambda) { + histos.fill(HIST("hMassAntiLambda"), v0.mAntiLambda()); + histos.fill(HIST("AntiLambda/h3dMassAntiLambda"), centrality, v0pt, v0.mAntiLambda()); + histos.fill(HIST("AntiLambda/hPosDCAToPV"), v0.dcapostopv()); + histos.fill(HIST("AntiLambda/hNegDCAToPV"), v0.dcanegtopv()); + histos.fill(HIST("AntiLambda/hDCADaughters"), v0.dcaV0daughters()); + histos.fill(HIST("AntiLambda/hPointingAngle"), std::acos(v0.v0cosPA())); + histos.fill(HIST("AntiLambda/hV0Radius"), v0.v0radius()); + histos.fill(HIST("AntiLambda/h2dPositiveITSvsTPCpts"), posTrackExtra.tpcNClsCrossedRows(), posTrackExtra.itsNCls()); + histos.fill(HIST("AntiLambda/h2dNegativeITSvsTPCpts"), negTrackExtra.tpcNClsCrossedRows(), negTrackExtra.itsNCls()); + histos.fill(HIST("AntiLambda/h2dPositivePtVsPhi"), v0.positivept(), computePhiMod(v0.positivephi(), 1)); + histos.fill(HIST("AntiLambda/h2dNegativePtVsPhi"), v0.negativept(), computePhiMod(v0.negativephi(), -1)); + if (doTPCQA) { + histos.fill(HIST("AntiLambda/h3dPosNsigmaTPC"), centrality, v0pt, posTrackExtra.tpcNSigmaPi()); + histos.fill(HIST("AntiLambda/h3dNegNsigmaTPC"), centrality, v0pt, negTrackExtra.tpcNSigmaPr()); + histos.fill(HIST("AntiLambda/h3dPosTPCsignal"), centrality, v0pt, posTrackExtra.tpcSignal()); + histos.fill(HIST("AntiLambda/h3dNegTPCsignal"), centrality, v0pt, negTrackExtra.tpcSignal()); + histos.fill(HIST("AntiLambda/h3dPosNsigmaTPCvsTrackPtot"), centrality, v0.pfracpos() * v0.p(), posTrackExtra.tpcNSigmaPi()); + histos.fill(HIST("AntiLambda/h3dNegNsigmaTPCvsTrackPtot"), centrality, v0.pfracneg() * v0.p(), negTrackExtra.tpcNSigmaPr()); + histos.fill(HIST("AntiLambda/h3dPosTPCsignalVsTrackPtot"), centrality, v0.pfracpos() * v0.p(), posTrackExtra.tpcSignal()); + histos.fill(HIST("AntiLambda/h3dNegTPCsignalVsTrackPtot"), centrality, v0.pfracneg() * v0.p(), negTrackExtra.tpcSignal()); + histos.fill(HIST("AntiLambda/h3dPosNsigmaTPCvsTrackPt"), centrality, v0.positivept(), posTrackExtra.tpcNSigmaPi()); + histos.fill(HIST("AntiLambda/h3dNegNsigmaTPCvsTrackPt"), centrality, v0.negativept(), negTrackExtra.tpcNSigmaPr()); + histos.fill(HIST("AntiLambda/h3dPosTPCsignalVsTrackPt"), centrality, v0.positivept(), posTrackExtra.tpcSignal()); + histos.fill(HIST("AntiLambda/h3dNegTPCsignalVsTrackPt"), centrality, v0.negativept(), negTrackExtra.tpcSignal()); + } + if (doTOFQA) { + histos.fill(HIST("AntiLambda/h3dPosNsigmaTOF"), centrality, v0pt, v0.tofNSigmaALaPi()); + histos.fill(HIST("AntiLambda/h3dNegNsigmaTOF"), centrality, v0pt, v0.tofNSigmaALaPr()); + histos.fill(HIST("AntiLambda/h3dPosTOFdeltaT"), centrality, v0pt, v0.posTOFDeltaTLaPi()); + histos.fill(HIST("AntiLambda/h3dNegTOFdeltaT"), centrality, v0pt, v0.negTOFDeltaTLaPr()); + histos.fill(HIST("AntiLambda/h3dPosNsigmaTOFvsTrackPtot"), centrality, v0.pfracpos() * v0.p(), v0.tofNSigmaALaPi()); + histos.fill(HIST("AntiLambda/h3dNegNsigmaTOFvsTrackPtot"), centrality, v0.pfracneg() * v0.p(), v0.tofNSigmaALaPr()); + histos.fill(HIST("AntiLambda/h3dPosTOFdeltaTvsTrackPtot"), centrality, v0.pfracpos() * v0.p(), v0.posTOFDeltaTLaPi()); + histos.fill(HIST("AntiLambda/h3dNegTOFdeltaTvsTrackPtot"), centrality, v0.pfracneg() * v0.p(), v0.negTOFDeltaTLaPr()); + histos.fill(HIST("AntiLambda/h3dPosNsigmaTOFvsTrackPt"), centrality, v0.positivept(), v0.tofNSigmaALaPi()); + histos.fill(HIST("AntiLambda/h3dNegNsigmaTOFvsTrackPt"), centrality, v0.negativept(), v0.tofNSigmaALaPr()); + histos.fill(HIST("AntiLambda/h3dPosTOFdeltaTvsTrackPt"), centrality, v0.positivept(), v0.posTOFDeltaTLaPi()); + histos.fill(HIST("AntiLambda/h3dNegTOFdeltaTvsTrackPt"), centrality, v0.negativept(), v0.negTOFDeltaTLaPr()); + } + if (doEtaPhiQA) { + histos.fill(HIST("AntiLambda/h5dV0PhiVsEta"), centrality, v0pt, v0.mAntiLambda(), v0.phi(), v0.eta()); + histos.fill(HIST("AntiLambda/h5dPosPhiVsEta"), centrality, v0.positivept(), v0.mAntiLambda(), v0.positivephi(), v0.positiveeta()); + histos.fill(HIST("AntiLambda/h5dNegPhiVsEta"), centrality, v0.negativept(), v0.mAntiLambda(), v0.negativephi(), v0.negativeeta()); + } + } + } // end CompleteTopoQA + } // end V0s loop + + // Fill histograms on a per-event level: + histos.fill(HIST("Lambda/hLambdasPerEvent"), NLambdas); + histos.fill(HIST("AntiLambda/hAntiLambdasPerEvent"), NAntiLambdas); + histos.fill(HIST("hAmbiguousPerEvent"), NAmbiguous); + histos.fill(HIST("Lambda/h2dNbrOfLambdaVsCentrality"), centrality, NLambdas); + histos.fill(HIST("AntiLambda/h2dNbrOfAntiLambdaVsCentrality"), centrality, NAntiLambdas); + } + + PROCESS_SWITCH(lambdajetpolarizationions, processJetsData, "Process jets and produce derived data in Run 3 Data", true); + PROCESS_SWITCH(lambdajetpolarizationions, processV0sData, "Process V0s and produce derived data in Run 3 Data", true); + // PROCESS_SWITCH(lambdajetpolarizationions, processJetsMC, "Process jets and produced derived data in Run 3 MC", true); + // PROCESS_SWITCH(lambdajetpolarizationions, processV0sMC, "Process V0s and produce derived data in Run 3 MC", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/Tasks/Strangeness/CMakeLists.txt b/PWGLF/Tasks/Strangeness/CMakeLists.txt index e3d115324c6..d59685bc93d 100644 --- a/PWGLF/Tasks/Strangeness/CMakeLists.txt +++ b/PWGLF/Tasks/Strangeness/CMakeLists.txt @@ -166,6 +166,11 @@ o2physics_add_dpl_workflow(lambdajetpolarization PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGJECore FastJet::FastJet FastJet::Contrib O2Physics::EventFilteringUtils COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(lambdajetpolarizationionsderived + SOURCES lambdaJetPolarizationIonsDerived.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(lambdaspincorrderived SOURCES lambdaspincorrderived.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore diff --git a/PWGLF/Tasks/Strangeness/lambdaJetPolarizationIonsDerived.cxx b/PWGLF/Tasks/Strangeness/lambdaJetPolarizationIonsDerived.cxx new file mode 100644 index 00000000000..3bff75a5a54 --- /dev/null +++ b/PWGLF/Tasks/Strangeness/lambdaJetPolarizationIonsDerived.cxx @@ -0,0 +1,776 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +// +/// \file lambdajetpolarizationionsderived.cxx +/// \brief Lambda and antiLambda polarization analysis task using derived data +/// +/// \author Cicero Domenico Muncinelli , Campinas State University +// +// Jet Polarization Ions task -- Derived data +// ================ +// +// This code loops over custom derived data tables defined on +// lambdaJetPolarizationIons.h (JetsRing, LambdaLikeV0sRing). +// From this derived data, calculates polarization on an EbE +// basis (see TProfiles). +// Signal extraction is done out of the framework, based on +// the AnalysisResults of this code. +// +// +// Comments, questions, complaints, suggestions? +// Please write to: +// cicero.domenico.muncinelli@cern.ch +// + +#include +#include +#include +#include +#include +#include + +// Custom data model: +#include "PWGLF/DataModel/lambdaJetPolarizationIons.h" + +#include +#include +#include +#include + +// #include +// #include +// New recommended format: +#include +#include +#include +#include // For perpendicular jet direction QAs + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using ROOT::Math::PtEtaPhiMVector; +using ROOT::Math::XYZVector; +// using namespace o2::aod::lambdajetpol; // Used it explicitly along the code for clarity + +// Declaring constants: +constexpr double protonMass = o2::constants::physics::MassProton; // Assumes particle identification for daughter is perfect +constexpr double lambdaWeakDecayConstant = 0.749; // DPG 2025 update +constexpr double antiLambdaWeakDecayConstant = -0.758; // DPG 2025 update +constexpr double polPrefactorLambda = 3.0 / lambdaWeakDecayConstant; +constexpr double polPrefactorAntiLambda = 3.0 / antiLambdaWeakDecayConstant; + +enum CentEstimator { + kCentFT0C = 0, + kCentFT0M, + kCentFV0A +}; + +// Helper macro to avoid writing the histogram fills 4 times for about 20 histograms: +#define RING_OBSERVABLE_FILL_LIST(X, FOLDER) \ + /* Counters */ \ + X(FOLDER "/QA/hDeltaPhi", deltaPhiJet) \ + X(FOLDER "/QA/hDeltaTheta", deltaThetaJet) \ + X(FOLDER "/QA/hIntegrated", 0.) \ + /* Lambda pT variation -- Youpeng's proposal */ \ + X(FOLDER "/QA/hLambdaPt", v0pt) \ + /* Counters */ \ + X(FOLDER "/QA/h2dDeltaPhiVsLambdaPt", deltaPhiJet, v0pt) \ + X(FOLDER "/QA/h2dDeltaThetaVsLambdaPt", deltaThetaJet, v0pt) \ + /* Additional plots for instant gratification - 1D Profiles */ \ + X(FOLDER "/pRingObservableDeltaPhi", deltaPhiJet, ringObservable) \ + X(FOLDER "/pRingObservableDeltaTheta", deltaThetaJet, ringObservable) \ + X(FOLDER "/pRingObservableIntegrated", 0., ringObservable) \ + X(FOLDER "/pRingObservableLambdaPt", v0pt, ringObservable) \ + /* 2D Profiles */ \ + X(FOLDER "/p2dRingObservableDeltaPhiVsLambdaPt", deltaPhiJet, v0pt, ringObservable) \ + X(FOLDER "/p2dRingObservableDeltaThetaVsLambdaPt", deltaThetaJet, v0pt, ringObservable) \ + X(FOLDER "/p2dRingObservableDeltaPhiVsLeadJetPt", deltaPhiJet, leadingJetPt, ringObservable) \ + X(FOLDER "/p2dRingObservableDeltaThetaVsLeadJetPt", deltaThetaJet, leadingJetPt, ringObservable) \ + /* 1D Mass */ \ + X(FOLDER "/QA/hMass", v0LambdaLikeMass) \ + X(FOLDER "/QA/hRingObservableNumMass", v0LambdaLikeMass, ringObservable) \ + X(FOLDER "/hMassSigExtract", v0LambdaLikeMass) \ + /* Counters */ \ + X(FOLDER "/QA/h2dDeltaPhiVsMass", deltaPhiJet, v0LambdaLikeMass) \ + X(FOLDER "/QA/h2dDeltaThetaVsMass", deltaThetaJet, v0LambdaLikeMass) \ + X(FOLDER "/QA/h3dDeltaPhiVsMassVsLambdaPt", deltaPhiJet, v0LambdaLikeMass, v0pt) \ + X(FOLDER "/QA/h3dDeltaThetaVsMassVsLambdaPt", deltaThetaJet, v0LambdaLikeMass, v0pt) \ + X(FOLDER "/QA/h3dDeltaPhiVsMassVsLeadJetPt", deltaPhiJet, v0LambdaLikeMass, leadingJetPt) \ + X(FOLDER "/QA/h3dDeltaThetaVsMassVsLeadJetPt", deltaThetaJet, v0LambdaLikeMass, leadingJetPt) \ + X(FOLDER "/QA/h3dDeltaPhiVsMassVsCent", deltaPhiJet, v0LambdaLikeMass, centrality) \ + X(FOLDER "/QA/h3dDeltaThetaVsMassVsCent", deltaThetaJet, v0LambdaLikeMass, centrality) \ + /* TProfile of Ring vs Mass */ \ + X(FOLDER "/pRingObservableMass", v0LambdaLikeMass, ringObservable) \ + /* TProfile of Ring vs Mass -- Leading Particle and 2nd-to-leading jet - QA */ \ + X(FOLDER "/pRingObservableLeadPMass", v0LambdaLikeMass, ringObservableLeadP) \ + X(FOLDER "/pRingObservable2ndJetMass", v0LambdaLikeMass, ringObservable2ndJet) \ + /* 2D Profiles: Angle vs Mass */ \ + X(FOLDER "/p2dRingObservableDeltaPhiVsMass", deltaPhiJet, v0LambdaLikeMass, ringObservable) \ + X(FOLDER "/p2dRingObservableDeltaThetaVsMass", deltaThetaJet, v0LambdaLikeMass, ringObservable) \ + /* 3D Profiles: Angle vs Mass vs Lambda pT */ \ + X(FOLDER "/p3dRingObservableDeltaPhiVsMassVsLambdaPt", deltaPhiJet, v0LambdaLikeMass, v0pt, ringObservable) \ + X(FOLDER "/p3dRingObservableDeltaThetaVsMassVsLambdaPt", deltaThetaJet, v0LambdaLikeMass, v0pt, ringObservable) \ + /* 3D Profiles: Angle vs Mass vs Lead Jet pT */ \ + X(FOLDER "/p3dRingObservableDeltaPhiVsMassVsLeadJetPt", deltaPhiJet, v0LambdaLikeMass, leadingJetPt, ringObservable) \ + X(FOLDER "/p3dRingObservableDeltaThetaVsMassVsLeadJetPt", deltaThetaJet, v0LambdaLikeMass, leadingJetPt, ringObservable) \ + /* 2D Profile: Mass vs Centrality */ \ + X(FOLDER "/p2dRingObservableMassVsCent", v0LambdaLikeMass, centrality, ringObservable) \ + /* 3D Profiles: Angle vs Mass vs Centrality */ \ + X(FOLDER "/p3dRingObservableDeltaPhiVsMassVsCent", deltaPhiJet, v0LambdaLikeMass, centrality, ringObservable) \ + X(FOLDER "/p3dRingObservableDeltaThetaVsMassVsCent", deltaThetaJet, v0LambdaLikeMass, centrality, ringObservable) \ + X(FOLDER "/pRingIntVsCentrality", centrality, ringObservable) +// (TODO: add counters for regular TH2Ds about centrality) + +// For leading particle +#define RING_OBSERVABLE_LEADP_FILL_LIST(X, FOLDER) \ + X(FOLDER "/pRingObservableLeadPDeltaPhi", deltaPhiLeadP, ringObservableLeadP) \ + X(FOLDER "/pRingObservableLeadPDeltaTheta", deltaThetaLeadP, ringObservableLeadP) \ + X(FOLDER "/pRingObservableLeadPIntegrated", 0., ringObservableLeadP) \ + X(FOLDER "/pRingObservableLeadPLambdaPt", v0pt, ringObservableLeadP) + +// For subleading jet: +#define RING_OBSERVABLE_2NDJET_FILL_LIST(X, FOLDER) \ + X(FOLDER "/pRingObservable2ndJetDeltaPhi", deltaPhi2ndJet, ringObservable2ndJet) \ + X(FOLDER "/pRingObservable2ndJetDeltaTheta", deltaTheta2ndJet, ringObservable2ndJet) \ + X(FOLDER "/pRingObservable2ndJetIntegrated", 0., ringObservable2ndJet) \ + X(FOLDER "/pRingObservable2ndJetLambdaPt", v0pt, ringObservable2ndJet) + +#define POLARIZATION_PROFILE_FILL_LIST(X, FOLDER) \ + /* =============================== */ \ + /* 1D TProfiles vs v0phi */ \ + /* =============================== */ \ + X(FOLDER "/QA/pPxStarPhi", v0phiToFillHists, PolStarX) \ + X(FOLDER "/QA/pPyStarPhi", v0phiToFillHists, PolStarY) \ + X(FOLDER "/QA/pPzStarPhi", v0phiToFillHists, PolStarZ) \ + /* =============================== */ \ + /* 1D TProfiles vs DeltaPhi_jet */ \ + /* =============================== */ \ + X(FOLDER "/QA/pPxStarDeltaPhi", deltaPhiJet, PolStarX) \ + X(FOLDER "/QA/pPyStarDeltaPhi", deltaPhiJet, PolStarY) \ + X(FOLDER "/QA/pPzStarDeltaPhi", deltaPhiJet, PolStarZ) \ + /* =============================== */ \ + /* 2D TProfiles vs DeltaPhi_jet and Lambda pT */ \ + /* =============================== */ \ + X(FOLDER "/QA/p2dPxStarDeltaPhiVsLambdaPt", deltaPhiJet, v0pt, PolStarX) \ + X(FOLDER "/QA/p2dPyStarDeltaPhiVsLambdaPt", deltaPhiJet, v0pt, PolStarY) \ + X(FOLDER "/QA/p2dPzStarDeltaPhiVsLambdaPt", deltaPhiJet, v0pt, PolStarZ) + +// Apply the macros (notice I had to include the semicolon (";") after the function, so you don't need to +// write that when calling this APPLY_HISTO_FILL. The code will look weird, but without this the compiler +// would not know to end each statement with a semicolon): +#define APPLY_HISTO_FILL(NAME, ...) histos.fill(HIST(NAME), __VA_ARGS__); + +struct lambdajetpolarizationionsderived { + + // Define histogram registries: + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + // Master analysis switches + Configurable analyseLambda{"analyseLambda", true, "process Lambda-like candidates"}; + Configurable analyseAntiLambda{"analyseAntiLambda", false, "process AntiLambda-like candidates"}; + Configurable doPPAnalysis{"doPPAnalysis", false, "if in pp, set to true. Default is HI"}; + + // Centrality: + Configurable centralityEstimator{"centralityEstimator", kCentFT0M, "Run 3 centrality estimator (0:CentFT0C, 1:CentFT0M, 2:CentFV0A)"}; // Default is FT0M + + // QAs that purposefully break the analysis + // -- All of these tests should give us zero signal if the source is truly Lambda Polarization from vortices + Configurable forcePolSignQA{"forcePolSignQA", false, "force antiLambda decay constant to be positive: should kill all the signal, if any. For QA"}; + Configurable forcePerpToJet{"forcePerpToJet", false, "force jet direction to be perpendicular to jet estimator. For QA"}; + Configurable forceJetDirectionSmudge{"forceJetDirectionSmudge", false, "fluctuate jet direction by 10% of R around original axis. For QA (tests sensibility)"}; + Configurable jetRForSmuding{"jetRForSmuding", 0.4, "QA quantity: the chosen R scale for the jet direction smudge"}; + + ///////////////////////// + // Configurable blocks: + // Histogram axes configuration: + struct : ConfigurableGroup { + std::string prefix = "axisConfigurations"; // JSON group name + ConfigurableAxis axisPt{"axisPt", {VARIABLE_WIDTH, 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f, 1.1f, 1.2f, 1.3f, 1.4f, 1.5f, 1.6f, 1.7f, 1.8f, 1.9f, 2.0f, 2.2f, 2.4f, 2.6f, 2.8f, 3.0f, 3.2f, 3.4f, 3.6f, 3.8f, 4.0f, 4.4f, 4.8f, 5.2f, 5.6f, 6.0f, 6.5f, 7.0f, 7.5f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 17.0f, 19.0f, 21.0f, 23.0f, 25.0f, 30.0f, 35.0f, 40.0f, 50.0f}, "pt axis for analysis"}; + ConfigurableAxis axisPtCoarseQA{"axisPtCoarse", {VARIABLE_WIDTH, 0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 7.0f, 10.0f, 15.0f}, "pt axis for QA"}; + ConfigurableAxis axisLambdaMass{"axisLambdaMass", {450, 1.08f, 1.15f}, "Lambda mass in GeV/c"}; // Default is {200, 1.101f, 1.131f} + + // Jet axes: + ConfigurableAxis axisLeadingParticlePt{"axisLeadingParticlePt", {100, 0.f, 200.f}, "Leading particle p_{T} (GeV/c)"}; // Simpler version! + ConfigurableAxis axisJetPt{"axisJetPt", {50, 0.f, 200.f}, "Jet p_{t} (GeV)"}; + ConfigurableAxis axisDeltaTheta{"axisDeltaTheta", {40, 0, constants::math::PI}, "#Delta #theta_{jet}"}; + ConfigurableAxis axisDeltaPhi{"axisDeltaPhi", {40, -constants::math::PI, constants::math::PI}, "#Delta #phi_{jet}"}; + + // Coarser axes for signal extraction: + ConfigurableAxis axisPtSigExtract{"axisPtSigExtract", {VARIABLE_WIDTH, 0.0f, 0.25f, 0.5f, 0.75f, 1.0f, 1.25f, 1.5f, 2.0f, 2.5f, 3.0f, 4.0f, 6.0f, 8.0f, 10.0f, 15.0f, 20.0f, 30.0f, 50.0f}, "pt axis for signal extraction"}; + // ConfigurableAxis axisLambdaMassSigExtract{"axisLambdaMassSigExtract", {175, 1.08f, 1.15f}, "Lambda mass in GeV/c"}; // With a sigma of 0.002 GeV/c, this has about 5 bins per sigma, so that the window is properly grasped. + // A coarser axis (sigma is still well estimated, with about 8 bins in the peak region) + ConfigurableAxis axisLambdaMassSigExtract{ + "axisLambdaMassSigExtract", + {VARIABLE_WIDTH, + // Left sideband (7 bins, 0.004 width) + 1.0800, 1.0840, 1.0880, 1.0920, + 1.0960, 1.1000, 1.1040, 1.1080, + // Fine peak region (8 bins, 0.0016 width) + 1.1096, 1.1112, 1.1128, 1.1144, + 1.1160, 1.1176, 1.1192, 1.1208, + // Right sideband (7 bins, 0.004 width) + 1.1248, 1.1288, 1.1328, 1.1368, + 1.1408, 1.1448, 1.1488}, + "Lambda mass in GeV/c"}; + ConfigurableAxis axisLeadingParticlePtSigExtract{"axisLeadingParticlePtSigExtract", {VARIABLE_WIDTH, 0, 4, 8, 12, 16, 20, 25, 30, 35, 40, 60, 100, 200}, "Leading particle p_{T} (GeV/c)"}; // Simpler version! + ConfigurableAxis axisJetPtSigExtract{"axisJetPtSigExtract", {VARIABLE_WIDTH, 0, 5, 10, 12, 16, 20, 25, 30, 35, 40, 60, 100, 200}, "Jet p_{t} (GeV)"}; + + // (TODO: add a lambdaPt axis that is pre-selected only on the 0.5 to 1.5 Pt region for the Ring observable with lambda cuts to not store a huge histogram with empty bins by construction) + + ConfigurableAxis axisCentrality{"axisCentrality", {VARIABLE_WIDTH, 0.0f, 5.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f, 100.0f}, "Centrality"}; + } axisConfigurations; + + // Helper functions: + // Fast wrapping into [-PI, PI) (restricted to this interval for function speed) + inline double wrapToPiFast(double phi) + { + constexpr double TwoPi = o2::constants::math::TwoPI; + constexpr double Pi = o2::constants::math::PI; + if (phi >= Pi) + phi -= TwoPi; + else if (phi < -Pi) + phi += TwoPi; + return phi; + } + + void init(InitContext const&) + { + // Ring observable histograms: + // Helper to register one full histogram family (kinematic cut variation of ring observable) + auto addRingObservableFamily = [&](const std::string& folder) { + // =============================== + // QA histograms: angle and pT distributions + // (No mass dependency -- useful to check kinematic sculpting from cuts) + // =============================== + histos.add((folder + "/QA/hDeltaPhi").c_str(), "hDeltaPhi", kTH1D, {axisConfigurations.axisDeltaPhi}); + histos.add((folder + "/QA/hDeltaTheta").c_str(), "hDeltaTheta", kTH1D, {axisConfigurations.axisDeltaTheta}); + histos.add((folder + "/QA/hIntegrated").c_str(), "hIntegrated", kTH1D, {{1, -0.5, 0.5}}); + // =============================== + // Lambda pT dependence + // =============================== + histos.add((folder + "/QA/hLambdaPt").c_str(), "hLambdaPt", kTH1D, {axisConfigurations.axisPt}); + histos.add((folder + "/QA/h2dDeltaPhiVsLambdaPt").c_str(), "h2dDeltaPhiVsLambdaPt", kTH2D, {axisConfigurations.axisDeltaPhi, axisConfigurations.axisPt}); + histos.add((folder + "/QA/h2dDeltaThetaVsLambdaPt").c_str(), "h2dDeltaThetaVsLambdaPt", kTH2D, {axisConfigurations.axisDeltaTheta, axisConfigurations.axisPt}); + // =============================== + // Polarization observable QAs + // (not Ring: actual polarization!) + // =============================== + // Will implement these as TProfiles, as polarization is also a measure like P_\Lambda = (3/\alpha_\Lambda) * , so the error is similar + // =============================== + // 1D TProfiles + // =============================== + histos.add((folder + "/QA/pPxStarPhi").c_str(), "pPxStarPhi;#varphi_{#Lambda};_{x}", kTProfile, {axisConfigurations.axisDeltaPhi}); + histos.add((folder + "/QA/pPyStarPhi").c_str(), "pPyStarPhi;#varphi_{#Lambda};_{y}", kTProfile, {axisConfigurations.axisDeltaPhi}); + histos.add((folder + "/QA/pPzStarPhi").c_str(), "pPzStarPhi;#varphi_{#Lambda};_{z}", kTProfile, {axisConfigurations.axisDeltaPhi}); + histos.add((folder + "/QA/pPxStarDeltaPhi").c_str(), "pPxStarDeltaPhi;#Delta#varphi_{jet};_{x}", kTProfile, {axisConfigurations.axisDeltaPhi}); + histos.add((folder + "/QA/pPyStarDeltaPhi").c_str(), "pPyStarDeltaPhi;#Delta#varphi_{jet};_{y}", kTProfile, {axisConfigurations.axisDeltaPhi}); + histos.add((folder + "/QA/pPzStarDeltaPhi").c_str(), "pPzStarDeltaPhi;#Delta#varphi_{jet};_{z}", kTProfile, {axisConfigurations.axisDeltaPhi}); + // =============================== + // 2D TProfiles (Lambda correlations) + // =============================== + histos.add((folder + "/QA/p2dPxStarDeltaPhiVsLambdaPt").c_str(), "p2dPxStarDeltaPhiVsLambdaPt;#Delta#varphi_{jet};#it{p}_{T}^{#Lambda};_{x}", kTProfile2D, {axisConfigurations.axisDeltaPhi, axisConfigurations.axisPtSigExtract}); + histos.add((folder + "/QA/p2dPyStarDeltaPhiVsLambdaPt").c_str(), "p2dPyStarDeltaPhiVsLambdaPt;#Delta#varphi_{jet};#it{p}_{T}^{#Lambda};_{y}", kTProfile2D, {axisConfigurations.axisDeltaPhi, axisConfigurations.axisPtSigExtract}); + histos.add((folder + "/QA/p2dPzStarDeltaPhiVsLambdaPt").c_str(), "p2dPzStarDeltaPhiVsLambdaPt;#Delta#varphi_{jet};#it{p}_{T}^{#Lambda};_{z}", kTProfile2D, {axisConfigurations.axisDeltaPhi, axisConfigurations.axisPtSigExtract}); + + // TProfiles with correct error bars:: + // -- TProfiles will handle the error estimate of the Ring Observable via the variance, even though + // they still lack the proper signal extraction and possible efficiency corrections in the current state + // -- If any efficiency corrections arise, you can fill with the kTH1D as (deltaPhiJet, ringObservable, weight) + // instead of the simple (deltaPhiJet, ringObservable) --> Notice TProfile knows how to accept 3 entries + // for a TH1D-like object! + // -- CAUTION! The TProfile does not utilize unbiased variance estimators with N-1 instead of N in the denominator, + // so you might get biased errors when counts are too low in higher-dimensional profiles (i.e., kTProfile2Ds) + // =============================== + // 1D TProfiles + // =============================== + histos.add((folder + "/pRingObservableDeltaPhi").c_str(), "pRingObservableDeltaPhi;#Delta#varphi_{jet};<#it{R}>", kTProfile, {axisConfigurations.axisDeltaPhi}); + histos.add((folder + "/pRingObservableDeltaTheta").c_str(), "pRingObservableDeltaTheta;#Delta#theta_{jet};<#it{R}>", kTProfile, {axisConfigurations.axisDeltaTheta}); + histos.add((folder + "/pRingObservableIntegrated").c_str(), "pRingObservableIntegrated; ;<#it{R}>", kTProfile, {{1, -0.5, 0.5}}); + histos.add((folder + "/pRingObservableLambdaPt").c_str(), "pRingObservableLambdaPt;#it{p}_{T}^{#Lambda};<#it{R}>", kTProfile, {axisConfigurations.axisPt}); + // For the leading particle: + histos.add((folder + "/pRingObservableLeadPDeltaPhi").c_str(), "pRingObservableLeadPDeltaPhi;#Delta#varphi_{leadP};<#it{R}>", kTProfile, {axisConfigurations.axisDeltaPhi}); + histos.add((folder + "/pRingObservableLeadPDeltaTheta").c_str(), "pRingObservableLeadPDeltaTheta;#Delta#theta_{leadP};<#it{R}>", kTProfile, {axisConfigurations.axisDeltaTheta}); + histos.add((folder + "/pRingObservableLeadPIntegrated").c_str(), "pRingObservableLeadPIntegrated; ;<#it{R}>", kTProfile, {{1, -0.5, 0.5}}); + histos.add((folder + "/pRingObservableLeadPLambdaPt").c_str(), "pRingObservableLeadPLambdaPt;#it{p}_{T}^{#Lambda};<#it{R}>", kTProfile, {axisConfigurations.axisPt}); + // For the second-to-leading jet: + histos.add((folder + "/pRingObservable2ndJetDeltaPhi").c_str(), "pRingObservable2ndJetDeltaPhi;#Delta#varphi_{2ndJet};<#it{R}>", kTProfile, {axisConfigurations.axisDeltaPhi}); + histos.add((folder + "/pRingObservable2ndJetDeltaTheta").c_str(), "pRingObservable2ndJetDeltaTheta;#Delta#theta_{2ndJet};<#it{R}>", kTProfile, {axisConfigurations.axisDeltaTheta}); + histos.add((folder + "/pRingObservable2ndJetIntegrated").c_str(), "pRingObservable2ndJetIntegrated; ;<#it{R}>", kTProfile, {{1, -0.5, 0.5}}); + histos.add((folder + "/pRingObservable2ndJetLambdaPt").c_str(), "pRingObservable2ndJetLambdaPt;#it{p}_{T}^{#Lambda};<#it{R}>", kTProfile, {axisConfigurations.axisPt}); + // =============================== + // 2D TProfiles (Lambda correlations) + // =============================== + histos.add((folder + "/p2dRingObservableDeltaPhiVsLambdaPt").c_str(), "p2dRingObservableDeltaPhiVsLambdaPt;#Delta#varphi_{jet};#it{p}_{T}^{#Lambda};<#it{R}>", kTProfile2D, {axisConfigurations.axisDeltaPhi, axisConfigurations.axisPt}); + histos.add((folder + "/p2dRingObservableDeltaThetaVsLambdaPt").c_str(), "p2dRingObservableDeltaThetaVsLambdaPt;#Delta#theta_{jet};#it{p}_{T}^{#Lambda};<#it{R}>", kTProfile2D, {axisConfigurations.axisDeltaTheta, axisConfigurations.axisPt}); + // =============================== + // 2D TProfiles (Jet correlations) + // =============================== + histos.add((folder + "/p2dRingObservableDeltaPhiVsLeadJetPt").c_str(), "p2dRingObservableDeltaPhiVsLeadJetPt;#Delta#varphi_{jet};#it{p}_{T}^{lead jet};<#it{R}>", kTProfile2D, {axisConfigurations.axisDeltaPhi, axisConfigurations.axisJetPt}); + histos.add((folder + "/p2dRingObservableDeltaThetaVsLeadJetPt").c_str(), "p2dRingObservableDeltaThetaVsLeadJetPt;#Delta#theta_{jet};#it{p}_{T}^{lead jet};<#it{R}>", kTProfile2D, {axisConfigurations.axisDeltaTheta, axisConfigurations.axisJetPt}); + + // =============================== + // Multi-dimensional histograms for signal extraction + // (Mass-dependent polarization extraction) + // =============================== + // Simple invariant mass plot for QA: + histos.add((folder + "/QA/hMass").c_str(), "hMass", kTH1D, {axisConfigurations.axisLambdaMass}); + histos.add((folder + "/hMassSigExtract").c_str(), "hMassSigExtract", kTH1D, {axisConfigurations.axisLambdaMassSigExtract}); + // 1D Mass dependence of observable numerator: + histos.add((folder + "/QA/hRingObservableNumMass").c_str(), "hRingObservableNumMass", kTH1D, {axisConfigurations.axisLambdaMassSigExtract}); + // --- 2D counters: Angle vs Mass vs --- + histos.add((folder + "/QA/h2dDeltaPhiVsMass").c_str(), "h2dDeltaPhiVsMass", kTH2D, {axisConfigurations.axisDeltaPhi, axisConfigurations.axisLambdaMassSigExtract}); + histos.add((folder + "/QA/h2dDeltaThetaVsMass").c_str(), "h2dDeltaThetaVsMass", kTH2D, {axisConfigurations.axisDeltaTheta, axisConfigurations.axisLambdaMassSigExtract}); + // --- 3D counters: Angle vs Mass vs Lambda pT --- + histos.add((folder + "/QA/h3dDeltaPhiVsMassVsLambdaPt").c_str(), "h3dDeltaPhiVsMassVsLambdaPt", kTH3D, {axisConfigurations.axisDeltaPhi, axisConfigurations.axisLambdaMassSigExtract, axisConfigurations.axisPtSigExtract}); + histos.add((folder + "/QA/h3dDeltaThetaVsMassVsLambdaPt").c_str(), "h3dDeltaThetaVsMassVsLambdaPt", kTH3D, {axisConfigurations.axisDeltaTheta, axisConfigurations.axisLambdaMassSigExtract, axisConfigurations.axisPtSigExtract}); + // --- 3D counters: Angle vs Mass vs Lead Jet pT --- + histos.add((folder + "/QA/h3dDeltaPhiVsMassVsLeadJetPt").c_str(), "h3dDeltaPhiVsMassVsLeadJetPt", kTH3D, {axisConfigurations.axisDeltaPhi, axisConfigurations.axisLambdaMassSigExtract, axisConfigurations.axisJetPtSigExtract}); + histos.add((folder + "/QA/h3dDeltaThetaVsMassVsLeadJetPt").c_str(), "h3dDeltaThetaVsMassVsLeadJetPt", kTH3D, {axisConfigurations.axisDeltaTheta, axisConfigurations.axisLambdaMassSigExtract, axisConfigurations.axisJetPtSigExtract}); + + // =============================== + // TProfiles vs Mass: quick glancing before signal extraction + // =============================== + // TProfile of ring vs mass (integrated in all phi, and properly normalized by N_\Lambda): + histos.add((folder + "/pRingObservableMass").c_str(), "pRingObservableMass;m_{p#pi};<#it{R}>", kTProfile, {axisConfigurations.axisLambdaMassSigExtract}); + histos.add((folder + "/pRingObservableLeadPMass").c_str(), "pRingObservableLeadPMass;m_{p#pi};<#it{R}>", kTProfile, {axisConfigurations.axisLambdaMassSigExtract}); + histos.add((folder + "/pRingObservable2ndJetMass").c_str(), "pRingObservable2ndJetMass;m_{p#pi};<#it{R}>", kTProfile, {axisConfigurations.axisLambdaMassSigExtract}); + // TProfile2D: vs Mass (DeltaPhi) + histos.add((folder + "/p2dRingObservableDeltaPhiVsMass").c_str(), "p2dRingObservableDeltaPhiVsMass;#Delta#varphi;m_{p#pi};<#it{R}>", kTProfile2D, {axisConfigurations.axisDeltaPhi, axisConfigurations.axisLambdaMassSigExtract}); + // TProfile2D: vs Mass (DeltaTheta) + histos.add((folder + "/p2dRingObservableDeltaThetaVsMass").c_str(), "p2dRingObservableDeltaThetaVsMass;#Delta#theta;m_{p#pi};<#it{R}>", kTProfile2D, {axisConfigurations.axisDeltaTheta, axisConfigurations.axisLambdaMassSigExtract}); + // --- TProfile3D: vs DeltaPhi vs Mass vs LambdaPt --- + histos.add((folder + "/p3dRingObservableDeltaPhiVsMassVsLambdaPt").c_str(), "p3dRingObservableDeltaPhiVsMassVsLambdaPt;#Delta#varphi;m_{p#pi};p_{T}^{#Lambda};<#it{R}>", kTProfile3D, {axisConfigurations.axisDeltaPhi, axisConfigurations.axisLambdaMassSigExtract, axisConfigurations.axisPtSigExtract}); + // --- TProfile3D: vs DeltaTheta vs Mass vs LambdaPt --- + histos.add((folder + "/p3dRingObservableDeltaThetaVsMassVsLambdaPt").c_str(), "p3dRingObservableDeltaThetaVsMassVsLambdaPt;#Delta#theta;m_{p#pi};p_{T}^{#Lambda};<#it{R}>", kTProfile3D, {axisConfigurations.axisDeltaTheta, axisConfigurations.axisLambdaMassSigExtract, axisConfigurations.axisPtSigExtract}); + // --- TProfile3D: vs DeltaPhi vs Mass vs LeadJetPt --- + histos.add((folder + "/p3dRingObservableDeltaPhiVsMassVsLeadJetPt").c_str(), "p3dRingObservableDeltaPhiVsMassVsLeadJetPt;#Delta#varphi;m_{p#pi};p_{T}^{jet};<#it{R}>", kTProfile3D, {axisConfigurations.axisDeltaPhi, axisConfigurations.axisLambdaMassSigExtract, axisConfigurations.axisJetPtSigExtract}); + // --- TProfile3D: vs DeltaTheta vs Mass vs LeadJetPt --- + histos.add((folder + "/p3dRingObservableDeltaThetaVsMassVsLeadJetPt").c_str(), "p3dRingObservableDeltaThetaVsMassVsLeadJetPt;#Delta#theta;m_{p#pi};p_{T}^{jet};<#it{R}>", kTProfile3D, {axisConfigurations.axisDeltaTheta, axisConfigurations.axisLambdaMassSigExtract, axisConfigurations.axisJetPtSigExtract}); + + // =============================== + // Mass histograms with centrality + // =============================== + // Counters + histos.add((folder + "/QA/h3dDeltaPhiVsMassVsCent").c_str(), "h3dDeltaPhiVsMassVsCent", kTH3D, {axisConfigurations.axisDeltaPhi, axisConfigurations.axisLambdaMassSigExtract, axisConfigurations.axisCentrality}); + histos.add((folder + "/QA/h3dDeltaThetaVsMassVsCent").c_str(), "h3dDeltaThetaVsMassVsCent", kTH3D, {axisConfigurations.axisDeltaTheta, axisConfigurations.axisLambdaMassSigExtract, axisConfigurations.axisCentrality}); + // Useful TProfiles: + // --- TProfile1D: Integrated vs Centrality: + histos.add((folder + "/pRingIntVsCentrality").c_str(), "pRingIntVsCentrality; Centrality (%);<#it{R}>", kTProfile, {axisConfigurations.axisCentrality}); + // --- TProfile2D: vs Mass vs Centrality --- + histos.add((folder + "/p2dRingObservableMassVsCent").c_str(), "p2dRingObservableMassVsCent;m_{p#pi};Centrality;<#it{R}>", kTProfile2D, {axisConfigurations.axisLambdaMassSigExtract, axisConfigurations.axisCentrality}); + // --- TProfile3D: vs DeltaPhi vs Mass vs Centrality --- + histos.add((folder + "/p3dRingObservableDeltaPhiVsMassVsCent").c_str(), "p3dRingObservableDeltaPhiVsMassVsCent;#Delta#varphi;m_{p#pi};Centrality;<#it{R}>", kTProfile3D, {axisConfigurations.axisDeltaPhi, axisConfigurations.axisLambdaMassSigExtract, axisConfigurations.axisCentrality}); + // --- TProfile3D: vs DeltaTheta vs Mass vs Centrality --- + histos.add((folder + "/p3dRingObservableDeltaThetaVsMassVsCent").c_str(), "p3dRingObservableDeltaThetaVsMassVsCent;#Delta#theta;m_{p#pi};Centrality;<#it{R}>", kTProfile3D, {axisConfigurations.axisDeltaTheta, axisConfigurations.axisLambdaMassSigExtract, axisConfigurations.axisCentrality}); + + // =============================== + // QA histograms - Useful numbers + // =============================== + // (TODO: implement these!) + // (TODO: implement momentum imbalance checks for jets!) + // Added to a separate folder for further control (changed the usage of the "folder" string): + // histos.add(("QA_Numbers/" + folder + "/hValidLeadJets").c_str(), "hValidLeadJets", kTH1D, {{1,0,1}}); + // TODO: Add "frequency of jets per pT" histograms either here or in the TableProducer + }; + // Execute local lambda to register histogram families: + addRingObservableFamily("Ring"); + addRingObservableFamily("RingKinematicCuts"); + addRingObservableFamily("JetKinematicCuts"); + addRingObservableFamily("JetAndLambdaKinematicCuts"); + + histos.add("pRingCuts", "pRingCuts; ;<#it{R}>", kTProfile, {{4, 0, 4}}); + histos.get(HIST("pRingCuts"))->GetXaxis()->SetBinLabel(1, "All #Lambda"); + histos.get(HIST("pRingCuts"))->GetXaxis()->SetBinLabel(2, "p_{T}^{#Lambda}@[0.5,1.5],|y_{#Lambda}|<0.5"); // (v0pt > 0.5 && v0pt < 1.5) && std::abs(lambdaRapidity) < 0.5; + histos.get(HIST("pRingCuts"))->GetXaxis()->SetBinLabel(3, "|Jet_{#eta}|<0.5"); + histos.get(HIST("pRingCuts"))->GetXaxis()->SetBinLabel(4, "#Lambda + Jet cuts"); + + // Same for subleading jet and leading particle: + histos.add("pRingCutsSubLeadingJet", "pRingCutsSubLeadingJet; ;<#it{R}>", kTProfile, {{4, 0, 4}}); + histos.get(HIST("pRingCutsSubLeadingJet"))->GetXaxis()->SetBinLabel(1, "All #Lambda"); + histos.get(HIST("pRingCutsSubLeadingJet"))->GetXaxis()->SetBinLabel(2, "p_{T,#Lambda}@[0.5,1.5],|y_{#Lambda}|<0.5"); + histos.get(HIST("pRingCutsSubLeadingJet"))->GetXaxis()->SetBinLabel(3, "|SubJet_{#eta}|<0.5"); + histos.get(HIST("pRingCutsSubLeadingJet"))->GetXaxis()->SetBinLabel(4, "#Lambda + SubJet cuts"); + + histos.add("pRingCutsLeadingP", "pRingCutsLeadingP; ;<#it{R}>", kTProfile, {{4, 0, 4}}); + histos.get(HIST("pRingCutsLeadingP"))->GetXaxis()->SetBinLabel(1, "All #Lambda"); + histos.get(HIST("pRingCutsLeadingP"))->GetXaxis()->SetBinLabel(2, "p_{T}^{#Lambda}@[0.5,1.5],|y_{#Lambda}|<0.5"); + histos.get(HIST("pRingCutsLeadingP"))->GetXaxis()->SetBinLabel(3, "|LeadP_{#eta}|<0.5"); + histos.get(HIST("pRingCutsLeadingP"))->GetXaxis()->SetBinLabel(4, "#Lambda + LeadP cuts"); + } + + // Helper to get centrality (same from TableProducer, thanks to templating!): + template + auto getCentrality(TCollision const& collision) + { + if (centralityEstimator == kCentFT0M) + return collision.centFT0M(); + else if (centralityEstimator == kCentFT0C) + return collision.centFT0C(); + else if (centralityEstimator == kCentFV0A) + return collision.centFV0A(); + return -1.f; + } + + // Initializing a random number generator for the worker (for perpendicular-to-jet direction QAs): + TRandom3 randomGen{0}; // 0 means we auto-seed from machine entropy. This is called once per device in the pipeline, so we should not see repeated seeds across workers + + // Preslices for correct collisions association: + // (TODO: test using custom grouping) + Preslice perColJets = o2::aod::lambdajetpol::collisionId; + Preslice perColV0s = o2::aod::lambdajetpol::collisionId; + Preslice perColLeadPs = o2::aod::lambdajetpol::collisionId; + void processPolarizationData(o2::aod::RingCollisions const& collisions, o2::aod::RingJets const& jets, o2::aod::RingLaV0s const& v0s, + o2::aod::RingLeadP const& leadPs) + { + for (auto const& collision : collisions) { + const auto collId = collision.collisionId(); + const double centrality = getCentrality(collision); + + // Slice jets, V0s and leading particle belonging to this collision: + // (global collision indices repeat a lot, but they are unique to a same TimeFrame (TF) subfolder in the derived data) + auto v0sInColl = v0s.sliceBy(perColV0s, collId); + auto leadPsInColl = leadPs.sliceBy(perColLeadPs, collId); + + // Check if there is at least one V0 and one jet in the collision: + // (in the way I fill the table, there is always at least one V0 in + // the stored collision, but the jets table can not be filled for + // that collision, and a collision may not be filled when the jets + // table is. Be mindful of that!) + // 1) Require at least one V0: + if (!v0sInColl.size()) + continue; + + // 2) We require at least a leading particle, then we get the leading jet only if it exists: + // (The goal is to see how diluted the signal gets with events which don't even have a loose FastJet jet) + // (The leading particle is built from all tracks that passed the pseudojet + // selection, so it exists whenever FastJet was run on this collision. + // Events that have a leading jet always have a leading particle too, but + // the converse is not true: events can have a leading particle with no jet + // if no jet survives the pT threshold/the background subtraction) + float leadPPt = -1.; // pT = -1 means "table entry not found for this collision". + float leadPEta = 0.; + float leadPPhi = 0.; + float leadPPx = 0., leadPPy = 0., leadPPz = 0.; + for (auto const& lp : leadPsInColl) { + // Table should contain exactly one entry per collision, + // but we break immediately to be safe: + leadPPt = lp.leadParticlePt(); + leadPEta = lp.leadParticleEta(); + leadPPhi = lp.leadParticlePhi(); + // Using dynamic columns to make code cleaner: + leadPPx = lp.leadParticlePx(); + leadPPy = lp.leadParticlePy(); + leadPPz = lp.leadParticlePz(); + break; + } + // Discard events with no leading particle (FastJet didn't even run in these cases!): + if (leadPPt < 0.) + continue; + + // Build leading particle unit vector, outside the V0 loop for performance: + XYZVector leadPUnitVec = XYZVector(leadPPx, leadPPy, leadPPz).Unit(); + + // 3) Checking if the event has a leading jet: + auto jetsInColl = jets.sliceBy(perColJets, collId); + float leadingJetPt = -1.; + float subleadingJetPt = -1.; + // std::optional avoids undefined behaviour from a default-constructed iterator: + // (essentially, just protection for when we fetch jetEta() and the such) + std::optional leadingJet; + std::optional subleadingJet; + for (auto const& jet : jetsInColl) { + const auto jetpt = jet.jetPt(); + if (jetpt > leadingJetPt) { + // Current leading becomes subleading: + subleadingJetPt = leadingJetPt; + subleadingJet = leadingJet; // may still be std::nullopt on first pass -- that is fine! + // Now update the leading jet: + leadingJetPt = jetpt; + leadingJet = jet; + } else if (jetpt > subleadingJetPt) { // Update subleading only: + subleadingJetPt = jetpt; + subleadingJet = jet; + } + } + + // Some useful bools to check if we have a leading jet and a subleading jet: + const bool hasValidLeadingJet = leadingJetPt > 0.; + const bool hasValidSubJet = subleadingJetPt > 0.; + + // Build jet vectors (only when the corresponding jet exists): + // Dummy initialisations are safe: all jet-dependent fills are gated on hasValidLeadingJet / hasValidSubJet. + float leadingJetEta = 0.; + float leadingJetPhi = 0.; + XYZVector leadingJetUnitVec(1., 0., 0.); // dummy (overwritten below) + if (hasValidLeadingJet) { + leadingJetEta = leadingJet->jetEta(); + leadingJetPhi = leadingJet->jetPhi(); + // Using internal getters to make code cleaner: + leadingJetUnitVec = XYZVector(leadingJet->jetPx(), leadingJet->jetPy(), leadingJet->jetPz()).Unit(); + + // QA block -- Purposefully changing the jet direction (should kill signal, if any): + if (forcePerpToJet) { // Use modified jet direction (done outside loop to guarantee all V0s inside event use same fake jet) + // First, we build a vector perpendicular to the jet by picking an arbitrary vector not parallel to the jet + XYZVector refVec(1., 0., 0.); + if (std::abs(leadingJetUnitVec.Dot(refVec)) > 0.99) + refVec = XYZVector(0., 1., 0.); + // Now we get a perpendicular vector to the jet direction: + XYZVector perpVec = leadingJetUnitVec.Cross(refVec).Unit(); + // Now we rotate around the jet axis by a random angle, just to make sure we are not introducing a bias in the QA: + // We will use Rodrigues' rotation formula (v_rot = v*cos(randomAngle) + (Jet \cross v)*sin(randomAngle)) + double randomAngle = randomGen.Uniform(0., o2::constants::math::TwoPI); + leadingJetUnitVec = perpVec * std::cos(randomAngle) + leadingJetUnitVec.Cross(perpVec) * std::sin(randomAngle); + } else if (forceJetDirectionSmudge) { + // Smear the jet direction by a small random angle to estimate sensitivity to + // jet axis uncertainty. We rotate the jet axis by angle theta around a uniformly + // random perpendicular axis -- this is isotropic and coordinate-independent, + // unlike smearing eta and phi separately (which would break azimuthal symmetry + // around the jet axis and depend on where in eta the jet sits). + + // 1) We pick a uniformly random axis perpendicular to the jet. + // (re-using the same Rodrigues formula as in the forcePerpToJet block above) + XYZVector refVec(1., 0., 0.); + if (std::abs(leadingJetUnitVec.Dot(refVec)) > 0.99) + refVec = XYZVector(0., 1., 0.); + XYZVector perpVec = leadingJetUnitVec.Cross(refVec).Unit(); + // Rotate perpVec around the jet axis by a uniform random azimuth to get + // a uniformly distributed random perpendicular direction (the smear axis): + double smearAzimuth = randomGen.Uniform(0., o2::constants::math::TwoPI); + XYZVector smearAxis = perpVec * std::cos(smearAzimuth) + leadingJetUnitVec.Cross(perpVec) * std::sin(smearAzimuth); + + // Step 2: draw the smearing polar angle from a Gaussian: + // sigma = 0.05 * R --> ~68% of events smeared within 5% of R, + // ~95% of events smeared within 10% of R, + // ~5% see a displacement > 0.1*R (a very "badly determined jet", for our QA purposes) + // std::abs() folds the symmetric Gaussian onto a half-normal ([0, inf)) + // -- R is not really an angle: just gives me a scale for the angular shift I am performing. + // -- This may pose problems for forward jets: a small displacemente in \theta becomes a large displacement in \eta space + double smearSigma = 0.05 * jetRForSmuding; + double smearAngle = std::abs(randomGen.Gaus(0., smearSigma)); + + // Step 3: rotate the jet axis by smearAngle around smearAxis. + // Rodrigues is v_rot = v*cos(theta) + (k \croos v)*sin(theta) + k*(k \cdot v)*(1-cos(theta)) + // But the last term vanishes because smearAxis is perpendicular to leadingJetUnitVec: + leadingJetUnitVec = leadingJetUnitVec * std::cos(smearAngle) + smearAxis.Cross(leadingJetUnitVec) * std::sin(smearAngle); + // Also, rotation preserves the norm, so no re-normalisation is needed for this to be a unit vector. + } + } + + float subleadingJetEta = 0.; + float subleadingJetPhi = 0.; + XYZVector subJetUnitVec(1., 0., 0.); + if (hasValidSubJet) { + subleadingJetEta = subleadingJet->jetEta(); + subleadingJetPhi = subleadingJet->jetPhi(); + // Using internal getters to make code cleaner: + subJetUnitVec = XYZVector(subleadingJet->jetPx(), subleadingJet->jetPy(), subleadingJet->jetPz()).Unit(); + } + + // (jet eta cuts only meaningful when the jet actually exists) + const bool kinematicJetCheck = hasValidLeadingJet && (std::abs(leadingJetEta) < 0.5); + const bool kinematic2ndJetCheck = hasValidSubJet && (std::abs(subleadingJetEta) < 0.5); + const bool kinematicLeadPCheck = std::abs(leadPEta) < 0.5; + + for (auto const& v0 : v0sInColl) { + const bool isLambda = v0.isLambda(); + const bool isAntiLambda = v0.isAntiLambda(); + // For now, removing the ambiguous candidates from the analysis. Derived data permits handling both. + // (From Podolanski-Armenteros plots, the population of ambiguous is ~2% without TOF, and without + // competing mass rejection. From those, ~99% seem to be K0s, so no real gain in considering the + // ambiguous candidates in the analysis) + if (isLambda && isAntiLambda) + continue; + const float v0pt = v0.v0Pt(); + const float v0eta = v0.v0Eta(); + const float v0phi = v0.v0Phi(); + + float v0LambdaLikeMass = 0; // Initialized just to catch any stray behavior + float protonLikePt = 0; + float protonLikeEta = 0; + float protonLikePhi = 0; + if (isLambda) { + if (!analyseLambda) + continue; + v0LambdaLikeMass = v0.massLambda(); + protonLikePt = v0.posPt(); + protonLikeEta = v0.posEta(); + protonLikePhi = v0.posPhi(); + } else if (isAntiLambda) { // (TODO: add a split histogram where you consider Lambda and AntiLambda polarization separately?) + if (!analyseAntiLambda) + continue; + v0LambdaLikeMass = v0.massAntiLambda(); + protonLikePt = v0.negPt(); + protonLikeEta = v0.negEta(); + protonLikePhi = v0.negPhi(); + } + + PtEtaPhiMVector lambdaLike4Vec(v0pt, v0eta, v0phi, v0LambdaLikeMass); + PtEtaPhiMVector protonLike4Vec(protonLikePt, protonLikeEta, protonLikePhi, protonMass); + float lambdaRapidity = lambdaLike4Vec.Rapidity(); // For further kinematic selections + + // Boosting proton into lambda frame: + XYZVector beta = -lambdaLike4Vec.BoostToCM(); // Boost trivector that goes from laboratory frame to the rest frame + auto protonLike4VecStar = ROOT::Math::VectorUtil::boost(protonLike4Vec, beta); + + // Getting unit vectors and 3-components: + XYZVector lambdaLike3Vec = lambdaLike4Vec.Vect(); + XYZVector protonLikeStarUnit3Vec = protonLike4VecStar.Vect().Unit(); + + //////////////////////////////////////////// + // Ring observable: Leading particle proxy + // Always computed -- leading particle existence is guaranteed by the second check above + //////////////////////////////////////////// + // Cross product + XYZVector crossLeadP = leadPUnitVec.Cross(lambdaLike3Vec); + float ringObservableLeadP = protonLikeStarUnit3Vec.Dot(crossLeadP) / crossLeadP.R(); + // Adding the prefactor related to the CP-violating decay (decay constants have different signs) + if (!forcePolSignQA) + ringObservableLeadP *= (isLambda) ? polPrefactorLambda : polPrefactorAntiLambda; + else + ringObservableLeadP *= (isLambda) ? polPrefactorLambda : -1.0 * polPrefactorAntiLambda; + // Angular variables + float deltaPhiLeadP = wrapToPiFast(v0phi - leadPPhi); // Wrapped to [-PI, pi), for convenience + float deltaThetaLeadP = ROOT::Math::VectorUtil::Angle(leadPUnitVec, lambdaLike3Vec); // 3D angular separation + + ////////////////////////////////////////// + // Ring observable: Leading jet proxy + // Only computed when a leading jet exists in this collision. + ////////////////////////////////////////// + float ringObservable = 0.; + float deltaPhiJet = 0.; + float deltaThetaJet = 0.; + if (hasValidLeadingJet) { + // Cross product + XYZVector cross = leadingJetUnitVec.Cross(lambdaLike3Vec); + ringObservable = protonLikeStarUnit3Vec.Dot(cross) / cross.R(); + // Adding prefactor + if (!forcePolSignQA) + ringObservable *= (isLambda) ? polPrefactorLambda : polPrefactorAntiLambda; + else + ringObservable *= (isLambda) ? polPrefactorLambda : -1.0 * polPrefactorAntiLambda; + // Angular variables + deltaPhiJet = wrapToPiFast(v0phi - leadingJetPhi); + deltaThetaJet = ROOT::Math::VectorUtil::Angle(leadingJetUnitVec, lambdaLike3Vec); + } + + ////////////////////////////////////////// + // Ring observable: Subleading jet proxy + // Only computed when a subleading jet exists in this collision. + ////////////////////////////////////////// + float ringObservable2ndJet = 0.; + float deltaPhi2ndJet = 0.; + float deltaTheta2ndJet = 0.; + if (hasValidSubJet) { + XYZVector cross2ndJet = subJetUnitVec.Cross(lambdaLike3Vec); + ringObservable2ndJet = protonLikeStarUnit3Vec.Dot(cross2ndJet) / cross2ndJet.R(); + // Adding prefactor + if (!forcePolSignQA) + ringObservable2ndJet *= (isLambda) ? polPrefactorLambda : polPrefactorAntiLambda; + else + ringObservable2ndJet *= (isLambda) ? polPrefactorLambda : -1.0 * polPrefactorAntiLambda; + // Angular variables + deltaPhi2ndJet = wrapToPiFast(v0phi - subleadingJetPhi); + deltaTheta2ndJet = ROOT::Math::VectorUtil::Angle(subJetUnitVec, lambdaLike3Vec); + } + + // Calculating polarization observables (in the Lambda frame, because that is easier -- does not require boosts): + // To be precise, not actually the polarization, but a part of the summand in P^*_\Lambda = (3/\alpha_\Lambda) * + float PolStarX = 0, PolStarY = 0, PolStarZ = 0; // Dummy initialization: avoid warnings in compile time + if (isLambda) { // Notice there is no need to check analyseLambda again due to previous checks. + PolStarX = polPrefactorLambda * protonLikeStarUnit3Vec.X(); + PolStarY = polPrefactorLambda * protonLikeStarUnit3Vec.Y(); + PolStarZ = polPrefactorLambda * protonLikeStarUnit3Vec.Z(); + } else if (isAntiLambda) { + PolStarX = polPrefactorAntiLambda * protonLikeStarUnit3Vec.X(); + PolStarY = polPrefactorAntiLambda * protonLikeStarUnit3Vec.Y(); + PolStarZ = polPrefactorAntiLambda * protonLikeStarUnit3Vec.Z(); + } + + float v0phiToFillHists = wrapToPiFast(v0phi); // A short wrap to reuse some predefined axes + + // Fill ring histograms: (1D, lambda 2D correlations and jet 2D correlations): + RING_OBSERVABLE_LEADP_FILL_LIST(APPLY_HISTO_FILL, "Ring") // Notice the usage of macros! If you change the variable names, this WILL break the code! + // No, there should NOT be any ";" here! Read the macro definition for an explanation + histos.fill(HIST("pRingCutsLeadingP"), 0, ringObservableLeadP); // First bin of comparison + POLARIZATION_PROFILE_FILL_LIST(APPLY_HISTO_FILL, "Ring") + + if (hasValidLeadingJet) { + RING_OBSERVABLE_FILL_LIST(APPLY_HISTO_FILL, "Ring") + histos.fill(HIST("pRingCuts"), 0, ringObservable); + } + if (hasValidSubJet) { + RING_OBSERVABLE_2NDJET_FILL_LIST(APPLY_HISTO_FILL, "Ring") + histos.fill(HIST("pRingCutsSubLeadingJet"), 0, ringObservable2ndJet); + } + + // Extra kinematic criteria for Lambda candidates (removes polarization background): + const bool kinematicLambdaCheck = (v0pt > 0.5 && v0pt < 1.5) && std::abs(lambdaRapidity) < 0.5; + if (kinematicLambdaCheck) { + RING_OBSERVABLE_LEADP_FILL_LIST(APPLY_HISTO_FILL, "RingKinematicCuts") + histos.fill(HIST("pRingCutsLeadingP"), 1, ringObservableLeadP); + POLARIZATION_PROFILE_FILL_LIST(APPLY_HISTO_FILL, "RingKinematicCuts") + if (hasValidLeadingJet) { + RING_OBSERVABLE_FILL_LIST(APPLY_HISTO_FILL, "RingKinematicCuts") + histos.fill(HIST("pRingCuts"), 1, ringObservable); + } + if (hasValidSubJet) { + RING_OBSERVABLE_2NDJET_FILL_LIST(APPLY_HISTO_FILL, "RingKinematicCuts") + histos.fill(HIST("pRingCutsSubLeadingJet"), 1, ringObservable2ndJet); + } + } + + // Extra selection criteria on jet candidates: + // (redundant for jets with R=0.4, but for jets with R<0.4 the leading jet may be farther in eta) + if (kinematicJetCheck) { // Already includes hasValidLeadingJet in the bool! (no need to check again) + RING_OBSERVABLE_FILL_LIST(APPLY_HISTO_FILL, "JetKinematicCuts") + histos.fill(HIST("pRingCuts"), 2, ringObservable); + POLARIZATION_PROFILE_FILL_LIST(APPLY_HISTO_FILL, "JetKinematicCuts") + } + + // Extra selection criteria on both Lambda and jet candidates: + if (kinematicLambdaCheck && kinematicJetCheck) { + RING_OBSERVABLE_FILL_LIST(APPLY_HISTO_FILL, "JetAndLambdaKinematicCuts") + histos.fill(HIST("pRingCuts"), 3, ringObservable); + POLARIZATION_PROFILE_FILL_LIST(APPLY_HISTO_FILL, "JetAndLambdaKinematicCuts") + } + + // Same variations for the leading particle and for the subleading jet: + if (kinematicLeadPCheck) { + RING_OBSERVABLE_LEADP_FILL_LIST(APPLY_HISTO_FILL, "JetKinematicCuts") + histos.fill(HIST("pRingCutsLeadingP"), 2, ringObservableLeadP); + } + if (kinematic2ndJetCheck) { + RING_OBSERVABLE_2NDJET_FILL_LIST(APPLY_HISTO_FILL, "JetKinematicCuts") + histos.fill(HIST("pRingCutsSubLeadingJet"), 2, ringObservable2ndJet); + } + if (kinematicLambdaCheck && kinematicLeadPCheck) { + RING_OBSERVABLE_LEADP_FILL_LIST(APPLY_HISTO_FILL, "JetAndLambdaKinematicCuts") + histos.fill(HIST("pRingCutsLeadingP"), 3, ringObservableLeadP); + } + if (kinematicLambdaCheck && kinematic2ndJetCheck) { + RING_OBSERVABLE_2NDJET_FILL_LIST(APPLY_HISTO_FILL, "JetAndLambdaKinematicCuts") + histos.fill(HIST("pRingCutsSubLeadingJet"), 3, ringObservable2ndJet); + } + } // end v0s loop + } // end collisions + } + + PROCESS_SWITCH(lambdajetpolarizationionsderived, processPolarizationData, "Process derived data in Run 3 Data", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} + +// Avoid macro leakage! +#undef APPLY_HISTO_FILL From 97898a6b8b95b04b49bed4947d40037478c95366 Mon Sep 17 00:00:00 2001 From: Marvin Hemmer <53471402+mhemmer-cern@users.noreply.github.com> Date: Thu, 5 Mar 2026 00:29:33 +0100 Subject: [PATCH 171/347] [PWGEM] PhotonMeson: Switch from EMEvents to PMEvents (#15270) --- PWGEM/PhotonMeson/Core/EMCPhotonCut.h | 6 +- PWGEM/PhotonMeson/Core/PhotonHBT.h | 5 +- PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h | 33 ++++---- PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h | 37 ++++----- PWGEM/PhotonMeson/Core/TaggingPi0.h | 17 ++-- PWGEM/PhotonMeson/Core/TaggingPi0MC.h | 15 ++-- PWGEM/PhotonMeson/Core/V0PhotonCut.h | 6 +- PWGEM/PhotonMeson/DataModel/EventTables.h | 78 +++++++++++++++++++ PWGEM/PhotonMeson/DataModel/gammaTables.h | 40 +++++----- .../PhotonMeson/TableProducer/CMakeLists.txt | 5 ++ .../TableProducer/createEMEventPhoton.cxx | 15 ++-- .../TableProducer/nonLinProducer.cxx | 11 +-- .../TableProducer/pmQvectorDummyOtf.cxx | 48 ++++++++++++ .../TableProducer/skimmerDalitzEE.cxx | 11 +-- PWGEM/PhotonMeson/Tasks/MaterialBudget.cxx | 9 ++- PWGEM/PhotonMeson/Tasks/MaterialBudgetMC.cxx | 5 +- PWGEM/PhotonMeson/Tasks/SinglePhoton.cxx | 5 +- PWGEM/PhotonMeson/Tasks/SinglePhotonMC.cxx | 5 +- PWGEM/PhotonMeson/Tasks/TagAndProbe.cxx | 5 +- PWGEM/PhotonMeson/Tasks/calibTaskEmc.cxx | 11 +-- PWGEM/PhotonMeson/Tasks/compconvbuilder.cxx | 7 +- PWGEM/PhotonMeson/Tasks/dalitzEEQC.cxx | 9 ++- PWGEM/PhotonMeson/Tasks/dalitzEEQCMC.cxx | 9 ++- PWGEM/PhotonMeson/Tasks/emcalQC.cxx | 5 +- PWGEM/PhotonMeson/Tasks/gammaConversions.cxx | 7 +- PWGEM/PhotonMeson/Tasks/pcmQC.cxx | 7 +- PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx | 7 +- PWGEM/PhotonMeson/Tasks/phosQC.cxx | 3 +- PWGEM/PhotonMeson/Tasks/photonResoTask.cxx | 7 +- PWGEM/PhotonMeson/Tasks/prefilterPhoton.cxx | 15 ++-- PWGEM/PhotonMeson/Tasks/taskFlowReso.cxx | 3 +- PWGEM/PhotonMeson/Tasks/taskPi0FlowEMC.cxx | 11 +-- 32 files changed, 306 insertions(+), 151 deletions(-) create mode 100644 PWGEM/PhotonMeson/DataModel/EventTables.h create mode 100644 PWGEM/PhotonMeson/TableProducer/pmQvectorDummyOtf.cxx diff --git a/PWGEM/PhotonMeson/Core/EMCPhotonCut.h b/PWGEM/PhotonMeson/Core/EMCPhotonCut.h index 57ed3fb4a2b..3f10f83d55f 100644 --- a/PWGEM/PhotonMeson/Core/EMCPhotonCut.h +++ b/PWGEM/PhotonMeson/Core/EMCPhotonCut.h @@ -295,9 +295,9 @@ class EMCPhotonCut : public TNamed const bool doQA = mDoQA && fRegistry != nullptr; nTotClusterPerColl = 0; - currentCollID = clusters.iteratorAt(0).emphotoneventId(); + currentCollID = clusters.iteratorAt(0).pmeventId(); for (const auto& cluster : clusters) { - const auto collID = cluster.emphotoneventId(); + const auto collID = cluster.pmeventId(); if (doQA) { fillBeforeClusterHistogram(cluster, fRegistry); } @@ -376,7 +376,7 @@ class EMCPhotonCut : public TNamed } return false; } - if (currentCollID == cluster.emphotoneventId()) { + if (currentCollID == cluster.pmeventId()) { ++nAccClusterPerColl; } else { if (doQA) { diff --git a/PWGEM/PhotonMeson/Core/PhotonHBT.h b/PWGEM/PhotonMeson/Core/PhotonHBT.h index 060768cdfde..fcd9d9d9ce7 100644 --- a/PWGEM/PhotonMeson/Core/PhotonHBT.h +++ b/PWGEM/PhotonMeson/Core/PhotonHBT.h @@ -20,6 +20,7 @@ #include "PWGEM/Dilepton/Utils/EventMixingHandler.h" #include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" #include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/EventHistograms.h" // @@ -71,7 +72,7 @@ using namespace o2::soa; using namespace o2::aod::pwgem::dilepton::utils; using namespace o2::aod::pwgem::photon::core::photonhbt; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; using MyV0Photons = soa::Join; @@ -668,7 +669,7 @@ struct PhotonHBT { std::map, uint64_t> map_mixed_eventId_to_globalBC; SliceCache cache; - Preslice perCollision_pcm = aod::v0photonkf::emphotoneventId; + Preslice perCollision_pcm = aod::v0photonkf::pmeventId; Filter collisionFilter_centrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); Filter collisionFilter_occupancy_track = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; diff --git a/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h b/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h index 25d149538cb..952fc5348ea 100644 --- a/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h +++ b/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h @@ -21,6 +21,7 @@ #include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" #include "PWGEM/PhotonMeson/Core/PHOSPhotonCut.h" #include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/EventHistograms.h" #include "PWGEM/PhotonMeson/Utils/NMHistograms.h" @@ -226,10 +227,10 @@ struct Pi0EtaToGammaGamma { //--------------------------------------------------------------------------- // Preslices and partitions o2::framework::SliceCache cache; - o2::framework::PresliceOptional>> perCollision_pcm = o2::aod::v0photonkf::emphotoneventId; - o2::framework::PresliceOptional> perCollision_emc = o2::aod::emccluster::emphotoneventId; - o2::framework::PresliceOptional> perCollision_phos = o2::aod::phoscluster::emphotoneventId; - o2::framework::PresliceOptional>> perCollision_electron = o2::aod::emprimaryelectronda::emphotoneventId; + o2::framework::PresliceOptional>> perCollision_pcm = o2::aod::v0photonkf::pmeventId; + o2::framework::PresliceOptional> perCollision_emc = o2::aod::emccluster::pmeventId; + o2::framework::PresliceOptional> perCollision_phos = o2::aod::phoscluster::pmeventId; + o2::framework::PresliceOptional>> perCollision_electron = o2::aod::emprimaryelectronda::pmeventId; o2::framework::PresliceOptional perEMCClusterMT = o2::aod::trackmatching::emEmcClusterId; o2::framework::PresliceOptional perEMCClusterMS = o2::aod::trackmatching::emEmcClusterId; @@ -262,7 +263,7 @@ struct Pi0EtaToGammaGamma { static auto& perCollision() { - static auto slice{o2::aod::v0photonkf::emphotoneventId}; + static auto slice{o2::aod::v0photonkf::pmeventId}; return slice; } @@ -283,7 +284,7 @@ struct Pi0EtaToGammaGamma { static auto& perCollision() { - static auto slice{o2::aod::emccluster::emphotoneventId}; + static auto slice{o2::aod::emccluster::pmeventId}; return slice; } @@ -317,7 +318,7 @@ struct Pi0EtaToGammaGamma { static auto& perCollision() { - static auto slice{o2::aod::phoscluster::emphotoneventId}; + static auto slice{o2::aod::phoscluster::pmeventId}; return slice; } @@ -338,7 +339,7 @@ struct Pi0EtaToGammaGamma { static auto& perCollision() { - static auto slice{o2::aod::emprimaryelectronda::emphotoneventId}; + static auto slice{o2::aod::emprimaryelectronda::pmeventId}; return slice; } @@ -709,7 +710,7 @@ struct Pi0EtaToGammaGamma { } float weight = 1.f; - if constexpr (std::is_same_v, o2::soa::Filtered, o2::aod::EMEventsWeight>>>) { + if constexpr (std::is_same_v, o2::soa::Filtered, o2::aod::EMEventsWeight>>>) { weight = collision.weight(); } @@ -776,8 +777,8 @@ struct Pi0EtaToGammaGamma { if constexpr (pairtype == o2::aod::pwgem::photonmeson::photonpair::PairType::kPCMDalitzEE) { auto photons1_per_collision = photons1.sliceByCached(TDetectorTag1::perCollision(), collision.globalIndex(), cache); - auto positrons_per_collision = positrons->sliceByCached(o2::aod::emprimaryelectronda::emphotoneventId, collision.globalIndex(), cache); - auto electrons_per_collision = electrons->sliceByCached(o2::aod::emprimaryelectronda::emphotoneventId, collision.globalIndex(), cache); + auto positrons_per_collision = positrons->sliceByCached(o2::aod::emprimaryelectronda::pmeventId, collision.globalIndex(), cache); + auto electrons_per_collision = electrons->sliceByCached(o2::aod::emprimaryelectronda::pmeventId, collision.globalIndex(), cache); for (const auto& g1 : photons1_per_collision) { if constexpr (std::is_same_v) { @@ -1024,13 +1025,13 @@ struct Pi0EtaToGammaGamma { o2::framework::expressions::Filter collisionFilter_occupancy_track = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; o2::framework::expressions::Filter collisionFilter_occupancy_ft0c = eventcuts.cfgFT0COccupancyMin <= o2::aod::evsel::ft0cOccupancyInTimeRange && o2::aod::evsel::ft0cOccupancyInTimeRange < eventcuts.cfgFT0COccupancyMax; o2::framework::expressions::Filter collisionFilter_centrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); - // using FilteredMyCollisions = o2::soa::Filtered>; + // using FilteredMyCollisions = o2::soa::Filtered>; o2::framework::expressions::Filter prefilter_pcm = ifnode(pcmcuts.cfg_apply_cuts_from_prefilter_derived.node(), o2::aod::v0photonkf::pfbderived == static_cast(0), true); o2::framework::expressions::Filter prefilter_primaryelectron = ifnode(dileptoncuts.cfg_apply_cuts_from_prefilter_derived.node(), o2::aod::emprimaryelectron::pfbderived == static_cast(0), true); int ndf = 0; - void processAnalysis(o2::soa::Filtered> const& collisions, Types const&... args) + void processAnalysis(o2::soa::Filtered> const& collisions, Types const&... args) { // LOGF(info, "ndf = %d", ndf); if constexpr (pairtype == o2::aod::pwgem::photonmeson::photonpair::PairType::kPCMPCM) { @@ -1066,8 +1067,8 @@ struct Pi0EtaToGammaGamma { } PROCESS_SWITCH(Pi0EtaToGammaGamma, processAnalysis, "process pair analysis", true); - // using FilteredMyCollisionsWithJJMC = o2::soa::Filtered, o2::aod::EMEventsWeight>>; - void processAnalysisJJMC(o2::soa::Filtered, o2::aod::EMEventsWeight>> const& collisions, Types const&... args) + // using FilteredMyCollisionsWithJJMC = o2::soa::Filtered, o2::aod::EMEventsWeight>>; + void processAnalysisJJMC(o2::soa::Filtered, o2::aod::EMEventsWeight>> const& collisions, Types const&... args) { // LOGF(info, "ndf = %d", ndf); if constexpr (pairtype == o2::aod::pwgem::photonmeson::photonpair::PairType::kPCMPCM) { @@ -1094,7 +1095,7 @@ struct Pi0EtaToGammaGamma { } PROCESS_SWITCH(Pi0EtaToGammaGamma, processAnalysisJJMC, "process pair analysis", false); - void processDummy(o2::aod::EMEvents_004 const&) {} + void processDummy(o2::aod::PMEvents const&) {} PROCESS_SWITCH(Pi0EtaToGammaGamma, processDummy, "Dummy function", false); }; #endif // PWGEM_PHOTONMESON_CORE_PI0ETATOGAMMAGAMMA_H_ diff --git a/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h b/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h index 3308b9c817c..9170a97ea73 100644 --- a/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h +++ b/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h @@ -21,6 +21,7 @@ #include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" #include "PWGEM/PhotonMeson/Core/PHOSPhotonCut.h" #include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/EventHistograms.h" #include "PWGEM/PhotonMeson/Utils/MCUtilities.h" @@ -423,10 +424,10 @@ struct Pi0EtaToGammaGammaMC { } o2::framework::SliceCache cache; - o2::framework::PresliceOptional>> perCollision_pcm = o2::aod::v0photonkf::emphotoneventId; - o2::framework::PresliceOptional> perCollision_emc = o2::aod::emccluster::emphotoneventId; - o2::framework::PresliceOptional> perCollision_phos = o2::aod::phoscluster::emphotoneventId; - o2::framework::PresliceOptional>> perCollision_electron = o2::aod::emprimaryelectronda::emphotoneventId; + o2::framework::PresliceOptional>> perCollision_pcm = o2::aod::v0photonkf::pmeventId; + o2::framework::PresliceOptional> perCollision_emc = o2::aod::emccluster::pmeventId; + o2::framework::PresliceOptional> perCollision_phos = o2::aod::phoscluster::pmeventId; + o2::framework::PresliceOptional>> perCollision_electron = o2::aod::emprimaryelectronda::pmeventId; o2::framework::PresliceOptional perEMCClusterMT = o2::aod::trackmatching::emEmcClusterId; o2::framework::PresliceOptional perEMCClusterMS = o2::aod::trackmatching::emEmcClusterId; @@ -440,7 +441,7 @@ struct Pi0EtaToGammaGammaMC { static auto& perCollision() { - static auto slice{o2::aod::v0photonkf::emphotoneventId}; + static auto slice{o2::aod::v0photonkf::pmeventId}; return slice; } @@ -461,7 +462,7 @@ struct Pi0EtaToGammaGammaMC { static auto& perCollision() { - static auto slice{o2::aod::emccluster::emphotoneventId}; + static auto slice{o2::aod::emccluster::pmeventId}; return slice; } @@ -495,7 +496,7 @@ struct Pi0EtaToGammaGammaMC { static auto& perCollision() { - static auto slice{o2::aod::phoscluster::emphotoneventId}; + static auto slice{o2::aod::phoscluster::pmeventId}; return slice; } @@ -515,7 +516,7 @@ struct Pi0EtaToGammaGammaMC { struct DalitzEETag { static auto& perCollision() { - static auto slice{o2::aod::emprimaryelectronda::emphotoneventId}; + static auto slice{o2::aod::emprimaryelectronda::pmeventId}; return slice; } @@ -566,7 +567,7 @@ struct Pi0EtaToGammaGammaMC { } float weight = 1.f; - if constexpr (std::is_same_v, o2::soa::Filtered, o2::aod::EMEventsWeight>>>) { + if constexpr (std::is_same_v, o2::soa::Filtered, o2::aod::EMEventsWeight>>>) { weight = collision.weight(); } @@ -703,8 +704,8 @@ struct Pi0EtaToGammaGammaMC { } else if constexpr (pairtype == o2::aod::pwgem::photonmeson::photonpair::PairType::kPCMDalitzEE) { auto photons1_per_collision = photons1.sliceByCached(TDetectorTag1::perCollision(), collision.globalIndex(), cache); - auto positrons_per_collision = positrons->sliceByCached(o2::aod::emprimaryelectronda::emphotoneventId, collision.globalIndex(), cache); - auto electrons_per_collision = electrons->sliceByCached(o2::aod::emprimaryelectronda::emphotoneventId, collision.globalIndex(), cache); + auto positrons_per_collision = positrons->sliceByCached(o2::aod::emprimaryelectronda::pmeventId, collision.globalIndex(), cache); + auto electrons_per_collision = electrons->sliceByCached(o2::aod::emprimaryelectronda::pmeventId, collision.globalIndex(), cache); for (const auto& g1 : photons1_per_collision) { if constexpr (std::is_same_v) { @@ -851,7 +852,7 @@ struct Pi0EtaToGammaGammaMC { } o2::framework::PresliceUnsorted perMcCollision = o2::aod::emmcparticle::emmceventId; - o2::framework::PresliceUnsorted> rec_perMcCollision = o2::aod::emmceventlabel::emmceventId; + o2::framework::PresliceUnsorted> rec_perMcCollision = o2::aod::emmceventlabel::emmceventId; template void runGenInfo(TCollisions const& collisions, TMCCollisions const& mccollisions, TMCParticles const& /*mcparticles*/) @@ -871,7 +872,7 @@ struct Pi0EtaToGammaGammaMC { } float weight = 1.f; - if constexpr (std::is_same_v, o2::soa::Filtered, o2::aod::EMEventsWeight>>>) { + if constexpr (std::is_same_v, o2::soa::Filtered, o2::aod::EMEventsWeight>>>) { weight = collision.weight(); } @@ -899,12 +900,12 @@ struct Pi0EtaToGammaGammaMC { o2::framework::expressions::Filter collisionFilter_occupancy_track = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; o2::framework::expressions::Filter collisionFilter_occupancy_ft0c = eventcuts.cfgFT0COccupancyMin <= o2::aod::evsel::ft0cOccupancyInTimeRange && o2::aod::evsel::ft0cOccupancyInTimeRange < eventcuts.cfgFT0COccupancyMax; o2::framework::expressions::Filter collisionFilter_centrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); - // using FilteredMyCollisions = o2::soa::Filtered>; + // using FilteredMyCollisions = o2::soa::Filtered>; o2::framework::expressions::Filter prefilter_pcm = ifnode(pcmcuts.cfg_apply_cuts_from_prefilter_derived.node(), o2::aod::v0photonkf::pfbderived == static_cast(0), true); o2::framework::expressions::Filter prefilter_primaryelectron = ifnode(dileptoncuts.cfg_apply_cuts_from_prefilter_derived.node(), o2::aod::emprimaryelectron::pfbderived == static_cast(0), true); - void processAnalysis(o2::soa::Filtered> const& collisions, o2::soa::Join const& mccollisions, o2::aod::EMMCParticles const& mcparticles, Types const&... args) + void processAnalysis(o2::soa::Filtered> const& collisions, o2::soa::Join const& mccollisions, o2::aod::EMMCParticles const& mcparticles, Types const&... args) { if constexpr (pairtype == o2::aod::pwgem::photonmeson::photonpair::PairType::kPCMPCM) { auto&& [v0photons, v0legs] = std::forward_as_tuple(args...); @@ -939,8 +940,8 @@ struct Pi0EtaToGammaGammaMC { } PROCESS_SWITCH(Pi0EtaToGammaGammaMC, processAnalysis, "process pair analysis", true); - // using FilteredMyCollisionsWithJJMC = o2::soa::Filtered, aod::EMEventsWeight>>; - void processAnalysisJJMC(o2::soa::Filtered, o2::aod::EMEventsWeight>> const& collisions, o2::soa::Join const& mccollisions, o2::aod::EMMCParticles const& mcparticles, Types const&... args) + // using FilteredMyCollisionsWithJJMC = o2::soa::Filtered, aod::EMEventsWeight>>; + void processAnalysisJJMC(o2::soa::Filtered, o2::aod::EMEventsWeight>> const& collisions, o2::soa::Join const& mccollisions, o2::aod::EMMCParticles const& mcparticles, Types const&... args) { if constexpr (pairtype == o2::aod::pwgem::photonmeson::photonpair::PairType::kPCMPCM) { auto&& [v0photons, v0legs] = std::forward_as_tuple(args...); @@ -985,7 +986,7 @@ struct Pi0EtaToGammaGammaMC { } PROCESS_SWITCH(Pi0EtaToGammaGammaMC, processAnalysisJJMC, "process pair analysis", false); - void processDummy(o2::aod::EMEvents_004 const&) {} + void processDummy(o2::aod::PMEvents const&) {} PROCESS_SWITCH(Pi0EtaToGammaGammaMC, processDummy, "Dummy function", false); }; #endif // PWGEM_PHOTONMESON_CORE_PI0ETATOGAMMAGAMMAMC_H_ diff --git a/PWGEM/PhotonMeson/Core/TaggingPi0.h b/PWGEM/PhotonMeson/Core/TaggingPi0.h index 4dd43e290bf..71d7fb9f48b 100644 --- a/PWGEM/PhotonMeson/Core/TaggingPi0.h +++ b/PWGEM/PhotonMeson/Core/TaggingPi0.h @@ -23,6 +23,7 @@ #include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" // #include "PWGEM/PhotonMeson/Core/PHOSPhotonCut.h" #include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/EventHistograms.h" #include "PWGEM/PhotonMeson/Utils/PairUtilities.h" @@ -73,7 +74,7 @@ using namespace o2::aod::pwgem::photon; using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; using namespace o2::aod::pwgem::dilepton::utils; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; using MyCollisionsWithJJMC = soa::Join; @@ -442,11 +443,11 @@ struct TaggingPi0 { // } SliceCache cache; - Preslice perCollision_pcm = aod::v0photonkf::emphotoneventId; - Preslice perCollision_emc = aod::emccluster::emphotoneventId; - // Preslice perCollision_phos = aod::phoscluster::emphotoneventId; + Preslice perCollision_pcm = aod::v0photonkf::pmeventId; + Preslice perCollision_emc = aod::emccluster::pmeventId; + // Preslice perCollision_phos = aod::phoscluster::pmeventId; - Preslice perCollision_electron = aod::emprimaryelectronda::emphotoneventId; + Preslice perCollision_electron = aod::emprimaryelectronda::pmeventId; Partition positrons = o2::aod::emprimaryelectron::sign > int8_t(0) && static_cast(dileptoncuts.cfg_min_pt_track) < o2::aod::track::pt&& nabs(o2::aod::track::eta) < static_cast(dileptoncuts.cfg_max_eta_track) && static_cast(dileptoncuts.cfg_min_TPCNsigmaEl) < o2::aod::pidtpc::tpcNSigmaEl&& o2::aod::pidtpc::tpcNSigmaEl < static_cast(dileptoncuts.cfg_max_TPCNsigmaEl); Partition electrons = o2::aod::emprimaryelectron::sign < int8_t(0) && static_cast(dileptoncuts.cfg_min_pt_track) < o2::aod::track::pt && nabs(o2::aod::track::eta) < static_cast(dileptoncuts.cfg_max_eta_track) && static_cast(dileptoncuts.cfg_min_TPCNsigmaEl) < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < static_cast(dileptoncuts.cfg_max_TPCNsigmaEl); @@ -534,9 +535,9 @@ struct TaggingPi0 { std::pair key_df_collision = std::make_pair(ndf, collision.globalIndex()); if constexpr (pairtype == PairType::kPCMDalitzEE) { - auto photons1_per_collision = photons1.sliceBy(perCollision1, collision.globalIndex()); // PCM - auto positrons_per_collision = positrons->sliceByCached(o2::aod::emprimaryelectronda::emphotoneventId, collision.globalIndex(), cache); // positrons - auto electrons_per_collision = electrons->sliceByCached(o2::aod::emprimaryelectronda::emphotoneventId, collision.globalIndex(), cache); // electrons + auto photons1_per_collision = photons1.sliceBy(perCollision1, collision.globalIndex()); // PCM + auto positrons_per_collision = positrons->sliceByCached(o2::aod::emprimaryelectronda::pmeventId, collision.globalIndex(), cache); // positrons + auto electrons_per_collision = electrons->sliceByCached(o2::aod::emprimaryelectronda::pmeventId, collision.globalIndex(), cache); // electrons for (const auto& g1 : photons1_per_collision) { if (!cut1.template IsSelected(g1)) { diff --git a/PWGEM/PhotonMeson/Core/TaggingPi0MC.h b/PWGEM/PhotonMeson/Core/TaggingPi0MC.h index 38d7a8e70d3..9dda549dc79 100644 --- a/PWGEM/PhotonMeson/Core/TaggingPi0MC.h +++ b/PWGEM/PhotonMeson/Core/TaggingPi0MC.h @@ -23,6 +23,7 @@ #include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" // #include "PWGEM/PhotonMeson/Core/PHOSPhotonCut.h" #include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/EventHistograms.h" #include "PWGEM/PhotonMeson/Utils/MCUtilities.h" @@ -70,7 +71,7 @@ using namespace o2::aod::pwgem::photonmeson::photonpair; using namespace o2::aod::pwgem::photonmeson::utils::mcutil; using namespace o2::aod::pwgem::dilepton::utils::mcutil; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; using MyCollisionsWithJJMC = soa::Join; @@ -418,11 +419,11 @@ struct TaggingPi0MC { // } SliceCache cache; - Preslice perCollision_pcm = aod::v0photonkf::emphotoneventId; - Preslice perCollision_emc = aod::emccluster::emphotoneventId; - // Preslice perCollision_phos = aod::phoscluster::emphotoneventId; + Preslice perCollision_pcm = aod::v0photonkf::pmeventId; + Preslice perCollision_emc = aod::emccluster::pmeventId; + // Preslice perCollision_phos = aod::phoscluster::pmeventId; - Preslice perCollision_electron = aod::emprimaryelectronda::emphotoneventId; + Preslice perCollision_electron = aod::emprimaryelectronda::pmeventId; Partition positrons = o2::aod::emprimaryelectron::sign > int8_t(0) && static_cast(dileptoncuts.cfg_min_pt_track) < o2::aod::track::pt&& nabs(o2::aod::track::eta) < static_cast(dileptoncuts.cfg_max_eta_track) && static_cast(dileptoncuts.cfg_min_TPCNsigmaEl) < o2::aod::pidtpc::tpcNSigmaEl&& o2::aod::pidtpc::tpcNSigmaEl < static_cast(dileptoncuts.cfg_max_TPCNsigmaEl); Partition electrons = o2::aod::emprimaryelectron::sign < int8_t(0) && static_cast(dileptoncuts.cfg_min_pt_track) < o2::aod::track::pt && nabs(o2::aod::track::eta) < static_cast(dileptoncuts.cfg_max_eta_track) && static_cast(dileptoncuts.cfg_min_TPCNsigmaEl) < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < static_cast(dileptoncuts.cfg_max_TPCNsigmaEl); @@ -461,8 +462,8 @@ struct TaggingPi0MC { if constexpr (pairtype == PairType::kPCMDalitzEE) { auto photons1_per_collision = photons1.sliceBy(perCollision1, collision.globalIndex()); - auto positrons_per_collision = positrons->sliceByCached(o2::aod::emprimaryelectronda::emphotoneventId, collision.globalIndex(), cache); - auto electrons_per_collision = electrons->sliceByCached(o2::aod::emprimaryelectronda::emphotoneventId, collision.globalIndex(), cache); + auto positrons_per_collision = positrons->sliceByCached(o2::aod::emprimaryelectronda::pmeventId, collision.globalIndex(), cache); + auto electrons_per_collision = electrons->sliceByCached(o2::aod::emprimaryelectronda::pmeventId, collision.globalIndex(), cache); for (const auto& g1 : photons1_per_collision) { if (!cut1.template IsSelected(g1)) { diff --git a/PWGEM/PhotonMeson/Core/V0PhotonCut.h b/PWGEM/PhotonMeson/Core/V0PhotonCut.h index 1be295b3235..f73cbf6d16a 100644 --- a/PWGEM/PhotonMeson/Core/V0PhotonCut.h +++ b/PWGEM/PhotonMeson/Core/V0PhotonCut.h @@ -367,10 +367,10 @@ class V0PhotonCut : public TNamed const bool doQA = mDoQA && fRegistry != nullptr; uint nTotV0PerColl = 0; - currentCollID = v0s.iteratorAt(0).emphotoneventId(); + currentCollID = v0s.iteratorAt(0).pmeventId(); for (const auto& v0 : v0s) { - const auto collID = v0.emphotoneventId(); + const auto collID = v0.pmeventId(); if (!IsSelected(v0, fRegistry)) { flags.set(iV0); } @@ -604,7 +604,7 @@ class V0PhotonCut : public TNamed } if (doQA) { fillAfterPhotonHistogram(v0, pos, ele, fRegistry); - if (v0.emphotoneventId() != currentCollID) { + if (v0.pmeventId() != currentCollID) { fRegistry->fill(HIST("QA/V0Photon/after/hNgamma"), nAccV0PerColl); nAccV0PerColl = 0; } diff --git a/PWGEM/PhotonMeson/DataModel/EventTables.h b/PWGEM/PhotonMeson/DataModel/EventTables.h new file mode 100644 index 00000000000..d902e82562a --- /dev/null +++ b/PWGEM/PhotonMeson/DataModel/EventTables.h @@ -0,0 +1,78 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file EventTables.h +/// \brief This header provides the table definitions to store photon meson event tables +/// \author Marvin Hemmer (marvin.hemmer@cern.ch) - Goethe University Frankfurt + +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/DataModel/EventSelection.h" + +#include +#include + +#include + +#include +#include + +#ifndef PWGEM_PHOTONMESON_DATAMODEL_EVENTTABLES_H_ +#define PWGEM_PHOTONMESON_DATAMODEL_EVENTTABLES_H_ + +namespace o2::aod +{ + +namespace pmevsel +{ +// Event selection criteria. See O2Physics/Common/CCDB/EventSelectionParams.h +enum EventSelectionFlags { + kIsTriggerTVX = 0, // FT0 vertex (acceptable FT0C-FT0A time difference) at trigger level + kNoITSROFrameBorder, // bunch crossing is far from ITS RO Frame border + kNoTimeFrameBorder, // bunch crossing is far from Time Frame borders + kNoSameBunchPileup, // reject collisions in case of pileup with another collision in the same foundBC + kIsGoodZvtxFT0vsPV, // small difference between z-vertex from PV and from FT0 + kIsVertexITSTPC, // at least one ITS-TPC track (reject vertices built from ITS-only tracks) + kIsVertexTOFmatched, // at least one of vertex contributors is matched to TOF + kIsVertexTRDmatched, // at least one of vertex contributors is matched to TRD + kNoCollInTimeRangeNarrow, // no other collisions in specified time range (narrower than Strict) + kNoCollInTimeRangeStrict, // no other collisions in specified time range + kNoCollInTimeRangeStandard, // no other collisions in specified time range with per-collision multiplicity above threshold + kNoCollInRofStrict, // no other collisions in this Readout Frame + kNoCollInRofStandard, // no other collisions in this Readout Frame with per-collision multiplicity above threshold + kNoHighMultCollInPrevRof, // veto an event if FT0C amplitude in previous ITS ROF is above threshold + kIsGoodITSLayer3, // number of inactive chips on ITS layer 3 is below maximum allowed value + kIsGoodITSLayer0123, // numbers of inactive chips on ITS layers 0-3 are below maximum allowed values + kIsGoodITSLayersAll, // numbers of inactive chips on all ITS layers are below maximum allowed values + kNsel // counter +}; + +DECLARE_SOA_BITMAP_COLUMN(Selection, selection, 32); //! Bitmask of selection flags +DECLARE_SOA_DYNAMIC_COLUMN(Sel8, sel8, [](uint32_t selection_bit) -> bool { return (selection_bit & BIT(o2::aod::pmevsel::kIsTriggerTVX)) && (selection_bit & BIT(o2::aod::pmevsel::kNoTimeFrameBorder)) && (selection_bit & BIT(o2::aod::pmevsel::kNoITSROFrameBorder)); }); + +} // namespace pmevsel + +namespace pmevent +{ +DECLARE_SOA_COLUMN(CollisionId, collisionId, int); + +DECLARE_SOA_DYNAMIC_COLUMN(Sel8, sel8, [](uint64_t selection_bit) -> bool { return (selection_bit & BIT(o2::aod::evsel::kIsTriggerTVX)) && (selection_bit & BIT(o2::aod::evsel::kNoTimeFrameBorder)) && (selection_bit & BIT(o2::aod::evsel::kNoITSROFrameBorder)); }); +} // namespace pmevent + +DECLARE_SOA_TABLE(PMEvents, "AOD", "PMEVENT", //! Main event information table + o2::soa::Index<>, pmevent::CollisionId, bc::RunNumber, bc::GlobalBC, evsel::Selection, evsel::Rct, timestamp::Timestamp, + collision::PosZ, + collision::NumContrib, evsel::NumTracksInTimeRange, evsel::SumAmpFT0CInTimeRange, pmevent::Sel8); + +using PMEvent = PMEvents::iterator; + +} // namespace o2::aod + +#endif // PWGEM_PHOTONMESON_DATAMODEL_EVENTTABLES_H_ diff --git a/PWGEM/PhotonMeson/DataModel/gammaTables.h b/PWGEM/PhotonMeson/DataModel/gammaTables.h index be66a8d611a..ee3d89310fa 100644 --- a/PWGEM/PhotonMeson/DataModel/gammaTables.h +++ b/PWGEM/PhotonMeson/DataModel/gammaTables.h @@ -14,6 +14,7 @@ /// \author D. Sekihata, daiki.sekihata@cern.ch; Marvin Hemmer (marvin.hemmer@cern.ch) - Goethe University Frankfurt #include "PWGEM/Dilepton/DataModel/dileptonTables.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "Common/Core/RecoDecay.h" #include "Common/DataModel/CaloClusters.h" @@ -36,9 +37,6 @@ namespace o2::aod { -using EMPhotonEvents = EMEvents_004; -using EMPhotonEvent = EMPhotonEvents::iterator; - namespace emmcbinnedgen { DECLARE_SOA_COLUMN(GeneratedGamma, generatedGamma, std::vector); //! gamma binned generated data @@ -266,7 +264,7 @@ using EMEventWeight = EMEventsWeight::iterator; namespace v0photonkf { DECLARE_SOA_INDEX_COLUMN(EMEvent, emevent); //! -DECLARE_SOA_INDEX_COLUMN(EMPhotonEvent, emphotonevent); //! +DECLARE_SOA_INDEX_COLUMN(PMEvent, pmevent); //! DECLARE_SOA_COLUMN(CollisionId, collisionId, int); //! DECLARE_SOA_COLUMN(V0Id, v0Id, int); //! DECLARE_SOA_INDEX_COLUMN_FULL(PosTrack, posTrack, int, V0Legs, "_Pos"); //! @@ -345,8 +343,8 @@ using V0PhotonsKF = V0PhotonsKF_001; // iterators using V0PhotonKF = V0PhotonsKF::iterator; -DECLARE_SOA_TABLE(V0KFEMEventIds_000, "AOD", "V0KFEMEVENTID", v0photonkf::EMEventId); // To be joined with V0PhotonsKF table at analysis level. -DECLARE_SOA_TABLE_VERSIONED(V0KFEMEventIds_001, "AOD", "V0KFEMEVENTID", 1, v0photonkf::EMPhotonEventId); // To be joined with V0PhotonsKF table at analysis level. +DECLARE_SOA_TABLE(V0KFEMEventIds_000, "AOD", "V0KFEMEVENTID", v0photonkf::EMEventId); // To be joined with V0PhotonsKF table at analysis level. +DECLARE_SOA_TABLE_VERSIONED(V0KFEMEventIds_001, "AOD", "V0KFEMEVENTID", 1, v0photonkf::PMEventId); // To be joined with V0PhotonsKF table at analysis level. using V0KFEMEventIds = V0KFEMEventIds_001; using V0KFEMEventId = V0KFEMEventIds::iterator; @@ -423,18 +421,18 @@ using EMPrimaryElectronFromDalitz = EMPrimaryElectronsFromDalitz::iterator; namespace emprimaryelectronda { -DECLARE_SOA_INDEX_COLUMN(EMEvent, emevent); //! -DECLARE_SOA_INDEX_COLUMN(EMPhotonEvent, emphotonevent); //! +DECLARE_SOA_INDEX_COLUMN(EMEvent, emevent); //! +DECLARE_SOA_INDEX_COLUMN(PMEvent, pmevent); //! } // namespace emprimaryelectronda -DECLARE_SOA_TABLE_VERSIONED(EMPrimaryElectronDaEMEventIds_001, "AOD", "PRMELDAEVENTID", 1, emprimaryelectronda::EMPhotonEventId); // To be joined with EMPrimaryElectronsFromDalitz table at analysis level. +DECLARE_SOA_TABLE_VERSIONED(EMPrimaryElectronDaEMEventIds_001, "AOD", "PRMELDAEVENTID", 1, emprimaryelectronda::PMEventId); // To be joined with EMPrimaryElectronsFromDalitz table at analysis level. using EMPrimaryElectronDaEMEventIds = EMPrimaryElectronDaEMEventIds_001; using EMPrimaryElectronDaEMEventId = EMPrimaryElectronDaEMEventIds::iterator; namespace v0photonsphivpsi { DECLARE_SOA_INDEX_COLUMN(EMEvent, emevent); //! -DECLARE_SOA_INDEX_COLUMN(EMPhotonEvent, emphotonevent); //! +DECLARE_SOA_INDEX_COLUMN(PMEvent, pmevent); //! DECLARE_SOA_COLUMN(PhiV, phiv, float); //! DECLARE_SOA_COLUMN(PsiPair, psipair, float); } // namespace v0photonsphivpsi @@ -446,7 +444,7 @@ using V0PhotonsPhiVPsi = V0PhotonsPhiVPsi; namespace dalitzee { DECLARE_SOA_INDEX_COLUMN(EMEvent, emevent); //! -DECLARE_SOA_INDEX_COLUMN(EMPhotonEvent, emphotonevent); //! +DECLARE_SOA_INDEX_COLUMN(PMEvent, pmevent); //! DECLARE_SOA_INDEX_COLUMN_FULL(PosTrack, posTrack, int, EMPrimaryElectrons, "_Pos"); //! DECLARE_SOA_INDEX_COLUMN_FULL(NegTrack, negTrack, int, EMPrimaryElectrons, "_Neg"); //! DECLARE_SOA_COLUMN(CollisionId, collisionId, int); //! @@ -468,15 +466,15 @@ DECLARE_SOA_TABLE(DalitzEEs, "AOD", "DALITZEE", //! // iterators using DalitzEE = DalitzEEs::iterator; -DECLARE_SOA_TABLE(DalitzEEEMEventIds_000, "AOD", "EEEMEVENTID", dalitzee::EMEventId); // To be joined with DalitzEEs table at analysis level. -DECLARE_SOA_TABLE_VERSIONED(DalitzEEEMEventIds_001, "AOD", "EEEMEVENTID", 1, dalitzee::EMPhotonEventId); // To be joined with DalitzEEs table at analysis level. +DECLARE_SOA_TABLE(DalitzEEEMEventIds_000, "AOD", "EEEMEVENTID", dalitzee::EMEventId); // To be joined with DalitzEEs table at analysis level. +DECLARE_SOA_TABLE_VERSIONED(DalitzEEEMEventIds_001, "AOD", "EEEMEVENTID", 1, dalitzee::PMEventId); // To be joined with DalitzEEs table at analysis level. using DalitzEEEMEventIds = DalitzEEEMEventIds_001; using DalitzEEEMEventId = DalitzEEEMEventIds::iterator; namespace pwgem::photon::swtinfo { DECLARE_SOA_INDEX_COLUMN(EMEvent, emevent); //! -DECLARE_SOA_INDEX_COLUMN(EMPhotonEvent, emphotonevent); //! +DECLARE_SOA_INDEX_COLUMN(PMEvent, pmevent); //! DECLARE_SOA_COLUMN(CollisionId, collisionId, int); //! DECLARE_SOA_INDEX_COLUMN_FULL(TriggerV0PhotonHighPt, triggerV0PhotonHighPt, int, V0PhotonsKF, "_TriggerV0PhotonHighPt"); //! high pT PCM trigger is fired by this v0 photon DECLARE_SOA_INDEX_COLUMN_FULL(TriggerV0PhotonPair, triggerV0PhotonPair, int, V0PhotonsKF, "_TriggerV0PhotonPair"); //! PCM+EE trigger is fired by this v0 photon and dielectron @@ -576,7 +574,7 @@ DECLARE_SOA_TABLE(McGammasTrue, "AOD", "MCGATRUE", namespace skimmedcluster { DECLARE_SOA_INDEX_COLUMN(EMEvent, emevent); //! -DECLARE_SOA_INDEX_COLUMN(EMPhotonEvent, emphotonevent); //! +DECLARE_SOA_INDEX_COLUMN(PMEvent, pmevent); //! DECLARE_SOA_COLUMN(CollisionId, collisionId, int); //! DECLARE_SOA_COLUMN(ID, id, int); //! cluster ID identifying cluster in event DECLARE_SOA_COLUMN(E, e, float); //! cluster energy (GeV) @@ -593,7 +591,7 @@ DECLARE_SOA_COLUMN(NLM, nlm, int); //! numbe namespace emccluster { DECLARE_SOA_INDEX_COLUMN(EMEvent, emevent); //! -DECLARE_SOA_INDEX_COLUMN(EMPhotonEvent, emphotonevent); //! +DECLARE_SOA_INDEX_COLUMN(PMEvent, pmevent); //! DECLARE_SOA_COLUMN(CoreEnergy, coreEnergy, float); //! cluster core energy (GeV) DECLARE_SOA_COLUMN(Time, time, float); //! cluster time (ns) DECLARE_SOA_COLUMN(IsExotic, isExotic, bool); //! flag to mark cluster as exotic @@ -650,15 +648,15 @@ DECLARE_SOA_TABLE(EmEmcMTracks, "AOD", "EMEMCMTRACK", //! DECLARE_SOA_TABLE(EmEmcMSTracks, "AOD", "EMEMCMSTRACK", //! trackmatching::EmEmcClusterId, emctm::DeltaPhi, emctm::DeltaEta, emctm::TrackP, emctm::TrackPt); -DECLARE_SOA_TABLE(EMCEMEventIds_000, "AOD", "EMCEMEVENTID", emccluster::EMEventId); // To be joined with SkimEMCClusters table at analysis level. -DECLARE_SOA_TABLE_VERSIONED(EMCEMEventIds_001, "AOD", "EMCEMEVENTID", 1, emccluster::EMPhotonEventId); // To be joined with SkimEMCClusters table at analysis level. +DECLARE_SOA_TABLE(EMCEMEventIds_000, "AOD", "EMCEMEVENTID", emccluster::EMEventId); // To be joined with SkimEMCClusters table at analysis level. +DECLARE_SOA_TABLE_VERSIONED(EMCEMEventIds_001, "AOD", "EMCEMEVENTID", 1, emccluster::PMEventId); // To be joined with SkimEMCClusters table at analysis level. using EMCEMEventIds = EMCEMEventIds_001; using EMCEMEventId = EMCEMEventIds::iterator; namespace phoscluster { DECLARE_SOA_INDEX_COLUMN(EMEvent, emevent); //! -DECLARE_SOA_INDEX_COLUMN(EMPhotonEvent, emphotonevent); //! +DECLARE_SOA_INDEX_COLUMN(PMEvent, pmevent); //! DECLARE_SOA_INDEX_COLUMN_FULL(MatchedTrack, matchedTrack, int, Tracks, "_Matched"); //! matched track index DECLARE_SOA_COLUMN(X, x, float); //! cluster hit position in ALICE global coordinate DECLARE_SOA_COLUMN(Y, y, float); //! cluster hit position in ALICE global coordinate @@ -693,8 +691,8 @@ DECLARE_SOA_TABLE(PHOSClusters, "AOD", "PHOSCLUSTERS", //! phoscluster::Phi); using PHOSCluster = PHOSClusters::iterator; -DECLARE_SOA_TABLE(PHOSEMEventIds_000, "AOD", "PHOSEMEVENTID", phoscluster::EMEventId); // To be joined with PHOSClusters table at analysis level. -DECLARE_SOA_TABLE_VERSIONED(PHOSEMEventIds_001, "AOD", "PHOSEMEVENTID", 1, phoscluster::EMPhotonEventId); // To be joined with PHOSClusters table at analysis level. +DECLARE_SOA_TABLE(PHOSEMEventIds_000, "AOD", "PHOSEMEVENTID", phoscluster::EMEventId); // To be joined with PHOSClusters table at analysis level. +DECLARE_SOA_TABLE_VERSIONED(PHOSEMEventIds_001, "AOD", "PHOSEMEVENTID", 1, phoscluster::PMEventId); // To be joined with PHOSClusters table at analysis level. using PHOSEMEventIds = PHOSEMEventIds_001; using PHOSEMEventId = PHOSEMEventIds::iterator; diff --git a/PWGEM/PhotonMeson/TableProducer/CMakeLists.txt b/PWGEM/PhotonMeson/TableProducer/CMakeLists.txt index 20db3ba057e..5c265e57d96 100644 --- a/PWGEM/PhotonMeson/TableProducer/CMakeLists.txt +++ b/PWGEM/PhotonMeson/TableProducer/CMakeLists.txt @@ -70,3 +70,8 @@ o2physics_add_dpl_workflow(non-lin-producer SOURCES nonLinProducer.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(pm-qvector-dummy-otf + SOURCES pmQvectorDummyOtf.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore + COMPONENT_NAME Analysis) diff --git a/PWGEM/PhotonMeson/TableProducer/createEMEventPhoton.cxx b/PWGEM/PhotonMeson/TableProducer/createEMEventPhoton.cxx index 48720ac6863..d9365251277 100644 --- a/PWGEM/PhotonMeson/TableProducer/createEMEventPhoton.cxx +++ b/PWGEM/PhotonMeson/TableProducer/createEMEventPhoton.cxx @@ -13,6 +13,7 @@ /// \brief This code produces reduced events for photon analyses. /// \author Daiki Sekihata, daiki.sekihata@cern.ch +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" // #include "PWGJE/DataModel/Jet.h" @@ -66,7 +67,7 @@ using MyCollisionsMCCentQvec = soa::Join; struct CreateEMEventPhoton { // Produces embc; - Produces event; + Produces event; Produces eventalias; // Produces eventCov; Produces eventMult; @@ -387,32 +388,32 @@ struct AssociatePhotonToEMEvent { // This struct is for both data and MC. // Note that reconstructed collisions without mc collisions are already rejected in CreateEMEventPhoton in MC. - void processPCM(aod::EMEvents_004 const& collisions, aod::V0PhotonsKF const& photons) + void processPCM(aod::PMEvents const& collisions, aod::V0PhotonsKF const& photons) { fillEventId(collisions, photons, v0kfeventid, perCollisionPCM); } - void processElectronFromDalitz(aod::EMEvents_004 const& collisions, aod::EMPrimaryElectronsFromDalitz const& tracks) + void processElectronFromDalitz(aod::PMEvents const& collisions, aod::EMPrimaryElectronsFromDalitz const& tracks) { fillEventId(collisions, tracks, prmeleventid, perCollisionEl); } - void processPHOS(aod::EMEvents_004 const& collisions, aod::PHOSClusters const& photons) + void processPHOS(aod::PMEvents const& collisions, aod::PHOSClusters const& photons) { fillEventId(collisions, photons, phoseventid, perCollisionPHOS); } - void processEMC(aod::EMEvents_004 const& collisions, aod::SkimEMCClusters const& photons) + void processEMC(aod::PMEvents const& collisions, aod::SkimEMCClusters const& photons) { fillEventId(collisions, photons, emceventid, perCollisionEMC); } - // void processChargedTrack(aod::EMEvents_004 const& collisions, aod::EMPrimaryTracks const& tracks) + // void processChargedTrack(aod::PMEvents const& collisions, aod::EMPrimaryTracks const& tracks) // { // fillEventId(collisions, tracks, prmtrackeventid, perCollision_track); // } - void processDummy(aod::EMEvents_004 const&) {} + void processDummy(aod::PMEvents const&) {} PROCESS_SWITCH(AssociatePhotonToEMEvent, processPCM, "process pcm-event indexing", false); PROCESS_SWITCH(AssociatePhotonToEMEvent, processElectronFromDalitz, "process dalitzee-event indexing", false); diff --git a/PWGEM/PhotonMeson/TableProducer/nonLinProducer.cxx b/PWGEM/PhotonMeson/TableProducer/nonLinProducer.cxx index 74ac6e4ed5e..9feae005b6d 100644 --- a/PWGEM/PhotonMeson/TableProducer/nonLinProducer.cxx +++ b/PWGEM/PhotonMeson/TableProducer/nonLinProducer.cxx @@ -15,6 +15,7 @@ /// dependencies: skimmer-gamma-calo #include "PWGEM/PhotonMeson/Core/EMNonLin.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "PWGEM/PhotonMeson/DataModel/GammaTablesRedux.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/emcalHistoDefinitions.h" @@ -59,7 +60,7 @@ struct NonLinProducer { using EMCalPhotons = soa::Join; using PcmPhotons = soa::Join; - using Colls = soa::Join; + using Colls = soa::Join; EMNonLin emNonLinEMC; EMNonLin emNonLinPCM; @@ -117,8 +118,8 @@ struct NonLinProducer { for (const auto& cluster : clusters) { // check that we are at the correct collision - if (cluster.emphotoneventId() != collIndex) { - collIndex = cluster.emphotoneventId(); + if (cluster.pmeventId() != collIndex) { + collIndex = cluster.pmeventId(); collision.setCursor(collIndex); cent = getCentrality(collision); emNonLinContextEMC.setParams(emNonLinEMC.resolveParams(o2::pwgem::nonlin::EMNonLin::PhotonType::kEMC, cent)); @@ -152,8 +153,8 @@ struct NonLinProducer { for (const auto& v0 : v0s) { // check that we are at the correct collision - if (v0.emphotoneventId() != collIndex) { - collIndex = v0.emphotoneventId(); + if (v0.pmeventId() != collIndex) { + collIndex = v0.pmeventId(); collision.setCursor(collIndex); cent = getCentrality(collision); emNonLinContextPCM.setParams(emNonLinPCM.resolveParams(o2::pwgem::nonlin::EMNonLin::PhotonType::kPCM, cent)); diff --git a/PWGEM/PhotonMeson/TableProducer/pmQvectorDummyOtf.cxx b/PWGEM/PhotonMeson/TableProducer/pmQvectorDummyOtf.cxx new file mode 100644 index 00000000000..b67aeb53d41 --- /dev/null +++ b/PWGEM/PhotonMeson/TableProducer/pmQvectorDummyOtf.cxx @@ -0,0 +1,48 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +// + +/// \file pmQvectorDummyOtf.cxx +/// \author Marvin Hemmer +/// \brief This code produces on-the-fly dummy qvector table. + +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" + +#include +#include +#include + +using namespace o2; +using namespace o2::aod; +using namespace o2::soa; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct PmQvectorDummyOtf { + Produces eventQvecs; + + void init(InitContext&) {} + + void process(aod::PMEvents const& collisions) + { + for (int i = 0; i < collisions.size(); i++) { + eventQvecs( + 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, + 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f); + } // end of collision loop + } // end of process +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGEM/PhotonMeson/TableProducer/skimmerDalitzEE.cxx b/PWGEM/PhotonMeson/TableProducer/skimmerDalitzEE.cxx index 49486d54ca0..0d7afd0a63e 100644 --- a/PWGEM/PhotonMeson/TableProducer/skimmerDalitzEE.cxx +++ b/PWGEM/PhotonMeson/TableProducer/skimmerDalitzEE.cxx @@ -13,6 +13,7 @@ /// \author daiki.sekihata@cern.ch #include "PWGEM/Dilepton/Utils/PairUtilities.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include @@ -37,7 +38,7 @@ using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::constants::physics; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; using MyTracks = soa::Join; @@ -54,7 +55,7 @@ struct skimmerDalitzEE { }; SliceCache cache; - Preslice perCol = o2::aod::emprimaryelectronda::emphotoneventId; + Preslice perCol = o2::aod::emprimaryelectronda::pmeventId; SliceCache cache_cefp; PresliceUnsorted perCol_cefp = o2::aod::emprimaryelectron::collisionId; @@ -337,8 +338,8 @@ struct skimmerDalitzEE { continue; } - auto posTracks_per_coll = posTracks->sliceByCached(o2::aod::emprimaryelectronda::emphotoneventId, collision.globalIndex(), cache); - auto negTracks_per_coll = negTracks->sliceByCached(o2::aod::emprimaryelectronda::emphotoneventId, collision.globalIndex(), cache); + auto posTracks_per_coll = posTracks->sliceByCached(o2::aod::emprimaryelectronda::pmeventId, collision.globalIndex(), cache); + auto negTracks_per_coll = negTracks->sliceByCached(o2::aod::emprimaryelectronda::pmeventId, collision.globalIndex(), cache); fRegistry.fill(HIST("hNpos"), collision.centFT0C(), posTracks_per_coll.size()); fRegistry.fill(HIST("hNele"), collision.centFT0C(), negTracks_per_coll.size()); // LOGF(info, "collision.centFT0C() = %f, posTracks_per_coll.size() = %d, negTracks_per_coll.size() = %d", collision.centFT0C() , posTracks_per_coll.size(), negTracks_per_coll.size()); @@ -375,7 +376,7 @@ struct skimmerDalitzEE { } PROCESS_SWITCH(skimmerDalitzEE, processCEFP, "Process dalitz ee for CEFP", false); // for central event filter processing - void processOnlyNee(soa::Join const& collisions) + void processOnlyNee(soa::Join const& collisions) { for (auto& collision : collisions) { float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; diff --git a/PWGEM/PhotonMeson/Tasks/MaterialBudget.cxx b/PWGEM/PhotonMeson/Tasks/MaterialBudget.cxx index a023826777b..0ee3d8e2f3e 100644 --- a/PWGEM/PhotonMeson/Tasks/MaterialBudget.cxx +++ b/PWGEM/PhotonMeson/Tasks/MaterialBudget.cxx @@ -17,6 +17,7 @@ #include "PWGEM/PhotonMeson/Core/DalitzEECut.h" #include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" #include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "Common/CCDB/EventSelectionParams.h" @@ -70,10 +71,10 @@ using namespace o2::aod::pwgem::dilepton::utils::mcutil; using namespace o2::aod::pwgem::dilepton::utils; using o2::constants::math::TwoPI; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; -using MyCollisionsMC = soa::Join; +using MyCollisionsMC = soa::Join; using MyCollisionMC = MyCollisionsMC::iterator; using MyMCCollisions = soa::Join; @@ -831,8 +832,8 @@ struct MaterialBudget { } SliceCache cache; - Preslice perCollision = aod::v0photonkf::emphotoneventId; - Preslice perCollisionElectron = aod::emprimaryelectronda::emphotoneventId; + Preslice perCollision = aod::v0photonkf::pmeventId; + Preslice perCollisionElectron = aod::emprimaryelectronda::pmeventId; Partition positrons = o2::aod::emprimaryelectron::sign > int8_t(0) && dileptoncuts.cfgMinPtTrack < o2::aod::track::pt&& nabs(o2::aod::track::eta) < dileptoncuts.cfgMaxEtaTrack; Partition electrons = o2::aod::emprimaryelectron::sign < int8_t(0) && dileptoncuts.cfgMinPtTrack < o2::aod::track::pt && nabs(o2::aod::track::eta) < dileptoncuts.cfgMaxEtaTrack; diff --git a/PWGEM/PhotonMeson/Tasks/MaterialBudgetMC.cxx b/PWGEM/PhotonMeson/Tasks/MaterialBudgetMC.cxx index 7956146ae89..7e5d8d80fc6 100644 --- a/PWGEM/PhotonMeson/Tasks/MaterialBudgetMC.cxx +++ b/PWGEM/PhotonMeson/Tasks/MaterialBudgetMC.cxx @@ -18,6 +18,7 @@ #include "PWGEM/PhotonMeson/Core/HistogramsLibrary.h" #include "PWGEM/PhotonMeson/Core/PairCut.h" #include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/MCUtilities.h" #include "PWGEM/PhotonMeson/Utils/PairUtilities.h" @@ -57,7 +58,7 @@ using namespace o2::aod::pwgem::photonmeson::utils::mcutil; using namespace o2::aod::pwgem::dilepton::utils::mcutil; using namespace o2::aod::pwgem::photon; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; using MyV0Photons = soa::Join; @@ -227,7 +228,7 @@ struct MaterialBudgetMC { LOGF(info, "Number of Pair cuts = %d", fPairCuts.size()); } - Preslice perCollision_pcm = aod::v0photonkf::emphotoneventId; + Preslice perCollision_pcm = aod::v0photonkf::pmeventId; template bool IsSelectedPair(TG1 const& g1, TG2 const& g2, TCut1 const& tagcut, TCut2 const& probecut) diff --git a/PWGEM/PhotonMeson/Tasks/SinglePhoton.cxx b/PWGEM/PhotonMeson/Tasks/SinglePhoton.cxx index 1c536cf5751..62d2e47a234 100644 --- a/PWGEM/PhotonMeson/Tasks/SinglePhoton.cxx +++ b/PWGEM/PhotonMeson/Tasks/SinglePhoton.cxx @@ -21,6 +21,7 @@ #include "PWGEM/PhotonMeson/Core/HistogramsLibrary.h" #include "PWGEM/PhotonMeson/Core/PHOSPhotonCut.h" #include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "Common/CCDB/TriggerAliases.h" @@ -53,7 +54,7 @@ using namespace o2::framework::expressions; using namespace o2::soa; using namespace o2::aod::pwgem::photon; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; using MyV0Photons = soa::Join; @@ -241,7 +242,7 @@ struct SinglePhoton { LOGF(info, "Number of EMCal cuts = %d", fEMCCuts.size()); } - Preslice perCollision = aod::v0photonkf::emphotoneventId; + Preslice perCollision = aod::v0photonkf::pmeventId; // Preslice perCollision_phos = aod::skimmedcluster::collisionId; // Preslice perCollision_emc = aod::skimmedcluster::collisionId; diff --git a/PWGEM/PhotonMeson/Tasks/SinglePhotonMC.cxx b/PWGEM/PhotonMeson/Tasks/SinglePhotonMC.cxx index f583890fd53..e8e083dca28 100644 --- a/PWGEM/PhotonMeson/Tasks/SinglePhotonMC.cxx +++ b/PWGEM/PhotonMeson/Tasks/SinglePhotonMC.cxx @@ -21,6 +21,7 @@ #include "PWGEM/PhotonMeson/Core/HistogramsLibrary.h" #include "PWGEM/PhotonMeson/Core/PHOSPhotonCut.h" #include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/MCUtilities.h" @@ -52,7 +53,7 @@ using namespace o2::aod::pwgem::photonmeson::utils::mcutil; using namespace o2::aod::pwgem::dilepton::utils::mcutil; using namespace o2::aod::pwgem::photon; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; using MyV0Photons = soa::Join; @@ -242,7 +243,7 @@ struct SinglePhotonMC { // LOGF(info, "Number of EMCal cuts = %d", fEMCCuts.size()); // } - Preslice perCollision = aod::v0photonkf::emphotoneventId; + Preslice perCollision = aod::v0photonkf::pmeventId; // Preslice perCollision_phos = aod::skimmedcluster::collisionId; // Preslice perCollision_emc = aod::skimmedcluster::collisionId; diff --git a/PWGEM/PhotonMeson/Tasks/TagAndProbe.cxx b/PWGEM/PhotonMeson/Tasks/TagAndProbe.cxx index 91b46605947..ac3f50b594a 100644 --- a/PWGEM/PhotonMeson/Tasks/TagAndProbe.cxx +++ b/PWGEM/PhotonMeson/Tasks/TagAndProbe.cxx @@ -22,6 +22,7 @@ #include "PWGEM/PhotonMeson/Core/PHOSPhotonCut.h" #include "PWGEM/PhotonMeson/Core/PairCut.h" #include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/PairUtilities.h" @@ -65,7 +66,7 @@ using namespace o2::soa; using namespace o2::aod::pwgem::photonmeson::photonpair; using namespace o2::aod::pwgem::photon; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; using MyV0Photons = soa::Join; @@ -245,7 +246,7 @@ struct TagAndProbe { LOGF(info, "Number of Pair cuts = %d", fPairCuts.size()); } - Preslice perCollision = aod::v0photonkf::emphotoneventId; + Preslice perCollision = aod::v0photonkf::pmeventId; Preslice perCollision_phos = aod::skimmedcluster::collisionId; Preslice perCollision_emc = aod::skimmedcluster::collisionId; diff --git a/PWGEM/PhotonMeson/Tasks/calibTaskEmc.cxx b/PWGEM/PhotonMeson/Tasks/calibTaskEmc.cxx index 66d140bf308..1d9ca1dbfeb 100644 --- a/PWGEM/PhotonMeson/Tasks/calibTaskEmc.cxx +++ b/PWGEM/PhotonMeson/Tasks/calibTaskEmc.cxx @@ -17,6 +17,7 @@ #include "PWGEM/PhotonMeson/Core/EMCPhotonCut.h" #include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" #include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "PWGEM/PhotonMeson/DataModel/GammaTablesRedux.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/EventHistograms.h" @@ -228,12 +229,12 @@ struct CalibTaskEmc { Filter collisionFilter = (nabs(aod::collision::posZ) <= eventcuts.cfgZvtxMax) && (aod::evsel::ft0cOccupancyInTimeRange <= eventcuts.cfgFT0COccupancyMax) && (aod::evsel::ft0cOccupancyInTimeRange >= eventcuts.cfgFT0COccupancyMin); using EMCalPhotons = soa::Join; using PCMPhotons = soa::Join; - using FilteredCollsWithQvecs = soa::Filtered>; - using CollsWithQvecs = soa::Join; - using Colls = soa::Join; + using FilteredCollsWithQvecs = soa::Filtered>; + using CollsWithQvecs = soa::Join; + using Colls = soa::Join; - PresliceOptional perCollisionEMC = o2::aod::emccluster::emphotoneventId; - PresliceOptional perCollisionPCM = aod::v0photonkf::emphotoneventId; + PresliceOptional perCollisionEMC = o2::aod::emccluster::pmeventId; + PresliceOptional perCollisionPCM = aod::v0photonkf::pmeventId; PresliceOptional perEMCClusterMT = o2::aod::mintm::minClusterId; PresliceOptional perEMCClusterMS = o2::aod::mintm::minClusterId; diff --git a/PWGEM/PhotonMeson/Tasks/compconvbuilder.cxx b/PWGEM/PhotonMeson/Tasks/compconvbuilder.cxx index be0e088e60d..22f05b2bec4 100644 --- a/PWGEM/PhotonMeson/Tasks/compconvbuilder.cxx +++ b/PWGEM/PhotonMeson/Tasks/compconvbuilder.cxx @@ -15,6 +15,7 @@ #include "PWGEM/Dilepton/Utils/MCUtilities.h" #include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGLF/DataModel/LFStrangenessMLTables.h" #include "PWGLF/DataModel/LFStrangenessPIDTables.h" @@ -57,7 +58,7 @@ using MyV0Photons = soa::Join; using MyMCV0Legs = soa::Join; using MyMCV0Leg = MyMCV0Legs::iterator; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; using MyMCCollisions = soa::Join; @@ -128,7 +129,7 @@ struct Compconvbuilder { } // Link V0-photons to their collision - Preslice perV0PhotonCollision = aod::v0photonkf::emphotoneventId; + Preslice perV0PhotonCollision = aod::v0photonkf::pmeventId; void init(InitContext const& /*ctx*/) { @@ -656,7 +657,7 @@ struct Compconvbuilder { } } - Preslice perCollision = aod::v0photonkf::emphotoneventId; + Preslice perCollision = aod::v0photonkf::pmeventId; void processEMV0sMC(MyV0Photons const& v0s, aod::EMMCParticles const& mcparticles, MyMCV0Legs const&, MyCollisions const& collisions) { diff --git a/PWGEM/PhotonMeson/Tasks/dalitzEEQC.cxx b/PWGEM/PhotonMeson/Tasks/dalitzEEQC.cxx index 4717c1d307b..e42b30e99cc 100644 --- a/PWGEM/PhotonMeson/Tasks/dalitzEEQC.cxx +++ b/PWGEM/PhotonMeson/Tasks/dalitzEEQC.cxx @@ -17,6 +17,7 @@ #include "PWGEM/Dilepton/Utils/PairUtilities.h" #include "PWGEM/PhotonMeson/Core/DalitzEECut.h" #include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/EventHistograms.h" @@ -43,7 +44,7 @@ using namespace o2::framework::expressions; using namespace o2::soa; using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; using MyTracks = soa::Join; @@ -332,7 +333,7 @@ struct DalitzEEQC { using FilteredMyCollisions = soa::Filtered; SliceCache cache; - Preslice perCollision_track = aod::emprimaryelectronda::emphotoneventId; + Preslice perCollision_track = aod::emprimaryelectronda::pmeventId; Filter trackFilter = dileptoncuts.cfg_min_pt_track < o2::aod::track::pt && nabs(o2::aod::track::eta) < dileptoncuts.cfg_max_eta_track && o2::aod::track::tpcChi2NCl < dileptoncuts.cfg_max_chi2tpc && o2::aod::track::itsChi2NCl < dileptoncuts.cfg_max_chi2its && nabs(o2::aod::track::dcaXY) < dileptoncuts.cfg_max_dcaxy && nabs(o2::aod::track::dcaZ) < dileptoncuts.cfg_max_dcaz; Filter pidFilter = dileptoncuts.cfg_min_TPCNsigmaEl < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < dileptoncuts.cfg_max_TPCNsigmaEl && (o2::aod::pidtpc::tpcNSigmaPi < dileptoncuts.cfg_min_TPCNsigmaPi || dileptoncuts.cfg_max_TPCNsigmaPi < o2::aod::pidtpc::tpcNSigmaPi); using FilteredMyTracks = soa::Filtered; @@ -360,8 +361,8 @@ struct DalitzEEQC { fRegistry.fill(HIST("Event/before/hCollisionCounter"), 12.0); // accepted fRegistry.fill(HIST("Event/after/hCollisionCounter"), 12.0); // accepted - auto posTracks_per_coll = posTracks->sliceByCached(o2::aod::emprimaryelectronda::emphotoneventId, collision.globalIndex(), cache); - auto negTracks_per_coll = negTracks->sliceByCached(o2::aod::emprimaryelectronda::emphotoneventId, collision.globalIndex(), cache); + auto posTracks_per_coll = posTracks->sliceByCached(o2::aod::emprimaryelectronda::pmeventId, collision.globalIndex(), cache); + auto negTracks_per_coll = negTracks->sliceByCached(o2::aod::emprimaryelectronda::pmeventId, collision.globalIndex(), cache); // LOGF(info, "centrality = %f , posTracks_per_coll.size() = %d, negTracks_per_coll.size() = %d", centralities[cfgCentEstimator], posTracks_per_coll.size(), negTracks_per_coll.size()); for (auto& [pos, ele] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS diff --git a/PWGEM/PhotonMeson/Tasks/dalitzEEQCMC.cxx b/PWGEM/PhotonMeson/Tasks/dalitzEEQCMC.cxx index f5e202985be..7a32eddf6ab 100644 --- a/PWGEM/PhotonMeson/Tasks/dalitzEEQCMC.cxx +++ b/PWGEM/PhotonMeson/Tasks/dalitzEEQCMC.cxx @@ -18,6 +18,7 @@ #include "PWGEM/Dilepton/Utils/PairUtilities.h" #include "PWGEM/PhotonMeson/Core/DalitzEECut.h" #include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/EventHistograms.h" #include "PWGEM/PhotonMeson/Utils/MCUtilities.h" @@ -46,7 +47,7 @@ using namespace o2::soa; using namespace o2::aod::pwgem::photonmeson::utils::mcutil; using namespace o2::aod::pwgem::dilepton::utils::mcutil; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; using MyMCTracks = soa::Join; @@ -487,7 +488,7 @@ struct DalitzEEQCMC { std::vector used_trackIds; SliceCache cache; - Preslice perCollision_track = aod::emprimaryelectronda::emphotoneventId; + Preslice perCollision_track = aod::emprimaryelectronda::pmeventId; Filter trackFilter = dileptoncuts.cfg_min_pt_track < o2::aod::track::pt && nabs(o2::aod::track::eta) < dileptoncuts.cfg_max_eta_track && o2::aod::track::tpcChi2NCl < dileptoncuts.cfg_max_chi2tpc && o2::aod::track::itsChi2NCl < dileptoncuts.cfg_max_chi2its && nabs(o2::aod::track::dcaXY) < dileptoncuts.cfg_max_dcaxy && nabs(o2::aod::track::dcaZ) < dileptoncuts.cfg_max_dcaz; Filter pidFilter = dileptoncuts.cfg_min_TPCNsigmaEl < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < dileptoncuts.cfg_max_TPCNsigmaEl && (o2::aod::pidtpc::tpcNSigmaPi < dileptoncuts.cfg_min_TPCNsigmaPi || dileptoncuts.cfg_max_TPCNsigmaPi < o2::aod::pidtpc::tpcNSigmaPi); using FilteredMyMCTracks = soa::Filtered; @@ -520,8 +521,8 @@ struct DalitzEEQCMC { fRegistry.fill(HIST("Event/before/hCollisionCounter"), 12.0); // accepted fRegistry.fill(HIST("Event/after/hCollisionCounter"), 12.0); // accepted - auto posTracks_per_coll = posTracks->sliceByCached(o2::aod::emprimaryelectronda::emphotoneventId, collision.globalIndex(), cache); - auto negTracks_per_coll = negTracks->sliceByCached(o2::aod::emprimaryelectronda::emphotoneventId, collision.globalIndex(), cache); + auto posTracks_per_coll = posTracks->sliceByCached(o2::aod::emprimaryelectronda::pmeventId, collision.globalIndex(), cache); + auto negTracks_per_coll = negTracks->sliceByCached(o2::aod::emprimaryelectronda::pmeventId, collision.globalIndex(), cache); // LOGF(info, "centrality = %f , posTracks_per_coll.size() = %d, negTracks_per_coll.size() = %d", centralities[cfgCentEstimator], posTracks_per_coll.size(), negTracks_per_coll.size()); for (auto& [pos, ele] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS diff --git a/PWGEM/PhotonMeson/Tasks/emcalQC.cxx b/PWGEM/PhotonMeson/Tasks/emcalQC.cxx index 651828b8194..39af167b327 100644 --- a/PWGEM/PhotonMeson/Tasks/emcalQC.cxx +++ b/PWGEM/PhotonMeson/Tasks/emcalQC.cxx @@ -16,6 +16,7 @@ #include "PWGEM/PhotonMeson/Core/EMCPhotonCut.h" #include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "PWGEM/PhotonMeson/DataModel/GammaTablesRedux.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/ClusterHistograms.h" @@ -47,7 +48,7 @@ using namespace o2::framework::expressions; using namespace o2::soa; using namespace o2::aod::pwgem::photon; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; using EMCalPhotons = soa::Join; @@ -137,7 +138,7 @@ struct EmcalQC { PresliceOptional perEMCClusterMT = o2::aod::mintm::minClusterId; PresliceOptional perEMCClusterMS = o2::aod::mintm::minClusterId; - PresliceOptional perCollisionEMC = o2::aod::emccluster::emphotoneventId; + PresliceOptional perCollisionEMC = o2::aod::emccluster::pmeventId; void init(InitContext&) { diff --git a/PWGEM/PhotonMeson/Tasks/gammaConversions.cxx b/PWGEM/PhotonMeson/Tasks/gammaConversions.cxx index 8a559d3c669..7c436bf018c 100644 --- a/PWGEM/PhotonMeson/Tasks/gammaConversions.cxx +++ b/PWGEM/PhotonMeson/Tasks/gammaConversions.cxx @@ -16,6 +16,7 @@ #include "PWGEM/PhotonMeson/Tasks/gammaConversions.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/gammaConvDefinitions.h" @@ -619,8 +620,8 @@ struct GammaConversions { } } - Preslice perCollision = aod::v0photonkf::emphotoneventId; - void processRec(aod::EMEvents_004::iterator const& theCollision, + Preslice perCollision = aod::v0photonkf::pmeventId; + void processRec(aod::PMEvents::iterator const& theCollision, V0DatasAdditional const& theV0s, aod::V0Legs const&) { @@ -645,7 +646,7 @@ struct GammaConversions { Preslice gperV0 = aod::gammamctrue::v0photonkfId; - void processMc(aod::EMEvents_004::iterator const& theCollision, + void processMc(aod::PMEvents::iterator const& theCollision, V0DatasAdditional const& theV0s, V0LegsWithMC const&, aod::V0DaughterMcParticles const&, diff --git a/PWGEM/PhotonMeson/Tasks/pcmQC.cxx b/PWGEM/PhotonMeson/Tasks/pcmQC.cxx index d8a006afd3f..7435451a3a6 100644 --- a/PWGEM/PhotonMeson/Tasks/pcmQC.cxx +++ b/PWGEM/PhotonMeson/Tasks/pcmQC.cxx @@ -15,6 +15,7 @@ #include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" #include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "Common/CCDB/EventSelectionParams.h" @@ -48,7 +49,7 @@ using namespace o2::framework::expressions; using namespace o2::soa; using namespace o2::aod::pwgem::photon; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; using MyV0Photons = soa::Join; @@ -476,8 +477,8 @@ struct PCMQC { // fRegistry.fill(HIST("V0Leg/hZY"), leg.z(), leg.y()); } - Preslice perCollisionV0 = aod::v0photonkf::emphotoneventId; - Preslice perCollisionV0ML = aod::v0photonkf::emphotoneventId; + Preslice perCollisionV0 = aod::v0photonkf::pmeventId; + Preslice perCollisionV0ML = aod::v0photonkf::pmeventId; Filter collisionFilter_centrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); Filter collisionFilter_occupancy_track = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; Filter collisionFilter_occupancy_ft0c = eventcuts.cfgFT0COccupancyMin <= o2::aod::evsel::ft0cOccupancyInTimeRange && o2::aod::evsel::ft0cOccupancyInTimeRange < eventcuts.cfgFT0COccupancyMax; diff --git a/PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx b/PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx index 5516dfdac41..f35b926e50c 100644 --- a/PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx +++ b/PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx @@ -16,6 +16,7 @@ #include "PWGEM/Dilepton/Utils/MCUtilities.h" #include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" #include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/MCUtilities.h" @@ -54,7 +55,7 @@ using namespace o2::aod::pwgem::photonmeson::utils::mcutil; using namespace o2::aod::pwgem::dilepton::utils::mcutil; using namespace o2::aod::pwgem::photon; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; using MyMCCollisions = soa::Join; @@ -568,8 +569,8 @@ struct PCMQCMC { fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hRxyGen_DeltaEta"), std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2)), leg.eta() - mcleg.eta()); fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hRxyGen_DeltaPhi"), std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2)), leg.phi() - mcleg.phi()); } - Preslice perCollisionV0 = aod::v0photonkf::emphotoneventId; - Preslice perCollisionV0ML = aod::v0photonkf::emphotoneventId; + Preslice perCollisionV0 = aod::v0photonkf::pmeventId; + Preslice perCollisionV0ML = aod::v0photonkf::pmeventId; Filter collisionFilter_centrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); Filter collisionFilter_occupancy_track = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; Filter collisionFilter_occupancy_ft0c = eventcuts.cfgFT0COccupancyMin <= o2::aod::evsel::ft0cOccupancyInTimeRange && o2::aod::evsel::ft0cOccupancyInTimeRange < eventcuts.cfgFT0COccupancyMax; diff --git a/PWGEM/PhotonMeson/Tasks/phosQC.cxx b/PWGEM/PhotonMeson/Tasks/phosQC.cxx index 8504be6ae8a..f98c5fcfba2 100644 --- a/PWGEM/PhotonMeson/Tasks/phosQC.cxx +++ b/PWGEM/PhotonMeson/Tasks/phosQC.cxx @@ -17,6 +17,7 @@ #include "PWGEM/PhotonMeson/Core/CutsLibrary.h" #include "PWGEM/PhotonMeson/Core/HistogramsLibrary.h" #include "PWGEM/PhotonMeson/Core/PHOSPhotonCut.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "Common/CCDB/TriggerAliases.h" @@ -44,7 +45,7 @@ using namespace o2::framework::expressions; using namespace o2::soa; using namespace o2::aod::pwgem::photon; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; struct phosQC { diff --git a/PWGEM/PhotonMeson/Tasks/photonResoTask.cxx b/PWGEM/PhotonMeson/Tasks/photonResoTask.cxx index fe6ec07c476..6de4f8bb17e 100644 --- a/PWGEM/PhotonMeson/Tasks/photonResoTask.cxx +++ b/PWGEM/PhotonMeson/Tasks/photonResoTask.cxx @@ -18,6 +18,7 @@ #include "PWGEM/PhotonMeson/Core/EMCPhotonCut.h" #include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" #include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "PWGEM/PhotonMeson/DataModel/GammaTablesRedux.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/EventHistograms.h" @@ -202,13 +203,13 @@ struct PhotonResoTask { using PcmMcLegs = soa::Join; - using Colls = soa::Join; + using Colls = soa::Join; using McColls = o2::soa::Join; using McParticles = EMMCParticles; - PresliceOptional perCollisionEMC = o2::aod::emccluster::emphotoneventId; - PresliceOptional perCollisionPCM = aod::v0photonkf::emphotoneventId; + PresliceOptional perCollisionEMC = o2::aod::emccluster::pmeventId; + PresliceOptional perCollisionPCM = aod::v0photonkf::pmeventId; PresliceOptional perEMCClusterMT = o2::aod::mintm::minClusterId; PresliceOptional perEMCClusterMS = o2::aod::mintm::minClusterId; diff --git a/PWGEM/PhotonMeson/Tasks/prefilterPhoton.cxx b/PWGEM/PhotonMeson/Tasks/prefilterPhoton.cxx index b7141518624..996ce6abdda 100644 --- a/PWGEM/PhotonMeson/Tasks/prefilterPhoton.cxx +++ b/PWGEM/PhotonMeson/Tasks/prefilterPhoton.cxx @@ -17,6 +17,7 @@ #include "PWGEM/PhotonMeson/Core/DalitzEECut.h" #include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" #include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/PairUtilities.h" @@ -59,7 +60,7 @@ using namespace o2::framework::expressions; using namespace o2::soa; using namespace o2::aod::pwgem::photonmeson::photonpair; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; using MyV0Photons = soa::Join; @@ -389,8 +390,8 @@ struct prefilterPhoton { } auto photons1_per_collision = photons1.sliceBy(perCollision1, collision.globalIndex()); - auto positrons_per_collision = posTracks->sliceByCached(o2::aod::emprimaryelectronda::emphotoneventId, collision.globalIndex(), cache); - auto electrons_per_collision = negTracks->sliceByCached(o2::aod::emprimaryelectronda::emphotoneventId, collision.globalIndex(), cache); + auto positrons_per_collision = posTracks->sliceByCached(o2::aod::emprimaryelectronda::pmeventId, collision.globalIndex(), cache); + auto electrons_per_collision = negTracks->sliceByCached(o2::aod::emprimaryelectronda::pmeventId, collision.globalIndex(), cache); if (!fEMEventCut.IsSelected(collision) || !is_cent_ok) { for (const auto& photon1 : photons1_per_collision) { @@ -537,8 +538,8 @@ struct prefilterPhoton { } auto photons1_per_collision = photons1.sliceBy(perCollision1, collision.globalIndex()); - auto positrons_per_collision = posTracks->sliceByCached(o2::aod::emprimaryelectronda::emphotoneventId, collision.globalIndex(), cache); - auto electrons_per_collision = negTracks->sliceByCached(o2::aod::emprimaryelectronda::emphotoneventId, collision.globalIndex(), cache); + auto positrons_per_collision = posTracks->sliceByCached(o2::aod::emprimaryelectronda::pmeventId, collision.globalIndex(), cache); + auto electrons_per_collision = negTracks->sliceByCached(o2::aod::emprimaryelectronda::pmeventId, collision.globalIndex(), cache); for (const auto& [g1, g2] : combinations(CombinationsStrictlyUpperIndexPolicy(photons1_per_collision, photons1_per_collision))) { if (!cut1.template IsSelected(g1) || !cut1.template IsSelected(g2)) { @@ -600,8 +601,8 @@ struct prefilterPhoton { std::unordered_map map_pfb_ele; // map ele.globalIndex -> prefilter bit SliceCache cache; - Preslice perCollision_v0 = aod::v0photonkf::emphotoneventId; - Preslice perCollision_electron = aod::emprimaryelectronda::emphotoneventId; + Preslice perCollision_v0 = aod::v0photonkf::pmeventId; + Preslice perCollision_electron = aod::emprimaryelectronda::pmeventId; Filter collisionFilter_centrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); Filter collisionFilter_occupancy_track = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; diff --git a/PWGEM/PhotonMeson/Tasks/taskFlowReso.cxx b/PWGEM/PhotonMeson/Tasks/taskFlowReso.cxx index 936e5ea335b..f7c5484084c 100644 --- a/PWGEM/PhotonMeson/Tasks/taskFlowReso.cxx +++ b/PWGEM/PhotonMeson/Tasks/taskFlowReso.cxx @@ -14,6 +14,7 @@ /// \author M. Hemmer, marvin.hemmer@cern.ch #include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/EventHistograms.h" @@ -118,7 +119,7 @@ struct TaskFlowReso { SliceCache cache; EventPlaneHelper epHelper; - using CollsWithQvecs = soa::Join; + using CollsWithQvecs = soa::Join; using CollWithQvec = CollsWithQvecs::iterator; static constexpr std::size_t NQVecEntries = 6; diff --git a/PWGEM/PhotonMeson/Tasks/taskPi0FlowEMC.cxx b/PWGEM/PhotonMeson/Tasks/taskPi0FlowEMC.cxx index 69c0dae38a8..ca6e5a02503 100644 --- a/PWGEM/PhotonMeson/Tasks/taskPi0FlowEMC.cxx +++ b/PWGEM/PhotonMeson/Tasks/taskPi0FlowEMC.cxx @@ -17,6 +17,7 @@ #include "PWGEM/PhotonMeson/Core/EMCPhotonCut.h" #include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" #include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "PWGEM/PhotonMeson/DataModel/GammaTablesRedux.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/EventHistograms.h" @@ -257,14 +258,14 @@ struct TaskPi0FlowEMC { // using FilteredEMCalPhotons = soa::Filtered>; using EMCalPhotons = soa::Join; using PCMPhotons = soa::Join; - using FilteredCollsWithQvecs = soa::Filtered>; - using CollsWithQvecs = soa::Join; - using Colls = soa::Join; + using FilteredCollsWithQvecs = soa::Filtered>; + using CollsWithQvecs = soa::Join; + using Colls = soa::Join; static constexpr std::size_t NQVecEntries = 6; - PresliceOptional perCollisionEMC = o2::aod::emccluster::emphotoneventId; - PresliceOptional perCollisionPCM = aod::v0photonkf::emphotoneventId; + PresliceOptional perCollisionEMC = o2::aod::emccluster::pmeventId; + PresliceOptional perCollisionPCM = aod::v0photonkf::pmeventId; PresliceOptional perEMCClusterMT = o2::aod::mintm::minClusterId; PresliceOptional perEMCClusterMS = o2::aod::mintm::minClusterId; From fd104bc852bd0a80533c9f69b45d688d0ee85c15 Mon Sep 17 00:00:00 2001 From: "M. Monalisa Melo Paulino" <71565863+monamelop@users.noreply.github.com> Date: Wed, 4 Mar 2026 20:36:59 -0300 Subject: [PATCH 172/347] [PWGJE] Add new jet substructure observable (#15244) --- PWGJE/Tasks/jetDsSpectrumAndSubstructure.cxx | 203 ++++++++++++++----- 1 file changed, 151 insertions(+), 52 deletions(-) diff --git a/PWGJE/Tasks/jetDsSpectrumAndSubstructure.cxx b/PWGJE/Tasks/jetDsSpectrumAndSubstructure.cxx index a7810742abe..3e2e12d378a 100644 --- a/PWGJE/Tasks/jetDsSpectrumAndSubstructure.cxx +++ b/PWGJE/Tasks/jetDsSpectrumAndSubstructure.cxx @@ -30,7 +30,6 @@ #include "Framework/ASoA.h" #include "Framework/AnalysisDataModel.h" #include "Framework/HistogramRegistry.h" -#include #include #include #include @@ -42,7 +41,6 @@ #include "TVector3.h" #include -#include #include #include @@ -67,6 +65,12 @@ DECLARE_SOA_COLUMN(HfY, hfY, float); DECLARE_SOA_COLUMN(HfMlScore0, hfMlScore0, float); DECLARE_SOA_COLUMN(HfMlScore1, hfMlScore1, float); DECLARE_SOA_COLUMN(HfMlScore2, hfMlScore2, float); + +// extra +DECLARE_SOA_COLUMN(JetMass, jetMass, float); +DECLARE_SOA_COLUMN(JetGirth, jetGirth, float); +DECLARE_SOA_COLUMN(JetThrust, jetThrust, float); // lambda_2^1 +DECLARE_SOA_COLUMN(JetLambda11, jetLambda11, float); // lambda_1^1 } // namespace jet_distance DECLARE_SOA_TABLE(JetDistanceTable, "AOD", "JETDISTTABLE", @@ -82,46 +86,117 @@ DECLARE_SOA_TABLE(JetDistanceTable, "AOD", "JETDISTTABLE", jet_distance::HfY, jet_distance::HfMlScore0, jet_distance::HfMlScore1, - jet_distance::HfMlScore2); + jet_distance::HfMlScore2, + jet_distance::JetMass, + jet_distance::JetGirth, + jet_distance::JetThrust, + jet_distance::JetLambda11); } // namespace o2::aod struct JetDsSpecSubs { - HistogramRegistry registry{"registry", - {{"h_collisions", "event status;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}}, - {"h_track_pt", "track pT;#it{p}_{T,track} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0., 200.}}}}, - {"h_track_eta", "track #eta;#eta_{track};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}}, - {"h_track_phi", "track #varphi;#varphi_{track};entries", {HistType::kTH1F, {{80, -1.0, 7.}}}}, - {"h_jet_pt", "jet pT;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0., 200.}}}}, - {"h_jet_eta", "jet #eta;#eta_{jet};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}}, - {"h_jet_phi", "jet #phi;#phi_{jet};entries", {HistType::kTH1F, {{80, -1.0, 7.}}}}, - {"h_collision_counter", "# of collisions;", {HistType::kTH1F, {{200, 0., 200.}}}}, - {"h_jet_counter", ";# of D_{S} jets;", {HistType::kTH1F, {{6, 0., 3.0}}}}, - {"h_ds_jet_projection", ";z^{D_{S},jet}_{||};dN/dz^{D_{S},jet}_{||}", {HistType::kTH1F, {{1000, 0., 2.}}}}, - {"h_ds_jet_distance_vs_projection", ";#DeltaR_{D_{S},jet};z^{D_{S},jet}_{||}", {HistType::kTH2F, {{1000, 0., 1.}, {1000, 0., 2.}}}}, - {"h_ds_jet_distance", ";#DeltaR_{D_{S},jet};dN/d(#DeltaR)", {HistType::kTH1F, {{1000, 0., 1.}}}}, - {"h_ds_jet_pt", ";p_{T,D_{S} jet};dN/dp_{T,D_{S} jet}", {HistType::kTH1F, {{1000, 0., 100.}}}}, - {"h_ds_jet_eta", ";#eta_{T,D_{S} jet};dN/d#eta_{D_{S} jet}", {HistType::kTH1F, {{250, -1., 1.}}}}, - {"h_ds_jet_phi", ";#phi_{T,D_{S} jet};dN/d#phi_{D_{S} jet}", {HistType::kTH1F, {{250, -1., 7.}}}}, - {"h_ds_mass", ";m_{D_{S}} (GeV/c^{2});dN/dm_{D_{S}}", {HistType::kTH1F, {{1000, 0., 6.}}}}, - {"h_ds_eta", ";#eta_{D_{S}} (GeV/c^{2});dN/d#eta_{D_{S}}", {HistType::kTH1F, {{250, -1., 1.}}}}, - {"h_ds_phi", ";#phi_{D_{S}} (GeV/c^{2});dN/d#phi_{D_{S}}", {HistType::kTH1F, {{250, -1., 7.}}}}}}; - Configurable vertexZCut{"vertexZCut", 10.0f, "Accepted z-vertex range"}; + HistogramRegistry registry{ + "registry", + { + {"h_collisions", "event status;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}}, + {"h_track_pt", "track pT;#it{p}_{T,track} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0., 200.}}}}, + {"h_track_eta", "track #eta;#eta_{track};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}}, + {"h_track_phi", "track #varphi;#varphi_{track};entries", {HistType::kTH1F, {{80, -1.0, 7.}}}}, + {"h_jet_pt", "jet pT;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0., 200.}}}}, + {"h_jet_eta", "jet #eta;#eta_{jet};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}}, + {"h_jet_phi", "jet #phi;#phi_{jet};entries", {HistType::kTH1F, {{80, -1.0, 7.}}}}, + {"h_collision_counter", "# of collisions;", {HistType::kTH1F, {{200, 0., 200.}}}}, + {"h_jet_counter", ";# of D_{S} jets;", {HistType::kTH1F, {{6, 0., 3.0}}}}, + {"h_ds_jet_projection", ";z^{D_{S},jet}_{||};dN/dz^{D_{S},jet}_{||}", {HistType::kTH1F, {{1000, 0., 2.}}}}, + {"h_ds_jet_distance_vs_projection", ";#DeltaR_{D_{S},jet};z^{D_{S},jet}_{||}", {HistType::kTH2F, {{1000, 0., 1.}, {1000, 0., 2.}}}}, + {"h_ds_jet_distance", ";#DeltaR_{D_{S},jet};dN/d(#DeltaR)", {HistType::kTH1F, {{1000, 0., 1.}}}}, + {"h_ds_jet_pt", ";p_{T,D_{S} jet};dN/dp_{T,D_{S} jet}", {HistType::kTH1F, {{1000, 0., 100.}}}}, + {"h_ds_jet_eta", ";#eta_{D_{S} jet};entries", {HistType::kTH1F, {{250, -1., 1.}}}}, + {"h_ds_jet_phi", ";#phi_{D_{S} jet};entries", {HistType::kTH1F, {{250, -1., 7.}}}}, + {"h_ds_mass", ";m_{D_{S}} (GeV/c^{2});entries", {HistType::kTH1F, {{1000, 0., 6.}}}}, + {"h_ds_eta", ";#eta_{D_{S}};entries", {HistType::kTH1F, {{250, -1., 1.}}}}, + {"h_ds_phi", ";#phi_{D_{S}};entries", {HistType::kTH1F, {{250, -1., 7.}}}}, + {"h_ds_jet_mass", ";m_{jet}^{ch} (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{200, 0., 50.}}}}, + {"h_ds_jet_lambda11", ";#lambda_{1}^{1};entries", {HistType::kTH1F, {{200, 0., 1.0}}}}, + {"h_ds_jet_lambda12", ";#lambda_{2}^{1} (thrust);entries", {HistType::kTH1F, {{200, 0., 1.0}}}}, + {"h_ds_jet_girth", ";g (#equiv #lambda_{1}^{1}R);entries", {HistType::kTH1F, {{200, 0., 0.5}}}}, + {"h2_dsjet_pt_lambda11", ";#it{p}_{T,jet} (GeV/#it{c});#lambda_{1}^{1}", {HistType::kTH2F, {{100, 0., 100.}, {200, 0., 1.0}}}}, + {"h2_dsjet_pt_lambda12", ";#it{p}_{T,jet} (GeV/#it{c});#lambda_{2}^{1}", {HistType::kTH2F, {{100, 0., 100.}, {200, 0., 1.0}}}}, + {"h2_dsjet_pt_mass", ";#it{p}_{T,jet} (GeV/#it{c});m_{jet}^{ch} (GeV/#it{c}^{2})", {HistType::kTH2F, {{100, 0., 100.}, {200, 0., 50.0}}}}, + {"h2_dsjet_pt_girth", ";#it{p}_{T,jet} (GeV/#it{c});g", {HistType::kTH2F, {{100, 0., 100.}, {200, 0., 0.5}}}}, + {"h_ds_jet_lambda_extra", ";#lambda_{#alpha}^{#kappa};entries", {HistType::kTH1F, {{200, 0., 1.0}}}}, + {"h2_dsjet_pt_lambda_extra", ";#it{p}_{T,jet} (GeV/#it{c});#lambda_{#alpha}^{#kappa}", {HistType::kTH2F, {{100, 0., 100.}, {200, 0., 1.0}}}}, + }}; + Configurable vertexZCut{"vertexZCut", 10.0f, "Accepted z-vertex range"}; Configurable jetPtMin{"jetPtMin", 5.0, "minimum jet pT cut"}; Configurable jetR{"jetR", 0.4, "jet resolution parameter"}; Configurable eventSelections{"eventSelections", "sel8", "choose event selection"}; Configurable trackSelections{"trackSelections", "globalTracks", "set track selections"}; + // extra angularity knob + Configurable kappa{"kappa", 1.0f, "angularity kappa"}; + Configurable alpha{"alpha", 1.0f, "angularity alpha"}; + + bool doExtraAngularity = false; + std::vector eventSelectionBits; int trackSelection = -1; Produces distJetTable; + template + float computeLambda(JET const& jet, TRACKS const& tracks, float a, float k) + { + if (jet.pt() <= 0.f) { + return -1.f; + } + float sum = 0.f; + for (auto const& trk : tracks) { + const float dr = jetutilities::deltaR(jet, trk); + sum += std::pow(trk.pt(), k) * std::pow(dr, a); + } + const float R = jet.r() / 100.f; + const float denom = std::pow(jet.pt(), k) * std::pow(R, a); + if (denom <= 0.f) { + return -1.f; + } + return sum / denom; + } + + template + float computeJetMassFromTracksMass(TRACKS const& tracks) + { + double sumPx = 0.0, sumPy = 0.0, sumPz = 0.0, sumE = 0.0; + + for (auto const& trk : tracks) { + const double pt = trk.pt(); + const double phi = trk.phi(); + const double eta = trk.eta(); + + const double px = pt * std::cos(phi); + const double py = pt * std::sin(phi); + const double pz = pt * std::sinh(eta); + const double p = std::sqrt(px * px + py * py + pz * pz); + + sumPx += px; + sumPy += py; + sumPz += pz; + sumE += p; // massless + } + + const double m2 = sumE * sumE - (sumPx * sumPx + sumPy * sumPy + sumPz * sumPz); + return (m2 > 0.0) ? static_cast(std::sqrt(m2)) : 0.f; + } + void init(o2::framework::InitContext&) { eventSelectionBits = jetderiveddatautilities::initialiseEventSelectionBits(static_cast(eventSelections)); trackSelection = jetderiveddatautilities::initialiseTrackSelection(static_cast(trackSelections)); + + const bool is11 = (std::abs(kappa.value - 1.f) < 1e-6f) && (std::abs(alpha.value - 1.f) < 1e-6f); + const bool is12 = (std::abs(kappa.value - 1.f) < 1e-6f) && (std::abs(alpha.value - 2.f) < 1e-6f); + doExtraAngularity = !(is11 || is12); } Filter jetCuts = aod::jet::pt > jetPtMin&& aod::jet::r == nround(jetR.node() * 100.0f); @@ -129,12 +204,12 @@ struct JetDsSpecSubs { void processCollisions(aod::JetCollision const& collision, aod::JetTracks const& tracks) { - registry.fill(HIST("h_collisions"), 0.5); if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { return; } registry.fill(HIST("h_collisions"), 1.5); + for (auto const& track : tracks) { if (!jetderiveddatautilities::selectTrack(track, trackSelection)) { continue; @@ -146,12 +221,12 @@ struct JetDsSpecSubs { } PROCESS_SWITCH(JetDsSpecSubs, processCollisions, "process JE collisions", false); - void processDataCharged(soa::Filtered::iterator const& collision, soa::Filtered const& jets) + void processDataCharged(soa::Filtered::iterator const& collision, + soa::Filtered const& jets) { if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { return; } - // jets -> charged jet for (auto& jet : jets) { registry.fill(HIST("h_jet_pt"), jet.pt()); registry.fill(HIST("h_jet_eta"), jet.eta()); @@ -165,31 +240,24 @@ struct JetDsSpecSubs { aod::CandidatesDsData const&, aod::JetTracks const&) { - // apply event selection and fill histograms for sanity check registry.fill(HIST("h_collision_counter"), 2.0); - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits) || !(std::abs(collision.posZ()) < vertexZCut)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits) || + !(std::abs(collision.posZ()) < vertexZCut)) { return; } registry.fill(HIST("h_collision_counter"), 3.0); - // jets -> charged jet with Ds + for (const auto& jet : jets) { - // number of charged jets with Ds registry.fill(HIST("h_jet_counter"), 0.5); - // obtaining jet 3-vector + TVector3 jetVector(jet.px(), jet.py(), jet.pz()); for (const auto& dsCandidate : jet.candidates_as()) { - - // obtaining jet 3-vector TVector3 dsVector(dsCandidate.px(), dsCandidate.py(), dsCandidate.pz()); - // calculating fraction of the jet momentum carried by the Ds along the direction of the jet axis - double zParallel = (jetVector * dsVector) / (jetVector * jetVector); - - // calculating angular distance in eta-phi plane - double axisDistance = jetutilities::deltaR(jet, dsCandidate); + const double zParallel = (jetVector * dsVector) / (jetVector * jetVector); + const double axisDistance = jetutilities::deltaR(jet, dsCandidate); - // filling histograms registry.fill(HIST("h_ds_jet_projection"), zParallel); registry.fill(HIST("h_ds_jet_distance_vs_projection"), axisDistance, zParallel); registry.fill(HIST("h_ds_jet_distance"), axisDistance); @@ -200,25 +268,56 @@ struct JetDsSpecSubs { registry.fill(HIST("h_ds_eta"), dsCandidate.eta()); registry.fill(HIST("h_ds_phi"), dsCandidate.phi()); - // Retrieve ML scores safely - auto scores = dsCandidate.mlScores(); + auto jetTracks = jet.tracks_as(); + + const float lambda11 = computeLambda(jet, jetTracks, 1.f, 1.f); + const float lambda12 = computeLambda(jet, jetTracks, 2.f, 1.f); // thrust = λ_2^1 + const float mjet = computeJetMassFromTracksMass(jetTracks); - float s0 = (scores.size() > 0) ? scores[0] : -999.f; - float s1 = (scores.size() > 1) ? scores[1] : -999.f; - float s2 = (scores.size() > 2) ? scores[2] : -999.f; + const float R = jet.r() / 100.f; + const float girth = (lambda11 >= 0.f) ? (lambda11 * R) : -1.f; - distJetTable(axisDistance, + if (lambda11 >= 0.f) { + registry.fill(HIST("h_ds_jet_lambda11"), lambda11); + registry.fill(HIST("h2_dsjet_pt_lambda11"), jet.pt(), lambda11); + } + if (lambda12 >= 0.f) { + registry.fill(HIST("h_ds_jet_lambda12"), lambda12); + registry.fill(HIST("h2_dsjet_pt_lambda12"), jet.pt(), lambda12); + } + registry.fill(HIST("h_ds_jet_mass"), mjet); + registry.fill(HIST("h2_dsjet_pt_mass"), jet.pt(), mjet); + + if (girth >= 0.f) { + registry.fill(HIST("h_ds_jet_girth"), girth); + registry.fill(HIST("h2_dsjet_pt_girth"), jet.pt(), girth); + } + + if (doExtraAngularity) { + const float lambdaExtra = computeLambda(jet, jetTracks, alpha.value, kappa.value); + if (lambdaExtra >= 0.f) { + registry.fill(HIST("h_ds_jet_lambda_extra"), lambdaExtra); + registry.fill(HIST("h2_dsjet_pt_lambda_extra"), jet.pt(), lambdaExtra); + } + } + + auto scores = dsCandidate.mlScores(); + const float s0 = (scores.size() > 0) ? scores[0] : -999.f; + const float s1 = (scores.size() > 1) ? scores[1] : -999.f; + const float s2 = (scores.size() > 2) ? scores[2] : -999.f; + + distJetTable(static_cast(axisDistance), jet.pt(), jet.eta(), jet.phi(), - static_cast(jet.tracks_as().size()), + static_cast(jetTracks.size()), dsCandidate.pt(), dsCandidate.eta(), dsCandidate.phi(), dsCandidate.m(), dsCandidate.y(), - s0, s1, s2); - break; // get out of candidates' loop after first HF particle is found in jet - } // end of DS candidates loop + s0, s1, s2, + mjet, girth, lambda12, lambda11); - } // end of jets loop - - } // end of process function + break; // only first Ds per jet + } + } + } PROCESS_SWITCH(JetDsSpecSubs, processDataChargedSubstructure, "charged HF jet substructure", false); }; From f13673728972a38fab9763a7691271bac2d93e6b Mon Sep 17 00:00:00 2001 From: ldellost <47105254+DelloStritto@users.noreply.github.com> Date: Thu, 5 Mar 2026 01:39:58 +0100 Subject: [PATCH 173/347] [PWGHF] Add derived data creator for Lc in pK0s. Farewell! (#15259) --- .../DataModel/CandidateReconstructionTables.h | 5 +- PWGHF/DataModel/DerivedTables.h | 83 +++- PWGHF/TableProducer/CMakeLists.txt | 5 + .../derivedDataCreatorLcToK0sP.cxx | 408 ++++++++++++++++++ 4 files changed, 499 insertions(+), 2 deletions(-) create mode 100644 PWGHF/TableProducer/derivedDataCreatorLcToK0sP.cxx diff --git a/PWGHF/DataModel/CandidateReconstructionTables.h b/PWGHF/DataModel/CandidateReconstructionTables.h index 50c51aec9ef..a13fb4280ab 100644 --- a/PWGHF/DataModel/CandidateReconstructionTables.h +++ b/PWGHF/DataModel/CandidateReconstructionTables.h @@ -495,6 +495,8 @@ DECLARE_SOA_DYNAMIC_COLUMN(PtV0Neg, ptV0Neg, //! pt of the negative V0 daughter [](float px, float py) { return RecoDecay::pt(px, py); }); DECLARE_SOA_DYNAMIC_COLUMN(CtV0, ctV0, //! c*t of the V0 [](float xVtxP, float yVtxP, float zVtxP, float xVtxS, float yVtxS, float zVtxS, float px, float py, float pz, double m) -> float { return RecoDecay::ct(std::array{px, py, pz}, RecoDecay::distance(std::array{xVtxP, yVtxP, zVtxP}, std::array{xVtxS, yVtxS, zVtxS}), m); }); +DECLARE_SOA_DYNAMIC_COLUMN(DecayLengthV0, decayLengthV0, //! + [](float xVtxP, float yVtxP, float zVtxP, float xVtxS, float yVtxS, float zVtxS) -> float { return RecoDecay::distance(std::array{xVtxP, yVtxP, zVtxP}, std::array{xVtxS, yVtxS, zVtxS}); }); DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); //! reconstruction level DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); //! generator level DECLARE_SOA_COLUMN(OriginMcRec, originMcRec, int8_t); //! particle origin, reconstruction level @@ -552,7 +554,8 @@ DECLARE_SOA_TABLE(HfCandCascBase, "AOD", "HFCANDCASCBASE", //! v0data::legacy::MAntiLambda, v0data::legacy::MK0Short, v0data::MGamma, - hf_cand_casc::CtV0); + hf_cand_casc::CtV0, + hf_cand_casc::DecayLengthV0); // , // v0data::MLambda, // v0data::MAntiLambda, diff --git a/PWGHF/DataModel/DerivedTables.h b/PWGHF/DataModel/DerivedTables.h index 16fafa2ec99..52ffdb44ab7 100644 --- a/PWGHF/DataModel/DerivedTables.h +++ b/PWGHF/DataModel/DerivedTables.h @@ -307,9 +307,10 @@ DECLARE_SOA_COLUMN(FlagMcDecayChanGen, flagMcDecayChanGen, int8_t); //! resonant DECLARE_TABLES_2P(D0, "D0", d0, 2); DECLARE_TABLES_3P(Lc, "LC", lc, 3); DECLARE_TABLES_3P(Dplus, "DP", dplus, 4); -DECLARE_TABLES_3P(Ds, "DS", ds, 9); DECLARE_TABLES_3P(Bplus, "BP", bplus, 5); DECLARE_TABLES_3P(Dstar, "DST", dstar, 6); +DECLARE_TABLES_3P(Ds, "DS", ds, 9); +DECLARE_TABLES_3P(LcToK0sP, "LCC", lc_to_k0s_p, 10); // Workaround for the existing B0 macro in termios.h #pragma push_macro("B0") #undef B0 @@ -355,6 +356,20 @@ DECLARE_SOA_COLUMN(PtProngXi, ptProngXi, float); DECLARE_SOA_COLUMN(PtProngPi0, ptProngPi0, float); //! transverse momentum of the first pion prong DECLARE_SOA_COLUMN(PtProngPi1, ptProngPi1, float); //! transverse momentum of the second pion prong DECLARE_SOA_COLUMN(RSecondaryVertex, rSecondaryVertex, float); //! distance of the secondary vertex from the z axis +// Lc± → K0s p± +DECLARE_SOA_COLUMN(V0CosPA, v0cosPA, float); //! cosine of the V0 pointing angle +DECLARE_SOA_COLUMN(CtV0, ctV0, float); //! V0 proper lifetime times c +DECLARE_SOA_COLUMN(DecayLengthV0, decayLengthV0, float); //! V0 decay length +DECLARE_SOA_COLUMN(PtV0Pos, ptV0Pos, float); //! transverse momentum of V0 pos prong +DECLARE_SOA_COLUMN(PtV0Neg, ptV0Neg, float); //! transverse momentum of V0 neg prong +DECLARE_SOA_COLUMN(DCAPosToPV, dcapostopv, float); //! V0 pos prong impact param wrt prim vtx in xy +DECLARE_SOA_COLUMN(DCANegToPV, dcanegtopv, float); //! V0 neg prong impact param wrt prim vtx in xy +DECLARE_SOA_COLUMN(DCAV0Daughters, dcaV0daughters, float); //! V0 daughters dca +DECLARE_SOA_COLUMN(V0Radius, v0radius, float); //! transverse distance of the V0 decay vertex from the beam line +DECLARE_SOA_COLUMN(MLambda, mLambda, float); +DECLARE_SOA_COLUMN(MAntiLambda, mAntiLambda, float); +DECLARE_SOA_COLUMN(MK0Short, mK0Short, float); +DECLARE_SOA_COLUMN(MGamma, mGamma, float); // D*± → D0(bar) π± DECLARE_SOA_COLUMN(SignProng1, signProng1, int8_t); // TOF @@ -801,6 +816,72 @@ DECLARE_SOA_TABLE_STAGED(HfLcMcs, "HFLCMC", //! Table with MC candidate info hf_cand_mc::IsCandidateSwapped, o2::soa::Marker); +// ---------------- +// Lc to K0sP +// ---------------- + +DECLARE_SOA_TABLE_STAGED(HfLcToK0sPPars, "HFLCTOK0SPPAR", //! Table with candidate properties used for selection + hf_cand::Chi2PCA, + hf_cand_par::Cpa, + hf_cand_par::CpaXY, + hf_cand_par::DecayLength, + hf_cand_par::DecayLengthXY, + hf_cand_par::PtProng0, + hf_cand_par::PtProng1, + hf_cand::ImpactParameter0, + hf_cand::ImpactParameter1, + hf_cand_par::V0Radius, + hf_cand_par::V0CosPA, + hf_cand_par::MLambda, + hf_cand_par::MAntiLambda, + hf_cand_par::MK0Short, + hf_cand_par::MGamma, + hf_cand_par::DCAV0Daughters, + hf_cand_par::PtV0Pos, + hf_cand_par::PtV0Neg, + hf_cand_par::DecayLengthV0, + hf_cand_par::DCAPosToPV, + hf_cand_par::DCANegToPV, + hf_cand_par::NSigTpcPr0, + hf_cand_par::NSigTofPr0, + hf_cand_par::CtV0, + o2::soa::Marker); + +DECLARE_SOA_TABLE_STAGED(HfLcToK0sPParEs, "HFLCTOK0SPPARE", //! Table with additional candidate properties used for selection + hf_cand::XSecondaryVertex, + hf_cand::YSecondaryVertex, + hf_cand::ZSecondaryVertex, + hf_cand::ErrorDecayLength, + hf_cand::ErrorDecayLengthXY, + hf_cand_par::RSecondaryVertex, + hf_cand_par::PProng0, + hf_cand_par::PProng1, + hf_cand::PxProng0, + hf_cand::PyProng0, + hf_cand::PzProng0, + hf_cand::PxProng1, + hf_cand::PyProng1, + hf_cand::PzProng1, + v0data::PxPos, + v0data::PyPos, + v0data::PzPos, + v0data::PxNeg, + v0data::PyNeg, + v0data::PzNeg, + hf_cand::ErrorImpactParameter0, + hf_cand::ErrorImpactParameter1, + hf_cand_par::Ct, + o2::soa::Marker); + +DECLARE_SOA_TABLE_STAGED(HfLcToK0sPMls, "HFLCTOK0SPML", //! Table with candidate selection ML scores + hf_cand_mc::MlScores, + o2::soa::Marker); + +DECLARE_SOA_TABLE_STAGED(HfLcToK0sPMcs, "HFLCTOK0SPMC", //! Table with MC candidate info + hf_cand_mc::FlagMcMatchRec, + hf_cand_mc::OriginMcRec, + o2::soa::Marker); + // ---------------- // D+ // ---------------- diff --git a/PWGHF/TableProducer/CMakeLists.txt b/PWGHF/TableProducer/CMakeLists.txt index 8103e914d1e..4ae18ad282e 100644 --- a/PWGHF/TableProducer/CMakeLists.txt +++ b/PWGHF/TableProducer/CMakeLists.txt @@ -330,6 +330,11 @@ o2physics_add_dpl_workflow(derived-data-creator-lc-to-p-k-pi PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(derived-data-creator-lc-to-k0s-p + SOURCES derivedDataCreatorLcToK0sP.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(derived-data-creator-xic-to-xi-pi-pi SOURCES derivedDataCreatorXicToXiPiPi.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore diff --git a/PWGHF/TableProducer/derivedDataCreatorLcToK0sP.cxx b/PWGHF/TableProducer/derivedDataCreatorLcToK0sP.cxx new file mode 100644 index 00000000000..83b2f90107d --- /dev/null +++ b/PWGHF/TableProducer/derivedDataCreatorLcToK0sP.cxx @@ -0,0 +1,408 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file derivedDataCreatorLcToK0sP.cxx +/// \brief Producer of derived tables of Lc candidates, collisions and MC particles +/// \note Based on treeCreatorLcToK0sP.cxx and derivedDataCreatorD0ToKPi.cxx +/// +/// \author Luigi Dello Stritto , Marietta-Blau Institute +/// \author Vít Kučera , Inha University + +#include "PWGHF/Core/DecayChannels.h" +#include "PWGHF/Core/HfHelper.h" +#include "PWGHF/DataModel/AliasTables.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/DataModel/DerivedTables.h" +#include "PWGHF/Utils/utilsDerivedData.h" +#include "PWGLF/DataModel/mcCentrality.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/Multiplicity.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::analysis::hf_derived; + +/// Writes the full information in an output TTree +struct HfDerivedDataCreatorLcToK0sP { + HfProducesDerivedData< + o2::aod::HfLcToK0sPBases, + o2::aod::HfLcToK0sPCollBases, + o2::aod::HfLcToK0sPCollIds, + o2::aod::HfLcToK0sPMcCollBases, + o2::aod::HfLcToK0sPMcCollIds, + o2::aod::HfLcToK0sPMcRCollIds, + o2::aod::HfLcToK0sPPBases, + o2::aod::HfLcToK0sPPIds> + rowsCommon; + // Candidates + Produces rowCandidatePar; + Produces rowCandidateParE; + Produces rowCandidateSel; + Produces rowCandidateMl; + Produces rowCandidateId; + Produces rowCandidateMc; + + // Switches for filling tables + HfConfigurableDerivedData confDerData; + Configurable fillCandidatePar{"fillCandidatePar", true, "Fill candidate parameters"}; + Configurable fillCandidateParE{"fillCandidateParE", true, "Fill candidate extended parameters"}; + Configurable fillCandidateSel{"fillCandidateSel", true, "Fill candidate selection flags"}; + Configurable fillCandidateMl{"fillCandidateMl", true, "Fill candidate selection ML scores"}; + Configurable fillCandidateId{"fillCandidateId", true, "Fill original indices from the candidate table"}; + Configurable fillCandidateMc{"fillCandidateMc", true, "Fill candidate MC info"}; + // Parameters for production of training samples + Configurable downSampleBkgFactor{"downSampleBkgFactor", 1., "Fraction of background candidates to keep for ML trainings"}; + Configurable ptMaxForDownSample{"ptMaxForDownSample", 10., "Maximum pt for the application of the downsampling factor"}; + + SliceCache cache; + static constexpr double Mass{o2::constants::physics::MassLambdaCPlus}; + + using CollisionsWCentMult = soa::Join; + using CollisionsWMcCentMult = soa::Join; + using TracksWPid = soa::Join; + using SelectedCandidates = soa::Filtered>; + using SelectedCandidatesMc = soa::Filtered>; + using SelectedCandidatesMl = soa::Filtered>; + using SelectedCandidatesMcMl = soa::Filtered>; + using MatchedGenCandidatesMc = soa::Filtered>; + using TypeMcCollisions = soa::Join; + + Filter filterSelectCandidates = aod::hf_sel_candidate_lc_to_k0s_p::isSelLcToK0sP >= 1; + Filter filterMcGenMatching = nabs(aod::hf_cand_casc::flagMcMatchGen) == 1; + + Preslice candidatesPerCollision = aod::hf_cand::collisionId; + Preslice candidatesMcPerCollision = aod::hf_cand::collisionId; + Preslice candidatesMlPerCollision = aod::hf_cand::collisionId; + Preslice candidatesMcMlPerCollision = aod::hf_cand::collisionId; + Preslice mcParticlesPerMcCollision = aod::mcparticle::mcCollisionId; + + // trivial partitions for all candidates to allow "->sliceByCached" inside processCandidates + Partition candidatesAll = aod::hf_sel_candidate_lc_to_k0s_p::isSelLcToK0sP >= 0; + Partition candidatesMcAll = aod::hf_sel_candidate_lc_to_k0s_p::isSelLcToK0sP >= 0; + Partition candidatesMlAll = aod::hf_sel_candidate_lc_to_k0s_p::isSelLcToK0sP >= 0; + Partition candidatesMcMlAll = aod::hf_sel_candidate_lc_to_k0s_p::isSelLcToK0sP >= 0; + // partitions for signal and background + Partition candidatesMcSig = nabs(aod::hf_cand_casc::flagMcMatchRec) == 1; + Partition candidatesMcBkg = nabs(aod::hf_cand_casc::flagMcMatchRec) != 1; + Partition candidatesMcMlSig = nabs(aod::hf_cand_casc::flagMcMatchRec) == 1; + Partition candidatesMcMlBkg = nabs(aod::hf_cand_casc::flagMcMatchRec) != 1; + + void init(InitContext const&) + { + std::array doprocess{doprocessData, doprocessMcSig, doprocessMcBkg, doprocessMcAll, doprocessDataMl, doprocessMcMlSig, doprocessMcMlBkg, doprocessMcMlAll, doprocessMcGenOnly}; + if (std::accumulate(doprocess.begin(), doprocess.end(), 0) != 1) { + LOGP(fatal, "Only one process function can be enabled at a time."); + } + rowsCommon.init(confDerData); + } + + template + void fillTablesCandidate(const T& candidate, const U& bach, int candFlag, double invMass, + double ct, double ctV0, double y, int8_t flagMc, int8_t origin, const std::vector& mlScores) + { + rowsCommon.fillTablesCandidate(candidate, invMass, y); + if (fillCandidatePar) { + rowCandidatePar( + candidate.chi2PCA(), + candidate.cpa(), + candidate.cpaXY(), + candidate.decayLength(), + candidate.decayLengthXY(), + candidate.ptProng0(), + candidate.ptProng1(), + candidate.impactParameter0(), + candidate.impactParameter1(), + candidate.v0radius(), + candidate.v0cosPA(), + candidate.mLambda(), + candidate.mAntiLambda(), + candidate.mK0Short(), + candidate.mGamma(), + candidate.dcaV0daughters(), + candidate.ptV0Pos(), + candidate.ptV0Neg(), + candidate.decayLengthV0(), + candidate.dcanegtopv(), + candidate.dcapostopv(), + bach.tpcNSigmaPr(), + bach.tofNSigmaPr(), + ctV0); + } + if (fillCandidateParE) { + rowCandidateParE( + candidate.xSecondaryVertex(), + candidate.ySecondaryVertex(), + candidate.zSecondaryVertex(), + candidate.errorDecayLength(), + candidate.errorDecayLengthXY(), + candidate.rSecondaryVertex(), + RecoDecay::p(candidate.pxProng0(), candidate.pyProng0(), candidate.pzProng0()), + RecoDecay::p(candidate.pxProng1(), candidate.pyProng1(), candidate.pzProng1()), + candidate.pxProng0(), + candidate.pyProng0(), + candidate.pzProng0(), + candidate.pxProng1(), + candidate.pyProng1(), + candidate.pzProng1(), + candidate.pxpos(), + candidate.pypos(), + candidate.pzpos(), + candidate.pxneg(), + candidate.pyneg(), + candidate.pzneg(), + candidate.errorImpactParameter0(), + candidate.errorImpactParameter1(), + ct); + } + if (fillCandidateSel) { + rowCandidateSel( + BIT(candFlag)); + } + if (fillCandidateMl) { + rowCandidateMl( + mlScores); + } + if (fillCandidateId) { + rowCandidateId( + candidate.collisionId(), + candidate.prong0Id(), + candidate.posTrackId(), + candidate.negTrackId()); + } + if (fillCandidateMc) { + rowCandidateMc( + flagMc, + origin); + } + } + + template + void processCandidates(CollType const& collisions, + Partition& candidates, + TracksWPid const&, + aod::BCs const&) + { + // Fill collision properties + if constexpr (IsMc) { + if (confDerData.fillMcRCollId) { + rowsCommon.matchedCollisions.clear(); + } + } + auto sizeTableColl = collisions.size(); + rowsCommon.reserveTablesColl(sizeTableColl); + for (const auto& collision : collisions) { + auto thisCollId = collision.globalIndex(); + auto candidatesThisColl = candidates->sliceByCached(aod::hf_cand::collisionId, thisCollId, cache); // FIXME + auto sizeTableCand = candidatesThisColl.size(); + LOGF(debug, "Rec. collision %d has %d candidates", thisCollId, sizeTableCand); + // Skip collisions without HF candidates (and without HF particles in matched MC collisions if saving indices of reconstructed collisions matched to MC collisions) + bool mcCollisionHasMcParticles{false}; + if constexpr (IsMc) { + mcCollisionHasMcParticles = confDerData.fillMcRCollId && collision.has_mcCollision() && rowsCommon.hasMcParticles[collision.mcCollisionId()]; + LOGF(debug, "Rec. collision %d has MC collision %d with MC particles? %s", thisCollId, collision.mcCollisionId(), mcCollisionHasMcParticles ? "yes" : "no"); + } + if (sizeTableCand == 0 && (!confDerData.fillMcRCollId || !mcCollisionHasMcParticles)) { + LOGF(debug, "Skipping rec. collision %d", thisCollId); + continue; + } + LOGF(debug, "Filling rec. collision %d at derived index %d", thisCollId, rowsCommon.rowCollBase.lastIndex() + 1); + rowsCommon.fillTablesCollision(collision); + + // Fill candidate properties + rowsCommon.reserveTablesCandidates(sizeTableCand); + reserveTable(rowCandidatePar, fillCandidatePar, sizeTableCand); + reserveTable(rowCandidateParE, fillCandidateParE, sizeTableCand); + reserveTable(rowCandidateSel, fillCandidateSel, sizeTableCand); + reserveTable(rowCandidateMl, fillCandidateMl, sizeTableCand); + reserveTable(rowCandidateId, fillCandidateId, sizeTableCand); + if constexpr (IsMc) { + reserveTable(rowCandidateMc, fillCandidateMc, sizeTableCand); + } + int8_t flagMcRec = 0, origin = 0; + for (const auto& candidate : candidatesThisColl) { + if constexpr (IsMc) { + flagMcRec = candidate.flagMcMatchRec(); + origin = candidate.originMcRec(); + if constexpr (OnlyBkg) { + if (std::abs(flagMcRec) == 1) { + continue; + } + if (downSampleBkgFactor < 1.) { + float const pseudoRndm = candidate.ptProng0() * 1000. - static_cast(candidate.ptProng0() * 1000); + if (candidate.pt() < ptMaxForDownSample && pseudoRndm >= downSampleBkgFactor) { + continue; + } + } + } + if constexpr (OnlySig) { + if (std::abs(flagMcRec) != 1) { + continue; + } + } + } else { + if (downSampleBkgFactor < 1.) { + float const pseudoRndm = candidate.ptProng0() * 1000. - static_cast(candidate.ptProng0() * 1000); + if (candidate.pt() < ptMaxForDownSample && pseudoRndm >= downSampleBkgFactor) { + continue; + } + } + } + auto bach = candidate.template prong0_as(); // bachelor + double const ct = HfHelper::ctLc(candidate); + double const ctV0 = HfHelper::ctV0K0s(candidate); + double const y = HfHelper::yLc(candidate); + float const massLcToK0sP = HfHelper::invMassLcToK0sP(candidate); + std::vector mlScoresLcToK0sP; + if constexpr (IsMl) { + std::copy(candidate.mlProbLcToK0sP().begin(), candidate.mlProbLcToK0sP().end(), std::back_inserter(mlScoresLcToK0sP)); + } + if (candidate.isSelLcToK0sP()) { + fillTablesCandidate(candidate, bach, 0, massLcToK0sP, ct, ctV0, y, flagMcRec, origin, mlScoresLcToK0sP); + } + } + } + } + + void processData(CollisionsWCentMult const& collisions, + SelectedCandidates const&, + TracksWPid const& tracks, + aod::BCs const& bcs) + { + processCandidates(collisions, candidatesAll, tracks, bcs); + } + PROCESS_SWITCH(HfDerivedDataCreatorLcToK0sP, processData, "Process data", true); + + void processMcSig(CollisionsWMcCentMult const& collisions, + SelectedCandidatesMc const&, + TypeMcCollisions const& mcCollisions, + MatchedGenCandidatesMc const& mcParticles, + TracksWPid const& tracks, + aod::BCs const& bcs) + { + rowsCommon.preProcessMcCollisions(mcCollisions, mcParticlesPerMcCollision, mcParticles); + processCandidates(collisions, candidatesMcSig, tracks, bcs); + rowsCommon.processMcParticles(mcCollisions, mcParticlesPerMcCollision, mcParticles, Mass); + } + PROCESS_SWITCH(HfDerivedDataCreatorLcToK0sP, processMcSig, "Process MC only for signals", false); + + void processMcBkg(CollisionsWMcCentMult const& collisions, + SelectedCandidatesMc const&, + TypeMcCollisions const& mcCollisions, + MatchedGenCandidatesMc const& mcParticles, + TracksWPid const& tracks, + aod::BCs const& bcs) + { + rowsCommon.preProcessMcCollisions(mcCollisions, mcParticlesPerMcCollision, mcParticles); + processCandidates(collisions, candidatesMcBkg, tracks, bcs); + rowsCommon.processMcParticles(mcCollisions, mcParticlesPerMcCollision, mcParticles, Mass); + } + PROCESS_SWITCH(HfDerivedDataCreatorLcToK0sP, processMcBkg, "Process MC only for background", false); + + void processMcAll(CollisionsWMcCentMult const& collisions, + SelectedCandidatesMc const&, + TypeMcCollisions const& mcCollisions, + MatchedGenCandidatesMc const& mcParticles, + TracksWPid const& tracks, + aod::BCs const& bcs) + { + rowsCommon.preProcessMcCollisions(mcCollisions, mcParticlesPerMcCollision, mcParticles); + processCandidates(collisions, candidatesMcAll, tracks, bcs); + rowsCommon.processMcParticles(mcCollisions, mcParticlesPerMcCollision, mcParticles, Mass); + } + PROCESS_SWITCH(HfDerivedDataCreatorLcToK0sP, processMcAll, "Process MC", false); + + // ML versions + + void processDataMl(CollisionsWCentMult const& collisions, + SelectedCandidatesMl const&, + TracksWPid const& tracks, + aod::BCs const& bcs) + { + processCandidates(collisions, candidatesMlAll, tracks, bcs); + } + PROCESS_SWITCH(HfDerivedDataCreatorLcToK0sP, processDataMl, "Process data with ML", false); + + void processMcMlSig(CollisionsWMcCentMult const& collisions, + SelectedCandidatesMcMl const&, + TypeMcCollisions const& mcCollisions, + MatchedGenCandidatesMc const& mcParticles, + TracksWPid const& tracks, + aod::BCs const& bcs) + { + rowsCommon.preProcessMcCollisions(mcCollisions, mcParticlesPerMcCollision, mcParticles); + processCandidates(collisions, candidatesMcMlSig, tracks, bcs); + rowsCommon.processMcParticles(mcCollisions, mcParticlesPerMcCollision, mcParticles, Mass); + } + PROCESS_SWITCH(HfDerivedDataCreatorLcToK0sP, processMcMlSig, "Process MC with ML only for signals", false); + + void processMcMlBkg(CollisionsWMcCentMult const& collisions, + SelectedCandidatesMcMl const&, + TypeMcCollisions const& mcCollisions, + MatchedGenCandidatesMc const& mcParticles, + TracksWPid const& tracks, + aod::BCs const& bcs) + { + rowsCommon.preProcessMcCollisions(mcCollisions, mcParticlesPerMcCollision, mcParticles); + processCandidates(collisions, candidatesMcMlBkg, tracks, bcs); + rowsCommon.processMcParticles(mcCollisions, mcParticlesPerMcCollision, mcParticles, Mass); + } + PROCESS_SWITCH(HfDerivedDataCreatorLcToK0sP, processMcMlBkg, "Process MC with ML only for background", false); + + void processMcMlAll(CollisionsWMcCentMult const& collisions, + SelectedCandidatesMcMl const&, + TypeMcCollisions const& mcCollisions, + MatchedGenCandidatesMc const& mcParticles, + TracksWPid const& tracks, + aod::BCs const& bcs) + { + rowsCommon.preProcessMcCollisions(mcCollisions, mcParticlesPerMcCollision, mcParticles); + processCandidates(collisions, candidatesMcMlAll, tracks, bcs); + rowsCommon.processMcParticles(mcCollisions, mcParticlesPerMcCollision, mcParticles, Mass); + } + PROCESS_SWITCH(HfDerivedDataCreatorLcToK0sP, processMcMlAll, "Process MC with ML", false); + + void processMcGenOnly(TypeMcCollisions const& mcCollisions, + MatchedGenCandidatesMc const& mcParticles) + { + rowsCommon.processMcParticles(mcCollisions, mcParticlesPerMcCollision, mcParticles, Mass); + } + PROCESS_SWITCH(HfDerivedDataCreatorLcToK0sP, processMcGenOnly, "Process MC gen. only", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} From 91d6549f2a87774abcd48095601504c0de58f248 Mon Sep 17 00:00:00 2001 From: ariedel-cern <85537041+ariedel-cern@users.noreply.github.com> Date: Thu, 5 Mar 2026 01:53:05 +0100 Subject: [PATCH 174/347] [PWGCF] Update femto framework (#15266) MegaLinter fails to lint 2 Python scripts. Merging anyway. --- PWGCF/Femto/Macros/cutculator.py | 37 ++- PWGCF/Femto/Macros/cutculatorGui.py | 437 ++++++++++++++++++++++++++++ 2 files changed, 473 insertions(+), 1 deletion(-) create mode 100755 PWGCF/Femto/Macros/cutculatorGui.py diff --git a/PWGCF/Femto/Macros/cutculator.py b/PWGCF/Femto/Macros/cutculator.py index 9e1d771b6da..34f9b2054c3 100755 --- a/PWGCF/Femto/Macros/cutculator.py +++ b/PWGCF/Femto/Macros/cutculator.py @@ -49,12 +49,20 @@ def ask_user_selection(group): Prompt user to select bin(s) for this selection group. - If minimal selections contain exactly 1 entry → auto-select it. - Optional selections remain user-selectable. + - Neither minimal nor optional selections are shown with a warning — useful for rejection masks. """ selection_name = group[0].get("SelectionName", "unknown") - # Separate minimal and optional bins + # Separate bins by type minimal_bins = [b for b in group if b.get("MinimalCut", "0") == "1" and b.get("OptionalCut", "0") == "0"] optional_bins = [b for b in group if b.get("OptionalCut", "0") == "1"] + neutral_bins = [ + b + for b in group + if b.get("MinimalCut", "0") == "0" + and b.get("OptionalCut", "0") == "0" + and b.get("BitPosition", "X").upper() != "X" + ] selected_bins = [] @@ -107,7 +115,34 @@ def ask_user_selection(group): b = optional_bins[i - 1] selected_bins.append(b) chosen.append(format_value_with_comment(b)) + print("Selected: " + ", ".join(chosen)) + break + except ValueError: + pass + + print("Invalid input. Please enter valid indices separated by space.") + # ----- Neither minimal nor optional----- + if neutral_bins: + print(f"\nSelection: {selection_name} (Neither minimal nor optional, 0 to skip)") + for idx, b in enumerate(neutral_bins, start=1): + print(f" [{idx}] {format_value_with_comment(b)}") + + while True: + sel_input = input("Enter indices separated by space (0 to skip): ") + if not sel_input.strip() or sel_input.strip() == "0": + print("Selected: (skipped)") + break + + try: + indices = [int(x) for x in sel_input.split()] + if all(0 <= i <= len(neutral_bins) for i in indices): + chosen = [] + for i in indices: + if i != 0: + b = neutral_bins[i - 1] + selected_bins.append(b) + chosen.append(format_value_with_comment(b)) print("Selected: " + ", ".join(chosen)) break except ValueError: diff --git a/PWGCF/Femto/Macros/cutculatorGui.py b/PWGCF/Femto/Macros/cutculatorGui.py new file mode 100755 index 00000000000..db776251e77 --- /dev/null +++ b/PWGCF/Femto/Macros/cutculatorGui.py @@ -0,0 +1,437 @@ +#!/usr/bin/env python3 + +# Copyright 2019-2025 CERN and copyright holders of ALICE O2. +# See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +# All rights not expressly granted are reserved. +# +# This software is distributed under the terms of the GNU General Public +# License v3 (GPL Version 3), copied verbatim in the file "COPYING". +# +# In applying this license CERN does not waive the privileges and immunities +# granted to it by virtue of its status as an Intergovernmental Organization +# or submit itself to any jurisdiction. + +"""! +@brief CutCulator GUI (Compute bitmask for selecting particles in the Femto Framework) +@author Anton Riedel , Technical University of Munich +""" + +import tkinter as tk +from tkinter import ttk, filedialog, messagebox +import argparse +import sys + +try: + import ROOT + + ROOT.gROOT.SetBatch(True) +except ImportError: + ROOT = None + +VALUE_DELIM = "___" +SECTION_DELIM = ":::" + +# ── Colours ────────────────────────────────────────────────────────────────── +BG = "#1e1e2e" +BG_CARD = "#2a2a3e" +BG_HOVER = "#3a3a50" +ACCENT = "#89b4fa" # blue – minimal +ACCENT_OPT = "#a6e3a1" # green – optional +ACCENT_REJ = "#f38ba8" # red – rejection / neutral +FG = "#cdd6f4" +FG_DIM = "#6c7086" +BORDER = "#45475a" +SEL_BG = "#313244" + +FONT_TITLE = ("Inter", 15, "bold") +FONT_HEAD = ("Inter", 11, "bold") +FONT_BODY = ("Inter", 10) +FONT_MONO = ("JetBrains Mono", 11, "bold") +FONT_SMALL = ("Inter", 9) + + +# ── Helpers ─────────────────────────────────────────────────────────────────── +def parse_bin_label(label): + result = {} + for sec in label.split(SECTION_DELIM): + if VALUE_DELIM in sec: + k, v = sec.split(VALUE_DELIM, 1) + result[k.strip()] = v.strip() + return result + + +def format_value_with_comment(b): + val = b.get("Value", "") + comment = b.get("Comment", "") + if comment and comment.upper() != "X": + return f"{val} ({comment})" + return val + + +def bin_type(b): + """Return 'minimal', 'optional', 'neutral', or 'skip'.""" + is_min = b.get("MinimalCut", "0") == "1" + is_opt = b.get("OptionalCut", "0") == "1" + pos = b.get("BitPosition", "X") + if pos.upper() == "X": + return "skip" + if is_min and not is_opt: + return "minimal" + if is_opt: + return "optional" + return "neutral" + + +def load_bins_from_hist(hist): + nbins = hist.GetNbinsX() + bins = [] + for i in range(1, nbins - 2 + 1): + label = hist.GetXaxis().GetBinLabel(i) + if not label: + continue + b = parse_bin_label(label) + b["_bin_index"] = i + bins.append(b) + # group by SelectionName preserving order + groups = {} + for b in bins: + name = b.get("SelectionName", f"unknown_{b['_bin_index']}") + groups.setdefault(name, []).append(b) + return groups + + +# ── Main Application ────────────────────────────────────────────────────────── +class CutCulatorApp(tk.Tk): + def __init__(self, rootfile=None, tdir="femto-producer"): + super().__init__() + self.title("CutCulator") + self.configure(bg=BG) + self.geometry("920x720") + self.minsize(780, 560) + self.resizable(True, True) + + self._rootfile_path = rootfile + self._tdir_path = tdir + self._root_file = None + self._hist = None + self._groups = {} # SelectionName → list[bin_dict] + self._vars = {} # (SelectionName, idx) → BooleanVar + + self._build_ui() + + if rootfile: + self._load_file(rootfile) + + # ── UI skeleton ────────────────────────────────────────────────────────── + def _build_ui(self): + # ── top bar ── + top = tk.Frame(self, bg=BG, pady=10, padx=18) + top.pack(fill="x") + + tk.Label(top, text="✂ CutCulator", font=FONT_TITLE, bg=BG, fg=ACCENT).pack(side="left") + + btn_frame = tk.Frame(top, bg=BG) + btn_frame.pack(side="right") + self._btn_open = self._make_button(btn_frame, "📂 Open ROOT file", self._open_file_dialog, ACCENT) + self._btn_open.pack(side="left", padx=4) + + # ── file + histogram selector bar ── + bar = tk.Frame(self, bg=BG_CARD, pady=8, padx=18) + bar.pack(fill="x") + + tk.Label(bar, text="File:", font=FONT_BODY, bg=BG_CARD, fg=FG_DIM).pack(side="left") + self._lbl_file = tk.Label(bar, text="(none)", font=FONT_BODY, bg=BG_CARD, fg=FG, wraplength=400, anchor="w") + self._lbl_file.pack(side="left", padx=6) + + tk.Label(bar, text="Histogram:", font=FONT_BODY, bg=BG_CARD, fg=FG_DIM).pack(side="left", padx=(20, 0)) + self._hist_var = tk.StringVar() + self._hist_combo = ttk.Combobox(bar, textvariable=self._hist_var, state="disabled", width=30, font=FONT_BODY) + self._hist_combo.pack(side="left", padx=6) + self._hist_combo.bind("<>", self._on_hist_selected) + + self._style_combobox() + + # ── legend ── + legend = tk.Frame(self, bg=BG, pady=4, padx=18) + legend.pack(fill="x") + for color, label in [(ACCENT, "Minimal"), (ACCENT_OPT, "Optional"), (ACCENT_REJ, "Neutral")]: + dot = tk.Label(legend, text="●", font=FONT_BODY, bg=BG, fg=color) + dot.pack(side="left") + tk.Label(legend, text=label, font=FONT_SMALL, bg=BG, fg=FG_DIM).pack(side="left", padx=(2, 12)) + + # ── scrollable selection area ── + outer = tk.Frame(self, bg=BG) + outer.pack(fill="both", expand=True, padx=12, pady=4) + + self._canvas = tk.Canvas(outer, bg=BG, highlightthickness=0, bd=0) + vsb = ttk.Scrollbar(outer, orient="vertical", command=self._canvas.yview) + self._canvas.configure(yscrollcommand=vsb.set) + vsb.pack(side="right", fill="y") + self._canvas.pack(side="left", fill="both", expand=True) + + self._inner = tk.Frame(self._canvas, bg=BG) + self._canvas_win = self._canvas.create_window((0, 0), window=self._inner, anchor="nw") + self._inner.bind("", self._on_inner_configure) + self._canvas.bind("", self._on_canvas_configure) + self._canvas.bind_all("", self._on_mousewheel) + self._canvas.bind_all("", self._on_mousewheel) + self._canvas.bind_all("", self._on_mousewheel) + + # ── bottom result bar ── + bottom = tk.Frame(self, bg=BG_CARD, pady=10, padx=18) + bottom.pack(fill="x", side="bottom") + + tk.Label(bottom, text="Bitmask:", font=FONT_HEAD, bg=BG_CARD, fg=FG).pack(side="left") + + self._lbl_dec = tk.Label(bottom, text="—", font=FONT_MONO, bg=BG_CARD, fg=ACCENT, width=14, anchor="w") + self._lbl_dec.pack(side="left", padx=8) + + self._lbl_hex = tk.Label(bottom, text="—", font=FONT_MONO, bg=BG_CARD, fg=ACCENT_OPT, width=14, anchor="w") + self._lbl_hex.pack(side="left", padx=8) + + self._lbl_bin = tk.Label(bottom, text="—", font=FONT_MONO, bg=BG_CARD, fg=FG_DIM, anchor="w") + self._lbl_bin.pack(side="left", padx=8) + + copy_frame = tk.Frame(bottom, bg=BG_CARD) + copy_frame.pack(side="right") + self._make_button(copy_frame, "Copy Dec", lambda: self._copy(self._lbl_dec["text"]), ACCENT).pack( + side="left", padx=3 + ) + self._make_button(copy_frame, "Copy Hex", lambda: self._copy(self._lbl_hex["text"]), ACCENT_OPT).pack( + side="left", padx=3 + ) + + # ── Combobox styling ────────────────────────────────────────────────────── + def _style_combobox(self): + s = ttk.Style(self) + s.theme_use("clam") + s.configure( + "TCombobox", + fieldbackground=BG_CARD, + background=BG_CARD, + foreground=FG, + selectbackground=SEL_BG, + selectforeground=FG, + bordercolor=BORDER, + arrowcolor=ACCENT, + ) + s.map("TCombobox", fieldbackground=[("readonly", BG_CARD)]) + s.configure("TScrollbar", troughcolor=BG, background=BORDER) + + # ── Canvas resize helpers ───────────────────────────────────────────────── + def _on_inner_configure(self, _e=None): + self._canvas.configure(scrollregion=self._canvas.bbox("all")) + + def _on_canvas_configure(self, e): + self._canvas.itemconfig(self._canvas_win, width=e.width) + + def _on_mousewheel(self, e): + if e.num == 4: + self._canvas.yview_scroll(-1, "units") + elif e.num == 5: + self._canvas.yview_scroll(1, "units") + else: + self._canvas.yview_scroll(int(-1 * (e.delta / 120)), "units") + + # ── File / histogram loading ────────────────────────────────────────────── + def _open_file_dialog(self): + path = filedialog.askopenfilename( + title="Open ROOT file", filetypes=[("ROOT files", "*.root"), ("All files", "*.*")] + ) + if path: + self._load_file(path) + + def _load_file(self, path): + if ROOT is None: + messagebox.showerror("Missing dependency", "PyROOT is not available. Please install ROOT.") + return + f = ROOT.TFile.Open(path) + if not f or f.IsZombie(): + messagebox.showerror("Error", f"Cannot open ROOT file:\n{path}") + return + self._root_file = f + self._lbl_file.config(text=path) + + d = f.Get(self._tdir_path) + if not d: + messagebox.showerror("Error", f"Directory '{self._tdir_path}' not found in file.") + return + + histograms = [k.GetName() for k in d.GetListOfKeys() if k.ReadObj().InheritsFrom("TH1")] + if not histograms: + messagebox.showwarning("Warning", "No TH1 histograms found in directory.") + return + + self._hist_combo.config(values=histograms, state="readonly") + self._hist_combo.current(0) + self._on_hist_selected() + + def _on_hist_selected(self, _e=None): + if self._root_file is None: + return + d = self._root_file.Get(self._tdir_path) + if not d: + return + hname = self._hist_var.get() + hist = d.Get(hname) + if not hist: + return + self._hist = hist + self._groups = load_bins_from_hist(hist) + self._vars = {} + self._build_selections() + self._update_bitmask() + + # ── Selection cards ─────────────────────────────────────────────────────── + def _build_selections(self): + for w in self._inner.winfo_children(): + w.destroy() + + for sel_name, group in self._groups.items(): + self._build_group_card(sel_name, group) + + self._on_inner_configure() + + def _build_group_card(self, sel_name, group): + # categorise + minimal = [(i, b) for i, b in enumerate(group) if bin_type(b) == "minimal"] + optional = [(i, b) for i, b in enumerate(group) if bin_type(b) == "optional"] + neutral = [(i, b) for i, b in enumerate(group) if bin_type(b) == "neutral"] + + if not (minimal or optional or neutral): + return # nothing to show (all "skip") + + card = tk.Frame(self._inner, bg=BG_CARD, bd=0, highlightthickness=1, highlightbackground=BORDER) + card.pack(fill="x", padx=10, pady=5, ipadx=8, ipady=6) + + # header row + hdr = tk.Frame(card, bg=BG_CARD) + hdr.pack(fill="x", padx=6, pady=(4, 2)) + tk.Label(hdr, text=sel_name, font=FONT_HEAD, bg=BG_CARD, fg=FG).pack(side="left") + + # show the loosest (most permissive) minimal threshold as a hint. + # the truly loosest threshold has mSkipMostPermissiveBit=true so its + # BitPosition is "X" — it lands in the "skip" category. check there first, + # then fall back to the loosest bit-carrying minimal bin. + skipped_minimal = [ + b for b in group if b.get("MinimalCut", "0") == "1" and b.get("BitPosition", "X").upper() == "X" + ] + if skipped_minimal: + loosest_val = format_value_with_comment(skipped_minimal[0]) + tk.Label( + hdr, text=f"minimal cut → loosest selection: {loosest_val}", font=FONT_SMALL, bg=BG_CARD, fg=FG_DIM + ).pack(side="left", padx=10) + elif minimal: + loosest_val = format_value_with_comment(minimal[0][1]) + tk.Label( + hdr, text=f"minimal cut → loosest selection: {loosest_val}", font=FONT_SMALL, bg=BG_CARD, fg=FG_DIM + ).pack(side="left", padx=10) + elif optional: + tk.Label(hdr, text="optional", font=FONT_SMALL, bg=BG_CARD, fg=ACCENT_OPT).pack(side="left", padx=10) + elif neutral: + tk.Label(hdr, text="neutral", font=FONT_SMALL, bg=BG_CARD, fg=ACCENT_REJ).pack(side="left", padx=10) + + # separator + tk.Frame(card, bg=BORDER, height=1).pack(fill="x", padx=6, pady=2) + + # bins + bins_frame = tk.Frame(card, bg=BG_CARD) + bins_frame.pack(fill="x", padx=6, pady=4) + + for i, b in minimal: + self._build_bin_row(bins_frame, sel_name, i, b, "minimal") + for i, b in optional: + self._build_bin_row(bins_frame, sel_name, i, b, "optional") + for i, b in neutral: + self._build_bin_row(bins_frame, sel_name, i, b, "neutral") + + def _build_bin_row(self, parent, sel_name, idx, b, kind): + color = {"minimal": ACCENT, "optional": ACCENT_OPT, "neutral": ACCENT_REJ}[kind] + label_text = format_value_with_comment(b) + + var = tk.BooleanVar(value=False) + + self._vars[(sel_name, idx)] = var + + row = tk.Frame(parent, bg=BG_CARD) + row.pack(fill="x", pady=1) + + # coloured dot + tk.Label(row, text="●", font=FONT_BODY, bg=BG_CARD, fg=color).pack(side="left", padx=(0, 4)) + + # checkbox styled as a toggle button + cb = tk.Checkbutton( + row, + text=label_text, + variable=var, + font=FONT_BODY, + bg=BG_CARD, + fg=FG, + activebackground=BG_HOVER, + activeforeground=FG, + selectcolor=SEL_BG, + relief="flat", + bd=0, + highlightthickness=0, + cursor="hand2", + command=self._update_bitmask, + ) + cb.pack(side="left", fill="x", expand=True) + + # bit-position badge + pos = b.get("BitPosition", "X") + if pos.upper() != "X": + tk.Label(row, text=f"bit {pos}", font=FONT_SMALL, bg=BG_CARD, fg=FG_DIM, width=8).pack(side="right", padx=4) + + # ── Bitmask computation ─────────────────────────────────────────────────── + def _update_bitmask(self): + bitmask = 0 + for (sel_name, idx), var in self._vars.items(): + if not var.get(): + continue + b = self._groups[sel_name][idx] + pos = b.get("BitPosition", "X") + if pos.upper() == "X": + continue + bitmask |= 1 << int(pos) + + self._lbl_dec.config(text=str(bitmask)) + self._lbl_hex.config(text=hex(bitmask)) + self._lbl_bin.config(text=bin(bitmask)) + + # ── Utilities ───────────────────────────────────────────────────────────── + def _copy(self, text): + self.clipboard_clear() + self.clipboard_append(text) + self.update() + + @staticmethod + def _make_button(parent, text, cmd, color): + return tk.Button( + parent, + text=text, + command=cmd, + font=FONT_BODY, + bg=BG_CARD, + fg=color, + activebackground=BG_HOVER, + activeforeground=color, + relief="flat", + bd=0, + padx=10, + pady=4, + highlightthickness=1, + highlightbackground=color, + cursor="hand2", + ) + + +# ── Entry point ─────────────────────────────────────────────────────────────── +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="CutCulator GUI") + parser.add_argument("rootfile", nargs="?", default=None, help="Path to ROOT file (optional, can be opened via GUI)") + parser.add_argument("--dir", default="femto-producer", help="TDirectory path in ROOT file") + args = parser.parse_args() + + app = CutCulatorApp(rootfile=args.rootfile, tdir=args.dir) + app.mainloop() From 0e1a8de1d6756637a50c96c69e9d30fe74219d85 Mon Sep 17 00:00:00 2001 From: Victor Gonzalez Date: Thu, 5 Mar 2026 03:25:04 +0100 Subject: [PATCH 175/347] [PWGCF] DptDpt - Fine tune on the fly initialization (#15269) Co-authored-by: Victor --- PWGCF/TableProducer/dptDptFilter.cxx | 22 ++++++++------- PWGCF/TableProducer/dptDptFilter.h | 40 +++++++++++++++------------- 2 files changed, 35 insertions(+), 27 deletions(-) diff --git a/PWGCF/TableProducer/dptDptFilter.cxx b/PWGCF/TableProducer/dptDptFilter.cxx index 86db0a8ce95..81b811da6c0 100644 --- a/PWGCF/TableProducer/dptDptFilter.cxx +++ b/PWGCF/TableProducer/dptDptFilter.cxx @@ -434,24 +434,28 @@ struct Multiplicity { if (fhCL1EtaGapMultiplicity != nullptr) { fhCL1EtaGapMultiplicity->Fill(cl1EtaGapM, dNchdEta); } + /* if there is not calibration assign 50% mutltiplicity */ + if (fhV0MMultPercentile == nullptr && fhCL1MultPercentile == nullptr && fhCL1EtaGapMultPercentile == nullptr) { + multiplicityClass = 50; + } switch (classestimator) { case kV0M: if (fhV0MMultPercentile != nullptr) { multiplicityClass = fhV0MMultPercentile->GetBinContent(fhV0MMultPercentile->FindFixBin(v0am + v0cm)); - multiplicity = v0am + v0cm; } + multiplicity = v0am + v0cm; break; case kCL1: if (fhCL1MultPercentile != nullptr) { multiplicityClass = fhCL1MultPercentile->GetBinContent(fhCL1MultPercentile->FindFixBin(cl1m)); - multiplicity = cl1m; } + multiplicity = cl1m; break; case kCL1GAP: if (fhCL1EtaGapMultPercentile != nullptr) { multiplicityClass = fhCL1EtaGapMultPercentile->GetBinContent(fhCL1EtaGapMultPercentile->FindFixBin(cl1EtaGapM)); - multiplicity = cl1EtaGapM; } + multiplicity = cl1EtaGapM; break; default: break; @@ -639,10 +643,10 @@ struct DptDptFilter { triggerSelectionFlags = getTriggerSelection(cfgEventSelection.triggSel.value.c_str()); traceCollId0 = cfgTraceCollId0; - /* get the system type */ + /* get the data type and the system type */ + fDataType = getDataType(cfgDataType); fSystem = getSystemType(cfgSystemForPeriod.value); fLhcRun = multRunForSystemMap.at(fSystem); - fDataType = getDataType(cfgDataType); /* the multiplicities outliers exclusion */ multiplicityCentralityCorrelationsExclusion = getExclusionFormula(cfgEventSelection.multiplicitiesExclusionFormula->getData()[fSystem][0].c_str()); @@ -1200,13 +1204,13 @@ struct DptDptFilterTracks { tpcExcluder = TpcExcludeTrack(tpcExclude); tpcExcluder.setCuts(pLowCut, pUpCut, nLowCut, nUpCut); - /* self configure system type and data type */ - o2::framework::LabeledArray tmpLabeledArray = {}; - getTaskOptionValue(initContext, "dpt-dpt-filter", "cfgSystemForPeriod", tmpLabeledArray, false); - fSystem = getSystemType(tmpLabeledArray); + /* self configure data type and system */ std::string tmpstr; getTaskOptionValue(initContext, "dpt-dpt-filter", "cfgDataType", tmpstr, false); fDataType = getDataType(tmpstr); + o2::framework::LabeledArray tmpLabeledArray = {}; + getTaskOptionValue(initContext, "dpt-dpt-filter", "cfgSystemForPeriod", tmpLabeledArray, false); + fSystem = getSystemType(tmpLabeledArray); /* required ambiguous tracks checks? */ if (dofilterDetectorLevelWithoutPIDAmbiguous || dofilterDetectorLevelWithPIDAmbiguous || dofilterDetectorLevelWithFullPIDAmbiguous || diff --git a/PWGCF/TableProducer/dptDptFilter.h b/PWGCF/TableProducer/dptDptFilter.h index 1d431bbde3f..d584938e927 100644 --- a/PWGCF/TableProducer/dptDptFilter.h +++ b/PWGCF/TableProducer/dptDptFilter.h @@ -896,27 +896,31 @@ inline std::bitset<32> getTriggerSelection(std::string_view const& triggstr) inline SystemType getSystemType(auto const& periodsForSysType) { - auto period = metadataInfo.get("LPMProductionTag"); - auto anchoredPeriod = metadataInfo.get("AnchorProduction"); - bool checkAnchor = anchoredPeriod.length() > 0; - - for (SystemType sT = SystemNoSystem; sT < SystemNoOfSystems; ++sT) { - const std::string& periods = periodsForSysType[static_cast(sT)][0]; - auto contains = [periods](auto const& period) { - if (periods.find(period) != std::string::npos) { - return true; - } - return false; - }; - if (periods.length() > 0) { - if (contains(period) || (checkAnchor && contains(anchoredPeriod))) { - LOGF(info, "DptDptCorrelations::getSystemType(). Assigned system type %s for period %s", systemExternalNamesMap.at(static_cast(sT)).data(), period.c_str()); - return sT; + if (fDataType != kOnTheFly) { + auto period = metadataInfo.get("LPMProductionTag"); + auto anchoredPeriod = metadataInfo.get("AnchorProduction"); + bool checkAnchor = anchoredPeriod.length() > 0; + + for (SystemType sT = SystemNoSystem; sT < SystemNoOfSystems; ++sT) { + const std::string& periods = periodsForSysType[static_cast(sT)][0]; + auto contains = [periods](auto const& period) { + if (periods.find(period) != std::string::npos) { + return true; + } + return false; + }; + if (periods.length() > 0) { + if (contains(period) || (checkAnchor && contains(anchoredPeriod))) { + LOGF(info, "DptDptCorrelations::getSystemType(). Assigned system type %s for period %s", systemExternalNamesMap.at(static_cast(sT)).data(), period.c_str()); + return sT; + } } } + LOGF(fatal, "DptDptCorrelations::getSystemType(). No system type for period: %s", period.c_str()); + return SystemPbPb; + } else { + return SystemNeNeRun3; } - LOGF(fatal, "DptDptCorrelations::getSystemType(). No system type for period: %s", period.c_str()); - return SystemPbPb; } /// \brief Type of data according to the configuration string From c3ada3aa6402523a8f3b4c42a6d3dc9fee48208b Mon Sep 17 00:00:00 2001 From: Oton Vazquez Doce Date: Thu, 5 Mar 2026 07:06:32 +0100 Subject: [PATCH 176/347] [Infrastructure] Update CODEOWNERS (#15271) --- CODEOWNERS | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CODEOWNERS b/CODEOWNERS index 89a96d4faea..f2ea6f38a0b 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -33,9 +33,9 @@ /PWGCF @alibuild @victor-gonzalez @otonvd @shouqiye /PWGCF/Core @alibuild @jgrosseo -/PWGCF/DataModel @alibuild @jgrosseo @victor-gonzalez @otonvd @shouqiye -/PWGCF/TableProducer @alibuild @jgrosseo @victor-gonzalez @otonvd @shouqiye -/PWGCF/Tasks @alibuild @jgrosseo @victor-gonzalez @otonvd @shouqiye +/PWGCF/DataModel @alibuild @jgrosseo @jaelpark @victor-gonzalez @otonvd @shouqiye +/PWGCF/TableProducer @alibuild @jgrosseo @jaelpark @victor-gonzalez @otonvd @shouqiye +/PWGCF/Tasks @alibuild @jgrosseo @jaelpark @victor-gonzalez @otonvd @shouqiye /PWGCF/EbyEFluctuations @alibuild @SwatiSaha-1997 @isputows @victor-gonzalez @otonvd @shouqiye /PWGCF/Femto @alibuild @lauraser @ariedel-cern @dimihayl @victor-gonzalez @otonvd @shouqiye /PWGCF/FemtoDream @alibuild @lauraser @ariedel-cern @dimihayl @victor-gonzalez @otonvd @shouqiye From 3ea952df2a6dc844eb09022cb2432f02d871592a Mon Sep 17 00:00:00 2001 From: ypwangg <142303052+ypwangg@users.noreply.github.com> Date: Thu, 5 Mar 2026 15:56:35 +0800 Subject: [PATCH 177/347] [PWGDQ] Comment out cout statements for bimodality coefficients (#15256) --- PWGDQ/Core/VarManager.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/PWGDQ/Core/VarManager.h b/PWGDQ/Core/VarManager.h index 389050980e2..8731bdc4401 100644 --- a/PWGDQ/Core/VarManager.h +++ b/PWGDQ/Core/VarManager.h @@ -2448,7 +2448,7 @@ void VarManager::FillEventTracks(T const& tracks, float* values) values[kDCAzBimodalityCoefficientBinned] = -9999.0; } values[kDCAzNPeaks] = nPeaksBin; - cout << "Bimodality coefficient binned: " << bimodalityCoefficientBin << ", mean: " << mean << ", stddev: " << stddev << ", skewness: " << skewness << ", kurtosis: " << kurtosis << ", nPeaks: " << nPeaksBin << endl; + // cout << "Bimodality coefficient binned: " << bimodalityCoefficientBin << ", mean: " << mean << ", stddev: " << stddev << ", skewness: " << skewness << ", kurtosis: " << kurtosis << ", nPeaks: " << nPeaksBin << endl; // compute the binned bimodality coefficient and related statistics with a bin width of 50um and different trimming versions // more then 3 counts per bin auto [bimodalityCoefficientBinTrimmed1, meanBinTrimmed1, stddevBinTrimmed1, skewnessBinTrimmed1, kurtosisBinTrimmed1, nPeaksBinTrimmed1] = BimodalityCoefficientAndNPeaks(dcazValues, 0.005, 4); @@ -2462,7 +2462,7 @@ void VarManager::FillEventTracks(T const& tracks, float* values) values[kDCAzRMSBinnedTrimmed1] = -9999.0; } values[kDCAzNPeaksTrimmed1] = nPeaksBinTrimmed1; - cout << "Bimodality coefficient (trimmed 1): " << bimodalityCoefficientBinTrimmed1 << ", mean: " << meanBinTrimmed1 << ", stddev: " << stddevBinTrimmed1 << ", skewness: " << skewnessBinTrimmed1 << ", kurtosis: " << kurtosisBinTrimmed1 << ", nPeaks: " << nPeaksBinTrimmed1 << endl; + // cout << "Bimodality coefficient (trimmed 1): " << bimodalityCoefficientBinTrimmed1 << ", mean: " << meanBinTrimmed1 << ", stddev: " << stddevBinTrimmed1 << ", skewness: " << skewnessBinTrimmed1 << ", kurtosis: " << kurtosisBinTrimmed1 << ", nPeaks: " << nPeaksBinTrimmed1 << endl; // more than 3% of the entries per peak auto [bimodalityCoefficientBinTrimmed2, meanBinTrimmed2, stddevBinTrimmed2, skewnessBinTrimmed2, kurtosisBinTrimmed2, nPeaksBinTrimmed2] = BimodalityCoefficientAndNPeaks(dcazValues, 0.005, -100); if (stddevBinTrimmed2 > -1.0) { @@ -2475,7 +2475,7 @@ void VarManager::FillEventTracks(T const& tracks, float* values) values[kDCAzRMSBinnedTrimmed2] = -9999.0; } values[kDCAzNPeaksTrimmed2] = nPeaksBinTrimmed2; - cout << "Bimodality coefficient (trimmed 2): " << bimodalityCoefficientBinTrimmed2 << ", mean: " << meanBinTrimmed2 << ", stddev: " << stddevBinTrimmed2 << ", skewness: " << skewnessBinTrimmed2 << ", kurtosis: " << kurtosisBinTrimmed2 << ", nPeaks: " << nPeaksBinTrimmed2 << endl; + // cout << "Bimodality coefficient (trimmed 2): " << bimodalityCoefficientBinTrimmed2 << ", mean: " << meanBinTrimmed2 << ", stddev: " << stddevBinTrimmed2 << ", skewness: " << skewnessBinTrimmed2 << ", kurtosis: " << kurtosisBinTrimmed2 << ", nPeaks: " << nPeaksBinTrimmed2 << endl; // more than 5% of the entries per peak auto [bimodalityCoefficientBinTrimmed3, meanBinTrimmed3, stddevBinTrimmed3, skewnessBinTrimmed3, kurtosisBinTrimmed3, nPeaksBinTrimmed3] = BimodalityCoefficientAndNPeaks(dcazValues, 0.005, -20); if (stddevBinTrimmed3 > -1.0) { @@ -2488,7 +2488,7 @@ void VarManager::FillEventTracks(T const& tracks, float* values) values[kDCAzRMSBinnedTrimmed3] = -9999.0; } values[kDCAzNPeaksTrimmed3] = nPeaksBinTrimmed3; - cout << "Bimodality coefficient (trimmed 3): " << bimodalityCoefficientBinTrimmed3 << ", mean: " << meanBinTrimmed3 << ", stddev: " << stddevBinTrimmed3 << ", skewness: " << skewnessBinTrimmed3 << ", kurtosis: " << kurtosisBinTrimmed3 << ", nPeaks: " << nPeaksBinTrimmed3 << endl; + // cout << "Bimodality coefficient (trimmed 3): " << bimodalityCoefficientBinTrimmed3 << ", mean: " << meanBinTrimmed3 << ", stddev: " << stddevBinTrimmed3 << ", skewness: " << skewnessBinTrimmed3 << ", kurtosis: " << kurtosisBinTrimmed3 << ", nPeaks: " << nPeaksBinTrimmed3 << endl; // compute fraction of tracks with |DCAz| > 100um, 200um, 500um, 1mm, 2mm, 5mm, 10mm // make a loop over the DCAz values and count how many are above each threshold From e7cc586acdcf58eb00b17df75ea448856d30be93 Mon Sep 17 00:00:00 2001 From: alcaliva <32872606+alcaliva@users.noreply.github.com> Date: Thu, 5 Mar 2026 09:25:26 +0100 Subject: [PATCH 178/347] [PWGLF] Add function to compute jet pt resolution (#15268) --- PWGLF/Tasks/Nuspex/antinucleiInJets.cxx | 160 ++++++++++++++++++++++++ 1 file changed, 160 insertions(+) diff --git a/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx b/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx index c055f5c2e2c..cedb442bd4e 100644 --- a/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx +++ b/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx @@ -128,6 +128,13 @@ struct ReducedParticle { } }; +// Jet Matching +struct JetMatching { + double distance; + double ptTrue; + double ptDiff; +}; + struct AntinucleiInJets { // Histogram registries for data, MC, quality control, multiplicity and correlations @@ -145,6 +152,7 @@ struct AntinucleiInJets { Configurable cfgAreaFrac{"cfgAreaFrac", 0.6, "fraction of jet area"}; Configurable cfgEtaJetMax{"cfgEtaJetMax", 0.5, "max jet eta"}; Configurable cfgMinPtTrack{"cfgMinPtTrack", 0.15, "minimum pt of tracks for jet reconstruction"}; + Configurable alpha{"alpha", 0.3, "parameter to control jet matching"}; // Event selection criteria Configurable rejectITSROFBorder{"rejectITSROFBorder", true, "Reject events near the ITS ROF border"}; @@ -501,6 +509,11 @@ struct AntinucleiInJets { registryMC.add("antiproton_coal_ue", "antiproton_coal_ue", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); } + // jet pt resolution + if (doprocessJetPtResolution) { + registryMC.add("jetPtResolution", "jet Pt Resolution", HistType::kTH2F, {{200, 0, 20, "#it{p}^{jet}_{T,true} (GeV/#it{c})"}, {1000, -5, 5, "#Delta #it{p}^{jet}_{T} (GeV/#it{c})"}}); + } + // Coalescence and Correlation analysis if (doprocessCoalescenceCorr) { @@ -3912,6 +3925,153 @@ struct AntinucleiInJets { } } PROCESS_SWITCH(AntinucleiInJets, processCoalescenceCorr, "process coalescence correlation", false); + + // Jet Pt resolution + void processJetPtResolution(RecCollisionsMc const& collisions, AntiNucleiTracksMc const& mcTracks, aod::McParticles const& mcParticles) + { + // Define per-event particle containers + std::vector fjParticles; + std::vector fjTracks; + + // Jet and area definitions + fastjet::JetDefinition jetDef(fastjet::antikt_algorithm, rJet); + fastjet::AreaDefinition areaDef(fastjet::active_area, fastjet::GhostedAreaSpec(1.0)); + + // Loop over all reconstructed collisions + for (const auto& collision : collisions) { + + // Clear containers at the start of the event loop + fjParticles.clear(); + fjTracks.clear(); + + // Reject reconstructed collisions with no simulated collision + if (!collision.has_mcCollision()) + continue; + + // Apply event selection: require sel8 and vertex position to be within the allowed z range + if (!collision.sel8() || std::fabs(collision.posZ()) > zVtx) + continue; + + // Reject events near the ITS Read-Out Frame border + if (rejectITSROFBorder && !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) + continue; + + // Reject events at the Time Frame border + if (rejectTFBorder && !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) + continue; + + // Require at least one ITS-TPC matched track + if (requireVtxITSTPC && !collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) + continue; + + // Reject events with same-bunch pileup + if (rejectSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) + continue; + + // Require consistent FT0 vs PV z-vertex + if (requireIsGoodZvtxFT0VsPV && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) + continue; + + // Require TOF match for at least one vertex track + if (requireIsVertexTOFmatched && !collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) + continue; + + // Get tracks and particles in this MC collision + const auto mcTracksThisMcColl = mcTracks.sliceBy(mcTracksPerMcCollision, collision.globalIndex()); + const auto mcParticlesThisMcColl = mcParticles.sliceBy(mcParticlesPerMcCollision, collision.globalIndex()); + + // Loop over reconstructed tracks + for (auto const& track : mcTracksThisMcColl) { + + // Apply track selection for jet reconstruction + if (!passedTrackSelectionForJetReconstruction(track)) + continue; + + // 4-momentum representation of a particle + fastjet::PseudoJet fourMomentum(track.px(), track.py(), track.pz(), track.energy(MassPionCharged)); + fjTracks.emplace_back(fourMomentum); + } + + // Loop over MC particles + for (const auto& particle : mcParticlesThisMcColl) { + + // Select physical primary particles or HF decay products + if (!isPhysicalPrimaryOrFromHF(particle, mcParticles)) + continue; + + // Select particles within acceptance + if (particle.eta() < minEta || particle.eta() > maxEta || particle.pt() < cfgMinPtTrack) + continue; + + // 4-momentum representation of a particle + double energy = std::sqrt(particle.p() * particle.p() + MassPionCharged * MassPionCharged); + fastjet::PseudoJet fourMomentum(particle.px(), particle.py(), particle.pz(), energy); + fjParticles.emplace_back(fourMomentum); + } + + // Reject empty events + if (fjTracks.empty() || fjParticles.empty()) + continue; + + // Cluster particles using the anti-kt algorithm + fastjet::ClusterSequenceArea csRec(fjTracks, jetDef, areaDef); + std::vector jetsRec = fastjet::sorted_by_pt(csRec.inclusive_jets()); + + fastjet::ClusterSequenceArea csGen(fjParticles, jetDef, areaDef); + std::vector jetsGen = fastjet::sorted_by_pt(csGen.inclusive_jets()); + + // Loop over reconstructed jets + std::vector jetGenRec; + for (const auto& jetRec : jetsRec) { + + // Jet must be fully contained in the acceptance + if ((std::fabs(jetRec.eta()) + rJet) > (maxEta - deltaEtaEdge)) + continue; + + // Apply area cut if required + if (applyAreaCut && (jetRec.area() / (PI * rJet * rJet)) > maxNormalizedJetArea) + continue; + + // Clear jet-pair container + jetGenRec.clear(); + + for (const auto& jetGen : jetsGen) { + + // Jet must be fully contained in the acceptance + if ((std::fabs(jetGen.eta()) + rJet) > (maxEta - deltaEtaEdge)) + continue; + + // Apply area cut if required + if (applyAreaCut && (jetGen.area() / (PI * rJet * rJet)) > maxNormalizedJetArea) + continue; + + double deltaEta = jetGen.eta() - jetRec.eta(); + double deltaPhi = getDeltaPhi(jetGen.phi(), jetRec.phi()); + double deltaR = std::sqrt(deltaEta * deltaEta + deltaPhi * deltaPhi); + if (deltaR < rJet) + jetGenRec.push_back({deltaR, jetGen.pt(), jetGen.pt() - jetRec.pt()}); + } + if (jetGenRec.empty()) + continue; + + double distanceMin(1e+06); + double diffPt(0); + double ptJetTrue(0); + for (const auto& jetPair : jetGenRec) { + if (jetPair.distance < distanceMin) { + distanceMin = jetPair.distance; + diffPt = jetPair.ptDiff; + ptJetTrue = jetPair.ptTrue; + } + } + + if (distanceMin < alpha * rJet) { + registryMC.fill(HIST("jetPtResolution"), ptJetTrue, diffPt); + } + } + } + } + PROCESS_SWITCH(AntinucleiInJets, processJetPtResolution, "process jet pt resolution", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) From 43831545ce11c140ae03b1719d02ce80ac3bc27d Mon Sep 17 00:00:00 2001 From: somabhatta <48771326+somabhatta@users.noreply.github.com> Date: Thu, 5 Mar 2026 11:09:44 +0100 Subject: [PATCH 179/347] [PWGCF] DCA cut for global tracks (#15248) --- .../Tasks/radialFlowDecorr.cxx | 2014 +++++++++++------ 1 file changed, 1259 insertions(+), 755 deletions(-) diff --git a/PWGCF/EbyEFluctuations/Tasks/radialFlowDecorr.cxx b/PWGCF/EbyEFluctuations/Tasks/radialFlowDecorr.cxx index 31f9d1b9d6e..33b16fb7c06 100644 --- a/PWGCF/EbyEFluctuations/Tasks/radialFlowDecorr.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/radialFlowDecorr.cxx @@ -13,12 +13,13 @@ /// \brief Analysis task for event-by-event radial-flow decorrelation measurement. /// \author Somadutta Bhatta -#include "Common/Core/RecoDecay.h" +#include "Common/Core/TrackSelection.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/FT0Corrected.h" #include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponseITS.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" @@ -38,6 +39,7 @@ #include "Framework/runDataProcessing.h" #include "MathUtils/Utils.h" #include "ReconstructionDataFormats/DCA.h" +#include "ReconstructionDataFormats/PID.h" #include "ReconstructionDataFormats/Track.h" #include "ReconstructionDataFormats/TrackTPCITS.h" @@ -58,6 +60,7 @@ #include #include #include +#include #include #include #include @@ -71,6 +74,11 @@ using namespace constants::math; struct RadialFlowDecorr { + static constexpr int KPidPionOne = 1; + static constexpr int KPidKaonTwo = 2; + static constexpr int KPidProtonThree = 3; + static constexpr int KConstTen = 10; + static constexpr int KnFt0cCell = 96; static constexpr int KIntM = 3; static constexpr int KIntK = 3; @@ -79,7 +87,6 @@ struct RadialFlowDecorr { static constexpr int KPiPlus = 211; static constexpr int KKPlus = 321; static constexpr int KProton = 2212; - static constexpr int KNsp = 10; static constexpr float KBinOffset = 0.5f; static constexpr float KPhiMin = 0.f; static constexpr int KNbinsZvtx = 240; @@ -88,7 +95,7 @@ struct RadialFlowDecorr { static constexpr float KPMin = 0.f; static constexpr float KPMax = 10.f; static constexpr int KNbinsPt = 200; - static constexpr float KPtMin = 0.f; + static constexpr float KPtMin = 0.15f; static constexpr float KPtMax = 10.f; static constexpr float KEtaMin = -1.2f; static constexpr float KEtaMax = 1.2f; @@ -108,25 +115,38 @@ struct RadialFlowDecorr { static constexpr int KNbinsDca = 400; static constexpr float KDcaMax = 0.2f; static constexpr float KCentMax = 90; - enum PID { - kInclusive = 0, // Suffix "" - kPiMinus, // Suffix "_PiMinus" - kPiPlus, // Suffix "_PiPlus" - kPiAll, // Suffix "_PiAll" - kKaMinus, // Suffix "_KaMinus" - kKaPlus, // Suffix "_KaPlus" - kKaAll, // Suffix "_KaAll" - kAntiProton, // Suffix "_AntiPr" - kProton, // Suffix "_Pr" - kAllProton, // Suffix "_AllPr" - kNumPID // Total: 10 + + enum PIDIdx { + kInclusiveIdx = 0, + kPiMinusIdx, + kPiPlusIdx, + kPiAllIdx, + kKaMinusIdx, + kKaPlusIdx, + kKaAllIdx, + kAntiPrIdx, + kPrIdx, + kPrAllIdx, + KNsp + }; + + const std::vector pidSuffix = {"", "_PiMinus", "_PiPlus", "_PiAll", "_KaMinus", "_KaPlus", "_KaAll", "_AntiPr", "_Pr", "_PrAll"}; + + struct PIDMeanSigmaMap { + static constexpr int MaxCentBins = 100; + double meanTOF[KNsp][MaxCentBins] = {{0.0}}; + double sigmaTOF[KNsp][MaxCentBins] = {{1.0}}; // Default sigma = 1 + double meanTPC[KNsp][MaxCentBins] = {{0.0}}; + double sigmaTPC[KNsp][MaxCentBins] = {{1.0}}; // Default sigma = 1 }; - const std::vector pidSuffix = {"", "_PiMinus", "_PiPlus", "_PiAll", "_KaMinus", "_KaPlus", "_KaAll", "_AntiPr", "_Pr", "_AllPr"}; + PIDMeanSigmaMap* pidMeanSigmaMap = nullptr; enum ECentralityEstimator { kCentFT0C = 1, - kCentFV0A = 2 + kCentFT0M = 2, + kCentFDDM = 3, + kCentFV0A = 4 }; enum SystemType { kPbPb = 1, @@ -144,21 +164,26 @@ struct RadialFlowDecorr { Configurable cfgVtxZCut{"cfgVtxZCut", 10.f, "z-vertex range"}; Configurable cfgPtMin{"cfgPtMin", 0.2f, "min pT"}; - Configurable cfgPtMax{"cfgPtMax", 10.0f, "max pT"}; + Configurable cfgPtMax{"cfgPtMax", 5.0f, "max pT"}; Configurable cfgEtaCut{"cfgEtaCut", 0.8f, "|η| cut"}; - Configurable cfgDCAXY{"cfgDCAXY", 2.4f, "DCAxy cut"}; - Configurable cfgDCAZ{"cfgDCAZ", 3.2f, "DCAz cut"}; Configurable cfgTPCClsMin{"cfgTPCClsMin", 70.f, "min TPC clusters"}; Configurable cfgChi2TPCMax{"cfgChi2TPCMax", 4.0f, "max TPC χ²"}; Configurable cfgCutTpcChi2NCl{"cfgCutTpcChi2NCl", 2.5f, "Maximum TPCchi2NCl"}; Configurable cfgCutItsChi2NCl{"cfgCutItsChi2NCl", 36.0f, "Maximum ITSchi2NCl"}; - - Configurable cfgPIDnSigmaCut{"cfgPIDnSigmaCut", 3.f, "TPC PID |nσ| cut"}; - Configurable cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted z-vertex range"}; Configurable cfgCutTracKDcaMaxZ{"cfgCutTracKDcaMaxZ", 2.0f, "Maximum DcaZ"}; Configurable cfgCutTracKDcaMaxXY{"cfgCutTracKDcaMaxXY", 0.2f, "Maximum DcaZ"}; + Configurable cfgPtDepDCAxy{"cfgPtDepDCAxy", false, "Use pt-dependent DCAxy cut"}; + Configurable cfgDcaXyP0{"cfgDcaXyP0", 0.0026f, "p0 for DCAxy"}; + Configurable cfgDcaXyP1{"cfgDcaXyP1", 0.005f, "p1 for DCAxy"}; + Configurable cfgDcaXyP2{"cfgDcaXyP2", 1.01f, "p2 for DCAxy"}; + + Configurable cfgPtDepDCAz{"cfgPtDepDCAz", false, "Use pt-dependent DCAz cut"}; + Configurable cfgDcaZP0{"cfgDcaZP0", 0.0026f, "p0 for DCAz"}; + Configurable cfgDcaZP1{"cfgDcaZP1", 0.005f, "p1 for DCAz"}; + Configurable cfgDcaZP2{"cfgDcaZP2", 1.01f, "p2 for DCAz"}; + Configurable cfgITScluster{"cfgITScluster", 1, "Minimum Number of ITS cluster"}; Configurable cfgTPCcluster{"cfgTPCcluster", 80, "Minimum Number of TPC cluster"}; Configurable cfgTPCnCrossedRows{"cfgTPCnCrossedRows", 70, "Minimum Number of TPC crossed-rows"}; @@ -167,21 +192,22 @@ struct RadialFlowDecorr { Configurable cfgnSigmaCutTPC{"cfgnSigmaCutTPC", 2.0f, "PID nSigma cut for TPC"}; Configurable cfgnSigmaCutTOF{"cfgnSigmaCutTOF", 2.0f, "PID nSigma cut for TOF"}; Configurable cfgnSigmaCutCombTPCTOF{"cfgnSigmaCutCombTPCTOF", 2.0f, "PID nSigma combined cut for TPC and TOF"}; + + Configurable cfgTpcElRejCutMin{"cfgTpcElRejCutMin", -3.0f, "Electron Rejection Cut Minimum"}; + Configurable cfgTpcElRejCutMax{"cfgTpcElRejCutMax", 5.0f, "Electron Rejection Cut Maximum"}; + Configurable cfgTpcElRejCut{"cfgTpcElRejCut", 3.0f, "TPC Hadron Rejection Cut"}; + Configurable cfgCutPtLower{"cfgCutPtLower", 0.2f, "Lower pT cut"}; Configurable cfgCutPtUpper{"cfgCutPtUpper", 10.0f, "Higher pT cut for inclusive hadron analysis"}; Configurable cfgCutPtUpperPID{"cfgCutPtUpperPID", 6.0f, "Higher pT cut for identified particle analysis"}; Configurable cfgCutEta{"cfgCutEta", 0.8f, "absolute Eta cut"}; - Configurable cfgCutEtaLeft{"cfgCutEtaLeft", 0.8f, "Left end of eta gap"}; - Configurable cfgCutEtaRight{"cfgCutEtaRight", 0.8f, "Right end of eta gap"}; Configurable cfgNsubsample{"cfgNsubsample", 10, "Number of subsamples"}; - Configurable cfgCentralityChoice{"cfgCentralityChoice", 1, "Which centrality estimator? 1-->FT0C, 2-->FV0A"}; + Configurable cfgCentralityChoice{"cfgCentralityChoice", 2, "Which centrality estimator? 1-->FT0C, 2-->FT0M, 3-->FDDM, 4-->FV0A"}; Configurable cfgEvSelNoSameBunchPileup{"cfgEvSelNoSameBunchPileup", true, "Pileup removal"}; Configurable cfgUseGoodITSLayerAllCut{"cfgUseGoodITSLayerAllCut", true, "Remove time interval with dead ITS zone"}; - Configurable cfgEvSelkNoITSROFrameBorder{"cfgEvSelkNoITSROFrameBorder", true, "ITSROFrame border event selection cut"}; - Configurable cfgEvSelkNoTimeFrameBorder{"cfgEvSelkNoTimeFrameBorder", true, "TimeFrame border event selection cut"}; Configurable cfgIsGoodZvtxFT0VsPV{"cfgIsGoodZvtxFT0VsPV", true, "Good Vertexing cut"}; - Configurable cfgNchPbMax{"cfgNchPbMax", 4000, "Max Nch range for PbPb collisions"}; + Configurable cfgNchPbMax{"cfgNchPbMax", 6000, "Max Nch range for PbPb collisions"}; Configurable cfgNchOMax{"cfgNchOMax", 600, "Max Nch range for OO collisions"}; Configurable cfgSys{"cfgSys", 1, "Efficiency to be used for which system? 1-->PbPb, 2-->NeNe, 3-->OO, 4-->pp"}; @@ -192,10 +218,10 @@ struct RadialFlowDecorr { Configurable cfgCCDBurl{"cfgCCDBurl", "https://alice-ccdb.cern.ch", "ccdb url"}; Configurable cfgCCDBUserPath{"cfgCCDBUserPath", "/Users/s/somadutt", "Base CCDB path"}; - ConfigurableAxis cfgAxisCent{"cfgAxisCent", {0.0, 1.0, 3.0, 5.0, 10, 20, 30, 40, 50, 60, 70, 80, 100}, "centrality axis (percentile)"}; + ConfigurableAxis cfgAxisCent{"cfgAxisCent", {0.0, 1.0, 5.0, 10, 20, 40, 60, 80, 100}, "centrality axis (percentile)"}; const AxisSpec centAxis{cfgAxisCent, "Centrality (%)"}; - const AxisSpec centAxis1Per{101, -0.5, 100.5, "Centrality (%)"}; + const AxisSpec centAxis1Per{100, 0.0, 100.0, "Centrality (%)"}; AxisSpec nChAxis{1, 0., 1., "Nch", "Nch"}; AxisSpec nChAxis2{1, 0., 1., "Nch", "Nch"}; @@ -204,13 +230,29 @@ struct RadialFlowDecorr { const AxisSpec pTAxis{{0.0, 0.2, 0.5, 1, 3, 5, 7.5, 10}, "pT Axis"}; const AxisSpec etaAxis{{-0.9, -0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.1, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9}, "Eta"}; const AxisSpec phiAxis{KNbinsPhi, KPhiMin, TwoPI, "#phi"}; - const AxisSpec etaBinAxis{KNEta + 1, -KBinOffset, KNEta + KBinOffset, "#eta bin Number"}; - const AxisSpec gapAxis{{-1.55, -1.45, -1.35, -1.25, -1.15, -1.05, -0.95, -0.85, -0.75, -0.65, -0.55, -0.45, -0.35, -0.25, -0.15, -0.05, 0.05, 0.15, 0.25, 0.35, 0.45, 0.55, 0.65, 0.75, 0.85, 0.95, 1.05, 1.15, 1.25, 1.35, 1.45, 1.55}, "Gaps"}; - const AxisSpec sumAxis{{-0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.1, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8}, "Sums"}; + const AxisSpec etaBinAxis{KNEta + 1, -0.5, KNEta + 0.5, "#eta bin Number"}; + const AxisSpec spBinAxis{KNsp + 1, -KBinOffset, static_cast(KNsp) + KBinOffset, "species index Number"}; + + const AxisSpec gapAxis{{-1.55, -1.45, -1.35, -1.25, -1.15, -1.05, -0.95, -0.85, + -0.75, -0.65, -0.55, -0.45, -0.35, -0.25, -0.15, -0.05, + 0.05, 0.15, 0.25, 0.35, 0.45, 0.55, 0.65, 0.75, + 0.85, 0.95, 1.05, 1.15, 1.25, 1.35, 1.45, 1.55}, + "Gaps"}; + + const AxisSpec sumAxis{{-0.775, -0.725, -0.675, -0.625, -0.575, -0.525, + -0.475, -0.425, -0.375, -0.325, -0.275, -0.225, + -0.175, -0.125, -0.075, -0.025, + 0.025, 0.075, 0.125, 0.175, 0.225, 0.275, + 0.325, 0.375, 0.425, 0.475, 0.525, 0.575, + 0.625, 0.675, 0.725, 0.775}, + "Sums"}; + Configurable cfgRunMCGetNSig{"cfgRunMCGetNSig", false, "Run MC pass to get mean of Nsig Plots"}; Configurable cfgRunGetEff{"cfgRunGetEff", false, "Run MC pass to build efficiency/fake maps"}; Configurable cfgRunGetMCFlat{"cfgRunGetMCFlat", false, "Run MC to Get Flattening Weights"}; Configurable cfgRunMCMean{"cfgRunMCMean", false, "Run MC mean(pT) & mean(Et)"}; Configurable cfgRunMCFluc{"cfgRunMCFluc", false, "Run MC fluctuations (C2, subevent)"}; + + Configurable cfgRunDataGetNSig{"cfgRunDataGetNSig", false, "Run MC pass to get mean of Nsig Plots"}; Configurable cfgRunGetDataFlat{"cfgRunGetDataFlat", false, "Run Data Get Flattening Weights"}; Configurable cfgRunDataMean{"cfgRunDataMean", false, "Run DATA mean(pT) & mean(Et)"}; Configurable cfgRunDataFluc{"cfgRunDataFluc", false, "Run DATA fluctuations (C2, subevent)"}; @@ -219,72 +261,324 @@ struct RadialFlowDecorr { Service pdg; HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; - std::array hEff{}; - std::array hFake{}; - std::array hFlatWeight{}; - - TProfile3D* pmeanTruNchEtabinSpbinStep2 = nullptr; - TProfile3D* pmeanRecoNchEtabinSpbinStep2 = nullptr; - TProfile3D* pmeanRecoEffcorrNchEtabinSpbinStep2 = nullptr; + struct InternalState { + std::array hEff{}; + std::array hFake{}; + std::array hFlatWeight{}; - TProfile3D* pmeanMultTruNchEtabinSpbinStep2 = nullptr; - TProfile3D* pmeanMultRecoNchEtabinSpbinStep2 = nullptr; - TProfile3D* pmeanMultRecoEffcorrNchEtabinSpbinStep2 = nullptr; + TProfile3D* pmeanTruNchEtabinSpbinStep2 = nullptr; + TProfile3D* pmeanRecoNchEtabinSpbinStep2 = nullptr; + TProfile3D* pmeanRecoEffcorrNchEtabinSpbinStep2 = nullptr; - TProfile3D* pmeanNchEtabinSpbinStep2 = nullptr; - TProfile3D* pmeanMultNchEtabinSpbinStep2 = nullptr; + TProfile3D* pmeanMultTruNchEtabinSpbinStep2 = nullptr; + TProfile3D* pmeanMultRecoNchEtabinSpbinStep2 = nullptr; + TProfile3D* pmeanMultRecoEffcorrNchEtabinSpbinStep2 = nullptr; - TProfile* pmeanFT0AmultpvStep2 = nullptr; - TProfile* pmeanFT0CmultpvStep2 = nullptr; + TProfile3D* pmeanNchEtabinSpbinStep2 = nullptr; + TProfile3D* pmeanMultNchEtabinSpbinStep2 = nullptr; + TProfile* pmeanFT0AmultpvStep2 = nullptr; + TProfile* pmeanFT0CmultpvStep2 = nullptr; + } state; o2::ft0::Geometry ft0Det; template - static std::tuple getAllCombinedNSigmas(const T& candidate) + void fillNSigmaBefCut(const T& track, float cent) { - return { - std::hypot(candidate.tpcNSigmaPr(), candidate.tofNSigmaPr()), // Proton - std::hypot(candidate.tpcNSigmaPi(), candidate.tofNSigmaPi()), // Pion - std::hypot(candidate.tpcNSigmaKa(), candidate.tofNSigmaKa()) // Kaon - }; + float pt = track.pt(); + auto sign = track.sign(); + // --- Generic Inclusive --- + histos.fill(HIST("h3DnsigmaTpcVsPtBefCut_Cent"), cent, pt, track.tpcNSigmaPi()); + histos.fill(HIST("h3DnsigmaTofVsPtBefCut_Cent"), cent, pt, track.tofNSigmaPi()); + histos.fill(HIST("h3DnsigmaTpcVsTofBefCut_Cent"), cent, track.tofNSigmaPi(), track.tpcNSigmaPi()); + + histos.fill(HIST("h3DnsigmaTpcVsPtBefCut_Cent"), cent, pt, track.tpcNSigmaKa()); + histos.fill(HIST("h3DnsigmaTofVsPtBefCut_Cent"), cent, pt, track.tofNSigmaKa()); + histos.fill(HIST("h3DnsigmaTpcVsTofBefCut_Cent"), cent, track.tofNSigmaKa(), track.tpcNSigmaKa()); + + histos.fill(HIST("h3DnsigmaTpcVsPtBefCut_Cent"), cent, pt, track.tpcNSigmaPr()); + histos.fill(HIST("h3DnsigmaTofVsPtBefCut_Cent"), cent, pt, track.tofNSigmaPr()); + histos.fill(HIST("h3DnsigmaTpcVsTofBefCut_Cent"), cent, track.tofNSigmaPr(), track.tpcNSigmaPr()); + if (sign > 0) { + histos.fill(HIST("h3DnsigmaTpcVsPtBefCut_Cent_PiPlus"), cent, pt, track.tpcNSigmaPi()); + histos.fill(HIST("h3DnsigmaTofVsPtBefCut_Cent_PiPlus"), cent, pt, track.tofNSigmaPi()); + histos.fill(HIST("h3DnsigmaTpcVsTofBefCut_Cent_PiPlus"), cent, track.tofNSigmaPi(), track.tpcNSigmaPi()); + histos.fill(HIST("h3DnsigmaTpcVsPtBefCut_Cent_KaPlus"), cent, pt, track.tpcNSigmaKa()); + histos.fill(HIST("h3DnsigmaTofVsPtBefCut_Cent_KaPlus"), cent, pt, track.tofNSigmaKa()); + histos.fill(HIST("h3DnsigmaTpcVsTofBefCut_Cent_KaPlus"), cent, track.tofNSigmaKa(), track.tpcNSigmaKa()); + histos.fill(HIST("h3DnsigmaTpcVsPtBefCut_Cent_Pr"), cent, pt, track.tpcNSigmaPr()); + histos.fill(HIST("h3DnsigmaTofVsPtBefCut_Cent_Pr"), cent, pt, track.tofNSigmaPr()); + histos.fill(HIST("h3DnsigmaTpcVsTofBefCut_Cent_Pr"), cent, track.tofNSigmaPr(), track.tpcNSigmaPr()); + } else if (sign < 0) { + histos.fill(HIST("h3DnsigmaTpcVsPtBefCut_Cent_PiMinus"), cent, pt, track.tpcNSigmaPi()); + histos.fill(HIST("h3DnsigmaTofVsPtBefCut_Cent_PiMinus"), cent, pt, track.tofNSigmaPi()); + histos.fill(HIST("h3DnsigmaTpcVsTofBefCut_Cent_PiMinus"), cent, track.tofNSigmaPi(), track.tpcNSigmaPi()); + histos.fill(HIST("h3DnsigmaTpcVsPtBefCut_Cent_KaMinus"), cent, pt, track.tpcNSigmaKa()); + histos.fill(HIST("h3DnsigmaTofVsPtBefCut_Cent_KaMinus"), cent, pt, track.tofNSigmaKa()); + histos.fill(HIST("h3DnsigmaTpcVsTofBefCut_Cent_KaMinus"), cent, track.tofNSigmaKa(), track.tpcNSigmaKa()); + histos.fill(HIST("h3DnsigmaTpcVsPtBefCut_Cent_AntiPr"), cent, pt, track.tpcNSigmaPr()); + histos.fill(HIST("h3DnsigmaTofVsPtBefCut_Cent_AntiPr"), cent, pt, track.tofNSigmaPr()); + histos.fill(HIST("h3DnsigmaTpcVsTofBefCut_Cent_AntiPr"), cent, track.tofNSigmaPr(), track.tpcNSigmaPr()); + } + histos.fill(HIST("h3DnsigmaTpcVsPtBefCut_Cent_PiAll"), cent, pt, track.tpcNSigmaPi()); + histos.fill(HIST("h3DnsigmaTofVsPtBefCut_Cent_PiAll"), cent, pt, track.tofNSigmaPi()); + histos.fill(HIST("h3DnsigmaTpcVsTofBefCut_Cent_PiAll"), cent, track.tofNSigmaPi(), track.tpcNSigmaPi()); + + histos.fill(HIST("h3DnsigmaTpcVsPtBefCut_Cent_KaAll"), cent, pt, track.tpcNSigmaKa()); + histos.fill(HIST("h3DnsigmaTofVsPtBefCut_Cent_KaAll"), cent, pt, track.tofNSigmaKa()); + histos.fill(HIST("h3DnsigmaTpcVsTofBefCut_Cent_KaAll"), cent, track.tofNSigmaKa(), track.tpcNSigmaKa()); + + histos.fill(HIST("h3DnsigmaTpcVsPtBefCut_Cent_PrAll"), cent, pt, track.tpcNSigmaPr()); + histos.fill(HIST("h3DnsigmaTofVsPtBefCut_Cent_PrAll"), cent, pt, track.tofNSigmaPr()); + histos.fill(HIST("h3DnsigmaTpcVsTofBefCut_Cent_PrAll"), cent, track.tofNSigmaPr(), track.tpcNSigmaPr()); + } + + template + void fillNSigmaAftCut(const T& track, float cent, bool isSpecies[]) + { + float pt = track.pt(); + + if (isSpecies[kInclusiveIdx]) { + histos.fill(HIST("h3DnsigmaTpcVsPtAftCut_Cent"), cent, pt, track.tpcNSigmaPi()); + histos.fill(HIST("h3DnsigmaTofVsPtAftCut_Cent"), cent, pt, track.tofNSigmaPi()); + histos.fill(HIST("h3DnsigmaTpcVsTofAftCut_Cent"), cent, track.tofNSigmaPi(), track.tpcNSigmaPi()); + + histos.fill(HIST("h3DnsigmaTpcVsPtAftCut_Cent"), cent, pt, track.tpcNSigmaKa()); + histos.fill(HIST("h3DnsigmaTofVsPtAftCut_Cent"), cent, pt, track.tofNSigmaKa()); + histos.fill(HIST("h3DnsigmaTpcVsTofAftCut_Cent"), cent, track.tofNSigmaKa(), track.tpcNSigmaKa()); + + histos.fill(HIST("h3DnsigmaTpcVsPtAftCut_Cent"), cent, pt, track.tpcNSigmaPr()); + histos.fill(HIST("h3DnsigmaTofVsPtAftCut_Cent"), cent, pt, track.tofNSigmaPr()); + histos.fill(HIST("h3DnsigmaTpcVsTofAftCut_Cent"), cent, track.tofNSigmaPr(), track.tpcNSigmaPr()); + } + if (isSpecies[kPiPlusIdx]) { + histos.fill(HIST("h3DnsigmaTpcVsPtAftCut_Cent_PiPlus"), cent, pt, track.tpcNSigmaPi()); + histos.fill(HIST("h3DnsigmaTofVsPtAftCut_Cent_PiPlus"), cent, pt, track.tofNSigmaPi()); + histos.fill(HIST("h3DnsigmaTpcVsTofAftCut_Cent_PiPlus"), cent, track.tofNSigmaPi(), track.tpcNSigmaPi()); + } else if (isSpecies[kPiMinusIdx]) { + histos.fill(HIST("h3DnsigmaTpcVsPtAftCut_Cent_PiMinus"), cent, pt, track.tpcNSigmaPi()); + histos.fill(HIST("h3DnsigmaTofVsPtAftCut_Cent_PiMinus"), cent, pt, track.tofNSigmaPi()); + histos.fill(HIST("h3DnsigmaTpcVsTofAftCut_Cent_PiMinus"), cent, track.tofNSigmaPi(), track.tpcNSigmaPi()); + } + if (isSpecies[kPiAllIdx]) { + histos.fill(HIST("h3DnsigmaTpcVsPtAftCut_Cent_PiAll"), cent, pt, track.tpcNSigmaPi()); + histos.fill(HIST("h3DnsigmaTofVsPtAftCut_Cent_PiAll"), cent, pt, track.tofNSigmaPi()); + histos.fill(HIST("h3DnsigmaTpcVsTofAftCut_Cent_PiAll"), cent, track.tofNSigmaPi(), track.tpcNSigmaPi()); + } + if (isSpecies[kKaPlusIdx]) { + histos.fill(HIST("h3DnsigmaTpcVsPtAftCut_Cent_KaPlus"), cent, pt, track.tpcNSigmaKa()); + histos.fill(HIST("h3DnsigmaTofVsPtAftCut_Cent_KaPlus"), cent, pt, track.tofNSigmaKa()); + histos.fill(HIST("h3DnsigmaTpcVsTofAftCut_Cent_KaPlus"), cent, track.tofNSigmaKa(), track.tpcNSigmaKa()); + } else if (isSpecies[kKaMinusIdx]) { + histos.fill(HIST("h3DnsigmaTpcVsPtAftCut_Cent_KaMinus"), cent, pt, track.tpcNSigmaKa()); + histos.fill(HIST("h3DnsigmaTofVsPtAftCut_Cent_KaMinus"), cent, pt, track.tofNSigmaKa()); + histos.fill(HIST("h3DnsigmaTpcVsTofAftCut_Cent_KaMinus"), cent, track.tofNSigmaKa(), track.tpcNSigmaKa()); + } + if (isSpecies[kKaAllIdx]) { + histos.fill(HIST("h3DnsigmaTpcVsPtAftCut_Cent_KaAll"), cent, pt, track.tpcNSigmaKa()); + histos.fill(HIST("h3DnsigmaTofVsPtAftCut_Cent_KaAll"), cent, pt, track.tofNSigmaKa()); + histos.fill(HIST("h3DnsigmaTpcVsTofAftCut_Cent_KaAll"), cent, track.tofNSigmaKa(), track.tpcNSigmaKa()); + } + if (isSpecies[kPrIdx]) { + histos.fill(HIST("h3DnsigmaTpcVsPtAftCut_Cent_Pr"), cent, pt, track.tpcNSigmaPr()); + histos.fill(HIST("h3DnsigmaTofVsPtAftCut_Cent_Pr"), cent, pt, track.tofNSigmaPr()); + histos.fill(HIST("h3DnsigmaTpcVsTofAftCut_Cent_Pr"), cent, track.tofNSigmaPr(), track.tpcNSigmaPr()); + } else if (isSpecies[kAntiPrIdx]) { + histos.fill(HIST("h3DnsigmaTpcVsPtAftCut_Cent_AntiPr"), cent, pt, track.tpcNSigmaPr()); + histos.fill(HIST("h3DnsigmaTofVsPtAftCut_Cent_AntiPr"), cent, pt, track.tofNSigmaPr()); + histos.fill(HIST("h3DnsigmaTpcVsTofAftCut_Cent_AntiPr"), cent, track.tofNSigmaPr(), track.tpcNSigmaPr()); + } + if (isSpecies[kPrAllIdx]) { + histos.fill(HIST("h3DnsigmaTpcVsPtAftCut_Cent_PrAll"), cent, pt, track.tpcNSigmaPr()); + histos.fill(HIST("h3DnsigmaTofVsPtAftCut_Cent_PrAll"), cent, pt, track.tofNSigmaPr()); + histos.fill(HIST("h3DnsigmaTpcVsTofAftCut_Cent_PrAll"), cent, track.tofNSigmaPr(), track.tpcNSigmaPr()); + } + } + + // Returns: 0 = Unknown/Reject, 1 = Pion, 2 = Kaon, 3 = Proton + template + int identifyTrack(const T& candidate, int centBin) + { + // Initial sanity checks + if (!candidate.hasTPC()) + return 0; + float pt = candidate.pt(); + if (pt <= cfgCutPtLower || pt >= cfgCutPtUpperPID) + return 0; // Out of bounds + // Determine species indices based on charge + auto charge = candidate.sign(); + int piIdx = (charge > 0) ? kPiPlusIdx : kPiMinusIdx; + int kaIdx = (charge > 0) ? kKaPlusIdx : kKaMinusIdx; + int prIdx = (charge > 0) ? kPrIdx : kAntiPrIdx; + // Fetch Calibration Data (Means and Sigmas) + // TPC + float mPiTpc = pidMeanSigmaMap ? pidMeanSigmaMap->meanTPC[piIdx][centBin] : 0.f; + float sPiTpc = pidMeanSigmaMap ? pidMeanSigmaMap->sigmaTPC[piIdx][centBin] : 1.f; + float mKaTpc = pidMeanSigmaMap ? pidMeanSigmaMap->meanTPC[kaIdx][centBin] : 0.f; + float sKaTpc = pidMeanSigmaMap ? pidMeanSigmaMap->sigmaTPC[kaIdx][centBin] : 1.f; + float mPrTpc = pidMeanSigmaMap ? pidMeanSigmaMap->meanTPC[prIdx][centBin] : 0.f; + float sPrTpc = pidMeanSigmaMap ? pidMeanSigmaMap->sigmaTPC[prIdx][centBin] : 1.f; + // TOF + float mPiTof = pidMeanSigmaMap ? pidMeanSigmaMap->meanTOF[piIdx][centBin] : 0.f; + float sPiTof = pidMeanSigmaMap ? pidMeanSigmaMap->sigmaTOF[piIdx][centBin] : 1.f; + float mKaTof = pidMeanSigmaMap ? pidMeanSigmaMap->meanTOF[kaIdx][centBin] : 0.f; + float sKaTof = pidMeanSigmaMap ? pidMeanSigmaMap->sigmaTOF[kaIdx][centBin] : 1.f; + float mPrTof = pidMeanSigmaMap ? pidMeanSigmaMap->meanTOF[prIdx][centBin] : 0.f; + float sPrTof = pidMeanSigmaMap ? pidMeanSigmaMap->sigmaTOF[prIdx][centBin] : 1.f; + // Fetch Raw nSigma Values + float rawTpcPi = candidate.tpcNSigmaPi(); + float rawTpcKa = candidate.tpcNSigmaKa(); + float rawTpcPr = candidate.tpcNSigmaPr(); + float rawTpcEl = candidate.tpcNSigmaEl(); + + float rawTofPi = 0.f, rawTofKa = 0.f, rawTofPr = 0.f; + if (candidate.hasTOF()) { + rawTofPi = candidate.tofNSigmaPi(); + rawTofKa = candidate.tofNSigmaKa(); + rawTofPr = candidate.tofNSigmaPr(); + } + // ELECTRON REJECTION: Reject if it is > cTpcRejCut from ALL hadron hypotheses AND falls within the electron band [-3, 5] + if (std::abs(rawTpcPi - mPiTpc) > cfgTpcElRejCut && + std::abs(rawTpcKa - mKaTpc) > cfgTpcElRejCut && + std::abs(rawTpcPr - mPrTpc) > cfgTpcElRejCut && + rawTpcEl > cfgTpcElRejCutMin && rawTpcEl < cfgTpcElRejCutMax) { + return 0; // It's an electron, reject it! + } + + // --- Low PT Regime --- + if (pt <= cfgCutPtUpperTPC) { + // Basic TPC passing check: |Raw - Mean| < (Cut * Sigma) + bool inTpcPi = std::abs(rawTpcPi - mPiTpc) < (cfgnSigmaCutTPC * sPiTpc); + bool inTpcKa = std::abs(rawTpcKa - mKaTpc) < (cfgnSigmaCutTPC * sKaTpc); + bool inTpcPr = std::abs(rawTpcPr - mPrTpc) < (cfgnSigmaCutTPC * sPrTpc); + // Combined passing check (adds TOF if available) + bool passPi = inTpcPi && (!candidate.hasTOF() || std::abs(rawTofPi - mPiTof) < (cfgnSigmaCutTOF * sPiTof)); + bool passKa = inTpcKa && (!candidate.hasTOF() || std::abs(rawTofKa - mKaTof) < (cfgnSigmaCutTOF * sKaTof)); + bool passPr = inTpcPr && (!candidate.hasTOF() || std::abs(rawTofPr - mPrTof) < (cfgnSigmaCutTOF * sPrTof)); + // Uniqueness check: Must pass target cut, and NOT fall into the TPC range of the others + if (passPi && !passKa && !passPr) + return 1; + if (passKa && !passPi && !passPr) + return 2; + if (passPr && !passPi && !passKa) + return 3; + + return 0; // Ambiguous or failed all cuts + } + // --- High PT Regime--- + if (candidate.hasTOF() && pt > cfgCutPtUpperTPC) { + // Calculate 2D Normalized Distance (Elliptical distance normalized by sigma) + float dPi = std::hypot((rawTpcPi - mPiTpc) / sPiTpc, (rawTofPi - mPiTof) / sPiTof); + float dKa = std::hypot((rawTpcKa - mKaTpc) / sKaTpc, (rawTofKa - mKaTof) / sKaTof); + float dPr = std::hypot((rawTpcPr - mPrTpc) / sPrTpc, (rawTofPr - mPrTof) / sPrTof); + // Count how many particles are within the ambiguity radius + int competitors = (dPi < cfgnSigmaOtherParticles) + + (dKa < cfgnSigmaOtherParticles) + + (dPr < cfgnSigmaOtherParticles); + // If 1 or fewer are in the ambiguity region, pick the absolute best match + if (competitors <= 1) { + if (dPi <= dKa && dPi <= dPr && dPi < cfgnSigmaCutCombTPCTOF) + return 1; + if (dKa <= dPi && dKa <= dPr && dKa < cfgnSigmaCutCombTPCTOF) + return 2; + if (dPr <= dPi && dPr <= dKa && dPr < cfgnSigmaCutCombTPCTOF) + return 3; + } + } + return 0; // Unknown/Reject } template bool isEventSelected(const T& col) { + histos.fill(HIST("hEvtCount"), 0.5); + if (!col.sel8()) return false; + histos.fill(HIST("hEvtCount"), 1.5); + if (std::abs(col.posZ()) > cfgCutVertex) return false; + histos.fill(HIST("hEvtCount"), 2.5); + if (cfgEvSelNoSameBunchPileup && !col.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) return false; + histos.fill(HIST("hEvtCount"), 3.5); + if (cfgUseGoodITSLayerAllCut && !col.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) return false; + histos.fill(HIST("hEvtCount"), 4.5); + if (cfgIsGoodZvtxFT0VsPV && !col.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) return false; + histos.fill(HIST("hEvtCount"), 5.5); + return true; } template bool isTrackSelected(const T& trk) { + histos.fill(HIST("hTrkCount"), 0.5); + if (trk.sign() == 0) return false; + histos.fill(HIST("hTrkCount"), 1.5); + if (!trk.has_collision()) return false; + histos.fill(HIST("hTrkCount"), 2.5); + if (!trk.isPVContributor()) return false; + histos.fill(HIST("hTrkCount"), 3.5); + if (!(trk.itsNCls() > cfgITScluster)) return false; + histos.fill(HIST("hTrkCount"), 4.5); + if (!(trk.tpcNClsFound() >= cfgTPCcluster)) return false; + histos.fill(HIST("hTrkCount"), 5.5); + if (!(trk.tpcNClsCrossedRows() >= cfgTPCnCrossedRows)) return false; + histos.fill(HIST("hTrkCount"), 6.5); if (trk.pt() < cfgCutPtLower || trk.pt() > cfgCutPtUpper || std::abs(trk.eta()) > cfgCutEta) return false; - if (std::abs(trk.dcaXY()) > cfgCutTracKDcaMaxXY || std::abs(trk.dcaZ()) > cfgCutTracKDcaMaxZ) + histos.fill(HIST("hTrkCount"), 7.5); + + if (!trk.isGlobalTrack()) return false; + histos.fill(HIST("hTrkCount"), 8.5); + + if (cfgPtDepDCAxy) { + // Evaluates: P0 + P1 / (pt^P2) + float maxDcaXY = cfgDcaXyP0 + cfgDcaXyP1 / std::pow(trk.pt(), cfgDcaXyP2); + if (std::abs(trk.dcaXY()) > maxDcaXY) { + return false; + } + histos.fill(HIST("hTrkCount"), 9.5); + } else { + if (std::abs(trk.dcaXY()) > cfgCutTracKDcaMaxXY) { + return false; + } + histos.fill(HIST("hTrkCount"), 9.5); + } + if (cfgPtDepDCAz) { + // Evaluates: P0 + P1 / (pt^P2) + float maxDcaZ = cfgDcaZP0 + cfgDcaZP1 / std::pow(trk.pt(), cfgDcaZP2); + if (std::abs(trk.dcaZ()) > maxDcaZ) { + return false; // Reject track if DCA is too large + } + histos.fill(HIST("hTrkCount"), 10.5); + } else { + if (std::abs(trk.dcaZ()) > cfgCutTracKDcaMaxZ) { + return false; + } + histos.fill(HIST("hTrkCount"), 10.5); + } return true; } @@ -303,123 +597,20 @@ struct RadialFlowDecorr { return true; } - template - bool selectionProton(const T& candidate) - { - if (!candidate.hasTPC()) - return false; - int flag = 0; - if (candidate.pt() > cfgCutPtLower && candidate.pt() <= cfgCutPtUpperTPC) { - if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaPr()) < cfgnSigmaCutTPC) { - flag = 1; - } - if (candidate.hasTOF() && std::abs(candidate.tpcNSigmaPr()) < cfgnSigmaCutTPC && std::abs(candidate.tofNSigmaPr()) < cfgnSigmaCutTOF) { - flag = 1; - } - } - if (candidate.hasTOF() && candidate.pt() > cfgCutPtUpperTPC && candidate.pt() < cfgCutPtUpperPID) { - auto [combNSigmaPr, combNSigmaPi, combNSigmaKa] = getAllCombinedNSigmas(candidate); - int flag2 = 0; - if (combNSigmaPr < cfgnSigmaOtherParticles) - flag2 += 1; - if (combNSigmaPi < cfgnSigmaOtherParticles) - flag2 += 1; - if (combNSigmaKa < cfgnSigmaOtherParticles) - flag2 += 1; - if (!(flag2 > 1) && !(combNSigmaPr > combNSigmaPi) && !(combNSigmaPr > combNSigmaKa)) { - if (combNSigmaPr < cfgnSigmaCutCombTPCTOF) { - flag = 1; - } - } - } - if (flag == 1) - return true; - else - return false; - } - - template - bool selectionPion(const T& candidate) - { - if (!candidate.hasTPC()) - return false; - int flag = 0; - - if (candidate.pt() > cfgCutPtLower && candidate.pt() <= cfgCutPtUpperTPC) { - if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaPi()) < cfgnSigmaCutTPC) { - flag = 1; - } - if (candidate.hasTOF() && std::abs(candidate.tpcNSigmaPi()) < cfgnSigmaCutTPC && std::abs(candidate.tofNSigmaPi()) < cfgnSigmaCutTOF) { - flag = 1; - } - } - if (candidate.hasTOF() && candidate.pt() > cfgCutPtUpperTPC && candidate.pt() < cfgCutPtUpperPID) { - auto [combNSigmaPr, combNSigmaPi, combNSigmaKa] = getAllCombinedNSigmas(candidate); - int flag2 = 0; - if (combNSigmaPr < cfgnSigmaOtherParticles) - flag2 += 1; - if (combNSigmaPi < cfgnSigmaOtherParticles) - flag2 += 1; - if (combNSigmaKa < cfgnSigmaOtherParticles) - flag2 += 1; - if (!(flag2 > 1) && !(combNSigmaPi > combNSigmaPr) && !(combNSigmaPi > combNSigmaKa)) { - if (combNSigmaPi < cfgnSigmaCutCombTPCTOF) { - flag = 1; - } - } - } - if (flag == 1) - return true; - else - return false; - } - - template - bool selectionKaon(const T& candidate) - { - if (!candidate.hasTPC()) - return false; - int flag = 0; - - if (candidate.pt() > cfgCutPtLower && candidate.pt() <= cfgCutPtUpperTPC) { - if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaKa()) < cfgnSigmaCutTPC) { - flag = 1; - } - if (candidate.hasTOF() && std::abs(candidate.tpcNSigmaKa()) < cfgnSigmaCutTPC && std::abs(candidate.tofNSigmaKa()) < cfgnSigmaCutTOF) { - flag = 1; - } - } - if (candidate.hasTOF() && candidate.pt() > cfgCutPtUpperTPC && candidate.pt() < cfgCutPtUpperPID) { - auto [combNSigmaPr, combNSigmaPi, combNSigmaKa] = getAllCombinedNSigmas(candidate); - int flag2 = 0; - if (combNSigmaPr < cfgnSigmaOtherParticles) - flag2 += 1; - if (combNSigmaPi < cfgnSigmaOtherParticles) - flag2 += 1; - if (combNSigmaKa < cfgnSigmaOtherParticles) - flag2 += 1; - if (!(flag2 > 1) && !(combNSigmaKa > combNSigmaPi) && !(combNSigmaKa > combNSigmaPr)) { - if (combNSigmaKa < cfgnSigmaCutCombTPCTOF) { - flag = 1; - } - } - } - if (flag == 1) - return true; - else - return false; - } - float getCentrality(const auto& col) const { if (cfgCentralityChoice.value == kCentFT0C) return col.centFT0C(); + if (cfgCentralityChoice.value == kCentFT0M) + return col.centFT0M(); + if (cfgCentralityChoice.value == kCentFDDM) + return col.centFDDM(); if (cfgCentralityChoice.value == kCentFV0A) return col.centFV0A(); return KinvalidCentrality; } - float getEfficiency(float mult, float pt, float eta, PID pidType, int effidx, bool cfgEff) const + float getEfficiency(float mult, float pt, float eta, PIDIdx pidType, int effidx, bool cfgEff) const { if (!cfgEff) { if (effidx == 0) @@ -429,9 +620,9 @@ struct RadialFlowDecorr { } TH3F* h = nullptr; if (effidx == 0) - h = hEff[pidType]; + h = state.hEff[pidType]; if (effidx == 1) - h = hFake[pidType]; + h = state.hFake[pidType]; if (!h) return -1; @@ -442,11 +633,11 @@ struct RadialFlowDecorr { return val; } - float getFlatteningWeight(float vz, float chg, float pt, float eta, float phi, PID pidType, bool cfgflat) const + float getFlatteningWeight(float vz, float chg, float pt, float eta, float phi, PIDIdx pidType, bool cfgflat) const { if (!cfgflat) return 1.0; - THnSparseF* h = hFlatWeight[pidType]; + THnSparseF* h = state.hFlatWeight[pidType]; if (!h) return 0.0; @@ -460,6 +651,7 @@ struct RadialFlowDecorr { return val; } + std::vector* offsetFT0 = nullptr; uint64_t mLastTimestamp = 0; double getEtaFT0(uint64_t globalChno, int i) @@ -534,12 +726,11 @@ struct RadialFlowDecorr { return {calculatedMeanPt, twopcorr}; } - using GeneralCollisions = soa::Join< - aod::Collisions, - aod::EvSels, - aod::Mults, - aod::CentFT0As, aod::CentFT0Cs, aod::CentFT0Ms, aod::CentFV0As, - aod::CentNGlobals>; + using GeneralCollisions = soa::Join; + Filter collisionFilter = nabs(aod::collision::posZ) < cfgVtxZCut; using AodCollisionsSel = soa::Filtered; @@ -548,12 +739,11 @@ struct RadialFlowDecorr { aod::TracksExtra, aod::TrackSelection, aod::TracksDCA, - aod::pidTPCFullPi, aod::pidTPCFullKa, aod::pidTPCFullPr, - aod::pidTOFFullPi, aod::pidTOFFullKa, aod::pidTOFFullPr>; - Filter trackFilter = nabs(aod::track::eta) < cfgEtaCut && - aod::track::pt > cfgPtMin&& - aod::track::pt < cfgPtMax&& - nabs(aod::track::dcaXY) < cfgDCAXY&& nabs(aod::track::dcaZ) < cfgDCAZ; + aod::pidTPCFullPi, aod::pidTPCFullKa, aod::pidTPCFullPr, aod::pidTPCFullEl, + aod::pidTOFFullPi, aod::pidTOFFullKa, aod::pidTOFFullPr, aod::pidTOFFullEl>; + Filter trackFilter = aod::track::pt > KPtMin&& + aod::track::pt < KPtMax&& + requireGlobalTrackInFilter(); using AodTracksSel = soa::Filtered; using TCs = soa::Join; using FilteredTCs = soa::Filtered; @@ -561,14 +751,14 @@ struct RadialFlowDecorr { using MyRun3MCCollisions = soa::Join< aod::Collisions, aod::EvSels, aod::Mults, aod::MultsExtra, - aod::CentFT0As, aod::CentFT0Cs, aod::CentFT0Ms, aod::CentFV0As, + aod::CentFT0Cs, aod::CentFT0Ms, aod::CentFDDMs, aod::CentFV0As, aod::CentNGlobals, aod::McCollisionLabels>; using MyMCTracks = soa::Join< aod::Tracks, aod::TrackSelection, aod::TracksExtra, aod::TracksDCA, aod::McTrackLabels, - aod::pidTPCFullPi, aod::pidTPCFullKa, aod::pidTPCFullPr, - aod::pidTOFFullPi, aod::pidTOFFullKa, aod::pidTOFFullPr>; + aod::pidTPCFullPi, aod::pidTPCFullKa, aod::pidTPCFullPr, aod::pidTPCFullEl, + aod::pidTOFFullPi, aod::pidTOFFullKa, aod::pidTOFFullPr, aod::pidTOFFullEl>; PresliceUnsorted partPerMcCollision = aod::mcparticle::mcCollisionId; PresliceUnsorted colPerMcCollision = aod::mccollisionlabel::mcCollisionId; @@ -578,7 +768,7 @@ struct RadialFlowDecorr { void declareCommonQA() { - histos.add("hZvtx_after_sel", ";z_{vtx} (cm)", kTH1F, {{KNbinsZvtx, KZvtxMin, KZvtxMax}}); + histos.add("hVtxZ_after_sel", ";z_{vtx} (cm)", kTH1F, {{KNbinsZvtx, KZvtxMin, KZvtxMax}}); histos.add("hVtxZ", ";z_{vtx} (cm)", kTH1F, {{KNbinsZvtx, KZvtxMin, KZvtxMax}}); histos.add("hCentrality", ";centrality (%)", kTH1F, {{centAxis1Per}}); histos.add("Hist2D_globalTracks_PVTracks", ";N_{global};N_{PV}", kTH2F, {{nChAxis2}, {nChAxis2}}); @@ -587,26 +777,57 @@ struct RadialFlowDecorr { histos.add("hPt", ";p_{T} (GeV/c)", kTH1F, {{KNbinsPt, KPtMin, KPtMax}}); histos.add("hEta", ";#eta", kTH1F, {{KNbinsEtaFine, KEtaMin, KEtaMax}}); histos.add("hPhi", ";#phi", kTH1F, {{KNbinsPhi, KPhiMin, TwoPI}}); - histos.add("hEtaPhiReco", ";z_{vtx};sign;p_{T};#eta;#phi", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {etaAxis}, {phiAxis}}); + + histos.add("hEvtCount", "Number of Event;; Count", kTH1F, {{7, 0, 7}}); + histos.get(HIST("hEvtCount"))->GetXaxis()->SetBinLabel(1, "all Events"); + histos.get(HIST("hEvtCount"))->GetXaxis()->SetBinLabel(2, "after sel8"); + histos.get(HIST("hEvtCount"))->GetXaxis()->SetBinLabel(3, "after VertexZ Cut"); + histos.get(HIST("hEvtCount"))->GetXaxis()->SetBinLabel(4, "after kNoSameBunchPileup"); + histos.get(HIST("hEvtCount"))->GetXaxis()->SetBinLabel(5, "after kIsGoodZvtxFT0vsPV"); + histos.get(HIST("hEvtCount"))->GetXaxis()->SetBinLabel(6, "after kIsGoodITSLayersAll"); + + histos.add("hTrkCount", "Number of Tracks;; Count", kTH1F, {{11, 0, 11}}); + histos.get(HIST("hTrkCount"))->GetXaxis()->SetBinLabel(1, "all Tracks"); + histos.get(HIST("hTrkCount"))->GetXaxis()->SetBinLabel(2, "after sign!=0"); + histos.get(HIST("hTrkCount"))->GetXaxis()->SetBinLabel(3, "after has_collision"); + histos.get(HIST("hTrkCount"))->GetXaxis()->SetBinLabel(4, "after isPVContributor"); + histos.get(HIST("hTrkCount"))->GetXaxis()->SetBinLabel(5, "after itsNCls"); + histos.get(HIST("hTrkCount"))->GetXaxis()->SetBinLabel(6, "after tpcNClsFound"); + histos.get(HIST("hTrkCount"))->GetXaxis()->SetBinLabel(7, "after tpcNClsCrossedRows"); + histos.get(HIST("hTrkCount"))->GetXaxis()->SetBinLabel(8, "after pT,#eta selections"); + histos.get(HIST("hTrkCount"))->GetXaxis()->SetBinLabel(9, "after isGlobalTrack"); + histos.get(HIST("hTrkCount"))->GetXaxis()->SetBinLabel(10, "after dcaXY"); + histos.get(HIST("hTrkCount"))->GetXaxis()->SetBinLabel(11, "after dcaZ"); } void declareMCCommonHists() { for (const auto& suf : pidSuffix) { - histos.add("h3_AllPrimary" + suf, ";N_{PV};p_{T};#eta", kTH3F, {{nChAxis2}, {KNbinsPtRes, cfgPtMin, cfgPtMax}, {KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); - histos.add("h3_RecoMatchedToPrimary" + suf, ";N_{PV};p_{T};#eta", kTH3F, {{nChAxis2}, {KNbinsPtRes, cfgPtMin, cfgPtMax}, {KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); - histos.add("h3_AllReco" + suf, ";N_{PV};p_{T};#eta", kTH3F, {{nChAxis2}, {KNbinsPtRes, cfgPtMin, cfgPtMax}, {KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); - histos.add("h3_RecoUnMatchedToPrimary_Secondary" + suf, ";N_{PV};p_{T};#eta", kTH3F, {{nChAxis2}, {KNbinsPtRes, cfgPtMin, cfgPtMax}, {KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); - histos.add("h3_RecoUnMatchedToPrimary_Fake" + suf, ";N_{PV};p_{T};#eta", kTH3F, {{nChAxis2}, {KNbinsPtRes, cfgPtMin, cfgPtMax}, {KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); + histos.add("h3_AllPrimary" + suf, ";N_{PV};p_{T};#eta", kTH3F, {{nChAxis2}, {KNbinsPtRes, KPtMin, KPtMax}, {KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); + histos.add("h3_RecoMatchedToPrimary" + suf, ";N_{PV};p_{T};#eta", kTH3F, {{nChAxis2}, {KNbinsPtRes, KPtMin, KPtMax}, {KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); + histos.add("h3_AllReco" + suf, ";N_{PV};p_{T};#eta", kTH3F, {{nChAxis2}, {KNbinsPtRes, KPtMin, KPtMax}, {KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); + histos.add("h3_RecoUnMatchedToPrimary_Secondary" + suf, ";N_{PV};p_{T};#eta", kTH3F, {{nChAxis2}, {KNbinsPtRes, KPtMin, KPtMax}, {KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); + histos.add("h3_RecoUnMatchedToPrimary_Fake" + suf, ";N_{PV};p_{T};#eta", kTH3F, {{nChAxis2}, {KNbinsPtRes, KPtMin, KPtMax}, {KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); + histos.add("h3_RecoMatchedToPrimary_MisID" + suf, ";N_{PV};p_{T};#eta", kTH3F, {{nChAxis2}, {KNbinsPtRes, KPtMin, KPtMax}, {KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); } - histos.add("ptResolution", ";p_{T}^{MC};(p_{T}^{reco}-p_{T}^{MC})/p_{T}^{MC}", kTH2F, {{KNbinsPtRes, cfgPtMin, cfgPtMax}, {100, -0.2, 0.2}}); + histos.add("ptResolution", ";p_{T}^{MC};(p_{T}^{reco}-p_{T}^{MC})/p_{T}^{MC}", kTH2F, {{KNbinsPtRes, KPtMin, KPtMax}, {100, -0.2, 0.2}}); histos.add("etaResolution", ";#eta^{MC};#eta^{reco}-#eta^{MC}", kTH2F, {{KNbinsEtaRes, -KEtaFineMax, KEtaFineMax}, {100, -0.02, 0.02}}); histos.add("etaTruthReco", ";#eta^{MC};#eta^{reco}", kTH2F, {{KNbinsEtaRes, -KEtaFineMax, KEtaFineMax}, {KNbinsEtaRes, -KEtaFineMax, KEtaFineMax}}); histos.add("TruthTracKVz", ";Vz^{MC};Vz^{Reco}", kTH2F, {{KNbinsVz, KVzMin, KVzMax}, {KNbinsVz, KVzMin, KVzMax}}); histos.add("vzResolution", ";Vz^{MC};(Vz^{reco}-Vz^{MC})/Vz^{MC}", kTH2F, {{KNbinsVz, KVzMin, KVzMax}, {100, -0.1, 0.1}}); + } - histos.add("h_RecoUnMatchedToPrimary", ";p_{T}", kTH1F, {{KNbinsPtRes, cfgPtMin, cfgPtMax}}); + void declarenSigHists() + { + for (const auto& suf : pidSuffix) { + histos.add("h3DnsigmaTpcVsPtBefCut_Cent" + suf, "TPC nSigma vs pT Before Cut;cent [%]; p_{T} (GeV/c);n#sigma_{TPC}", kTH3F, {{centAxis1Per}, {KNbinsPtRes, KPtMin, KPtMax}, {200, -10.f, 10.f}}); + histos.add("h3DnsigmaTofVsPtBefCut_Cent" + suf, "TOF nSigma vs pT Before Cut;cent [%]; p_{T} (GeV/c);n#sigma_{TOF}", kTH3F, {{centAxis1Per}, {KNbinsPtRes, KPtMin, KPtMax}, {200, -10.f, 10.f}}); + histos.add("h3DnsigmaTpcVsTofBefCut_Cent" + suf, "TPC vs TOF nSigma Before Cut;cent [%]; n#sigma_{TOF};n#sigma_{TPC}", kTH3F, {{centAxis1Per}, {200, -10.f, 10.f}, {200, -10.f, 10.f}}); + histos.add("h3DnsigmaTpcVsPtAftCut_Cent" + suf, "TPC nSigma vs pT After Cut;cent [%],; p_{T} (GeV/c);n#sigma_{TPC}", kTH3F, {{centAxis1Per}, {KNbinsPtRes, KPtMin, KPtMax}, {200, -10.f, 10.f}}); + histos.add("h3DnsigmaTofVsPtAftCut_Cent" + suf, "TOF nSigma vs pT After Cut;cent [%],; p_{T} (GeV/c);n#sigma_{TOF}", kTH3F, {{centAxis1Per}, {KNbinsPtRes, KPtMin, KPtMax}, {200, -10.f, 10.f}}); + histos.add("h3DnsigmaTpcVsTofAftCut_Cent" + suf, "TPC vs TOF nSigma After Cut;cent [%],; n#sigma_{TOF};n#sigma_{TPC}", kTH3F, {{centAxis1Per}, {200, -10.f, 10.f}, {200, -10.f, 10.f}}); + } } void declareMCGetFlatHists() @@ -622,40 +843,44 @@ struct RadialFlowDecorr { { histos.add("Eff_cent", ";cent", kTProfile, {centAxis1Per}); histos.add("Eff_Ntrk", ";N_{PV}", kTProfile, {nChAxis2}); - histos.add("Eff_pT", ";p_{T}", kTProfile, {{KNbinsPtRes, cfgPtMin, cfgPtMax}}); + histos.add("Eff_pT", ";p_{T}", kTProfile, {{KNbinsPtRes, KPtMin, KPtMax}}); histos.add("Eff_eta", ";#eta", kTProfile, {{KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); histos.add("Fake_cent", ";cent", kTProfile, {centAxis1Per}); histos.add("Fake_Ntrk", ";N_{PV}", kTProfile, {nChAxis2}); - histos.add("Fake_pT", ";p_{T}", kTProfile, {{KNbinsPtRes, cfgPtMin, cfgPtMax}}); + histos.add("Fake_pT", ";p_{T}", kTProfile, {{KNbinsPtRes, KPtMin, KPtMax}}); histos.add("Fake_eta", ";#eta", kTProfile, {{KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); histos.add("wgt_cent", ";cent", kTProfile, {centAxis1Per}); histos.add("wgt_Ntrk", ";N_{PV}", kTProfile, {nChAxis2}); - histos.add("wgt_pT", ";p_{T}", kTProfile, {{KNbinsPtRes, cfgPtMin, cfgPtMax}}); + histos.add("wgt_pT", ";p_{T}", kTProfile, {{KNbinsPtRes, KPtMin, KPtMax}}); histos.add("wgt_eta", ";#eta", kTProfile, {{KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); histos.add("pmeanFT0Amultpv", ";N_{PV};Ampl", kTProfile, {nChAxis}); histos.add("pmeanFT0Cmultpv", ";N_{PV};Ampl", kTProfile, {nChAxis}); histos.add("pmeanFT0A_cent", ";cent;Ampl", kTProfile, {centAxis1Per}); histos.add("pmeanFT0C_cent", ";cent;Ampl", kTProfile, {centAxis1Per}); - histos.add("pmean_cent_id_eta_FT0", ";cent;id;#eta", kTProfile3D, {{centAxis1Per}, {100, -0.5, 99.5}, {100, -5.0, 5.0}}); - histos.add("h3_cent_id_eta_FT0", ";cent;id;#eta", kTH3F, {{centAxis1Per}, {100, -0.5, 99.5}, {100, -5.0, 5.0}}); + histos.add("pmean_cent_id_eta_FT0", ";cent;id;#eta", kTProfile3D, {{centAxis1Per}, {200, -0.5, 199.5}, {100, -5.0, 5.0}}); + histos.add("h3_cent_id_eta_FT0", ";cent;id;#eta", kTH3F, {{centAxis1Per}, {200, -0.5, 199.5}, {100, -5.0, 5.0}}); - histos.add("MCGen/Prof_Cent_Nsp_Nchrec", ";cent;isp", kTProfile2D, {{centAxis1Per}, {KNsp, -0.5, KNsp - 0.5}}); - histos.add("MCGen/Prof_Mult_Nsp_Nchrec", ";mult;isp", kTProfile2D, {{nChAxis}, {KNsp, -0.5, KNsp - 0.5}}); - histos.add("MCGen/Prof_Cent_Nsp_MeanpT", ";cent;isp", kTProfile2D, {{centAxis1Per}, {KNsp, -0.5, KNsp - 0.5}}); - histos.add("MCGen/Prof_Mult_Nsp_MeanpT", ";mult;isp", kTProfile2D, {{nChAxis}, {KNsp, -0.5, KNsp - 0.5}}); + histos.add("MCGen/Prof_Cent_Nsp_Nchrec", ";cent;isp", kTProfile2D, {{centAxis1Per}, {spBinAxis}}); + histos.add("MCGen/Prof_Mult_Nsp_Nchrec", ";mult;isp", kTProfile2D, {{nChAxis}, {spBinAxis}}); + histos.add("MCGen/Prof_Cent_Nsp_MeanpT", ";cent;isp", kTProfile2D, {{centAxis1Per}, {spBinAxis}}); + histos.add("MCGen/Prof_Mult_Nsp_MeanpT", ";mult;isp", kTProfile2D, {{nChAxis}, {spBinAxis}}); - histos.add("pmeanTru_nch_etabin_spbin", ";mult;eta;isp", kTProfile3D, {{nChAxis}, {KNEta, 0.5, KNEta + 0.5}, {KNsp, -0.5, KNsp - 0.5}}); - histos.add("pmeanReco_nch_etabin_spbin", ";mult;eta;isp", kTProfile3D, {{nChAxis}, {KNEta, 0.5, KNEta + 0.5}, {KNsp, -0.5, KNsp - 0.5}}); - histos.add("pmeanRecoEffcorr_nch_etabin_spbin", ";mult;eta;isp", kTProfile3D, {{nChAxis}, {KNEta, 0.5, KNEta + 0.5}, {KNsp, -0.5, KNsp - 0.5}}); + histos.add("pmeanTru_nch_etabin_spbin", ";mult;eta;isp", kTProfile3D, {{nChAxis}, {etaBinAxis}, {spBinAxis}}); + histos.add("pmeanReco_nch_etabin_spbin", ";mult;eta;isp", kTProfile3D, {{nChAxis}, {etaBinAxis}, {spBinAxis}}); + histos.add("pmeanRecoEffcorr_nch_etabin_spbin", ";mult;eta;isp", kTProfile3D, {{nChAxis}, {etaBinAxis}, {spBinAxis}}); - histos.add("pmeanMultTru_nch_etabin_spbin", ";mult;eta;isp", kTProfile3D, {{nChAxis}, {KNEta, 0.5, KNEta + 0.5}, {KNsp, -0.5, KNsp - 0.5}}); - histos.add("pmeanMultReco_nch_etabin_spbin", ";mult;eta;isp", kTProfile3D, {{nChAxis}, {KNEta, 0.5, KNEta + 0.5}, {KNsp, -0.5, KNsp - 0.5}}); - histos.add("pmeanMultRecoEffcorr_nch_etabin_spbin", ";mult;eta;isp", kTProfile3D, {{nChAxis}, {KNEta, 0.5, KNEta + 0.5}, {KNsp, -0.5, KNsp - 0.5}}); + histos.add("pmeanMultTru_nch_etabin_spbin", ";mult;eta;isp", kTProfile3D, {{nChAxis}, {etaBinAxis}, {spBinAxis}}); + histos.add("pmeanMultReco_nch_etabin_spbin", ";mult;eta;isp", kTProfile3D, {{nChAxis}, {etaBinAxis}, {spBinAxis}}); + histos.add("pmeanMultRecoEffcorr_nch_etabin_spbin", ";mult;eta;isp", kTProfile3D, {{nChAxis}, {etaBinAxis}, {spBinAxis}}); for (const auto& suf : pidSuffix) { + histos.add("hEtaPhiReco" + suf, ";vz;sign;pt;eta;phi", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {etaAxis}, {phiAxis}}); + histos.add("hEtaPhiRecoEffWtd" + suf, ";vz;sign;pt;eta;phi", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {etaAxis}, {phiAxis}}); + histos.add("hEtaPhiRecoWtd" + suf, ";vz;sign;pt;eta;phi", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {etaAxis}, {phiAxis}}); + histos.add("Prof2D_MeanpTSub_Tru" + suf, ";cent;etaA;etaC", kTProfile3D, {{centAxis1Per}, {etaBinAxis}, {etaBinAxis}}); histos.add("Prof2D_MeanpTSub_Reco" + suf, ";cent;etaA;etaC", kTProfile3D, {{centAxis1Per}, {etaBinAxis}, {etaBinAxis}}); histos.add("Prof2D_MeanpTSub_RecoEffCorr" + suf, ";cent;etaA;etaC", kTProfile3D, {{centAxis1Per}, {etaBinAxis}, {etaBinAxis}}); @@ -664,17 +889,35 @@ struct RadialFlowDecorr { void declareMCFlucHists() { - histos.add("MCGen/Prof_MeanpT_Cent_etabin_spbin", ";cent;eta;isp", kTProfile3D, {{centAxis1Per}, {etaBinAxis}, {KNsp, -0.5, KNsp - 0.5}}); - histos.add("MCGen/Prof_C2_Cent_etabin_spbin", ";cent;eta;isp", kTProfile3D, {{centAxis1Per}, {etaBinAxis}, {KNsp, -0.5, KNsp - 0.5}}); - histos.add("MCGen/Prof_C2Sub_Cent_etabin_spbin", ";cent;eta;isp", kTProfile3D, {{centAxis1Per}, {etaBinAxis}, {KNsp, -0.5, KNsp - 0.5}}); - histos.add("MCGen/Prof_Cov_Cent_etabin_spbin", ";cent;eta;isp", kTProfile3D, {{centAxis1Per}, {etaBinAxis}, {KNsp, -0.5, KNsp - 0.5}}); - histos.add("MCGen/Prof_CovFT0A_Cent_etabin_spbin", ";cent;eta;isp", kTProfile3D, {{centAxis1Per}, {etaBinAxis}, {KNsp, -0.5, KNsp - 0.5}}); - histos.add("MCGen/Prof_CovFT0C_Cent_etabin_spbin", ";cent;eta;isp", kTProfile3D, {{centAxis1Per}, {etaBinAxis}, {KNsp, -0.5, KNsp - 0.5}}); + histos.add("MCGen/Prof_Cent_NEta_Nsp_Nchrec", ";cent;eta;isp", kTProfile3D, {{centAxis1Per}, {etaBinAxis}, {spBinAxis}}); + histos.add("MCGen/Prof_Mult_NEta_Nsp_Nchrec", ";mult;eta;isp", kTProfile3D, {{nChAxis}, {etaBinAxis}, {spBinAxis}}); + histos.add("MCGen/Prof_Cent_NEta_Nsp_MeanpT", ";cent;eta;isp", kTProfile3D, {{centAxis1Per}, {etaBinAxis}, {spBinAxis}}); + histos.add("MCGen/Prof_Mult_NEta_Nsp_MeanpT", ";mult;eta;isp", kTProfile3D, {{nChAxis}, {etaBinAxis}, {spBinAxis}}); + + histos.add("MCGen/Prof_MeanpT_Cent_etabin_spbin", ";cent;eta;isp", kTProfile3D, {{centAxis1Per}, {etaBinAxis}, {spBinAxis}}); + histos.add("MCGen/Prof_C2_Cent_etabin_spbin", ";cent;eta;isp", kTProfile3D, {{centAxis1Per}, {etaBinAxis}, {spBinAxis}}); + histos.add("MCGen/Prof_C2Sub_Cent_etabin_spbin", ";cent;eta;isp", kTProfile3D, {{centAxis1Per}, {etaBinAxis}, {spBinAxis}}); + histos.add("MCGen/Prof_Cov_Cent_etabin_spbin", ";cent;eta;isp", kTProfile3D, {{centAxis1Per}, {etaBinAxis}, {spBinAxis}}); + histos.add("MCGen/Prof_CovFT0A_Cent_etabin_spbin", ";cent;eta;isp", kTProfile3D, {{centAxis1Per}, {etaBinAxis}, {spBinAxis}}); + histos.add("MCGen/Prof_CovFT0C_Cent_etabin_spbin", ";cent;eta;isp", kTProfile3D, {{centAxis1Per}, {etaBinAxis}, {spBinAxis}}); + + histos.add("MCGen/Prof_MeanpT_Mult_etabin_spbin", ";mult;eta;isp", kTProfile3D, {{nChAxis}, {etaBinAxis}, {spBinAxis}}); + histos.add("MCGen/Prof_C2_Mult_etabin_spbin", ";mult;eta;isp", kTProfile3D, {{nChAxis}, {etaBinAxis}, {spBinAxis}}); + histos.add("MCGen/Prof_C2Sub_Mult_etabin_spbin", ";mult;eta;isp", kTProfile3D, {{nChAxis}, {etaBinAxis}, {spBinAxis}}); + histos.add("MCGen/Prof_Cov_Mult_etabin_spbin", ";mult;eta;isp", kTProfile3D, {{nChAxis}, {etaBinAxis}, {spBinAxis}}); + histos.add("MCGen/Prof_CovFT0A_Mult_etabin_spbin", ";mult;eta;isp", kTProfile3D, {{nChAxis}, {etaBinAxis}, {spBinAxis}}); + histos.add("MCGen/Prof_CovFT0C_Mult_etabin_spbin", ";mult;eta;isp", kTProfile3D, {{nChAxis}, {etaBinAxis}, {spBinAxis}}); for (const auto& suf : pidSuffix) { + histos.add("hEtaPhiReco" + suf, ";vz;sign;pt;eta;phi", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {etaAxis}, {phiAxis}}); + histos.add("hEtaPhiRecoEffWtd" + suf, ";vz;sign;pt;eta;phi", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {etaAxis}, {phiAxis}}); + histos.add("hEtaPhiRecoWtd" + suf, ";vz;sign;pt;eta;phi", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {etaAxis}, {phiAxis}}); + histos.add(Form("MCGen/Prof_C2Sub2D_Cent_etaA_etaC%s", suf.c_str()), ";cent;etaA;etaC", kTProfile3D, {{centAxis1Per}, {etaAxis}, {etaAxis}}); histos.add(Form("MCGen/Prof_GapSum2D%s", suf.c_str()), ";cent;gap;sum", kTProfile3D, {{centAxis1Per}, {gapAxis}, {sumAxis}}); histos.add(Form("MCGen/Prof_Cov2D_Cent_etaA_etaC%s", suf.c_str()), ";cent;etaA;etaC", kTProfile3D, {{centAxis1Per}, {etaAxis}, {etaAxis}}); + histos.add(Form("MCGen/Prof_CovFT0A2D_Cent_etaA_etaC%s", suf.c_str()), ";cent;etaA;etaC", kTProfile3D, {{centAxis1Per}, {etaAxis}, {etaAxis}}); + histos.add(Form("MCGen/Prof_CovFT0C2D_Cent_etaA_etaC%s", suf.c_str()), ";cent;etaA;etaC", kTProfile3D, {{centAxis1Per}, {etaAxis}, {etaAxis}}); } } @@ -701,41 +944,41 @@ struct RadialFlowDecorr { histos.add("pmean_cent_id_eta_FT0", ";cent;channel id; #eta;amplitude", kTProfile3D, {{centAxis1Per}, {100, -0.5, 99.5}, {100, -5.0, 5.0}}); histos.add("h3_cent_id_eta_FT0", ";cent;channel id; #eta", kTH3F, {{centAxis1Per}, {100, -0.5, 99.5}, {100, -5.0, 5.0}}); - histos.add("Prof_Cent_Nsp_Nchrec", ";cent;Species;#LT N_{PV}#GT", kTProfile2D, {{centAxis1Per}, {KNsp, -0.5, KNsp - 0.5}}); - histos.add("Prof_Mult_Nsp_Nchrec", ";N_{PV};Species;#LT N_{PV}#GT", kTProfile2D, {{nChAxis}, {KNsp, -0.5, KNsp - 0.5}}); - histos.add("Prof_Cent_Nsp_MeanpT", ";cent;Species;#LT p_{T}#GT", kTProfile2D, {{centAxis1Per}, {KNsp, -0.5, KNsp - 0.5}}); - histos.add("Prof_Mult_Nsp_MeanpT", ";N_{PV};Species;#LT p_{T}#GT", kTProfile2D, {{nChAxis}, {KNsp, -0.5, KNsp - 0.5}}); + histos.add("Prof_Cent_Nsp_Nchrec", ";cent;Species;#LT N_{PV}#GT", kTProfile2D, {{centAxis1Per}, {spBinAxis}}); + histos.add("Prof_Mult_Nsp_Nchrec", ";N_{PV};Species;#LT N_{PV}#GT", kTProfile2D, {{nChAxis}, {spBinAxis}}); + histos.add("Prof_Cent_Nsp_MeanpT", ";cent;Species;#LT p_{T}#GT", kTProfile2D, {{centAxis1Per}, {spBinAxis}}); + histos.add("Prof_Mult_Nsp_MeanpT", ";N_{PV};Species;#LT p_{T}#GT", kTProfile2D, {{nChAxis}, {spBinAxis}}); - histos.add("pmean_nch_etabin_spbin", ";N_{PV};#eta-bin;Species", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNsp, -0.5, KNsp - 0.5}}); - histos.add("pmeanMult_nch_etabin_spbin", ";N_{PV};#eta-bin;Species", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNsp, -0.5, KNsp - 0.5}}); - histos.add("pmean_cent_etabin_spbin", ";Centrality (%) ;#eta-bin;Species", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNsp, -0.5, KNsp - 0.5}}); - histos.add("pmeanMult_cent_etabin_spbin", ";Centrality (%) ;#eta-bin;Species", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNsp, -0.5, KNsp - 0.5}}); + histos.add("pmean_nch_etabin_spbin", ";N_{PV};#eta-bin;Species", kTProfile3D, {{nChAxis}, {{etaBinAxis}}, {spBinAxis}}); + histos.add("pmeanMult_nch_etabin_spbin", ";N_{PV};#eta-bin;Species", kTProfile3D, {{nChAxis}, {{etaBinAxis}}, {spBinAxis}}); + histos.add("pmean_cent_etabin_spbin", ";Centrality (%) ;#eta-bin;Species", kTProfile3D, {{centAxis1Per}, {{etaBinAxis}}, {spBinAxis}}); + histos.add("pmeanMult_cent_etabin_spbin", ";Centrality (%) ;#eta-bin;Species", kTProfile3D, {{centAxis1Per}, {{etaBinAxis}}, {spBinAxis}}); for (const auto& suf : pidSuffix) { histos.add("hEtaPhiReco" + suf, ";vz;sign;pt;eta;phi", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {etaAxis}, {phiAxis}}); histos.add("hEtaPhiRecoEffWtd" + suf, ";vz;sign;pt;eta;phi", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {etaAxis}, {phiAxis}}); histos.add("hEtaPhiRecoWtd" + suf, ";vz;sign;pt;eta;phi", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {etaAxis}, {phiAxis}}); - histos.add("Prof2D_MeanpTSub" + suf, ";cent;#eta_{A} bin;#eta_{C} bin", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}}); + histos.add("Prof2D_MeanpTSub" + suf, ";cent;#eta_{A} bin;#eta_{C} bin", kTProfile3D, {{centAxis1Per}, {{etaBinAxis}}, {{etaBinAxis}}}); } } void declareDataFlucHists() { - histos.add("Prof_MeanpT_Cent_etabin_spbin", ";cent;#eta-bin;Species", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNsp, -0.5, KNsp - 0.5}}); - histos.add("Prof_MeanpT_Mult_etabin_spbin", ";N_{PV};#eta-bin;Species", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNsp, -0.5, KNsp - 0.5}}); - histos.add("Prof_C2_Cent_etabin_spbin", ";cent;#eta-bin;Species", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNsp, -0.5, KNsp - 0.5}}); - histos.add("Prof_C2_Mult_etabin_spbin", ";N_{PV};#eta-bin;Species", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNsp, -0.5, KNsp - 0.5}}); + histos.add("Prof_MeanpT_Cent_etabin_spbin", ";cent;#eta-bin;Species", kTProfile3D, {{centAxis1Per}, {{etaBinAxis}}, {spBinAxis}}); + histos.add("Prof_MeanpT_Mult_etabin_spbin", ";N_{PV};#eta-bin;Species", kTProfile3D, {{nChAxis}, {{etaBinAxis}}, {spBinAxis}}); + histos.add("Prof_C2_Cent_etabin_spbin", ";cent;#eta-bin;Species", kTProfile3D, {{centAxis1Per}, {{etaBinAxis}}, {spBinAxis}}); + histos.add("Prof_C2_Mult_etabin_spbin", ";N_{PV};#eta-bin;Species", kTProfile3D, {{nChAxis}, {{etaBinAxis}}, {spBinAxis}}); - histos.add("Prof_C2Sub_Cent_etabin_spbin", ";Centrality;#eta-bin;Species", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNsp, -0.5, KNsp - 0.5}}); - histos.add("Prof_C2Sub_Mult_etabin_spbin", ";N_{PV};#eta-bin;Species", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNsp, -0.5, KNsp - 0.5}}); - histos.add("Prof_Cov_Cent_etabin_spbin", ";Centrality;#eta-bin;Species", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNsp, -0.5, KNsp - 0.5}}); - histos.add("Prof_Cov_Mult_etabin_spbin", ";N_{PV};#eta-bin;Species", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNsp, -0.5, KNsp - 0.5}}); + histos.add("Prof_C2Sub_Cent_etabin_spbin", ";Centrality;#eta-bin;Species", kTProfile3D, {{centAxis1Per}, {{etaBinAxis}}, {spBinAxis}}); + histos.add("Prof_C2Sub_Mult_etabin_spbin", ";N_{PV};#eta-bin;Species", kTProfile3D, {{nChAxis}, {{etaBinAxis}}, {spBinAxis}}); + histos.add("Prof_Cov_Cent_etabin_spbin", ";Centrality;#eta-bin;Species", kTProfile3D, {{centAxis1Per}, {{etaBinAxis}}, {spBinAxis}}); + histos.add("Prof_Cov_Mult_etabin_spbin", ";N_{PV};#eta-bin;Species", kTProfile3D, {{nChAxis}, {{etaBinAxis}}, {spBinAxis}}); - histos.add("Prof_CovFT0A_Cent_etabin_spbin", ";Centrality;#eta-bin;Species", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNsp, -0.5, KNsp - 0.5}}); - histos.add("Prof_CovFT0A_Mult_etabin_spbin", ";N_{PV};#eta-bin;Species", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNsp, -0.5, KNsp - 0.5}}); - histos.add("Prof_CovFT0C_Cent_etabin_spbin", ";Centrality;#eta-bin;Species", kTProfile3D, {{centAxis1Per}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNsp, -0.5, KNsp - 0.5}}); - histos.add("Prof_CovFT0C_Mult_etabin_spbin", ";N_{PV};#eta-bin;Species", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNsp, -0.5, KNsp - 0.5}}); + histos.add("Prof_CovFT0A_Cent_etabin_spbin", ";Centrality;#eta-bin;Species", kTProfile3D, {{centAxis1Per}, {{etaBinAxis}}, {spBinAxis}}); + histos.add("Prof_CovFT0A_Mult_etabin_spbin", ";N_{PV};#eta-bin;Species", kTProfile3D, {{nChAxis}, {{etaBinAxis}}, {spBinAxis}}); + histos.add("Prof_CovFT0C_Cent_etabin_spbin", ";Centrality;#eta-bin;Species", kTProfile3D, {{centAxis1Per}, {{etaBinAxis}}, {spBinAxis}}); + histos.add("Prof_CovFT0C_Mult_etabin_spbin", ";N_{PV};#eta-bin;Species", kTProfile3D, {{nChAxis}, {{etaBinAxis}}, {spBinAxis}}); for (const auto& suf : pidSuffix) { histos.add("hEtaPhiReco" + suf, ";vz;sign;pt;eta;phi", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {etaAxis}, {phiAxis}}); @@ -855,18 +1098,28 @@ struct RadialFlowDecorr { default: LOGF(fatal, "Invalid cfgSys value: %d", cfgSys.value); } - + std::string pathNsig = cfgCCDBUserPath.value + "/" + sysDir + "/Job0_nSigMaps"; std::string pathEff = cfgCCDBUserPath.value + "/" + sysDir + "/Job1_EffMaps"; std::string pathMCFlat = cfgCCDBUserPath.value + "/" + sysDir + "/Job1_MCFlatMaps"; std::string pathMCMean = cfgCCDBUserPath.value + "/" + sysDir + "/Job2_MCMean"; + + std::string pathDataNsig = cfgCCDBUserPath.value + "/" + sysDir + "/Job0_DatanSigMaps"; std::string pathDataFlat = cfgCCDBUserPath.value + "/" + sysDir + "/Job1_DataFlatMaps"; std::string pathDataMean = cfgCCDBUserPath.value + "/" + sysDir + "/Job2_DataMean"; declareCommonQA(); + if (cfgRunMCGetNSig || cfgRunGetEff || cfgRunDataGetNSig || cfgRunGetDataFlat) { + declarenSigHists(); + } if (cfgRunMCMean || cfgRunMCFluc || cfgRunGetEff) { declareMCCommonHists(); } + if (cfgRunGetMCFlat) { + declareMCGetFlatHists(); + histos.addClone("MCGen/", "MCReco/"); + histos.addClone("MCGen/", "MCRecoEffCorr/"); + } if (cfgRunMCMean) { declareMCMeanHists(); histos.addClone("MCGen/", "MCReco/"); @@ -877,13 +1130,11 @@ struct RadialFlowDecorr { histos.addClone("MCGen/", "MCReco/"); histos.addClone("MCGen/", "MCRecoEffCorr/"); } - if (cfgRunGetDataFlat) { + if (cfgRunDataGetNSig) { declareDataGetFlatHists(); } - if (cfgRunGetMCFlat) { - declareMCGetFlatHists(); - histos.addClone("MCGen/", "MCReco/"); - histos.addClone("MCGen/", "MCRecoEffCorr/"); + if (cfgRunGetDataFlat) { + declareDataGetFlatHists(); } if (cfgRunDataMean) { declareDataMeanHists(); @@ -892,7 +1143,7 @@ struct RadialFlowDecorr { declareDataFlucHists(); } - if (!cfgRunGetEff && (cfgEff)) { + if (!cfgRunGetEff && !cfgRunMCGetNSig && (cfgEff)) { TList* lst = ccdb->getForTimeStamp(pathEff, now); if (!lst) { @@ -901,41 +1152,152 @@ struct RadialFlowDecorr { LOGF(info, "Loading Eff/Fake maps from TList for all species..."); - auto loadEffFakeForPID = [&](PID pidType) { + auto loadEffFakeForPID = [&](PIDIdx pidType) { std::string suffix = pidSuffix[pidType]; std::string hEffNumName = "h3_RecoMatchedToPrimary" + suffix; std::string hEffDenName = "h3_AllPrimary" + suffix; std::string hFakeNumSecName = "h3_RecoUnMatchedToPrimary_Secondary" + suffix; std::string hFakeNumFakName = "h3_RecoUnMatchedToPrimary_Fake" + suffix; + std::string hFakeNumFakName2 = "h3_RecoMatchedToPrimary_MisID" + suffix; std::string hFakeDenName = "h3_AllReco" + suffix; auto* hNum = reinterpret_cast(lst->FindObject(hEffNumName.c_str())); auto* hDen = reinterpret_cast(lst->FindObject(hEffDenName.c_str())); if (hNum && hDen) { - hEff[pidType] = reinterpret_cast(hNum->Clone(Form("hEff%s", suffix.c_str()))); - hEff[pidType]->SetDirectory(nullptr); - hEff[pidType]->Divide(hDen); + state.hEff[pidType] = reinterpret_cast(hNum->Clone(Form("hEff%s", suffix.c_str()))); + state.hEff[pidType]->SetDirectory(nullptr); + state.hEff[pidType]->Divide(hDen); } else { LOGF(error, "Missing CCDB objects for efficiency. Checked: %s, %s", hEffNumName.c_str(), hEffDenName.c_str()); } auto* hNumS = reinterpret_cast(lst->FindObject(hFakeNumSecName.c_str())); auto* hNumF = reinterpret_cast(lst->FindObject(hFakeNumFakName.c_str())); + auto* hNumF2 = reinterpret_cast(lst->FindObject(hFakeNumFakName2.c_str())); auto* hDenF = reinterpret_cast(lst->FindObject(hFakeDenName.c_str())); if (hNumS && hNumF && hDenF) { - hFake[pidType] = reinterpret_cast(hNumS->Clone(Form("hFake%s", suffix.c_str()))); - hFake[pidType]->Add(hNumF); - hFake[pidType]->SetDirectory(nullptr); - hFake[pidType]->Divide(hDenF); + state.hFake[pidType] = reinterpret_cast(hNumS->Clone(Form("hFake%s", suffix.c_str()))); + state.hFake[pidType]->Add(hNumF); + state.hFake[pidType]->Add(hNumF2); + state.hFake[pidType]->SetDirectory(nullptr); + state.hFake[pidType]->Divide(hDenF); } else { LOGF(error, "Missing CCDB object(s) for fakes for %s in list.", suffix.c_str()); } }; for (int i = 0; i < KNsp; ++i) { - loadEffFakeForPID(static_cast(i)); + loadEffFakeForPID(static_cast(i)); + } + } + + if (cfgRunGetEff || cfgRunGetMCFlat || cfgRunMCMean || cfgRunMCFluc) { + TList* pidList = ccdb->getForTimeStamp(pathNsig, now); + + if (!pidList) { + LOGF(warn, "nSigma maps required but CCDB list is null at %s! Using raw values.", pathNsig.c_str()); + } else { + if (!pidMeanSigmaMap) + pidMeanSigmaMap = new PIDMeanSigmaMap(); + + LOGF(info, "Performing 2D Gaussian fits on PID maps from CCDB..."); + + auto loadPIDMeans = [&](PIDIdx pidType) { + std::string suffix = pidSuffix[pidType]; + std::string hName = "h3DnsigmaTpcVsTofBefCut_Cent" + suffix; + auto* h3 = reinterpret_cast(pidList->FindObject(hName.c_str())); + + if (!h3) { + LOGF(warn, " [!] PID Hist %s not found in CCDB list.", hName.c_str()); + return; + } + + int nCentBins = std::min(h3->GetXaxis()->GetNbins(), PIDMeanSigmaMap::MaxCentBins - 1); + LOGF(info, " -> Species: %s (Bins: %d)", hName.c_str(), nCentBins); + + for (int iCent = 1; iCent <= nCentBins; ++iCent) { + h3->GetXaxis()->SetRange(iCent, iCent); + // Projecting: Z(TPC) vs Y(TOF). Result: X_axis=TOF, Y_axis=TPC + std::unique_ptr h2(reinterpret_cast(h3->Project3D("zy"))); + if (h2) { + TF2 f2("f2", "[0]*TMath::Gaus(x,[1],[2])*TMath::Gaus(y,[3],[4])", -3, 3, -3, 3); + // Initial Parameters: Amp, MeanTOF, SigmaTOF, MeanTPC, SigmaTPC + f2.SetParameter(0, h2->GetMaximum()); + f2.SetParameter(1, 0.0); + f2.SetParLimits(1, -2, 2); + + h2->Fit(&f2, "QRN"); + pidMeanSigmaMap->meanTOF[pidType][iCent - 1] = f2.GetParameter(1); + pidMeanSigmaMap->meanTPC[pidType][iCent - 1] = f2.GetParameter(3); + pidMeanSigmaMap->sigmaTOF[pidType][iCent - 1] = std::abs(f2.GetParameter(2)); + pidMeanSigmaMap->sigmaTPC[pidType][iCent - 1] = std::abs(f2.GetParameter(4)); + + if (iCent % KConstTen == 0) { + LOGF(info, " Bin %d: Mean TOF = %.3f, Mean TPC = %.3f", + iCent - 1, f2.GetParameter(1), f2.GetParameter(3)); + } + } + } + }; + for (int i = 0; i < KNsp; ++i) { + loadPIDMeans(static_cast(i)); + } + } + } + + if (cfgRunGetDataFlat || cfgRunDataMean || cfgRunDataFluc) { + TList* pidList = ccdb->getForTimeStamp(pathDataNsig, now); + + if (!pidList) { + LOGF(warn, "nSigma maps required but CCDB list is null at %s! Using raw values.", pathDataNsig.c_str()); + } else { + if (!pidMeanSigmaMap) + pidMeanSigmaMap = new PIDMeanSigmaMap(); + + LOGF(info, "Performing 2D Gaussian fits on PID maps from CCDB..."); + + auto loadPIDMeans = [&](PIDIdx pidType) { + std::string suffix = pidSuffix[pidType]; + std::string hName = "h3DnsigmaTpcVsTofBefCut_Cent" + suffix; + auto* h3 = reinterpret_cast(pidList->FindObject(hName.c_str())); + + if (!h3) { + LOGF(warn, " [!] PID Hist %s not found in CCDB list.", hName.c_str()); + return; + } + + int nCentBins = std::min(h3->GetXaxis()->GetNbins(), PIDMeanSigmaMap::MaxCentBins - 1); + LOGF(info, " -> Species: %s (Bins: %d)", hName.c_str(), nCentBins); + + for (int iCent = 1; iCent <= nCentBins; ++iCent) { + h3->GetXaxis()->SetRange(iCent, iCent); + // Projecting: Z(TPC) vs Y(TOF). Result: X_axis=TOF, Y_axis=TPC + std::unique_ptr h2(reinterpret_cast(h3->Project3D("zy"))); + if (h2) { + TF2 f2("f2", "[0]*TMath::Gaus(x,[1],[2])*TMath::Gaus(y,[3],[4])", -3, 3, -3, 3); + // Initial Parameters: Amp, MeanTOF, SigmaTOF, MeanTPC, SigmaTPC + f2.SetParameter(0, h2->GetMaximum()); + f2.SetParameter(1, 0.0); + f2.SetParLimits(1, -2, 2); + + h2->Fit(&f2, "QRN"); + pidMeanSigmaMap->meanTOF[pidType][iCent - 1] = f2.GetParameter(1); + pidMeanSigmaMap->meanTPC[pidType][iCent - 1] = f2.GetParameter(3); + pidMeanSigmaMap->sigmaTOF[pidType][iCent - 1] = std::abs(f2.GetParameter(2)); + pidMeanSigmaMap->sigmaTPC[pidType][iCent - 1] = std::abs(f2.GetParameter(4)); + + if (iCent % KConstTen == 0) { + LOGF(info, " Bin %d: Mean TOF = %.3f, Mean TPC = %.3f", + iCent - 1, f2.GetParameter(1), f2.GetParameter(3)); + } + } + } + }; + for (int i = 0; i < KNsp; ++i) { + loadPIDMeans(static_cast(i)); + } } } @@ -959,7 +1321,7 @@ struct RadialFlowDecorr { auto* hRaw = reinterpret_cast(lstDataFlat->FindObject(hName.c_str())); if (hRaw) { - hFlatWeight[i] = buildWeightMapFromRaw(hRaw, Form("hFlatWeight%s", suffix.c_str())); + state.hFlatWeight[i] = buildWeightMapFromRaw(hRaw, Form("hFlatWeight%s", suffix.c_str())); } else { LOGF(error, "Data flattening map '%s' not found.", hName.c_str()); } @@ -974,28 +1336,28 @@ struct RadialFlowDecorr { TList* lstMCFlat = ccdb->getForTimeStamp(pathMCFlat, now); if (lstMCFlat) { - auto loadFlatForPID = [&](PID pidType) { + auto loadFlatForPID = [&](PIDIdx pidType) { std::string suffix = pidSuffix[pidType]; std::string hFlatSrcName; if (cfgEff && cfgFlat) { - hFlatSrcName = "hEtaPhiRecoWtd" + suffix; + hFlatSrcName = "MCReco/hEtaPhiRecoWtd" + suffix; } else if (cfgEff) { - hFlatSrcName = "hEtaPhiRecoEffWtd" + suffix; + hFlatSrcName = "MCReco/hEtaPhiRecoEffWtd" + suffix; } else { - hFlatSrcName = "hEtaPhiReco" + suffix; + hFlatSrcName = "MCReco/hEtaPhiReco" + suffix; } auto* hRaw = reinterpret_cast(lstMCFlat->FindObject(hFlatSrcName.c_str())); if (hRaw) { - hFlatWeight[pidType] = buildWeightMapFromRaw(hRaw, Form("hFlatWeight%s", suffix.c_str())); + state.hFlatWeight[pidType] = buildWeightMapFromRaw(hRaw, Form("hFlatWeight%s", suffix.c_str())); } else { LOGF(warning, "MC flattening source '%s' not found in list.", hFlatSrcName.c_str()); } }; for (int i = 0; i < KNsp; ++i) { - loadFlatForPID(static_cast(i)); + loadFlatForPID(static_cast(i)); } } else { LOGF(error, "Could not retrieve MC Flattening TList from: %s", pathMCFlat.c_str()); @@ -1034,16 +1396,16 @@ struct RadialFlowDecorr { TList* lstMCMean = ccdb->getForTimeStamp(pathMCMean, now); if (lstMCMean) { - loadTProfileFromList(lstMCMean, "pmeanFT0Amultpv", pmeanFT0AmultpvStep2); - loadTProfileFromList(lstMCMean, "pmeanFT0Cmultpv", pmeanFT0CmultpvStep2); + loadTProfileFromList(lstMCMean, "pmeanFT0Amultpv", state.pmeanFT0AmultpvStep2); + loadTProfileFromList(lstMCMean, "pmeanFT0Cmultpv", state.pmeanFT0CmultpvStep2); - loadTProfile3DFromList(lstMCMean, "pmeanTru_nch_etabin_spbin", pmeanTruNchEtabinSpbinStep2); - loadTProfile3DFromList(lstMCMean, "pmeanReco_nch_etabin_spbin", pmeanRecoNchEtabinSpbinStep2); - loadTProfile3DFromList(lstMCMean, "pmeanRecoEffcorr_nch_etabin_spbin", pmeanRecoEffcorrNchEtabinSpbinStep2); + loadTProfile3DFromList(lstMCMean, "pmeanTru_nch_etabin_spbin", state.pmeanTruNchEtabinSpbinStep2); + loadTProfile3DFromList(lstMCMean, "pmeanReco_nch_etabin_spbin", state.pmeanRecoNchEtabinSpbinStep2); + loadTProfile3DFromList(lstMCMean, "pmeanRecoEffcorr_nch_etabin_spbin", state.pmeanRecoEffcorrNchEtabinSpbinStep2); - loadTProfile3DFromList(lstMCMean, "pmeanMultTru_nch_etabin_spbin", pmeanMultTruNchEtabinSpbinStep2); - loadTProfile3DFromList(lstMCMean, "pmeanMultReco_nch_etabin_spbin", pmeanMultRecoNchEtabinSpbinStep2); - loadTProfile3DFromList(lstMCMean, "pmeanMultRecoEffcorr_nch_etabin_spbin", pmeanMultRecoEffcorrNchEtabinSpbinStep2); + loadTProfile3DFromList(lstMCMean, "pmeanMultTru_nch_etabin_spbin", state.pmeanMultTruNchEtabinSpbinStep2); + loadTProfile3DFromList(lstMCMean, "pmeanMultReco_nch_etabin_spbin", state.pmeanMultRecoNchEtabinSpbinStep2); + loadTProfile3DFromList(lstMCMean, "pmeanMultRecoEffcorr_nch_etabin_spbin", state.pmeanMultRecoEffcorrNchEtabinSpbinStep2); } else { LOGF(error, "Could not retrieve TList for MC Mean from: %s", pathMCMean.c_str()); } @@ -1054,11 +1416,11 @@ struct RadialFlowDecorr { TList* lstDataMean = ccdb->getForTimeStamp(pathDataMean, now); if (lstDataMean) { - loadTProfileFromList(lstDataMean, "pmeanFT0Amultpv", pmeanFT0AmultpvStep2); - loadTProfileFromList(lstDataMean, "pmeanFT0Cmultpv", pmeanFT0CmultpvStep2); + loadTProfileFromList(lstDataMean, "pmeanFT0Amultpv", state.pmeanFT0AmultpvStep2); + loadTProfileFromList(lstDataMean, "pmeanFT0Cmultpv", state.pmeanFT0CmultpvStep2); - loadTProfile3DFromList(lstDataMean, "pmean_nch_etabin_spbin", pmeanNchEtabinSpbinStep2); - loadTProfile3DFromList(lstDataMean, "pmeanMult_nch_etabin_spbin", pmeanMultNchEtabinSpbinStep2); + loadTProfile3DFromList(lstDataMean, "pmean_nch_etabin_spbin", state.pmeanNchEtabinSpbinStep2); + loadTProfile3DFromList(lstDataMean, "pmeanMult_nch_etabin_spbin", state.pmeanMultNchEtabinSpbinStep2); } else { LOGF(error, "Could not retrieve TList for Data Mean from: %s", pathDataMean.c_str()); } @@ -1066,6 +1428,44 @@ struct RadialFlowDecorr { LOGF(info, "CCDB initialization complete for RadialFlowDecorr."); } + void processMCGetMeanNsig(aod::McCollisions const& mcColl, MyRun3MCCollisions const& collisions, TCs const& tracks, FilteredTCs const& /*filteredTracks*/, aod::McParticles const& mcParticles) + { + for (const auto& mcCollision : mcColl) { + auto colSlice = collisions.sliceBy(colPerMcCollision, mcCollision.globalIndex()); + if (colSlice.size() != 1) + continue; + for (const auto& col : colSlice) { + histos.fill(HIST("hVtxZ"), col.posZ()); + if (!col.has_mcCollision() || !isEventSelected(col)) + continue; + auto trackSlice = tracks.sliceBy(trackPerCollision, col.globalIndex()); + auto partSlice = mcParticles.sliceBy(partPerMcCollision, mcCollision.globalIndex()); + if (trackSlice.size() < 1 || partSlice.size() < 1) + continue; + float cent = getCentrality(col); + if (cent > KCentMax) + continue; + float multPV = col.multNTracksPV(); + for (const auto& particle : partSlice) { + if (!isParticleSelected(particle) || !particle.isPhysicalPrimary()) + continue; + histos.fill(HIST("hVtxZ_after_sel"), col.posZ()); + histos.fill(HIST("hCentrality"), cent); + + histos.fill(HIST("Hist2D_globalTracks_PVTracks"), multPV, trackSlice.size()); + histos.fill(HIST("Hist2D_cent_nch"), trackSlice.size(), cent); + + for (const auto& track : trackSlice) { + if (!isTrackSelected(track)) + continue; + fillNSigmaBefCut(track, cent); + } + } + } + } + } + PROCESS_SWITCH(RadialFlowDecorr, processMCGetMeanNsig, "process MC to calculate Mean values of nSig Plots", cfgRunMCGetNSig); + void processGetEffHists(aod::McCollisions const& mcColl, MyRun3MCCollisions const& collisions, TCs const& tracks, FilteredTCs const& /*filteredTracks*/, aod::McParticles const& mcParticles) { for (const auto& mcCollision : mcColl) { @@ -1074,10 +1474,8 @@ struct RadialFlowDecorr { continue; for (const auto& col : colSlice) { - if (!col.has_mcCollision()) - continue; histos.fill(HIST("hVtxZ"), col.posZ()); - if (!isEventSelected(col)) + if (!col.has_mcCollision() || !isEventSelected(col)) continue; auto trackSlice = tracks.sliceBy(trackPerCollision, col.globalIndex()); @@ -1086,220 +1484,264 @@ struct RadialFlowDecorr { continue; float cent = getCentrality(col); + if (cent > KCentMax) continue; float multPV = col.multNTracksPV(); - - histos.fill(HIST("hZvtx_after_sel"), col.posZ()); - histos.fill(HIST("hCentrality"), cent); - histos.fill(HIST("Hist2D_globalTracks_PVTracks"), multPV, tracks.size()); - histos.fill(HIST("Hist2D_cent_nch"), multPV, cent); + float vz = col.posZ(); for (const auto& particle : partSlice) { if (!isParticleSelected(particle) || !particle.isPhysicalPrimary()) continue; - const int pdgCode = particle.pdgCode(); - const int absPdg = std::abs(pdgCode); - float pt = particle.pt(); - float eta = particle.eta(); + const int pdg = particle.pdgCode(); + const int absPdg = std::abs(pdg); + float pt = particle.pt(), eta = particle.eta(); + bool isSpecies[KNsp] = { - true, // kInclusive - pdgCode == kPiMinus, // kPiMinus - pdgCode == kPiPlus, // kPiPlus - absPdg == kPiPlus, // kPiAll - pdgCode == kKMinus, // kKaMinus - pdgCode == kKPlus, // kKaPlus - absPdg == kKPlus, // kKaAll - pdgCode == kProtonBar, // kAntiProton - pdgCode == kProton, // kProton - absPdg == kProton // kAllProton + true, // kInclusiveIdx + pdg == -KPiPlus, // kPiMinusIdx + pdg == KPiPlus, // kPiPlusIdx + absPdg == KPiPlus, // kPiAllIdx + pdg == -KKPlus, // kKaMinusIdx + pdg == KKPlus, // kKaPlusIdx + absPdg == KKPlus, // kKaAllIdx + pdg == -KProton, // kAntiPrIdx + pdg == KProton, // kPrIdx + absPdg == KProton // kPrAllIdx }; histos.fill(HIST("h3_AllPrimary"), multPV, pt, eta); - - if (isSpecies[kPiMinus]) + if (isSpecies[kPiMinusIdx]) histos.fill(HIST("h3_AllPrimary_PiMinus"), multPV, pt, eta); - else if (isSpecies[kPiPlus]) + else if (isSpecies[kPiPlusIdx]) histos.fill(HIST("h3_AllPrimary_PiPlus"), multPV, pt, eta); - if (isSpecies[kPiAll]) + if (isSpecies[kPiAllIdx]) histos.fill(HIST("h3_AllPrimary_PiAll"), multPV, pt, eta); - if (isSpecies[kKaMinus]) + if (isSpecies[kKaMinusIdx]) histos.fill(HIST("h3_AllPrimary_KaMinus"), multPV, pt, eta); - else if (isSpecies[kKaPlus]) + else if (isSpecies[kKaPlusIdx]) histos.fill(HIST("h3_AllPrimary_KaPlus"), multPV, pt, eta); - if (isSpecies[kKaAll]) + if (isSpecies[kKaAllIdx]) histos.fill(HIST("h3_AllPrimary_KaAll"), multPV, pt, eta); - if (isSpecies[kAntiProton]) + if (isSpecies[kAntiPrIdx]) histos.fill(HIST("h3_AllPrimary_AntiPr"), multPV, pt, eta); - else if (isSpecies[kProton]) + else if (isSpecies[kPrIdx]) histos.fill(HIST("h3_AllPrimary_Pr"), multPV, pt, eta); - if (isSpecies[kAllProton]) - histos.fill(HIST("h3_AllPrimary_AllPr"), multPV, pt, eta); + if (isSpecies[kPrAllIdx]) + histos.fill(HIST("h3_AllPrimary_PrAll"), multPV, pt, eta); } + histos.fill(HIST("hVtxZ_after_sel"), col.posZ()); + histos.fill(HIST("hCentrality"), cent); + + histos.fill(HIST("Hist2D_globalTracks_PVTracks"), multPV, trackSlice.size()); + histos.fill(HIST("Hist2D_cent_nch"), trackSlice.size(), cent); + for (const auto& track : trackSlice) { if (!isTrackSelected(track)) continue; - float pt = track.pt(); - float eta = track.eta(); - float phi = track.phi(); + float pt = track.pt(), eta = track.eta(); auto sign = track.sign(); + fillNSigmaBefCut(track, cent); - bool isPi = selectionPion(track); - bool isKa = selectionKaon(track); - bool isPr = selectionProton(track); + int centBin = static_cast(cent); + int id = identifyTrack(track, centBin); + bool isPi = (id == KPidPionOne); + bool isKa = (id == KPidKaonTwo); + bool isPr = (id == KPidProtonThree); bool isSpecies[KNsp] = { - true, // kInclusive - isPi && sign < 0, // kPiMinus - isPi && sign > 0, // kPiPlus - isPi, // kPiAll - isKa && sign < 0, // kKaMinus - isKa && sign > 0, // kKaPlus - isKa, // kKaAll - isPr && sign < 0, // kAntiProton - isPr && sign > 0, // kProton - isPr // kAllProton - }; + true, + isPi && sign < 0, isPi && sign > 0, isPi, + isKa && sign < 0, isKa && sign > 0, isKa, + isPr && sign < 0, isPr && sign > 0, isPr}; for (int isp = 0; isp < KNsp; ++isp) { if (!isSpecies[isp]) continue; - if (isp == kInclusive) { + fillNSigmaAftCut(track, cent, isSpecies); + + if (isp == kInclusiveIdx) { histos.fill(HIST("h3_AllReco"), multPV, pt, eta); - histos.fill(HIST("hEtaPhiReco"), col.posZ(), sign, pt, eta, phi); if (track.has_mcParticle()) { auto mcP = track.mcParticle(); - if (mcP.isPhysicalPrimary()) { - histos.fill(HIST("ptResolution"), mcP.pt(), (pt - mcP.pt()) / mcP.pt()); - histos.fill(HIST("etaResolution"), mcP.eta(), eta - mcP.eta()); - histos.fill(HIST("etaTruthReco"), mcP.eta(), eta); - histos.fill(HIST("vzResolution"), mcP.vz(), (col.posZ() - mcP.vz()) / mcP.vz()); - histos.fill(HIST("TruthTracKVz"), mcP.vz(), col.posZ()); - - histos.fill(HIST("h3_RecoMatchedToPrimary"), multPV, mcP.pt(), mcP.eta()); + int mcPdg = std::abs(mcP.pdgCode()); + if (mcPdg == KPiPlus || mcPdg == KKPlus || mcPdg == KProton) { + histos.fill(HIST("ptResolution"), mcP.pt(), (pt - mcP.pt()) / mcP.pt()); + histos.fill(HIST("etaResolution"), mcP.eta(), eta - mcP.eta()); + histos.fill(HIST("etaTruthReco"), mcP.eta(), eta); + histos.fill(HIST("vzResolution"), mcP.vz(), (vz - mcP.vz()) / mcP.vz()); + histos.fill(HIST("TruthTracKVz"), mcP.vz(), vz); + histos.fill(HIST("h3_RecoMatchedToPrimary"), multPV, mcP.pt(), mcP.eta()); + } else { + // Misidentified! Reconstructed track, but true particle is not pi/K/P + histos.fill(HIST("h3_RecoMatchedToPrimary_MisID"), multPV, pt, eta); + } } else { histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary"), multPV, pt, eta); - histos.fill(HIST("h_RecoUnMatchedToPrimary"), pt); } } else { histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake"), multPV, pt, eta); } - } else if (isp == kPiMinus) { + } else if (isp == kPiMinusIdx) { histos.fill(HIST("h3_AllReco_PiMinus"), multPV, pt, eta); if (track.has_mcParticle()) { auto mcP = track.mcParticle(); - if (mcP.isPhysicalPrimary() && mcP.pdgCode() == kPiMinus) - histos.fill(HIST("h3_RecoMatchedToPrimary_PiMinus"), multPV, mcP.pt(), mcP.eta()); - else if (!mcP.isPhysicalPrimary()) + if (mcP.isPhysicalPrimary()) { + if (mcP.pdgCode() == -KPiPlus) { + histos.fill(HIST("h3_RecoMatchedToPrimary_PiMinus"), multPV, mcP.pt(), mcP.eta()); + } else { // Misidentified + histos.fill(HIST("h3_RecoMatchedToPrimary_MisID_PiMinus"), multPV, pt, eta); + } + } else { histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_PiMinus"), multPV, pt, eta); - } else { + } + } else { // No MC histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_PiMinus"), multPV, pt, eta); } - } else if (isp == kPiPlus) { + } else if (isp == kPiPlusIdx) { histos.fill(HIST("h3_AllReco_PiPlus"), multPV, pt, eta); if (track.has_mcParticle()) { auto mcP = track.mcParticle(); - if (mcP.isPhysicalPrimary() && mcP.pdgCode() == kPiPlus) - histos.fill(HIST("h3_RecoMatchedToPrimary_PiPlus"), multPV, mcP.pt(), mcP.eta()); - else if (!mcP.isPhysicalPrimary()) + if (mcP.isPhysicalPrimary()) { + if (mcP.pdgCode() == KPiPlus) { + histos.fill(HIST("h3_RecoMatchedToPrimary_PiPlus"), multPV, mcP.pt(), mcP.eta()); + } else { // Misidentified + histos.fill(HIST("h3_RecoMatchedToPrimary_MisID_PiPlus"), multPV, pt, eta); + } + } else { histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_PiPlus"), multPV, pt, eta); + } } else { histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_PiPlus"), multPV, pt, eta); } - } else if (isp == kPiAll) { + } else if (isp == kPiAllIdx) { histos.fill(HIST("h3_AllReco_PiAll"), multPV, pt, eta); if (track.has_mcParticle()) { auto mcP = track.mcParticle(); - if (mcP.isPhysicalPrimary() && std::abs(mcP.pdgCode()) == kPiPlus) - histos.fill(HIST("h3_RecoMatchedToPrimary_PiAll"), multPV, mcP.pt(), mcP.eta()); - else if (!mcP.isPhysicalPrimary()) + if (mcP.isPhysicalPrimary()) { + if (std::abs(mcP.pdgCode()) == KPiPlus) { + histos.fill(HIST("h3_RecoMatchedToPrimary_PiAll"), multPV, mcP.pt(), mcP.eta()); + } else { // Misidentified + histos.fill(HIST("h3_RecoMatchedToPrimary_MisID_PiAll"), multPV, pt, eta); + } + } else { histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_PiAll"), multPV, pt, eta); + } } else { histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_PiAll"), multPV, pt, eta); } - } else if (isp == kKaMinus) { + } else if (isp == kKaMinusIdx) { histos.fill(HIST("h3_AllReco_KaMinus"), multPV, pt, eta); if (track.has_mcParticle()) { auto mcP = track.mcParticle(); - if (mcP.isPhysicalPrimary() && mcP.pdgCode() == kKMinus) - histos.fill(HIST("h3_RecoMatchedToPrimary_KaMinus"), multPV, mcP.pt(), mcP.eta()); - else if (!mcP.isPhysicalPrimary()) + if (mcP.isPhysicalPrimary()) { + if (mcP.pdgCode() == -KKPlus) { + histos.fill(HIST("h3_RecoMatchedToPrimary_KaMinus"), multPV, mcP.pt(), mcP.eta()); + } else { // Misidentified + histos.fill(HIST("h3_RecoMatchedToPrimary_MisID_KaMinus"), multPV, pt, eta); + } + } else { histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_KaMinus"), multPV, pt, eta); + } } else { histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_KaMinus"), multPV, pt, eta); } - } else if (isp == kKaPlus) { + } else if (isp == kKaPlusIdx) { histos.fill(HIST("h3_AllReco_KaPlus"), multPV, pt, eta); if (track.has_mcParticle()) { auto mcP = track.mcParticle(); - if (mcP.isPhysicalPrimary() && mcP.pdgCode() == kKPlus) - histos.fill(HIST("h3_RecoMatchedToPrimary_KaPlus"), multPV, mcP.pt(), mcP.eta()); - else if (!mcP.isPhysicalPrimary()) + if (mcP.isPhysicalPrimary()) { + if (mcP.pdgCode() == KKPlus) { + histos.fill(HIST("h3_RecoMatchedToPrimary_KaPlus"), multPV, mcP.pt(), mcP.eta()); + } else { // Misidentified + histos.fill(HIST("h3_RecoMatchedToPrimary_MisID_KaPlus"), multPV, pt, eta); + } + } else { histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_KaPlus"), multPV, pt, eta); + } } else { histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_KaPlus"), multPV, pt, eta); } - } else if (isp == kKaAll) { + } else if (isp == kKaAllIdx) { histos.fill(HIST("h3_AllReco_KaAll"), multPV, pt, eta); if (track.has_mcParticle()) { auto mcP = track.mcParticle(); - if (mcP.isPhysicalPrimary() && std::abs(mcP.pdgCode()) == kKPlus) - histos.fill(HIST("h3_RecoMatchedToPrimary_KaAll"), multPV, mcP.pt(), mcP.eta()); - else if (!mcP.isPhysicalPrimary()) + if (mcP.isPhysicalPrimary()) { + if (std::abs(mcP.pdgCode()) == KKPlus) { + histos.fill(HIST("h3_RecoMatchedToPrimary_KaAll"), multPV, mcP.pt(), mcP.eta()); + } else { // Misidentified + histos.fill(HIST("h3_RecoMatchedToPrimary_MisID_KaAll"), multPV, pt, eta); + } + } else { histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_KaAll"), multPV, pt, eta); + } } else { histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_KaAll"), multPV, pt, eta); } - } else if (isp == kAntiProton) { + } else if (isp == kAntiPrIdx) { histos.fill(HIST("h3_AllReco_AntiPr"), multPV, pt, eta); if (track.has_mcParticle()) { auto mcP = track.mcParticle(); - if (mcP.isPhysicalPrimary() && mcP.pdgCode() == kProtonBar) - histos.fill(HIST("h3_RecoMatchedToPrimary_AntiPr"), multPV, mcP.pt(), mcP.eta()); - else if (!mcP.isPhysicalPrimary()) + if (mcP.isPhysicalPrimary()) { + if (mcP.pdgCode() == -KProton) { + histos.fill(HIST("h3_RecoMatchedToPrimary_AntiPr"), multPV, mcP.pt(), mcP.eta()); + } else { // Misidentified + histos.fill(HIST("h3_RecoMatchedToPrimary_MisID_AntiPr"), multPV, pt, eta); + } + } else { histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_AntiPr"), multPV, pt, eta); + } } else { histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_AntiPr"), multPV, pt, eta); } - } else if (isp == kProton) { + } else if (isp == kPrIdx) { histos.fill(HIST("h3_AllReco_Pr"), multPV, pt, eta); if (track.has_mcParticle()) { auto mcP = track.mcParticle(); - if (mcP.isPhysicalPrimary() && mcP.pdgCode() == kProton) - histos.fill(HIST("h3_RecoMatchedToPrimary_Pr"), multPV, mcP.pt(), mcP.eta()); - else if (!mcP.isPhysicalPrimary()) + if (mcP.isPhysicalPrimary()) { + if (mcP.pdgCode() == KProton) { + histos.fill(HIST("h3_RecoMatchedToPrimary_Pr"), multPV, mcP.pt(), mcP.eta()); + } else { // Misidentified + histos.fill(HIST("h3_RecoMatchedToPrimary_MisID_Pr"), multPV, pt, eta); + } + } else { histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_Pr"), multPV, pt, eta); + } } else { histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_Pr"), multPV, pt, eta); } - } else if (isp == kAllProton) { - histos.fill(HIST("h3_AllReco_AllPr"), multPV, pt, eta); + } else if (isp == kPrAllIdx) { + histos.fill(HIST("h3_AllReco_PrAll"), multPV, pt, eta); if (track.has_mcParticle()) { auto mcP = track.mcParticle(); - if (mcP.isPhysicalPrimary() && std::abs(mcP.pdgCode()) == kProton) - histos.fill(HIST("h3_RecoMatchedToPrimary_AllPr"), multPV, mcP.pt(), mcP.eta()); - else if (!mcP.isPhysicalPrimary()) - histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_AllPr"), multPV, pt, eta); + if (mcP.isPhysicalPrimary()) { + if (std::abs(mcP.pdgCode()) == KProton) { + histos.fill(HIST("h3_RecoMatchedToPrimary_PrAll"), multPV, mcP.pt(), mcP.eta()); + } else { // Misidentified + histos.fill(HIST("h3_RecoMatchedToPrimary_MisID_PrAll"), multPV, pt, eta); + } + } else { + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_PrAll"), multPV, pt, eta); + } } else { - histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_AllPr"), multPV, pt, eta); + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_PrAll"), multPV, pt, eta); } } - } // end isp loop - } // end track loop + } + } } } - LOGF(info, "FINISHED RUNNING processGetEffHists"); } PROCESS_SWITCH(RadialFlowDecorr, processGetEffHists, "process MC to calculate EffWeights", cfgRunGetEff); - void processMCFlat(aod::McCollisions const& mcColl, MyRun3MCCollisions const& collisions, /*soa::SmallGroups const& collisions,*/ TCs const& tracks, FilteredTCs const& /*filteredTracks*/, aod::McParticles const& mcParticles) + void processMCFlat(aod::McCollisions const& mcColl, MyRun3MCCollisions const& collisions, TCs const& tracks, FilteredTCs const& /*filteredTracks*/) { for (const auto& mcCollision : mcColl) { auto colSlice = collisions.sliceBy(colPerMcCollision, mcCollision.globalIndex()); @@ -1309,87 +1751,96 @@ struct RadialFlowDecorr { for (const auto& col : colSlice) { if (!col.has_mcCollision() || !isEventSelected(col)) continue; + + float cent = getCentrality(col); + if (cent > KCentMax) + continue; + auto trackSlice = tracks.sliceBy(trackPerCollision, col.globalIndex()); - auto partSlice = mcParticles.sliceBy(partPerMcCollision, mcCollision.globalIndex()); - if (trackSlice.size() < 1 || partSlice.size() < 1) + if (trackSlice.size() < 1) continue; float multPV = col.multNTracksPV(); float vz = col.posZ(); + histos.fill(HIST("hVtxZ_after_sel"), col.posZ()); + histos.fill(HIST("hCentrality"), cent); + + histos.fill(HIST("Hist2D_globalTracks_PVTracks"), col.multNTracksPV(), trackSlice.size()); + histos.fill(HIST("Hist2D_cent_nch"), trackSlice.size(), cent); for (const auto& track : trackSlice) { if (!isTrackSelected(track)) continue; - float pt = track.pt(); - float eta = track.eta(); - float phi = track.phi(); + float pt = track.pt(), eta = track.eta(), phi = track.phi(); auto sign = track.sign(); - - bool isPi = selectionPion(track); - bool isKa = selectionKaon(track); - bool isPr = selectionProton(track); + int centBin = static_cast(cent); + int id = identifyTrack(track, centBin); + bool isPi = (id == KPidPionOne); + bool isKa = (id == KPidKaonTwo); + bool isPr = (id == KPidProtonThree); bool isSpecies[KNsp] = { - true, // kInclusive - isPi && sign < 0, // kPiMinus - isPi && sign > 0, // kPiPlus - isPi, // kPiAll - isKa && sign < 0, // kKaMinus - isKa && sign > 0, // kKaPlus - isKa, // kKaAll - isPr && sign < 0, // kAntiProton (Negative) - isPr && sign > 0, // kProton (Positive) - isPr // kAllProton - }; + true, + isPi && sign < 0, isPi && sign > 0, isPi, + isKa && sign < 0, isKa && sign > 0, isKa, + isPr && sign < 0, isPr && sign > 0, isPr}; for (int isp = 0; isp < KNsp; ++isp) { if (!isSpecies[isp]) continue; - std::string suffix = pidSuffix[isp]; - - float eff = getEfficiency(multPV, pt, eta, static_cast(isp), 0, cfgEff); - float fake = getEfficiency(multPV, pt, eta, static_cast(isp), 1, cfgEff); - float w = (1.0 - fake) / eff; - - if (std::isfinite(w) && w > 0.f && eff > KFloatEpsilon) { - if (isp == kInclusive) { - histos.fill(HIST("hEtaPhiRecoEffWtd"), vz, sign, pt, eta, phi, w); - histos.fill(HIST("hEtaPhiReco"), vz, sign, pt, eta, phi, 1.0); - } else if (isp == kPiMinus) { - histos.fill(HIST("hEtaPhiRecoEffWtd_PiMinus"), vz, sign, pt, eta, phi, w); - histos.fill(HIST("hEtaPhiReco_PiMinus"), vz, sign, pt, eta, phi, 1.0); - } else if (isp == kPiPlus) { - histos.fill(HIST("hEtaPhiRecoEffWtd_PiPlus"), vz, sign, pt, eta, phi, w); - histos.fill(HIST("hEtaPhiReco_PiPlus"), vz, sign, pt, eta, phi, 1.0); - } else if (isp == kPiAll) { - histos.fill(HIST("hEtaPhiRecoEffWtd_PiAll"), vz, sign, pt, eta, phi, w); - histos.fill(HIST("hEtaPhiReco_PiAll"), vz, sign, pt, eta, phi, 1.0); - } else if (isp == kKaMinus) { - histos.fill(HIST("hEtaPhiRecoEffWtd_KaMinus"), vz, sign, pt, eta, phi, w); - histos.fill(HIST("hEtaPhiReco_KaMinus"), vz, sign, pt, eta, phi, 1.0); - } else if (isp == kKaPlus) { - histos.fill(HIST("hEtaPhiRecoEffWtd_KaPlus"), vz, sign, pt, eta, phi, w); - histos.fill(HIST("hEtaPhiReco_KaPlus"), vz, sign, pt, eta, phi, 1.0); - } else if (isp == kKaAll) { - histos.fill(HIST("hEtaPhiRecoEffWtd_KaAll"), vz, sign, pt, eta, phi, w); - histos.fill(HIST("hEtaPhiReco_KaAll"), vz, sign, pt, eta, phi, 1.0); - } else if (isp == kAntiProton) { - histos.fill(HIST("hEtaPhiRecoEffWtd_AntiPr"), vz, sign, pt, eta, phi, w); - histos.fill(HIST("hEtaPhiReco_AntiPr"), vz, sign, pt, eta, phi, 1.0); - } else if (isp == kProton) { - histos.fill(HIST("hEtaPhiRecoEffWtd_Pr"), vz, sign, pt, eta, phi, w); - histos.fill(HIST("hEtaPhiReco_Pr"), vz, sign, pt, eta, phi, 1.0); - } else if (isp == kAllProton) { - histos.fill(HIST("hEtaPhiRecoEffWtd_AllPr"), vz, sign, pt, eta, phi, w); - histos.fill(HIST("hEtaPhiReco_AllPr"), vz, sign, pt, eta, phi, 1.0); + + float eff = getEfficiency(multPV, pt, eta, static_cast(isp), 0, cfgEff); + float fake = getEfficiency(multPV, pt, eta, static_cast(isp), 1, cfgEff); + float w = (eff > KFloatEpsilon) ? (1.0f - fake) / eff : 0.0f; + + if (std::isfinite(w) && w > 0.f) { + if (isp == kInclusiveIdx) { + histos.fill(HIST("MCReco/hEtaPhiRecoEffWtd"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("MCReco/hEtaPhiReco"), vz, sign, pt, eta, phi, 1.0); + histos.fill(HIST("MCReco/hEtaPhiRecoWtd"), vz, sign, pt, eta, phi, w); + } else if (isp == kPiMinusIdx) { + histos.fill(HIST("MCReco/hEtaPhiRecoEffWtd_PiMinus"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("MCReco/hEtaPhiReco_PiMinus"), vz, sign, pt, eta, phi, 1.0); + histos.fill(HIST("MCReco/hEtaPhiRecoWtd_PiMinus"), vz, sign, pt, eta, phi, w); + } else if (isp == kPiPlusIdx) { + histos.fill(HIST("MCReco/hEtaPhiRecoEffWtd_PiPlus"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("MCReco/hEtaPhiReco_PiPlus"), vz, sign, pt, eta, phi, 1.0); + histos.fill(HIST("MCReco/hEtaPhiRecoWtd_PiPlus"), vz, sign, pt, eta, phi, w); + } else if (isp == kPiAllIdx) { + histos.fill(HIST("MCReco/hEtaPhiRecoEffWtd_PiAll"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("MCReco/hEtaPhiReco_PiAll"), vz, sign, pt, eta, phi, 1.0); + histos.fill(HIST("MCReco/hEtaPhiRecoWtd_PiAll"), vz, sign, pt, eta, phi, w); + } else if (isp == kKaMinusIdx) { + histos.fill(HIST("MCReco/hEtaPhiRecoEffWtd_KaMinus"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("MCReco/hEtaPhiReco_KaMinus"), vz, sign, pt, eta, phi, 1.0); + histos.fill(HIST("MCReco/hEtaPhiRecoWtd_KaMinus"), vz, sign, pt, eta, phi, w); + } else if (isp == kKaPlusIdx) { + histos.fill(HIST("MCReco/hEtaPhiRecoEffWtd_KaPlus"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("MCReco/hEtaPhiReco_KaPlus"), vz, sign, pt, eta, phi, 1.0); + histos.fill(HIST("MCReco/hEtaPhiRecoWtd_KaPlus"), vz, sign, pt, eta, phi, w); + } else if (isp == kKaAllIdx) { + histos.fill(HIST("MCReco/hEtaPhiRecoEffWtd_KaAll"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("MCReco/hEtaPhiReco_KaAll"), vz, sign, pt, eta, phi, 1.0); + histos.fill(HIST("MCReco/hEtaPhiRecoWtd_KaAll"), vz, sign, pt, eta, phi, w); + } else if (isp == kAntiPrIdx) { + histos.fill(HIST("MCReco/hEtaPhiRecoEffWtd_AntiPr"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("MCReco/hEtaPhiReco_AntiPr"), vz, sign, pt, eta, phi, 1.0); + histos.fill(HIST("MCReco/hEtaPhiRecoWtd_AntiPr"), vz, sign, pt, eta, phi, w); + } else if (isp == kPrIdx) { + histos.fill(HIST("MCReco/hEtaPhiRecoEffWtd_Pr"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("MCReco/hEtaPhiReco_Pr"), vz, sign, pt, eta, phi, 1.0); + histos.fill(HIST("MCReco/hEtaPhiRecoWtd_Pr"), vz, sign, pt, eta, phi, w); + } else if (isp == kPrAllIdx) { + histos.fill(HIST("MCReco/hEtaPhiRecoEffWtd_PrAll"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("MCReco/hEtaPhiReco_PrAll"), vz, sign, pt, eta, phi, 1.0); + histos.fill(HIST("MCReco/hEtaPhiRecoWtd_PrAll"), vz, sign, pt, eta, phi, w); } } } - } // end track loop - } // end col loop - } // end mcColl loop - LOGF(info, "FINISHED RUNNING processMCFlat"); + } + } + } } PROCESS_SWITCH(RadialFlowDecorr, processMCFlat, "process MC to calculate FlatWeights", cfgRunGetMCFlat); @@ -1430,22 +1881,22 @@ struct RadialFlowDecorr { if (!isParticleSelected(particle) || !particle.isPhysicalPrimary()) continue; float pt = particle.pt(), eta = particle.eta(); - if (pt <= KPtMin || pt > KPtMax) + if (pt <= cfgPtMin || pt > cfgPtMax) continue; int pdgCode = particle.pdgCode(); int absPdg = std::abs(pdgCode); bool isSpecies[KNsp] = { - true, // kInclusive - pdgCode == kPiMinus, // kPiMinus - pdgCode == kPiPlus, // kPiPlus - absPdg == kPiPlus, // kPiAll - pdgCode == kKMinus, // kKaMinus - pdgCode == kKPlus, // kKaPlus - absPdg == kKPlus, // kKaAll - pdgCode == kProtonBar, // kAntiProton - pdgCode == kProton, // kProton - absPdg == kProton // kAllProton + true, // kInclusiveIdx + pdgCode == -KPiPlus, // kPiMinusIdx + pdgCode == KPiPlus, // kPiPlusIdx + absPdg == KPiPlus, // kPiAllIdx + pdgCode == -KKPlus, // kKaMinusIdx + pdgCode == KKPlus, // kKaPlusIdx + absPdg == KKPlus, // kKaAllIdx + pdgCode == -KProton, // kAntiPrIdx + pdgCode == KProton, // kPrIdx + absPdg == KProton // kPrAllIdx }; for (int ieta = 0; ieta < KNEta; ++ieta) { @@ -1470,36 +1921,37 @@ struct RadialFlowDecorr { } } + histos.fill(HIST("hVtxZ_after_sel"), col.posZ()); + histos.fill(HIST("hCentrality"), cent); + + histos.fill(HIST("Hist2D_globalTracks_PVTracks"), col.multNTracksPV(), trackSlice.size()); + histos.fill(HIST("Hist2D_cent_nch"), trackSlice.size(), cent); + for (const auto& track : trackSlice) { if (!isTrackSelected(track)) continue; float pt = track.pt(), eta = track.eta(), phi = track.phi(); - if (pt <= KPtMin || pt > KPtMax) + if (pt <= cfgPtMin || pt > cfgPtMax) continue; auto sign = track.sign(); - bool isPi = selectionPion(track); - bool isKa = selectionKaon(track); - bool isPr = selectionProton(track); + int centBin = static_cast(cent); + int id = identifyTrack(track, centBin); + bool isPi = (id == KPidPionOne); + bool isKa = (id == KPidKaonTwo); + bool isPr = (id == KPidProtonThree); bool isSpecies[KNsp] = { - true, // kInclusive - isPi && sign < 0, // kPiMinus - isPi && sign > 0, // kPiPlus - isPi, // kPiAll - isKa && sign < 0, // kKaMinus - isKa && sign > 0, // kKaPlus - isKa, // kKaAll - isPr && sign < 0, // kAntiProton (Negative) - isPr && sign > 0, // kProton (Positive) - isPr // kAllProton - }; + true, + isPi && sign < 0, isPi && sign > 0, isPi, + isKa && sign < 0, isKa && sign > 0, isKa, + isPr && sign < 0, isPr && sign > 0, isPr}; for (int isp = 0; isp < KNsp; ++isp) { if (!isSpecies[isp]) continue; - float eff = getEfficiency(multPV, pt, eta, static_cast(isp), 0, cfgEff); - float fake = getEfficiency(multPV, pt, eta, static_cast(isp), 1, cfgEff); - float flatW = getFlatteningWeight(vz, sign, pt, eta, phi, static_cast(isp), cfgFlat); + float eff = getEfficiency(multPV, pt, eta, static_cast(isp), 0, cfgEff); + float fake = getEfficiency(multPV, pt, eta, static_cast(isp), 1, cfgEff); + float flatW = getFlatteningWeight(vz, sign, pt, eta, phi, static_cast(isp), cfgFlat); float w = flatW * (1.0 - fake) / eff; if (!std::isfinite(w) || w <= 0.f || eff <= KFloatEpsilon) continue; @@ -1513,7 +1965,7 @@ struct RadialFlowDecorr { sumWiptiRecoEffCorr[isp][ieta] += w * pt; } - if (isp == kInclusive) { + if (isp == kInclusiveIdx) { histos.fill(HIST("Eff_cent"), cent, eff); histos.fill(HIST("Fake_cent"), cent, fake); histos.fill(HIST("wgt_cent"), cent, w); @@ -1531,46 +1983,46 @@ struct RadialFlowDecorr { histos.fill(HIST("wgt_eta"), eta, w); } - if (isp == kInclusive) { + if (isp == kInclusiveIdx) { histos.fill(HIST("hEtaPhiReco"), vz, sign, pt, eta, phi); histos.fill(HIST("hEtaPhiRecoWtd"), vz, sign, pt, eta, phi, w); histos.fill(HIST("hEtaPhiRecoEffWtd"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - } else if (isp == kPiMinus) { + } else if (isp == kPiMinusIdx) { histos.fill(HIST("hEtaPhiReco_PiMinus"), vz, sign, pt, eta, phi); histos.fill(HIST("hEtaPhiRecoWtd_PiMinus"), vz, sign, pt, eta, phi, w); histos.fill(HIST("hEtaPhiRecoEffWtd_PiMinus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - } else if (isp == kPiPlus) { + } else if (isp == kPiPlusIdx) { histos.fill(HIST("hEtaPhiReco_PiPlus"), vz, sign, pt, eta, phi); histos.fill(HIST("hEtaPhiRecoWtd_PiPlus"), vz, sign, pt, eta, phi, w); histos.fill(HIST("hEtaPhiRecoEffWtd_PiPlus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - } else if (isp == kPiAll) { + } else if (isp == kPiAllIdx) { histos.fill(HIST("hEtaPhiReco_PiAll"), vz, sign, pt, eta, phi); histos.fill(HIST("hEtaPhiRecoWtd_PiAll"), vz, sign, pt, eta, phi, w); histos.fill(HIST("hEtaPhiRecoEffWtd_PiAll"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - } else if (isp == kKaMinus) { + } else if (isp == kKaMinusIdx) { histos.fill(HIST("hEtaPhiReco_KaMinus"), vz, sign, pt, eta, phi); histos.fill(HIST("hEtaPhiRecoWtd_KaMinus"), vz, sign, pt, eta, phi, w); histos.fill(HIST("hEtaPhiRecoEffWtd_KaMinus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - } else if (isp == kKaPlus) { + } else if (isp == kKaPlusIdx) { histos.fill(HIST("hEtaPhiReco_KaPlus"), vz, sign, pt, eta, phi); histos.fill(HIST("hEtaPhiRecoWtd_KaPlus"), vz, sign, pt, eta, phi, w); histos.fill(HIST("hEtaPhiRecoEffWtd_KaPlus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - } else if (isp == kKaAll) { + } else if (isp == kKaAllIdx) { histos.fill(HIST("hEtaPhiReco_KaAll"), vz, sign, pt, eta, phi); histos.fill(HIST("hEtaPhiRecoWtd_KaAll"), vz, sign, pt, eta, phi, w); histos.fill(HIST("hEtaPhiRecoEffWtd_KaAll"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - } else if (isp == kProton) { + } else if (isp == kPrIdx) { histos.fill(HIST("hEtaPhiReco_Pr"), vz, sign, pt, eta, phi); histos.fill(HIST("hEtaPhiRecoWtd_Pr"), vz, sign, pt, eta, phi, w); histos.fill(HIST("hEtaPhiRecoEffWtd_Pr"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - } else if (isp == kAntiProton) { + } else if (isp == kAntiPrIdx) { histos.fill(HIST("hEtaPhiReco_AntiPr"), vz, sign, pt, eta, phi); histos.fill(HIST("hEtaPhiRecoWtd_AntiPr"), vz, sign, pt, eta, phi, w); histos.fill(HIST("hEtaPhiRecoEffWtd_AntiPr"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - } else if (isp == kAllProton) { - histos.fill(HIST("hEtaPhiReco_AllPr"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoWtd_AllPr"), vz, sign, pt, eta, phi, w); - histos.fill(HIST("hEtaPhiRecoEffWtd_AllPr"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kPrAllIdx) { + histos.fill(HIST("hEtaPhiReco_PrAll"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_PrAll"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_PrAll"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); } } } @@ -1604,91 +2056,93 @@ struct RadialFlowDecorr { float mptsubRecoEffCorr = (sumWiptiRecoEffCorr[isp][ietaA] + sumWiptiRecoEffCorr[isp][ietaC]) / nCorrAB; if (nTruAB > 0) { - if (isp == kInclusive) + if (isp == kInclusiveIdx) histos.fill(HIST("Prof2D_MeanpTSub_Tru"), cent, ietaA, ietaC, mptsubTru); - else if (isp == kPiMinus) + else if (isp == kPiMinusIdx) histos.fill(HIST("Prof2D_MeanpTSub_Tru_PiMinus"), cent, ietaA, ietaC, mptsubTru); - else if (isp == kPiPlus) + else if (isp == kPiPlusIdx) histos.fill(HIST("Prof2D_MeanpTSub_Tru_PiPlus"), cent, ietaA, ietaC, mptsubTru); - else if (isp == kPiAll) + else if (isp == kPiAllIdx) histos.fill(HIST("Prof2D_MeanpTSub_Tru_PiAll"), cent, ietaA, ietaC, mptsubTru); - else if (isp == kKaMinus) + else if (isp == kKaMinusIdx) histos.fill(HIST("Prof2D_MeanpTSub_Tru_KaMinus"), cent, ietaA, ietaC, mptsubTru); - else if (isp == kKaPlus) + else if (isp == kKaPlusIdx) histos.fill(HIST("Prof2D_MeanpTSub_Tru_KaPlus"), cent, ietaA, ietaC, mptsubTru); - else if (isp == kKaAll) + else if (isp == kKaAllIdx) histos.fill(HIST("Prof2D_MeanpTSub_Tru_KaAll"), cent, ietaA, ietaC, mptsubTru); - else if (isp == kProton) + else if (isp == kPrIdx) histos.fill(HIST("Prof2D_MeanpTSub_Tru_Pr"), cent, ietaA, ietaC, mptsubTru); - else if (isp == kAntiProton) + else if (isp == kAntiPrIdx) histos.fill(HIST("Prof2D_MeanpTSub_Tru_AntiPr"), cent, ietaA, ietaC, mptsubTru); - else if (isp == kAllProton) - histos.fill(HIST("Prof2D_MeanpTSub_Tru_AllPr"), cent, ietaA, ietaC, mptsubTru); + else if (isp == kPrAllIdx) + histos.fill(HIST("Prof2D_MeanpTSub_Tru_PrAll"), cent, ietaA, ietaC, mptsubTru); } if (nRecoAB > 0) { - if (isp == kInclusive) + if (isp == kInclusiveIdx) histos.fill(HIST("Prof2D_MeanpTSub_Reco"), cent, ietaA, ietaC, mptsubReco); - else if (isp == kPiMinus) + else if (isp == kPiMinusIdx) histos.fill(HIST("Prof2D_MeanpTSub_Reco_PiMinus"), cent, ietaA, ietaC, mptsubReco); - else if (isp == kPiPlus) + else if (isp == kPiPlusIdx) histos.fill(HIST("Prof2D_MeanpTSub_Reco_PiPlus"), cent, ietaA, ietaC, mptsubReco); - else if (isp == kPiAll) + else if (isp == kPiAllIdx) histos.fill(HIST("Prof2D_MeanpTSub_Reco_PiAll"), cent, ietaA, ietaC, mptsubReco); - else if (isp == kKaMinus) + else if (isp == kKaMinusIdx) histos.fill(HIST("Prof2D_MeanpTSub_Reco_KaMinus"), cent, ietaA, ietaC, mptsubReco); - else if (isp == kKaPlus) + else if (isp == kKaPlusIdx) histos.fill(HIST("Prof2D_MeanpTSub_Reco_KaPlus"), cent, ietaA, ietaC, mptsubReco); - else if (isp == kKaAll) + else if (isp == kKaAllIdx) histos.fill(HIST("Prof2D_MeanpTSub_Reco_KaAll"), cent, ietaA, ietaC, mptsubReco); - else if (isp == kProton) + else if (isp == kPrIdx) histos.fill(HIST("Prof2D_MeanpTSub_Reco_Pr"), cent, ietaA, ietaC, mptsubReco); - else if (isp == kAntiProton) + else if (isp == kAntiPrIdx) histos.fill(HIST("Prof2D_MeanpTSub_Reco_AntiPr"), cent, ietaA, ietaC, mptsubReco); - else if (isp == kAllProton) - histos.fill(HIST("Prof2D_MeanpTSub_Reco_AllPr"), cent, ietaA, ietaC, mptsubReco); + else if (isp == kPrAllIdx) + histos.fill(HIST("Prof2D_MeanpTSub_Reco_PrAll"), cent, ietaA, ietaC, mptsubReco); } if (nCorrAB > 0) { - if (isp == kInclusive) + if (isp == kInclusiveIdx) histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr"), cent, ietaA, ietaC, mptsubRecoEffCorr); - else if (isp == kPiMinus) + else if (isp == kPiMinusIdx) histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr_PiMinus"), cent, ietaA, ietaC, mptsubRecoEffCorr); - else if (isp == kPiPlus) + else if (isp == kPiPlusIdx) histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr_PiPlus"), cent, ietaA, ietaC, mptsubRecoEffCorr); - else if (isp == kPiAll) + else if (isp == kPiAllIdx) histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr_PiAll"), cent, ietaA, ietaC, mptsubRecoEffCorr); - else if (isp == kKaMinus) + else if (isp == kKaMinusIdx) histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr_KaMinus"), cent, ietaA, ietaC, mptsubRecoEffCorr); - else if (isp == kKaPlus) + else if (isp == kKaPlusIdx) histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr_KaPlus"), cent, ietaA, ietaC, mptsubRecoEffCorr); - else if (isp == kKaAll) + else if (isp == kKaAllIdx) histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr_KaAll"), cent, ietaA, ietaC, mptsubRecoEffCorr); - else if (isp == kProton) + else if (isp == kPrIdx) histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr_Pr"), cent, ietaA, ietaC, mptsubRecoEffCorr); - else if (isp == kAntiProton) + else if (isp == kAntiPrIdx) histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr_AntiPr"), cent, ietaA, ietaC, mptsubRecoEffCorr); - else if (isp == kAllProton) - histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr_AllPr"), cent, ietaA, ietaC, mptsubRecoEffCorr); + else if (isp == kPrAllIdx) + histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr_PrAll"), cent, ietaA, ietaC, mptsubRecoEffCorr); } + } + } - if (ietaA == ietaC) { - if (sumWiTruth[isp][ietaA] > 0) { - float val = sumWiptiTruth[isp][ietaA] / sumWiTruth[isp][ietaA]; - histos.fill(HIST("pmeanTru_nch_etabin_spbin"), multPV, ietaA, isp, val); - } - if (sumWiReco[isp][ietaA] > 0) { - float val = sumWiptiReco[isp][ietaA] / sumWiReco[isp][ietaA]; - histos.fill(HIST("pmeanReco_nch_etabin_spbin"), multPV, ietaA, isp, val); - } - if (sumWiRecoEffCorr[isp][ietaA] > 0) { - float val = sumWiptiRecoEffCorr[isp][ietaA] / sumWiRecoEffCorr[isp][ietaA]; - histos.fill(HIST("pmeanRecoEffcorr_nch_etabin_spbin"), multPV, ietaA, isp, val); - histos.fill(HIST("pmeanMultRecoEffcorr_nch_etabin_spbin"), multPV, ietaA, isp, sumWiRecoEffCorr[isp][ietaA]); - } - } - } // end isp - } // end ietaC + for (int isp = 0; isp < KNsp; ++isp) { + if (sumWiTruth[isp][ietaA] > 0) { + float val = sumWiptiTruth[isp][ietaA] / sumWiTruth[isp][ietaA]; + histos.fill(HIST("pmeanTru_nch_etabin_spbin"), multPV, ietaA, isp, val); + histos.fill(HIST("pmeanMultTru_nch_etabin_spbin"), multPV, ietaA, isp, sumWiTruth[isp][ietaA]); + } + if (sumWiReco[isp][ietaA] > 0) { + float val = sumWiptiReco[isp][ietaA] / sumWiReco[isp][ietaA]; + histos.fill(HIST("pmeanReco_nch_etabin_spbin"), multPV, ietaA, isp, val); + histos.fill(HIST("pmeanMultReco_nch_etabin_spbin"), multPV, ietaA, isp, sumWiReco[isp][ietaA]); + } + if (sumWiRecoEffCorr[isp][ietaA] > 0) { + float val = sumWiptiRecoEffCorr[isp][ietaA] / sumWiRecoEffCorr[isp][ietaA]; + histos.fill(HIST("pmeanRecoEffcorr_nch_etabin_spbin"), multPV, ietaA, isp, val); + histos.fill(HIST("pmeanMultRecoEffcorr_nch_etabin_spbin"), multPV, ietaA, isp, sumWiRecoEffCorr[isp][ietaA]); + } + } } // end ietaA double amplFT0A = 0, amplFT0C = 0; @@ -1699,8 +2153,8 @@ struct RadialFlowDecorr { float ampl = ft0.amplitudeA()[iCh]; amplFT0A += ampl; auto eta = getEtaFT0(chanelid, 0); - histos.fill(HIST("pmean_cent_id_eta_FT0"), cent, iCh, eta, ampl); - histos.fill(HIST("h3_cent_id_eta_FT0"), cent, iCh, eta, ampl); + histos.fill(HIST("pmean_cent_id_eta_FT0"), cent, chanelid, eta, ampl); + histos.fill(HIST("h3_cent_id_eta_FT0"), cent, chanelid, eta, ampl); } for (std::size_t iCh = 0; iCh < ft0.channelC().size(); iCh++) { auto chanelid = ft0.channelC()[iCh]; @@ -1708,8 +2162,8 @@ struct RadialFlowDecorr { float ampl = ft0.amplitudeC()[iCh]; auto eta = getEtaFT0(globalId, 1); amplFT0C += ampl; - histos.fill(HIST("pmean_cent_id_eta_FT0"), cent, iCh, eta, ampl); - histos.fill(HIST("h3_cent_id_eta_FT0"), cent, iCh, eta, ampl); + histos.fill(HIST("pmean_cent_id_eta_FT0"), cent, globalId, eta, ampl); + histos.fill(HIST("h3_cent_id_eta_FT0"), cent, globalId, eta, ampl); } } @@ -1724,8 +2178,8 @@ struct RadialFlowDecorr { void processMCFluc(aod::McCollisions const& mcColl, MyRun3MCCollisions const& collisions, TCs const& tracks, FilteredTCs const& /*filteredTracks*/, aod::FT0s const&, aod::McParticles const& mcParticles) { - if (!pmeanTruNchEtabinSpbinStep2 || !pmeanRecoNchEtabinSpbinStep2 || !pmeanRecoEffcorrNchEtabinSpbinStep2 || - !pmeanMultTruNchEtabinSpbinStep2 || !pmeanMultRecoNchEtabinSpbinStep2 || !pmeanMultRecoEffcorrNchEtabinSpbinStep2) { + if (!state.pmeanTruNchEtabinSpbinStep2 || !state.pmeanRecoNchEtabinSpbinStep2 || !state.pmeanRecoEffcorrNchEtabinSpbinStep2 || + !state.pmeanMultTruNchEtabinSpbinStep2 || !state.pmeanMultRecoNchEtabinSpbinStep2 || !state.pmeanMultRecoEffcorrNchEtabinSpbinStep2) { LOGF(warning, "MC fluc: Unified Mean pT or Mult map missing"); return; } @@ -1765,6 +2219,7 @@ struct RadialFlowDecorr { if (cent > KCentMax) continue; float multPV = col.multNTracksPV(); + memset(sumPmwkTru, 0, sizeof(sumPmwkTru)); memset(sumWkTru, 0, sizeof(sumWkTru)); memset(sumPmwkReco, 0, sizeof(sumPmwkReco)); @@ -1798,23 +2253,23 @@ struct RadialFlowDecorr { continue; float pt = particle.pt(); - if (pt <= KPtMin || pt > KPtMax) + if (pt <= cfgPtMin || pt > cfgPtMax) continue; float eta = particle.eta(); int pdgCode = particle.pdgCode(); int absPdg = std::abs(pdgCode); bool isSpecies[KNsp] = { - true, // kInclusive - pdgCode == kPiMinus, // kPiMinus - pdgCode == kPiPlus, // kPiPlus - absPdg == kPiPlus, // kPiAll - pdgCode == kKMinus, // kKaMinus - pdgCode == kKPlus, // kKaPlus - absPdg == kKPlus, // kKaAll - pdgCode == kProtonBar, // kAntiProton - pdgCode == kProton, // kProton - absPdg == kProton // kAllProton + true, // kInclusiveIdx + pdgCode == -KPiPlus, // kPiMinusIdx + pdgCode == KPiPlus, // kPiPlusIdx + absPdg == KPiPlus, // kPiAllIdx + pdgCode == -KKPlus, // kKaMinusIdx + pdgCode == KKPlus, // kKaPlusIdx + absPdg == KKPlus, // kKaAllIdx + pdgCode == -KProton, // kAntiPrIdx + pdgCode == KProton, // kPrIdx + absPdg == KProton // kPrAllIdx }; for (int ieta = 0; ieta < KNEta; ++ieta) { @@ -1833,40 +2288,41 @@ struct RadialFlowDecorr { } } // end truth loop float vz = col.posZ(); + + histos.fill(HIST("hVtxZ_after_sel"), col.posZ()); + histos.fill(HIST("hCentrality"), cent); + + histos.fill(HIST("Hist2D_globalTracks_PVTracks"), col.multNTracksPV(), trackSlice.size()); + histos.fill(HIST("Hist2D_cent_nch"), trackSlice.size(), cent); + for (const auto& track : trackSlice) { if (!isTrackSelected(track)) continue; float pt = track.pt(); - if (pt <= KPtMin || pt > KPtMax) + if (pt <= cfgPtMin || pt > cfgPtMax) continue; float eta = track.eta(); float phi = track.phi(); auto sign = track.sign(); - bool isPi = selectionPion(track); - bool isKa = selectionKaon(track); - bool isPr = selectionProton(track); + int centBin = static_cast(cent); + int id = identifyTrack(track, centBin); + bool isPi = (id == KPidPionOne); + bool isKa = (id == KPidKaonTwo); + bool isPr = (id == KPidProtonThree); bool isSpecies[KNsp] = { - true, // kInclusive - isPi && sign < 0, // kPiMinus - isPi && sign > 0, // kPiPlus - isPi, // kPiAll - isKa && sign < 0, // kKaMinus - isKa && sign > 0, // kKaPlus - isKa, // kKaAll - isPr && sign < 0, // kAntiProton (Negative) - isPr && sign > 0, // kProton (Positive) - isPr // kAllProton - }; + true, + isPi && sign < 0, isPi && sign > 0, isPi, + isKa && sign < 0, isKa && sign > 0, isKa, + isPr && sign < 0, isPr && sign > 0, isPr}; for (int isp = 0; isp < KNsp; ++isp) { if (!isSpecies[isp]) continue; - - float eff = getEfficiency(col.multNTracksPV(), pt, eta, static_cast(isp), 0, cfgEff); - float fake = getEfficiency(col.multNTracksPV(), pt, eta, static_cast(isp), 1, cfgEff); - float flatW = getFlatteningWeight(vz, sign, pt, eta, phi, static_cast(isp), cfgFlat); + float eff = getEfficiency(col.multNTracksPV(), pt, eta, static_cast(isp), 0, cfgEff); + float fake = getEfficiency(col.multNTracksPV(), pt, eta, static_cast(isp), 1, cfgEff); + float flatW = getFlatteningWeight(vz, sign, pt, eta, phi, static_cast(isp), cfgFlat); float w = flatW * (1.0 - fake) / eff; if (!std::isfinite(w) || w <= 0.f || eff <= KFloatEpsilon) @@ -1885,52 +2341,52 @@ struct RadialFlowDecorr { } } - if (isp == kInclusive) { + if (isp == kInclusiveIdx) { histos.fill(HIST("hEtaPhiReco"), vz, sign, pt, eta, phi); histos.fill(HIST("hEtaPhiRecoWtd"), vz, sign, pt, eta, phi, w); histos.fill(HIST("hEtaPhiRecoEffWtd"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - } else if (isp == kPiMinus) { + } else if (isp == kPiMinusIdx) { histos.fill(HIST("hEtaPhiReco_PiMinus"), vz, sign, pt, eta, phi); histos.fill(HIST("hEtaPhiRecoWtd_PiMinus"), vz, sign, pt, eta, phi, w); histos.fill(HIST("hEtaPhiRecoEffWtd_PiMinus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - } else if (isp == kPiPlus) { + } else if (isp == kPiPlusIdx) { histos.fill(HIST("hEtaPhiReco_PiPlus"), vz, sign, pt, eta, phi); histos.fill(HIST("hEtaPhiRecoWtd_PiPlus"), vz, sign, pt, eta, phi, w); histos.fill(HIST("hEtaPhiRecoEffWtd_PiPlus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - } else if (isp == kPiAll) { + } else if (isp == kPiAllIdx) { histos.fill(HIST("hEtaPhiReco_PiAll"), vz, sign, pt, eta, phi); histos.fill(HIST("hEtaPhiRecoWtd_PiAll"), vz, sign, pt, eta, phi, w); histos.fill(HIST("hEtaPhiRecoEffWtd_PiAll"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - } else if (isp == kKaMinus) { + } else if (isp == kKaMinusIdx) { histos.fill(HIST("hEtaPhiReco_KaMinus"), vz, sign, pt, eta, phi); histos.fill(HIST("hEtaPhiRecoWtd_KaMinus"), vz, sign, pt, eta, phi, w); histos.fill(HIST("hEtaPhiRecoEffWtd_KaMinus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - } else if (isp == kKaPlus) { + } else if (isp == kKaPlusIdx) { histos.fill(HIST("hEtaPhiReco_KaPlus"), vz, sign, pt, eta, phi); histos.fill(HIST("hEtaPhiRecoWtd_KaPlus"), vz, sign, pt, eta, phi, w); histos.fill(HIST("hEtaPhiRecoEffWtd_KaPlus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - } else if (isp == kKaAll) { + } else if (isp == kKaAllIdx) { histos.fill(HIST("hEtaPhiReco_KaAll"), vz, sign, pt, eta, phi); histos.fill(HIST("hEtaPhiRecoWtd_KaAll"), vz, sign, pt, eta, phi, w); histos.fill(HIST("hEtaPhiRecoEffWtd_KaAll"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - } else if (isp == kProton) { + } else if (isp == kPrIdx) { histos.fill(HIST("hEtaPhiReco_Pr"), vz, sign, pt, eta, phi); histos.fill(HIST("hEtaPhiRecoWtd_Pr"), vz, sign, pt, eta, phi, w); histos.fill(HIST("hEtaPhiRecoEffWtd_Pr"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - } else if (isp == kAntiProton) { + } else if (isp == kAntiPrIdx) { histos.fill(HIST("hEtaPhiReco_AntiPr"), vz, sign, pt, eta, phi); histos.fill(HIST("hEtaPhiRecoWtd_AntiPr"), vz, sign, pt, eta, phi, w); histos.fill(HIST("hEtaPhiRecoEffWtd_AntiPr"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - } else if (isp == kAllProton) { - histos.fill(HIST("hEtaPhiReco_AllPr"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoWtd_AllPr"), vz, sign, pt, eta, phi, w); - histos.fill(HIST("hEtaPhiRecoEffWtd_AllPr"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kPrAllIdx) { + histos.fill(HIST("hEtaPhiReco_PrAll"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_PrAll"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_PrAll"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); } } } // trkslice for (int ieta = 0; ieta < KNEta; ++ieta) { - const int ibx = pmeanTruNchEtabinSpbinStep2->GetXaxis()->FindBin(col.multNTracksPV()); + const int ibx = state.pmeanTruNchEtabinSpbinStep2->GetXaxis()->FindBin(col.multNTracksPV()); const int iby = ieta + 1; for (int isp = 0; isp < KNsp; ++isp) { @@ -1940,13 +2396,13 @@ struct RadialFlowDecorr { meanRecoMult[isp][ieta] = sumWkReco[isp][ieta][1]; meanRecoEffCorMult[isp][ieta] = sumWkRecoEffCor[isp][ieta][1]; - float mmptTru = pmeanTruNchEtabinSpbinStep2->GetBinContent(ibx, iby, ibz); - float mmptReco = pmeanRecoNchEtabinSpbinStep2->GetBinContent(ibx, iby, ibz); - float mmptRecoEffCor = pmeanRecoEffcorrNchEtabinSpbinStep2->GetBinContent(ibx, iby, ibz); + float mmptTru = state.pmeanTruNchEtabinSpbinStep2->GetBinContent(ibx, iby, ibz); + float mmptReco = state.pmeanRecoNchEtabinSpbinStep2->GetBinContent(ibx, iby, ibz); + float mmptRecoEffCor = state.pmeanRecoEffcorrNchEtabinSpbinStep2->GetBinContent(ibx, iby, ibz); - float mmMultTru = pmeanMultTruNchEtabinSpbinStep2->GetBinContent(ibx, iby, ibz); - float mmMultReco = pmeanMultRecoNchEtabinSpbinStep2->GetBinContent(ibx, iby, ibz); - float mmMultRecoEffCor = pmeanMultRecoEffcorrNchEtabinSpbinStep2->GetBinContent(ibx, iby, ibz); + float mmMultTru = state.pmeanMultTruNchEtabinSpbinStep2->GetBinContent(ibx, iby, ibz); + float mmMultReco = state.pmeanMultRecoNchEtabinSpbinStep2->GetBinContent(ibx, iby, ibz); + float mmMultRecoEffCor = state.pmeanMultRecoEffcorrNchEtabinSpbinStep2->GetBinContent(ibx, iby, ibz); if (std::isfinite(mmptTru)) std::tie(meanTru[isp][ieta], c2Tru[isp][ieta]) = calculateMeanAndC2FromSums(sumPmwkTru[isp][ieta], sumWkTru[isp][ieta], mmptTru); @@ -2039,8 +2495,8 @@ struct RadialFlowDecorr { } } - p1kBarFt0A = amplFT0A - pmeanFT0AmultpvStep2->GetBinContent(pmeanFT0AmultpvStep2->GetXaxis()->FindBin(col.multNTracksPV())); - p1kBarFt0C = amplFT0C - pmeanFT0CmultpvStep2->GetBinContent(pmeanFT0CmultpvStep2->GetXaxis()->FindBin(col.multNTracksPV())); + p1kBarFt0A = amplFT0A - state.pmeanFT0AmultpvStep2->GetBinContent(state.pmeanFT0AmultpvStep2->GetXaxis()->FindBin(col.multNTracksPV())); + p1kBarFt0C = amplFT0C - state.pmeanFT0CmultpvStep2->GetBinContent(state.pmeanFT0CmultpvStep2->GetXaxis()->FindBin(col.multNTracksPV())); for (int ietaA = 1; ietaA <= (KNEta - 1) / 2; ++ietaA) { int ietaC = KNEta - ietaA; @@ -2139,7 +2595,7 @@ struct RadialFlowDecorr { float covFT0CReco = p1kBarFt0C * p1kBarReco[isp][ietaA]; float covFT0CRecoEffCor = p1kBarFt0C * p1kBarRecoEffCor[isp][ietaA]; - if (isp == kInclusive) { + if (isp == kInclusiveIdx) { if (std::isfinite(c2SubTru)) { histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC"), cent, etaValA, etaValB, c2SubTru); histos.fill(HIST("MCGen/Prof_GapSum2D"), cent, gap, sum, c2SubTru); @@ -2174,7 +2630,7 @@ struct RadialFlowDecorr { if (std::isfinite(covFT0CRecoEffCor)) histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covFT0CRecoEffCor); - } else if (isp == kPiMinus) { + } else if (isp == kPiMinusIdx) { if (std::isfinite(c2SubTru)) { histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, c2SubTru); histos.fill(HIST("MCGen/Prof_GapSum2D_PiMinus"), cent, gap, sum, c2SubTru); @@ -2209,7 +2665,7 @@ struct RadialFlowDecorr { if (std::isfinite(covFT0CRecoEffCor)) histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, covFT0CRecoEffCor); - } else if (isp == kPiPlus) { + } else if (isp == kPiPlusIdx) { if (std::isfinite(c2SubTru)) { histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, c2SubTru); histos.fill(HIST("MCGen/Prof_GapSum2D_PiPlus"), cent, gap, sum, c2SubTru); @@ -2244,7 +2700,7 @@ struct RadialFlowDecorr { if (std::isfinite(covFT0CRecoEffCor)) histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, covFT0CRecoEffCor); - } else if (isp == kPiAll) { + } else if (isp == kPiAllIdx) { if (std::isfinite(c2SubTru)) { histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, c2SubTru); histos.fill(HIST("MCGen/Prof_GapSum2D_PiAll"), cent, gap, sum, c2SubTru); @@ -2279,7 +2735,7 @@ struct RadialFlowDecorr { if (std::isfinite(covFT0CRecoEffCor)) histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, covFT0CRecoEffCor); - } else if (isp == kKaMinus) { + } else if (isp == kKaMinusIdx) { if (std::isfinite(c2SubTru)) { histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, c2SubTru); histos.fill(HIST("MCGen/Prof_GapSum2D_KaMinus"), cent, gap, sum, c2SubTru); @@ -2314,7 +2770,7 @@ struct RadialFlowDecorr { if (std::isfinite(covFT0CRecoEffCor)) histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, covFT0CRecoEffCor); - } else if (isp == kKaPlus) { + } else if (isp == kKaPlusIdx) { if (std::isfinite(c2SubTru)) { histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, c2SubTru); histos.fill(HIST("MCGen/Prof_GapSum2D_KaPlus"), cent, gap, sum, c2SubTru); @@ -2349,7 +2805,7 @@ struct RadialFlowDecorr { if (std::isfinite(covFT0CRecoEffCor)) histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, covFT0CRecoEffCor); - } else if (isp == kKaAll) { + } else if (isp == kKaAllIdx) { if (std::isfinite(c2SubTru)) { histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, c2SubTru); histos.fill(HIST("MCGen/Prof_GapSum2D_KaAll"), cent, gap, sum, c2SubTru); @@ -2384,7 +2840,7 @@ struct RadialFlowDecorr { if (std::isfinite(covFT0CRecoEffCor)) histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, covFT0CRecoEffCor); - } else if (isp == kProton) { + } else if (isp == kPrIdx) { if (std::isfinite(c2SubTru)) { histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, c2SubTru); histos.fill(HIST("MCGen/Prof_GapSum2D_Pr"), cent, gap, sum, c2SubTru); @@ -2419,7 +2875,7 @@ struct RadialFlowDecorr { if (std::isfinite(covFT0CRecoEffCor)) histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covFT0CRecoEffCor); - } else if (isp == kAntiProton) { + } else if (isp == kAntiPrIdx) { if (std::isfinite(c2SubTru)) { histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, c2SubTru); histos.fill(HIST("MCGen/Prof_GapSum2D_AntiPr"), cent, gap, sum, c2SubTru); @@ -2454,40 +2910,40 @@ struct RadialFlowDecorr { if (std::isfinite(covFT0CRecoEffCor)) histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, covFT0CRecoEffCor); - } else if (isp == kAllProton) { + } else if (isp == kPrAllIdx) { if (std::isfinite(c2SubTru)) { - histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC_AllPr"), cent, etaValA, etaValB, c2SubTru); - histos.fill(HIST("MCGen/Prof_GapSum2D_AllPr"), cent, gap, sum, c2SubTru); + histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, c2SubTru); + histos.fill(HIST("MCGen/Prof_GapSum2D_PrAll"), cent, gap, sum, c2SubTru); } if (std::isfinite(c2SubReco)) { - histos.fill(HIST("MCReco/Prof_C2Sub2D_Cent_etaA_etaC_AllPr"), cent, etaValA, etaValB, c2SubReco); - histos.fill(HIST("MCReco/Prof_GapSum2D_AllPr"), cent, gap, sum, c2SubReco); + histos.fill(HIST("MCReco/Prof_C2Sub2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, c2SubReco); + histos.fill(HIST("MCReco/Prof_GapSum2D_PrAll"), cent, gap, sum, c2SubReco); } if (std::isfinite(c2SubRecoEffCor)) { - histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub2D_Cent_etaA_etaC_AllPr"), cent, etaValA, etaValB, c2SubRecoEffCor); - histos.fill(HIST("MCRecoEffCorr/Prof_GapSum2D_AllPr"), cent, gap, sum, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_GapSum2D_PrAll"), cent, gap, sum, c2SubRecoEffCor); } if (std::isfinite(covTru)) - histos.fill(HIST("MCGen/Prof_Cov2D_Cent_etaA_etaC_AllPr"), cent, etaValA, etaValB, covTru); + histos.fill(HIST("MCGen/Prof_Cov2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, covTru); if (std::isfinite(covReco)) - histos.fill(HIST("MCReco/Prof_Cov2D_Cent_etaA_etaC_AllPr"), cent, etaValA, etaValB, covReco); + histos.fill(HIST("MCReco/Prof_Cov2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, covReco); if (std::isfinite(covRecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_Cov2D_Cent_etaA_etaC_AllPr"), cent, etaValA, etaValB, covRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_Cov2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, covRecoEffCor); if (std::isfinite(covFT0ATru)) - histos.fill(HIST("MCGen/Prof_CovFT0A2D_Cent_etaA_etaC_AllPr"), cent, etaValA, etaValB, covFT0ATru); + histos.fill(HIST("MCGen/Prof_CovFT0A2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, covFT0ATru); if (std::isfinite(covFT0AReco)) - histos.fill(HIST("MCReco/Prof_CovFT0A2D_Cent_etaA_etaC_AllPr"), cent, etaValA, etaValB, covFT0AReco); + histos.fill(HIST("MCReco/Prof_CovFT0A2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, covFT0AReco); if (std::isfinite(covFT0ARecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A2D_Cent_etaA_etaC_AllPr"), cent, etaValA, etaValB, covFT0ARecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, covFT0ARecoEffCor); if (std::isfinite(covFT0CTru)) - histos.fill(HIST("MCGen/Prof_CovFT0C2D_Cent_etaA_etaC_AllPr"), cent, etaValA, etaValB, covFT0CTru); + histos.fill(HIST("MCGen/Prof_CovFT0C2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, covFT0CTru); if (std::isfinite(covFT0CReco)) - histos.fill(HIST("MCReco/Prof_CovFT0C2D_Cent_etaA_etaC_AllPr"), cent, etaValA, etaValB, covFT0CReco); + histos.fill(HIST("MCReco/Prof_CovFT0C2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, covFT0CReco); if (std::isfinite(covFT0CRecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC_AllPr"), cent, etaValA, etaValB, covFT0CRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, covFT0CRecoEffCor); } } } @@ -2498,6 +2954,49 @@ struct RadialFlowDecorr { } PROCESS_SWITCH(RadialFlowDecorr, processMCFluc, "process MC to calculate pt fluc", cfgRunMCFluc); + void processDataGetNSig(AodCollisionsSel::iterator const& coll, BCsRun3 const& /*bcs*/, aod::Zdcs const& /*zdcsData*/, AodTracksSel const& tracks) + { + histos.fill(HIST("hVtxZ"), coll.posZ()); + if (!isEventSelected(coll)) + return; + float cent = getCentrality(coll); + if (cent > KCentMax) + return; + histos.fill(HIST("hVtxZ_after_sel"), coll.posZ()); + histos.fill(HIST("hCentrality"), cent); + + histos.fill(HIST("Hist2D_globalTracks_PVTracks"), coll.multNTracksPV(), tracks.size()); + histos.fill(HIST("Hist2D_cent_nch"), tracks.size(), cent); + + int ntrk = 0; + for (const auto& track : tracks) { + if (!isTrackSelected(track)) + continue; + float pt = track.pt(); + if (pt <= cfgPtMin || pt > cfgPtMax) + continue; + float eta = track.eta(); + if (eta > etaLw[0] && eta < etaUp[0]) + ntrk++; + fillNSigmaBefCut(track, cent); + } + + histos.fill(HIST("hCentnTrk"), cent, ntrk); + histos.fill(HIST("hCentnTrkPV"), cent, coll.multNTracksPV()); + + if (cfgZDC) { + const auto& foundBC = coll.foundBC_as(); + if (!foundBC.has_zdc()) { + return; + } + auto zdc = foundBC.zdc(); + auto zdcAmp = zdc.energyCommonZNA() + zdc.energyCommonZNC(); + histos.fill(HIST("hnTrkPVZDC"), coll.multNTracksPV(), zdcAmp); + histos.fill(HIST("hNchZDC"), ntrk, zdcAmp); + } + } + PROCESS_SWITCH(RadialFlowDecorr, processDataGetNSig, "process data to Get Nsigma cuts", cfgRunDataGetNSig); + void processGetDataFlat(AodCollisionsSel::iterator const& coll, BCsRun3 const& /*bcs*/, aod::Zdcs const& /*zdcsData*/, AodTracksSel const& tracks) { histos.fill(HIST("hVtxZ"), coll.posZ()); @@ -2507,7 +3006,7 @@ struct RadialFlowDecorr { if (cent > KCentMax) return; - histos.fill(HIST("hZvtx_after_sel"), coll.posZ()); + histos.fill(HIST("hVtxZ_after_sel"), coll.posZ()); histos.fill(HIST("hCentrality"), cent); histos.fill(HIST("Hist2D_globalTracks_PVTracks"), coll.multNTracksPV(), tracks.size()); @@ -2520,79 +3019,81 @@ struct RadialFlowDecorr { if (!isTrackSelected(track)) continue; float pt = track.pt(); - if (pt <= KPtMin || pt > KPtMax) + if (pt <= cfgPtMin || pt > cfgPtMax) continue; float eta = track.eta(); float phi = track.phi(); auto sign = track.sign(); + if (eta > etaLw[0] && eta < etaUp[0]) ntrk++; - bool isPi = selectionPion(track); - bool isKa = selectionKaon(track); - bool isPr = selectionProton(track); + fillNSigmaBefCut(track, cent); + int centBin = static_cast(cent); + int id = identifyTrack(track, centBin); + bool isPi = (id == KPidPionOne); + bool isKa = (id == KPidKaonTwo); + bool isPr = (id == KPidProtonThree); bool isSpecies[KNsp] = { - true, // kInclusive - isPi && sign < 0, // kPiMinus - isPi && sign > 0, // kPiPlus - isPi, // kPiAll - isKa && sign < 0, // kKaMinus - isKa && sign > 0, // kKaPlus - isKa, // kKaAll - isPr && sign < 0, // kAntiProton (Negative) - isPr && sign > 0, // kProton (Positive) - isPr // kAllProton - }; + true, + isPi && sign < 0, isPi && sign > 0, isPi, + isKa && sign < 0, isKa && sign > 0, isKa, + isPr && sign < 0, isPr && sign > 0, isPr}; for (int isp = 0; isp < KNsp; ++isp) { if (!isSpecies[isp]) continue; - float eff = getEfficiency(coll.multNTracksPV(), pt, eta, static_cast(isp), 0, cfgEff); - float fake = getEfficiency(coll.multNTracksPV(), pt, eta, static_cast(isp), 1, cfgEff); - float w = (1.0 - fake) / eff; + fillNSigmaAftCut(track, cent, isSpecies); + float eff = getEfficiency(coll.multNTracksPV(), pt, eta, static_cast(isp), 0, cfgEff); + if (eff <= KFloatEpsilon) + continue; - if (!std::isfinite(w) || w <= KFloatEpsilon || eff <= KFloatEpsilon) + float fake = getEfficiency(coll.multNTracksPV(), pt, eta, static_cast(isp), 1, cfgEff); + float w = (1.0f - fake) / eff; + + if (!std::isfinite(w) || w <= 0.f) continue; - if (isp == kInclusive) { + + if (isp == kInclusiveIdx) { histos.fill(HIST("hEtaPhiReco"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoEffWtd"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + histos.fill(HIST("hEtaPhiRecoEffWtd"), vz, sign, pt, eta, phi, (1.0f - fake) / eff); histos.fill(HIST("hEtaPhiRecoWtd"), vz, sign, pt, eta, phi, w); - } else if (isp == kPiMinus) { + } else if (isp == kPiMinusIdx) { histos.fill(HIST("hEtaPhiReco_PiMinus"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoEffWtd_PiMinus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + histos.fill(HIST("hEtaPhiRecoEffWtd_PiMinus"), vz, sign, pt, eta, phi, (1.0f - fake) / eff); histos.fill(HIST("hEtaPhiRecoWtd_PiMinus"), vz, sign, pt, eta, phi, w); - } else if (isp == kPiPlus) { + } else if (isp == kPiPlusIdx) { histos.fill(HIST("hEtaPhiReco_PiPlus"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoEffWtd_PiPlus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + histos.fill(HIST("hEtaPhiRecoEffWtd_PiPlus"), vz, sign, pt, eta, phi, (1.0f - fake) / eff); histos.fill(HIST("hEtaPhiRecoWtd_PiPlus"), vz, sign, pt, eta, phi, w); - } else if (isp == kPiAll) { + } else if (isp == kPiAllIdx) { histos.fill(HIST("hEtaPhiReco_PiAll"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoEffWtd_PiAll"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + histos.fill(HIST("hEtaPhiRecoEffWtd_PiAll"), vz, sign, pt, eta, phi, (1.0f - fake) / eff); histos.fill(HIST("hEtaPhiRecoWtd_PiAll"), vz, sign, pt, eta, phi, w); - } else if (isp == kKaMinus) { + } else if (isp == kKaMinusIdx) { histos.fill(HIST("hEtaPhiReco_KaMinus"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoEffWtd_KaMinus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + histos.fill(HIST("hEtaPhiRecoEffWtd_KaMinus"), vz, sign, pt, eta, phi, (1.0f - fake) / eff); histos.fill(HIST("hEtaPhiRecoWtd_KaMinus"), vz, sign, pt, eta, phi, w); - } else if (isp == kKaPlus) { + } else if (isp == kKaPlusIdx) { histos.fill(HIST("hEtaPhiReco_KaPlus"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoEffWtd_KaPlus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + histos.fill(HIST("hEtaPhiRecoEffWtd_KaPlus"), vz, sign, pt, eta, phi, (1.0f - fake) / eff); histos.fill(HIST("hEtaPhiRecoWtd_KaPlus"), vz, sign, pt, eta, phi, w); - } else if (isp == kKaAll) { + } else if (isp == kKaAllIdx) { histos.fill(HIST("hEtaPhiReco_KaAll"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoEffWtd_KaAll"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + histos.fill(HIST("hEtaPhiRecoEffWtd_KaAll"), vz, sign, pt, eta, phi, (1.0f - fake) / eff); histos.fill(HIST("hEtaPhiRecoWtd_KaAll"), vz, sign, pt, eta, phi, w); - } else if (isp == kProton) { + } else if (isp == kPrIdx) { histos.fill(HIST("hEtaPhiReco_Pr"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoEffWtd_Pr"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + histos.fill(HIST("hEtaPhiRecoEffWtd_Pr"), vz, sign, pt, eta, phi, (1.0f - fake) / eff); histos.fill(HIST("hEtaPhiRecoWtd_Pr"), vz, sign, pt, eta, phi, w); - } else if (isp == kAntiProton) { + } else if (isp == kAntiPrIdx) { histos.fill(HIST("hEtaPhiReco_AntiPr"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoEffWtd_AntiPr"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + histos.fill(HIST("hEtaPhiRecoEffWtd_AntiPr"), vz, sign, pt, eta, phi, (1.0f - fake) / eff); histos.fill(HIST("hEtaPhiRecoWtd_AntiPr"), vz, sign, pt, eta, phi, w); - } else if (isp == kAllProton) { - histos.fill(HIST("hEtaPhiReco_AllPr"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoEffWtd_AllPr"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - histos.fill(HIST("hEtaPhiRecoWtd_AllPr"), vz, sign, pt, eta, phi, w); + } else if (isp == kPrAllIdx) { + histos.fill(HIST("hEtaPhiReco_PrAll"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd_PrAll"), vz, sign, pt, eta, phi, (1.0f - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd_PrAll"), vz, sign, pt, eta, phi, w); } } } @@ -2624,7 +3125,7 @@ struct RadialFlowDecorr { if (cent > KCentMax) return; - histos.fill(HIST("hZvtx_after_sel"), coll.posZ()); + histos.fill(HIST("hVtxZ_after_sel"), coll.posZ()); histos.fill(HIST("hCentrality"), cent); histos.fill(HIST("Hist2D_globalTracks_PVTracks"), coll.multNTracksPV(), tracks.size()); @@ -2645,83 +3146,81 @@ struct RadialFlowDecorr { if (p < KFloatEpsilon) continue; - if (pt <= KPtMin || pt > KPtMax) + if (pt <= cfgPtMin || pt > cfgPtMax) continue; histos.fill(HIST("hP"), p); histos.fill(HIST("hPt"), pt); histos.fill(HIST("hEta"), eta); histos.fill(HIST("hPhi"), phi); - - bool isPi = selectionPion(track); - bool isKa = selectionKaon(track); - bool isPr = selectionProton(track); + int centBin = static_cast(cent); + int id = identifyTrack(track, centBin); + bool isPi = (id == KPidPionOne); + bool isKa = (id == KPidKaonTwo); + bool isPr = (id == KPidProtonThree); bool isSpecies[KNsp] = { - true, // kInclusive - isPi && sign < 0, // kPiMinus - isPi && sign > 0, // kPiPlus - isPi, // kPiAll - isKa && sign < 0, // kKaMinus - isKa && sign > 0, // kKaPlus - isKa, // kKaAll - isPr && sign < 0, // kAntiProton (Negative) - isPr && sign > 0, // kProton (Positive) - isPr // kAllProton - }; + true, + isPi && sign < 0, isPi && sign > 0, isPi, + isKa && sign < 0, isKa && sign > 0, isKa, + isPr && sign < 0, isPr && sign > 0, isPr}; for (int isp = 0; isp < KNsp; ++isp) { if (!isSpecies[isp]) continue; + float eff = getEfficiency(coll.multNTracksPV(), pt, eta, static_cast(isp), 0, cfgEff); - float eff = getEfficiency(coll.multNTracksPV(), pt, eta, static_cast(isp), 0, cfgEff); - float fake = getEfficiency(coll.multNTracksPV(), pt, eta, static_cast(isp), 1, cfgEff); - float flatWeight = getFlatteningWeight(vz, sign, pt, eta, phi, static_cast(isp), cfgFlat); - float w = flatWeight * (1.0 - fake) / eff; + // Safety check BEFORE dividing + if (eff <= KFloatEpsilon) + continue; - if (!std::isfinite(w) || w <= KFloatEpsilon || eff <= KFloatEpsilon) + float fake = getEfficiency(coll.multNTracksPV(), pt, eta, static_cast(isp), 1, cfgEff); + float flatWeight = getFlatteningWeight(vz, sign, pt, eta, phi, static_cast(isp), cfgFlat); + float w = flatWeight * (1.0f - fake) / eff; + + if (!std::isfinite(w) || w <= 0.f) continue; - if (isp == kInclusive) { + if (isp == kInclusiveIdx) { histos.fill(HIST("hEtaPhiReco"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoEffWtd"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + histos.fill(HIST("hEtaPhiRecoEffWtd"), vz, sign, pt, eta, phi, (1.0f - fake) / eff); histos.fill(HIST("hEtaPhiRecoWtd"), vz, sign, pt, eta, phi, w); - } else if (isp == kPiMinus) { + } else if (isp == kPiMinusIdx) { histos.fill(HIST("hEtaPhiReco_PiMinus"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoEffWtd_PiMinus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + histos.fill(HIST("hEtaPhiRecoEffWtd_PiMinus"), vz, sign, pt, eta, phi, (1.0f - fake) / eff); histos.fill(HIST("hEtaPhiRecoWtd_PiMinus"), vz, sign, pt, eta, phi, w); - } else if (isp == kPiPlus) { + } else if (isp == kPiPlusIdx) { histos.fill(HIST("hEtaPhiReco_PiPlus"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoEffWtd_PiPlus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + histos.fill(HIST("hEtaPhiRecoEffWtd_PiPlus"), vz, sign, pt, eta, phi, (1.0f - fake) / eff); histos.fill(HIST("hEtaPhiRecoWtd_PiPlus"), vz, sign, pt, eta, phi, w); - } else if (isp == kPiAll) { + } else if (isp == kPiAllIdx) { histos.fill(HIST("hEtaPhiReco_PiAll"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoEffWtd_PiAll"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + histos.fill(HIST("hEtaPhiRecoEffWtd_PiAll"), vz, sign, pt, eta, phi, (1.0f - fake) / eff); histos.fill(HIST("hEtaPhiRecoWtd_PiAll"), vz, sign, pt, eta, phi, w); - } else if (isp == kKaMinus) { + } else if (isp == kKaMinusIdx) { histos.fill(HIST("hEtaPhiReco_KaMinus"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoEffWtd_KaMinus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + histos.fill(HIST("hEtaPhiRecoEffWtd_KaMinus"), vz, sign, pt, eta, phi, (1.0f - fake) / eff); histos.fill(HIST("hEtaPhiRecoWtd_KaMinus"), vz, sign, pt, eta, phi, w); - } else if (isp == kKaPlus) { + } else if (isp == kKaPlusIdx) { histos.fill(HIST("hEtaPhiReco_KaPlus"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoEffWtd_KaPlus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + histos.fill(HIST("hEtaPhiRecoEffWtd_KaPlus"), vz, sign, pt, eta, phi, (1.0f - fake) / eff); histos.fill(HIST("hEtaPhiRecoWtd_KaPlus"), vz, sign, pt, eta, phi, w); - } else if (isp == kKaAll) { + } else if (isp == kKaAllIdx) { histos.fill(HIST("hEtaPhiReco_KaAll"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoEffWtd_KaAll"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + histos.fill(HIST("hEtaPhiRecoEffWtd_KaAll"), vz, sign, pt, eta, phi, (1.0f - fake) / eff); histos.fill(HIST("hEtaPhiRecoWtd_KaAll"), vz, sign, pt, eta, phi, w); - } else if (isp == kProton) { + } else if (isp == kPrIdx) { histos.fill(HIST("hEtaPhiReco_Pr"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoEffWtd_Pr"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + histos.fill(HIST("hEtaPhiRecoEffWtd_Pr"), vz, sign, pt, eta, phi, (1.0f - fake) / eff); histos.fill(HIST("hEtaPhiRecoWtd_Pr"), vz, sign, pt, eta, phi, w); - } else if (isp == kAntiProton) { + } else if (isp == kAntiPrIdx) { histos.fill(HIST("hEtaPhiReco_AntiPr"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoEffWtd_AntiPr"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + histos.fill(HIST("hEtaPhiRecoEffWtd_AntiPr"), vz, sign, pt, eta, phi, (1.0f - fake) / eff); histos.fill(HIST("hEtaPhiRecoWtd_AntiPr"), vz, sign, pt, eta, phi, w); - } else if (isp == kAllProton) { - histos.fill(HIST("hEtaPhiReco_AllPr"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoEffWtd_AllPr"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - histos.fill(HIST("hEtaPhiRecoWtd_AllPr"), vz, sign, pt, eta, phi, w); + } else if (isp == kPrAllIdx) { + histos.fill(HIST("hEtaPhiReco_PrAll"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd_PrAll"), vz, sign, pt, eta, phi, (1.0f - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd_PrAll"), vz, sign, pt, eta, phi, w); } for (int ieta = 0; ieta < KNEta; ++ieta) { @@ -2738,33 +3237,35 @@ struct RadialFlowDecorr { histos.fill(HIST("Prof_Mult_Nsp_Nchrec"), coll.multNTracksPV(), isp, sumWi[isp][0]); if (sumWi[isp][0] > 1.0f) histos.fill(HIST("Prof_Cent_Nsp_MeanpT"), cent, isp, sumWipti[isp][0] / sumWi[isp][0]); + histos.fill(HIST("Prof_Mult_Nsp_MeanpT"), coll.multNTracksPV(), isp, sumWipti[isp][0] / sumWi[isp][0]); } + for (int ietaA = 0; ietaA < KNEta; ++ietaA) { for (int ietaC = 0; ietaC < KNEta; ++ietaC) { for (int isp = 0; isp < KNsp; ++isp) { double wCorrAB = sumWi[isp][ietaA] + sumWi[isp][ietaC]; if (wCorrAB > 0) { float mptsub = (sumWipti[isp][ietaA] + sumWipti[isp][ietaC]) / wCorrAB; - if (isp == kInclusive) + if (isp == kInclusiveIdx) histos.fill(HIST("Prof2D_MeanpTSub"), cent, ietaA, ietaC, mptsub); - else if (isp == kPiMinus) + else if (isp == kPiMinusIdx) histos.fill(HIST("Prof2D_MeanpTSub_PiMinus"), cent, ietaA, ietaC, mptsub); - else if (isp == kPiPlus) + else if (isp == kPiPlusIdx) histos.fill(HIST("Prof2D_MeanpTSub_PiPlus"), cent, ietaA, ietaC, mptsub); - else if (isp == kPiAll) + else if (isp == kPiAllIdx) histos.fill(HIST("Prof2D_MeanpTSub_PiAll"), cent, ietaA, ietaC, mptsub); - else if (isp == kKaMinus) + else if (isp == kKaMinusIdx) histos.fill(HIST("Prof2D_MeanpTSub_KaMinus"), cent, ietaA, ietaC, mptsub); - else if (isp == kKaPlus) + else if (isp == kKaPlusIdx) histos.fill(HIST("Prof2D_MeanpTSub_KaPlus"), cent, ietaA, ietaC, mptsub); - else if (isp == kKaAll) + else if (isp == kKaAllIdx) histos.fill(HIST("Prof2D_MeanpTSub_KaAll"), cent, ietaA, ietaC, mptsub); - else if (isp == kProton) + else if (isp == kPrIdx) histos.fill(HIST("Prof2D_MeanpTSub_Pr"), cent, ietaA, ietaC, mptsub); - else if (isp == kAntiProton) + else if (isp == kAntiPrIdx) histos.fill(HIST("Prof2D_MeanpTSub_AntiPr"), cent, ietaA, ietaC, mptsub); - else if (isp == kAllProton) - histos.fill(HIST("Prof2D_MeanpTSub_AllPr"), cent, ietaA, ietaC, mptsub); + else if (isp == kPrAllIdx) + histos.fill(HIST("Prof2D_MeanpTSub_PrAll"), cent, ietaA, ietaC, mptsub); } if (ietaA == ietaC) { double mpt = sumWipti[isp][ietaA] / sumWi[isp][ietaA]; @@ -2787,8 +3288,8 @@ struct RadialFlowDecorr { float ampl = ft0.amplitudeA()[iCh]; amplFT0A += ampl; auto eta = getEtaFT0(chanelid, 0); - histos.fill(HIST("pmean_cent_id_eta_FT0"), cent, iCh, eta, ampl); - histos.fill(HIST("h3_cent_id_eta_FT0"), cent, iCh, eta, ampl); + histos.fill(HIST("pmean_cent_id_eta_FT0"), cent, chanelid, eta, ampl); + histos.fill(HIST("h3_cent_id_eta_FT0"), cent, chanelid, eta, ampl); } for (std::size_t iCh = 0; iCh < ft0.channelC().size(); iCh++) { auto chanelid = ft0.channelC()[iCh]; @@ -2796,8 +3297,8 @@ struct RadialFlowDecorr { float ampl = ft0.amplitudeC()[iCh]; auto eta = getEtaFT0(globalId, 1); amplFT0C += ampl; - histos.fill(HIST("pmean_cent_id_eta_FT0"), cent, iCh, eta, ampl); - histos.fill(HIST("h3_cent_id_eta_FT0"), cent, iCh, eta, ampl); + histos.fill(HIST("pmean_cent_id_eta_FT0"), cent, globalId, eta, ampl); + histos.fill(HIST("h3_cent_id_eta_FT0"), cent, globalId, eta, ampl); } } @@ -2816,14 +3317,14 @@ struct RadialFlowDecorr { if (cent > KCentMax) return; - if (!pmeanNchEtabinSpbinStep2 || !pmeanMultNchEtabinSpbinStep2) { + if (!state.pmeanNchEtabinSpbinStep2 || !state.pmeanMultNchEtabinSpbinStep2) { LOGF(warning, "Data fluc: Mean pT or Mult map missing"); return; } for (int isp = 0; isp < KNsp; ++isp) { - auto pid = static_cast(isp); - if (!hEff[pid] || !hFake[pid] || !hFlatWeight[pid]) { + auto pid = static_cast(isp); + if (!state.hEff[pid] || !state.hFake[pid] || !state.hFlatWeight[pid]) { LOGF(warning, "Data fluc: Correction maps (Eff, Fake, or Flat) are null for species index %d", isp); return; } @@ -2851,37 +3352,36 @@ struct RadialFlowDecorr { if (p < KFloatEpsilon) continue; - if (pt <= KPtMin || pt > KPtMax) + if (pt <= cfgPtMin || pt > cfgPtMax) continue; - - bool isPi = selectionPion(track); - bool isKa = selectionKaon(track); - bool isPr = selectionProton(track); + int centBin = static_cast(cent); + int id = identifyTrack(track, centBin); + bool isPi = (id == KPidPionOne); + bool isKa = (id == KPidKaonTwo); + bool isPr = (id == KPidProtonThree); bool isSpecies[KNsp] = { - true, // kInclusive - isPi && sign < 0, // kPiMinus - isPi && sign > 0, // kPiPlus - isPi, // kPiAll - isKa && sign < 0, // kKaMinus - isKa && sign > 0, // kKaPlus - isKa, // kKaAll - isPr && sign < 0, // kAntiProton (Negative) - isPr && sign > 0, // kProton (Positive) - isPr // kAllProton - }; + true, + isPi && sign < 0, isPi && sign > 0, isPi, + isKa && sign < 0, isKa && sign > 0, isKa, + isPr && sign < 0, isPr && sign > 0, isPr}; for (int isp = 0; isp < KNsp; ++isp) { if (!isSpecies[isp]) continue; + float eff = getEfficiency(coll.multNTracksPV(), pt, eta, static_cast(isp), 0, cfgEff); + + // Safety check BEFORE dividing + if (eff <= KFloatEpsilon) + continue; - float eff = getEfficiency(coll.multNTracksPV(), pt, eta, static_cast(isp), 0, cfgEff); - float fake = getEfficiency(coll.multNTracksPV(), pt, eta, static_cast(isp), 1, cfgEff); - float flatWeight = getFlatteningWeight(vz, sign, pt, eta, phi, static_cast(isp), cfgFlat); - float w = flatWeight * (1.0 - fake) / eff; + float fake = getEfficiency(coll.multNTracksPV(), pt, eta, static_cast(isp), 1, cfgEff); + float flatWeight = getFlatteningWeight(vz, sign, pt, eta, phi, static_cast(isp), cfgFlat); + float w = flatWeight * (1.0f - fake) / eff; - if (!std::isfinite(w) || w <= KFloatEpsilon || eff <= KFloatEpsilon) + if (!std::isfinite(w) || w <= 0.f) continue; + for (int ieta = 0; ieta < KNEta; ++ieta) { if (eta <= etaLw[ieta] || eta > etaUp[ieta]) continue; @@ -2907,18 +3407,18 @@ struct RadialFlowDecorr { amplFT0C += ampl; } } - double p1kBarFt0A = amplFT0A - pmeanFT0AmultpvStep2->GetBinContent(pmeanFT0AmultpvStep2->GetXaxis()->FindBin(coll.multNTracksPV())); - double p1kBarFt0C = amplFT0C - pmeanFT0CmultpvStep2->GetBinContent(pmeanFT0CmultpvStep2->GetXaxis()->FindBin(coll.multNTracksPV())); + double p1kBarFt0A = amplFT0A - state.pmeanFT0AmultpvStep2->GetBinContent(state.pmeanFT0AmultpvStep2->GetXaxis()->FindBin(coll.multNTracksPV())); + double p1kBarFt0C = amplFT0C - state.pmeanFT0CmultpvStep2->GetBinContent(state.pmeanFT0CmultpvStep2->GetXaxis()->FindBin(coll.multNTracksPV())); for (int ieta = 0; ieta < KNEta; ++ieta) { - const int ibx = pmeanNchEtabinSpbinStep2->GetXaxis()->FindBin(coll.multNTracksPV()); + const int ibx = state.pmeanNchEtabinSpbinStep2->GetXaxis()->FindBin(coll.multNTracksPV()); const int iby = ieta + 1; for (int isp = 0; isp < KNsp; ++isp) { const int ibz = isp + 1; - float mmpt = pmeanNchEtabinSpbinStep2->GetBinContent(ibx, iby, ibz); - float mmMult = pmeanMultNchEtabinSpbinStep2->GetBinContent(ibx, iby, ibz); + float mmpt = state.pmeanNchEtabinSpbinStep2->GetBinContent(ibx, iby, ibz); + float mmMult = state.pmeanMultNchEtabinSpbinStep2->GetBinContent(ibx, iby, ibz); mean[isp][ieta] = sumpmwk[isp][ieta][1][1] / sumwk[isp][ieta][1]; meanMult[isp][ieta] = sumwk[isp][ieta][1]; @@ -2975,6 +3475,7 @@ struct RadialFlowDecorr { } } } + for (int ietaA = 1; ietaA < KNEta; ++ietaA) { for (int ietaC = 1; ietaC < KNEta; ++ietaC) { @@ -2982,6 +3483,7 @@ struct RadialFlowDecorr { float etaValB = (etaLw[ietaC] + etaUp[ietaC]) / 2.0f; float gap = etaValA - etaValB; float sum = (etaValA + etaValB) / 2.0f; + for (int isp = 0; isp < KNsp; ++isp) { float c2Sub = p1kBar[isp][ietaA] * p1kBar[isp][ietaC]; @@ -2989,7 +3491,8 @@ struct RadialFlowDecorr { float covFT0A = p1kBarFt0A * p1kBar[isp][ietaC]; float covFT0C = p1kBarFt0C * p1kBar[isp][ietaA]; - if (isp == kInclusive) { + // Updated enum checks here + if (isp == kInclusiveIdx) { if (std::isfinite(c2Sub)) { histos.fill(HIST("Prof_C2Sub2D_Cent_etaA_etaC"), cent, etaValA, etaValB, c2Sub); histos.fill(HIST("Prof_GapSum2D"), cent, gap, sum, c2Sub); @@ -3000,7 +3503,7 @@ struct RadialFlowDecorr { histos.fill(HIST("Prof_CovFT0A2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covFT0A); if (std::isfinite(covFT0C)) histos.fill(HIST("Prof_CovFT0C2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covFT0C); - } else if (isp == kPiMinus) { + } else if (isp == kPiMinusIdx) { if (std::isfinite(c2Sub)) { histos.fill(HIST("Prof_C2Sub2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, c2Sub); histos.fill(HIST("Prof_GapSum2D_PiMinus"), cent, gap, sum, c2Sub); @@ -3011,7 +3514,7 @@ struct RadialFlowDecorr { histos.fill(HIST("Prof_CovFT0A2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, covFT0A); if (std::isfinite(covFT0C)) histos.fill(HIST("Prof_CovFT0C2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, covFT0C); - } else if (isp == kPiPlus) { + } else if (isp == kPiPlusIdx) { if (std::isfinite(c2Sub)) { histos.fill(HIST("Prof_C2Sub2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, c2Sub); histos.fill(HIST("Prof_GapSum2D_PiPlus"), cent, gap, sum, c2Sub); @@ -3022,7 +3525,7 @@ struct RadialFlowDecorr { histos.fill(HIST("Prof_CovFT0A2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, covFT0A); if (std::isfinite(covFT0C)) histos.fill(HIST("Prof_CovFT0C2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, covFT0C); - } else if (isp == kPiAll) { + } else if (isp == kPiAllIdx) { if (std::isfinite(c2Sub)) { histos.fill(HIST("Prof_C2Sub2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, c2Sub); histos.fill(HIST("Prof_GapSum2D_PiAll"), cent, gap, sum, c2Sub); @@ -3033,7 +3536,7 @@ struct RadialFlowDecorr { histos.fill(HIST("Prof_CovFT0A2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, covFT0A); if (std::isfinite(covFT0C)) histos.fill(HIST("Prof_CovFT0C2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, covFT0C); - } else if (isp == kKaMinus) { + } else if (isp == kKaMinusIdx) { if (std::isfinite(c2Sub)) { histos.fill(HIST("Prof_C2Sub2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, c2Sub); histos.fill(HIST("Prof_GapSum2D_KaMinus"), cent, gap, sum, c2Sub); @@ -3044,7 +3547,7 @@ struct RadialFlowDecorr { histos.fill(HIST("Prof_CovFT0A2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, covFT0A); if (std::isfinite(covFT0C)) histos.fill(HIST("Prof_CovFT0C2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, covFT0C); - } else if (isp == kKaPlus) { + } else if (isp == kKaPlusIdx) { if (std::isfinite(c2Sub)) { histos.fill(HIST("Prof_C2Sub2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, c2Sub); histos.fill(HIST("Prof_GapSum2D_KaPlus"), cent, gap, sum, c2Sub); @@ -3055,7 +3558,7 @@ struct RadialFlowDecorr { histos.fill(HIST("Prof_CovFT0A2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, covFT0A); if (std::isfinite(covFT0C)) histos.fill(HIST("Prof_CovFT0C2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, covFT0C); - } else if (isp == kKaAll) { + } else if (isp == kKaAllIdx) { if (std::isfinite(c2Sub)) { histos.fill(HIST("Prof_C2Sub2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, c2Sub); histos.fill(HIST("Prof_GapSum2D_KaAll"), cent, gap, sum, c2Sub); @@ -3066,7 +3569,7 @@ struct RadialFlowDecorr { histos.fill(HIST("Prof_CovFT0A2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, covFT0A); if (std::isfinite(covFT0C)) histos.fill(HIST("Prof_CovFT0C2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, covFT0C); - } else if (isp == kProton) { + } else if (isp == kPrIdx) { if (std::isfinite(c2Sub)) { histos.fill(HIST("Prof_C2Sub2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, c2Sub); histos.fill(HIST("Prof_GapSum2D_Pr"), cent, gap, sum, c2Sub); @@ -3077,7 +3580,7 @@ struct RadialFlowDecorr { histos.fill(HIST("Prof_CovFT0A2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covFT0A); if (std::isfinite(covFT0C)) histos.fill(HIST("Prof_CovFT0C2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covFT0C); - } else if (isp == kAntiProton) { + } else if (isp == kAntiPrIdx) { if (std::isfinite(c2Sub)) { histos.fill(HIST("Prof_C2Sub2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, c2Sub); histos.fill(HIST("Prof_GapSum2D_AntiPr"), cent, gap, sum, c2Sub); @@ -3088,17 +3591,17 @@ struct RadialFlowDecorr { histos.fill(HIST("Prof_CovFT0A2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, covFT0A); if (std::isfinite(covFT0C)) histos.fill(HIST("Prof_CovFT0C2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, covFT0C); - } else if (isp == kAllProton) { + } else if (isp == kPrAllIdx) { if (std::isfinite(c2Sub)) { - histos.fill(HIST("Prof_C2Sub2D_Cent_etaA_etaC_AllPr"), cent, etaValA, etaValB, c2Sub); - histos.fill(HIST("Prof_GapSum2D_AllPr"), cent, gap, sum, c2Sub); + histos.fill(HIST("Prof_C2Sub2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, c2Sub); + histos.fill(HIST("Prof_GapSum2D_PrAll"), cent, gap, sum, c2Sub); } if (std::isfinite(cov)) - histos.fill(HIST("Prof_Cov2D_Cent_etaA_etaC_AllPr"), cent, etaValA, etaValB, cov); + histos.fill(HIST("Prof_Cov2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, cov); if (std::isfinite(covFT0A)) - histos.fill(HIST("Prof_CovFT0A2D_Cent_etaA_etaC_AllPr"), cent, etaValA, etaValB, covFT0A); + histos.fill(HIST("Prof_CovFT0A2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, covFT0A); if (std::isfinite(covFT0C)) - histos.fill(HIST("Prof_CovFT0C2D_Cent_etaA_etaC_AllPr"), cent, etaValA, etaValB, covFT0C); + histos.fill(HIST("Prof_CovFT0C2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, covFT0C); } } } @@ -3106,6 +3609,7 @@ struct RadialFlowDecorr { } PROCESS_SWITCH(RadialFlowDecorr, processDataFluc, "process data to calculate fluc pT", cfgRunDataFluc); }; + WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { WorkflowSpec workflow{adaptAnalysisTask(cfgc)}; From a2453cc4f0a9258603cf47f4285cbadffa6d633f Mon Sep 17 00:00:00 2001 From: limhyunji999 <95397778+limhyunji999@users.noreply.github.com> Date: Thu, 5 Mar 2026 21:36:56 +0900 Subject: [PATCH 180/347] [PWGLF] Add isPhysicalPrimary() for check the primary tagging (#15273) --- PWGLF/Tasks/Resonances/rho770analysis.cxx | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/PWGLF/Tasks/Resonances/rho770analysis.cxx b/PWGLF/Tasks/Resonances/rho770analysis.cxx index b1d954f0117..6715835c8ea 100644 --- a/PWGLF/Tasks/Resonances/rho770analysis.cxx +++ b/PWGLF/Tasks/Resonances/rho770analysis.cxx @@ -12,7 +12,7 @@ /// \file rho770analysis.cxx /// \brief rho(770)0 analysis in pp 13 & 13.6 TeV /// \author Hyunji Lim (hyunji.lim@cern.ch) -/// \since 08/02/2026 +/// \since 05/03/2026 #include "PWGLF/DataModel/LFResonanceTables.h" #include "PWGLF/DataModel/mcCentrality.h" @@ -64,9 +64,9 @@ struct rho770analysis { // DCA cuts Configurable cDCAxyToPVAsPt{"cDCAxyToPVAsPt", true, "DCAxy to PV selection as pt"}; - Configurable cDCAzToPVAsPt{"cDCAzToPVAsPt", false, "DCAz to PV selection as pt"}; - Configurable cfgMaxDCAxyToPVcut{"cfgMaxDCAxyToPVcut", 0.15, "Maximum transverse DCA"}; - Configurable cfgMaxDCAzToPVcut{"cfgMaxDCAzToPVcut", 2.0, "Maximum longitudinal DCA"}; + Configurable cDCAzToPVAsPt{"cDCAzToPVAsPt", true, "DCAz to PV selection as pt"}; + Configurable cfgMaxDCAxyToPVcut{"cfgMaxDCAxyToPVcut", 0.10, "Maximum transverse DCA"}; + Configurable cfgMaxDCAzToPVcut{"cfgMaxDCAzToPVcut", 0.10, "Maximum longitudinal DCA"}; Configurable cDCAxytoPVByPtPiFirstP0{"cDCAxytoPVByPtPiFirstP0", 0.0105, "Coeff. Track DCAxy cut to PV by pt for Pion First (p0)"}; Configurable cDCAxyToPVByPtPiFirstExp{"cDCAxyToPVByPtPiFirstExp", 0.035, "Coeff. Track DCAxy cut to PV by pt for Pion First (exp)"}; Configurable cDCAztoPVByPtPiFirstP0{"cDCAztoPVByPtPiFirstP0", 0.0105, "Coeff. Track DCAz cut to PV by pt for Pion First (p0)"}; @@ -88,7 +88,7 @@ struct rho770analysis { Configurable cfgUseITSRefit{"cfgUseITSRefit", false, "Require ITS Refit"}; Configurable cfgHasTOF{"cfgHasTOF", false, "Require TOF"}; Configurable cfgTPCcluster{"cfgTPCcluster", 1, "Number of TPC cluster"}; - Configurable cfgTPCRows{"cfgTPCRows", 80, "Minimum Number of TPC Crossed Rows "}; + Configurable cfgTPCRows{"cfgTPCRows", 70, "Minimum Number of TPC Crossed Rows "}; // PID Configurable cMaxTOFnSigmaPion{"cMaxTOFnSigmaPion", 3.0, "TOF nSigma cut for Pion"}; // TOF @@ -102,7 +102,7 @@ struct rho770analysis { ConfigurableAxis massK0sAxis{"massK0sAxis", {200, 0.46, 0.54}, "K0s Invariant mass axis"}; ConfigurableAxis massKstarAxis{"massKstarAxis", {200, 0.6, 1.3}, "Kstar Invariant mass axis"}; ConfigurableAxis ptAxis{"ptAxis", {VARIABLE_WIDTH, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0, 10.0, 13.0, 20.0}, "Transverse momentum Binning"}; - ConfigurableAxis centAxis{"centAxis", {VARIABLE_WIDTH, 0.0, 1.0, 5.0, 10.0, 15.0, 20.0, 25.0, 30.0, 35.0, 40.0, 45.0, 50.0, 55.0, 60.0, 65.0, 70.0, 75.0, 80.0, 95.0, 100.0, 105.0, 110.0}, "Centrality Binning"}; + ConfigurableAxis centAxis{"centAxis", {VARIABLE_WIDTH, 0.0, 1.0, 5.0, 10.0, 15.0, 20.0, 25.0, 30.0, 35.0, 40.0, 45.0, 50.0, 55.0, 60.0, 65.0, 70.0, 75.0, 80.0, 85.0, 90.0, 95.0, 100.0, 105.0}, "Centrality Binning"}; void init(o2::framework::InitContext&) { @@ -197,7 +197,7 @@ struct rho770analysis { const auto mode = static_cast(selectTypeInt.value); if (mode == TrackPIDMode::TPCOrTOF) { // TPC or TOF - if (std::fabs(track.tpcNSigmaPi()) >= cMaxTPCnSigmaPion || std::fabs(track.tofNSigmaPi()) >= cMaxTOFnSigmaPion) + if (std::fabs(track.tpcNSigmaPi()) >= cMaxTPCnSigmaPion && std::fabs(track.tofNSigmaPi()) >= cMaxTOFnSigmaPion) return false; } if (mode == TrackPIDMode::OnlyTPC) { // only TPC @@ -226,7 +226,7 @@ struct rho770analysis { const auto mode = static_cast(selectTypeInt.value); if (mode == TrackPIDMode::TPCOrTOF) { - if (std::fabs(track.tpcNSigmaKa()) >= cMaxTPCnSigmaPion || std::fabs(track.tofNSigmaKa()) >= cMaxTOFnSigmaPion) + if (std::fabs(track.tpcNSigmaKa()) >= cMaxTPCnSigmaPion && std::fabs(track.tofNSigmaKa()) >= cMaxTOFnSigmaPion) return false; } if (mode == TrackPIDMode::OnlyTPC) { @@ -410,6 +410,8 @@ struct rho770analysis { for (const auto& part : resoParents) { // loop over all pre-filtered MC particles if (std::abs(part.pdgCode()) != kRho770_0) continue; + if (!part.isPhysicalPrimary()) + continue; if (!part.producedByGenerator()) continue; if (part.y() < cfgMinRap || part.y() > cfgMaxRap) From 3705ceeb33a7f928530e324774e40dc8ffff473d Mon Sep 17 00:00:00 2001 From: rolavick Date: Thu, 5 Mar 2026 16:50:53 +0100 Subject: [PATCH 181/347] [PWGUD] Fix of two tracks table tree (#15257) Co-authored-by: ALICE Action Bot --- PWGUD/DataModel/TwoTracksEventTables.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWGUD/DataModel/TwoTracksEventTables.h b/PWGUD/DataModel/TwoTracksEventTables.h index 73be3f3c438..5eb2640f431 100644 --- a/PWGUD/DataModel/TwoTracksEventTables.h +++ b/PWGUD/DataModel/TwoTracksEventTables.h @@ -29,7 +29,7 @@ namespace two_tracks_tree { // event info DECLARE_SOA_COLUMN(RunNumber, runNumber, int32_t); -DECLARE_SOA_COLUMN(Bc, bc, int); +DECLARE_SOA_COLUMN(Bc, bc, uint64_t); DECLARE_SOA_COLUMN(TotalTracks, totalTracks, int); DECLARE_SOA_COLUMN(NumContrib, numContrib, int); DECLARE_SOA_COLUMN(GlobalNonPVtracks, globalNonPVtracks, int); From f249b10b9d25278d673ce41144a700495ea14617 Mon Sep 17 00:00:00 2001 From: arossi81 Date: Thu, 5 Mar 2026 20:44:17 +0100 Subject: [PATCH 182/347] [DPG] Adding possibility to filter on collisions with kIsGoodITSLayer0123. (#15225) Co-authored-by: Andrea --- DPG/Tasks/ITS/filterTracks.cxx | 51 ++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/DPG/Tasks/ITS/filterTracks.cxx b/DPG/Tasks/ITS/filterTracks.cxx index b97c48d4f5c..446a792e3f4 100644 --- a/DPG/Tasks/ITS/filterTracks.cxx +++ b/DPG/Tasks/ITS/filterTracks.cxx @@ -55,15 +55,15 @@ DECLARE_SOA_COLUMN(Pz, pz, float); //! track pz // DECLARE_SOA_COLUMN(Z, z, float); //! track z position at the DCA to the primary vertex // DECLARE_SOA_COLUMN(DcaXY, dcaXY, float); //! track distance of closest approach at the primary vertex: in xy plane // DECLARE_SOA_COLUMN(DcaZ, dcaz, float); //! track distance of closest approach at the primary vertex: along z (beam line) direction -DECLARE_SOA_COLUMN(Charge, charge, int); //! track sign, not really charge -DECLARE_SOA_COLUMN(NsigmaTPCpi, nsigmaTPCpi, float); //! TPC nsigma w.r.t. pion mass hypothesis -DECLARE_SOA_COLUMN(NsigmaTPCka, nsigmaTPCka, float); //! TPC nsigma w.r.t. kaon mass hypothesis -DECLARE_SOA_COLUMN(NsigmaTPCpr, nsigmaTPCpr, float); //! TPC nsigma w.r.t. proton mass hypothesis -DECLARE_SOA_COLUMN(NsigmaTOFpi, nsigmaTOFpi, float); //! TOF nsigma w.r.t. pion mass hypothesis -DECLARE_SOA_COLUMN(NsigmaTOFka, nsigmaTOFka, float); //! TOF nsigma w.r.t. kaon mass hypothesis -DECLARE_SOA_COLUMN(NsigmaTOFpr, nsigmaTOFpr, float); //! TOF nsigma w.r.t. proton mass hypothesis -DECLARE_SOA_COLUMN(TpcNCluster, tpcNCluster, int); //! TOF nsigma w.r.t. proton mass hypothesis - +DECLARE_SOA_COLUMN(Charge, charge, int); //! track sign, not really charge +DECLARE_SOA_COLUMN(NsigmaTPCpi, nsigmaTPCpi, float); //! TPC nsigma w.r.t. pion mass hypothesis +DECLARE_SOA_COLUMN(NsigmaTPCka, nsigmaTPCka, float); //! TPC nsigma w.r.t. kaon mass hypothesis +DECLARE_SOA_COLUMN(NsigmaTPCpr, nsigmaTPCpr, float); //! TPC nsigma w.r.t. proton mass hypothesis +DECLARE_SOA_COLUMN(NsigmaTOFpi, nsigmaTOFpi, float); //! TOF nsigma w.r.t. pion mass hypothesis +DECLARE_SOA_COLUMN(NsigmaTOFka, nsigmaTOFka, float); //! TOF nsigma w.r.t. kaon mass hypothesis +DECLARE_SOA_COLUMN(NsigmaTOFpr, nsigmaTOFpr, float); //! TOF nsigma w.r.t. proton mass hypothesis +DECLARE_SOA_COLUMN(TpcNCluster, tpcNCluster, int); //! TOF nsigma w.r.t. proton mass hypothesis +DECLARE_SOA_COLUMN(EventIsGoodITS123, eventIsGoodITS0123, uint8_t); //! flag to store bit of o2::aod::evsel::kIsGoodITSLayer0123 ///// MC INFO DECLARE_SOA_COLUMN(MainHfMotherPdgCode, mainHfMotherPdgCode, int); //! mother pdg code for particles coming from HF, skipping intermediate resonance states. Not trustable when mother is not HF. Not suited for Sc->Lc decays, since Sc are never pointed to DECLARE_SOA_COLUMN(IsPhysicalPrimary, isPhysicalPrimary, bool); //! is phyiscal primary according to ALICE definition @@ -92,7 +92,8 @@ DECLARE_SOA_TABLE(FilterColl, "AOD", "FILTERCOLL", o2::aod::collision::Chi2, o2::aod::collision::NumContrib, o2::aod::collision::CollisionTime, - o2::aod::collision::CollisionTimeRes); + o2::aod::collision::CollisionTimeRes, + aod::filtertracks::EventIsGoodITS123); DECLARE_SOA_TABLE(FilterCollLite, "AOD", "FILTERCOLLLITE", o2::aod::collision::PosX, o2::aod::collision::PosY, @@ -105,14 +106,16 @@ DECLARE_SOA_TABLE(FilterCollLite, "AOD", "FILTERCOLLLITE", o2::aod::collision::CovZZ, o2::aod::collision::Chi2, o2::aod::collision::NumContrib, - o2::aod::collision::CollisionTime); + o2::aod::collision::CollisionTime, + aod::filtertracks::EventIsGoodITS123); DECLARE_SOA_TABLE(FilterCollPos, "AOD", "FILTERCOLLPOS", o2::aod::collision::PosX, o2::aod::collision::PosY, o2::aod::collision::PosZ, o2::aod::collision::Chi2, o2::aod::collision::NumContrib, - o2::aod::collision::CollisionTime); + o2::aod::collision::CollisionTime, + aod::filtertracks::EventIsGoodITS123); DECLARE_SOA_TABLE(FiltTrackColIdx, "AOD", "FILTTRACKCOLIDX", o2::aod::track::CollisionId); DECLARE_SOA_TABLE(FilterTrack, "AOD", "FILTERTRACK", @@ -166,7 +169,7 @@ DECLARE_SOA_TABLE(GenParticles, "AOD", "GENPARTICLES", } // namespace o2::aod struct FilterTracks { - const static int nStudiedParticlesMc = 3; + static const int nStudiedParticlesMc = 3; Produces filteredTracksCollIdx; Produces filteredTracksTableExtra; @@ -307,30 +310,30 @@ struct FilterTracks { for (auto const& track : tracks) { fillTableData(track); if (produceCollTableExtraLite == 2) { - filterCollPosTable(collision.posX(), collision.posY(), collision.posZ(), collision.chi2(), collision.numContrib(), collision.collisionTime()); - }; + filterCollPosTable(collision.posX(), collision.posY(), collision.posZ(), collision.chi2(), collision.numContrib(), collision.collisionTime(), collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer0123)); + } } } else { auto lowPtTracksThisColl = lowPtTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); for (auto const& track : lowPtTracksThisColl) { fillTableData(track); if (produceCollTableExtraLite == 2) { - filterCollPosTable(collision.posX(), collision.posY(), collision.posZ(), collision.chi2(), collision.numContrib(), collision.collisionTime()); - }; + filterCollPosTable(collision.posX(), collision.posY(), collision.posZ(), collision.chi2(), collision.numContrib(), collision.collisionTime(), collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer0123)); + } } auto midPtTracksThisColl = midPtTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); for (auto const& track : midPtTracksThisColl) { fillTableData(track); if (produceCollTableExtraLite == 2) { - filterCollPosTable(collision.posX(), collision.posY(), collision.posZ(), collision.chi2(), collision.numContrib(), collision.collisionTime()); - }; + filterCollPosTable(collision.posX(), collision.posY(), collision.posZ(), collision.chi2(), collision.numContrib(), collision.collisionTime(), collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer0123)); + } } auto highPtTracksThisColl = highPtTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); for (auto const& track : highPtTracksThisColl) { fillTableData(track); if (produceCollTableExtraLite == 2) { - filterCollPosTable(collision.posX(), collision.posY(), collision.posZ(), collision.chi2(), collision.numContrib(), collision.collisionTime()); - }; + filterCollPosTable(collision.posX(), collision.posY(), collision.posZ(), collision.chi2(), collision.numContrib(), collision.collisionTime(), collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer0123)); + } } } } @@ -338,11 +341,11 @@ struct FilterTracks { void processCollisions(FilterCollisionsWithEvSel::iterator const& collision) { if (produceCollTableFull) - filterCollTable(collision.bcId(), collision.posX(), collision.posY(), collision.posZ(), collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ(), collision.flags(), collision.chi2(), collision.numContrib(), collision.collisionTime(), collision.collisionTimeRes()); + filterCollTable(collision.bcId(), collision.posX(), collision.posY(), collision.posZ(), collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ(), collision.flags(), collision.chi2(), collision.numContrib(), collision.collisionTime(), collision.collisionTimeRes(), collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer0123)); if (produceCollTableLite) - filterCollLiteTable(collision.posX(), collision.posY(), collision.posZ(), collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ(), collision.chi2(), collision.numContrib(), collision.collisionTime()); + filterCollLiteTable(collision.posX(), collision.posY(), collision.posZ(), collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ(), collision.chi2(), collision.numContrib(), collision.collisionTime(), collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer0123)); if (produceCollTableExtraLite == 1) - filterCollPosTable(collision.posX(), collision.posY(), collision.posZ(), collision.chi2(), collision.numContrib(), collision.collisionTime()); + filterCollPosTable(collision.posX(), collision.posY(), collision.posZ(), collision.chi2(), collision.numContrib(), collision.collisionTime(), collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer0123)); } PROCESS_SWITCH(FilterTracks, processCollisions, "process collisions", true); From 54a3dfbad6ef7d04352c9e90d58bebed56c787a3 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Thu, 5 Mar 2026 23:15:50 +0100 Subject: [PATCH 183/347] [PWGEM/Dilepton] update electron table 6 to add pid for tracking (#15281) Co-authored-by: ALICE Action Bot --- PWGEM/Dilepton/Core/SingleTrackQC.h | 3 + PWGEM/Dilepton/Core/SingleTrackQCMC.h | 3 + PWGEM/Dilepton/DataModel/dileptonTables.h | 37 ++++++++- .../TableProducer/Converters/CMakeLists.txt | 5 ++ .../Converters/electronConverter6.cxx | 76 +++++++++++++++++++ .../TableProducer/skimmerPrimaryElectron.cxx | 2 +- .../skimmerPrimaryElectronQC.cxx | 2 +- 7 files changed, 125 insertions(+), 3 deletions(-) create mode 100644 PWGEM/Dilepton/TableProducer/Converters/electronConverter6.cxx diff --git a/PWGEM/Dilepton/Core/SingleTrackQC.h b/PWGEM/Dilepton/Core/SingleTrackQC.h index 9fb4d919e4d..c0725cd2c58 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQC.h @@ -285,6 +285,7 @@ struct SingleTrackQC { // fRegistry.add("Track/positive/hTOFNsigmaKa", "TOF n sigma ka;p_{pv} (GeV/c);n #sigma_{K}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); // fRegistry.add("Track/positive/hTOFNsigmaPr", "TOF n sigma pr;p_{pv} (GeV/c);n #sigma_{p}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/positive/hPIDForTracking", "PID for trackng", kTH1F, {{9, -0.5, 8.5}}, false); // see numbering in O2/DataFormats/Reconstruction/include/ReconstructionDataFormats/PID.h fRegistry.add("Track/positive/hProbElBDT", "probability to be e from BDT;p_{in} (GeV/c);BDT score;", kTH2F, {{1000, 0, 10}, {100, 0, 1}}, false); fRegistry.add("Track/positive/hMeanClusterSizeITS", "mean cluster size ITS;p_{pv} (GeV/c); on ITS #times cos(#lambda);", kTH2F, {{1000, 0.f, 10.f}, {150, 0, 15}}, false); fRegistry.add("Track/positive/hMeanClusterSizeITSib", "mean cluster size ITS inner barrel;p_{pv} (GeV/c); on ITS #times cos(#lambda);", kTH2F, {{1000, 0.f, 10.f}, {150, 0, 15}}, false); @@ -582,6 +583,7 @@ struct SingleTrackQC { fRegistry.fill(HIST("Track/positive/hTPCdEdx"), track.tpcInnerParam(), track.tpcSignal()); fRegistry.fill(HIST("Track/positive/hTOFbeta"), track.p(), track.beta()); + fRegistry.fill(HIST("Track/positive/hPIDForTracking"), track.pidForTracking()); fRegistry.fill(HIST("Track/positive/hProbElBDT"), track.tpcInnerParam(), track.probElBDT()); fRegistry.fill(HIST("Track/positive/hMeanClusterSizeITS"), track.p(), track.meanClusterSizeITS() * std::cos(std::atan(track.tgl()))); fRegistry.fill(HIST("Track/positive/hMeanClusterSizeITSib"), track.p(), track.meanClusterSizeITSib() * std::cos(std::atan(track.tgl()))); @@ -621,6 +623,7 @@ struct SingleTrackQC { fRegistry.fill(HIST("Track/negative/hTPCdEdx"), track.tpcInnerParam(), track.tpcSignal()); fRegistry.fill(HIST("Track/negative/hTOFbeta"), track.p(), track.beta()); + fRegistry.fill(HIST("Track/negative/hPIDForTracking"), track.pidForTracking()); fRegistry.fill(HIST("Track/negative/hProbElBDT"), track.tpcInnerParam(), track.probElBDT()); fRegistry.fill(HIST("Track/negative/hMeanClusterSizeITS"), track.p(), track.meanClusterSizeITS() * std::cos(std::atan(track.tgl()))); fRegistry.fill(HIST("Track/negative/hMeanClusterSizeITSib"), track.p(), track.meanClusterSizeITSib() * std::cos(std::atan(track.tgl()))); diff --git a/PWGEM/Dilepton/Core/SingleTrackQCMC.h b/PWGEM/Dilepton/Core/SingleTrackQCMC.h index 34eb5e4094c..daae66bd252 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQCMC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQCMC.h @@ -292,6 +292,7 @@ struct SingleTrackQCMC { fRegistry.add("Track/PromptLF/positive/hDeltaPin", "p_{in} vs. p_{pv};p_{in} (GeV/c);(p_{pv} - p_{in})/p_{in}", kTH2F, {{1000, 0, 10}, {200, -1, +1}}, false); fRegistry.add("Track/PromptLF/positive/hChi2TOF", "TOF Chi2;p_{pv} (GeV/c);chi2", kTH2F, {{1000, 0, 10}, {100, 0, 10}}, false); fRegistry.add("Track/PromptLF/positive/hITSClusterMap", "ITS cluster map", kTH1F, {{128, -0.5, 127.5}}, false); + fRegistry.add("Track/PromptLF/positive/hPIDForTracking", "PID for trackng", kTH1F, {{9, -0.5, 8.5}}, false); // see numbering in O2/DataFormats/Reconstruction/include/ReconstructionDataFormats/PID.h fRegistry.add("Track/PromptLF/positive/hPtGen_DeltaPtOverPtGen", "electron p_{T} resolution;p_{T}^{gen} (GeV/c);(p_{T}^{rec} - p_{T}^{gen})/p_{T}^{gen}", kTH2F, {{200, 0, 10}, {200, -1.0f, 1.0f}}, true); fRegistry.add("Track/PromptLF/positive/hPtGen_DeltaEta", "electron #eta resolution;p_{T}^{gen} (GeV/c);#eta^{rec} - #eta^{gen}", kTH2F, {{200, 0, 10}, {100, -0.05f, 0.05f}}, true); fRegistry.add("Track/PromptLF/positive/hPtGen_DeltaPhi", "electron #varphi resolution;p_{T}^{gen} (GeV/c);#varphi^{rec} - #varphi^{gen} (rad.)", kTH2F, {{200, 0, 10}, {100, -0.05f, 0.05f}}, true); @@ -676,6 +677,7 @@ struct SingleTrackQCMC { fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hDeltaPin"), track.tpcInnerParam(), (track.p() - track.tpcInnerParam()) / track.tpcInnerParam()); } fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hITSClusterMap"), track.itsClusterMap()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hPIDForTracking"), track.pidForTracking()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hPtGen_DeltaPtOverPtGen"), mctrack.pt(), (track.pt() - mctrack.pt()) / mctrack.pt()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hPtGen_DeltaEta"), mctrack.pt(), track.eta() - mctrack.eta()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hPtGen_DeltaPhi"), mctrack.pt(), track.phi() - mctrack.phi()); @@ -721,6 +723,7 @@ struct SingleTrackQCMC { fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hDeltaPin"), track.tpcInnerParam(), (track.p() - track.tpcInnerParam()) / track.tpcInnerParam()); } fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hITSClusterMap"), track.itsClusterMap()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hPIDForTracking"), track.pidForTracking()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hPtGen_DeltaPtOverPtGen"), mctrack.pt(), (track.pt() - mctrack.pt()) / mctrack.pt()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hPtGen_DeltaEta"), mctrack.pt(), track.eta() - mctrack.eta()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hPtGen_DeltaPhi"), mctrack.pt(), track.phi() - mctrack.phi()); diff --git a/PWGEM/Dilepton/DataModel/dileptonTables.h b/PWGEM/Dilepton/DataModel/dileptonTables.h index 5d051a9705a..10252c7cc9d 100644 --- a/PWGEM/Dilepton/DataModel/dileptonTables.h +++ b/PWGEM/Dilepton/DataModel/dileptonTables.h @@ -910,7 +910,42 @@ DECLARE_SOA_TABLE_VERSIONED(EMPrimaryElectrons_005, "AOD", "EMPRIMARYEL", 5, //! emprimaryelectron::MeanClusterSizeITSib, emprimaryelectron::MeanClusterSizeITSob); -using EMPrimaryElectrons = EMPrimaryElectrons_005; +DECLARE_SOA_TABLE_VERSIONED(EMPrimaryElectrons_006, "AOD", "EMPRIMARYEL", 6, //! + o2::soa::Index<>, emprimaryelectron::CollisionId, + emprimaryelectron::TrackId, emprimaryelectron::Sign, + track::Pt, track::Eta, track::Phi, + track::DcaXY, track::DcaZ, aod::track::CYY, aod::track::CZY, aod::track::CZZ, + track::TPCNClsFindable, track::TPCNClsFindableMinusFound, track::TPCNClsFindableMinusPID, track::TPCNClsFindableMinusCrossedRows, track::TPCNClsShared, + track::TPCChi2NCl, track::TPCInnerParam, + track::TPCSignal, pidtpc::TPCNSigmaEl, pidtpc::TPCNSigmaPi, pidtpc::TPCNSigmaKa, pidtpc::TPCNSigmaPr, + pidtofbeta::Beta, pidtof::TOFNSigmaEl, /*pidtof::TOFNSigmaPi, pidtof::TOFNSigmaKa, pidtof::TOFNSigmaPr,*/ + track::ITSClusterSizes, track::ITSChi2NCl, track::TOFChi2, track::DetectorMap, /*track::Tgl,*/ + emprimaryelectron::IsAssociatedToMPC, emprimaryelectron::IsAmbiguous, emprimaryelectron::ProbElBDT, track::Flags, + mcpidtpc::DeDxTunedMc, + + // dynamic column + track::TPCNClsFound, + track::TPCNClsPID, + track::TPCNClsCrossedRows, + track::TPCCrossedRowsOverFindableCls, + track::TPCFoundOverFindableCls, + track::TPCFractionSharedCls, + track::v001::ITSClusterMap, track::v001::ITSNCls, track::v001::ITSNClsInnerBarrel, + track::HasITS, track::HasTPC, track::HasTRD, track::HasTOF, + track::PIDForTracking, // see numbering in O2/DataFormats/Reconstruction/include/ReconstructionDataFormats/PID.h + track::IsPVContributor, + + emprimaryelectron::Signed1Pt, + emprimaryelectron::P, + emprimaryelectron::Px, + emprimaryelectron::Py, + emprimaryelectron::Pz, + emprimaryelectron::Tgl, + emprimaryelectron::MeanClusterSizeITS, + emprimaryelectron::MeanClusterSizeITSib, + emprimaryelectron::MeanClusterSizeITSob); + +using EMPrimaryElectrons = EMPrimaryElectrons_006; // iterators using EMPrimaryElectron = EMPrimaryElectrons::iterator; diff --git a/PWGEM/Dilepton/TableProducer/Converters/CMakeLists.txt b/PWGEM/Dilepton/TableProducer/Converters/CMakeLists.txt index b2fb9161bd4..d3b100b2a31 100644 --- a/PWGEM/Dilepton/TableProducer/Converters/CMakeLists.txt +++ b/PWGEM/Dilepton/TableProducer/Converters/CMakeLists.txt @@ -50,6 +50,11 @@ o2physics_add_dpl_workflow(electron-converter5 PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(electron-converter6 + SOURCES electronConverter6.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(track-converter1 SOURCES trackConverter1.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore diff --git a/PWGEM/Dilepton/TableProducer/Converters/electronConverter6.cxx b/PWGEM/Dilepton/TableProducer/Converters/electronConverter6.cxx new file mode 100644 index 00000000000..4f4550cccc9 --- /dev/null +++ b/PWGEM/Dilepton/TableProducer/Converters/electronConverter6.cxx @@ -0,0 +1,76 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +// +// ======================== +// +// This code runs loop over ULS ee pars for virtual photon QC. +// Please write to: daiki.sekihata@cern.ch + +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" + +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +struct electronConverter6 { + Produces track_006; + + void process(aod::EMPrimaryElectrons_005 const& tracks) + { + for (const auto& track : tracks) { + track_006(track.collisionId(), + track.trackId(), + track.sign(), + track.pt(), + track.eta(), + track.phi(), + track.dcaXY(), + track.dcaZ(), + track.cYY(), + track.cZY(), + track.cZZ(), + track.tpcNClsFindable(), + track.tpcNClsFindableMinusFound(), + track.tpcNClsFindableMinusPID(), + track.tpcNClsFindableMinusCrossedRows(), + track.tpcNClsShared(), + track.tpcChi2NCl(), + track.tpcInnerParam(), + track.tpcSignal(), + track.tpcNSigmaEl(), + track.tpcNSigmaPi(), + track.tpcNSigmaKa(), + track.tpcNSigmaPr(), + track.beta(), + track.tofNSigmaEl(), + track.itsClusterSizes(), + track.itsChi2NCl(), + track.tofChi2(), + track.detectorMap(), + track.isAssociatedToMPC(), + track.isAmbiguous(), + track.probElBDT(), + 0, + track.mcTunedTPCSignal()); + } // end of track loop + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"electron-converter6"})}; +} diff --git a/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx index c838228edcf..8148a855f6d 100644 --- a/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx +++ b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx @@ -495,7 +495,7 @@ struct skimmerPrimaryElectron { beta, tofNSigmaEl, track.itsClusterSizes(), track.itsChi2NCl(), track.tofChi2(), track.detectorMap(), - isAssociatedToMPC, false, probaEl, mcTunedTPCSignal); + isAssociatedToMPC, false, probaEl, track.flags(), mcTunedTPCSignal); emprimaryelectronscov( trackParCov.getX(), diff --git a/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectronQC.cxx b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectronQC.cxx index edae6eba189..335fb978425 100644 --- a/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectronQC.cxx +++ b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectronQC.cxx @@ -501,7 +501,7 @@ struct skimmerPrimaryElectronQC { track.itsClusterSizes(), track.itsChi2NCl(), track.tofChi2(), track.detectorMap(), // trackParCov.getTgl(), - isAssociatedToMPC, false, probaEl, mcTunedTPCSignal); + isAssociatedToMPC, false, probaEl, track.flags(), mcTunedTPCSignal); emprimaryelectronscov( trackParCov.getX(), From 329e962809537f9fb6259c4fee913e0140b9e1fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Eduardo=20Mu=C3=B1oz=20M=C3=A9ndez?= <56033627+jmunozme@users.noreply.github.com> Date: Thu, 5 Mar 2026 17:14:29 -0600 Subject: [PATCH 184/347] [PWGLF,PWGMM] Make track cuts configurable (#15247) --- PWGMM/UE/Tasks/uecharged.cxx | 142 ++++++++++++++++++++--------------- 1 file changed, 83 insertions(+), 59 deletions(-) diff --git a/PWGMM/UE/Tasks/uecharged.cxx b/PWGMM/UE/Tasks/uecharged.cxx index 56bd369a290..dc65eeda8eb 100644 --- a/PWGMM/UE/Tasks/uecharged.cxx +++ b/PWGMM/UE/Tasks/uecharged.cxx @@ -13,7 +13,7 @@ /// \file uecharged.cxx /// \brief Underlying event analysis task /// \since November 2021 -/// \last update: January 2026 +/// \last update: March 2026 #include "PWGLF/DataModel/mcCentrality.h" #include "PWGLF/Utils/collisionCuts.h" @@ -50,47 +50,6 @@ using FT0s = aod::FT0s; struct ueCharged { - TrackSelection myTrackSelectionPrim() - { - TrackSelection selectedTracks; - selectedTracks.SetPtRange(0.1f, 1e10f); - selectedTracks.SetEtaRange(-0.8f, 0.8f); - selectedTracks.SetRequireITSRefit(true); - selectedTracks.SetRequireTPCRefit(true); - selectedTracks.SetRequireGoldenChi2(true); - selectedTracks.SetMinNCrossedRowsTPC(70); - selectedTracks.SetMinNCrossedRowsOverFindableClustersTPC(0.8f); - selectedTracks.SetMaxChi2PerClusterTPC(4.f); - selectedTracks.SetRequireHitsInITSLayers(1, {0, 1, 2}); // Run3ITSibAny - selectedTracks.SetMaxChi2PerClusterITS(36.f); - selectedTracks.SetMaxDcaXYPtDep([](float pt) { return 0.0105f + 0.0350f / std::pow(pt, 1.1f); }); - selectedTracks.SetMaxDcaZ(0.1f); - return selectedTracks; - } - - TrackSelection myTrackSelectionOpenDCA() - { - TrackSelection selectedTracks; - selectedTracks.SetPtRange(0.1f, 1e10f); - selectedTracks.SetEtaRange(-0.8f, 0.8f); - selectedTracks.SetRequireITSRefit(true); - selectedTracks.SetRequireTPCRefit(true); - selectedTracks.SetRequireGoldenChi2(true); - selectedTracks.SetMinNCrossedRowsTPC(70); - selectedTracks.SetMinNCrossedRowsOverFindableClustersTPC(0.8f); - selectedTracks.SetMaxChi2PerClusterTPC(4.f); - selectedTracks.SetRequireHitsInITSLayers(1, {0, 1, 2}); // Run3ITSibAny - selectedTracks.SetMaxChi2PerClusterITS(36.f); - selectedTracks.SetMaxDcaXYPtDep([](float pt) { return 0.0105f + 0.0350f / pow(pt, 1.1f); }); - selectedTracks.SetMaxDcaZ(0.1f); - return selectedTracks; - } - - TrackSelection mySelectionPrim; - TrackSelection mySelectionOpenDCA; - - Service pdg; - // Configurable for event selection Configurable isRun3{"isRun3", true, "is Run3 dataset"}; Configurable pileuprejection{"pileuprejection", true, "Pileup rejection"}; @@ -99,9 +58,27 @@ struct ueCharged { Configurable removeITSROFBorder{"removeITSROFBorder", false, "Remove ITS Read-Out Frame border and only apply kIsTriggerTVX & kNoTimeFrameBorder (recommended for MC)"}; Configurable cfgINELCut{"cfgINELCut", 0, "INEL event selection: 0 no sel, 1 INEL>0, 2 INEL>1"}; Configurable analyzeEvandTracksel{"analyzeEvandTracksel", true, "Analyze the event and track selection"}; - // acceptance cuts - Configurable cfgTrkEtaCut{"cfgTrkEtaCut", 0.8f, "Eta range for tracks"}; + + // Track selection configurables + TrackSelection myTrkSel; Configurable cfgTrkLowPtCut{"cfgTrkLowPtCut", 0.15f, "Minimum constituent pT"}; + Configurable isCustomTracks{"isCustomTracks", true, "Use custom track cuts"}; + Configurable setITSreq{"setITSreq", 0, "0 = Run3ITSibAny, 1 = Run3ITSallAny, 2 = Run3ITSall7Layers, 3 = Run3ITSibTwo"}; + Configurable minPt{"minPt", 0.1f, "Set minimum pT of tracks"}; + Configurable maxPt{"maxPt", 1e10f, "Set maximum pT of tracks"}; + Configurable requireEta{"requireEta", 0.8f, "Set eta range of tracks"}; + Configurable requireITSRefit{"requireITSRefit", true, "Additional cut on the ITS requirement"}; + Configurable requireTPCRefit{"requireTPCRefit", true, "Additional cut on the TPC requirement"}; + Configurable requireGoldenChi2{"requireGoldenChi2", true, "Additional cut on the GoldenChi2"}; + Configurable maxChi2PerClusterTPC{"maxChi2PerClusterTPC", 4.f, "Additional cut on the maximum value of the chi2 per cluster in the TPC"}; + Configurable maxChi2PerClusterITS{"maxChi2PerClusterITS", 36.f, "Additional cut on the maximum value of the chi2 per cluster in the ITS"}; + // Configurable minITSnClusters{"minITSnClusters", 5, "minimum number of found ITS clusters"}; + Configurable minNCrossedRowsTPC{"minNCrossedRowsTPC", 70.f, "Additional cut on the minimum number of crossed rows in the TPC"}; + Configurable minNCrossedRowsOverFindableClustersTPC{"minNCrossedRowsOverFindableClustersTPC", 0.8f, "Additional cut on the minimum value of the ratio between crossed rows and findable clusters in the TPC"}; + Configurable maxDcaXYFactor{"maxDcaXYFactor", 1.f, "Multiplicative factor on the maximum value of the DCA xy"}; + Configurable maxDcaZ{"maxDcaZ", 0.1f, "Additional cut on the maximum value of the DCA z"}; + + Service pdg; // Data table definitions using ColDataTable = soa::Join; @@ -152,6 +129,24 @@ struct ueCharged { void init(InitContext const&) { + if (isCustomTracks.value) { + myTrkSel = getGlobalTrackSelectionRun3ITSMatch(setITSreq.value); + myTrkSel.SetPtRange(minPt.value, maxPt.value); + myTrkSel.SetEtaRange(-requireEta.value, requireEta.value); + myTrkSel.SetRequireITSRefit(requireITSRefit.value); + myTrkSel.SetRequireTPCRefit(requireTPCRefit.value); + myTrkSel.SetRequireGoldenChi2(requireGoldenChi2.value); + myTrkSel.SetMaxChi2PerClusterTPC(maxChi2PerClusterTPC.value); + myTrkSel.SetMaxChi2PerClusterITS(maxChi2PerClusterITS.value); + // myTrkSel.SetMinNClustersITS(minITSnClusters.value); + myTrkSel.SetMinNCrossedRowsTPC(minNCrossedRowsTPC.value); + myTrkSel.SetMinNCrossedRowsOverFindableClustersTPC(minNCrossedRowsOverFindableClustersTPC.value); + // myTrkSel.SetMaxDcaXYPtDep([](float pt) { return 0.0105f + 0.0350f / pow(pt, 1.1f); }); + myTrkSel.SetMaxDcaXYPtDep([](float /*pt*/) { return 10000.f; }); + myTrkSel.SetMaxDcaZ(maxDcaZ.value); + myTrkSel.print(); + } + ConfigurableAxis ptBinningt{"ptBinningt", {0, 0.15, 0.50, 1.00, 1.50, 2.00, 2.50, 3.00, 3.50, 4.00, 4.50, 5.00, 6.00, 7.00, @@ -325,16 +320,41 @@ struct ueCharged { if (!track.has_collision()) { return false; } - if (!mySelectionPrim.IsSelected(track)) { + if (track.pt() < cfgTrkLowPtCut) { return false; } - if (std::abs(track.eta()) >= cfgTrkEtaCut) { - return false; + if (isCustomTracks.value) { + for (int i = 0; i < static_cast(TrackSelection::TrackCuts::kNCuts); i++) { + if (i == static_cast(TrackSelection::TrackCuts::kDCAxy)) { + continue; + } + if (!myTrkSel.IsSelected(track, static_cast(i))) { + return false; + } + } + return (std::abs(track.dcaXY()) <= (maxDcaXYFactor.value * (0.0105f + 0.0350f / std::pow(track.pt(), 1.1f)))); } - if (track.pt() < cfgTrkLowPtCut) { - return false; + return track.isGlobalTrack(); + } + + template + bool isDCAxyWoCut(T const& track) // function to skip DCA track selections + { + if (isCustomTracks.value) { + for (int i = 0; i < static_cast(TrackSelection::TrackCuts::kNCuts); i++) { + if (i == static_cast(TrackSelection::TrackCuts::kDCAxy)) { + continue; + } + if (i == static_cast(TrackSelection::TrackCuts::kDCAz)) { + continue; + } + if (!myTrkSel.IsSelected(track, static_cast(i))) { + return false; + } + } + return true; } - return true; + return track.isGlobalTrackWoDCA(); } template @@ -350,7 +370,7 @@ struct ueCharged { if (!pdgParticle || pdgParticle->Charge() == 0.) { return false; } - if (std::abs(particle.eta()) >= cfgTrkEtaCut) { + if (std::abs(particle.eta()) >= requireEta) { return false; } if (particle.pt() < cfgTrkLowPtCut) { @@ -508,7 +528,7 @@ struct ueCharged { std::vector indexArray; for (const auto& track : tracks) { - if (mySelectionOpenDCA.IsSelected(track)) + if (isDCAxyWoCut(track)) ue.fill(HIST("hPTVsDCAData"), track.pt(), track.dcaXY()); if (isTrackSelected(track)) { @@ -667,6 +687,10 @@ struct ueCharged { if (!foundRec) return; + if (analyzeEvandTracksel) { + analyzeEventAndTrackSelection(chosenRec, RecTracks.sliceBy(perCollision, chosenRecGlobalIndex)); + } + // compute truth-level leading particle and truth-region observables double flPtTrue = 0.; double flPhiTrue = 0.; @@ -762,7 +786,7 @@ struct ueCharged { if (!pdgParticle || pdgParticle->Charge() == 0.) { continue; } - if (std::abs(particle.eta()) >= cfgTrkEtaCut) { + if (std::abs(particle.eta()) >= requireEta) { continue; } @@ -832,7 +856,7 @@ struct ueCharged { if (track.collisionId() != chosenRecGlobalIndex) continue; - if (mySelectionOpenDCA.IsSelected(track)) + if (isDCAxyWoCut(track)) ue.fill(HIST("hPTVsDCAData"), track.pt(), track.dcaXY()); if (track.has_mcParticle()) { @@ -843,20 +867,20 @@ struct ueCharged { if (isTrackSelected(track)) ue.fill(HIST("hPtOut"), track.pt()); - if (mySelectionOpenDCA.IsSelected(track)) + if (isDCAxyWoCut(track)) ue.fill(HIST("hPtDCAall"), track.pt(), track.dcaXY()); if (particle.isPhysicalPrimary() && particle.producedByGenerator()) { // primary particles if (isTrackSelected(track) && isParticleSelected(particle)) { // TODO check if this condition ue.fill(HIST("hPtOutPrim"), particle.pt()); } - if (mySelectionOpenDCA.IsSelected(track)) { + if (isDCAxyWoCut(track)) { ue.fill(HIST("hPtDCAPrimary"), track.pt(), track.dcaXY()); } } else { // Secondaries (weak decays and material) if (isTrackSelected(track)) ue.fill(HIST("hPtOutSec"), track.pt()); - if (mySelectionOpenDCA.IsSelected(track)) { + if (isDCAxyWoCut(track)) { if (particle.getProcess() == 4) ue.fill(HIST("hPtDCAWeak"), track.pt(), track.dcaXY()); else @@ -996,7 +1020,7 @@ struct ueCharged { auto pdgParticle = pdg->GetParticle(particle.pdgCode()); if (!pdgParticle || pdgParticle->Charge() == 0.) continue; - if (std::abs(particle.eta()) >= cfgTrkEtaCut) + if (std::abs(particle.eta()) >= requireEta) continue; multTrue++; if (particle.pt() < cfgTrkLowPtCut) @@ -1145,7 +1169,7 @@ struct ueCharged { tracks_before++; } - if (mySelectionPrim.IsSelected(track)) { + if (isTrackSelected(track)) { if (track.hasITS() && track.hasTPC()) { ue.fill(HIST("postselection_track/ITS/itsNCls"), track.itsNCls()); ue.fill(HIST("postselection_track/ITS/itsChi2NCl"), track.itsChi2NCl()); From a10b7cd5390471627909a97dbe54ed7f08f7be76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <26327373+vkucera@users.noreply.github.com> Date: Fri, 6 Mar 2026 00:16:39 +0100 Subject: [PATCH 185/347] [PWGHF] Delete redundant MC columns from the data model (#14962) --- PWGHF/D2H/DataModel/ReducedDataModel.h | 111 ++--- PWGHF/D2H/Tasks/taskB0Reduced.cxx | 6 +- PWGHF/D2H/Tasks/taskBplusReduced.cxx | 6 +- PWGHF/D2H/Tasks/taskBplusToJpsiKReduced.cxx | 8 +- PWGHF/D2H/Tasks/taskBsReduced.cxx | 6 +- PWGHF/D2H/Tasks/taskBsToJpsiPhiReduced.cxx | 8 +- PWGHF/D2H/Tasks/taskDplus.cxx | 8 +- PWGHF/D2H/Tasks/taskLbReduced.cxx | 6 +- PWGHF/D2H/Tasks/taskOmegac0ToOmegaPi.cxx | 4 +- PWGHF/D2H/Tasks/taskXic0ToXiPi.cxx | 4 +- .../DataModel/CandidateReconstructionTables.h | 400 +++++++----------- PWGHF/DataModel/DerivedTables.h | 6 +- .../HFC/DataModel/ReducedDMesonPairsTables.h | 24 +- .../correlatorDplusDplusReduced.cxx | 8 +- .../derivedDataCreatorB0ToDPi.cxx | 10 +- .../derivedDataCreatorBplusToD0Pi.cxx | 10 +- .../derivedDataCreatorD0ToKPi.cxx | 18 +- .../derivedDataCreatorDplusToPiKPi.cxx | 10 +- .../derivedDataCreatorDsToKKPi.cxx | 10 +- .../derivedDataCreatorDstarToD0Pi.cxx | 10 +- .../derivedDataCreatorLcToK0sP.cxx | 10 +- .../derivedDataCreatorLcToPKPi.cxx | 10 +- .../derivedDataCreatorXicToXiPiPi.cxx | 10 +- PWGHF/TableProducer/treeCreatorB0ToDPi.cxx | 16 +- .../TableProducer/treeCreatorBplusToD0Pi.cxx | 14 +- PWGHF/TableProducer/treeCreatorBsToDsPi.cxx | 10 +- PWGHF/TableProducer/treeCreatorD0ToKPi.cxx | 18 +- .../TableProducer/treeCreatorDplusToPiKPi.cxx | 26 +- PWGHF/TableProducer/treeCreatorDsToKKPi.cxx | 36 +- .../TableProducer/treeCreatorDstarToD0Pi.cxx | 18 +- PWGHF/TableProducer/treeCreatorXicToPKPi.cxx | 6 +- .../TableProducer/treeCreatorXicToXiPiPi.cxx | 26 +- 32 files changed, 391 insertions(+), 482 deletions(-) diff --git a/PWGHF/D2H/DataModel/ReducedDataModel.h b/PWGHF/D2H/DataModel/ReducedDataModel.h index f3fcbc188d1..d70597c8678 100644 --- a/PWGHF/D2H/DataModel/ReducedDataModel.h +++ b/PWGHF/D2H/DataModel/ReducedDataModel.h @@ -846,6 +846,11 @@ DECLARE_SOA_TABLE(HfRedLbLcMls, "AOD", "HFREDLBLCML", //! Table with ML scores f using HfRedCandLb = soa::Join; +namespace hf_cand_mc_flag +{ +DECLARE_SOA_COLUMN(FlagWrongCollision, flagWrongCollision, int8_t); //! reconstruction level +} + namespace hf_b0_mc { // MC Rec @@ -873,9 +878,9 @@ DECLARE_SOA_COLUMN(PdgCodeProng3, pdgCodeProng3, int); //! Pdg code DECLARE_SOA_TABLE(HfMcRecRedDpPis, "AOD", "HFMCRECREDDPPI", //! Table with reconstructed MC information on DPi(<-B0) pairs for reduced workflow hf_cand_b0_reduced::Prong0Id, hf_cand_b0_reduced::Prong1Id, - hf_cand_b0::FlagMcMatchRec, - hf_cand_b0::FlagWrongCollision, - hf_cand_b0::DebugMcRec, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::FlagWrongCollision, + hf_cand_mc_flag::DebugMcRec, hf_b0_mc::PtMother); // try with extended table ? @@ -893,17 +898,17 @@ DECLARE_SOA_TABLE(HfMcCheckDpPis, "AOD", "HFMCCHECKDPPI", //! Table with reconst DECLARE_SOA_TABLE(HfMcRecRedDStarPis, "AOD", "HFMCRECREDDSTPI", //! Table with reconstructed MC information on DStarPi pairs for reduced workflow hf_cand_b0_reduced::ProngD0Id, hf_cand_b0_reduced::ProngBachPiId, - hf_cand_b0::FlagMcMatchRec, - hf_cand_b0::FlagWrongCollision, - hf_cand_b0::DebugMcRec, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::FlagWrongCollision, + hf_cand_mc_flag::DebugMcRec, hf_b0_mc::PtMother); // Table with same size as HFCANDB0 DECLARE_SOA_TABLE(HfMcRecRedB0s, "AOD", "HFMCRECREDB0", //! Reconstruction-level MC information on B0 candidates for reduced workflow - hf_cand_b0::FlagMcMatchRec, - hf_cand_b0::FlagMcDecayChanRec, - hf_cand_b0::FlagWrongCollision, - hf_cand_b0::DebugMcRec, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::FlagMcDecayChanRec, + hf_cand_mc_flag::FlagWrongCollision, + hf_cand_mc_flag::DebugMcRec, hf_b0_mc::PtMother); DECLARE_SOA_TABLE(HfMcCheckB0s, "AOD", "HFMCCHECKB0", //! Table with reconstructed MC information on B0 candidates for MC checks in reduced workflow @@ -916,8 +921,8 @@ DECLARE_SOA_TABLE(HfMcCheckB0s, "AOD", "HFMCCHECKB0", //! Table with reconstruct o2::soa::Marker<2>); DECLARE_SOA_TABLE(HfMcGenRedB0s, "AOD", "HFMCGENREDB0", //! Generation-level MC information on B0 candidates for reduced workflow - hf_cand_b0::FlagMcMatchGen, - hf_cand_b0::FlagMcDecayChanRec, + hf_cand_mc_flag::FlagMcMatchGen, + hf_cand_mc_flag::FlagMcDecayChanRec, hf_b0_mc::PtTrack, hf_b0_mc::YTrack, hf_b0_mc::EtaTrack, @@ -969,19 +974,19 @@ DECLARE_SOA_COLUMN(PdgCodeProng2, pdgCodeProng2, int); //! Pdg code DECLARE_SOA_TABLE(HfMcRecRedD0Pis, "AOD", "HFMCRECREDD0PI", //! Table with reconstructed MC information on D0Pi(<-B+) pairs for reduced workflow hf_cand_bplus_reduced::Prong0Id, hf_cand_bplus_reduced::Prong1Id, - hf_cand_bplus::FlagMcMatchRec, - hf_cand_bplus::FlagWrongCollision, - hf_cand_bplus::DebugMcRec, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::FlagWrongCollision, + hf_cand_mc_flag::DebugMcRec, hf_bplus_mc::PtMother); // table with results of reconstruction level MC matching DECLARE_SOA_TABLE(HfMcRecRedJPKs, "AOD", "HFMCRECREDJPK", //! Table with reconstructed MC information on J/PsiK(<-B+) pairs for reduced workflow hf_cand_bplus_reduced::JpsiId, hf_cand_bplus_reduced::BachKaId, - hf_cand_bplus::FlagMcMatchRec, - hf_cand_bplus::FlagMcDecayChanRec, - hf_cand_bplus::FlagWrongCollision, - hf_cand_bplus::DebugMcRec, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::FlagMcDecayChanRec, + hf_cand_mc_flag::FlagWrongCollision, + hf_cand_mc_flag::DebugMcRec, hf_bplus_mc::PtMother); // DECLARE_SOA_EXTENDED_TABLE_USER(ExTable, Tracks, "EXTABLE", @@ -995,10 +1000,10 @@ DECLARE_SOA_TABLE(HfMcCheckD0Pis, "AOD", "HFMCCHECKD0PI", //! Table with reconst // Table with same size as HFCANDBPLUS DECLARE_SOA_TABLE(HfMcRecRedBps, "AOD", "HFMCRECREDBP", //! Reconstruction-level MC information on B+ candidates for reduced workflow - hf_cand_bplus::FlagMcMatchRec, - hf_cand_bplus::FlagMcDecayChanRec, - hf_cand_bplus::FlagWrongCollision, - hf_cand_bplus::DebugMcRec, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::FlagMcDecayChanRec, + hf_cand_mc_flag::FlagWrongCollision, + hf_cand_mc_flag::DebugMcRec, hf_bplus_mc::PtMother); DECLARE_SOA_TABLE(HfMcCheckBps, "AOD", "HFMCCHECKBP", //! Table with reconstructed MC information on B+ candidates for MC checks in reduced workflow @@ -1010,8 +1015,8 @@ DECLARE_SOA_TABLE(HfMcCheckBps, "AOD", "HFMCCHECKBP", //! Table with reconstruct o2::soa::Marker<2>); DECLARE_SOA_TABLE(HfMcGenRedBps, "AOD", "HFMCGENREDBP", //! Generation-level MC information on B+ candidates for reduced workflow - hf_cand_bplus::FlagMcMatchGen, - hf_cand_bplus::FlagMcDecayChanRec, + hf_cand_mc_flag::FlagMcMatchGen, + hf_cand_mc_flag::FlagMcDecayChanRec, hf_bplus_mc::PtTrack, hf_bplus_mc::YTrack, hf_bplus_mc::EtaTrack, @@ -1070,9 +1075,9 @@ DECLARE_SOA_COLUMN(PdgCodeProng3, pdgCodeProng3, int); //! Pdg code DECLARE_SOA_TABLE(HfMcRecRedDsPis, "AOD", "HFMCRECREDDSPI", //! Table with reconstructed MC information on DsPi(<-Bs) pairs for reduced workflow hf_cand_bs_reduced::Prong0Id, hf_cand_bs_reduced::Prong1Id, - hf_cand_bs::FlagMcMatchRec, - hf_cand_bs::FlagWrongCollision, - hf_cand_bs::DebugMcRec, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::FlagWrongCollision, + hf_cand_mc_flag::DebugMcRec, hf_bs_mc::PtMother); // table with results of reconstruction level MC matching @@ -1080,10 +1085,10 @@ DECLARE_SOA_TABLE(HfMcRecRedJPPhis, "AOD", "HFMCRECREDJPPHI", //! Table with rec hf_cand_bs_reduced::JpsiId, hf_cand_bs_reduced::Prong0PhiId, hf_cand_bs_reduced::Prong1PhiId, - hf_cand_bs::FlagMcMatchRec, - hf_cand_bs::FlagMcDecayChanRec, - hf_cand_bs::FlagWrongCollision, - hf_cand_bs::DebugMcRec, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::FlagMcDecayChanRec, + hf_cand_mc_flag::FlagWrongCollision, + hf_cand_mc_flag::DebugMcRec, hf_bs_mc::PtMother); // try with extended table ? @@ -1099,10 +1104,10 @@ DECLARE_SOA_TABLE(HfMcCheckDsPis, "AOD", "HFMCCHECKDSPI", //! Table with reconst // Table with same size as HFCANDBS DECLARE_SOA_TABLE(HfMcRecRedBss, "AOD", "HFMCRECREDBS", //! Reconstruction-level MC information on Bs candidates for reduced workflow - hf_cand_bs::FlagMcMatchRec, - hf_cand_bs::FlagMcDecayChanRec, - hf_cand_bs::FlagWrongCollision, - hf_cand_bs::DebugMcRec, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::FlagMcDecayChanRec, + hf_cand_mc_flag::FlagWrongCollision, + hf_cand_mc_flag::DebugMcRec, hf_bs_mc::PtMother); DECLARE_SOA_TABLE(HfMcCheckBss, "AOD", "HFMCCHECKBS", //! Table with reconstructed MC information on Bs candidates for MC checks in reduced workflow @@ -1115,8 +1120,8 @@ DECLARE_SOA_TABLE(HfMcCheckBss, "AOD", "HFMCCHECKBS", //! Table with reconstruct o2::soa::Marker<2>); DECLARE_SOA_TABLE(HfMcGenRedBss, "AOD", "HFMCGENREDBS", //! Generation-level MC information on Bs candidates for reduced workflow - hf_cand_bs::FlagMcMatchGen, - hf_cand_bs::FlagMcDecayChanRec, + hf_cand_mc_flag::FlagMcMatchGen, + hf_cand_mc_flag::FlagMcDecayChanRec, hf_bs_mc::PtTrack, hf_bs_mc::YTrack, hf_bs_mc::EtaTrack, @@ -1172,9 +1177,9 @@ DECLARE_SOA_COLUMN(PdgCodeProng3, pdgCodeProng3, int); //! Pdg code DECLARE_SOA_TABLE(HfMcRecRedLcPis, "AOD", "HFMCRECREDLCPI", //! Table with reconstructed MC information on LcPi(<-Lb) pairs for reduced workflow hf_cand_lb_reduced::Prong0Id, hf_cand_lb_reduced::Prong1Id, - hf_cand_lb::FlagMcMatchRec, - hf_cand_lb::FlagWrongCollision, - hf_cand_lb::DebugMcRec, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::FlagWrongCollision, + hf_cand_mc_flag::DebugMcRec, hf_lb_mc::PtMother); DECLARE_SOA_TABLE(HfMcCheckLcPis, "AOD", "HFMCCHECKLCPI", //! Table with reconstructed MC information on LcPi(<-Lb) pairs for MC checks in reduced workflow @@ -1188,9 +1193,9 @@ DECLARE_SOA_TABLE(HfMcCheckLcPis, "AOD", "HFMCCHECKLCPI", //! Table with reconst // Table with same size as HFCANDLc DECLARE_SOA_TABLE(HfMcRecRedLbs, "AOD", "HFMCRECREDLB", //! Reconstruction-level MC information on Lb candidates for reduced workflow - hf_cand_lb::FlagMcMatchRec, - hf_cand_lb::FlagWrongCollision, - hf_cand_lb::DebugMcRec, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::FlagWrongCollision, + hf_cand_mc_flag::DebugMcRec, hf_lb_mc::PtMother); DECLARE_SOA_TABLE(HfMcCheckLbs, "AOD", "HFMCCHECKLB", //! Table with reconstructed MC information on Lb candidates for MC checks in reduced workflow @@ -1203,7 +1208,7 @@ DECLARE_SOA_TABLE(HfMcCheckLbs, "AOD", "HFMCCHECKLB", //! Table with reconstruct o2::soa::Marker<2>); DECLARE_SOA_TABLE(HfMcGenRedLbs, "AOD", "HFMCGENREDLB", //! Generation-level MC information on Lb candidates for reduced workflow - hf_cand_lb::FlagMcMatchGen, + hf_cand_mc_flag::FlagMcMatchGen, hf_lb_mc::PtTrack, hf_lb_mc::YTrack, hf_lb_mc::EtaTrack, @@ -1553,7 +1558,7 @@ DECLARE_SOA_TABLE(Hf3PrV0McRec, "AOD", "HF3PRV0MCREC", hf_reso_cand_reduced::Origin, hf_reso_cand_reduced::PtGen, hf_reso_cand_reduced::InvMassGen, - hf_cand::NTracksDecayed, + hf_cand_mc_flag::NTracksDecayed, o2::soa::Marker<1>); DECLARE_SOA_TABLE(HfDstarV0McRec, "AOD", "HFDSTARV0MCREC", @@ -1566,7 +1571,7 @@ DECLARE_SOA_TABLE(HfDstarV0McRec, "AOD", "HFDSTARV0MCREC", hf_reso_cand_reduced::Origin, hf_reso_cand_reduced::PtGen, hf_reso_cand_reduced::InvMassGen, - hf_cand::NTracksDecayed, + hf_cand_mc_flag::NTracksDecayed, o2::soa::Marker<1>); DECLARE_SOA_TABLE(Hf2PrV0McRec, "AOD", "HF2PRV0MCREC", @@ -1579,7 +1584,7 @@ DECLARE_SOA_TABLE(Hf2PrV0McRec, "AOD", "HF2PRV0MCREC", hf_reso_cand_reduced::Origin, hf_reso_cand_reduced::PtGen, hf_reso_cand_reduced::InvMassGen, - hf_cand::NTracksDecayed, + hf_cand_mc_flag::NTracksDecayed, o2::soa::Marker<1>); DECLARE_SOA_TABLE(Hf3PrTrkMcRec, "AOD", "HF3PRTRKMCREC", @@ -1592,7 +1597,7 @@ DECLARE_SOA_TABLE(Hf3PrTrkMcRec, "AOD", "HF3PRTRKMCREC", hf_reso_cand_reduced::Origin, hf_reso_cand_reduced::PtGen, hf_reso_cand_reduced::InvMassGen, - hf_cand::NTracksDecayed, + hf_cand_mc_flag::NTracksDecayed, o2::soa::Marker<1>); DECLARE_SOA_TABLE(HfDstarTrkMcRec, "AOD", "HFDSTARTRKMCREC", @@ -1605,7 +1610,7 @@ DECLARE_SOA_TABLE(HfDstarTrkMcRec, "AOD", "HFDSTARTRKMCREC", hf_reso_cand_reduced::Origin, hf_reso_cand_reduced::PtGen, hf_reso_cand_reduced::InvMassGen, - hf_cand::NTracksDecayed, + hf_cand_mc_flag::NTracksDecayed, o2::soa::Marker<1>); DECLARE_SOA_TABLE(Hf2PrTrkMcRec, "AOD", "HF2PRTRKMCREC", @@ -1618,11 +1623,11 @@ DECLARE_SOA_TABLE(Hf2PrTrkMcRec, "AOD", "HF2PRTRKMCREC", hf_reso_cand_reduced::Origin, hf_reso_cand_reduced::PtGen, hf_reso_cand_reduced::InvMassGen, - hf_cand::NTracksDecayed, + hf_cand_mc_flag::NTracksDecayed, o2::soa::Marker<1>); DECLARE_SOA_TABLE(HfMcGenRedResos, "AOD", "HFMCGENREDRESO", //! Generation-level MC information on Ds-Resonances candidates for reduced workflow - hf_cand_b0::FlagMcMatchGen, + hf_cand_mc_flag::FlagMcMatchGen, hf_reso_cand_reduced::Origin, hf_b0_mc::PtTrack, hf_b0_mc::YTrack, @@ -1646,7 +1651,7 @@ DECLARE_SOA_TABLE(HfMcRecRedResos, "AOD", "HFMCRECREDRESO", //! Reconstruction-l hf_reso_cand_reduced::Origin, hf_reso_cand_reduced::PtGen, hf_reso_cand_reduced::InvMassGen, - hf_cand::NTracksDecayed, + hf_cand_mc_flag::NTracksDecayed, o2::soa::Marker<1>); } // namespace aod diff --git a/PWGHF/D2H/Tasks/taskB0Reduced.cxx b/PWGHF/D2H/Tasks/taskB0Reduced.cxx index 5e146308c45..16634591c5f 100644 --- a/PWGHF/D2H/Tasks/taskB0Reduced.cxx +++ b/PWGHF/D2H/Tasks/taskB0Reduced.cxx @@ -152,13 +152,13 @@ DECLARE_SOA_TABLE(HfRedCandB0Lites, "AOD", "HFREDCANDB0LITE", //! Table with som hf_cand_b0_lite::NSigTofPiBachelor, hf_cand_b0_lite::NSigTpcTofPiBachelor, // MC truth - hf_cand_3prong::FlagMcMatchRec, - hf_cand_3prong::OriginMcRec, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcRec, hf_cand_b0_lite::FlagWrongCollision, hf_cand_b0_lite::PtGen); DECLARE_SOA_TABLE(HfRedB0McCheck, "AOD", "HFREDB0MCCHECK", //! Table with MC decay type check - hf_cand_3prong::FlagMcMatchRec, + hf_cand_mc_flag::FlagMcMatchRec, hf_cand_b0_lite::FlagWrongCollision, hf_cand_b0_lite::MD, hf_cand_b0_lite::PtD, diff --git a/PWGHF/D2H/Tasks/taskBplusReduced.cxx b/PWGHF/D2H/Tasks/taskBplusReduced.cxx index bca08dbf154..5913760dcea 100644 --- a/PWGHF/D2H/Tasks/taskBplusReduced.cxx +++ b/PWGHF/D2H/Tasks/taskBplusReduced.cxx @@ -149,13 +149,13 @@ DECLARE_SOA_TABLE(HfRedCandBpLites, "AOD", "HFREDCANDBPLITE", //! Table with som hf_cand_bplus_lite::NSigTofPiBachelor, hf_cand_bplus_lite::NSigTpcTofPiBachelor, // MC truth - hf_cand_2prong::FlagMcMatchRec, - hf_cand_2prong::OriginMcRec, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcRec, hf_cand_bplus_lite::FlagWrongCollision, hf_cand_bplus_lite::PtGen); DECLARE_SOA_TABLE(HfRedBpMcCheck, "AOD", "HFREDBPMCCHECK", //! Table with MC decay type check - hf_cand_2prong::FlagMcMatchRec, + hf_cand_mc_flag::FlagMcMatchRec, hf_cand_bplus_lite::FlagWrongCollision, hf_cand_bplus_lite::MD, hf_cand_bplus_lite::PtD, diff --git a/PWGHF/D2H/Tasks/taskBplusToJpsiKReduced.cxx b/PWGHF/D2H/Tasks/taskBplusToJpsiKReduced.cxx index aa0ff931938..31fae6a389d 100644 --- a/PWGHF/D2H/Tasks/taskBplusToJpsiKReduced.cxx +++ b/PWGHF/D2H/Tasks/taskBplusToJpsiKReduced.cxx @@ -164,14 +164,14 @@ DECLARE_SOA_TABLE(HfRedCandBpLites, "AOD", "HFREDCANDBPLITE", //! Table with som hf_cand_bplustojpsik_lite::NSigTofKaBachelor, hf_cand_bplustojpsik_lite::NSigTpcTofKaBachelor, // MC truth - hf_cand_bplus::FlagMcMatchRec, - hf_cand_bplus::FlagMcDecayChanRec, - hf_cand_bplus::OriginMcRec, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::FlagMcDecayChanRec, + hf_cand_mc_flag::OriginMcRec, hf_cand_bplustojpsik_lite::FlagWrongCollision, hf_cand_bplustojpsik_lite::PtGen); // DECLARE_SOA_TABLE(HfRedBpMcCheck, "AOD", "HFREDBPMCCHECK", //! Table with MC decay type check -// hf_cand_2prong::FlagMcMatchRec, +// hf_cand_mc_flag::FlagMcMatchRec, // hf_cand_bplustojpsik_lite::FlagWrongCollision, // hf_cand_bplustojpsik_lite::MJpsi, // hf_cand_bplustojpsik_lite::PtJpsi, diff --git a/PWGHF/D2H/Tasks/taskBsReduced.cxx b/PWGHF/D2H/Tasks/taskBsReduced.cxx index 93b4485228a..703a527ffac 100644 --- a/PWGHF/D2H/Tasks/taskBsReduced.cxx +++ b/PWGHF/D2H/Tasks/taskBsReduced.cxx @@ -155,13 +155,13 @@ DECLARE_SOA_TABLE(HfRedCandBsLites, "AOD", "HFREDCANDBSLITE", //! Table with som hf_cand_bs_lite::NSigTofPiProng1, hf_cand_bs_lite::NSigTpcTofPiProng1, // MC truth - hf_cand_3prong::FlagMcMatchRec, - hf_cand_3prong::OriginMcRec, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcRec, hf_cand_bs_lite::FlagWrongCollision, hf_cand_bs_lite::PtGen); DECLARE_SOA_TABLE(HfRedBsMcCheck, "AOD", "HFREDBSMCCHECK", //! Table with MC decay type check - hf_cand_3prong::FlagMcMatchRec, + hf_cand_mc_flag::FlagMcMatchRec, hf_cand_bs_lite::FlagWrongCollision, hf_cand_bs_lite::MProng0, hf_cand_bs_lite::PtProng0, diff --git a/PWGHF/D2H/Tasks/taskBsToJpsiPhiReduced.cxx b/PWGHF/D2H/Tasks/taskBsToJpsiPhiReduced.cxx index 2ff8dbe84e2..ab44c6f7dbe 100644 --- a/PWGHF/D2H/Tasks/taskBsToJpsiPhiReduced.cxx +++ b/PWGHF/D2H/Tasks/taskBsToJpsiPhiReduced.cxx @@ -189,14 +189,14 @@ DECLARE_SOA_TABLE(HfRedCandBsLites, "AOD", "HFREDCANDBSLITE", //! Table with som hf_cand_bstojpsiphi_lite::NSigTofKaBachelor1, hf_cand_bstojpsiphi_lite::NSigTpcTofKaBachelor1, // MC truth - hf_cand_bs::FlagMcMatchRec, - hf_cand_bs::FlagMcDecayChanRec, - hf_cand_bs::OriginMcRec, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::FlagMcDecayChanRec, + hf_cand_mc_flag::OriginMcRec, hf_cand_bstojpsiphi_lite::FlagWrongCollision, hf_cand_bstojpsiphi_lite::PtGen); // DECLARE_SOA_TABLE(HfRedBsMcCheck, "AOD", "HFREDBPMCCHECK", //! Table with MC decay type check -// hf_cand_2prong::FlagMcMatchRec, +// hf_cand_mc_flag::FlagMcMatchRec, // hf_cand_bstojpsiphi_lite::FlagWrongCollision, // hf_cand_bstojpsiphi_lite::MJpsi, // hf_cand_bstojpsiphi_lite::PtJpsi, diff --git a/PWGHF/D2H/Tasks/taskDplus.cxx b/PWGHF/D2H/Tasks/taskDplus.cxx index 819c5f3891f..fb4102b48a1 100644 --- a/PWGHF/D2H/Tasks/taskDplus.cxx +++ b/PWGHF/D2H/Tasks/taskDplus.cxx @@ -114,12 +114,12 @@ struct HfTaskDplus { Partition selectedDPlusCandidatesWithMl = aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; // Matched MC - Partition recoDPlusCandidates = nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) && aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; - Partition recoDPlusCandidatesWithMl = nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) && aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; + Partition recoDPlusCandidates = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) && aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; + Partition recoDPlusCandidatesWithMl = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) && aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; // MC Bkg - Partition recoBkgCandidates = nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) && aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; - Partition recoBkgCandidatesWithMl = nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) && aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; + Partition recoBkgCandidates = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) && aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; + Partition recoBkgCandidatesWithMl = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) && aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; ConfigurableAxis thnConfigAxisMass{"thnConfigAxisMass", {600, 1.67, 2.27}, "Cand. mass bins"}; ConfigurableAxis thnConfigAxisY{"thnConfigAxisY", {40, -1, 1}, "Cand. rapidity bins"}; diff --git a/PWGHF/D2H/Tasks/taskLbReduced.cxx b/PWGHF/D2H/Tasks/taskLbReduced.cxx index b8ba64cb42a..fe43e8d2c6e 100644 --- a/PWGHF/D2H/Tasks/taskLbReduced.cxx +++ b/PWGHF/D2H/Tasks/taskLbReduced.cxx @@ -150,13 +150,13 @@ DECLARE_SOA_TABLE(HfRedCandLbLites, "AOD", "HFREDCANDLBLITE", //! Table with som hf_cand_lb_lite::NSigTofPiBachelor, hf_cand_lb_lite::NSigTpcTofPiBachelor, // MC truth - hf_cand_3prong::FlagMcMatchRec, - hf_cand_3prong::OriginMcRec, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcRec, hf_cand_lb_lite::FlagWrongCollision, hf_cand_lb_lite::PtGen); DECLARE_SOA_TABLE(HfRedLbMcCheck, "AOD", "HFREDLBMCCHECK", //! Table with MC decay type check - hf_cand_3prong::FlagMcMatchRec, + hf_cand_mc_flag::FlagMcMatchRec, hf_cand_lb_lite::FlagWrongCollision, hf_cand_lb_lite::MLc, hf_cand_lb_lite::PtLc, diff --git a/PWGHF/D2H/Tasks/taskOmegac0ToOmegaPi.cxx b/PWGHF/D2H/Tasks/taskOmegac0ToOmegaPi.cxx index 23cd80e4d00..c2d0ed06dcd 100644 --- a/PWGHF/D2H/Tasks/taskOmegac0ToOmegaPi.cxx +++ b/PWGHF/D2H/Tasks/taskOmegac0ToOmegaPi.cxx @@ -91,8 +91,8 @@ struct HfTaskOmegac0ToOmegaPi { using McCollisionsWithFT0M = soa::Join; Filter filterOmegaCToOmegaPiFlag = (aod::hf_track_index::hfflag & static_cast(BIT(aod::hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaPi))) != static_cast(0); - Filter filterOmegaCMatchedRec = nabs(aod::hf_cand_xic0_omegac0::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToOmegaPi)); - Filter filterOmegaCMatchedGen = nabs(aod::hf_cand_xic0_omegac0::flagMcMatchGen) == static_cast(BIT(aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToOmegaPi)); + Filter filterOmegaCMatchedRec = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToOmegaPi)); + Filter filterOmegaCMatchedGen = nabs(aod::hf_cand_mc_flag::flagMcMatchGen) == static_cast(BIT(aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToOmegaPi)); Preslice candOmegacKFPerCollision = aod::hf_cand_xic0_omegac0::collisionId; Preslice candOmegacKFMlPerCollision = aod::hf_cand_xic0_omegac0::collisionId; diff --git a/PWGHF/D2H/Tasks/taskXic0ToXiPi.cxx b/PWGHF/D2H/Tasks/taskXic0ToXiPi.cxx index 28e461c815c..92e8ff37531 100644 --- a/PWGHF/D2H/Tasks/taskXic0ToXiPi.cxx +++ b/PWGHF/D2H/Tasks/taskXic0ToXiPi.cxx @@ -83,8 +83,8 @@ struct HfTaskXic0ToXiPi { using McCollisionsCentFT0Ms = soa::Join; Filter filterSelectXic0Candidates = aod::hf_sel_toxipi::resultSelections == true; - Filter filterXicMatchedRec = nabs(aod::hf_cand_xic0_omegac0::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_xic0_omegac0::DecayType::XiczeroToXiPi)); - Filter filterXicMatchedGen = nabs(aod::hf_cand_xic0_omegac0::flagMcMatchGen) == static_cast(BIT(aod::hf_cand_xic0_omegac0::DecayType::XiczeroToXiPi)); + Filter filterXicMatchedRec = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_xic0_omegac0::DecayType::XiczeroToXiPi)); + Filter filterXicMatchedGen = nabs(aod::hf_cand_mc_flag::flagMcMatchGen) == static_cast(BIT(aod::hf_cand_xic0_omegac0::DecayType::XiczeroToXiPi)); Preslice candXicPerCollision = aod::hf_cand_xic0_omegac0::collisionId; Preslice candXicKFPerCollision = aod::hf_cand_xic0_omegac0::collisionId; Preslice candXicMlPerCollision = aod::hf_cand_xic0_omegac0::collisionId; diff --git a/PWGHF/DataModel/CandidateReconstructionTables.h b/PWGHF/DataModel/CandidateReconstructionTables.h index a13fb4280ab..bd34cc4817a 100644 --- a/PWGHF/DataModel/CandidateReconstructionTables.h +++ b/PWGHF/DataModel/CandidateReconstructionTables.h @@ -329,13 +329,6 @@ DECLARE_SOA_DYNAMIC_COLUMN(Ct, ct, //! DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterXY, impactParameterXY, //! [](float xVtxP, float yVtxP, float zVtxP, float xVtxS, float yVtxS, float zVtxS, float px, float py, float pz) -> float { return RecoDecay::impParXY(std::array{xVtxP, yVtxP, zVtxP}, std::array{xVtxS, yVtxS, zVtxS}, std::array{px, py, pz}); }); DECLARE_SOA_COLUMN(KfTopolChi2OverNdf, kfTopolChi2OverNdf, float); //! chi2overndf of the KFParticle topological constraint -// B-hadron mother information -DECLARE_SOA_COLUMN(PtBhadMotherPart, ptBhadMotherPart, float); //! pt of the first B-hadron mother particle (only in case of non-prompt) -DECLARE_SOA_COLUMN(PdgBhadMotherPart, pdgBhadMotherPart, int); //! pdg of the first B-hadron mother particle (only in case of non-prompt) -DECLARE_SOA_COLUMN(IdxBhadMotherPart, idxBhadMotherPart, int); //! index of the first B-hadron mother particle (only in case of non-prompt) -// Kink topology and material interaction mc flags -DECLARE_SOA_COLUMN(NTracksDecayed, nTracksDecayed, int8_t); //! number of tracks matched with kinked decay topology -DECLARE_SOA_COLUMN(NInteractionsWithMaterial, nInteractionsWithMaterial, int8_t); //! number of tracks matched after interaction with material // method of secondary-vertex reconstruction enum VertexerType { DCAFitter = 0, @@ -365,13 +358,6 @@ DECLARE_SOA_DYNAMIC_COLUMN(MaxNormalisedDeltaIP, maxNormalisedDeltaIP, //! [](float xVtxP, float yVtxP, float xVtxS, float yVtxS, float errDlxy, float pxM, float pyM, float ip0, float errIp0, float ip1, float errIp1, float px0, float py0, float px1, float py1) -> float { return RecoDecay::maxNormalisedDeltaIP(std::array{xVtxP, yVtxP}, std::array{xVtxS, yVtxS}, errDlxy, std::array{pxM, pyM}, std::array{ip0, ip1}, std::array{errIp0, errIp1}, std::array{std::array{px0, py0}, std::array{px1, py1}}); }); DECLARE_SOA_DYNAMIC_COLUMN(CtXY, ctXY, //! [](float px0, float py0, float pz0, float px1, float py1, float pz1, float xVtxP, float yVtxP, float xVtxS, float yVtxS, const std::array& m) -> float { return RecoDecay::ctXY(std::array{xVtxP, yVtxP}, std::array{xVtxS, yVtxS}, std::array{std::array{px0, py0, pz0}, std::array{px1, py1, pz1}}, m); }); -// MC matching result: -DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); //! reconstruction level -DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); //! generator level -DECLARE_SOA_COLUMN(OriginMcRec, originMcRec, int8_t); //! particle origin, reconstruction level -DECLARE_SOA_COLUMN(OriginMcGen, originMcGen, int8_t); //! particle origin, generator level -DECLARE_SOA_COLUMN(FlagMcDecayChanRec, flagMcDecayChanRec, int8_t); //! resonant decay channel flag, reconstruction level -DECLARE_SOA_COLUMN(FlagMcDecayChanGen, flagMcDecayChanGen, int8_t); //! resonant decay channel flag, reconstruction level // KF related properties DECLARE_SOA_COLUMN(KfGeoMassD0, kfGeoMassD0, float); //! mass of the D0 candidate from the KFParticle geometric fit @@ -379,6 +365,26 @@ DECLARE_SOA_COLUMN(KfGeoMassD0bar, kfGeoMassD0bar, float); //! mass of the D0bar } // namespace hf_cand_2prong +// MC +namespace hf_cand_mc_flag +{ +DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); //! main decay channel, reconstruction level +DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); //! main decay channel, generator level +DECLARE_SOA_COLUMN(FlagMcDecayChanRec, flagMcDecayChanRec, int8_t); //! resonant decay channel, reconstruction level +DECLARE_SOA_COLUMN(FlagMcDecayChanGen, flagMcDecayChanGen, int8_t); //! resonant decay channel, generator level +DECLARE_SOA_COLUMN(OriginMcRec, originMcRec, int8_t); //! particle origin, reconstruction level +DECLARE_SOA_COLUMN(OriginMcGen, originMcGen, int8_t); //! particle origin, generator level +DECLARE_SOA_COLUMN(IsCandidateSwapped, isCandidateSwapped, int8_t); //! swapping of the prongs order +DECLARE_SOA_COLUMN(DebugMcRec, debugMcRec, int8_t); //! debug flag for mis-association reconstruction level +// B-hadron mother information +DECLARE_SOA_COLUMN(PtBhadMotherPart, ptBhadMotherPart, float); //! pt of the first B-hadron mother particle (only in case of non-prompt) +DECLARE_SOA_COLUMN(PdgBhadMotherPart, pdgBhadMotherPart, int); //! pdg of the first B-hadron mother particle (only in case of non-prompt) +DECLARE_SOA_COLUMN(IdxBhadMotherPart, idxBhadMotherPart, int); //! index of the first B-hadron mother particle (only in case of non-prompt) +// Kink topology and material interaction MC flags +DECLARE_SOA_COLUMN(NTracksDecayed, nTracksDecayed, int8_t); //! number of tracks matched with kinked decay topology +DECLARE_SOA_COLUMN(NInteractionsWithMaterial, nInteractionsWithMaterial, int8_t); //! number of tracks matched after interaction with material +} // namespace hf_cand_mc_flag + // general columns #define HFCAND_COLUMNS \ hf_cand::CollisionId, \ @@ -463,20 +469,20 @@ DECLARE_SOA_TABLE(HfCand2ProngKF, "AOD", "HFCAND2PKF", // table with results of reconstruction level MC matching DECLARE_SOA_TABLE(HfCand2ProngMcRec, "AOD", "HFCAND2PMCREC", //! - hf_cand_2prong::FlagMcMatchRec, - hf_cand_2prong::OriginMcRec, - hf_cand_2prong::FlagMcDecayChanRec, - hf_cand::PtBhadMotherPart, - hf_cand::PdgBhadMotherPart, - hf_cand::NTracksDecayed, - hf_cand::NInteractionsWithMaterial); + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcRec, + hf_cand_mc_flag::FlagMcDecayChanRec, + hf_cand_mc_flag::PtBhadMotherPart, + hf_cand_mc_flag::PdgBhadMotherPart, + hf_cand_mc_flag::NTracksDecayed, + hf_cand_mc_flag::NInteractionsWithMaterial); // table with results of generator level MC matching DECLARE_SOA_TABLE(HfCand2ProngMcGen, "AOD", "HFCAND2PMCGEN", //! - hf_cand_2prong::FlagMcMatchGen, - hf_cand_2prong::OriginMcGen, - hf_cand_2prong::FlagMcDecayChanGen, - hf_cand::IdxBhadMotherPart); + hf_cand_mc_flag::FlagMcMatchGen, + hf_cand_mc_flag::OriginMcGen, + hf_cand_mc_flag::FlagMcDecayChanGen, + hf_cand_mc_flag::IdxBhadMotherPart); // cascade decay candidate table @@ -497,13 +503,9 @@ DECLARE_SOA_DYNAMIC_COLUMN(CtV0, ctV0, //! c*t of the V0 [](float xVtxP, float yVtxP, float zVtxP, float xVtxS, float yVtxS, float zVtxS, float px, float py, float pz, double m) -> float { return RecoDecay::ct(std::array{px, py, pz}, RecoDecay::distance(std::array{xVtxP, yVtxP, zVtxP}, std::array{xVtxS, yVtxS, zVtxS}), m); }); DECLARE_SOA_DYNAMIC_COLUMN(DecayLengthV0, decayLengthV0, //! [](float xVtxP, float yVtxP, float zVtxP, float xVtxS, float yVtxS, float zVtxS) -> float { return RecoDecay::distance(std::array{xVtxP, yVtxP, zVtxP}, std::array{xVtxS, yVtxS, zVtxS}); }); -DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); //! reconstruction level -DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); //! generator level -DECLARE_SOA_COLUMN(OriginMcRec, originMcRec, int8_t); //! particle origin, reconstruction level -DECLARE_SOA_COLUMN(OriginMcGen, originMcGen, int8_t); //! particle origin, generator level -DECLARE_SOA_COLUMN(V0X, v0X, float); //! X position of V0 decay -DECLARE_SOA_COLUMN(V0Y, v0Y, float); //! Y position of V0 decay -DECLARE_SOA_COLUMN(V0Z, v0Z, float); //! Z position of V0 decay +DECLARE_SOA_COLUMN(V0X, v0X, float); //! X position of V0 decay +DECLARE_SOA_COLUMN(V0Y, v0Y, float); //! Y position of V0 decay +DECLARE_SOA_COLUMN(V0Z, v0Z, float); //! Z position of V0 decay } // namespace hf_cand_casc DECLARE_SOA_TABLE(HfCandCascBase, "AOD", "HFCANDCASCBASE", //! @@ -569,30 +571,21 @@ using HfCandCascade = HfCandCascExt; // table with results of reconstruction level MC matching for Cascade DECLARE_SOA_TABLE(HfCandCascadeMcRec, "AOD", "HFCANDCASCMCREC", //! - hf_cand_casc::FlagMcMatchRec, - hf_cand_casc::OriginMcRec, - hf_cand::PtBhadMotherPart, - hf_cand::PdgBhadMotherPart); + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcRec, + hf_cand_mc_flag::PtBhadMotherPart, + hf_cand_mc_flag::PdgBhadMotherPart); // table with results of generator level MC matching DECLARE_SOA_TABLE(HfCandCascadeMcGen, "AOD", "HFCANDCASCMCGEN", //! - hf_cand_casc::FlagMcMatchGen, - hf_cand_casc::OriginMcGen, - hf_cand::IdxBhadMotherPart); + hf_cand_mc_flag::FlagMcMatchGen, + hf_cand_mc_flag::OriginMcGen, + hf_cand_mc_flag::IdxBhadMotherPart); // specific BPlus candidate properties namespace hf_cand_bplus { -DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfCand2Prong, "_0"); // D0 index -// MC matching result: -DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); // main decay channel, reconstruction level -DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); // main decay channel, generator level -DECLARE_SOA_COLUMN(FlagMcDecayChanRec, flagMcDecayChanRec, int8_t); // resonant decay channel, reconstruction level -DECLARE_SOA_COLUMN(FlagMcDecayChanGen, flagMcDecayChanGen, int8_t); // resonant decay channel, generator level -DECLARE_SOA_COLUMN(OriginMcRec, originMcRec, int8_t); // particle origin, reconstruction level -DECLARE_SOA_COLUMN(OriginMcGen, originMcGen, int8_t); // particle origin, generator level -DECLARE_SOA_COLUMN(FlagWrongCollision, flagWrongCollision, int8_t); // reconstruction level -DECLARE_SOA_COLUMN(DebugMcRec, debugMcRec, int8_t); // debug flag for mis-association reconstruction level +DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfCand2Prong, "_0"); // D0 index DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterProduct, impactParameterProduct, // Impact parameter product for B+ -> J/Psi K [](float px0, float py0, float pz0, float px1, float py1, float pz1, float xVtxP, float yVtxP, float zVtxP, float xVtxS, float yVtxS, float zVtxS, float impParK) -> float { return impParK * RecoDecay::impParXY(std::array{xVtxP, yVtxP, zVtxP}, std::array{xVtxS, yVtxS, zVtxS}, RecoDecay::pVec(std::array{px0, py0, pz0}, std::array{px1, py1, pz1})); }); DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterProductJpsi, impactParameterProductJpsi, // J/Psi impact parameter for B+ -> J/Psi K @@ -655,15 +648,15 @@ using HfCandBplus = soa::Join; // table with results of reconstruction level MC matching DECLARE_SOA_TABLE(HfCandBplusMcRec, "AOD", "HFCANDBPMCREC", - hf_cand_bplus::FlagMcMatchRec, - hf_cand_bplus::FlagMcDecayChanRec, - hf_cand_bplus::OriginMcRec); + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::FlagMcDecayChanRec, + hf_cand_mc_flag::OriginMcRec); // table with results of generator level MC matching DECLARE_SOA_TABLE(HfCandBplusMcGen, "AOD", "HFCANDBPMCGEN", - hf_cand_bplus::FlagMcMatchGen, - hf_cand_bplus::FlagMcDecayChanGen, - hf_cand_bplus::OriginMcGen); + hf_cand_mc_flag::FlagMcMatchGen, + hf_cand_mc_flag::FlagMcDecayChanGen, + hf_cand_mc_flag::OriginMcGen); // specific 3-prong decay properties namespace hf_cand_3prong @@ -686,14 +679,6 @@ DECLARE_SOA_DYNAMIC_COLUMN(CtXY, ctXY, //! [](float px0, float py0, float pz0, float px1, float py1, float pz1, float px2, float py2, float pz2, float xVtxP, float yVtxP, float xVtxS, float yVtxS, const std::array& m) -> float { return RecoDecay::ctXY(std::array{xVtxP, yVtxP}, std::array{xVtxS, yVtxS}, std::array{std::array{px0, py0, pz0}, std::array{px1, py1, pz1}, std::array{px2, py2, pz2}}, m); }); -// MC matching result: -DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); //! reconstruction level -DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); //! generator level -DECLARE_SOA_COLUMN(OriginMcRec, originMcRec, int8_t); //! particle origin, reconstruction level -DECLARE_SOA_COLUMN(OriginMcGen, originMcGen, int8_t); //! particle origin, generator level -DECLARE_SOA_COLUMN(IsCandidateSwapped, isCandidateSwapped, int8_t); //! swapping of the prongs order -DECLARE_SOA_COLUMN(FlagMcDecayChanRec, flagMcDecayChanRec, int8_t); //! resonant decay channel flag, reconstruction level -DECLARE_SOA_COLUMN(FlagMcDecayChanGen, flagMcDecayChanGen, int8_t); //! resonant decay channel flag, generator level // Ds± → K± K∓ π± or D± → K± K∓ π± @@ -870,21 +855,21 @@ DECLARE_SOA_TABLE(HfCand3ProngKF, "AOD", "HFCAND3PKF", // table with results of reconstruction level MC matching DECLARE_SOA_TABLE(HfCand3ProngMcRec, "AOD", "HFCAND3PMCREC", //! - hf_cand_3prong::FlagMcMatchRec, - hf_cand_3prong::OriginMcRec, - hf_cand_3prong::IsCandidateSwapped, - hf_cand_3prong::FlagMcDecayChanRec, - hf_cand::PtBhadMotherPart, - hf_cand::PdgBhadMotherPart, - hf_cand::NTracksDecayed, - hf_cand::NInteractionsWithMaterial); + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcRec, + hf_cand_mc_flag::IsCandidateSwapped, + hf_cand_mc_flag::FlagMcDecayChanRec, + hf_cand_mc_flag::PtBhadMotherPart, + hf_cand_mc_flag::PdgBhadMotherPart, + hf_cand_mc_flag::NTracksDecayed, + hf_cand_mc_flag::NInteractionsWithMaterial); // table with results of generator level MC matching DECLARE_SOA_TABLE(HfCand3ProngMcGen, "AOD", "HFCAND3PMCGEN", //! - hf_cand_3prong::FlagMcMatchGen, - hf_cand_3prong::OriginMcGen, - hf_cand_3prong::FlagMcDecayChanGen, - hf_cand::IdxBhadMotherPart); + hf_cand_mc_flag::FlagMcMatchGen, + hf_cand_mc_flag::OriginMcGen, + hf_cand_mc_flag::FlagMcDecayChanGen, + hf_cand_mc_flag::IdxBhadMotherPart); // declare dedicated BPlus -> J/Psi K decay candidate table // convention: prongs 0 and 1 should be J/Psi decay products @@ -945,14 +930,6 @@ enum ConstructMethod { DcaFitter = 0, namespace hf_cand_x { DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfCand2Prong, "_0"); // Jpsi index -// MC matching result: -DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); // reconstruction level -DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); // generator level -DECLARE_SOA_COLUMN(OriginMcRec, originMcRec, int8_t); // particle origin, reconstruction level -DECLARE_SOA_COLUMN(OriginMcGen, originMcGen, int8_t); // particle origin, generator level -DECLARE_SOA_COLUMN(FlagMcDecayChanRec, flagMcDecayChanRec, int8_t); // resonant decay channel flag, reconstruction level -DECLARE_SOA_COLUMN(FlagMcDecayChanGen, flagMcDecayChanGen, int8_t); // resonant decay channel flag, generator level - } // namespace hf_cand_x // declare dedicated X candidate table @@ -999,26 +976,20 @@ using HfCandX = HfCandXExt; // table with results of reconstruction level MC matching DECLARE_SOA_TABLE(HfCandXMcRec, "AOD", "HFCANDXMCREC", //! - hf_cand_x::FlagMcMatchRec, - hf_cand_x::OriginMcRec, - hf_cand_x::FlagMcDecayChanRec); + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcRec, + hf_cand_mc_flag::FlagMcDecayChanRec); // table with results of generator level MC matching DECLARE_SOA_TABLE(HfCandXMcGen, "AOD", "HFCANDXMCGEN", //! - hf_cand_x::FlagMcMatchGen, - hf_cand_x::OriginMcGen, - hf_cand_x::FlagMcDecayChanGen); + hf_cand_mc_flag::FlagMcMatchGen, + hf_cand_mc_flag::OriginMcGen, + hf_cand_mc_flag::FlagMcDecayChanGen); // specific Xicc candidate properties namespace hf_cand_xicc { DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfCand3Prong, "_0"); // Xic index -// MC matching result: -DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); // reconstruction level -DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); // generator level -DECLARE_SOA_COLUMN(OriginMcRec, originMcRec, int8_t); // particle origin, reconstruction level -DECLARE_SOA_COLUMN(OriginMcGen, originMcGen, int8_t); // particle origin, generator level -DECLARE_SOA_COLUMN(DebugMcRec, debugMcRec, int8_t); // debug flag for mis-association reconstruction level } // namespace hf_cand_xicc // declare dedicated Xicc candidate table @@ -1061,14 +1032,14 @@ using HfCandXicc = HfCandXiccExt; // table with results of reconstruction level MC matching DECLARE_SOA_TABLE(HfCandXiccMcRec, "AOD", "HFCANDXICCMCREC", //! - hf_cand_xicc::FlagMcMatchRec, - hf_cand_xicc::OriginMcRec, - hf_cand_xicc::DebugMcRec); + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcRec, + hf_cand_mc_flag::DebugMcRec); // table with results of generator level MC matching DECLARE_SOA_TABLE(HfCandXiccMcGen, "AOD", "HFCANDXICCMCGEN", //! - hf_cand_xicc::FlagMcMatchGen, - hf_cand_xicc::OriginMcGen); + hf_cand_mc_flag::FlagMcMatchGen, + hf_cand_mc_flag::OriginMcGen); // specific Omegac and Xic to Xi Pi candidate properties namespace hf_cand_xic0_omegac0 @@ -1312,16 +1283,10 @@ DECLARE_SOA_COLUMN(Xic0XError, xic0XError, float); DECLARE_SOA_COLUMN(Xic0YError, xic0YError, float); DECLARE_SOA_COLUMN(Xic0ZError, xic0ZError, float); -// MC matching result: -DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); // reconstruction level -DECLARE_SOA_COLUMN(DebugMcRec, debugMcRec, int8_t); // debug flag for mis-association reconstruction level -DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); // generator level DECLARE_SOA_COLUMN(CollisionMatched, collisionMatched, bool); DECLARE_SOA_COLUMN(DebugGenCharmBar, debugGenCharmBar, int8_t); DECLARE_SOA_COLUMN(DebugGenCasc, debugGenCasc, int8_t); DECLARE_SOA_COLUMN(DebugGenLambda, debugGenLambda, int8_t); -DECLARE_SOA_COLUMN(OriginMcRec, originMcRec, int8_t); -DECLARE_SOA_COLUMN(OriginMcGen, originMcGen, int8_t); DECLARE_SOA_COLUMN(PtCharmBaryonGen, ptCharmBaryonGen, float); DECLARE_SOA_COLUMN(RapidityCharmBaryonGen, rapidityCharmBaryonGen, float); @@ -1403,8 +1368,7 @@ DECLARE_SOA_TABLE(HfCandToOmegaPi, "AOD", "HFCANDTOOMEGAPI", hf_cand_xic0_omegac0::DcaXYToPvV0Dau0, hf_cand_xic0_omegac0::DcaXYToPvV0Dau1, hf_cand_xic0_omegac0::DcaXYToPvCascDau, hf_cand_xic0_omegac0::DcaZToPvV0Dau0, hf_cand_xic0_omegac0::DcaZToPvV0Dau1, hf_cand_xic0_omegac0::DcaZToPvCascDau, hf_cand_xic0_omegac0::DcaCascDau, hf_cand_xic0_omegac0::DcaV0Dau, hf_cand_xic0_omegac0::DcaCharmBaryonDau, - hf_cand_xic0_omegac0::DecLenCharmBaryon, hf_cand_xic0_omegac0::DecLenCascade, hf_cand_xic0_omegac0::DecLenV0, hf_cand_xic0_omegac0::ErrorDecayLengthCharmBaryon, hf_cand_xic0_omegac0::ErrorDecayLengthXYCharmBaryon, hf_track_index::HFflag, - o2::soa::Marker<1>); + hf_cand_xic0_omegac0::DecLenCharmBaryon, hf_cand_xic0_omegac0::DecLenCascade, hf_cand_xic0_omegac0::DecLenV0, hf_cand_xic0_omegac0::ErrorDecayLengthCharmBaryon, hf_cand_xic0_omegac0::ErrorDecayLengthXYCharmBaryon, hf_track_index::HFflag); DECLARE_SOA_TABLE(HfCandToOmegaK, "AOD", "HFCANDTOOMEGAK", o2::soa::Index<>, @@ -1432,8 +1396,7 @@ DECLARE_SOA_TABLE(HfCandToOmegaK, "AOD", "HFCANDTOOMEGAK", hf_cand_xic0_omegac0::DcaXYToPvV0Dau0, hf_cand_xic0_omegac0::DcaXYToPvV0Dau1, hf_cand_xic0_omegac0::DcaXYToPvCascDau, hf_cand_xic0_omegac0::DcaZToPvV0Dau0, hf_cand_xic0_omegac0::DcaZToPvV0Dau1, hf_cand_xic0_omegac0::DcaZToPvCascDau, hf_cand_xic0_omegac0::DcaCascDau, hf_cand_xic0_omegac0::DcaV0Dau, hf_cand_xic0_omegac0::DcaCharmBaryonDau, - hf_cand_xic0_omegac0::DecLenCharmBaryon, hf_cand_xic0_omegac0::DecLenCascade, hf_cand_xic0_omegac0::DecLenV0, hf_cand_xic0_omegac0::ErrorDecayLengthCharmBaryon, hf_cand_xic0_omegac0::ErrorDecayLengthXYCharmBaryon, - o2::soa::Marker<2>); + hf_cand_xic0_omegac0::DecLenCharmBaryon, hf_cand_xic0_omegac0::DecLenCascade, hf_cand_xic0_omegac0::DecLenV0, hf_cand_xic0_omegac0::ErrorDecayLengthCharmBaryon, hf_cand_xic0_omegac0::ErrorDecayLengthXYCharmBaryon); // table with results of KFParticle DECLARE_SOA_TABLE(HfOmegacKf, "AOD", "HFOMEGACKF", //! @@ -1537,51 +1500,47 @@ DECLARE_SOA_TABLE(HfCandToXiPiKfQa, "AOD", "HFCANDTOXIPIKFQA", // table with results of reconstruction level MC matching DECLARE_SOA_TABLE(HfXicToXiPiMCRec, "AOD", "HFXICXIPIMCREC", //! - hf_cand_xic0_omegac0::FlagMcMatchRec, - hf_cand_xic0_omegac0::DebugMcRec, - hf_cand_xic0_omegac0::OriginMcRec, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::DebugMcRec, + hf_cand_mc_flag::OriginMcRec, hf_cand_xic0_omegac0::CollisionMatched, - hf_cand::PtBhadMotherPart, - hf_cand::PdgBhadMotherPart, - o2::soa::Marker<1>); + hf_cand_mc_flag::PtBhadMotherPart, + hf_cand_mc_flag::PdgBhadMotherPart); DECLARE_SOA_TABLE(HfOmegacToXiPiMCRec, "AOD", "HFOMCXIPIMCREC", //! - hf_cand_xic0_omegac0::FlagMcMatchRec, - hf_cand_xic0_omegac0::DebugMcRec, - hf_cand_xic0_omegac0::OriginMcRec, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::DebugMcRec, + hf_cand_mc_flag::OriginMcRec, hf_cand_xic0_omegac0::CollisionMatched, - hf_cand::PtBhadMotherPart, - hf_cand::PdgBhadMotherPart, - o2::soa::Marker<2>); + hf_cand_mc_flag::PtBhadMotherPart, + hf_cand_mc_flag::PdgBhadMotherPart); DECLARE_SOA_TABLE(HfToOmegaPiMCRec, "AOD", "HFTOOMEPIMCREC", //! - hf_cand_xic0_omegac0::FlagMcMatchRec, - hf_cand_xic0_omegac0::DebugMcRec, - hf_cand_xic0_omegac0::OriginMcRec, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::DebugMcRec, + hf_cand_mc_flag::OriginMcRec, hf_cand_xic0_omegac0::CollisionMatched, - hf_cand::PtBhadMotherPart, - hf_cand::PdgBhadMotherPart, - o2::soa::Marker<3>); + hf_cand_mc_flag::PtBhadMotherPart, + hf_cand_mc_flag::PdgBhadMotherPart); DECLARE_SOA_TABLE(HfToOmegaKMCRec, "AOD", "HFTOOMEKMCREC", //! - hf_cand_xic0_omegac0::FlagMcMatchRec, - hf_cand_xic0_omegac0::DebugMcRec, - hf_cand_xic0_omegac0::OriginMcRec, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::DebugMcRec, + hf_cand_mc_flag::OriginMcRec, hf_cand_xic0_omegac0::CollisionMatched, - hf_cand::PtBhadMotherPart, - hf_cand::PdgBhadMotherPart, - o2::soa::Marker<4>); + hf_cand_mc_flag::PtBhadMotherPart, + hf_cand_mc_flag::PdgBhadMotherPart); // table with results of generator level MC matching DECLARE_SOA_TABLE(HfXicToXiPiMCGen, "AOD", "HFXICXIPIMCGEN", //! - hf_cand_xic0_omegac0::FlagMcMatchGen, hf_cand_xic0_omegac0::DebugGenCharmBar, hf_cand_xic0_omegac0::DebugGenCasc, hf_cand_xic0_omegac0::DebugGenLambda, - hf_cand_xic0_omegac0::PtCharmBaryonGen, hf_cand_xic0_omegac0::RapidityCharmBaryonGen, hf_cand_xic0_omegac0::OriginMcGen, hf_cand::IdxBhadMotherPart, o2::soa::Marker<1>); + hf_cand_mc_flag::FlagMcMatchGen, hf_cand_xic0_omegac0::DebugGenCharmBar, hf_cand_xic0_omegac0::DebugGenCasc, hf_cand_xic0_omegac0::DebugGenLambda, + hf_cand_xic0_omegac0::PtCharmBaryonGen, hf_cand_xic0_omegac0::RapidityCharmBaryonGen, hf_cand_mc_flag::OriginMcGen, hf_cand_mc_flag::IdxBhadMotherPart); DECLARE_SOA_TABLE(HfOmegacToXiPiMCGen, "AOD", "HFOMECXIPIMCGEN", //! - hf_cand_xic0_omegac0::FlagMcMatchGen, hf_cand_xic0_omegac0::DebugGenCharmBar, hf_cand_xic0_omegac0::DebugGenCasc, hf_cand_xic0_omegac0::DebugGenLambda, - hf_cand_xic0_omegac0::PtCharmBaryonGen, hf_cand_xic0_omegac0::RapidityCharmBaryonGen, hf_cand_xic0_omegac0::OriginMcGen, hf_cand::IdxBhadMotherPart, o2::soa::Marker<2>); + hf_cand_mc_flag::FlagMcMatchGen, hf_cand_xic0_omegac0::DebugGenCharmBar, hf_cand_xic0_omegac0::DebugGenCasc, hf_cand_xic0_omegac0::DebugGenLambda, + hf_cand_xic0_omegac0::PtCharmBaryonGen, hf_cand_xic0_omegac0::RapidityCharmBaryonGen, hf_cand_mc_flag::OriginMcGen, hf_cand_mc_flag::IdxBhadMotherPart); DECLARE_SOA_TABLE(HfToOmegaPiMCGen, "AOD", "HFTOOMEPIMCGEN", //! - hf_cand_xic0_omegac0::FlagMcMatchGen, hf_cand_xic0_omegac0::DebugGenCharmBar, hf_cand_xic0_omegac0::DebugGenCasc, hf_cand_xic0_omegac0::DebugGenLambda, - hf_cand_xic0_omegac0::PtCharmBaryonGen, hf_cand_xic0_omegac0::RapidityCharmBaryonGen, hf_cand_xic0_omegac0::OriginMcGen, hf_cand::IdxBhadMotherPart, o2::soa::Marker<3>); + hf_cand_mc_flag::FlagMcMatchGen, hf_cand_xic0_omegac0::DebugGenCharmBar, hf_cand_xic0_omegac0::DebugGenCasc, hf_cand_xic0_omegac0::DebugGenLambda, + hf_cand_xic0_omegac0::PtCharmBaryonGen, hf_cand_xic0_omegac0::RapidityCharmBaryonGen, hf_cand_mc_flag::OriginMcGen, hf_cand_mc_flag::IdxBhadMotherPart); DECLARE_SOA_TABLE(HfToOmegaKMCGen, "AOD", "HFTOOMEKMCGEN", //! - hf_cand_xic0_omegac0::FlagMcMatchGen, hf_cand_xic0_omegac0::DebugGenCharmBar, hf_cand_xic0_omegac0::DebugGenCasc, hf_cand_xic0_omegac0::DebugGenLambda, - hf_cand_xic0_omegac0::PtCharmBaryonGen, hf_cand_xic0_omegac0::RapidityCharmBaryonGen, hf_cand_xic0_omegac0::OriginMcGen, hf_cand::IdxBhadMotherPart, o2::soa::Marker<4>); + hf_cand_mc_flag::FlagMcMatchGen, hf_cand_xic0_omegac0::DebugGenCharmBar, hf_cand_xic0_omegac0::DebugGenCasc, hf_cand_xic0_omegac0::DebugGenLambda, + hf_cand_xic0_omegac0::PtCharmBaryonGen, hf_cand_xic0_omegac0::RapidityCharmBaryonGen, hf_cand_mc_flag::OriginMcGen, hf_cand_mc_flag::IdxBhadMotherPart); // specific Xic to Xi Pi Pi candidate properties namespace hf_cand_xic_to_xi_pi_pi @@ -1646,11 +1605,7 @@ DECLARE_SOA_COLUMN(NSigTofPiFromXicPlus1, nSigTofPiFromXicPlus1, float); DECLARE_SOA_COLUMN(NSigTofBachelorPi, nSigTofBachelorPi, float); DECLARE_SOA_COLUMN(NSigTofPiFromLambda, nSigTofPiFromLambda, float); DECLARE_SOA_COLUMN(NSigTofPrFromLambda, nSigTofPrFromLambda, float); -// MC matching result: -DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); // reconstruction level -DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); // generator level -DECLARE_SOA_COLUMN(OriginMcRec, originMcRec, int8_t); -DECLARE_SOA_COLUMN(OriginMcGen, originMcGen, int8_t); +// MC DECLARE_SOA_COLUMN(DecayLengthMcGen, decayLengthMcGen, float); // Residuals and pulls DECLARE_SOA_COLUMN(PtResidual, ptResidual, float); @@ -1748,19 +1703,19 @@ DECLARE_SOA_TABLE(HfCandXicKF, "AOD", "HFCANDXICKF", // table with results of reconstruction level MC matching DECLARE_SOA_TABLE(HfCandXicMcRec, "AOD", "HFCANDXICMCREC", - hf_cand_xic_to_xi_pi_pi::FlagMcMatchRec, - hf_cand_xic_to_xi_pi_pi::OriginMcRec); + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcRec); // table with results of generator level MC matching DECLARE_SOA_TABLE(HfCandXicMcGen, "AOD", "HFCANDXICMCGEN", - hf_cand_xic_to_xi_pi_pi::FlagMcMatchGen, - hf_cand_xic_to_xi_pi_pi::OriginMcGen, - hf_cand::PdgBhadMotherPart, + hf_cand_mc_flag::FlagMcMatchGen, + hf_cand_mc_flag::OriginMcGen, + hf_cand_mc_flag::PdgBhadMotherPart, hf_cand_xic_to_xi_pi_pi::DecayLengthMcGen); // table with residuals and pulls of PV DECLARE_SOA_TABLE(HfCandXicResid, "AOD", "HFCANDXICRESID", - hf_cand_xic_to_xi_pi_pi::OriginMcGen, + hf_cand_mc_flag::OriginMcGen, hf_cand_xic_to_xi_pi_pi::PResidual, hf_cand_xic_to_xi_pi_pi::PtResidual, hf_cand_xic_to_xi_pi_pi::XPvResidual, @@ -1781,14 +1736,7 @@ namespace hf_cand_chic { DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfCand2Prong, "_0"); // Jpsi index DECLARE_SOA_INDEX_COLUMN_FULL(Prong1, prong1, int, ECALs, "_1"); -// MC matching result: -DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); // reconstruction level -DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); // generator level -DECLARE_SOA_COLUMN(OriginMcRec, originMcRec, int8_t); // particle origin, reconstruction level -DECLARE_SOA_COLUMN(OriginMcGen, originMcGen, int8_t); // particle origin, generator level -DECLARE_SOA_COLUMN(FlagMcDecayChanRec, flagMcDecayChanRec, int8_t); // resonant decay channel flag, reconstruction level -DECLARE_SOA_COLUMN(FlagMcDecayChanGen, flagMcDecayChanGen, int8_t); // resonant decay channel flag, generator level -DECLARE_SOA_COLUMN(JpsiToMuMuMass, jpsiToMuMuMass, float); // Jpsi mass +DECLARE_SOA_COLUMN(JpsiToMuMuMass, jpsiToMuMuMass, float); // Jpsi mass } // namespace hf_cand_chic // declare dedicated chi_c candidate table @@ -1834,29 +1782,20 @@ using HfCandChic = HfCandChicExt; // table with results of reconstruction level MC matching DECLARE_SOA_TABLE(HfCandChicMcRec, "AOD", "HFCANDCHICMCREC", //! - hf_cand_chic::FlagMcMatchRec, - hf_cand_chic::OriginMcRec, - hf_cand_chic::FlagMcDecayChanRec); + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcRec, + hf_cand_mc_flag::FlagMcDecayChanRec); // table with results of generator level MC matching DECLARE_SOA_TABLE(HfCandChicMcGen, "AOD", "HFCANDCHICMCGEN", //! - hf_cand_chic::FlagMcMatchGen, - hf_cand_chic::OriginMcGen, - hf_cand_chic::FlagMcDecayChanGen); + hf_cand_mc_flag::FlagMcMatchGen, + hf_cand_mc_flag::OriginMcGen, + hf_cand_mc_flag::FlagMcDecayChanGen); // specific Lb candidate properties namespace hf_cand_lb { DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfCand3Prong, "_0"); // Lb index -// MC matching result: -DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); // main decay channel, reconstruction level -DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); // main decay channel, generator level -DECLARE_SOA_COLUMN(FlagMcDecayChanRec, flagMcDecayChanRec, int8_t); // resonant decay channel, reconstruction level -DECLARE_SOA_COLUMN(FlagMcDecayChanGen, flagMcDecayChanGen, int8_t); // resonant decay channel, generator level -DECLARE_SOA_COLUMN(OriginMcRec, originMcRec, int8_t); // particle origin, reconstruction level -DECLARE_SOA_COLUMN(OriginMcGen, originMcGen, int8_t); // particle origin, generator level -DECLARE_SOA_COLUMN(FlagWrongCollision, flagWrongCollision, int8_t); // reconstruction level -DECLARE_SOA_COLUMN(DebugMcRec, debugMcRec, int8_t); // debug flag for mis-association reconstruction level enum DecayTypeMc : uint8_t { LbToLcPiToPKPiPi = 0, LbToLcKToPKPiK, @@ -1907,30 +1846,21 @@ using HfCandLb = soa::Join; // table with results of reconstruction level MC matching DECLARE_SOA_TABLE(HfCandLbMcRec, "AOD", "HFCANDLBMCREC", //! - hf_cand_lb::FlagMcMatchRec, - hf_cand_lb::FlagMcDecayChanRec, - hf_cand_lb::OriginMcRec, - hf_cand_lb::DebugMcRec); + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::FlagMcDecayChanRec, + hf_cand_mc_flag::OriginMcRec, + hf_cand_mc_flag::DebugMcRec); // table with results of generator level MC matching DECLARE_SOA_TABLE(HfCandLbMcGen, "AOD", "HFCANDLBMCGEN", //! - hf_cand_lb::FlagMcMatchGen, - hf_cand_lb::FlagMcDecayChanGen, - hf_cand_lb::OriginMcGen); + hf_cand_mc_flag::FlagMcMatchGen, + hf_cand_mc_flag::FlagMcDecayChanGen, + hf_cand_mc_flag::OriginMcGen); // specific B0 candidate properties namespace hf_cand_b0 { DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfCand3Prong, "_0"); // D index -// MC matching result: -DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); // main decay channel, reconstruction level -DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); // main decay channel, generator level -DECLARE_SOA_COLUMN(FlagMcDecayChanRec, flagMcDecayChanRec, int8_t); // resonant decay channel, reconstruction level -DECLARE_SOA_COLUMN(FlagMcDecayChanGen, flagMcDecayChanGen, int8_t); // resonant decay channel, generator level -DECLARE_SOA_COLUMN(OriginMcRec, originMcRec, int8_t); // particle origin, reconstruction level -DECLARE_SOA_COLUMN(OriginMcGen, originMcGen, int8_t); // particle origin, generator level -DECLARE_SOA_COLUMN(FlagWrongCollision, flagWrongCollision, int8_t); // reconstruction level -DECLARE_SOA_COLUMN(DebugMcRec, debugMcRec, int8_t); // debug flag for mis-association reconstruction level enum DecayTypeMc : uint8_t { B0ToDplusPiToPiKPiPi = 0, B0ToDsPiToKKPiPi, @@ -2025,30 +1955,21 @@ DECLARE_SOA_EXTENDED_TABLE_USER(HfCandB0DStExt, HfCandB0DStar, "HFCANDB0DSTEXT", // table with results of reconstruction level MC matching DECLARE_SOA_TABLE(HfCandB0McRec, "AOD", "HFCANDB0MCREC", - hf_cand_b0::FlagMcMatchRec, - hf_cand_b0::FlagMcDecayChanRec, - hf_cand_b0::OriginMcRec, - hf_cand_b0::DebugMcRec); + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::FlagMcDecayChanRec, + hf_cand_mc_flag::OriginMcRec, + hf_cand_mc_flag::DebugMcRec); // table with results of generator level MC matching DECLARE_SOA_TABLE(HfCandB0McGen, "AOD", "HFCANDB0MCGEN", - hf_cand_b0::FlagMcMatchGen, - hf_cand_b0::FlagMcDecayChanGen, - hf_cand_b0::OriginMcGen); + hf_cand_mc_flag::FlagMcMatchGen, + hf_cand_mc_flag::FlagMcDecayChanGen, + hf_cand_mc_flag::OriginMcGen); // specific Bs candidate properties namespace hf_cand_bs { -DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfCand3Prong, "_0"); // Ds index -// MC matching result: -DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); // main decay channel, reconstruction level -DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); // main decay channel, generator level -DECLARE_SOA_COLUMN(FlagMcDecayChanRec, flagMcDecayChanRec, int8_t); // resonant decay channel, reconstruction level -DECLARE_SOA_COLUMN(FlagMcDecayChanGen, flagMcDecayChanGen, int8_t); // resonant decay channel, generator level -DECLARE_SOA_COLUMN(OriginMcRec, originMcRec, int8_t); // particle origin, reconstruction level -DECLARE_SOA_COLUMN(OriginMcGen, originMcGen, int8_t); // particle origin, generator level -DECLARE_SOA_COLUMN(FlagWrongCollision, flagWrongCollision, int8_t); // reconstruction level -DECLARE_SOA_COLUMN(DebugMcRec, debugMcRec, int8_t); // debug flag for mis-association reconstruction level +DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfCand3Prong, "_0"); // Ds index DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterProduct, impactParameterProduct, // Impact parameter product for Bs -> J/Psi phi [](float pxJpsiDauPos, float pyJpsiDauPos, float pzJpsiDauPos, float pxJpsiDauNeg, float pyJpsiDauNeg, float pzJpsiDauNeg, float pxLfTrack0, float pyLfTrack0, float pzLfTrack0, float pxLfTrack1, float pyLfTrack1, float pzLfTrack1, float xVtxP, float yVtxP, float zVtxP, float xVtxS, float yVtxS, float zVtxS) -> float { float impParJpsi = RecoDecay::impParXY(std::array{xVtxP, yVtxP, zVtxP}, std::array{xVtxS, yVtxS, zVtxS}, RecoDecay::pVec(std::array{pxJpsiDauPos, pyJpsiDauPos, pzJpsiDauPos}, std::array{pxJpsiDauNeg, pyJpsiDauNeg, pzJpsiDauNeg})); @@ -2108,8 +2029,7 @@ DECLARE_SOA_TABLE(HfCandBsBase, "AOD", "HFCANDBSBASE", hf_cand::Y, hf_cand::E, hf_cand::E2, - hf_cand_2prong::CtXY, - o2::soa::Marker<1>); + hf_cand_2prong::CtXY); // extended table with expression columns that can be used as arguments of dynamic columns DECLARE_SOA_EXTENDED_TABLE_USER(HfCandBsExt, HfCandBsBase, "HFCANDBSEXT", @@ -2122,13 +2042,13 @@ using HfCandBs = soa::Join; // table with results of reconstruction level MC matching DECLARE_SOA_TABLE(HfCandBsMcRec, "AOD", "HFCANDBSMCREC", - hf_cand_bs::FlagMcMatchRec, - hf_cand_bs::FlagMcDecayChanRec); + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::FlagMcDecayChanRec); // table with results of generator level MC matching DECLARE_SOA_TABLE(HfCandBsMcGen, "AOD", "HFCANDBSMCGEN", - hf_cand_bs::FlagMcMatchGen, - hf_cand_bs::FlagMcDecayChanGen); + hf_cand_mc_flag::FlagMcMatchGen, + hf_cand_mc_flag::FlagMcDecayChanGen); namespace hf_cand_4prong { @@ -2194,8 +2114,7 @@ DECLARE_SOA_TABLE(HfCandBsJPBase, "AOD", "HFCANDBSJPBASE", hf_cand::Y, hf_cand::E, hf_cand::E2, - hf_cand_4prong::CtXY, - o2::soa::Marker<1>); + hf_cand_4prong::CtXY); // extended table with expression columns that can be used as arguments of dynamic columns DECLARE_SOA_EXTENDED_TABLE_USER(HfCandBsJPExt, HfCandBsJPBase, "HFCANDBSJPEXT", @@ -2217,10 +2136,6 @@ DECLARE_SOA_COLUMN(SoftPiDcaXY, softPiDcaXY, float); DECLARE_SOA_COLUMN(SoftPiDcaZ, softPiDcaZ, float); //! soft-pion impact parameter in z DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfCand3Prong, "_0"); //! Λc index // MC matching result: -DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); //! reconstruction level -DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); //! generator level -DECLARE_SOA_COLUMN(OriginMcRec, originMcRec, int8_t); //! particle origin, reconstruction level -DECLARE_SOA_COLUMN(OriginMcGen, originMcGen, int8_t); //! particle origin, generator level DECLARE_SOA_COLUMN(ParticleAntiparticle, particleAntiparticle, int8_t); //! particle or antiparticle enum Species : int { Sc2455 = 0, @@ -2286,17 +2201,17 @@ using HfCandSc = HfCandScExt; // table with results of reconstruction level MC matching DECLARE_SOA_TABLE(HfCandScMcRec, "AOD", "HFCANDSCMCREC", //! - hf_cand_sigmac::FlagMcMatchRec, - hf_cand_sigmac::OriginMcRec, - hf_cand::PtBhadMotherPart, - hf_cand::PdgBhadMotherPart, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcRec, + hf_cand_mc_flag::PtBhadMotherPart, + hf_cand_mc_flag::PdgBhadMotherPart, hf_cand_sigmac::ParticleAntiparticle); // table with results of generation level MC matching DECLARE_SOA_TABLE(HfCandScMcGen, "AOD", "HFCANDSCMCGEN", //! - hf_cand_sigmac::FlagMcMatchGen, - hf_cand_sigmac::OriginMcGen, - hf_cand::IdxBhadMotherPart, + hf_cand_mc_flag::FlagMcMatchGen, + hf_cand_mc_flag::OriginMcGen, + hf_cand_mc_flag::IdxBhadMotherPart, hf_cand_sigmac::ParticleAntiparticle); // specific Σc0,++ candidate properties in cascade channel @@ -2308,11 +2223,6 @@ DECLARE_SOA_COLUMN(ChargeLc, chargeLc, int8_t); DECLARE_SOA_COLUMN(ChargeSoftPi, chargeSoftPi, int8_t); //! // pion charge(either - or +) DECLARE_SOA_COLUMN(StatusSpreadLcMinvKs0PFromPDG, statusSpreadLcMinvKs0PFromPDG, int); //! // Λc Minv spread from PDG Λc mass DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfCandCascade, "_0"); //! Λc index -// MC matching result: -DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); //! reconstruction level -DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); //! generator level -DECLARE_SOA_COLUMN(OriginMcRec, originMcRec, int8_t); //! particle origin, reconstruction level -DECLARE_SOA_COLUMN(OriginMcGen, originMcGen, int8_t); //! particle origin, generator level } // namespace hf_cand_sigmac_to_cascade // declare dedicated Σc0,++ decay candidate table @@ -2470,14 +2380,8 @@ DECLARE_SOA_DYNAMIC_COLUMN(PVecSoftPi, pVecSoftPi, [](float px, float py, float DECLARE_SOA_DYNAMIC_COLUMN(TPCTOFNSigmaPiSoftPi, tpcTofNSigmaPiSoftPi, //! Combination of NsigmaTPC and NsigmaTOF, o2-linter: disable=name/o2-column (written to disk) [](float tpcNSigmaPiSoftPi, float TOFNSigmaPiSoftPi) -> float { return pid_tpc_tof_utils::combineNSigma(tpcNSigmaPiSoftPi, TOFNSigmaPiSoftPi); }); // MC matching result: -DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); //! reconstruction level -DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); //! generator level DECLARE_SOA_COLUMN(FlagMcMatchRecD0, flagMcMatchRecD0, int8_t); //! reconstruction level DECLARE_SOA_COLUMN(FlagMcMatchGenD0, flagMcMatchGenD0, int8_t); //! generator level - -DECLARE_SOA_COLUMN(OriginMcRec, originMcRec, int8_t); //! particle origin, reconstruction level -DECLARE_SOA_COLUMN(OriginMcGen, originMcGen, int8_t); //! particle origin, generator level - } // namespace hf_cand_dstar /// D0 (table) from DStar @@ -2608,20 +2512,20 @@ using HfCandDstarsWPid = soa::Join); // ---------------- diff --git a/PWGHF/HFC/DataModel/ReducedDMesonPairsTables.h b/PWGHF/HFC/DataModel/ReducedDMesonPairsTables.h index b739ae6c89a..9c4484de852 100644 --- a/PWGHF/HFC/DataModel/ReducedDMesonPairsTables.h +++ b/PWGHF/HFC/DataModel/ReducedDMesonPairsTables.h @@ -103,9 +103,9 @@ DECLARE_SOA_TABLE(HfCandDpTinys, "AOD", "HFCANDDPTINY", full::Eta, full::Phi, full::HfCandDpFullEvId, - hf_cand_3prong::FlagMcMatchRec, - hf_cand_3prong::OriginMcRec, - hf_cand_3prong::FlagMcDecayChanRec) + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcRec, + hf_cand_mc_flag::FlagMcDecayChanRec) DECLARE_SOA_TABLE(HfCandDpLites, "AOD", "HFCANDDPLITE", hf_cand::Chi2PCA, @@ -151,9 +151,9 @@ DECLARE_SOA_TABLE(HfCandDpLites, "AOD", "HFCANDDPLITE", full::Y, full::Centrality, full::HfCandDpFullEvId, - hf_cand_3prong::FlagMcMatchRec, - hf_cand_3prong::OriginMcRec, - hf_cand_3prong::FlagMcDecayChanRec) + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcRec, + hf_cand_mc_flag::FlagMcDecayChanRec) DECLARE_SOA_TABLE(HfCandDpFulls, "AOD", "HFCANDDPFULL", hf_cand::XSecondaryVertex, @@ -229,9 +229,9 @@ DECLARE_SOA_TABLE(HfCandDpFulls, "AOD", "HFCANDDPFULL", full::E, full::Centrality, full::HfCandDpFullEvId, - hf_cand_3prong::FlagMcMatchRec, - hf_cand_3prong::OriginMcRec, - hf_cand_3prong::FlagMcDecayChanRec); + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcRec, + hf_cand_mc_flag::FlagMcDecayChanRec); DECLARE_SOA_TABLE(HfCandDpMcPs, "AOD", "HFCANDDPMCP", full::Pt, @@ -239,9 +239,9 @@ DECLARE_SOA_TABLE(HfCandDpMcPs, "AOD", "HFCANDDPMCP", full::Phi, full::Y, full::HfCandDpMcEvId, - hf_cand_3prong::FlagMcMatchGen, - hf_cand_3prong::FlagMcDecayChanGen, - hf_cand_3prong::OriginMcGen); + hf_cand_mc_flag::FlagMcMatchGen, + hf_cand_mc_flag::FlagMcDecayChanGen, + hf_cand_mc_flag::OriginMcGen); } // namespace o2::aod #endif // PWGHF_HFC_DATAMODEL_REDUCEDDMESONPAIRSTABLES_H_ diff --git a/PWGHF/HFC/TableProducer/correlatorDplusDplusReduced.cxx b/PWGHF/HFC/TableProducer/correlatorDplusDplusReduced.cxx index 306d2d494e8..3d00c7ac8eb 100644 --- a/PWGHF/HFC/TableProducer/correlatorDplusDplusReduced.cxx +++ b/PWGHF/HFC/TableProducer/correlatorDplusDplusReduced.cxx @@ -80,14 +80,14 @@ struct HfCorrelatorDplusDplusReduced { using CollisionsCent = soa::Join; Filter filterSelectCandidates = aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; - Filter filterMcGenMatching = (nabs(o2::aod::hf_cand_3prong::flagMcMatchGen) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi)) || (fillCorrBkgs && (nabs(o2::aod::hf_cand_3prong::flagMcMatchGen) != 0)); + Filter filterMcGenMatching = (nabs(o2::aod::hf_cand_mc_flag::flagMcMatchGen) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi)) || (fillCorrBkgs && (nabs(o2::aod::hf_cand_mc_flag::flagMcMatchGen) != 0)); Preslice tracksPerCollision = o2::aod::track::collisionId; Preslice mcParticlesPerMcCollision = o2::aod::mcparticle::mcCollisionId; - Partition reconstructedCandSig = (nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi)) || (fillCorrBkgs && (nabs(o2::aod::hf_cand_3prong::flagMcMatchRec) != 0)); - Partition reconstructedCandBkg = nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi); - Partition reconstructedCandSigMl = (nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi)) || (fillCorrBkgs && (nabs(o2::aod::hf_cand_3prong::flagMcMatchRec) != 0)); + Partition reconstructedCandSig = (nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi)) || (fillCorrBkgs && (nabs(o2::aod::hf_cand_mc_flag::flagMcMatchRec) != 0)); + Partition reconstructedCandBkg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi); + Partition reconstructedCandSigMl = (nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi)) || (fillCorrBkgs && (nabs(o2::aod::hf_cand_mc_flag::flagMcMatchRec) != 0)); HistogramRegistry registry{"registry"}; Zorro zorro; diff --git a/PWGHF/TableProducer/derivedDataCreatorB0ToDPi.cxx b/PWGHF/TableProducer/derivedDataCreatorB0ToDPi.cxx index 5378586cff8..bb52685c14e 100644 --- a/PWGHF/TableProducer/derivedDataCreatorB0ToDPi.cxx +++ b/PWGHF/TableProducer/derivedDataCreatorB0ToDPi.cxx @@ -107,7 +107,7 @@ struct HfDerivedDataCreatorB0ToDPi { using THfCandDaughtersMl = soa::Join; Filter filterSelectCandidates = (aod::hf_sel_candidate_b0::isSelB0ToDPi & static_cast(BIT(aod::SelectionStep::RecoMl - 1))) != 0; - Filter filterMcGenMatching = nabs(aod::hf_cand_b0::flagMcMatchGen) == static_cast(DecayChannelMain::B0ToDminusPi); + Filter filterMcGenMatching = nabs(aod::hf_cand_mc_flag::flagMcMatchGen) == static_cast(DecayChannelMain::B0ToDminusPi); Preslice candidatesPerCollision = aod::hf_cand::collisionId; Preslice candidatesMcPerCollision = aod::hf_cand::collisionId; @@ -121,10 +121,10 @@ struct HfDerivedDataCreatorB0ToDPi { Partition candidatesMlAll = aod::hf_sel_candidate_b0::isSelB0ToDPi >= 0; Partition candidatesMcMlAll = aod::hf_sel_candidate_b0::isSelB0ToDPi >= 0; // partitions for signal and background - Partition candidatesMcSig = nabs(aod::hf_cand_b0::flagMcMatchRec) == static_cast(DecayChannelMain::B0ToDminusPi); - Partition candidatesMcBkg = nabs(aod::hf_cand_b0::flagMcMatchRec) != static_cast(DecayChannelMain::B0ToDminusPi); - Partition candidatesMcMlSig = nabs(aod::hf_cand_b0::flagMcMatchRec) == static_cast(DecayChannelMain::B0ToDminusPi); - Partition candidatesMcMlBkg = nabs(aod::hf_cand_b0::flagMcMatchRec) != static_cast(DecayChannelMain::B0ToDminusPi); + Partition candidatesMcSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(DecayChannelMain::B0ToDminusPi); + Partition candidatesMcBkg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(DecayChannelMain::B0ToDminusPi); + Partition candidatesMcMlSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(DecayChannelMain::B0ToDminusPi); + Partition candidatesMcMlBkg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(DecayChannelMain::B0ToDminusPi); void init(InitContext const&) { diff --git a/PWGHF/TableProducer/derivedDataCreatorBplusToD0Pi.cxx b/PWGHF/TableProducer/derivedDataCreatorBplusToD0Pi.cxx index 05c34f4c85b..3efeb95a145 100644 --- a/PWGHF/TableProducer/derivedDataCreatorBplusToD0Pi.cxx +++ b/PWGHF/TableProducer/derivedDataCreatorBplusToD0Pi.cxx @@ -108,7 +108,7 @@ struct HfDerivedDataCreatorBplusToD0Pi { using THfCandDaughtersMl = soa::Join; Filter filterSelectCandidates = (aod::hf_sel_candidate_bplus::isSelBplusToD0Pi & static_cast(BIT(aod::SelectionStep::RecoMl - 1))) != 0; - Filter filterMcGenMatching = nabs(aod::hf_cand_bplus::flagMcMatchGen) == static_cast(DecayChannelMain::BplusToD0Pi); + Filter filterMcGenMatching = nabs(aod::hf_cand_mc_flag::flagMcMatchGen) == static_cast(DecayChannelMain::BplusToD0Pi); Preslice candidatesPerCollision = aod::hf_cand::collisionId; Preslice candidatesMcPerCollision = aod::hf_cand::collisionId; @@ -122,10 +122,10 @@ struct HfDerivedDataCreatorBplusToD0Pi { Partition candidatesMlAll = aod::hf_sel_candidate_bplus::isSelBplusToD0Pi >= 0; Partition candidatesMcMlAll = aod::hf_sel_candidate_bplus::isSelBplusToD0Pi >= 0; // partitions for signal and background - Partition candidatesMcSig = nabs(aod::hf_cand_bplus::flagMcMatchRec) == static_cast(DecayChannelMain::BplusToD0Pi); - Partition candidatesMcBkg = nabs(aod::hf_cand_bplus::flagMcMatchRec) != static_cast(DecayChannelMain::BplusToD0Pi); - Partition candidatesMcMlSig = nabs(aod::hf_cand_bplus::flagMcMatchRec) == static_cast(DecayChannelMain::BplusToD0Pi); - Partition candidatesMcMlBkg = nabs(aod::hf_cand_bplus::flagMcMatchRec) != static_cast(DecayChannelMain::BplusToD0Pi); + Partition candidatesMcSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(DecayChannelMain::BplusToD0Pi); + Partition candidatesMcBkg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(DecayChannelMain::BplusToD0Pi); + Partition candidatesMcMlSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(DecayChannelMain::BplusToD0Pi); + Partition candidatesMcMlBkg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(DecayChannelMain::BplusToD0Pi); void init(InitContext const&) { diff --git a/PWGHF/TableProducer/derivedDataCreatorD0ToKPi.cxx b/PWGHF/TableProducer/derivedDataCreatorD0ToKPi.cxx index f8e71198d1c..9041d4d7c2e 100644 --- a/PWGHF/TableProducer/derivedDataCreatorD0ToKPi.cxx +++ b/PWGHF/TableProducer/derivedDataCreatorD0ToKPi.cxx @@ -105,7 +105,7 @@ struct HfDerivedDataCreatorD0ToKPi { using TypeMcCollisions = soa::Join; Filter filterSelectCandidates = aod::hf_sel_candidate_d0::isSelD0 >= 1 || aod::hf_sel_candidate_d0::isSelD0bar >= 1; - Filter filterMcGenMatching = nabs(aod::hf_cand_2prong::flagMcMatchGen) == static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); + Filter filterMcGenMatching = nabs(aod::hf_cand_mc_flag::flagMcMatchGen) == static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); Preslice candidatesPerCollision = aod::hf_cand::collisionId; Preslice candidatesKfPerCollision = aod::hf_cand::collisionId; @@ -127,14 +127,14 @@ struct HfDerivedDataCreatorD0ToKPi { Partition candidatesMcMlAll = aod::hf_sel_candidate_d0::isSelD0 >= 0; Partition candidatesMcKfMlAll = aod::hf_sel_candidate_d0::isSelD0 >= 0; // partitions for signal and background - Partition candidatesMcSig = nabs(aod::hf_cand_2prong::flagMcMatchRec) == static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); - Partition candidatesMcBkg = nabs(aod::hf_cand_2prong::flagMcMatchRec) != static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); - Partition candidatesMcKfSig = nabs(aod::hf_cand_2prong::flagMcMatchRec) == static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); - Partition candidatesMcKfBkg = nabs(aod::hf_cand_2prong::flagMcMatchRec) != static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); - Partition candidatesMcMlSig = nabs(aod::hf_cand_2prong::flagMcMatchRec) == static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); - Partition candidatesMcMlBkg = nabs(aod::hf_cand_2prong::flagMcMatchRec) != static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); - Partition candidatesMcKfMlSig = nabs(aod::hf_cand_2prong::flagMcMatchRec) == static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); - Partition candidatesMcKfMlBkg = nabs(aod::hf_cand_2prong::flagMcMatchRec) != static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); + Partition candidatesMcSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); + Partition candidatesMcBkg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); + Partition candidatesMcKfSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); + Partition candidatesMcKfBkg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); + Partition candidatesMcMlSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); + Partition candidatesMcMlBkg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); + Partition candidatesMcKfMlSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); + Partition candidatesMcKfMlBkg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); void init(InitContext const&) { diff --git a/PWGHF/TableProducer/derivedDataCreatorDplusToPiKPi.cxx b/PWGHF/TableProducer/derivedDataCreatorDplusToPiKPi.cxx index 957ad139756..a7a90b507c5 100644 --- a/PWGHF/TableProducer/derivedDataCreatorDplusToPiKPi.cxx +++ b/PWGHF/TableProducer/derivedDataCreatorDplusToPiKPi.cxx @@ -102,7 +102,7 @@ struct HfDerivedDataCreatorDplusToPiKPi { using TypeMcCollisions = soa::Join; Filter filterSelectCandidates = (aod::hf_sel_candidate_dplus::isSelDplusToPiKPi & static_cast(BIT(aod::SelectionStep::RecoMl - 1))) != 0; // select candidates which passed all cuts at least up to RecoMl - 1 - Filter filterMcGenMatching = nabs(aod::hf_cand_3prong::flagMcMatchGen) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi); + Filter filterMcGenMatching = nabs(aod::hf_cand_mc_flag::flagMcMatchGen) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi); Preslice candidatesPerCollision = aod::hf_cand::collisionId; Preslice candidatesMcPerCollision = aod::hf_cand::collisionId; @@ -116,10 +116,10 @@ struct HfDerivedDataCreatorDplusToPiKPi { Partition candidatesMlAll = aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= 0; Partition candidatesMcMlAll = aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= 0; // partitions for signal and background - Partition candidatesMcSig = nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi); - Partition candidatesMcBkg = nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi); - Partition candidatesMcMlSig = nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi); - Partition candidatesMcMlBkg = nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi); + Partition candidatesMcSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi); + Partition candidatesMcBkg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi); + Partition candidatesMcMlSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi); + Partition candidatesMcMlBkg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi); void init(InitContext const&) { diff --git a/PWGHF/TableProducer/derivedDataCreatorDsToKKPi.cxx b/PWGHF/TableProducer/derivedDataCreatorDsToKKPi.cxx index 0a5f217e19e..587b967af0b 100644 --- a/PWGHF/TableProducer/derivedDataCreatorDsToKKPi.cxx +++ b/PWGHF/TableProducer/derivedDataCreatorDsToKKPi.cxx @@ -100,7 +100,7 @@ struct HfDerivedDataCreatorDsToKKPi { using TypeMcCollisions = soa::Join; Filter filterSelectCandidates = (aod::hf_sel_candidate_ds::isSelDsToKKPi & static_cast(BIT(aod::SelectionStep::RecoMl - 1))) != 0; // select candidates which passed all cuts at least up to RecoMl - 1 - Filter filterMcGenMatching = nabs(aod::hf_cand_3prong::flagMcMatchGen) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK); + Filter filterMcGenMatching = nabs(aod::hf_cand_mc_flag::flagMcMatchGen) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK); Preslice candidatesPerCollision = aod::hf_cand::collisionId; Preslice candidatesMcPerCollision = aod::hf_cand::collisionId; @@ -114,10 +114,10 @@ struct HfDerivedDataCreatorDsToKKPi { Partition candidatesMlAll = aod::hf_sel_candidate_ds::isSelDsToKKPi >= 0; Partition candidatesMcMlAll = aod::hf_sel_candidate_ds::isSelDsToKKPi >= 0; // partitions for signal and background - Partition candidatesMcSig = nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK); - Partition candidatesMcBkg = nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK); - Partition candidatesMcMlSig = nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK); - Partition candidatesMcMlBkg = nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK); + Partition candidatesMcSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK); + Partition candidatesMcBkg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK); + Partition candidatesMcMlSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK); + Partition candidatesMcMlBkg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK); void init(InitContext const&) { diff --git a/PWGHF/TableProducer/derivedDataCreatorDstarToD0Pi.cxx b/PWGHF/TableProducer/derivedDataCreatorDstarToD0Pi.cxx index 1a15c3b1fb3..a04dc0cf033 100644 --- a/PWGHF/TableProducer/derivedDataCreatorDstarToD0Pi.cxx +++ b/PWGHF/TableProducer/derivedDataCreatorDstarToD0Pi.cxx @@ -98,7 +98,7 @@ struct HfDerivedDataCreatorDstarToD0Pi { using TypeMcCollisions = soa::Join; Filter filterSelectCandidates = aod::hf_sel_candidate_dstar::isSelDstarToD0Pi == true; - Filter filterMcGenMatching = nabs(aod::hf_cand_dstar::flagMcMatchGen) == static_cast(hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi); + Filter filterMcGenMatching = nabs(aod::hf_cand_mc_flag::flagMcMatchGen) == static_cast(hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi); Preslice candidatesPerCollision = aod::hf_cand::collisionId; Preslice candidatesMcPerCollision = aod::hf_cand::collisionId; @@ -112,10 +112,10 @@ struct HfDerivedDataCreatorDstarToD0Pi { Partition candidatesMlAll = aod::hf_sel_candidate_dstar::isSelDstarToD0Pi == true; Partition candidatesMcMlAll = aod::hf_sel_candidate_dstar::isSelDstarToD0Pi == true; // partitions for signal and background - Partition candidatesMcSig = nabs(aod::hf_cand_dstar::flagMcMatchRec) == static_cast(hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi); - Partition candidatesMcBkg = nabs(aod::hf_cand_dstar::flagMcMatchRec) != static_cast(hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi); - Partition candidatesMcMlSig = nabs(aod::hf_cand_dstar::flagMcMatchRec) == static_cast(hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi); - Partition candidatesMcMlBkg = nabs(aod::hf_cand_dstar::flagMcMatchRec) != static_cast(hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi); + Partition candidatesMcSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi); + Partition candidatesMcBkg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi); + Partition candidatesMcMlSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi); + Partition candidatesMcMlBkg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi); void init(InitContext const&) { diff --git a/PWGHF/TableProducer/derivedDataCreatorLcToK0sP.cxx b/PWGHF/TableProducer/derivedDataCreatorLcToK0sP.cxx index 83b2f90107d..0386d6afba6 100644 --- a/PWGHF/TableProducer/derivedDataCreatorLcToK0sP.cxx +++ b/PWGHF/TableProducer/derivedDataCreatorLcToK0sP.cxx @@ -101,7 +101,7 @@ struct HfDerivedDataCreatorLcToK0sP { using TypeMcCollisions = soa::Join; Filter filterSelectCandidates = aod::hf_sel_candidate_lc_to_k0s_p::isSelLcToK0sP >= 1; - Filter filterMcGenMatching = nabs(aod::hf_cand_casc::flagMcMatchGen) == 1; + Filter filterMcGenMatching = nabs(aod::hf_cand_mc_flag::flagMcMatchGen) == 1; Preslice candidatesPerCollision = aod::hf_cand::collisionId; Preslice candidatesMcPerCollision = aod::hf_cand::collisionId; @@ -115,10 +115,10 @@ struct HfDerivedDataCreatorLcToK0sP { Partition candidatesMlAll = aod::hf_sel_candidate_lc_to_k0s_p::isSelLcToK0sP >= 0; Partition candidatesMcMlAll = aod::hf_sel_candidate_lc_to_k0s_p::isSelLcToK0sP >= 0; // partitions for signal and background - Partition candidatesMcSig = nabs(aod::hf_cand_casc::flagMcMatchRec) == 1; - Partition candidatesMcBkg = nabs(aod::hf_cand_casc::flagMcMatchRec) != 1; - Partition candidatesMcMlSig = nabs(aod::hf_cand_casc::flagMcMatchRec) == 1; - Partition candidatesMcMlBkg = nabs(aod::hf_cand_casc::flagMcMatchRec) != 1; + Partition candidatesMcSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == 1; + Partition candidatesMcBkg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != 1; + Partition candidatesMcMlSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == 1; + Partition candidatesMcMlBkg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != 1; void init(InitContext const&) { diff --git a/PWGHF/TableProducer/derivedDataCreatorLcToPKPi.cxx b/PWGHF/TableProducer/derivedDataCreatorLcToPKPi.cxx index b96ac350953..efecd6f6713 100644 --- a/PWGHF/TableProducer/derivedDataCreatorLcToPKPi.cxx +++ b/PWGHF/TableProducer/derivedDataCreatorLcToPKPi.cxx @@ -100,7 +100,7 @@ struct HfDerivedDataCreatorLcToPKPi { using TypeMcCollisions = soa::Join; Filter filterSelectCandidates = aod::hf_sel_candidate_lc::isSelLcToPKPi >= 1 || aod::hf_sel_candidate_lc::isSelLcToPiKP >= 1; - Filter filterMcGenMatching = nabs(aod::hf_cand_3prong::flagMcMatchGen) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi); + Filter filterMcGenMatching = nabs(aod::hf_cand_mc_flag::flagMcMatchGen) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi); Preslice candidatesPerCollision = aod::hf_cand::collisionId; Preslice candidatesMcPerCollision = aod::hf_cand::collisionId; @@ -114,10 +114,10 @@ struct HfDerivedDataCreatorLcToPKPi { Partition candidatesMlAll = aod::hf_sel_candidate_lc::isSelLcToPKPi >= 0; Partition candidatesMcMlAll = aod::hf_sel_candidate_lc::isSelLcToPKPi >= 0; // partitions for signal and background - Partition candidatesMcSig = nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi); - Partition candidatesMcBkg = nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi); - Partition candidatesMcMlSig = nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi); - Partition candidatesMcMlBkg = nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi); + Partition candidatesMcSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi); + Partition candidatesMcBkg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi); + Partition candidatesMcMlSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi); + Partition candidatesMcMlBkg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi); void init(InitContext const&) { diff --git a/PWGHF/TableProducer/derivedDataCreatorXicToXiPiPi.cxx b/PWGHF/TableProducer/derivedDataCreatorXicToXiPiPi.cxx index fa52ec0a79f..9e0529b97d6 100644 --- a/PWGHF/TableProducer/derivedDataCreatorXicToXiPiPi.cxx +++ b/PWGHF/TableProducer/derivedDataCreatorXicToXiPiPi.cxx @@ -102,7 +102,7 @@ struct HfDerivedDataCreatorXicToXiPiPi { using THfCandDaughtersMl = aod::Cascades; Filter filterSelectCandidates = (aod::hf_sel_candidate_xic::isSelXicToXiPiPi & static_cast(BIT(o2::aod::hf_sel_candidate_xic::XicToXiPiPiSelectionStep::RecoMl - 1))) != 0; - Filter filterMcGenMatching = aod::hf_cand_xic_to_xi_pi_pi::flagMcMatchGen != 0; + Filter filterMcGenMatching = aod::hf_cand_mc_flag::flagMcMatchGen != 0; Preslice candidatesPerCollision = aod::hf_cand::collisionId; Preslice candidatesMcPerCollision = aod::hf_cand::collisionId; @@ -116,10 +116,10 @@ struct HfDerivedDataCreatorXicToXiPiPi { Partition candidatesMlAll = aod::hf_sel_candidate_xic::isSelXicToXiPiPi >= 0; Partition candidatesMcMlAll = aod::hf_sel_candidate_xic::isSelXicToXiPiPi >= 0; // partitions for signal and background - Partition candidatesMcSig = aod::hf_cand_xic_to_xi_pi_pi::flagMcMatchRec != 0; - Partition candidatesMcBkg = aod::hf_cand_xic_to_xi_pi_pi::flagMcMatchRec == 0; - Partition candidatesMcMlSig = aod::hf_cand_xic_to_xi_pi_pi::flagMcMatchRec != 0; - Partition candidatesMcMlBkg = aod::hf_cand_xic_to_xi_pi_pi::flagMcMatchRec == 0; + Partition candidatesMcSig = aod::hf_cand_mc_flag::flagMcMatchRec != 0; + Partition candidatesMcBkg = aod::hf_cand_mc_flag::flagMcMatchRec == 0; + Partition candidatesMcMlSig = aod::hf_cand_mc_flag::flagMcMatchRec != 0; + Partition candidatesMcMlBkg = aod::hf_cand_mc_flag::flagMcMatchRec == 0; void init(InitContext const&) { diff --git a/PWGHF/TableProducer/treeCreatorB0ToDPi.cxx b/PWGHF/TableProducer/treeCreatorB0ToDPi.cxx index af4663a1b41..dda2819b164 100644 --- a/PWGHF/TableProducer/treeCreatorB0ToDPi.cxx +++ b/PWGHF/TableProducer/treeCreatorB0ToDPi.cxx @@ -96,8 +96,8 @@ DECLARE_SOA_TABLE(HfCandB0Lites, "AOD", "HFCANDB0LITE", full::Eta, full::Phi, full::Y, - hf_cand_3prong::FlagMcMatchRec, - hf_cand_3prong::OriginMcRec); + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcRec); DECLARE_SOA_TABLE(HfCandB0Fulls, "AOD", "HFCANDB0FULL", collision::BCId, @@ -146,8 +146,8 @@ DECLARE_SOA_TABLE(HfCandB0Fulls, "AOD", "HFCANDB0FULL", full::Phi, full::Y, full::E, - hf_cand_3prong::FlagMcMatchRec, - hf_cand_3prong::OriginMcRec); + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcRec); DECLARE_SOA_TABLE(HfCandB0FullEvs, "AOD", "HFCANDB0FULLEV", collision::BCId, @@ -164,8 +164,8 @@ DECLARE_SOA_TABLE(HfCandB0FullPs, "AOD", "HFCANDB0FULLP", full::Eta, full::Phi, full::Y, - hf_cand_3prong::FlagMcMatchRec, - hf_cand_3prong::OriginMcGen); + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcGen); } // namespace o2::aod /// Writes the full information in an output TTree @@ -188,8 +188,8 @@ struct HfTreeCreatorB0ToDPi { Filter filterSelectCandidates = aod::hf_sel_candidate_b0::isSelB0ToDPi >= selectionFlagB0; - Partition recSig = nabs(aod::hf_cand_b0::flagMcMatchRec) == static_cast(DecayChannelMain::B0ToDminusPi); - Partition recBg = nabs(aod::hf_cand_b0::flagMcMatchRec) != static_cast(DecayChannelMain::B0ToDminusPi); + Partition recSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(DecayChannelMain::B0ToDminusPi); + Partition recBg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(DecayChannelMain::B0ToDminusPi); void init(InitContext const&) { diff --git a/PWGHF/TableProducer/treeCreatorBplusToD0Pi.cxx b/PWGHF/TableProducer/treeCreatorBplusToD0Pi.cxx index 9aa6b5f7cab..66826ddfe5c 100644 --- a/PWGHF/TableProducer/treeCreatorBplusToD0Pi.cxx +++ b/PWGHF/TableProducer/treeCreatorBplusToD0Pi.cxx @@ -153,7 +153,7 @@ DECLARE_SOA_TABLE(HfCandBpFulls, "AOD", "HFCANDBPFULL", full::Phi, full::Y, full::E, - hf_cand_2prong::FlagMcMatchRec, + hf_cand_mc_flag::FlagMcMatchRec, full::D0M, full::D0PtProng0, full::D0PtProng1, @@ -195,8 +195,8 @@ DECLARE_SOA_TABLE(HfCandBpFullPs, "AOD", "HFCANDBPFULLP", full::Eta, full::Phi, full::Y, - hf_cand_2prong::FlagMcMatchRec, - hf_cand_2prong::OriginMcGen); + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcGen); DECLARE_SOA_TABLE(HfCandBpLites, "AOD", "HFCANDBPLITE", hf_cand::Chi2PCA, @@ -219,8 +219,8 @@ DECLARE_SOA_TABLE(HfCandBpLites, "AOD", "HFCANDBPLITE", full::Eta, full::Phi, full::Y, - hf_cand_2prong::FlagMcMatchRec, - hf_cand_2prong::OriginMcRec); + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcRec); } // namespace o2::aod @@ -244,8 +244,8 @@ struct HfTreeCreatorBplusToD0Pi { Filter filterSelectCandidates = aod::hf_sel_candidate_bplus::isSelBplusToD0Pi >= selectionFlagBplus; - Partition recSig = nabs(aod::hf_cand_bplus::flagMcMatchRec) == static_cast(DecayChannelMain::BplusToD0Pi); - Partition recBg = nabs(aod::hf_cand_bplus::flagMcMatchRec) != static_cast(DecayChannelMain::BplusToD0Pi); + Partition recSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(DecayChannelMain::BplusToD0Pi); + Partition recBg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(DecayChannelMain::BplusToD0Pi); void init(InitContext const&) { diff --git a/PWGHF/TableProducer/treeCreatorBsToDsPi.cxx b/PWGHF/TableProducer/treeCreatorBsToDsPi.cxx index 6e30341f584..6dd99548b7c 100644 --- a/PWGHF/TableProducer/treeCreatorBsToDsPi.cxx +++ b/PWGHF/TableProducer/treeCreatorBsToDsPi.cxx @@ -95,7 +95,7 @@ DECLARE_SOA_TABLE(HfCandBsLites, "AOD", "HFCANDBSLITE", full::Eta, full::Phi, full::Y, - hf_cand_bs::FlagMcMatchRec); + hf_cand_mc_flag::FlagMcMatchRec); DECLARE_SOA_TABLE(HfCandBsFulls, "AOD", "HFCANDBSFULL", collision::BCId, @@ -143,7 +143,7 @@ DECLARE_SOA_TABLE(HfCandBsFulls, "AOD", "HFCANDBSFULL", full::Phi, full::Y, full::E, - hf_cand_bs::FlagMcMatchRec); + hf_cand_mc_flag::FlagMcMatchRec); DECLARE_SOA_TABLE(HfCandBsFullEvs, "AOD", "HFCANDBSFULLEV", collision::BCId, @@ -160,7 +160,7 @@ DECLARE_SOA_TABLE(HfCandBsFullPs, "AOD", "HFCANDBSFULLP", full::Eta, full::Phi, full::Y, - hf_cand_bs::FlagMcMatchGen); + hf_cand_mc_flag::FlagMcMatchGen); } // namespace o2::aod /// Writes the full information in an output TTree @@ -183,8 +183,8 @@ struct HfTreeCreatorBsToDsPi { Filter filterSelectCandidates = aod::hf_sel_candidate_bs::isSelBsToDsPi >= selectionFlagBs; - Partition recSig = nabs(aod::hf_cand_bs::flagMcMatchRec) == static_cast(DecayChannelMain::BsToDsPi); - Partition recBg = nabs(aod::hf_cand_bs::flagMcMatchRec) != static_cast(DecayChannelMain::BsToDsPi); + Partition recSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(DecayChannelMain::BsToDsPi); + Partition recBg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(DecayChannelMain::BsToDsPi); void init(InitContext const&) { diff --git a/PWGHF/TableProducer/treeCreatorD0ToKPi.cxx b/PWGHF/TableProducer/treeCreatorD0ToKPi.cxx index 7ad269131f9..49656d8c364 100644 --- a/PWGHF/TableProducer/treeCreatorD0ToKPi.cxx +++ b/PWGHF/TableProducer/treeCreatorD0ToKPi.cxx @@ -249,17 +249,17 @@ struct HfTreeCreatorD0ToKPi { using MatchedGenCandidatesMc = soa::Filtered>; Filter filterSelectCandidates = aod::hf_sel_candidate_d0::isSelD0 >= 1 || aod::hf_sel_candidate_d0::isSelD0bar >= 1; - Filter filterMcGenMatching = nabs(aod::hf_cand_2prong::flagMcMatchGen) == static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) || (fillCorrBkgs && (nabs(aod::hf_cand_2prong::flagMcMatchGen) != 0)); + Filter filterMcGenMatching = nabs(aod::hf_cand_mc_flag::flagMcMatchGen) == static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) || (fillCorrBkgs && (nabs(aod::hf_cand_mc_flag::flagMcMatchGen) != 0)); - Partition reconstructedCandSig = nabs(aod::hf_cand_2prong::flagMcMatchRec) == static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) || (fillCorrBkgs && nabs(aod::hf_cand_2prong::flagMcMatchRec) != 0); - Partition reconstructedCandBkg = nabs(aod::hf_cand_2prong::flagMcMatchRec) != static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); - Partition reconstructedCandSigKF = nabs(aod::hf_cand_2prong::flagMcMatchRec) == static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) || (fillCorrBkgs && nabs(aod::hf_cand_2prong::flagMcMatchRec) != 0); - Partition reconstructedCandBkgKF = nabs(aod::hf_cand_2prong::flagMcMatchRec) != static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); + Partition reconstructedCandSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) || (fillCorrBkgs && nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != 0); + Partition reconstructedCandBkg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); + Partition reconstructedCandSigKF = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) || (fillCorrBkgs && nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != 0); + Partition reconstructedCandBkgKF = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); - Partition reconstructedCandSigMl = nabs(aod::hf_cand_2prong::flagMcMatchRec) == static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) || (fillCorrBkgs && nabs(aod::hf_cand_2prong::flagMcMatchRec) != 0); - Partition reconstructedCandBkgMl = nabs(aod::hf_cand_2prong::flagMcMatchRec) != static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); - Partition reconstructedCandSigKFMl = nabs(aod::hf_cand_2prong::flagMcMatchRec) == static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) || (fillCorrBkgs && nabs(aod::hf_cand_2prong::flagMcMatchRec) != 0); - Partition reconstructedCandBkgKFMl = nabs(aod::hf_cand_2prong::flagMcMatchRec) != static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); + Partition reconstructedCandSigMl = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) || (fillCorrBkgs && nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != 0); + Partition reconstructedCandBkgMl = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); + Partition reconstructedCandSigKFMl = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) || (fillCorrBkgs && nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != 0); + Partition reconstructedCandBkgKFMl = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); void init(InitContext const&) { diff --git a/PWGHF/TableProducer/treeCreatorDplusToPiKPi.cxx b/PWGHF/TableProducer/treeCreatorDplusToPiKPi.cxx index 97978baac1e..d301cee0752 100644 --- a/PWGHF/TableProducer/treeCreatorDplusToPiKPi.cxx +++ b/PWGHF/TableProducer/treeCreatorDplusToPiKPi.cxx @@ -147,9 +147,9 @@ DECLARE_SOA_TABLE(HfCandDpLites, "AOD", "HFCANDDPLITE", full::Y, full::Centrality, collision::NumContrib, - hf_cand_3prong::FlagMcMatchRec, - hf_cand_3prong::OriginMcRec, - hf_cand_3prong::FlagMcDecayChanRec) + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcRec, + hf_cand_mc_flag::FlagMcDecayChanRec) DECLARE_SOA_TABLE(HfCandDpFulls, "AOD", "HFCANDDPFULL", collision::NumContrib, @@ -228,9 +228,9 @@ DECLARE_SOA_TABLE(HfCandDpFulls, "AOD", "HFCANDDPFULL", full::Y, full::E, full::Centrality, - hf_cand_3prong::FlagMcMatchRec, - hf_cand_3prong::OriginMcRec, - hf_cand_3prong::FlagMcDecayChanRec); + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcRec, + hf_cand_mc_flag::FlagMcDecayChanRec); DECLARE_SOA_TABLE(HfCandDpFullEvs, "AOD", "HFCANDDPFULLEV", collision::NumContrib, @@ -245,9 +245,9 @@ DECLARE_SOA_TABLE(HfCandDpFullPs, "AOD", "HFCANDDPFULLP", full::Eta, full::Phi, full::Y, - hf_cand_3prong::FlagMcMatchGen, - hf_cand_3prong::FlagMcDecayChanGen, - hf_cand_3prong::OriginMcGen); + hf_cand_mc_flag::FlagMcMatchGen, + hf_cand_mc_flag::FlagMcDecayChanGen, + hf_cand_mc_flag::OriginMcGen); } // namespace o2::aod /// Writes the full information in an output TTree @@ -277,11 +277,11 @@ struct HfTreeCreatorDplusToPiKPi { using CollisionsCent = soa::Join; Filter filterSelectCandidates = aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; - Filter filterMcGenMatching = (nabs(o2::aod::hf_cand_3prong::flagMcMatchGen) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi)) || (fillCorrBkgs && (nabs(o2::aod::hf_cand_3prong::flagMcMatchGen) != 0)); + Filter filterMcGenMatching = (nabs(o2::aod::hf_cand_mc_flag::flagMcMatchGen) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi)) || (fillCorrBkgs && (nabs(o2::aod::hf_cand_mc_flag::flagMcMatchGen) != 0)); - Partition reconstructedCandSig = (nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi)) || (fillCorrBkgs && (nabs(o2::aod::hf_cand_3prong::flagMcMatchRec) != 0)); - Partition reconstructedCandBkg = nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi); - Partition reconstructedCandSigMl = (nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi)) || (fillCorrBkgs && (nabs(o2::aod::hf_cand_3prong::flagMcMatchRec) != 0)); + Partition reconstructedCandSig = (nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi)) || (fillCorrBkgs && (nabs(o2::aod::hf_cand_mc_flag::flagMcMatchRec) != 0)); + Partition reconstructedCandBkg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi); + Partition reconstructedCandSigMl = (nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi)) || (fillCorrBkgs && (nabs(o2::aod::hf_cand_mc_flag::flagMcMatchRec) != 0)); void init(InitContext const&) { diff --git a/PWGHF/TableProducer/treeCreatorDsToKKPi.cxx b/PWGHF/TableProducer/treeCreatorDsToKKPi.cxx index 90dfa44d771..57d484a63b1 100644 --- a/PWGHF/TableProducer/treeCreatorDsToKKPi.cxx +++ b/PWGHF/TableProducer/treeCreatorDsToKKPi.cxx @@ -146,10 +146,10 @@ DECLARE_SOA_TABLE(HfCandDsLites, "AOD", "HFCANDDSLITE", hf_cand::Chi2PCA, full::Centrality, collision::NumContrib, - hf_cand_3prong::FlagMcMatchRec, - hf_cand_3prong::OriginMcRec, - hf_cand_3prong::FlagMcDecayChanRec, - hf_cand_3prong::IsCandidateSwapped, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcRec, + hf_cand_mc_flag::FlagMcDecayChanRec, + hf_cand_mc_flag::IsCandidateSwapped, full::Sign); DECLARE_SOA_TABLE(HfCandDsFulls, "AOD", "HFCANDDSFULL", @@ -219,10 +219,10 @@ DECLARE_SOA_TABLE(HfCandDsFulls, "AOD", "HFCANDDSFULL", full::AbsCos3PiK, hf_cand::Chi2PCA, full::Centrality, - hf_cand_3prong::FlagMcMatchRec, - hf_cand_3prong::OriginMcRec, - hf_cand_3prong::FlagMcDecayChanRec, - hf_cand_3prong::IsCandidateSwapped, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcRec, + hf_cand_mc_flag::FlagMcDecayChanRec, + hf_cand_mc_flag::IsCandidateSwapped, full::Sign); DECLARE_SOA_TABLE(HfCandDsFullEvs, "AOD", "HFCANDDSFULLEV", @@ -241,8 +241,8 @@ DECLARE_SOA_TABLE(HfCandDsFullPs, "AOD", "HFCANDDSFULLP", full::Eta, full::Phi, full::Y, - hf_cand_3prong::FlagMcMatchRec, - hf_cand_3prong::OriginMcGen); + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcGen); } // namespace o2::aod enum Mother : int8_t { @@ -289,18 +289,18 @@ struct HfTreeCreatorDsToKKPi { Filter filterSelectCandidates = aod::hf_sel_candidate_ds::isSelDsToKKPi >= selectionFlagDs || aod::hf_sel_candidate_ds::isSelDsToPiKK >= selectionFlagDs; Filter filterMcGenMatching = - nabs(o2::aod::hf_cand_3prong::flagMcMatchGen) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK) && - (aod::hf_cand_3prong::flagMcDecayChanGen == channelsResonant[Mother::Ds][decayChannel] || - (fillDplusMc && aod::hf_cand_3prong::flagMcDecayChanGen == channelsResonant[Mother::Dplus][decayChannel])); // Do not store Dplus MC if fillDplusMc is false + nabs(o2::aod::hf_cand_mc_flag::flagMcMatchGen) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK) && + (aod::hf_cand_mc_flag::flagMcDecayChanGen == channelsResonant[Mother::Ds][decayChannel] || + (fillDplusMc && aod::hf_cand_mc_flag::flagMcDecayChanGen == channelsResonant[Mother::Dplus][decayChannel])); // Do not store Dplus MC if fillDplusMc is false Partition selectedDsToKKPiCand = aod::hf_sel_candidate_ds::isSelDsToKKPi >= selectionFlagDs; Partition selectedDsToPiKKCand = aod::hf_sel_candidate_ds::isSelDsToPiKK >= selectionFlagDs; - Partition reconstructedCandSig = (nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK) && aod::hf_cand_3prong::flagMcDecayChanRec == channelsResonant[Mother::Ds][decayChannel]) || (fillDplusMc && nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKK) && aod::hf_cand_3prong::flagMcDecayChanRec == channelsResonant[Mother::Dplus][decayChannel]); // Do not store Dplus MC if fillDplusMc is false - Partition reconstructedCandBkg = (nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK) && nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKK)) || - (nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK) && aod::hf_cand_3prong::flagMcDecayChanRec != channelsResonant[Mother::Ds][decayChannel]) || - (nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKK) && aod::hf_cand_3prong::flagMcDecayChanRec != channelsResonant[Mother::Dplus][decayChannel]) || - (!fillDplusMc && nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKK) && aod::hf_cand_3prong::flagMcDecayChanRec == channelsResonant[Mother::Dplus][decayChannel]); + Partition reconstructedCandSig = (nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK) && aod::hf_cand_mc_flag::flagMcDecayChanRec == channelsResonant[Mother::Ds][decayChannel]) || (fillDplusMc && nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKK) && aod::hf_cand_mc_flag::flagMcDecayChanRec == channelsResonant[Mother::Dplus][decayChannel]); // Do not store Dplus MC if fillDplusMc is false + Partition reconstructedCandBkg = (nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK) && nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKK)) || + (nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK) && aod::hf_cand_mc_flag::flagMcDecayChanRec != channelsResonant[Mother::Ds][decayChannel]) || + (nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKK) && aod::hf_cand_mc_flag::flagMcDecayChanRec != channelsResonant[Mother::Dplus][decayChannel]) || + (!fillDplusMc && nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKK) && aod::hf_cand_mc_flag::flagMcDecayChanRec == channelsResonant[Mother::Dplus][decayChannel]); void init(InitContext const&) { diff --git a/PWGHF/TableProducer/treeCreatorDstarToD0Pi.cxx b/PWGHF/TableProducer/treeCreatorDstarToD0Pi.cxx index 059c3ed8f11..9cdbc18b889 100644 --- a/PWGHF/TableProducer/treeCreatorDstarToD0Pi.cxx +++ b/PWGHF/TableProducer/treeCreatorDstarToD0Pi.cxx @@ -153,8 +153,8 @@ DECLARE_SOA_TABLE(HfCandDstLites, "AOD", "HFCANDDSTLITE", full::Phi, full::Y, full::CandidateSelFlag, - hf_cand_dstar::FlagMcMatchRec, - hf_cand_dstar::OriginMcRec, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcRec, full::PtBhadMother) DECLARE_SOA_TABLE(HfCandDstFulls, "AOD", "HFCANDDSTFULL", @@ -226,8 +226,8 @@ DECLARE_SOA_TABLE(HfCandDstFulls, "AOD", "HFCANDDSTFULL", full::Y, full::E, full::CandidateSelFlag, - hf_cand_dstar::FlagMcMatchRec, - hf_cand_dstar::OriginMcRec, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcRec, full::PtBhadMother); DECLARE_SOA_TABLE(HfCandDstFullEvs, "AOD", "HFCANDDSTFULLEV", @@ -245,8 +245,8 @@ DECLARE_SOA_TABLE(HfCandDstFullPs, "AOD", "HFCANDDSTFULLP", full::Eta, full::Phi, full::Y, - hf_cand_dstar::FlagMcMatchGen, - hf_cand_dstar::OriginMcGen, + hf_cand_mc_flag::FlagMcMatchGen, + hf_cand_mc_flag::OriginMcGen, full::PtBhadMother); } // namespace o2::aod @@ -272,10 +272,10 @@ struct HfTreeCreatorDstarToD0Pi { using CandDstarMcGen = soa::Filtered>; Filter filterSelectCandidates = aod::hf_sel_candidate_dstar::isSelDstarToD0Pi == selectionFlagDstarToD0Pi; - Filter filterMcGenMatching = nabs(aod::hf_cand_dstar::flagMcMatchGen) == static_cast(hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi); + Filter filterMcGenMatching = nabs(aod::hf_cand_mc_flag::flagMcMatchGen) == static_cast(hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi); - Partition reconstructedCandSig = nabs(aod::hf_cand_dstar::flagMcMatchRec) == static_cast(hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi); - Partition reconstructedCandBkg = nabs(aod::hf_cand_dstar::flagMcMatchRec) != static_cast(hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi); + Partition reconstructedCandSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi); + Partition reconstructedCandBkg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi); void init(InitContext const&) { diff --git a/PWGHF/TableProducer/treeCreatorXicToPKPi.cxx b/PWGHF/TableProducer/treeCreatorXicToPKPi.cxx index 81543b0e7bf..8cdba2fe442 100644 --- a/PWGHF/TableProducer/treeCreatorXicToPKPi.cxx +++ b/PWGHF/TableProducer/treeCreatorXicToPKPi.cxx @@ -239,13 +239,13 @@ struct HfTreeCreatorXicToPKPi { using CandXicMcGen = soa::Filtered>; Filter filterSelectCandidates = aod::hf_sel_candidate_xic::isSelXicToPKPi >= selectionFlagXic || aod::hf_sel_candidate_xic::isSelXicToPiKP >= selectionFlagXic; - Filter filterMcGenMatching = nabs(o2::aod::hf_cand_3prong::flagMcMatchGen) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::XicToPKPi); + Filter filterMcGenMatching = nabs(o2::aod::hf_cand_mc_flag::flagMcMatchGen) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::XicToPKPi); Partition selectedXicToPKPiCand = aod::hf_sel_candidate_xic::isSelXicToPKPi >= selectionFlagXic; Partition selectedXicToPiKPCand = aod::hf_sel_candidate_xic::isSelXicToPiKP >= selectionFlagXic; - Partition reconstructedCandSig = nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::XicToPKPi); - Partition reconstructedCandBkg = nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::XicToPKPi); + Partition reconstructedCandSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::XicToPKPi); + Partition reconstructedCandBkg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::XicToPKPi); void init(InitContext const&) { diff --git a/PWGHF/TableProducer/treeCreatorXicToXiPiPi.cxx b/PWGHF/TableProducer/treeCreatorXicToXiPiPi.cxx index 3d0500c3690..47748b4c30d 100644 --- a/PWGHF/TableProducer/treeCreatorXicToXiPiPi.cxx +++ b/PWGHF/TableProducer/treeCreatorXicToXiPiPi.cxx @@ -44,7 +44,7 @@ namespace o2::aod { namespace full { -DECLARE_SOA_COLUMN(ParticleFlag, particleFlag, int8_t); //! hf_cand_xic_to_xi_pi_pi::Sign for data, hf_cand_xic_to_xi_pi_pi::FlagMcMatchRec for MC +DECLARE_SOA_COLUMN(ParticleFlag, particleFlag, int8_t); //! hf_cand_xic_to_xi_pi_pi::Sign for data, hf_cand_mc_flag::FlagMcMatchRec for MC DECLARE_SOA_COLUMN(CandidateSelFlag, candidateSelFlag, int); //! Selection flag of candidate (output of candidateSelector) // vertices DECLARE_SOA_COLUMN(Chi2SV, chi2SV, float); //! Chi2 of candidate vertex @@ -82,7 +82,7 @@ DECLARE_SOA_COLUMN(MaxNormalisedDeltaIP, maxNormalisedDeltaIP, float); DECLARE_SOA_TABLE(HfCandXicToXiPiPiLites, "AOD", "HFXICXI2PILITE", full::ParticleFlag, - hf_cand_xic_to_xi_pi_pi::OriginMcRec, + hf_cand_mc_flag::OriginMcRec, full::CandidateSelFlag, full::Y, full::Eta, @@ -119,7 +119,7 @@ DECLARE_SOA_TABLE(HfCandXicToXiPiPiLites, "AOD", "HFXICXI2PILITE", DECLARE_SOA_TABLE(HfCandXicToXiPiPiLiteKfs, "AOD", "HFXICXI2PILITKF", full::ParticleFlag, - hf_cand_xic_to_xi_pi_pi::OriginMcRec, + hf_cand_mc_flag::OriginMcRec, full::CandidateSelFlag, full::Y, full::Eta, @@ -188,7 +188,7 @@ DECLARE_SOA_TABLE(HfCandXicToXiPiPiLiteKfs, "AOD", "HFXICXI2PILITKF", DECLARE_SOA_TABLE(HfCandXicToXiPiPiFulls, "AOD", "HFXICXI2PIFULL", full::ParticleFlag, - hf_cand_xic_to_xi_pi_pi::OriginMcRec, + hf_cand_mc_flag::OriginMcRec, full::CandidateSelFlag, full::Y, full::Eta, @@ -250,7 +250,7 @@ DECLARE_SOA_TABLE(HfCandXicToXiPiPiFulls, "AOD", "HFXICXI2PIFULL", DECLARE_SOA_TABLE(HfCandXicToXiPiPiFullKfs, "AOD", "HFXICXI2PIFULKF", full::ParticleFlag, - hf_cand_xic_to_xi_pi_pi::OriginMcRec, + hf_cand_mc_flag::OriginMcRec, full::CandidateSelFlag, full::Y, full::Eta, @@ -329,9 +329,9 @@ DECLARE_SOA_TABLE(HfCandXicToXiPiPiFullKfs, "AOD", "HFXICXI2PIFULKF", hf_cand_xic_to_xi_pi_pi::DcaXYPi1Xi); DECLARE_SOA_TABLE(HfCandXicToXiPiPiFullPs, "AOD", "HFXICXI2PIFULLP", - hf_cand_xic_to_xi_pi_pi::FlagMcMatchGen, - hf_cand_xic_to_xi_pi_pi::OriginMcGen, - hf_cand::PdgBhadMotherPart, + hf_cand_mc_flag::FlagMcMatchGen, + hf_cand_mc_flag::OriginMcGen, + hf_cand_mc_flag::PdgBhadMotherPart, full::Pt, full::Eta, full::Phi, @@ -363,12 +363,12 @@ struct HfTreeCreatorXicToXiPiPi { using MatchedGenXicToXiPiPi = soa::Filtered>; Filter filterSelectCandidates = aod::hf_sel_candidate_xic::isSelXicToXiPiPi >= selectionFlagXic; - Filter filterGenXicToXiPiPi = (nabs(aod::hf_cand_xic_to_xi_pi_pi::flagMcMatchGen) == static_cast(BIT(aod::hf_cand_xic_to_xi_pi_pi::DecayType::XicToXiPiPi)) || nabs(aod::hf_cand_xic_to_xi_pi_pi::flagMcMatchGen) == static_cast(BIT(aod::hf_cand_xic_to_xi_pi_pi::DecayType::XicToXiResPiToXiPiPi))); + Filter filterGenXicToXiPiPi = (nabs(aod::hf_cand_mc_flag::flagMcMatchGen) == static_cast(BIT(aod::hf_cand_xic_to_xi_pi_pi::DecayType::XicToXiPiPi)) || nabs(aod::hf_cand_mc_flag::flagMcMatchGen) == static_cast(BIT(aod::hf_cand_xic_to_xi_pi_pi::DecayType::XicToXiResPiToXiPiPi))); - Partition recSig = nabs(aod::hf_cand_xic_to_xi_pi_pi::flagMcMatchRec) != int8_t(0); - Partition recBg = nabs(aod::hf_cand_xic_to_xi_pi_pi::flagMcMatchRec) == int8_t(0); - Partition recSigKf = nabs(aod::hf_cand_xic_to_xi_pi_pi::flagMcMatchRec) != int8_t(0); - Partition recBgKf = nabs(aod::hf_cand_xic_to_xi_pi_pi::flagMcMatchRec) == int8_t(0); + Partition recSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != int8_t(0); + Partition recBg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == int8_t(0); + Partition recSigKf = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != int8_t(0); + Partition recBgKf = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == int8_t(0); void init(InitContext const&) { From 27ad18584a311346a900ef4f464e0da7f5a33e80 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Fri, 6 Mar 2026 02:28:57 +0100 Subject: [PATCH 186/347] [PWGEM/Dilepton] update DimuonCut (#15285) --- PWGEM/Dilepton/Core/Dilepton.h | 8 ++++++-- PWGEM/Dilepton/Core/DileptonHadronMPC.h | 8 ++++++-- PWGEM/Dilepton/Core/DileptonMC.h | 8 ++++++-- PWGEM/Dilepton/Core/DimuonCut.cxx | 5 +++++ PWGEM/Dilepton/Core/DimuonCut.h | 5 ++++- PWGEM/Dilepton/Core/SingleTrackQC.h | 8 ++++++-- PWGEM/Dilepton/Core/SingleTrackQCMC.h | 8 ++++++-- 7 files changed, 39 insertions(+), 11 deletions(-) diff --git a/PWGEM/Dilepton/Core/Dilepton.h b/PWGEM/Dilepton/Core/Dilepton.h index da847226252..c4fc90372b1 100644 --- a/PWGEM/Dilepton/Core/Dilepton.h +++ b/PWGEM/Dilepton/Core/Dilepton.h @@ -276,7 +276,10 @@ struct Dilepton { Configurable cfg_min_ncluster_mch{"cfg_min_ncluster_mch", 5, "min ncluster MCH"}; Configurable cfg_max_chi2{"cfg_max_chi2", 1e+6, "max chi2/ndf"}; Configurable cfg_max_chi2mft{"cfg_max_chi2mft", 1e+6, "max chi2/ndf"}; - Configurable cfg_max_matching_chi2_mftmch{"cfg_max_matching_chi2_mftmch", 40, "max chi2 for MFT-MCH matching"}; + // Configurable cfg_max_matching_chi2_mftmch{"cfg_max_matching_chi2_mftmch", 40, "max chi2 for MFT-MCH matching"}; + Configurable cfg_border_pt_for_chi2mchmft{"cfg_border_pt_for_chi2mchmft", 0, "border pt for different max chi2 for MFT-MCH matching"}; + Configurable cfg_max_matching_chi2_mftmch_lowPt{"cfg_max_matching_chi2_mftmch_lowPt", 8, "max chi2 for MFT-MCH matching for low pT"}; + Configurable cfg_max_matching_chi2_mftmch_highPt{"cfg_max_matching_chi2_mftmch_highPt", 40, "max chi2 for MFT-MCH matching for high pT"}; Configurable cfg_max_matching_chi2_mchmid{"cfg_max_matching_chi2_mchmid", 1e+10, "max chi2 for MCH-MID matching"}; Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1e+10, "max dca XY for single track in cm"}; Configurable cfg_min_rabs{"cfg_min_rabs", 17.6, "min Radius at the absorber end"}; @@ -799,7 +802,8 @@ struct Dilepton { fDimuonCut.SetNClustersMCHMID(dimuoncuts.cfg_min_ncluster_mch, 20); fDimuonCut.SetChi2(0.f, dimuoncuts.cfg_max_chi2); fDimuonCut.SetChi2MFT(0.f, dimuoncuts.cfg_max_chi2mft); - fDimuonCut.SetMatchingChi2MCHMFT(0.f, dimuoncuts.cfg_max_matching_chi2_mftmch); + // fDimuonCut.SetMatchingChi2MCHMFT(0.f, dimuoncuts.cfg_max_matching_chi2_mftmch); + fDimuonCut.SetMaxMatchingChi2MCHMFTPtDep([&](float pt) { return (pt < dimuoncuts.cfg_border_pt_for_chi2mchmft ? dimuoncuts.cfg_max_matching_chi2_mftmch_lowPt : dimuoncuts.cfg_max_matching_chi2_mftmch_highPt); }); fDimuonCut.SetMatchingChi2MCHMID(0.f, dimuoncuts.cfg_max_matching_chi2_mchmid); fDimuonCut.SetDCAxy(0.f, dimuoncuts.cfg_max_dcaxy); fDimuonCut.SetRabs(dimuoncuts.cfg_min_rabs, dimuoncuts.cfg_max_rabs); diff --git a/PWGEM/Dilepton/Core/DileptonHadronMPC.h b/PWGEM/Dilepton/Core/DileptonHadronMPC.h index 83797ce3e96..08a607e75e0 100644 --- a/PWGEM/Dilepton/Core/DileptonHadronMPC.h +++ b/PWGEM/Dilepton/Core/DileptonHadronMPC.h @@ -263,7 +263,10 @@ struct DileptonHadronMPC { Configurable cfg_min_ncluster_mch{"cfg_min_ncluster_mch", 8, "min ncluster MCH"}; Configurable cfg_max_chi2{"cfg_max_chi2", 1e+6, "max chi2/ndf"}; Configurable cfg_max_chi2mft{"cfg_max_chi2mft", 1e+6, "max chi2/ndf"}; - Configurable cfg_max_matching_chi2_mftmch{"cfg_max_matching_chi2_mftmch", 40, "max chi2 for MFT-MCH matching"}; + // Configurable cfg_max_matching_chi2_mftmch{"cfg_max_matching_chi2_mftmch", 40, "max chi2 for MFT-MCH matching"}; + Configurable cfg_border_pt_for_chi2mchmft{"cfg_border_pt_for_chi2mchmft", 0, "border pt for different max chi2 for MFT-MCH matching"}; + Configurable cfg_max_matching_chi2_mftmch_lowPt{"cfg_max_matching_chi2_mftmch_lowPt", 8, "max chi2 for MFT-MCH matching for low pT"}; + Configurable cfg_max_matching_chi2_mftmch_highPt{"cfg_max_matching_chi2_mftmch_highPt", 40, "max chi2 for MFT-MCH matching for high pT"}; Configurable cfg_max_matching_chi2_mchmid{"cfg_max_matching_chi2_mchmid", 1e+10, "max chi2 for MCH-MID matching"}; Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1e+10, "max dca XY for single track in cm"}; Configurable cfg_min_rabs{"cfg_min_rabs", 17.6, "min Radius at the absorber end"}; @@ -687,7 +690,8 @@ struct DileptonHadronMPC { fDimuonCut.SetNClustersMCHMID(dimuoncuts.cfg_min_ncluster_mch, 20); fDimuonCut.SetChi2(0.f, dimuoncuts.cfg_max_chi2); fDimuonCut.SetChi2MFT(0.f, dimuoncuts.cfg_max_chi2mft); - fDimuonCut.SetMatchingChi2MCHMFT(0.f, dimuoncuts.cfg_max_matching_chi2_mftmch); + // fDimuonCut.SetMatchingChi2MCHMFT(0.f, dimuoncuts.cfg_max_matching_chi2_mftmch); + fDimuonCut.SetMaxMatchingChi2MCHMFTPtDep([&](float pt) { return (pt < dimuoncuts.cfg_border_pt_for_chi2mchmft ? dimuoncuts.cfg_max_matching_chi2_mftmch_lowPt : dimuoncuts.cfg_max_matching_chi2_mftmch_highPt); }); fDimuonCut.SetMatchingChi2MCHMID(0.f, dimuoncuts.cfg_max_matching_chi2_mchmid); fDimuonCut.SetDCAxy(0.f, dimuoncuts.cfg_max_dcaxy); fDimuonCut.SetRabs(dimuoncuts.cfg_min_rabs, dimuoncuts.cfg_max_rabs); diff --git a/PWGEM/Dilepton/Core/DileptonMC.h b/PWGEM/Dilepton/Core/DileptonMC.h index cbab42900e7..3dbafde4c86 100644 --- a/PWGEM/Dilepton/Core/DileptonMC.h +++ b/PWGEM/Dilepton/Core/DileptonMC.h @@ -278,7 +278,10 @@ struct DileptonMC { Configurable cfg_min_ncluster_mch{"cfg_min_ncluster_mch", 5, "min ncluster MCH"}; Configurable cfg_max_chi2{"cfg_max_chi2", 1e+6, "max chi2/ndf"}; Configurable cfg_max_chi2mft{"cfg_max_chi2mft", 1e+6, "max chi2/ndf"}; - Configurable cfg_max_matching_chi2_mftmch{"cfg_max_matching_chi2_mftmch", 40, "max chi2 for MFT-MCH matching"}; + // Configurable cfg_max_matching_chi2_mftmch{"cfg_max_matching_chi2_mftmch", 40, "max chi2 for MFT-MCH matching"}; + Configurable cfg_border_pt_for_chi2mchmft{"cfg_border_pt_for_chi2mchmft", 0, "border pt for different max chi2 for MFT-MCH matching"}; + Configurable cfg_max_matching_chi2_mftmch_lowPt{"cfg_max_matching_chi2_mftmch_lowPt", 8, "max chi2 for MFT-MCH matching for low pT"}; + Configurable cfg_max_matching_chi2_mftmch_highPt{"cfg_max_matching_chi2_mftmch_highPt", 40, "max chi2 for MFT-MCH matching for high pT"}; Configurable cfg_max_matching_chi2_mchmid{"cfg_max_matching_chi2_mchmid", 1e+10, "max chi2 for MCH-MID matching"}; Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1e+10, "max dca XY for single track in cm"}; Configurable cfg_min_rabs{"cfg_min_rabs", 17.6, "min Radius at the absorber end"}; @@ -807,7 +810,8 @@ struct DileptonMC { fDimuonCut.SetNClustersMCHMID(dimuoncuts.cfg_min_ncluster_mch, 20); fDimuonCut.SetChi2(0.f, dimuoncuts.cfg_max_chi2); fDimuonCut.SetChi2MFT(0.f, dimuoncuts.cfg_max_chi2mft); - fDimuonCut.SetMatchingChi2MCHMFT(0.f, dimuoncuts.cfg_max_matching_chi2_mftmch); + // fDimuonCut.SetMatchingChi2MCHMFT(0.f, dimuoncuts.cfg_max_matching_chi2_mftmch); + fDimuonCut.SetMaxMatchingChi2MCHMFTPtDep([&](float pt) { return (pt < dimuoncuts.cfg_border_pt_for_chi2mchmft ? dimuoncuts.cfg_max_matching_chi2_mftmch_lowPt : dimuoncuts.cfg_max_matching_chi2_mftmch_highPt); }); fDimuonCut.SetMatchingChi2MCHMID(0.f, dimuoncuts.cfg_max_matching_chi2_mchmid); fDimuonCut.SetDCAxy(0.f, dimuoncuts.cfg_max_dcaxy); fDimuonCut.SetRabs(dimuoncuts.cfg_min_rabs, dimuoncuts.cfg_max_rabs); diff --git a/PWGEM/Dilepton/Core/DimuonCut.cxx b/PWGEM/Dilepton/Core/DimuonCut.cxx index c9cded44408..25db52f6052 100644 --- a/PWGEM/Dilepton/Core/DimuonCut.cxx +++ b/PWGEM/Dilepton/Core/DimuonCut.cxx @@ -93,6 +93,11 @@ void DimuonCut::SetMatchingChi2MCHMFT(float min, float max) mMaxMatchingChi2MCHMFT = max; LOG(info) << "Dimuon Cut, set matching chi2 MFT-MCH range: " << mMinMatchingChi2MCHMFT << " - " << mMaxMatchingChi2MCHMFT; } +void DimuonCut::SetMaxMatchingChi2MCHMFTPtDep(std::function PtDepCut) +{ + mMaxMatchingChi2MCHMFTPtDep = PtDepCut; + LOG(info) << "Dimuon Cut, set matching chi2 MFT-MCH range: " << mMaxMatchingChi2MCHMFTPtDep(0.5); +} void DimuonCut::SetMatchingChi2MCHMID(float min, float max) { mMinMatchingChi2MCHMID = min; diff --git a/PWGEM/Dilepton/Core/DimuonCut.h b/PWGEM/Dilepton/Core/DimuonCut.h index 53421b278a9..f474ee4c073 100644 --- a/PWGEM/Dilepton/Core/DimuonCut.h +++ b/PWGEM/Dilepton/Core/DimuonCut.h @@ -208,7 +208,8 @@ class DimuonCut : public TNamed return track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) ? 0.f < track.chi2MFT() / (2.f * track.nClustersMFT() - 5.f) && track.chi2MFT() / (2.f * track.nClustersMFT() - 5.f) < mMaxChi2MFT : true; case DimuonCuts::kMatchingChi2MCHMFT: - return 0.f < track.chi2MatchMCHMFT() && track.chi2MatchMCHMFT() < mMaxMatchingChi2MCHMFT; + // return 0.f < track.chi2MatchMCHMFT() && track.chi2MatchMCHMFT() < mMaxMatchingChi2MCHMFT; + return 0.f < track.chi2MatchMCHMFT() && track.chi2MatchMCHMFT() < mMaxMatchingChi2MCHMFTPtDep(track.pt()); case DimuonCuts::kMatchingChi2MCHMID: return 0.f < track.chi2MatchMCHMID() && track.chi2MatchMCHMID() < mMaxMatchingChi2MCHMID; @@ -259,6 +260,7 @@ class DimuonCut : public TNamed void SetMaxPDCARabsDep(std::function RabsDepCut); void SetMFTHitMap(bool flag, std::vector hitMap); void SetMaxdPtdEtadPhiwrtMCHMID(float reldPtMax, float dEtaMax, float dPhiMax); // this is relevant for global muons + void SetMaxMatchingChi2MCHMFTPtDep(std::function PtDepCut); private: // pair cuts @@ -284,6 +286,7 @@ class DimuonCut : public TNamed float mMinMatchingChi2MCHMFT{0.f}, mMaxMatchingChi2MCHMFT{1e10f}; // max matching chi2 between MCH-MFT float mMinMatchingChi2MCHMID{0.f}, mMaxMatchingChi2MCHMID{1e10f}; // max matching chi2 between MCH-MID std::function mMaxPDCARabsDep{}; // max pdca in xy plane as function of Rabs + std::function mMaxMatchingChi2MCHMFTPtDep{}; // max matching chi2 between MCH-MFT as function of pt float mMinRabs{17.6}, mMaxRabs{89.5}; float mMinDcaXY{0.0f}, mMaxDcaXY{1e10f}; diff --git a/PWGEM/Dilepton/Core/SingleTrackQC.h b/PWGEM/Dilepton/Core/SingleTrackQC.h index c0725cd2c58..0bf1734c7c4 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQC.h @@ -200,7 +200,10 @@ struct SingleTrackQC { Configurable cfg_min_ncluster_mch{"cfg_min_ncluster_mch", 5, "min ncluster MCH"}; Configurable cfg_max_chi2{"cfg_max_chi2", 1e+6, "max chi2/ndf"}; Configurable cfg_max_chi2mft{"cfg_max_chi2mft", 1e+6, "max chi2/ndf"}; - Configurable cfg_max_matching_chi2_mftmch{"cfg_max_matching_chi2_mftmch", 40, "max chi2 for MFT-MCH matching"}; + // Configurable cfg_max_matching_chi2_mftmch{"cfg_max_matching_chi2_mftmch", 40, "max chi2 for MFT-MCH matching"}; + Configurable cfg_border_pt_for_chi2mchmft{"cfg_border_pt_for_chi2mchmft", 0, "border pt for different max chi2 for MFT-MCH matching"}; + Configurable cfg_max_matching_chi2_mftmch_lowPt{"cfg_max_matching_chi2_mftmch_lowPt", 8, "max chi2 for MFT-MCH matching for low pT"}; + Configurable cfg_max_matching_chi2_mftmch_highPt{"cfg_max_matching_chi2_mftmch_highPt", 40, "max chi2 for MFT-MCH matching for high pT"}; Configurable cfg_max_matching_chi2_mchmid{"cfg_max_matching_chi2_mchmid", 1e+10, "max chi2 for MCH-MID matching"}; Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1e+10, "max dca XY for single track in cm"}; Configurable cfg_min_rabs{"cfg_min_rabs", 17.6, "min Radius at the absorber end"}; @@ -535,7 +538,8 @@ struct SingleTrackQC { fDimuonCut.SetNClustersMCHMID(dimuoncuts.cfg_min_ncluster_mch, 20); fDimuonCut.SetChi2(0.f, dimuoncuts.cfg_max_chi2); fDimuonCut.SetChi2MFT(0.f, dimuoncuts.cfg_max_chi2mft); - fDimuonCut.SetMatchingChi2MCHMFT(0.f, dimuoncuts.cfg_max_matching_chi2_mftmch); + // fDimuonCut.SetMatchingChi2MCHMFT(0.f, dimuoncuts.cfg_max_matching_chi2_mftmch); + fDimuonCut.SetMaxMatchingChi2MCHMFTPtDep([&](float pt) { return (pt < dimuoncuts.cfg_border_pt_for_chi2mchmft ? dimuoncuts.cfg_max_matching_chi2_mftmch_lowPt : dimuoncuts.cfg_max_matching_chi2_mftmch_highPt); }); fDimuonCut.SetMatchingChi2MCHMID(0.f, dimuoncuts.cfg_max_matching_chi2_mchmid); fDimuonCut.SetDCAxy(0.f, dimuoncuts.cfg_max_dcaxy); fDimuonCut.SetRabs(dimuoncuts.cfg_min_rabs, dimuoncuts.cfg_max_rabs); diff --git a/PWGEM/Dilepton/Core/SingleTrackQCMC.h b/PWGEM/Dilepton/Core/SingleTrackQCMC.h index daae66bd252..c10f2936601 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQCMC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQCMC.h @@ -208,7 +208,10 @@ struct SingleTrackQCMC { Configurable cfg_min_ncluster_mch{"cfg_min_ncluster_mch", 5, "min ncluster MCH"}; Configurable cfg_max_chi2{"cfg_max_chi2", 1e+6, "max chi2/ndf"}; Configurable cfg_max_chi2mft{"cfg_max_chi2mft", 1e+6, "max chi2/ndf"}; - Configurable cfg_max_matching_chi2_mftmch{"cfg_max_matching_chi2_mftmch", 40, "max chi2 for MFT-MCH matching"}; + // Configurable cfg_max_matching_chi2_mftmch{"cfg_max_matching_chi2_mftmch", 40, "max chi2 for MFT-MCH matching"}; + Configurable cfg_border_pt_for_chi2mchmft{"cfg_border_pt_for_chi2mchmft", 0, "border pt for different max chi2 for MFT-MCH matching"}; + Configurable cfg_max_matching_chi2_mftmch_lowPt{"cfg_max_matching_chi2_mftmch_lowPt", 8, "max chi2 for MFT-MCH matching for low pT"}; + Configurable cfg_max_matching_chi2_mftmch_highPt{"cfg_max_matching_chi2_mftmch_highPt", 40, "max chi2 for MFT-MCH matching for high pT"}; Configurable cfg_max_matching_chi2_mchmid{"cfg_max_matching_chi2_mchmid", 1e+10, "max chi2 for MCH-MID matching"}; Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1e+10, "max dca XY for single track in cm"}; Configurable cfg_min_rabs{"cfg_min_rabs", 17.6, "min Radius at the absorber end"}; @@ -580,7 +583,8 @@ struct SingleTrackQCMC { fDimuonCut.SetNClustersMCHMID(dimuoncuts.cfg_min_ncluster_mch, 20); fDimuonCut.SetChi2(0.f, dimuoncuts.cfg_max_chi2); fDimuonCut.SetChi2MFT(0.f, dimuoncuts.cfg_max_chi2mft); - fDimuonCut.SetMatchingChi2MCHMFT(0.f, dimuoncuts.cfg_max_matching_chi2_mftmch); + // fDimuonCut.SetMatchingChi2MCHMFT(0.f, dimuoncuts.cfg_max_matching_chi2_mftmch); + fDimuonCut.SetMaxMatchingChi2MCHMFTPtDep([&](float pt) { return (pt < dimuoncuts.cfg_border_pt_for_chi2mchmft ? dimuoncuts.cfg_max_matching_chi2_mftmch_lowPt : dimuoncuts.cfg_max_matching_chi2_mftmch_highPt); }); fDimuonCut.SetMatchingChi2MCHMID(0.f, dimuoncuts.cfg_max_matching_chi2_mchmid); fDimuonCut.SetDCAxy(0.f, dimuoncuts.cfg_max_dcaxy); fDimuonCut.SetRabs(dimuoncuts.cfg_min_rabs, dimuoncuts.cfg_max_rabs); From 4e1122941d09edb96579e206ae1153b2025e2d83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Tiek=C3=B6tter?= Date: Fri, 6 Mar 2026 04:17:08 +0100 Subject: [PATCH 187/347] [ALICE3] Pass number of silicon hits to the track and store it. (#15265) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Nicolò Jacazio --- ALICE3/TableProducer/OTF/onTheFlyTracker.cxx | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx b/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx index 14ab69f0dab..c2b14a5c6f4 100644 --- a/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx +++ b/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx @@ -1525,14 +1525,16 @@ struct OnTheFlyTracker { } bool reconstructed = true; + int nTrkHits = 0; if (enablePrimarySmearing && !fastPrimaryTrackerSettings.fastTrackPrimaries) { reconstructed = mSmearer[icfg]->smearTrack(trackParCov, mcParticle.pdgCode(), dNdEta); + nTrkHits = fastTrackerSettings.minSiliconHits; } else if (fastPrimaryTrackerSettings.fastTrackPrimaries) { o2::track::TrackParCov o2Track; o2::upgrade::convertMCParticleToO2Track(mcParticle, o2Track, pdgDB); o2Track.setPID(pdgCodeToPID(mcParticle.pdgCode())); - const int nHits = fastTracker[icfg]->FastTrack(o2Track, trackParCov, dNdEta); - if (nHits < fastPrimaryTrackerSettings.minSiliconHits) { + nTrkHits = fastTracker[icfg]->FastTrack(o2Track, trackParCov, dNdEta); + if (nTrkHits < fastPrimaryTrackerSettings.minSiliconHits) { reconstructed = false; } } @@ -1567,7 +1569,7 @@ struct OnTheFlyTracker { // populate vector with track if we reco-ed it if (reconstructed) { - tracksAlice3.push_back(TrackAlice3{trackParCov, mcParticle.globalIndex(), time, timeResolutionUs, isDecayDaughter}); + tracksAlice3.push_back(TrackAlice3{trackParCov, mcParticle.globalIndex(), time, timeResolutionUs, isDecayDaughter, false, 0, nTrkHits}); } else { ghostTracksAlice3.push_back(TrackAlice3{trackParCov, mcParticle.globalIndex(), time, timeResolutionUs, isDecayDaughter}); } @@ -1927,15 +1929,17 @@ struct OnTheFlyTracker { const float time = (eventCollisionTimeNS + gRandom->Gaus(0., timeResolutionNs)) * nsToMus; bool reconstructed = false; + int nTrkHits = 0; if (enablePrimarySmearing && mcParticle.isPrimary()) { o2::upgrade::convertMCParticleToO2Track(mcParticle, trackParCov, pdgDB); reconstructed = mSmearer[icfg]->smearTrack(trackParCov, mcParticle.pdgCode(), dNdEta); + nTrkHits = fastTrackerSettings.minSiliconHits; } else if (enableSecondarySmearing) { o2::track::TrackParCov perfectTrackParCov; o2::upgrade::convertMCParticleToO2Track(mcParticle, perfectTrackParCov, pdgDB); perfectTrackParCov.setPID(pdgCodeToPID(mcParticle.pdgCode())); - const int nHits = fastTracker[icfg]->FastTrack(perfectTrackParCov, trackParCov, dNdEta); - if (nHits < fastTrackerSettings.minSiliconHits) { + nTrkHits = fastTracker[icfg]->FastTrack(perfectTrackParCov, trackParCov, dNdEta); + if (nTrkHits < fastTrackerSettings.minSiliconHits) { reconstructed = false; } else { reconstructed = true; @@ -1965,7 +1969,7 @@ struct OnTheFlyTracker { } if (reconstructed) { - tracksAlice3.push_back(TrackAlice3{trackParCov, mcParticle.globalIndex(), time, timeResolutionUs, isDecayDaughter}); + tracksAlice3.push_back(TrackAlice3{trackParCov, mcParticle.globalIndex(), time, timeResolutionUs, isDecayDaughter, false, 0, nTrkHits}); } else { ghostTracksAlice3.push_back(TrackAlice3{trackParCov, mcParticle.globalIndex(), time, timeResolutionUs, isDecayDaughter}); } From 7913b7bcbca9adc36cb9640239f8f82bcc7f4d91 Mon Sep 17 00:00:00 2001 From: Marvin Hemmer <53471402+mhemmer-cern@users.noreply.github.com> Date: Fri, 6 Mar 2026 04:54:44 +0100 Subject: [PATCH 188/347] [PWGEM] PhotonMeson: Add converter from EMEvents_004 to PMEvents (#15272) --- .../TableProducer/Converters/CMakeLists.txt | 4 ++ .../Converters/converterEmeventPmevent.cxx | 53 +++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 PWGEM/PhotonMeson/TableProducer/Converters/converterEmeventPmevent.cxx diff --git a/PWGEM/PhotonMeson/TableProducer/Converters/CMakeLists.txt b/PWGEM/PhotonMeson/TableProducer/Converters/CMakeLists.txt index 8ee98eb4d36..63a2f1814c5 100644 --- a/PWGEM/PhotonMeson/TableProducer/Converters/CMakeLists.txt +++ b/PWGEM/PhotonMeson/TableProducer/Converters/CMakeLists.txt @@ -25,3 +25,7 @@ o2physics_add_dpl_workflow(phosid-converter1 PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(converter-emevent-pmevent + SOURCES converterEmeventPmevent.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) diff --git a/PWGEM/PhotonMeson/TableProducer/Converters/converterEmeventPmevent.cxx b/PWGEM/PhotonMeson/TableProducer/Converters/converterEmeventPmevent.cxx new file mode 100644 index 00000000000..9147873fb71 --- /dev/null +++ b/PWGEM/PhotonMeson/TableProducer/Converters/converterEmeventPmevent.cxx @@ -0,0 +1,53 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file converterEmeventPmevent.cxx +/// \author Marvin Hemmer +/// \brief converter for EMEvents_004 to PMEvents + +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" + +#include +#include +#include + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +struct ConverterEmeventPmevent { + Produces pmEvents; + + void process(EMEvents_004 const& collisions) + { + for (const auto& collision : collisions) { + pmEvents( + collision.collisionId(), + collision.runNumber(), + collision.globalBC(), + collision.selection_raw(), + collision.rct_raw(), + collision.timestamp(), + collision.posZ(), + collision.numContrib(), + collision.trackOccupancyInTimeRange(), + collision.ft0cOccupancyInTimeRange()); + } // end of collision loop + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} From a6145bb86d96dc94a4764fc4824a3f296b339918 Mon Sep 17 00:00:00 2001 From: nzardosh Date: Fri, 6 Mar 2026 10:25:05 +0100 Subject: [PATCH 189/347] [PWGJE] adding mcCollision selections for TVX trigger (#15278) --- PWGJE/Core/JetDerivedDataUtilities.h | 60 +++++++++++-------- PWGJE/DataModel/JetReducedData.h | 2 + PWGJE/JetFinders/jetFinder.h | 8 +-- PWGJE/JetFinders/jetFinderHF.h | 2 +- PWGJE/JetFinders/jetFinderHFHFBar.h | 2 +- PWGJE/JetFinders/jetFinderV0.h | 2 +- PWGJE/TableProducer/derivedDataProducer.cxx | 23 +++++-- PWGJE/TableProducer/derivedDataWriter.cxx | 2 +- .../eventwiseConstituentSubtractor.cxx | 4 +- PWGJE/TableProducer/rhoEstimator.cxx | 20 +++---- PWGJE/Tasks/jetHadronRecoil.cxx | 4 +- PWGJE/Tasks/recoilJets.cxx | 2 +- 12 files changed, 78 insertions(+), 53 deletions(-) diff --git a/PWGJE/Core/JetDerivedDataUtilities.h b/PWGJE/Core/JetDerivedDataUtilities.h index 1d342bc8f96..113e240bc2b 100644 --- a/PWGJE/Core/JetDerivedDataUtilities.h +++ b/PWGJE/Core/JetDerivedDataUtilities.h @@ -51,9 +51,9 @@ enum JCollisionSel { selIsGoodZvtxFT0vsPV = 7, selNoCollInTimeRangeStandard = 8, selNoCollInRofStandard = 9, - selUpcSingleGapA = 10, - selUpcSingleGapC = 11, - selUpcDoubleGap = 12, + selUPCSingleGapA = 10, + selUPCSingleGapC = 11, + selUPCDoubleGap = 12, }; enum JCollisionSubGeneratorId { @@ -62,8 +62,9 @@ enum JCollisionSubGeneratorId { }; template -bool commonCollisionSelection(T const& collision, bool skipMBGapEvents = true, bool rctSelection = true, std::string rctLabel = "CBT_hadronPID", bool rejectLimitedAcceptanceRct = false, bool requireZDCRct = false) +bool selectCollision(T const& collision, const std::vector& eventSelectionMaskBits, bool skipMBGapEvents = true, bool rctSelection = true, std::string rctLabel = "CBT_hadronPID", bool rejectLimitedAcceptanceRct = false, bool requireZDCRct = false) { + if (skipMBGapEvents && collision.getSubGeneratorId() == JCollisionSubGeneratorId::mbGap) { return false; } @@ -72,22 +73,6 @@ bool commonCollisionSelection(T const& collision, bool skipMBGapEvents = true, b if (rctSelection && !rctChecker.checkTable(collision)) { // CBT_hadronPID given as default so that TOF is included in RCT selection to benefit from better timing for tracks. Impact of this for inclusive jets should be studied return false; } - return true; -} - -template -bool selectMcCollision(T const& mcCollision, bool skipMBGapEvents = true, bool rctSelection = true, std::string rctLabel = "CBT_hadronPID", bool rejectLimitedAcceptanceRct = false, bool requireZDCRct = false) -{ - return commonCollisionSelection(mcCollision, skipMBGapEvents, rctSelection, rctLabel, rejectLimitedAcceptanceRct, requireZDCRct); -} - -template -bool selectCollision(T const& collision, const std::vector& eventSelectionMaskBits, bool skipMBGapEvents = true, bool rctSelection = true, std::string rctLabel = "CBT_hadronPID", bool rejectLimitedAcceptanceRct = false, bool requireZDCRct = false) -{ - - if (!commonCollisionSelection(collision, skipMBGapEvents, rctSelection, rctLabel, rejectLimitedAcceptanceRct, requireZDCRct)) { - return false; - } if (eventSelectionMaskBits.size() == 0) { return true; } @@ -192,13 +177,13 @@ std::vector initialiseEventSelectionBits(const std::string& eventSelectionM eventSelectionMaskBits.push_back(JCollisionSel::selKINT7); } if (eventSelectionMasksContainSelection(eventSelectionMasks, "selUPCSingleGapA")) { - eventSelectionMaskBits.push_back(JCollisionSel::selUpcSingleGapA); + eventSelectionMaskBits.push_back(JCollisionSel::selUPCSingleGapA); } if (eventSelectionMasksContainSelection(eventSelectionMasks, "selUPCSingleGapC")) { - eventSelectionMaskBits.push_back(JCollisionSel::selUpcSingleGapC); + eventSelectionMaskBits.push_back(JCollisionSel::selUPCSingleGapC); } if (eventSelectionMasksContainSelection(eventSelectionMasks, "selUPCDoubleGap")) { - eventSelectionMaskBits.push_back(JCollisionSel::selUpcDoubleGap); + eventSelectionMaskBits.push_back(JCollisionSel::selUPCDoubleGap); } return eventSelectionMaskBits; @@ -239,14 +224,37 @@ uint16_t setEventSelectionBit(T const& collision, int upcSelectionResult = o2::a SETBIT(bit, JCollisionSel::selNoCollInRofStandard); } if (upcSelectionResult == o2::aod::sgselector::SingleGapA) { - SETBIT(bit, JCollisionSel::selUpcSingleGapA); + SETBIT(bit, JCollisionSel::selUPCSingleGapA); } if (upcSelectionResult == o2::aod::sgselector::SingleGapC) { - SETBIT(bit, JCollisionSel::selUpcSingleGapC); + SETBIT(bit, JCollisionSel::selUPCSingleGapC); } if (upcSelectionResult == o2::aod::sgselector::DoubleGap) { - SETBIT(bit, JCollisionSel::selUpcDoubleGap); + SETBIT(bit, JCollisionSel::selUPCDoubleGap); + } + + return bit; +} + +template +uint16_t setMCEventSelectionBit(T const& bc) +{ + uint16_t bit = 0; + if (bc.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + SETBIT(bit, JCollisionSel::sel8); + SETBIT(bit, JCollisionSel::sel7); + SETBIT(bit, JCollisionSel::selKINT7); + SETBIT(bit, JCollisionSel::selTVX); } + SETBIT(bit, JCollisionSel::selNoTimeFrameBorder); + SETBIT(bit, JCollisionSel::selNoITSROFrameBorder); + SETBIT(bit, JCollisionSel::selNoSameBunchPileup); + SETBIT(bit, JCollisionSel::selIsGoodZvtxFT0vsPV); + SETBIT(bit, JCollisionSel::selNoCollInTimeRangeStandard); + SETBIT(bit, JCollisionSel::selNoCollInRofStandard); + SETBIT(bit, JCollisionSel::selUPCSingleGapA); + SETBIT(bit, JCollisionSel::selUPCSingleGapC); + SETBIT(bit, JCollisionSel::selUPCDoubleGap); return bit; } diff --git a/PWGJE/DataModel/JetReducedData.h b/PWGJE/DataModel/JetReducedData.h index c2a3f95d485..039a1ec46de 100644 --- a/PWGJE/DataModel/JetReducedData.h +++ b/PWGJE/DataModel/JetReducedData.h @@ -219,6 +219,7 @@ DECLARE_SOA_COLUMN(XsectGen, xsectGen, float); DECLARE_SOA_COLUMN(XsectErr, xsectErr, float); DECLARE_SOA_COLUMN(PtHard, ptHard, float); DECLARE_SOA_COLUMN(IsOutlier, isOutlier, bool); +DECLARE_SOA_COLUMN(EventSel, eventSel, uint16_t); DECLARE_SOA_BITMAP_COLUMN(Rct, rct, 32); DECLARE_SOA_COLUMN(GetGeneratorId, getGeneratorId, int); DECLARE_SOA_COLUMN(GetSubGeneratorId, getSubGeneratorId, int); @@ -243,6 +244,7 @@ DECLARE_SOA_TABLE_STAGED(JMcCollisions, "JMCCOLLISION", jmccollision::XsectGen, jmccollision::XsectErr, jmccollision::PtHard, + jmccollision::EventSel, jmccollision::Rct, jmccollision::GetGeneratorId, jmccollision::GetSubGeneratorId, diff --git a/PWGJE/JetFinders/jetFinder.h b/PWGJE/JetFinders/jetFinder.h index 7b2a4d0bc80..d664e5781da 100644 --- a/PWGJE/JetFinders/jetFinder.h +++ b/PWGJE/JetFinders/jetFinder.h @@ -251,7 +251,7 @@ struct JetFinderTask { void processParticleLevelChargedJets(o2::soa::Filtered::iterator const& mcCollision, o2::soa::Filtered const& particles) { - if (!jetderiveddatautilities::selectMcCollision(mcCollision, skipMBGapEvents, applyRCTSelections)) { + if (!jetderiveddatautilities::selectCollision(mcCollision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { return; } inputParticles.clear(); @@ -262,7 +262,7 @@ struct JetFinderTask { void processParticleLevelChargedEvtWiseSubJets(o2::soa::Filtered::iterator const& mcCollision, o2::soa::Filtered const& particles) { - if (!jetderiveddatautilities::selectMcCollision(mcCollision, skipMBGapEvents, applyRCTSelections)) { + if (!jetderiveddatautilities::selectCollision(mcCollision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { return; } inputParticles.clear(); @@ -273,7 +273,7 @@ struct JetFinderTask { void processParticleLevelNeutralJets(o2::soa::Filtered::iterator const& mcCollision, o2::soa::Filtered const& particles) { - if (!jetderiveddatautilities::selectMcCollision(mcCollision, skipMBGapEvents, applyRCTSelections, "CBT_calo")) { + if (!jetderiveddatautilities::selectCollision(mcCollision, eventSelectionBits, skipMBGapEvents, applyRCTSelections, "CBT_calo")) { return; } inputParticles.clear(); @@ -284,7 +284,7 @@ struct JetFinderTask { void processParticleLevelFullJets(o2::soa::Filtered::iterator const& mcCollision, o2::soa::Filtered const& particles) { - if (!jetderiveddatautilities::selectMcCollision(mcCollision, skipMBGapEvents, applyRCTSelections, "CBT_calo")) { + if (!jetderiveddatautilities::selectCollision(mcCollision, eventSelectionBits, skipMBGapEvents, applyRCTSelections, "CBT_calo")) { return; } inputParticles.clear(); diff --git a/PWGJE/JetFinders/jetFinderHF.h b/PWGJE/JetFinders/jetFinderHF.h index 47289f4691f..b5e9a531ff3 100644 --- a/PWGJE/JetFinders/jetFinderHF.h +++ b/PWGJE/JetFinders/jetFinderHF.h @@ -239,7 +239,7 @@ struct JetFinderHFTask { template void analyseMCP(T const& mcCollision, U const& particles, V const& candidate, M& jetsTableInput, N& constituentsTableInput, int jetTypeParticleLevel, float minJetPt, float maxJetPt) { - if (!jetderiveddatautilities::selectMcCollision(mcCollision, skipMBGapEvents, applyRCTSelections)) { + if (!jetderiveddatautilities::selectCollision(mcCollision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { return; } diff --git a/PWGJE/JetFinders/jetFinderHFHFBar.h b/PWGJE/JetFinders/jetFinderHFHFBar.h index 28d3a4000bf..77635798346 100644 --- a/PWGJE/JetFinders/jetFinderHFHFBar.h +++ b/PWGJE/JetFinders/jetFinderHFHFBar.h @@ -250,7 +250,7 @@ struct JetFinderHFHFBarTask { return; } } - if (!jetderiveddatautilities::selectMcCollision(mcCollision, skipMBGapEvents, applyRCTSelections)) { + if (!jetderiveddatautilities::selectCollision(mcCollision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { return; } diff --git a/PWGJE/JetFinders/jetFinderV0.h b/PWGJE/JetFinders/jetFinderV0.h index 8314173e0e3..2b9b1d76dbd 100644 --- a/PWGJE/JetFinders/jetFinderV0.h +++ b/PWGJE/JetFinders/jetFinderV0.h @@ -206,7 +206,7 @@ struct JetFinderV0Task { void analyseMCP(T const& mcCollision, U const& particles, V const& candidates, int jetTypeParticleLevel, float minJetPt, float maxJetPt) { - if (!jetderiveddatautilities::selectMcCollision(mcCollision, skipMBGapEvents, applyRCTSelections)) { + if (!jetderiveddatautilities::selectCollision(mcCollision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { return; } diff --git a/PWGJE/TableProducer/derivedDataProducer.cxx b/PWGJE/TableProducer/derivedDataProducer.cxx index e21627baea2..7182fbcec05 100644 --- a/PWGJE/TableProducer/derivedDataProducer.cxx +++ b/PWGJE/TableProducer/derivedDataProducer.cxx @@ -193,6 +193,7 @@ struct JetDerivedDataProducerTask { std::vector trackMCSelection; + std::vector bcSelMapping; std::vector bcRctMapping; ctpRateFetcher rateFetcher; @@ -267,11 +268,14 @@ struct JetDerivedDataProducerTask { void processBunchCrossings(soa::Join const& bcs) { + bcSelMapping.clear(); + bcSelMapping.resize(bcs.size(), ~uint16_t{0}); bcRctMapping.clear(); bcRctMapping.resize(bcs.size(), ~uint32_t{0}); for (const auto& bc : bcs) { products.jBCsTable(bc.runNumber(), bc.globalBC(), bc.triggerMask(), bc.timestamp(), bc.alias_raw(), bc.selection_raw(), bc.rct_raw()); products.jBCParentIndexTable(bc.globalIndex()); + bcSelMapping[bc.globalIndex()] = jetderiveddatautilities::setMCEventSelectionBit(bc); bcRctMapping[bc.globalIndex()] = bc.rct_raw(); } } @@ -279,6 +283,8 @@ struct JetDerivedDataProducerTask { void processBunchCrossingsWithoutSels(soa::Join const& bcs) { + bcSelMapping.clear(); + bcSelMapping.resize(bcs.size(), ~uint16_t{0}); bcRctMapping.clear(); bcRctMapping.resize(bcs.size(), ~uint32_t{0}); for (const auto& bc : bcs) { @@ -377,64 +383,73 @@ struct JetDerivedDataProducerTask { void processMcCollisions(soa::Join::iterator const& mcCollision) { + uint32_t selDecision = ~uint16_t{0}; uint32_t rctDecision = ~uint32_t{0}; int32_t bcId = -1; if (!config.isMCGenOnly) { bcId = mcCollision.bcId(); + selDecision = bcSelMapping[bcId]; rctDecision = bcRctMapping[bcId]; } else { products.jBCsTable(-1, -1, -1, -1, ~uint32_t{0}, ~uint32_t{0}, ~uint32_t{0}); bcId = products.jBCsTable.lastIndex(); } - products.jMcCollisionsTable(bcId, mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), mcCollision.multMCFV0A(), mcCollision.multMCFT0A(), mcCollision.multMCFT0C(), mcCollision.centFT0M(), mcCollision.weight(), mcCollision.accepted(), mcCollision.attempted(), mcCollision.xsectGen(), mcCollision.xsectErr(), mcCollision.ptHard(), rctDecision, mcCollision.getGeneratorId(), mcCollision.getSubGeneratorId(), mcCollision.getSourceId(), mcCollision.impactParameter(), mcCollision.eventPlaneAngle()); + products.jMcCollisionsTable(bcId, mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), mcCollision.multMCFV0A(), mcCollision.multMCFT0A(), mcCollision.multMCFT0C(), mcCollision.centFT0M(), mcCollision.weight(), mcCollision.accepted(), mcCollision.attempted(), mcCollision.xsectGen(), mcCollision.xsectErr(), mcCollision.ptHard(), selDecision, rctDecision, mcCollision.getGeneratorId(), mcCollision.getSubGeneratorId(), mcCollision.getSourceId(), mcCollision.impactParameter(), mcCollision.eventPlaneAngle()); products.jMcCollisionsParentIndexTable(mcCollision.globalIndex()); } PROCESS_SWITCH(JetDerivedDataProducerTask, processMcCollisions, "produces derived MC collision table", false); void processMcCollisionsWithoutCentralityAndMultiplicity(soa::Join::iterator const& mcCollision) { + + uint32_t selDecision = ~uint16_t{0}; uint32_t rctDecision = ~uint32_t{0}; int32_t bcId = -1; if (!config.isMCGenOnly) { bcId = mcCollision.bcId(); + selDecision = bcSelMapping[bcId]; rctDecision = bcRctMapping[bcId]; } else { products.jBCsTable(-1, -1, -1, -1, ~uint32_t{0}, ~uint32_t{0}, ~uint32_t{0}); bcId = products.jBCsTable.lastIndex(); } - products.jMcCollisionsTable(bcId, mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), -1.0, -1.0, -1.0, -1.0, mcCollision.weight(), mcCollision.accepted(), mcCollision.attempted(), mcCollision.xsectGen(), mcCollision.xsectErr(), mcCollision.ptHard(), rctDecision, mcCollision.getGeneratorId(), mcCollision.getSubGeneratorId(), mcCollision.getSourceId(), mcCollision.impactParameter(), mcCollision.eventPlaneAngle()); + products.jMcCollisionsTable(bcId, mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), -1.0, -1.0, -1.0, -1.0, mcCollision.weight(), mcCollision.accepted(), mcCollision.attempted(), mcCollision.xsectGen(), mcCollision.xsectErr(), mcCollision.ptHard(), selDecision, rctDecision, mcCollision.getGeneratorId(), mcCollision.getSubGeneratorId(), mcCollision.getSourceId(), mcCollision.impactParameter(), mcCollision.eventPlaneAngle()); products.jMcCollisionsParentIndexTable(mcCollision.globalIndex()); } PROCESS_SWITCH(JetDerivedDataProducerTask, processMcCollisionsWithoutCentralityAndMultiplicity, "produces derived MC collision table without centraility and multiplicity", false); void processMcCollisionsWithoutXsection(soa::Join::iterator const& mcCollision) { + uint32_t selDecision = ~uint16_t{0}; uint32_t rctDecision = ~uint32_t{0}; int32_t bcId = -1; if (!config.isMCGenOnly) { bcId = mcCollision.bcId(); + selDecision = bcSelMapping[bcId]; rctDecision = bcRctMapping[bcId]; } else { products.jBCsTable(-1, -1, -1, -1, ~uint32_t{0}, ~uint32_t{0}, ~uint32_t{0}); bcId = products.jBCsTable.lastIndex(); } - products.jMcCollisionsTable(bcId, mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), mcCollision.multMCFV0A(), mcCollision.multMCFT0A(), mcCollision.multMCFT0C(), mcCollision.centFT0M(), mcCollision.weight(), 1, 1, 1.0, 1.0, 999.0, rctDecision, mcCollision.getGeneratorId(), mcCollision.getSubGeneratorId(), mcCollision.getSourceId(), mcCollision.impactParameter(), mcCollision.eventPlaneAngle()); + products.jMcCollisionsTable(bcId, mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), mcCollision.multMCFV0A(), mcCollision.multMCFT0A(), mcCollision.multMCFT0C(), mcCollision.centFT0M(), mcCollision.weight(), 1, 1, 1.0, 1.0, 999.0, selDecision, rctDecision, mcCollision.getGeneratorId(), mcCollision.getSubGeneratorId(), mcCollision.getSourceId(), mcCollision.impactParameter(), mcCollision.eventPlaneAngle()); products.jMcCollisionsParentIndexTable(mcCollision.globalIndex()); } PROCESS_SWITCH(JetDerivedDataProducerTask, processMcCollisionsWithoutXsection, "produces derived MC collision table without cross section information", false); void processMcCollisionsWithoutCentralityAndMultiplicityAndXsection(aod::McCollision const& mcCollision) { + uint32_t selDecision = ~uint16_t{0}; uint32_t rctDecision = ~uint32_t{0}; int32_t bcId = -1; if (!config.isMCGenOnly) { bcId = mcCollision.bcId(); + selDecision = bcSelMapping[bcId]; rctDecision = bcRctMapping[bcId]; } else { products.jBCsTable(-1, -1, -1, -1, ~uint32_t{0}, ~uint32_t{0}, ~uint32_t{0}); bcId = products.jBCsTable.lastIndex(); } - products.jMcCollisionsTable(bcId, mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), -1.0, -1.0, -1.0, -1.0, mcCollision.weight(), 1, 1, 1.0, 1.0, 999.0, rctDecision, mcCollision.getGeneratorId(), mcCollision.getSubGeneratorId(), mcCollision.getSourceId(), mcCollision.impactParameter(), mcCollision.eventPlaneAngle()); + products.jMcCollisionsTable(bcId, mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), -1.0, -1.0, -1.0, -1.0, mcCollision.weight(), 1, 1, 1.0, 1.0, 999.0, selDecision, rctDecision, mcCollision.getGeneratorId(), mcCollision.getSubGeneratorId(), mcCollision.getSourceId(), mcCollision.impactParameter(), mcCollision.eventPlaneAngle()); products.jMcCollisionsParentIndexTable(mcCollision.globalIndex()); } PROCESS_SWITCH(JetDerivedDataProducerTask, processMcCollisionsWithoutCentralityAndMultiplicityAndXsection, "produces derived MC collision table without centrality, multiplicity and cross section information", false); diff --git a/PWGJE/TableProducer/derivedDataWriter.cxx b/PWGJE/TableProducer/derivedDataWriter.cxx index 61bbefed01a..e5676af0d58 100644 --- a/PWGJE/TableProducer/derivedDataWriter.cxx +++ b/PWGJE/TableProducer/derivedDataWriter.cxx @@ -685,7 +685,7 @@ struct JetDerivedDataWriter { mcCollisionMapping.resize(mcCollisions.size(), -1); for (auto const& mcCollision : mcCollisions) { if (mcCollision.isMcCollisionSelected()) { - products.storedJMcCollisionsTable(bcMapping[mcCollision.bcId()], mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), mcCollision.multFV0A(), mcCollision.multFT0A(), mcCollision.multFT0C(), mcCollision.centFT0M(), mcCollision.weight(), mcCollision.accepted(), mcCollision.attempted(), mcCollision.xsectGen(), mcCollision.xsectErr(), mcCollision.ptHard(), mcCollision.rct_raw(), mcCollision.getGeneratorId(), mcCollision.getSubGeneratorId(), mcCollision.getSourceId(), mcCollision.impactParameter(), mcCollision.eventPlaneAngle()); + products.storedJMcCollisionsTable(bcMapping[mcCollision.bcId()], mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), mcCollision.multFV0A(), mcCollision.multFT0A(), mcCollision.multFT0C(), mcCollision.centFT0M(), mcCollision.weight(), mcCollision.accepted(), mcCollision.attempted(), mcCollision.xsectGen(), mcCollision.xsectErr(), mcCollision.ptHard(), mcCollision.eventSel(), mcCollision.rct_raw(), mcCollision.getGeneratorId(), mcCollision.getSubGeneratorId(), mcCollision.getSourceId(), mcCollision.impactParameter(), mcCollision.eventPlaneAngle()); products.storedJMcCollisionsParentIndexTable(mcCollision.mcCollisionId()); mcCollisionMapping[mcCollision.globalIndex()] = products.storedJMcCollisionsTable.lastIndex(); } diff --git a/PWGJE/TableProducer/eventwiseConstituentSubtractor.cxx b/PWGJE/TableProducer/eventwiseConstituentSubtractor.cxx index acb7a092ce2..33cafe0db0c 100644 --- a/PWGJE/TableProducer/eventwiseConstituentSubtractor.cxx +++ b/PWGJE/TableProducer/eventwiseConstituentSubtractor.cxx @@ -141,7 +141,7 @@ struct eventWiseConstituentSubtractorTask { template void analyseHFMc(T const& mcCollision, U const& particles, V const& candidates, M& particleSubTable) { - if (!jetderiveddatautilities::selectMcCollision(mcCollision, skipMBGapEvents, applyRCTSelections) || std::abs(mcCollision.posZ()) > vertexZCut) { + if (!jetderiveddatautilities::selectCollision(mcCollision, eventSelectionBits, skipMBGapEvents, applyRCTSelections) || std::abs(mcCollision.posZ()) > vertexZCut) { return; } for (auto& candidate : candidates) { @@ -178,7 +178,7 @@ struct eventWiseConstituentSubtractorTask { void processMcCollisions(soa::Join::iterator const& mcCollision, soa::Filtered const& particles) { - if (!jetderiveddatautilities::selectMcCollision(mcCollision, skipMBGapEvents, applyRCTSelections) || std::abs(mcCollision.posZ()) > vertexZCut) { + if (!jetderiveddatautilities::selectCollision(mcCollision, eventSelectionBits, skipMBGapEvents, applyRCTSelections) || std::abs(mcCollision.posZ()) > vertexZCut) { return; } inputParticles.clear(); diff --git a/PWGJE/TableProducer/rhoEstimator.cxx b/PWGJE/TableProducer/rhoEstimator.cxx index fb14c472885..6f94e1e8785 100644 --- a/PWGJE/TableProducer/rhoEstimator.cxx +++ b/PWGJE/TableProducer/rhoEstimator.cxx @@ -223,7 +223,7 @@ struct RhoEstimatorTask { void processChargedMcCollisions(aod::JetMcCollision const& mcCollision, soa::Filtered const& particles) { - if (!jetderiveddatautilities::selectMcCollision(mcCollision, config.skipMBGapEvents, config.applyRCTSelections) || std::abs(mcCollision.posZ()) > config.vertexZCut) { + if (!jetderiveddatautilities::selectCollision(mcCollision, eventSelectionBits, config.skipMBGapEvents, config.applyRCTSelections) || std::abs(mcCollision.posZ()) > config.vertexZCut) { rhoChargedMcTable(0.0, 0.0); return; } @@ -253,7 +253,7 @@ struct RhoEstimatorTask { void processD0McCollisions(aod::JetMcCollision const& mcCollision, soa::Filtered const& particles, aod::CandidatesD0MCP const& candidates) { for (auto& candidate : candidates) { - if (!jetderiveddatautilities::selectMcCollision(mcCollision, config.skipMBGapEvents, config.applyRCTSelections) || std::abs(mcCollision.posZ()) > config.vertexZCut) { + if (!jetderiveddatautilities::selectCollision(mcCollision, eventSelectionBits, config.skipMBGapEvents, config.applyRCTSelections) || std::abs(mcCollision.posZ()) > config.vertexZCut) { rhoD0McTable(0.0, 0.0); continue; } @@ -286,7 +286,7 @@ struct RhoEstimatorTask { { for (auto& candidate : candidates) { - if (!jetderiveddatautilities::selectMcCollision(mcCollision, config.skipMBGapEvents, config.applyRCTSelections) || std::abs(mcCollision.posZ()) > config.vertexZCut) { + if (!jetderiveddatautilities::selectCollision(mcCollision, eventSelectionBits, config.skipMBGapEvents, config.applyRCTSelections) || std::abs(mcCollision.posZ()) > config.vertexZCut) { rhoDplusMcTable(0.0, 0.0); continue; } @@ -318,7 +318,7 @@ struct RhoEstimatorTask { void processDsMcCollisions(aod::JetMcCollision const& mcCollision, soa::Filtered const& particles, aod::CandidatesDsMCP const& candidates) { for (auto& candidate : candidates) { - if (!jetderiveddatautilities::selectMcCollision(mcCollision, config.skipMBGapEvents, config.applyRCTSelections) || std::abs(mcCollision.posZ()) > config.vertexZCut) { + if (!jetderiveddatautilities::selectCollision(mcCollision, eventSelectionBits, config.skipMBGapEvents, config.applyRCTSelections) || std::abs(mcCollision.posZ()) > config.vertexZCut) { rhoDsMcTable(0.0, 0.0); continue; } @@ -350,7 +350,7 @@ struct RhoEstimatorTask { void processDstarMcCollisions(aod::JetMcCollision const& mcCollision, soa::Filtered const& particles, aod::CandidatesDstarMCP const& candidates) { for (auto& candidate : candidates) { - if (!jetderiveddatautilities::selectMcCollision(mcCollision, config.skipMBGapEvents, config.applyRCTSelections) || std::abs(mcCollision.posZ()) > config.vertexZCut) { + if (!jetderiveddatautilities::selectCollision(mcCollision, eventSelectionBits, config.skipMBGapEvents, config.applyRCTSelections) || std::abs(mcCollision.posZ()) > config.vertexZCut) { rhoDstarMcTable(0.0, 0.0); continue; } @@ -382,7 +382,7 @@ struct RhoEstimatorTask { void processLcMcCollisions(aod::JetMcCollision const& mcCollision, soa::Filtered const& particles, aod::CandidatesLcMCP const& candidates) { for (auto& candidate : candidates) { - if (!jetderiveddatautilities::selectMcCollision(mcCollision, config.skipMBGapEvents, config.applyRCTSelections) || std::abs(mcCollision.posZ()) > config.vertexZCut) { + if (!jetderiveddatautilities::selectCollision(mcCollision, eventSelectionBits, config.skipMBGapEvents, config.applyRCTSelections) || std::abs(mcCollision.posZ()) > config.vertexZCut) { rhoLcMcTable(0.0, 0.0); continue; } @@ -414,7 +414,7 @@ struct RhoEstimatorTask { void processB0McCollisions(aod::JetMcCollision const& mcCollision, soa::Filtered const& particles, aod::CandidatesB0MCP const& candidates) { for (auto& candidate : candidates) { - if (!jetderiveddatautilities::selectMcCollision(mcCollision, config.skipMBGapEvents, config.applyRCTSelections) || std::abs(mcCollision.posZ()) > config.vertexZCut) { + if (!jetderiveddatautilities::selectCollision(mcCollision, eventSelectionBits, config.skipMBGapEvents, config.applyRCTSelections) || std::abs(mcCollision.posZ()) > config.vertexZCut) { rhoB0McTable(0.0, 0.0); continue; } @@ -446,7 +446,7 @@ struct RhoEstimatorTask { void processBplusMcCollisions(aod::JetMcCollision const& mcCollision, soa::Filtered const& particles, aod::CandidatesBplusMCP const& candidates) { for (auto& candidate : candidates) { - if (!jetderiveddatautilities::selectMcCollision(mcCollision, config.skipMBGapEvents, config.applyRCTSelections) || std::abs(mcCollision.posZ()) > config.vertexZCut) { + if (!jetderiveddatautilities::selectCollision(mcCollision, eventSelectionBits, config.skipMBGapEvents, config.applyRCTSelections) || std::abs(mcCollision.posZ()) > config.vertexZCut) { rhoBplusMcTable(0.0, 0.0); continue; } @@ -478,7 +478,7 @@ struct RhoEstimatorTask { void processXicToXiPiPiMcCollisions(aod::JetMcCollision const& mcCollision, soa::Filtered const& particles, aod::CandidatesXicToXiPiPiMCP const& candidates) { for (auto& candidate : candidates) { - if (!jetderiveddatautilities::selectMcCollision(mcCollision, config.skipMBGapEvents, config.applyRCTSelections) || std::abs(mcCollision.posZ()) > config.vertexZCut) { + if (!jetderiveddatautilities::selectCollision(mcCollision, eventSelectionBits, config.skipMBGapEvents, config.applyRCTSelections) || std::abs(mcCollision.posZ()) > config.vertexZCut) { rhoXicToXiPiPiMcTable(0.0, 0.0); continue; } @@ -510,7 +510,7 @@ struct RhoEstimatorTask { void processDielectronMcCollisions(aod::JetMcCollision const& mcCollision, soa::Filtered const& particles, aod::CandidatesDielectronMCP const& candidates) { for (auto& candidate : candidates) { - if (!jetderiveddatautilities::selectMcCollision(mcCollision, config.skipMBGapEvents, config.applyRCTSelections) || std::abs(mcCollision.posZ()) > config.vertexZCut) { + if (!jetderiveddatautilities::selectCollision(mcCollision, eventSelectionBits, config.skipMBGapEvents, config.applyRCTSelections) || std::abs(mcCollision.posZ()) > config.vertexZCut) { rhoDielectronMcTable(0.0, 0.0); continue; } diff --git a/PWGJE/Tasks/jetHadronRecoil.cxx b/PWGJE/Tasks/jetHadronRecoil.cxx index 94044235003..a16770e19f1 100644 --- a/PWGJE/Tasks/jetHadronRecoil.cxx +++ b/PWGJE/Tasks/jetHadronRecoil.cxx @@ -960,7 +960,7 @@ struct JetHadronRecoil { if (std::abs(mccollision.posZ()) > vertexZCut) { return; } - if (!jetderiveddatautilities::selectMcCollision(mccollision, skipMBGapEvents, applyRCTSelections)) { + if (!jetderiveddatautilities::selectCollision(mccollision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { return; } if (mccollision.ptHard() < pTHatMinEvent) { @@ -990,7 +990,7 @@ struct JetHadronRecoil { if (std::abs(mccollision.posZ()) > vertexZCut) { return; } - if (!jetderiveddatautilities::selectMcCollision(mccollision, skipMBGapEvents, applyRCTSelections)) { + if (!jetderiveddatautilities::selectCollision(mccollision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { return; } if (mccollision.ptHard() < pTHatMinEvent) { diff --git a/PWGJE/Tasks/recoilJets.cxx b/PWGJE/Tasks/recoilJets.cxx index 378c42875ed..08271300538 100644 --- a/PWGJE/Tasks/recoilJets.cxx +++ b/PWGJE/Tasks/recoilJets.cxx @@ -2663,7 +2663,7 @@ struct RecoilJets { template bool skipMCEvent(const Collision& coll) { - return !jetderiveddatautilities::selectMcCollision(coll, ev.skipMBGapEvents, rct.enable, rct.label, rct.rejectLimitedAcceptance, rct.requireZDC); + return !jetderiveddatautilities::selectCollision(coll, eventSelectionBits, ev.skipMBGapEvents, rct.enable, rct.label, rct.rejectLimitedAcceptance, rct.requireZDC); } template From bd1005d78e04ec98bc84948b606d6cbe591fcb49 Mon Sep 17 00:00:00 2001 From: skundu692 <86804743+skundu692@users.noreply.github.com> Date: Fri, 6 Mar 2026 11:10:15 +0100 Subject: [PATCH 190/347] [PWGLF] Add new process function for spin correlation to study mixing in data and MC (#15280) --- .../Strangeness/lambdaspincorrderived.cxx | 722 ++++++++++++++++-- 1 file changed, 672 insertions(+), 50 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx b/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx index 51e13a779f1..07fbd5434f4 100644 --- a/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx +++ b/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx @@ -202,12 +202,26 @@ struct lambdaspincorrderived { Configurable ConfWeightPathLAL2{"ConfWeightPathLAL2", "Users/s/skundu/My/Object/spincorr/cent010LL", "Weight path 2"}; Configurable ConfWeightPathALL2{"ConfWeightPathALL2", "Users/s/skundu/My/Object/spincorr/cent010LL", "Weight path 2"}; - // event sel///////// - Configurable maxMatchesPerPair{"maxMatchesPerPair", 25, "Max mixed candidates per (t1,t2)"}; + // Mixing ///////// + + Configurable cfgV5NeighborPt{"cfgV5NeighborPt", 0, "v5: neighbor bins in pT (use symmetric ±N, edge-safe)"}; + Configurable cfgV5NeighborEta{"cfgV5NeighborEta", 0, "v5: neighbor bins in eta (use symmetric ±N, edge-safe)"}; + Configurable cfgV5NeighborPhi{"cfgV5NeighborPhi", 0, "v5: neighbor bins in phi (use symmetric ±N, periodic wrap)"}; + Configurable cfgV5MaxMatches{"cfgV5MaxMatches", 50, "v5: max ME replacements per SE pair (after all cuts)"}; + Configurable cfgMixSeed{"cfgMixSeed", 0xdecafbadULL, "RNG seed for downsampling matches (deterministic)"}; Configurable centMin{"centMin", 0, "Minimum Centrality"}; Configurable centMax{"centMax", 80, "Maximum Centrality"}; Configurable rngSeed{"rngSeed", 12345, "Seed for random mixing (reproducible)"}; std::mt19937 rng{12345}; + Configurable nEvtMixing{"nEvtMixing", 10, "Number of events to mix"}; + ConfigurableAxis CfgVtxBins{"CfgVtxBins", {VARIABLE_WIDTH, -10, -8, -6, -4, -2, 0, 2, 4, 6, 8, 10}, "Mixing bins - z-vertex"}; + ConfigurableAxis CfgMultBins{"CfgMultBins", {VARIABLE_WIDTH, 0, 110}, "Mixing bins - centrality"}; + Configurable etaMix{"etaMix", 0.1, "Eta cut on event mixing"}; + Configurable ptMix{"ptMix", 0.1, "Pt cut on event mixing"}; + Configurable phiMix{"phiMix", 0.1, "Phi cut on event mixing"}; + Configurable massMix{"massMix", 0.0028, "Masscut on event mixing"}; + Configurable userapidity{"userapidity", 1, "Use Rapidity for mixing"}; + // Lambda selection //////////// Configurable harmonic{"harmonic", 1, "Harmonic phi"}; Configurable harmonicDphi{"harmonicDphi", 2, "Harmonic delta phi"}; @@ -228,17 +242,11 @@ struct lambdaspincorrderived { Configurable MassMin{"MassMin", 1.09, "V0 Mass minimum"}; Configurable MassMax{"MassMax", 1.14, "V0 Mass maximum"}; Configurable rapidity{"rapidity", 0.5, "Rapidity cut on lambda"}; + Configurable v0etaMixBuffer{"v0etaMixBuffer", 0.8, "Eta cut on mix event buffer"}; Configurable v0eta{"v0eta", 0.8, "Eta cut on lambda"}; // Event Mixing Configurable cosDef{"cosDef", 1, "Defination of cos"}; - Configurable nEvtMixing{"nEvtMixing", 10, "Number of events to mix"}; - ConfigurableAxis CfgVtxBins{"CfgVtxBins", {VARIABLE_WIDTH, -10, -8, -6, -4, -2, 0, 2, 4, 6, 8, 10}, "Mixing bins - z-vertex"}; - ConfigurableAxis CfgMultBins{"CfgMultBins", {VARIABLE_WIDTH, 0, 110}, "Mixing bins - centrality"}; - Configurable etaMix{"etaMix", 0.1, "Eta cut on event mixing"}; - Configurable ptMix{"ptMix", 0.1, "Pt cut on event mixing"}; - Configurable phiMix{"phiMix", 0.1, "Phi cut on event mixing"}; - Configurable massMix{"massMix", 0.0028, "Masscut on event mixing"}; ConfigurableAxis ax_dphi_h{"ax_dphi_h", {VARIABLE_WIDTH, 0.0, 2.0 * TMath::Pi()}, "Δφ_h"}; ConfigurableAxis ax_deta{"ax_deta", {VARIABLE_WIDTH, -1.0, 1.0}, "Δη"}; @@ -402,26 +410,37 @@ struct lambdaspincorrderived { } template - bool checkKinematics(T1 const& candidate1, T2 const& candidate2) + bool checkKinematics(T1 const& c1, T2 const& c2) { - if (candidate1.v0Status() != candidate2.v0Status()) { + if (c1.v0Status() != c2.v0Status()) { return false; } - if (std::abs(candidate1.lambdaPt() - candidate2.lambdaPt()) > ptMix) { + + if (std::abs(c1.lambdaPt() - c2.lambdaPt()) > ptMix) { return false; } - if (std::abs(candidate1.lambdaEta() - candidate2.lambdaEta()) > etaMix) { - return false; + + if (!userapidity) { + if (std::abs(c1.lambdaEta() - c2.lambdaEta()) > etaMix) { + return false; + } + } else { + const auto l1 = ROOT::Math::PtEtaPhiMVector(c1.lambdaPt(), c1.lambdaEta(), c1.lambdaPhi(), c1.lambdaMass()); + const auto l2 = ROOT::Math::PtEtaPhiMVector(c2.lambdaPt(), c2.lambdaEta(), c2.lambdaPhi(), c2.lambdaMass()); + if (std::abs(l1.Rapidity() - l2.Rapidity()) > etaMix) { // etaMix used as Δy + return false; + } } - if (std::abs(RecoDecay::constrainAngle(RecoDecay::constrainAngle(candidate1.lambdaPhi(), 0.f, harmonic) - RecoDecay::constrainAngle(candidate2.lambdaPhi(), 0.f, harmonic), -TMath::Pi(), 1)) > phiMix) { + + const float dphi = deltaPhiMinusPiToPi((float)c1.lambdaPhi(), (float)c2.lambdaPhi()); + if (std::abs(dphi) > phiMix) { return false; } - /*if (std::abs(RecoDecay::constrainAngle(candidate1.lambdaPhi(), 0.0F, harmonic) - RecoDecay::constrainAngle(candidate2.lambdaPhi(), 0.0F, harmonic)) > phiMix) { - return false; - }*/ - if (std::abs(candidate1.lambdaMass() - candidate2.lambdaMass()) > massMix) { + + if (std::abs(c1.lambdaMass() - c2.lambdaMass()) > massMix) { return false; } + return true; } @@ -537,8 +556,13 @@ struct lambdaspincorrderived { mixpairweight = 1.0; histos.fill(HIST("hPtYSame"), particle1.Pt(), particle1.Rapidity(), mixpairweight); if (tag1 == 0 && tag2 == 0) { - histos.fill(HIST("SE_LL"), dphi1, deta1, pt1, mixpairweight); - histos.fill(HIST("SE_LL2"), dphi2, deta2, pt2, mixpairweight); + if (!userapidity) { + histos.fill(HIST("SE_LL"), dphi1, deta1, pt1, mixpairweight); + histos.fill(HIST("SE_LL2"), dphi2, deta2, pt2, mixpairweight); + } else { + histos.fill(HIST("SE_LL"), dphi1, particle1.Rapidity(), pt1, mixpairweight); + histos.fill(HIST("SE_LL2"), dphi2, particle2.Rapidity(), pt2, mixpairweight); + } histos.fill(HIST("hSparseLambdaLambda"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, mixpairweight); histos.fill(HIST("hSparseLambdaLambdaAnalysis"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, deltaRap, std::abs(dphi_pair), mixpairweight); if (useAdditionalHisto) { @@ -547,8 +571,13 @@ struct lambdaspincorrderived { histos.fill(HIST("hSparsePairMassLambdaLambda"), particle1.M(), particle2.M(), cosThetaDiff, pairDummy.M(), mixpairweight); } } else if (tag1 == 0 && tag2 == 1) { - histos.fill(HIST("SE_LAL"), dphi1, deta1, pt1, mixpairweight); - histos.fill(HIST("SE_LAL2"), dphi2, deta2, pt2, mixpairweight); + if (!userapidity) { + histos.fill(HIST("SE_LAL"), dphi1, deta1, pt1, mixpairweight); + histos.fill(HIST("SE_LAL2"), dphi2, deta2, pt2, mixpairweight); + } else { + histos.fill(HIST("SE_LAL"), dphi1, particle1.Rapidity(), pt1, mixpairweight); + histos.fill(HIST("SE_LAL2"), dphi2, particle2.Rapidity(), pt2, mixpairweight); + } histos.fill(HIST("hSparseLambdaAntiLambda"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, mixpairweight); histos.fill(HIST("hSparseLambdaAntiLambdaAnalysis"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, deltaRap, std::abs(dphi_pair), mixpairweight); if (useAdditionalHisto) { @@ -559,8 +588,13 @@ struct lambdaspincorrderived { } else if (tag1 == 1 && tag2 == 0) { histos.fill(HIST("hSparseAntiLambdaLambda"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, mixpairweight); histos.fill(HIST("hSparseAntiLambdaLambdaAnalysis"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, deltaRap, std::abs(dphi_pair), mixpairweight); - histos.fill(HIST("SE_ALL"), dphi1, deta1, pt1, mixpairweight); - histos.fill(HIST("SE_ALL2"), dphi2, deta2, pt2, mixpairweight); + if (!userapidity) { + histos.fill(HIST("SE_ALL"), dphi1, deta1, pt1, mixpairweight); + histos.fill(HIST("SE_ALL2"), dphi2, deta2, pt2, mixpairweight); + } else { + histos.fill(HIST("SE_ALL"), dphi1, particle1.Rapidity(), pt1, mixpairweight); + histos.fill(HIST("SE_ALL2"), dphi2, particle2.Rapidity(), pt2, mixpairweight); + } if (useAdditionalHisto) { histos.fill(HIST("hSparseRapAntiLambdaLambda"), particle1.M(), particle2.M(), cosThetaDiff, deltaRap, mixpairweight); histos.fill(HIST("hSparsePhiAntiLambdaLambda"), particle1.M(), particle2.M(), cosThetaDiff, dphi_pair, mixpairweight); @@ -569,8 +603,13 @@ struct lambdaspincorrderived { } else if (tag1 == 1 && tag2 == 1) { histos.fill(HIST("hSparseAntiLambdaAntiLambda"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, mixpairweight); histos.fill(HIST("hSparseAntiLambdaAntiLambdaAnalysis"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, deltaRap, std::abs(dphi_pair), mixpairweight); - histos.fill(HIST("SE_ALAL"), dphi1, deta1, pt1, mixpairweight); - histos.fill(HIST("SE_ALAL2"), dphi2, deta2, pt2, mixpairweight); + if (!userapidity) { + histos.fill(HIST("SE_ALAL"), dphi1, deta1, pt1, mixpairweight); + histos.fill(HIST("SE_ALAL2"), dphi2, deta2, pt2, mixpairweight); + } else { + histos.fill(HIST("SE_ALAL"), dphi1, particle1.Rapidity(), pt1, mixpairweight); + histos.fill(HIST("SE_ALAL2"), dphi2, particle2.Rapidity(), pt2, mixpairweight); + } if (useAdditionalHisto) { histos.fill(HIST("hSparseRapAntiLambdaAntiLambda"), particle1.M(), particle2.M(), cosThetaDiff, deltaRap, mixpairweight); histos.fill(HIST("hSparsePhiAntiLambdaAntiLambda"), particle1.M(), particle2.M(), cosThetaDiff, dphi_pair, mixpairweight); @@ -591,8 +630,13 @@ struct lambdaspincorrderived { } histos.fill(HIST("hPtYMix"), particle1.Pt(), particle1.Rapidity(), weight); if (tag1 == 0 && tag2 == 0) { - histos.fill(HIST("ME_LL"), dphi1, deta1, pt1, mixpairweight); - histos.fill(HIST("ME_LL2"), dphi2, deta2, pt2, mixpairweight); + if (!userapidity) { + histos.fill(HIST("ME_LL"), dphi1, deta1, pt1, mixpairweight); + histos.fill(HIST("ME_LL2"), dphi2, deta2, pt2, mixpairweight); + } else { + histos.fill(HIST("ME_LL"), dphi1, particle1.Rapidity(), pt1, mixpairweight); + histos.fill(HIST("ME_LL2"), dphi2, particle2.Rapidity(), pt2, mixpairweight); + } histos.fill(HIST("hSparseLambdaLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, weight); histos.fill(HIST("hSparseLambdaLambdaMixedAnalysis"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, deltaRap, std::abs(dphi_pair), weight); if (useAdditionalHisto) { @@ -601,8 +645,13 @@ struct lambdaspincorrderived { histos.fill(HIST("hSparsePairMassLambdaLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, pairDummy.M(), weight); } } else if (tag1 == 0 && tag2 == 1) { - histos.fill(HIST("ME_LAL"), dphi1, deta1, pt1, mixpairweight); - histos.fill(HIST("ME_LAL2"), dphi2, deta2, pt2, mixpairweight); + if (!userapidity) { + histos.fill(HIST("ME_LAL"), dphi1, deta1, pt1, mixpairweight); + histos.fill(HIST("ME_LAL2"), dphi2, deta2, pt2, mixpairweight); + } else { + histos.fill(HIST("ME_LAL"), dphi1, particle1.Rapidity(), pt1, mixpairweight); + histos.fill(HIST("ME_LAL2"), dphi2, particle2.Rapidity(), pt2, mixpairweight); + } histos.fill(HIST("hSparseLambdaAntiLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, weight); histos.fill(HIST("hSparseLambdaAntiLambdaMixedAnalysis"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, deltaRap, std::abs(dphi_pair), weight); if (useAdditionalHisto) { @@ -611,8 +660,13 @@ struct lambdaspincorrderived { histos.fill(HIST("hSparsePairMassLambdaAntiLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, pairDummy.M(), weight); } } else if (tag1 == 1 && tag2 == 0) { - histos.fill(HIST("ME_ALL"), dphi1, deta1, pt1, mixpairweight); - histos.fill(HIST("ME_ALL2"), dphi2, deta2, pt2, mixpairweight); + if (!userapidity) { + histos.fill(HIST("ME_ALL"), dphi1, deta1, pt1, mixpairweight); + histos.fill(HIST("ME_ALL2"), dphi2, deta2, pt2, mixpairweight); + } else { + histos.fill(HIST("ME_ALL"), dphi1, particle1.Rapidity(), pt1, mixpairweight); + histos.fill(HIST("ME_ALL2"), dphi2, particle2.Rapidity(), pt2, mixpairweight); + } histos.fill(HIST("hSparseAntiLambdaLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, weight); histos.fill(HIST("hSparseAntiLambdaLambdaMixedAnalysis"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, deltaRap, std::abs(dphi_pair), weight); if (useAdditionalHisto) { @@ -621,8 +675,13 @@ struct lambdaspincorrderived { histos.fill(HIST("hSparsePairMassAntiLambdaLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, pairDummy.M(), weight); } } else if (tag1 == 1 && tag2 == 1) { - histos.fill(HIST("ME_ALAL"), dphi1, deta1, pt1, mixpairweight); - histos.fill(HIST("ME_ALAL2"), dphi2, deta2, pt2, mixpairweight); + if (!userapidity) { + histos.fill(HIST("ME_ALAL"), dphi1, deta1, pt1, mixpairweight); + histos.fill(HIST("ME_ALAL2"), dphi2, deta2, pt2, mixpairweight); + } else { + histos.fill(HIST("ME_ALAL"), dphi1, particle1.Rapidity(), pt1, mixpairweight); + histos.fill(HIST("ME_ALAL2"), dphi2, particle2.Rapidity(), pt2, mixpairweight); + } histos.fill(HIST("hSparseAntiLambdaAntiLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, weight); histos.fill(HIST("hSparseAntiLambdaAntiLambdaMixedAnalysis"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, deltaRap, std::abs(dphi_pair), weight); if (useAdditionalHisto) { @@ -1048,7 +1107,7 @@ struct lambdaspincorrderived { // Build binner from your existing configurables MixBinner mb{ ptMin.value, ptMax.value, ptMix.value, // pT range & step - v0eta.value, etaMix.value, // |eta| max & step + v0etaMixBuffer.value, etaMix.value, // |eta| max & step phiMix.value // φ step; φ range fixed to [0, 2π) }; @@ -1088,7 +1147,7 @@ struct lambdaspincorrderived { buffer[key].push_back(BufferCand{ .collisionIdx = static_cast(col.index()), - .rowIndex = static_cast(t.globalIndex()), // adapt accessor if needed + .rowIndex = static_cast(t.globalIndex()), .v0Status = static_cast(status), .ptBin = static_cast(ptB), .etaBin = static_cast(etaB), @@ -1246,26 +1305,45 @@ struct lambdaspincorrderived { } template - bool checkKinematicsMC(T1 const& c1, T2 const& c2) + bool checkKinematicsMC(T1 const& candidate1, T2 const& candidate2) { - if (mcacc::v0Status(c1) != mcacc::v0Status(c2)) { + // keep same species/status + if (mcacc::v0Status(candidate1) != mcacc::v0Status(candidate2)) { return false; } - if (std::abs(mcacc::lamPt(c1) - mcacc::lamPt(c2)) > ptMix) { + + // pT window + if (std::abs(mcacc::lamPt(candidate1) - mcacc::lamPt(candidate2)) > ptMix) { return false; } - if (std::abs(mcacc::lamEta(c1) - mcacc::lamEta(c2)) > etaMix) { - return false; + + // eta or rapidity window (etaMix used as Δη or Δy) + if (!userapidity) { + if (std::abs(mcacc::lamEta(candidate1) - mcacc::lamEta(candidate2)) > etaMix) { + return false; + } + } else { + const auto l1 = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(candidate1), mcacc::lamEta(candidate1), + mcacc::lamPhi(candidate1), mcacc::lamMass(candidate1)); + const auto l2 = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(candidate2), mcacc::lamEta(candidate2), + mcacc::lamPhi(candidate2), mcacc::lamMass(candidate2)); + if (std::abs(l1.Rapidity() - l2.Rapidity()) > etaMix) { + return false; + } } - if (std::abs(RecoDecay::constrainAngle( - RecoDecay::constrainAngle(mcacc::lamPhi(c1), 0.f, harmonic) - - RecoDecay::constrainAngle(mcacc::lamPhi(c2), 0.f, harmonic), - -TMath::Pi(), 1)) > phiMix) { + + // delta-phi window (wrapped) + const float dphi = deltaPhiMinusPiToPi((float)mcacc::lamPhi(candidate1), + (float)mcacc::lamPhi(candidate2)); + if (std::abs(dphi) > phiMix) { return false; } - if (std::abs(mcacc::lamMass(c1) - mcacc::lamMass(c2)) > massMix) { + + // mass window (optional but consistent with data) + if (std::abs(mcacc::lamMass(candidate1) - mcacc::lamMass(candidate2)) > massMix) { return false; } + return true; } @@ -1455,6 +1533,7 @@ struct lambdaspincorrderived { // enable it PROCESS_SWITCH(lambdaspincorrderived, processMCMEV3, "Process MC ME (MEV3)", false); + // ----------------------------------------------------- // 5) MC Event Mixing using your MEV4 6D-buffer approach // ----------------------------------------------------- @@ -1463,7 +1542,7 @@ struct lambdaspincorrderived { // Same binner as in data MEV4 MixBinner mb{ ptMin.value, ptMax.value, ptMix.value, - v0eta.value, etaMix.value, + v0etaMixBuffer.value, etaMix.value, phiMix.value}; const int nCol = colBinning.getAllBinsCount(); @@ -1502,8 +1581,6 @@ struct lambdaspincorrderived { const size_t key = linearKey(colBin, status, ptB, etaB, phiB, mB, nStat, nPt, nEta, nPhi, nM); - // rowIndex storage: use globalIndex like your data MEV4 - // If your build doesn't support globalIndex() for this table, replace with t.index() buffer[key].push_back(BufferCand{ .collisionIdx = static_cast(col.index()), .rowIndex = static_cast(t.globalIndex()), @@ -1626,6 +1703,551 @@ struct lambdaspincorrderived { } } PROCESS_SWITCH(lambdaspincorrderived, processMCMEV4, "Process MC ME (5d buffer)", false); + + static inline float phi0To2Pi(float phi) + { + // harmonic=1, min=0 => [0, 2pi) + return RecoDecay::constrainAngle(phi, 0.0f, 1); + } + + static inline float deltaPhiMinusPiToPi(float phiA, float phiB) + { + // returns in [-pi, pi) + const float d = phi0To2Pi(phiA) - phi0To2Pi(phiB); + return RecoDecay::constrainAngle(d, -TMath::Pi(), 1); + } + + static inline float absDeltaPhi(float phiA, float phiB) + { + return std::abs(deltaPhiMinusPiToPi(phiA, phiB)); + } + + // symmetric neighbors for continuous mixing (pt/eta): include bin, ±1, ±2..., edge-safe + static inline void collectNeighborBins1D(int b, int nBins, int nNeighbor, std::vector& out) + { + out.clear(); + out.reserve(2 * nNeighbor + 1); + for (int d = -nNeighbor; d <= nNeighbor; ++d) { + const int bb = b + d; + if (bb < 0 || bb >= nBins) { + continue; + } + out.push_back(bb); + } + std::sort(out.begin(), out.end()); + out.erase(std::unique(out.begin(), out.end()), out.end()); + } + + // symmetric neighbors for phi: periodic wrap + static inline void collectNeighborBinsPhi(int b, int nPhi, int nNeighbor, std::vector& out) + { + out.clear(); + out.reserve(2 * nNeighbor + 1); + for (int d = -nNeighbor; d <= nNeighbor; ++d) { + int bb = b + d; + bb %= nPhi; + if (bb < 0) { + bb += nPhi; + } + out.push_back(bb); + } + std::sort(out.begin(), out.end()); + out.erase(std::unique(out.begin(), out.end()), out.end()); + } + + static inline void collectNeighborBinsClamp(int b, int nBins, int nNeighbor, std::vector& out) + { + out.clear(); + out.reserve(2 * nNeighbor + 1); + for (int d = -nNeighbor; d <= nNeighbor; ++d) { + const int bb = b + d; + if (bb >= 0 && bb < nBins) { + out.push_back(bb); + } + } + } + + static inline void collectPhiBinsWithEdgeWrap(int phiB, int nPhi, std::vector& out) + { + out.clear(); + out.reserve(2); + out.push_back(phiB); + if (nPhi <= 1) { + return; + } + if (phiB == 0) { + out.push_back(nPhi - 1); + } else if (phiB == nPhi - 1) { + out.push_back(0); + } + } + + static inline uint64_t splitmix64(uint64_t x) + { + // simple deterministic hash for reproducible shuffling + x += 0x9e3779b97f4a7c15ULL; + x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9ULL; + x = (x ^ (x >> 27)) * 0x94d049bb133111ebULL; + return x ^ (x >> 31); + } + + static inline uint64_t splitmixmc64(uint64_t x) + { + x += 0x9e3779b97f4a7c15ULL; + x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9ULL; + x = (x ^ (x >> 27)) * 0x94d049bb133111ebULL; + return x ^ (x >> 31); + } + + void processMEV5(EventCandidates const& collisions, AllTrackCandidates const& V0s) + { + // Buffer binning: use v0etaMixBuffer as the max range, etaMix as the bin step + MixBinner mb{ + ptMin.value, ptMax.value, ptMix.value, // pT range & step + v0etaMixBuffer.value, etaMix.value, // |eta| (or |y|) max & step + phiMix.value // phi step + }; + + const int nCol = colBinning.getAllBinsCount(); + const int nStat = N_STATUS; + const int nPt = mb.nPt(); + const int nEta = mb.nEta(); // logical "nY" if userapidity=true + const int nPhi = mb.nPhi(); + const int nM = mb.nM(); + + const size_t nKeys = static_cast(nCol) * nStat * nPt * nEta * nPhi * nM; + std::vector> buffer(nKeys); + + // -------- PASS 1: fill buffer -------- + for (auto const& col : collisions) { + const int colBin = colBinning.getBin(std::make_tuple(col.posz(), col.cent())); + if (colBin < 0) { + continue; + } + + auto slice = V0s.sliceBy(tracksPerCollisionV0, col.index()); + + for (auto const& t : slice) { + if (!selectionV0(t)) { + continue; + } + + const int status = static_cast(t.v0Status()); + if (status < 0 || status >= nStat) { + continue; + } + + const int ptB = mb.ptBin(t.lambdaPt()); + + int etaB = mb.etaBin(t.lambdaEta()); + if (userapidity) { + const auto lv = ROOT::Math::PtEtaPhiMVector(t.lambdaPt(), t.lambdaEta(), t.lambdaPhi(), t.lambdaMass()); + etaB = mb.etaBin(lv.Rapidity()); // treat "eta axis" as rapidity axis + } + + const int phiB = mb.phiBin(RecoDecay::constrainAngle(t.lambdaPhi(), 0.0F, harmonic)); + const int mB = mb.massBin(t.lambdaMass()); + + if (ptB < 0 || etaB < 0 || phiB < 0 || mB < 0) { + continue; + } + + const size_t key = linearKey(colBin, status, ptB, etaB, phiB, mB, + nStat, nPt, nEta, nPhi, nM); + + buffer[key].push_back(BufferCand{ + .collisionIdx = static_cast(col.index()), + .rowIndex = static_cast(t.globalIndex()), + .v0Status = static_cast(status), + .ptBin = static_cast(ptB), + .etaBin = static_cast(etaB), + .phiBin = static_cast(phiB), + .mBin = static_cast(mB)}); + } + } + + // Neighbor policy (continuous mixing) + constexpr int nN_pt = 1; // ±1 pt-bin + constexpr int nN_eta = 1; // ±1 eta/y-bin (can make configurable later) + + std::vector ptBins, etaBins, phiBins; + std::vector matches; + matches.reserve(256); + + // -------- PASS 2: mix (replace t1 by tX, keep t2 from same event) -------- + for (auto const& col1 : collisions) { + const int colBin = colBinning.getBin(std::make_tuple(col1.posz(), col1.cent())); + if (colBin < 0) { + continue; + } + + const int64_t curColIdx = static_cast(col1.index()); + auto poolA = V0s.sliceBy(tracksPerCollisionV0, col1.index()); + + for (auto const& [t1, t2] : + soa::combinations(o2::soa::CombinationsFullIndexPolicy(poolA, poolA))) { + + if (!selectionV0(t1) || !selectionV0(t2)) { + continue; + } + if (t2.index() <= t1.index()) { + continue; // same-event ordering + } + + // no shared daughters (same-event) + if (t1.protonIndex() == t2.protonIndex()) + continue; + if (t1.pionIndex() == t2.pionIndex()) + continue; + if (t1.protonIndex() == t2.pionIndex()) + continue; + if (t1.pionIndex() == t2.protonIndex()) + continue; + + const int status = static_cast(t1.v0Status()); + if (status < 0 || status >= nStat) { + continue; + } + + const int ptB = mb.ptBin(t1.lambdaPt()); + + int etaB = mb.etaBin(t1.lambdaEta()); + if (userapidity) { + const auto lv1 = ROOT::Math::PtEtaPhiMVector(t1.lambdaPt(), t1.lambdaEta(), t1.lambdaPhi(), t1.lambdaMass()); + etaB = mb.etaBin(lv1.Rapidity()); + } + + const int phiB = mb.phiBin(RecoDecay::constrainAngle(t1.lambdaPhi(), 0.0F, harmonic)); + const int mB = mb.massBin(t1.lambdaMass()); + + if (ptB < 0 || etaB < 0 || phiB < 0 || mB < 0) { + continue; + } + + collectNeighborBinsClamp(ptB, nPt, nN_pt, ptBins); + collectNeighborBinsClamp(etaB, nEta, nN_eta, etaBins); + collectPhiBinsWithEdgeWrap(phiB, nPhi, phiBins); + + matches.clear(); + + for (int ptUse : ptBins) { + for (int etaUse : etaBins) { + for (int phiUse : phiBins) { + const size_t keyUse = linearKey(colBin, status, ptUse, etaUse, phiUse, mB, + nStat, nPt, nEta, nPhi, nM); + auto const& vec = buffer[keyUse]; + + for (auto const& bc : vec) { + if (bc.collisionIdx == curColIdx) { + continue; // enforce different event + } + + auto tX = V0s.iteratorAt(static_cast(bc.rowIndex)); + if (!selectionV0(tX)) { + continue; + } + + // extra strict kinematic check (uses eta or rapidity based on userapidity) + if (!checkKinematics(t1, tX)) { + continue; + } + + // safety (should be redundant because different event) + if (tX.globalIndex() == t1.globalIndex()) + continue; + if (tX.globalIndex() == t2.globalIndex()) + continue; + + matches.push_back(MatchRef{bc.collisionIdx, bc.rowIndex}); + } + } + } + } + + if (matches.empty()) { + continue; + } + + // dedupe + std::sort(matches.begin(), matches.end(), + [](auto const& a, auto const& b) { + return std::tie(a.collisionIdx, a.rowIndex) < std::tie(b.collisionIdx, b.rowIndex); + }); + matches.erase(std::unique(matches.begin(), matches.end(), + [](auto const& a, auto const& b) { + return a.collisionIdx == b.collisionIdx && a.rowIndex == b.rowIndex; + }), + matches.end()); + if (matches.empty()) { + continue; + } + + // unbiased cap (cfgV5MaxMatches==1 => pick-one mode) + if (cfgV5MaxMatches.value > 0 && (int)matches.size() > cfgV5MaxMatches.value) { + uint64_t seed = 0; + seed ^= splitmix64((uint64_t)t1.globalIndex()); + seed ^= splitmix64((uint64_t)t2.globalIndex() + 0x1234567ULL); + seed ^= splitmix64((uint64_t)curColIdx + 0x9abcULL); + + const int K = cfgV5MaxMatches.value; + for (int i = 0; i < K; ++i) { + seed = splitmix64(seed); + const int j = i + (int)(seed % (uint64_t)(matches.size() - i)); + std::swap(matches[i], matches[j]); + } + matches.resize(K); + } + + const float wBase = 1.0f / static_cast(matches.size()); + + for (auto const& m : matches) { + auto tX = V0s.iteratorAt(static_cast(m.rowIndex)); + + auto proton = ROOT::Math::PtEtaPhiMVector(tX.protonPt(), tX.protonEta(), tX.protonPhi(), + o2::constants::physics::MassProton); + auto lambda = ROOT::Math::PtEtaPhiMVector(tX.lambdaPt(), tX.lambdaEta(), tX.lambdaPhi(), + tX.lambdaMass()); + + auto proton2 = ROOT::Math::PtEtaPhiMVector(t2.protonPt(), t2.protonEta(), t2.protonPhi(), + o2::constants::physics::MassProton); + auto lambda2 = ROOT::Math::PtEtaPhiMVector(t2.lambdaPt(), t2.lambdaEta(), t2.lambdaPhi(), + t2.lambdaMass()); + + const float dPhi = deltaPhiMinusPiToPi((float)lambda.Phi(), (float)lambda2.Phi()); + histos.fill(HIST("deltaPhiMix"), dPhi, wBase); + + fillHistograms(tX.v0Status(), t2.v0Status(), + lambda, lambda2, proton, proton2, + /*datatype=*/1, /*mixpairweight=*/wBase); + } + } + } + } + PROCESS_SWITCH(lambdaspincorrderived, processMEV5, "Process data ME v5", false); + + void processMCMEV5(EventCandidatesMC const& collisions, AllTrackCandidatesMC const& V0sMC) + { + // Buffer binning: v0etaMixBuffer = max(|eta|) or max(|y|) if userapidity + // etaMix = step for that axis (and also your matching window inside checkKinematicsMC) + MixBinner mb{ + ptMin.value, ptMax.value, ptMix.value, + v0etaMixBuffer.value, etaMix.value, + phiMix.value}; + + const int nCol = colBinning.getAllBinsCount(); + const int nStat = N_STATUS; + const int nPt = mb.nPt(); + const int nEta = mb.nEta(); // logical "nY" if userapidity=true + const int nPhi = mb.nPhi(); + + const size_t nKeys = static_cast(nCol) * nStat * nPt * nEta * nPhi; + std::vector> buffer(nKeys); + + auto key5 = [&](int colBin, int status, int ptB, int etaB, int phiB) -> size_t { + size_t k = static_cast(colBin); + k = k * static_cast(nStat) + static_cast(status); + k = k * static_cast(nPt) + static_cast(ptB); + k = k * static_cast(nEta) + static_cast(etaB); + k = k * static_cast(nPhi) + static_cast(phiB); + return k; + }; + + // -------- PASS 1: fill buffer -------- + for (auto const& col : collisions) { + const int colBin = colBinning.getBin(std::make_tuple(mcacc::posz(col), mcacc::cent(col))); + if (colBin < 0) { + continue; + } + + auto slice = V0sMC.sliceBy(tracksPerCollisionV0mc, col.index()); + + for (auto const& t : slice) { + if (!selectionV0MC(t)) { + continue; + } + + const int status = mcacc::v0Status(t); + if (status < 0 || status >= nStat) { + continue; + } + + const int ptB = mb.ptBin(mcacc::lamPt(t)); + + int etaB = mb.etaBin(mcacc::lamEta(t)); + if (userapidity) { + const auto lv = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(t), mcacc::lamEta(t), + mcacc::lamPhi(t), mcacc::lamMass(t)); + etaB = mb.etaBin(lv.Rapidity()); + } + + const int phiB = mb.phiBin(phi0To2Pi(mcacc::lamPhi(t))); + if (ptB < 0 || etaB < 0 || phiB < 0) { + continue; + } + + buffer[key5(colBin, status, ptB, etaB, phiB)].push_back(BufferCand{ + .collisionIdx = static_cast(col.index()), + .rowIndex = static_cast(t.globalIndex()), + .v0Status = static_cast(status), + .ptBin = static_cast(ptB), + .etaBin = static_cast(etaB), + .phiBin = static_cast(phiB), + .mBin = 0}); + } + } + + constexpr int nN_pt = 1; + constexpr int nN_eta = 1; + + std::vector ptBins, etaBins, phiBins; + std::vector matches; + matches.reserve(256); + + // -------- PASS 2: build ME -------- + for (auto const& col1 : collisions) { + const int colBin = colBinning.getBin(std::make_tuple(mcacc::posz(col1), mcacc::cent(col1))); + if (colBin < 0) { + continue; + } + + const int64_t curColIdx = static_cast(col1.index()); + auto poolA = V0sMC.sliceBy(tracksPerCollisionV0mc, col1.index()); + + for (auto const& [t1, t2] : + soa::combinations(o2::soa::CombinationsFullIndexPolicy(poolA, poolA))) { + + if (!selectionV0MC(t1) || !selectionV0MC(t2)) { + continue; + } + if (t2.index() <= t1.index()) { + continue; + } + + // no shared daughters + if (mcacc::prIdx(t1) == mcacc::prIdx(t2)) + continue; + if (mcacc::piIdx(t1) == mcacc::piIdx(t2)) + continue; + if (mcacc::prIdx(t1) == mcacc::piIdx(t2)) + continue; + if (mcacc::piIdx(t1) == mcacc::prIdx(t2)) + continue; + + const int status = mcacc::v0Status(t1); + if (status < 0 || status >= nStat) { + continue; + } + + const int ptB = mb.ptBin(mcacc::lamPt(t1)); + + int etaB = mb.etaBin(mcacc::lamEta(t1)); + if (userapidity) { + const auto lv1 = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(t1), mcacc::lamEta(t1), + mcacc::lamPhi(t1), mcacc::lamMass(t1)); + etaB = mb.etaBin(lv1.Rapidity()); + } + + const int phiB = mb.phiBin(phi0To2Pi(mcacc::lamPhi(t1))); + if (ptB < 0 || etaB < 0 || phiB < 0) { + continue; + } + + collectNeighborBinsClamp(ptB, nPt, nN_pt, ptBins); + collectNeighborBinsClamp(etaB, nEta, nN_eta, etaBins); + collectPhiBinsWithEdgeWrap(phiB, nPhi, phiBins); + + matches.clear(); + + for (int ptUse : ptBins) { + for (int etaUse : etaBins) { + for (int phiUse : phiBins) { + auto const& vec = buffer[key5(colBin, status, ptUse, etaUse, phiUse)]; + + for (auto const& bc : vec) { + if (bc.collisionIdx == curColIdx) { + continue; // different event + } + + auto tX = V0sMC.iteratorAt(static_cast(bc.rowIndex)); + if (!selectionV0MC(tX)) { + continue; + } + if (!checkKinematicsMC(t1, tX)) { + continue; + } + + // safety (should be redundant due to different event) + if (tX.globalIndex() == t1.globalIndex()) + continue; + if (tX.globalIndex() == t2.globalIndex()) + continue; + + matches.push_back(MatchRef{bc.collisionIdx, bc.rowIndex}); + } + } + } + } + + if (matches.empty()) { + continue; + } + + // dedupe + std::sort(matches.begin(), matches.end(), + [](auto const& a, auto const& b) { + return std::tie(a.collisionIdx, a.rowIndex) < std::tie(b.collisionIdx, b.rowIndex); + }); + matches.erase(std::unique(matches.begin(), matches.end(), + [](auto const& a, auto const& b) { + return a.collisionIdx == b.collisionIdx && a.rowIndex == b.rowIndex; + }), + matches.end()); + if (matches.empty()) { + continue; + } + + // unbiased cap (cfgV5MaxMatches==1 => pick-one mode) + if (cfgV5MaxMatches.value > 0 && (int)matches.size() > cfgV5MaxMatches.value) { + uint64_t seed = 0; + seed ^= splitmix64((uint64_t)t1.globalIndex()); + seed ^= splitmix64((uint64_t)t2.globalIndex() + 0x1234567ULL); + seed ^= splitmix64((uint64_t)curColIdx + 0x9abcULL); + + const int K = cfgV5MaxMatches.value; + for (int i = 0; i < K; ++i) { + seed = splitmix64(seed); + const int j = i + (int)(seed % (uint64_t)(matches.size() - i)); + std::swap(matches[i], matches[j]); + } + matches.resize(K); + } + + const float wBase = 1.0f / static_cast(matches.size()); + + for (auto const& m : matches) { + auto tX = V0sMC.iteratorAt(static_cast(m.rowIndex)); + + auto pX = ROOT::Math::PtEtaPhiMVector(mcacc::prPt(tX), mcacc::prEta(tX), mcacc::prPhi(tX), + o2::constants::physics::MassProton); + auto lX = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(tX), mcacc::lamEta(tX), mcacc::lamPhi(tX), + mcacc::lamMass(tX)); + + auto p2 = ROOT::Math::PtEtaPhiMVector(mcacc::prPt(t2), mcacc::prEta(t2), mcacc::prPhi(t2), + o2::constants::physics::MassProton); + auto l2 = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(t2), mcacc::lamEta(t2), mcacc::lamPhi(t2), + mcacc::lamMass(t2)); + + const float dPhi = deltaPhiMinusPiToPi((float)lX.Phi(), (float)l2.Phi()); + histos.fill(HIST("deltaPhiMix"), dPhi, wBase); + + fillHistograms(mcacc::v0Status(tX), mcacc::v0Status(t2), + lX, l2, pX, p2, + /*datatype=*/1, /*mixpairweight=*/wBase); + } + } + } + } + PROCESS_SWITCH(lambdaspincorrderived, processMCMEV5, "Process MC ME v5 (paper-style)", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { From fb53848fbc657744572b3f43aa7e4e848b02b848 Mon Sep 17 00:00:00 2001 From: VDiBella <162152869+VDiBella@users.noreply.github.com> Date: Fri, 6 Mar 2026 12:18:09 +0100 Subject: [PATCH 191/347] [PWGHF] Adding missing subscriptions to important tables in correlator, separating charges of D mesons candidates in the task (#15178) Co-authored-by: Valerio Di Bella --- .../correlatorDplusDplusReduced.cxx | 29 +++++++++++-------- .../taskCorrelationDplusDplusReduced.cxx | 18 ++++++++++-- 2 files changed, 32 insertions(+), 15 deletions(-) diff --git a/PWGHF/HFC/TableProducer/correlatorDplusDplusReduced.cxx b/PWGHF/HFC/TableProducer/correlatorDplusDplusReduced.cxx index 3d00c7ac8eb..d58da7fccd6 100644 --- a/PWGHF/HFC/TableProducer/correlatorDplusDplusReduced.cxx +++ b/PWGHF/HFC/TableProducer/correlatorDplusDplusReduced.cxx @@ -114,21 +114,21 @@ struct HfCorrelatorDplusDplusReduced { collision.posZ()); } - template + template void fillCandidateTable(const T& candidate, int localEvIdx = -1, int sign = 1) { int8_t flagMc = 0; int8_t originMc = 0; int8_t channelMc = 0; - if constexpr (doMc) { + if constexpr (DoMc) { flagMc = candidate.flagMcMatchRec(); originMc = candidate.originMcRec(); channelMc = candidate.flagMcDecayChanRec(); } std::vector outputMl = {-999., -999.}; - if constexpr (doMl) { + if constexpr (DoMl) { for (unsigned int iclass = 0; iclass < classMlIndexes->size(); iclass++) { outputMl[iclass] = candidate.mlProbDplusToPiKPi()[classMlIndexes->at(iclass)]; } @@ -283,7 +283,10 @@ struct HfCorrelatorDplusDplusReduced { } } - void processData(aod::Collisions const& collisions, SelectedCandidates const& candidates, aod::Tracks const&) + void processData(aod::Collisions const& collisions, + SelectedCandidates const& candidates, + aod::Tracks const&, + aod::BCsWithTimestamps const&) { static int lastRunNumber = -1; // reserve memory @@ -315,16 +318,17 @@ struct HfCorrelatorDplusDplusReduced { continue; fillEvent(collision); for (const auto& candidate : candidatesInThisCollision) { - auto prong_candidate = candidate.prong1_as(); - auto candidate_sign = prong_candidate.sign(); - fillCandidateTable(candidate, rowCandidateFullEvents.lastIndex(), candidate_sign); + auto prongCandidate = candidate.prong1_as(); + auto candidateSign = -prongCandidate.sign(); + fillCandidateTable(candidate, rowCandidateFullEvents.lastIndex(), candidateSign); } } } PROCESS_SWITCH(HfCorrelatorDplusDplusReduced, processData, "Process data per collision", false); void processMcRec(aod::Collisions const& collisions, - SelectedCandidatesMc const& candidates) + SelectedCandidatesMc const& candidates, + aod::Tracks const&) { // reserve memory rowCandidateFullEvents.reserve(collisions.size()); @@ -342,15 +346,16 @@ struct HfCorrelatorDplusDplusReduced { continue; fillEvent(collision); for (const auto& candidate : candidatesInThisCollision) { - auto prong_candidate = candidate.prong1_as(); - auto candidate_sign = prong_candidate.sign(); - fillCandidateTable(candidate, rowCandidateFullEvents.lastIndex(), candidate_sign); + auto prongCandidate = candidate.prong1_as(); + auto candidateSign = -prongCandidate.sign(); + fillCandidateTable(candidate, rowCandidateFullEvents.lastIndex(), candidateSign); } } } PROCESS_SWITCH(HfCorrelatorDplusDplusReduced, processMcRec, "Process data per collision", false); - void processMcGen(aod::McCollisions const& mccollisions, MatchedGenCandidatesMc const& mcparticles) + void processMcGen(aod::McCollisions const& mccollisions, + MatchedGenCandidatesMc const& mcparticles) { // reserve memory rowCandidateMcCollisions.reserve(mccollisions.size()); diff --git a/PWGHF/HFC/Tasks/taskCorrelationDplusDplusReduced.cxx b/PWGHF/HFC/Tasks/taskCorrelationDplusDplusReduced.cxx index 926e2a111e5..c37c1f73feb 100644 --- a/PWGHF/HFC/Tasks/taskCorrelationDplusDplusReduced.cxx +++ b/PWGHF/HFC/Tasks/taskCorrelationDplusDplusReduced.cxx @@ -55,7 +55,9 @@ struct HfTaskCorrelationDplusDplusReduced { void init(InitContext const&) { registry.add("hMassDplus", "D+ candidates;inv. mass (#pi#pi K) (GeV/#it{c}^{2}))", {HistType::kTH1F, {{120, 1.5848, 2.1848}}}); + registry.add("hMassDminus", "D- candidates;inv. mass (#pi#pi K) (GeV/#it{c}^{2}))", {HistType::kTH1F, {{120, 1.5848, 2.1848}}}); registry.add("hMassDplusMatched", "D+ matched candidates;inv. mass (#pi#pi K) (GeV/#it{c}^{2}))", {HistType::kTH1F, {{120, 1.5848, 2.1848}}}); + registry.add("hMassDminusMatched", "D- matched candidates;inv. mass (#pi#pi K) (GeV/#it{c}^{2}))", {HistType::kTH1F, {{120, 1.5848, 2.1848}}}); registry.add("hMassDplusminusPair", "D plus-minus pair candidates;inv. mass (#pi K) (GeV/#it{c}^{2});inv. mass (#pi K) (GeV/#it{c}^{2})", {HistType::kTH2F, {{120, 1.5848, 2.1848}, {120, 1.5848, 2.1848}}}); registry.add("hMassDplusPair", "D plus pair candidates;inv. mass (#pi K) (GeV/#it{c}^{2});inv. mass (#pi K) (GeV/#it{c}^{2})", {HistType::kTH2F, {{120, 1.5848, 2.1848}, {120, 1.5848, 2.1848}}}); registry.add("hMassDminusPair", "D minus pair candidates;inv. mass (#pi K) (GeV/#it{c}^{2});inv. mass (#pi K) (GeV/#it{c}^{2})", {HistType::kTH2F, {{120, 1.5848, 2.1848}, {120, 1.5848, 2.1848}}}); @@ -72,7 +74,11 @@ struct HfTaskCorrelationDplusDplusReduced { auto sign1 = 1; if (cand1.pt() < 0) { sign1 = -1; + registry.fill(HIST("hMassDminus"), mass1); + } else { + registry.fill(HIST("hMassDplus"), mass1); } + for (auto cand2 = cand1 + 1; cand2 != localCandidates.end(); ++cand2) { auto mass2 = cand2.m(); auto sign2 = 1; @@ -100,9 +106,15 @@ struct HfTaskCorrelationDplusDplusReduced { for (const auto& cand1 : localCandidates) { auto mass1 = cand1.m(); - registry.fill(HIST("hMassDplus"), mass1); - if (std::abs(cand1.flagMcMatchRec()) == hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) - registry.fill(HIST("hMassDplusMatched"), mass1); + if (cand1.pt() < 0) { + registry.fill(HIST("hMassDminus"), mass1); + if (std::abs(cand1.flagMcMatchRec()) == hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) + registry.fill(HIST("hMassDminusMatched"), mass1); + } else { + registry.fill(HIST("hMassDplus"), mass1); + if (std::abs(cand1.flagMcMatchRec()) == hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) + registry.fill(HIST("hMassDplusMatched"), mass1); + } } } PROCESS_SWITCH(HfTaskCorrelationDplusDplusReduced, processLocalDataMcRec, "Process local MC data", false); From b1a894163a3361d441c8f9df2e075e394e137cb4 Mon Sep 17 00:00:00 2001 From: Chuntai <48704924+wuctlby@users.noreply.github.com> Date: Fri, 6 Mar 2026 12:40:41 +0100 Subject: [PATCH 192/347] [PWGHF] Apply the eta selection to the trigger candidates (#15289) --- .../derivedDataCreatorCorrelationsReduced.cxx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/PWGHF/HFC/TableProducer/derivedDataCreatorCorrelationsReduced.cxx b/PWGHF/HFC/TableProducer/derivedDataCreatorCorrelationsReduced.cxx index 22277105bb4..c8b4ea6c71a 100644 --- a/PWGHF/HFC/TableProducer/derivedDataCreatorCorrelationsReduced.cxx +++ b/PWGHF/HFC/TableProducer/derivedDataCreatorCorrelationsReduced.cxx @@ -88,6 +88,7 @@ struct HfDerivedDataCreatorCorrelationsReduced { Configurable ptCandMax{"ptCandMax", 24., "max. cand. pT"}; Configurable tpcNClsCrossedRowsMin{"tpcNClsCrossedRowsMin", 70, "min. TPC crossed rows for associated tracks"}; Configurable etaTrkMax{"etaTrkMax", 1., "max. track eta"}; + Configurable etaCandMax{"etaCandMax", 1., "max. trigger candidate eta"}; Configurable ptTrkMin{"ptTrkMin", 0.2, "min. track pT"}; Configurable ptTrkMax{"ptTrkMax", 3., "max. track pT"}; Configurable dcaXYTrkMax{"dcaXYTrkMax", 1., "max. track DCA XY"}; @@ -335,6 +336,9 @@ struct HfDerivedDataCreatorCorrelationsReduced { const float collCentrality) { for (const auto& trigCand : trigCands) { + if (std::fabs(trigCand.eta()) >= etaCandMax) { + continue; + } double trigCandPt = trigCand.pt(); registry.fill(HIST("hPhiVsPtTrig"), RecoDecay::constrainAngle(trigCand.phi(), -o2::constants::math::PIHalf), trigCandPt); registry.fill(HIST("hEtaVsPtTrig"), trigCand.eta(), trigCandPt); @@ -388,6 +392,9 @@ struct HfDerivedDataCreatorCorrelationsReduced { void fillCharmMixedEvent(TTrigCands const& trigCands) { for (const auto& trigCand : trigCands) { + if (std::fabs(trigCand.eta()) >= etaCandMax) { + continue; + } registry.fill(HIST("hPhiVsPtTrig"), RecoDecay::constrainAngle(trigCand.phi(), -o2::constants::math::PIHalf), trigCand.pt()); registry.fill(HIST("hEtaVsPtTrig"), trigCand.eta(), trigCand.pt()); From 8827e751d85c46a233479ce80bfdefa1ea91d26c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Fri, 6 Mar 2026 12:59:08 +0100 Subject: [PATCH 193/347] [ALICE3] Refactor track hit storage to use std::array (#15275) --- ALICE3/TableProducer/OTF/onTheFlyTracker.cxx | 34 ++++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx b/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx index c2b14a5c6f4..5989f9d3965 100644 --- a/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx +++ b/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx @@ -928,12 +928,12 @@ struct OnTheFlyTracker { const float timeResolutionUs = timeResolutionNs * nsToMus; // us const float time = (eventCollisionTimeNS + gRandom->Gaus(0., timeResolutionNs)) * nsToMus; static constexpr int kCascProngs = 3; - std::vector xiDaughterTrackParCovsPerfect(3); - std::vector xiDaughterTrackParCovsTracked(3); - std::vector isReco(kCascProngs); - std::vector nHits(kCascProngs); // total - std::vector nSiliconHits(kCascProngs); // silicon type - std::vector nTPCHits(kCascProngs); // TPC type + std::array xiDaughterTrackParCovsPerfect; + std::array xiDaughterTrackParCovsTracked; + std::array isReco; + std::array nHitsCascadeProngs; // total + std::array nSiliconHitsCascadeProngs; // silicon type + std::array nTPCHitsCascadeProngs; // TPC type bool tryKinkReco = false; if (cascadeDecaySettings.decayXi && isCascade) { @@ -951,19 +951,19 @@ struct OnTheFlyTracker { for (int i = 0; i < kCascProngs; i++) { isReco[i] = false; - nHits[i] = 0; - nSiliconHits[i] = 0; - nTPCHits[i] = 0; + nHitsCascadeProngs[i] = 0; + nSiliconHitsCascadeProngs[i] = 0; + nTPCHitsCascadeProngs[i] = 0; if (enableSecondarySmearing) { - nHits[i] = fastTracker[icfg]->FastTrack(xiDaughterTrackParCovsPerfect[i], xiDaughterTrackParCovsTracked[i], dNdEta); - nSiliconHits[i] = fastTracker[icfg]->GetNSiliconPoints(); - nTPCHits[i] = fastTracker[icfg]->GetNGasPoints(); + nHitsCascadeProngs[i] = fastTracker[icfg]->FastTrack(xiDaughterTrackParCovsPerfect[i], xiDaughterTrackParCovsTracked[i], dNdEta); + nSiliconHitsCascadeProngs[i] = fastTracker[icfg]->GetNSiliconPoints(); + nTPCHitsCascadeProngs[i] = fastTracker[icfg]->GetNGasPoints(); - if (nHits[i] < 0 && cascadeDecaySettings.doXiQA) { // QA - getHist(TH1, histPath + "hFastTrackerQA")->Fill(o2::math_utils::abs(nHits[i])); + if (nHitsCascadeProngs[i] < 0 && cascadeDecaySettings.doXiQA) { // QA + getHist(TH1, histPath + "hFastTrackerQA")->Fill(o2::math_utils::abs(nHitsCascadeProngs[i])); } - if (nSiliconHits[i] >= fastTrackerSettings.minSiliconHits || (nSiliconHits[i] >= fastTrackerSettings.minSiliconHitsIfTPCUsed && nTPCHits[i] >= fastTrackerSettings.minTPCClusters)) { + if (nSiliconHitsCascadeProngs[i] >= fastTrackerSettings.minSiliconHits || (nSiliconHitsCascadeProngs[i] >= fastTrackerSettings.minSiliconHitsIfTPCUsed && nTPCHitsCascadeProngs[i] >= fastTrackerSettings.minTPCClusters)) { isReco[i] = true; } else { continue; // extra sure @@ -982,7 +982,7 @@ struct OnTheFlyTracker { histos.fill(HIST("hNaNBookkeeping"), i + 1, 1.0f); } if (isReco[i]) { - tracksAlice3.push_back(TrackAlice3{xiDaughterTrackParCovsTracked[i], mcParticle.globalIndex(), time, timeResolutionUs, true, true, i + 2, nSiliconHits[i], nTPCHits[i]}); + tracksAlice3.push_back(TrackAlice3{xiDaughterTrackParCovsTracked[i], mcParticle.globalIndex(), time, timeResolutionUs, true, true, i + 2, nSiliconHitsCascadeProngs[i], nTPCHitsCascadeProngs[i]}); } else { ghostTracksAlice3.push_back(TrackAlice3{xiDaughterTrackParCovsTracked[i], mcParticle.globalIndex(), time, timeResolutionUs, true, true, i + 2}); } @@ -1379,7 +1379,7 @@ struct OnTheFlyTracker { // histos.fill(HIST("hNaNBookkeeping"), i + 1, 1.0f); // } if (isReco[i]) { - tracksAlice3.push_back(TrackAlice3{v0DaughterTrackParCovsTracked[i], mcParticle.globalIndex(), time, timeResolutionUs, true, true, i + 2, nSiliconHits[i], nTPCHits[i]}); + tracksAlice3.push_back(TrackAlice3{v0DaughterTrackParCovsTracked[i], mcParticle.globalIndex(), time, timeResolutionUs, true, true, i + 2, nSiliconHitsCascadeProngs[i], nTPCHitsCascadeProngs[i]}); } else { ghostTracksAlice3.push_back(TrackAlice3{v0DaughterTrackParCovsTracked[i], mcParticle.globalIndex(), time, timeResolutionUs, true, true, i + 2}); } From 187a6e30c6683945439716f3b40cfeb3ae2de527 Mon Sep 17 00:00:00 2001 From: Kegang Xiong Date: Fri, 6 Mar 2026 20:49:38 +0800 Subject: [PATCH 194/347] [PWGCF] use zdc energy to do some try (#15288) --- PWGCF/Flow/Tasks/CMakeLists.txt | 5 + PWGCF/Flow/Tasks/flowZdcEnergy.cxx | 174 +++++++++++++++++++++++++++++ 2 files changed, 179 insertions(+) create mode 100644 PWGCF/Flow/Tasks/flowZdcEnergy.cxx diff --git a/PWGCF/Flow/Tasks/CMakeLists.txt b/PWGCF/Flow/Tasks/CMakeLists.txt index b1300623c73..cb080629efb 100644 --- a/PWGCF/Flow/Tasks/CMakeLists.txt +++ b/PWGCF/Flow/Tasks/CMakeLists.txt @@ -64,6 +64,11 @@ o2physics_add_dpl_workflow(flow-pid-cme PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::GFWCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(flow-zdc-energy + SOURCES flowZdcEnergy.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::GFWCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(flow-sp SOURCES flowSP.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::GFWCore diff --git a/PWGCF/Flow/Tasks/flowZdcEnergy.cxx b/PWGCF/Flow/Tasks/flowZdcEnergy.cxx new file mode 100644 index 00000000000..5feb8a01b80 --- /dev/null +++ b/PWGCF/Flow/Tasks/flowZdcEnergy.cxx @@ -0,0 +1,174 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file flowZdcEnergy.cxx +/// \author Kegang Xiong (kegang.xiong@cern.ch) +/// \since 03/2026 +/// \brief A try to use the znc energy. + +#include "PWGCF/DataModel/SPTableZDC.h" + +#include "Common/Core/EventPlaneHelper.h" +#include "Common/Core/RecoDecay.h" +#include "Common/Core/TrackSelection.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/Qvectors.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsParameters/GRPLHCIFData.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/runDataProcessing.h" + +#include "TF1.h" +#include "TPDGCode.h" + +#include +#include +#include +#include +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::aod::rctsel; +// using namespace o2::analysis; + +#define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable NAME{#NAME, DEFAULT, HELP}; + +struct flowZdcEnergy { + + RCTFlagsChecker rctChecker; + + struct : ConfigurableGroup { + O2_DEFINE_CONFIGURABLE(cfgEvtUseRCTFlagChecker, bool, false, "Evt sel: use RCT flag checker"); + O2_DEFINE_CONFIGURABLE(cfgEvtRCTFlagCheckerLabel, std::string, "CBT_hadronPID", "Evt sel: RCT flag checker label (CBT, CBT_hadronPID)"); // all Labels can be found in Common/CCDB/RCTSelectionFlags.h + O2_DEFINE_CONFIGURABLE(cfgEvtRCTFlagCheckerZDCCheck, bool, false, "Evt sel: RCT flag checker ZDC check"); + O2_DEFINE_CONFIGURABLE(cfgEvtRCTFlagCheckerLimitAcceptAsBad, bool, false, "Evt sel: RCT flag checker treat Limited Acceptance As Bad"); + } rctFlags; + + struct : ConfigurableGroup { + // Additional event selections + O2_DEFINE_CONFIGURABLE(cfgMaxOccupancy, int, 10000, "Maximum occupancy of selected events"); + O2_DEFINE_CONFIGURABLE(cfgCentMin, float, 0, "Minimum cenrality for selected events"); + O2_DEFINE_CONFIGURABLE(cfgCentMax, float, 90, "Maximum cenrality for selected events"); + } EvSel; + + // Configurables containing vector + O2_DEFINE_CONFIGURABLE(cfgVtxZ, float, 10.0f, "Accepted z-vertex range") + O2_DEFINE_CONFIGURABLE(cfgEtaMax, float, 0.8f, "Maximum track #eta") + O2_DEFINE_CONFIGURABLE(cfgPtMin, float, 0.2f, "Minimum track #P_{t}") + O2_DEFINE_CONFIGURABLE(cfgPtMax, float, 10.0f, "Maximum track #P_{t}") + O2_DEFINE_CONFIGURABLE(cfgDcaXYMax, float, 0.2f, "Maximum DCAxy") + O2_DEFINE_CONFIGURABLE(cfgDcaZMax, float, 2.0f, "Maximum DCAz") + + // Filter trackFilter = nabs(aod::track::eta) < cfgEtaMax && aod::track::pt > cfgPtMin&& aod::track::pt < cfgPtMax && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)) && nabs(aod::track::dcaXY) < cfgDcaXYMax&& nabs(aod::track::dcaZ) < cfgDcaZMax; + + // using UsedTracks = soa::Filtered>; + using ZDCCollisions = soa::Join, aod::SPTableZDC>; + using BCsRun3 = soa::Join; + + // Connect to ccdb + Service ccdb; + + HistogramRegistry registry{"registry"}; + + void init(InitContext const&) + { + ccdb->setURL("http://alice-ccdb.cern.ch"); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + + int64_t now = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + ccdb->setCreatedNotAfter(now); + + rctChecker.init(rctFlags.cfgEvtRCTFlagCheckerLabel, rctFlags.cfgEvtRCTFlagCheckerZDCCheck, rctFlags.cfgEvtRCTFlagCheckerLimitAcceptAsBad); + + AxisSpec axisCent = {100, 0, 100, "Centrality(%)"}; + AxisSpec axisEnergy = {300, 0, 300, "Energy"}; + AxisSpec axisRescaledDiff = {40, -2, 2, "(#E_{A}-#E_{C}) / (#E_{A}+#E_{C})"}; + + registry.add("hEnergyWithCent_ZNA_Common", "", {HistType::kTH2D, {axisEnergy, axisCent}}); + registry.add("hEnergyWithCent_ZNC_Common", "", {HistType::kTH2D, {axisEnergy, axisCent}}); + registry.add("hEnergyWithCent_RescaledDiff", "", {HistType::kTH2D, {axisRescaledDiff, axisCent}}); + registry.add("hEnergyWithCent_ZNA_1", "", {HistType::kTH2D, {axisEnergy, axisCent}}); + registry.add("hEnergyWithCent_ZNA_2", "", {HistType::kTH2D, {axisEnergy, axisCent}}); + registry.add("hEnergyWithCent_ZNA_3", "", {HistType::kTH2D, {axisEnergy, axisCent}}); + registry.add("hEnergyWithCent_ZNA_4", "", {HistType::kTH2D, {axisEnergy, axisCent}}); + registry.add("hEnergyWithCent_ZNC_1", "", {HistType::kTH2D, {axisEnergy, axisCent}}); + registry.add("hEnergyWithCent_ZNC_2", "", {HistType::kTH2D, {axisEnergy, axisCent}}); + registry.add("hEnergyWithCent_ZNC_3", "", {HistType::kTH2D, {axisEnergy, axisCent}}); + registry.add("hEnergyWithCent_ZNC_4", "", {HistType::kTH2D, {axisEnergy, axisCent}}); + registry.add("hEnergyWithCent_ZNA_SumSectors", "", {HistType::kTH2D, {axisEnergy, axisCent}}); + registry.add("hEnergyWithCent_ZNC_SumSectors", "", {HistType::kTH2D, {axisEnergy, axisCent}}); + registry.add("hEnergyWithCent_RescaledSumDiff", "", {HistType::kTH2D, {axisRescaledDiff, axisCent}}); + } + + void process(ZDCCollisions::iterator const& collision, BCsRun3 const& /*bcs*/, aod::Zdcs const& /*zdcs*/) + { + + double centrality = collision.centFT0C(); + // event selection + if (centrality < EvSel.cfgCentMin || centrality > EvSel.cfgCentMax || !collision.sel8() || std::abs(collision.posZ()) > cfgVtxZ) { + return; + } + + const auto& foundBC = collision.foundBC_as(); + if (!foundBC.has_zdc()) { + return; + } + + const auto& zdcCol = foundBC.zdc(); + + double SumEnergyZNA = zdcCol.energySectorZNA()[0] + zdcCol.energySectorZNA()[1] + zdcCol.energySectorZNA()[2] + zdcCol.energySectorZNA()[3]; + double SumEnergyZNC = zdcCol.energySectorZNC()[0] + zdcCol.energySectorZNC()[1] + zdcCol.energySectorZNC()[2] + zdcCol.energySectorZNC()[3]; + double commonDen = zdcCol.energyCommonZNA() + zdcCol.energyCommonZNC(); + double sumDen = SumEnergyZNA + SumEnergyZNC; + + if (commonDen > 1e-3) { + registry.fill(HIST("hEnergyWithCent_RescaledDiff"), + (zdcCol.energyCommonZNA() - zdcCol.energyCommonZNC()) / commonDen, + centrality); + } + if (sumDen > 1e-3) { + registry.fill(HIST("hEnergyWithCent_RescaledSumDiff"), + (SumEnergyZNA - SumEnergyZNC) / sumDen, + centrality); + } + registry.fill(HIST("hEnergyWithCent_ZNA_Common"), zdcCol.energyCommonZNA(), centrality); + registry.fill(HIST("hEnergyWithCent_ZNC_Common"), zdcCol.energyCommonZNC(), centrality); + registry.fill(HIST("hEnergyWithCent_ZNA_1"), zdcCol.energySectorZNA()[0], centrality); + registry.fill(HIST("hEnergyWithCent_ZNA_2"), zdcCol.energySectorZNA()[1], centrality); + registry.fill(HIST("hEnergyWithCent_ZNA_3"), zdcCol.energySectorZNA()[2], centrality); + registry.fill(HIST("hEnergyWithCent_ZNA_4"), zdcCol.energySectorZNA()[3], centrality); + registry.fill(HIST("hEnergyWithCent_ZNC_1"), zdcCol.energySectorZNC()[0], centrality); + registry.fill(HIST("hEnergyWithCent_ZNC_2"), zdcCol.energySectorZNC()[1], centrality); + registry.fill(HIST("hEnergyWithCent_ZNC_3"), zdcCol.energySectorZNC()[2], centrality); + registry.fill(HIST("hEnergyWithCent_ZNC_4"), zdcCol.energySectorZNC()[3], centrality); + registry.fill(HIST("hEnergyWithCent_ZNA_SumSectors"), SumEnergyZNA, centrality); + registry.fill(HIST("hEnergyWithCent_ZNC_SumSectors"), SumEnergyZNC, centrality); + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} From cd05deb9cadf15f4385865872f619d1592f29a21 Mon Sep 17 00:00:00 2001 From: Nasir Mehdi Malik <89008506+nasirmehdimalik@users.noreply.github.com> Date: Fri, 6 Mar 2026 18:38:26 +0530 Subject: [PATCH 195/347] [PWGLF] added DCAxy p-dependent cut and added rotational method (#15274) --- PWGLF/Tasks/Resonances/lambda1520_PbPb.cxx | 164 ++++++++++++++++----- 1 file changed, 127 insertions(+), 37 deletions(-) diff --git a/PWGLF/Tasks/Resonances/lambda1520_PbPb.cxx b/PWGLF/Tasks/Resonances/lambda1520_PbPb.cxx index d8edd64cdb9..6af3bde09f8 100644 --- a/PWGLF/Tasks/Resonances/lambda1520_PbPb.cxx +++ b/PWGLF/Tasks/Resonances/lambda1520_PbPb.cxx @@ -29,9 +29,6 @@ #include #include -#include -#include - #include using namespace o2; @@ -56,7 +53,15 @@ struct lambdaAnalysis_pb { Configurable cPMin{"cPMin", 0., "Minimum Track p"}; Configurable cEtaCut{"cEtaCut", 0.8, "Pseudorapidity cut"}; Configurable cDcaz{"cDcazMin", 1., "Minimum DCAz"}; - Configurable cDcaxy{"cDcaxyMin", 0.1, "Minimum DCAxy"}; + + Configurable> cDcaPtBinsPr{"cDcaPtBinsPr", {0.0f, 0.5f, 1.0f, 2.0f, 3.0f, 5.0f, 1000.0f}, "Proton pT bin edges for DCAxy cut"}; + + Configurable> cDcaXYBinsPr{"cDcaXYBinsPr", {0.020f, 0.015f, 0.010f, 0.007f, 0.005f, 0.004f}, "Proton max |DCAxy| per pT bin (cm)"}; + + // Kaon DCAxy — pT binned + Configurable> cDcaPtBinsKa{"cDcaPtBinsKa", {0.0f, 0.3f, 0.6f, 1.0f, 2.0f, 1000.0f}, "Kaon pT bin edges for DCAxy cut"}; + + Configurable> cDcaXYBinsKa{"cDcaXYBinsKa", {0.025f, 0.018f, 0.012f, 0.008f, 0.004f}, "Kaon max |DCAxy| per pT bin (cm)"}; Configurable isonlyQC{"isonlyQC", false, "only QC"}; Configurable isDeepAngle{"isDeepAngle", false, "Deep Angle cut"}; Configurable cfgDeepAngle{"cfgDeepAngle", 0.04, "Deep Angle cut value"}; @@ -108,6 +113,16 @@ struct lambdaAnalysis_pb { ConfigurableAxis cMixMultBins{"cMixMultBins", {VARIABLE_WIDTH, 0.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f, 100.0f, 200.0f}, "Mixing bins - multiplicity"}; ConfigurableAxis cMixEPAngle{"cMixEPAngle", {VARIABLE_WIDTH, -1.5708f, -1.25664f, -0.942478f, -0.628319f, 0.f, 0.628319f, 0.942478f, 1.25664f, 1.5708f}, "event plane"}; ConfigurableAxis occupancy_bins{"occupancy_bins", {VARIABLE_WIDTH, 0.0, 100, 500, 600, 1000, 1100, 1500, 1600, 2000, 2100, 2500, 2600, 3000, 3100, 3500, 3600, 4000, 4100, 4500, 4600, 5000, 5100, 9999}, "Binning of the occupancy axis"}; + Configurable cNofRotations{"cNofRotations", 10, "Number of rotations for rotational background"}; + Configurable rotationalcut{"rotationalcut", 6.f, "Rotational background angle window: PI/rotationalcut"}; + + // ── MC Event Selection Configurables ───────────────────────────────────── + Configurable cEvtMCAfterAllCuts{"cEvtMCAfterAllCuts", false, "MC event sel: isInAfterAllCuts"}; + Configurable cEvtMCINELgt0{"cEvtMCINELgt0", false, "MC event sel: isINELgt0"}; + Configurable cEvtMCSel8{"cEvtMCSel8", false, "MC event sel: isInSel8"}; + Configurable cEvtMCVtxIn10{"cEvtMCVtxIn10", false, "MC event sel: isVtxIn10"}; + Configurable cEvtMCTriggerTVX{"cEvtMCTriggerTVX", false, "MC event sel: isTriggerTVX"}; + Configurable cEvtMCRecINELgt0{"cEvtMCRecINELgt0", false, "MC event sel: isRecINELgt0"}; // Histogram Registry. HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -131,6 +146,7 @@ struct lambdaAnalysis_pb { AxisSpec axisDCAz = {cDCAzBins, "DCA_{z} (cm)"}; histos.add("Event/h1d_ft0_mult_percentile", "FT0 (%)", kTH2F, {axisCent, axisOccupancy}); + histos.add("Event/h_ft0_vz", "Collision Vertex Z position", kTH1F, {{100, -15., 15.}}); if (doprocessMix || doprocessMixDF || doprocessMixepDF) { histos.add("Event/mixing_vzVsmultpercentile", "FT0(%)", kTH3F, {axisCent, axisVz, axisEP}); } @@ -208,19 +224,58 @@ struct lambdaAnalysis_pb { if (std::abs(track.eta()) > cEtaCut) return false; - if (std::abs(track.dcaZ()) > cDcaz) + if (cPrimaryTrack && !track.isPrimaryTrack()) return false; - if (std::abs(track.dcaXY()) > cDcaxy) + if (cGlobalWoDCATrack && !track.isGlobalTrackWoDCA()) return false; - if (cPrimaryTrack && !track.isPrimaryTrack()) + if (cPVContributor && !track.isPVContributor()) return false; - if (cGlobalWoDCATrack && !track.isGlobalTrackWoDCA()) + return true; + } + // ── Proton DCA Selection ────────────────────────────────────────────────── + template + bool dcaSelectionProton(T const& track, float p) + { + auto ptBinsPr = static_cast>(cDcaPtBinsPr); + auto dcaXYPr = static_cast>(cDcaXYBinsPr); + int nBinsPr = static_cast(ptBinsPr.size()) - 1; + + bool dcaXYPassed = false; + for (int i = 0; i < nBinsPr; i++) { + if (p >= ptBinsPr[i] && p < ptBinsPr[i + 1] && + std::abs(track.dcaXY()) < dcaXYPr[i]) + dcaXYPassed = true; + } + if (!dcaXYPassed) return false; - if (cPVContributor && !track.isPVContributor()) + if (std::abs(track.dcaZ()) > cDcaz) + return false; + + return true; + } + + // ── Kaon DCA Selection ──────────────────────────────────────────────────── + template + bool dcaSelectionKaon(T const& track, float p) + { + auto ptBinsKa = static_cast>(cDcaPtBinsKa); + auto dcaXYKa = static_cast>(cDcaXYBinsKa); + int nBinsKa = static_cast(ptBinsKa.size()) - 1; + + bool dcaXYPassed = false; + for (int i = 0; i < nBinsKa; i++) { + if (p >= ptBinsKa[i] && p < ptBinsKa[i + 1] && + std::abs(track.dcaXY()) < dcaXYKa[i]) + dcaXYPassed = true; + } + if (!dcaXYPassed) + return false; + + if (std::abs(track.dcaZ()) > cDcaz) return false; return true; @@ -362,8 +417,6 @@ struct lambdaAnalysis_pb { void fillDataHistos(trackType const& trk1, trackType const& trk2, float mult, int occup = 100) { - TLorentzVector p1, p2, p; - TRandom* rn = new TRandom(); float p_ptot = 0., k_ptot = 0.; for (auto const& [trkPr, trkKa] : soa::combinations(soa::CombinationsFullIndexPolicy(trk1, trk2))) { @@ -412,6 +465,9 @@ struct lambdaAnalysis_pb { continue; if (!selectionPIDProton(trkPr, p_ptot) || !selectionPIDKaon(trkKa, k_ptot)) continue; + if (!dcaSelectionProton(trkPr, p_ptot) || !dcaSelectionKaon(trkKa, k_ptot)) + continue; + if (isDeepAngle && TMath::ACos((trkPr.pt() * trkKa.pt() + _pzPr * _pzKa) / (p_ptot * k_ptot)) < cfgDeepAngle) continue; @@ -461,39 +517,56 @@ struct lambdaAnalysis_pb { if (isonlyQC) continue; - // Invariant mass reconstruction. - p1.SetXYZM(_pxPr, _pyPr, _pzPr, MassProton); - p2.SetXYZM(_pxKa, _pyKa, _pzKa, MassKaonCharged); - p = p1 + p2; - if (std::abs(p.Rapidity()) > 0.5) - continue; + std::array pvec0 = {_pxPr, _pyPr, _pzPr}; + std::array pvec1 = {_pxKa, _pyKa, _pzKa}; + std::array, 2> arrMomrec = {pvec0, pvec1}; + + float _M = RecoDecay::m(arrMomrec, std::array{MassProton, MassKaonCharged}); + float _pt = RecoDecay::pt(std::array{_pxPr + _pxKa, _pyPr + _pyKa}); - auto _M = p.M(); - auto _pt = p.Pt(); + if (std::abs(RecoDecay::y(std::array{_pxPr + _pxKa, _pyPr + _pyKa, _pzPr + _pzKa}, MassLambda1520)) > 0.5) + continue; // Apply kinematic cuts. - if (cKinCuts) { - TVector3 v1(_pxPr, _pyPr, _pzPr); - TVector3 v2(_pxKa, _pyKa, _pzKa); - float alpha = v1.Angle(v2); - if (alpha > 1.4 && alpha < 2.4) - continue; - } // Fill Invariant Mass Histograms. if constexpr (!mix && !mc) { if (trkPr.sign() * trkKa.sign() < 0) { + if (trkPr.sign() > 0) histos.fill(HIST("Analysis/h4d_lstar_invm_US_PM"), _M, _pt, mult, occup); else histos.fill(HIST("Analysis/h4d_lstar_invm_US_MP"), _M, _pt, mult, occup); + if (doRotate) { - float theta = rn->Uniform(1.56, 1.58); - p1.RotateZ(theta); - p = p1 + p2; - if (std::abs(p.Rapidity()) < 0.5) { - histos.fill(HIST("Analysis/h4d_lstar_invm_rot"), p.M(), p.Pt(), mult, occup); + for (int i = 0; i < cNofRotations; i++) { + + float delta = o2::constants::math::PI / rotationalcut; + float theta2 = (o2::constants::math::PI - delta) + i * (2.f * delta / (cNofRotations - 1)); + + float phiRot = trkKa.phi() + theta2; + if (phiRot > o2::constants::math::TwoPI) + phiRot -= o2::constants::math::TwoPI; + if (phiRot < 0.f) + phiRot += o2::constants::math::TwoPI; + + float _pxKaRot = trkKa.pt() * std::cos(phiRot); + float _pyKaRot = trkKa.pt() * std::sin(phiRot); + + std::array pvec0rot = {_pxPr, _pyPr, _pzPr}; + std::array pvec1rot = {_pxKaRot, _pyKaRot, _pzKa}; + std::array, 2> arrMomRot = {pvec0rot, pvec1rot}; + + float _Mrot = RecoDecay::m(arrMomRot, std::array{MassProton, MassKaonCharged}); + float _ptRot = RecoDecay::pt(std::array{_pxPr + _pxKaRot, _pyPr + _pyKaRot}); + + if (std::abs(RecoDecay::y( + std::array{_pxPr + _pxKaRot, _pyPr + _pyKaRot, _pzPr + _pzKa}, + MassLambda1520)) > 0.5f) + continue; + + histos.fill(HIST("Analysis/h4d_lstar_invm_rot"), _Mrot, _ptRot, mult, occup); } } } else { @@ -542,6 +615,8 @@ struct lambdaAnalysis_pb { } using resoCols = soa::Join; + using resoMCCols = soa::Join; + using resoTracks = aod::ResoTracks; void processData(resoCols::iterator const& collision, resoTracks const& tracks) @@ -549,17 +624,32 @@ struct lambdaAnalysis_pb { // LOGF(info, " collisions: Index = %d %d", collision.globalIndex(),tracks.size()); histos.fill(HIST("Event/h1d_ft0_mult_percentile"), collision.cent(), 100); + histos.fill(HIST("Event/h_ft0_vz"), collision.posZ()); + fillDataHistos(tracks, tracks, collision.cent()); } PROCESS_SWITCH(lambdaAnalysis_pb, processData, "Process for Same Event Data", true); - void processMC(resoCols::iterator const& collision, + void processMC(resoMCCols::iterator const& collision, soa::Join const& tracks, aod::ResoMCParents const& resoParents) { + if (cEvtMCAfterAllCuts && !collision.isInAfterAllCuts()) + return; + if (cEvtMCINELgt0 && !collision.isINELgt0()) + return; + if (cEvtMCSel8 && !collision.isInSel8()) + return; + if (cEvtMCVtxIn10 && !collision.isVtxIn10()) + return; + if (cEvtMCTriggerTVX && !collision.isTriggerTVX()) + return; + if (cEvtMCRecINELgt0 && !collision.isRecINELgt0()) + return; auto mult = collision.cent(); histos.fill(HIST("Event/h1d_ft0_mult_percentile"), mult, 100); + histos.fill(HIST("Event/h_ft0_vz"), collision.posZ()); fillDataHistos(tracks, tracks, mult); // get MC pT-spectra @@ -587,9 +677,9 @@ struct lambdaAnalysis_pb { } for (auto const& part : resoParents) { - if (abs(part.pdgCode()) != lambda1520id) // // L* pdg_code = 3124 + if (std::abs(part.pdgCode()) != lambda1520id) // // L* pdg_code = 3124 continue; - if (abs(part.y()) > 0.5) { // rapidity cut + if (std::abs(part.y()) > 0.5) { // rapidity cut continue; } @@ -605,10 +695,10 @@ struct lambdaAnalysis_pb { if (!pass1 || !pass2) // If we have both decay products continue; + std::array pvec = {part.px(), part.py(), part.pz()}; + + float mass = RecoDecay::m(pvec, part.e()); - TLorentzVector p4; - p4.SetPxPyPzE(part.px(), part.py(), part.pz(), part.e()); - auto mass = p4.M(); if (part.pdgCode() > 0) histos.fill(HIST("Analysis/h3d_gen_lstar_PM"), mass, part.pt(), mult); else From baf99e512e0b33932696e2b41ce27f2d3f953ce9 Mon Sep 17 00:00:00 2001 From: Hamwooseok <168405791+Hamwooseok@users.noreply.github.com> Date: Fri, 6 Mar 2026 22:09:11 +0900 Subject: [PATCH 196/347] [PWGJE] modify the delta pT method to include jetless events (#15286) Co-authored-by: Wooseok Ham --- PWGJE/Tasks/jetBackgroundAnalysis.cxx | 81 ++++++++++++++------------- 1 file changed, 43 insertions(+), 38 deletions(-) diff --git a/PWGJE/Tasks/jetBackgroundAnalysis.cxx b/PWGJE/Tasks/jetBackgroundAnalysis.cxx index 4760c63e1e4..84925d2dafe 100644 --- a/PWGJE/Tasks/jetBackgroundAnalysis.cxx +++ b/PWGJE/Tasks/jetBackgroundAnalysis.cxx @@ -119,37 +119,38 @@ struct JetBackgroundAnalysisTask { template void bkgFluctuationsRandomCone(TCollisions const& collision, TJets const& jets, TTracks const& tracks, float centrality) { - if (jets.size() > 0) { // Since the purpose of the fluctuation measurement is jet correction, events with zero accepted jets (from the jetfinder cuts) are excluded - float randomConeEta = randomNumber.Uniform(trackEtaMin + randomConeR, trackEtaMax - randomConeR); - float randomConePhi = randomNumber.Uniform(0.0, o2::constants::math::TwoPI); - float randomConePt = 0; - for (auto const& track : tracks) { - if (jetderiveddatautilities::selectTrack(track, trackSelection)) { - float dPhi = RecoDecay::constrainAngle(track.phi() - randomConePhi, static_cast(-o2::constants::math::PI)); - float dEta = track.eta() - randomConeEta; - if (std::sqrt(dEta * dEta + dPhi * dPhi) < randomConeR) { - randomConePt += track.pt(); - } + float randomConeEta = randomNumber.Uniform(trackEtaMin + randomConeR, trackEtaMax - randomConeR); + float randomConePhi = randomNumber.Uniform(0.0, o2::constants::math::TwoPI); + float randomConePt = 0; + for (auto const& track : tracks) { + if (jetderiveddatautilities::selectTrack(track, trackSelection)) { + float dPhi = RecoDecay::constrainAngle(track.phi() - randomConePhi, static_cast(-o2::constants::math::PI)); + float dEta = track.eta() - randomConeEta; + if (std::sqrt(dEta * dEta + dPhi * dPhi) < randomConeR) { + randomConePt += track.pt(); } } - registry.fill(HIST("h2_centrality_rhorandomcone"), centrality, randomConePt - o2::constants::math::PI * randomConeR * randomConeR * collision.rho()); + } + registry.fill(HIST("h2_centrality_rhorandomcone"), centrality, randomConePt - o2::constants::math::PI * randomConeR * randomConeR * collision.rho()); - // randomised eta,phi for tracks, to assess part of fluctuations coming from statistically independently emitted particles - { - float randomConePt = 0; - for (auto const& track : tracks) { - if (jetderiveddatautilities::selectTrack(track, trackSelection)) { - float dPhi = RecoDecay::constrainAngle(randomNumber.Uniform(0.0, o2::constants::math::TwoPI) - randomConePhi, static_cast(-o2::constants::math::PI)); // ignores actual phi of track - float dEta = randomNumber.Uniform(trackEtaMin, trackEtaMax) - randomConeEta; // ignores actual eta of track - if (std::sqrt(dEta * dEta + dPhi * dPhi) < randomConeR) { - randomConePt += track.pt(); - } - } + // randomised eta,phi for tracks, to assess part of fluctuations coming from statistically independently emitted particles + float randomConePtRandomTrackDirection = 0; + for (auto const& track : tracks) { + if (jetderiveddatautilities::selectTrack(track, trackSelection)) { + float dPhi = RecoDecay::constrainAngle(randomNumber.Uniform(0.0, o2::constants::math::TwoPI) - randomConePhi, static_cast(-o2::constants::math::PI)); // ignores actual phi of track + float dEta = randomNumber.Uniform(trackEtaMin, trackEtaMax) - randomConeEta; // ignores actual eta of track + if (std::sqrt(dEta * dEta + dPhi * dPhi) < randomConeR) { + randomConePtRandomTrackDirection += track.pt(); } - registry.fill(HIST("h2_centrality_rhorandomconerandomtrackdirection"), centrality, randomConePt - o2::constants::math::PI * randomConeR * randomConeR * collision.rho()); } + } + registry.fill(HIST("h2_centrality_rhorandomconerandomtrackdirection"), centrality, randomConePtRandomTrackDirection - o2::constants::math::PI * randomConeR * randomConeR * collision.rho()); - // removing the leading jet from the random cone + // removing the leading jet from the random cone + const bool hasLead = jets.size() >= 1; + const bool hasSub = jets.size() >= 2; + float randomConePtWithoutLeadingJet = randomConePt; + if (hasLead) { float dPhiLeadingJet = RecoDecay::constrainAngle(jets.iteratorAt(0).phi() - randomConePhi, static_cast(-o2::constants::math::PI)); float dEtaLeadingJet = jets.iteratorAt(0).eta() - randomConeEta; @@ -162,41 +163,45 @@ struct JetBackgroundAnalysisTask { dEtaLeadingJet = jets.iteratorAt(0).eta() - randomConeEta; } if (jetWasInCone) { - randomConePt = 0.0; + randomConePtWithoutLeadingJet = 0.0; for (auto const& track : tracks) { if (jetderiveddatautilities::selectTrack(track, trackSelection)) { // if track selection is uniformTrack, dcaXY and dcaZ cuts need to be added as they aren't in the selection so that they can be studied here float dPhi = RecoDecay::constrainAngle(track.phi() - randomConePhi, static_cast(-o2::constants::math::PI)); float dEta = track.eta() - randomConeEta; if (std::sqrt(dEta * dEta + dPhi * dPhi) < randomConeR) { - randomConePt += track.pt(); + randomConePtWithoutLeadingJet += track.pt(); } } } } - registry.fill(HIST("h2_centrality_rhorandomconewithoutleadingjet"), centrality, randomConePt - o2::constants::math::PI * randomConeR * randomConeR * collision.rho()); - - // randomised eta,phi for tracks, to assess part of fluctuations coming from statistically independently emitted particles, removing tracks from 2 leading jets - double randomConePtWithoutOneLeadJet = 0; - double randomConePtWithoutTwoLeadJet = 0; + } + registry.fill(HIST("h2_centrality_rhorandomconewithoutleadingjet"), centrality, randomConePtWithoutLeadingJet - o2::constants::math::PI * randomConeR * randomConeR * collision.rho()); + + // randomised eta,phi for tracks, to assess part of fluctuations coming from statistically independently emitted particles, removing tracks from 2 leading jets + double randomConePtWithoutOneLeadJet = randomConePtRandomTrackDirection; + double randomConePtWithoutTwoLeadJet = randomConePtRandomTrackDirection; + if (hasLead) { + randomConePtWithoutOneLeadJet = 0.0; + randomConePtWithoutTwoLeadJet = 0.0; for (auto const& track : tracks) { if (jetderiveddatautilities::selectTrack(track, trackSelection)) { float dPhi = RecoDecay::constrainAngle(randomNumber.Uniform(0.0, o2::constants::math::TwoPI) - randomConePhi, static_cast(-o2::constants::math::PI)); // ignores actual phi of track float dEta = randomNumber.Uniform(trackEtaMin, trackEtaMax) - randomConeEta; // ignores actual eta of track if (std::sqrt(dEta * dEta + dPhi * dPhi) < randomConeR) { - if (!trackIsInJet(track, jets.iteratorAt(0))) { + const bool inLead = hasLead && trackIsInJet(track, jets.iteratorAt(0)); + const bool inSub = hasSub && trackIsInJet(track, jets.iteratorAt(1)); + if (!inLead) { randomConePtWithoutOneLeadJet += track.pt(); - if (jets.size() > 1 && !trackIsInJet(track, jets.iteratorAt(1))) { // if there are jets in the acceptance (from the jetfinder cuts) less than two then one cannot find 2 leading jets + if (!hasSub || !inSub) { randomConePtWithoutTwoLeadJet += track.pt(); } } } } } - registry.fill(HIST("h2_centrality_rhorandomconerandomtrackdirectionwithoutoneleadingjets"), centrality, randomConePtWithoutOneLeadJet - o2::constants::math::PI * randomConeR * randomConeR * collision.rho()); - if (jets.size() > 1) { - registry.fill(HIST("h2_centrality_rhorandomconerandomtrackdirectionwithouttwoleadingjets"), centrality, randomConePtWithoutTwoLeadJet - o2::constants::math::PI * randomConeR * randomConeR * collision.rho()); - } } + registry.fill(HIST("h2_centrality_rhorandomconerandomtrackdirectionwithoutoneleadingjets"), centrality, randomConePtWithoutOneLeadJet - o2::constants::math::PI * randomConeR * randomConeR * collision.rho()); + registry.fill(HIST("h2_centrality_rhorandomconerandomtrackdirectionwithouttwoleadingjets"), centrality, randomConePtWithoutTwoLeadJet - o2::constants::math::PI * randomConeR * randomConeR * collision.rho()); } void processRho(soa::Filtered>::iterator const& collision, soa::Filtered const& tracks) From 5fd8e915c0110a02c6e45ed351bb550b50c9b956 Mon Sep 17 00:00:00 2001 From: MattOckleton <149105337+MattOckleton@users.noreply.github.com> Date: Fri, 6 Mar 2026 14:51:29 +0000 Subject: [PATCH 197/347] [PWGJE] Adding D0+JET correlation task (#14795) --- PWGJE/Tasks/CMakeLists.txt | 4 + PWGJE/Tasks/jetCorrelationD0.cxx | 385 +++++++++++++++++++++++++++++++ 2 files changed, 389 insertions(+) create mode 100644 PWGJE/Tasks/jetCorrelationD0.cxx diff --git a/PWGJE/Tasks/CMakeLists.txt b/PWGJE/Tasks/CMakeLists.txt index 68fd3e9bdfb..224b0278f73 100644 --- a/PWGJE/Tasks/CMakeLists.txt +++ b/PWGJE/Tasks/CMakeLists.txt @@ -375,6 +375,10 @@ if(FastJet_FOUND) SOURCES jetFormationTimeReclustering.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(jet-correlation-d0 + SOURCES jetCorrelationD0.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore + COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(hf-debug SOURCES hfDebug.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore diff --git a/PWGJE/Tasks/jetCorrelationD0.cxx b/PWGJE/Tasks/jetCorrelationD0.cxx new file mode 100644 index 00000000000..504928dd56b --- /dev/null +++ b/PWGJE/Tasks/jetCorrelationD0.cxx @@ -0,0 +1,385 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +// +/// \file jetCorrelationD0.cxx +/// \brief Task for analysing D0 triggered jet events. +/// \author Matthew Ockleton matthew.ockleton@cern.ch, University of Liverpool + +#include "PWGHF/Core/DecayChannels.h" +#include "PWGHF/DataModel/AliasTables.h" +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" + +#include "Common/Core/RecoDecay.h" + +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/Logger.h" +#include "Framework/runDataProcessing.h" +#include +#include + +#include + +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +namespace o2::aod +{ + +namespace d0collisionInfo +{ +DECLARE_SOA_COLUMN(PosZ, posZ, float); +} // namespace d0collisionInfo + +DECLARE_SOA_TABLE(CollisionTables, "AOD", "COLLINFOTABLE", + o2::soa::Index<>, + d0collisionInfo::PosZ); + +DECLARE_SOA_TABLE(McCollisionTables, "AOD", "MCCOLLINFOTABLE", + o2::soa::Index<>, + d0collisionInfo::PosZ); + +namespace collisionInfo +{ +DECLARE_SOA_INDEX_COLUMN(CollisionTable, collisionTable); +DECLARE_SOA_INDEX_COLUMN(McCollisionTable, mcCollisionTable); +} // namespace collisionInfo +namespace d0Info +{ +// D0 +DECLARE_SOA_COLUMN(D0PromptBDT, d0PromptBDT, float); +DECLARE_SOA_COLUMN(D0NonPromptBDT, d0NonPromptBDT, float); +DECLARE_SOA_COLUMN(D0BkgBDT, d0BkgBDT, float); +DECLARE_SOA_COLUMN(D0M, d0M, float); +DECLARE_SOA_COLUMN(D0Pt, d0Pt, float); +DECLARE_SOA_COLUMN(D0Eta, d0Eta, float); +DECLARE_SOA_COLUMN(D0Phi, d0Phi, float); +DECLARE_SOA_COLUMN(D0Y, d0Y, float); +DECLARE_SOA_COLUMN(D0McOrigin, d0McOrigin, float); +DECLARE_SOA_COLUMN(D0MD, d0MD, float); +DECLARE_SOA_COLUMN(D0PtD, d0PtD, float); +DECLARE_SOA_COLUMN(D0EtaD, d0EtaD, float); +DECLARE_SOA_COLUMN(D0PhiD, d0PhiD, float); +DECLARE_SOA_COLUMN(D0Reflection, d0Reflection, int); +} // namespace d0Info + +DECLARE_SOA_TABLE(D0DataTables, "AOD", "D0DATATABLE", + o2::soa::Index<>, + collisionInfo::CollisionTableId, + d0Info::D0PromptBDT, + d0Info::D0NonPromptBDT, + d0Info::D0BkgBDT, + d0Info::D0M, + d0Info::D0Pt, + d0Info::D0Eta, + d0Info::D0Phi, + d0Info::D0Y); + +DECLARE_SOA_TABLE(D0McPTables, "AOD", "D0MCPARTICLELEVELTABLE", + o2::soa::Index<>, + collisionInfo::McCollisionTableId, + d0Info::D0McOrigin, + d0Info::D0Pt, + d0Info::D0Eta, + d0Info::D0Phi, + d0Info::D0Y); + +namespace jetInfo +{ +// D0 tables +DECLARE_SOA_INDEX_COLUMN(D0DataTable, d0Data); +DECLARE_SOA_INDEX_COLUMN(D0McPTable, d0MCP); +// Jet +DECLARE_SOA_COLUMN(JetPt, jetPt, float); +DECLARE_SOA_COLUMN(JetEta, jetEta, float); +DECLARE_SOA_COLUMN(JetPhi, jetPhi, float); +// D0-jet +DECLARE_SOA_COLUMN(D0JetDeltaPhi, d0JetDeltaPhi, float); +} // namespace jetInfo + +DECLARE_SOA_TABLE_STAGED(JetDataTables, "JETDATATABLE", + o2::soa::Index<>, + collisionInfo::CollisionTableId, + jetInfo::D0DataTableId, + jetInfo::JetPt, + jetInfo::JetEta, + jetInfo::JetPhi, + jetInfo::D0JetDeltaPhi); + +DECLARE_SOA_TABLE_STAGED(JetMCPTables, "JETMCPTABLE", + o2::soa::Index<>, + collisionInfo::McCollisionTableId, + jetInfo::D0McPTableId, + jetInfo::JetPt, + jetInfo::JetEta, + jetInfo::JetPhi, + jetInfo::D0JetDeltaPhi); + +} // namespace o2::aod + +struct JetCorrelationD0 { + // Define new table + Produces tableCollision; + Produces tableMcCollision; + Produces tableD0; + Produces tableD0MCParticle; + Produces tableJet; + Produces tableJetMCParticle; + + // Configurables + Configurable eventSelections{"eventSelections", "sel8", "choose event selection"}; + Configurable skipMBGapEvents{"skipMBGapEvents", false, "decide to run over MB gap events or not"}; + Configurable applyRCTSelections{"applyRCTSelections", true, "decide to apply RCT selections"}; + // Configurable triggerMasks{"triggerMasks", "", "possible JE Trigger masks: fJetChLowPt,fJetChHighPt,fTrackLowPt,fTrackHighPt,fJetD0ChLowPt,fJetD0ChHighPt,fJetLcChLowPt,fJetLcChHighPt,fEMCALReadout,fJetFullHighPt,fJetFullLowPt,fJetNeutralHighPt,fJetNeutralLowPt,fGammaVeryHighPtEMCAL,fGammaVeryHighPtDCAL,fGammaHighPtEMCAL,fGammaHighPtDCAL,fGammaLowPtEMCAL,fGammaLowPtDCAL,fGammaVeryLowPtEMCAL,fGammaVeryLowPtDCAL"}; + Configurable jetPtCutMin{"jetPtCutMin", 5.0, "minimum value of jet pt"}; + Configurable d0PtCutMin{"d0PtCutMin", 1.0, "minimum value of d0 pt"}; + Configurable vertexZCut{"vertexZCut", 10.0, "Accepted z-vertex range"}; + Configurable pTHatExponent{"pTHatExponent", 6.0, "exponent of the event weight for the calculation of pTHat"}; + Configurable pTHatMaxMCD{"pTHatMaxMCD", 999.0, "maximum fraction of hard scattering for jet acceptance in detector MC"}; + Configurable pTHatMaxMCP{"pTHatMaxMCP", 999.0, "maximum fraction of hard scattering for jet acceptance in particle MC"}; + Configurable pTHatAbsoluteMin{"pTHatAbsoluteMin", -99.0, "minimum value of pTHat"}; + + // Filters + Filter eventCuts = (nabs(aod::jcollision::posZ) < vertexZCut); + std::vector eventSelectionBits; + + // Histograms + HistogramRegistry registry{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + template + void fillD0Histograms(T const& d0, U const& scores) + { + registry.fill(HIST("hD0MlBkg"), scores[0]); + registry.fill(HIST("hD0MlNonPrompt"), scores[1]); + registry.fill(HIST("hD0MlPrompt"), scores[2]); + + registry.fill(HIST("hD0Pt"), d0.pt()); + registry.fill(HIST("hD0M"), d0.m()); + registry.fill(HIST("hD0Eta"), d0.eta()); + registry.fill(HIST("hD0Phi"), d0.phi()); + } + template + void fillJetHistograms(T const& jet, U const& dphi) + { + registry.fill(HIST("hJetPt"), jet.pt()); + registry.fill(HIST("hJetEta"), jet.eta()); + registry.fill(HIST("hJetPhi"), jet.phi()); + registry.fill(HIST("hJet3D"), jet.pt(), jet.eta(), jet.phi()); + registry.fill(HIST("h_Jet_pT_D0_Jet_dPhi"), jet.pt(), dphi); + } + + template + bool applyCollisionSelections(T const& collision) + { + registry.fill(HIST("hCollisions"), 0.5); // All collisions + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { + return false; + } + registry.fill(HIST("hCollisions"), 1.5); // Selected collisions + registry.fill(HIST("hZvtxSelected"), collision.posZ()); + return true; + } + + template + // Jetbase is an MCD jet. We then loop through jettagv(MCP jets) to test if they match + // void fillMatchedHistograms(T const& jetBase, float weight = 1.0) // float leadingTrackPtBase, + void fillMatchedHistograms(T const& jetsBase, U const&, float weight = 1.0, float rho = 0.0) + { + for (const auto& jetBase : jetsBase) { + if (jetBase.has_matchedJetGeo()) { // geometric matching + for (auto& jetTag : jetBase.template matchedJetGeo_as>()) { + registry.fill(HIST("hPtMatched"), jetBase.pt() - (rho * jetBase.area()), jetTag.pt(), weight); + registry.fill(HIST("hPtMatched1d"), jetTag.pt(), weight); + registry.fill(HIST("hPhiMatched"), jetBase.phi(), jetTag.phi(), weight); + registry.fill(HIST("hEtaMatched"), jetBase.eta(), jetTag.eta(), weight); + registry.fill(HIST("hPtResolution"), jetTag.pt(), (jetTag.pt() - (jetBase.pt() - (rho * jetBase.area()))) / jetTag.pt(), weight); + registry.fill(HIST("hPhiResolution"), jetTag.pt(), jetTag.phi() - jetBase.phi(), weight); + registry.fill(HIST("hEtaResolution"), jetTag.pt(), jetTag.eta() - jetBase.eta(), weight); + } + } + } + } + void init(InitContext const&) + { + eventSelectionBits = jetderiveddatautilities::initialiseEventSelectionBits(static_cast(eventSelections)); + // General Axes + AxisSpec axisEta = {100, -1.0, 1.0, "#eta"}; + AxisSpec axisPhi = {100, 0.0, o2::constants::math::TwoPI, "#phi"}; + AxisSpec axisInvMass = {500, 0, 10, "M (GeV/c)"}; + + // General Histograms + registry.add("hCollisions", "event status;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}); + registry.add("hZvtxSelected", "Z vertex position;Z_{vtx};entries", {HistType::kTH1F, {{80, -20, 20}}}); + + // D0 Histograms + registry.add("hD0MlPrompt", "D0 ML Prompt Scores", {HistType::kTH1F, {{100, -1.0, 2.0}}}); + registry.add("hD0MlNonPrompt", "D0 ML NonPrompt Scores", {HistType::kTH1F, {{100, -1.0, 2.0}}}); + registry.add("hD0MlBkg", "D0 ML Background Scores", {HistType::kTH1F, {{100, -1.0, 2.0}}}); + + registry.add("hD0Pt", "D^{0} p_{T};p_{T}^{D^{0}} (GeV/c);entries", {HistType::kTH1F, {{500, -100, 400, "p_{T}^{D^{0}} (GeV/c)"}}}); + registry.add("hD0M", "D^{0} Mass;M_{#pi K} (GeV/c);entries", HistType::kTH1F, {axisInvMass}); + registry.add("hD0Eta", "D^{0} #eta ;#eta_{D^{0}};entries", HistType::kTH1F, {axisEta}); + registry.add("hD0Phi", "D^{0} #phi ;#phi_{D^{0}};entries", HistType::kTH1F, {axisPhi}); + + // Jet Histograms + registry.add("hJetPt", "jet p_{T};p_{T,jet};entries", {HistType::kTH1F, {{500, -100, 400}}}); + registry.add("hJetEta", "jet #eta;#eta_{jet};entries", HistType::kTH1F, {axisEta}); + registry.add("hJetPhi", "jet #phi;#phi_{jet};entries", HistType::kTH1F, {axisPhi}); + registry.add("hJet3D", "3D jet distribution;p_{T};#eta;#phi", {HistType::kTH3F, {{500, -100, 400}, {100, -1.0, 1.0}, {100, 0.0, o2::constants::math::TwoPI}}}); + registry.add("h_Jet_pT_D0_Jet_dPhi", "p_{T, jet} vs #Delta #phi _{D^{0}, jet}", kTH2F, {{100, 0, 100}, {100, 0, o2::constants::math::TwoPI}}); + + // Matching histograms + registry.add("hPtMatched", "p_{T} matching;p_{T,det};p_{T,part}", {HistType::kTH2F, {{500, -100, 400}, {400, 0, 400}}}); + registry.add("hPtMatched1d", "p_{T} matching 1d;p_{T,part}", {HistType::kTH1F, {{400, 0, 400}}}); + registry.add("hPhiMatched", "#phi matching;#phi_{det};#phi_{part}", {HistType::kTH2F, {{100, 0.0, o2::constants::math::TwoPI}, {100, 0.0, o2::constants::math::TwoPI}}}); + registry.add("hEtaMatched", "#eta matching;#eta_{det};#eta_{part}", {HistType::kTH2F, {{100, -1, 1}, {100, -1, 1}}}); + registry.add("hPtResolution", "p_{T} resolution;p_{T,part};Relative Resolution", {HistType::kTH2F, {{400, 0, 400}, {1000, -5.0, 5.0}}}); + registry.add("hPhiResolution", "#phi resolution;#p_{T,part};Resolution", {HistType::kTH2F, {{400, 0, 400}, {1000, -7.0, 7.0}}}); + registry.add("hEtaResolution", "#eta resolution;#p_{T,part};Resolution", {HistType::kTH2F, {{400, 0, 400}, {1000, -1.0, 1.0}}}); + } + void processData(soa::Filtered::iterator const& collision, + aod::CandidatesD0Data const& d0Candidates, + soa::Join const& jets) + { + if (!applyCollisionSelections(collision)) { + return; + } + tableCollision(collision.posZ()); + for (const auto& d0Candidate : d0Candidates) { + if (d0Candidate.pt() < d0PtCutMin) { // once settled on a mlcut, then add the lower bound of the systematics as a cut here + continue; + } + const auto scores = d0Candidate.mlScores(); + fillD0Histograms(d0Candidate, scores); + tableD0(tableCollision.lastIndex(), + scores[2], + scores[1], + scores[0], + d0Candidate.m(), + d0Candidate.pt(), + d0Candidate.eta(), + d0Candidate.phi(), + d0Candidate.y()); + for (const auto& jet : jets) { + if (jet.pt() < jetPtCutMin) { + continue; + } + float dphi = RecoDecay::constrainAngle(jet.phi() - d0Candidate.phi()); + if (abs(dphi - M_PI) > (M_PI / 2)) { // this is quite loose instead of pi/2 could do 0.6 + continue; + } + fillJetHistograms(jet, dphi); + tableJet(tableCollision.lastIndex(), + tableD0.lastIndex(), + jet.pt(), + jet.eta(), + jet.phi(), + dphi); + } + } + } + PROCESS_SWITCH(JetCorrelationD0, processData, "charged particle level jet analysis", true); + + void processMCDetector(soa::Filtered::iterator const& collision, + aod::CandidatesD0MCD const& d0Candidates, + soa::Join const& jets) + { + if (!applyCollisionSelections(collision)) { + return; + } + tableCollision(collision.posZ()); + for (const auto& d0Candidate : d0Candidates) { + if (d0Candidate.pt() < d0PtCutMin) { // once settled on a mlcut, then add the lower biund of the systematics as a cut here + continue; + } + const auto scores = d0Candidate.mlScores(); + fillD0Histograms(d0Candidate, scores); + tableD0(tableCollision.lastIndex(), // might want to add some more detector level D0 quantities like prompt or non prompt info + scores[2], + scores[1], + scores[0], + d0Candidate.m(), + d0Candidate.pt(), + d0Candidate.eta(), + d0Candidate.phi(), + d0Candidate.y()); + for (const auto& jet : jets) { + if (jet.pt() < jetPtCutMin) { + continue; + } + float dphi = RecoDecay::constrainAngle(jet.phi() - d0Candidate.phi()); + if (abs(dphi - M_PI) > (M_PI / 2)) { // this is quite loose instead of pi/2 could do 0.6 + continue; + } + fillJetHistograms(jet, dphi); + tableJet(tableCollision.lastIndex(), + tableD0.lastIndex(), + jet.pt(), + jet.eta(), + jet.phi(), + dphi); + } + } + } + PROCESS_SWITCH(JetCorrelationD0, processMCDetector, "charged particle level jet analysis", false); + + void processMCParticle(aod::JetMcCollision const& collision, + aod::CandidatesD0MCP const& d0MCPCandidates, + soa::Filtered> const& jets) + { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { // build without this + return; + } + tableMcCollision(collision.posZ()); + for (const auto& d0MCPCandidate : d0MCPCandidates) { + if (d0MCPCandidate.pt() < d0PtCutMin) { + continue; + } + tableD0MCParticle(tableCollision.lastIndex(), + d0MCPCandidate.originMcGen(), + d0MCPCandidate.pt(), + d0MCPCandidate.eta(), + d0MCPCandidate.phi(), + d0MCPCandidate.y()); + + for (const auto& jet : jets) { + if (jet.pt() < jetPtCutMin) { + continue; + } + float dphi = RecoDecay::constrainAngle(jet.phi() - d0MCPCandidate.phi()); + if (abs(dphi - M_PI) > (M_PI / 2)) { + continue; + } + fillJetHistograms(jet, dphi); + tableJetMCParticle(tableCollision.lastIndex(), + tableD0MCParticle.lastIndex(), + jet.pt(), + jet.eta(), + jet.phi(), + dphi); + } + } + } + PROCESS_SWITCH(JetCorrelationD0, processMCParticle, "process MC Particle jets", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} From bab6b719ca4c3e895ad9bc93d1a7d2ed627e3955 Mon Sep 17 00:00:00 2001 From: SCHOTTER Romain <47983209+romainschotter@users.noreply.github.com> Date: Fri, 6 Mar 2026 15:53:31 +0100 Subject: [PATCH 198/347] [PWGLF] Fix missing update of the TPCdrift manager (#15194) --- PWGLF/Utils/strangenessBuilderModule.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/PWGLF/Utils/strangenessBuilderModule.h b/PWGLF/Utils/strangenessBuilderModule.h index 136f93be492..7dc1bc57ace 100644 --- a/PWGLF/Utils/strangenessBuilderModule.h +++ b/PWGLF/Utils/strangenessBuilderModule.h @@ -897,6 +897,9 @@ class BuilderModule // handle TPC-only tracks properly (photon conversions) if (v0BuilderOpts.moveTPCOnlyTracks) { + if (collision.has_bc()) { + mVDriftMgr.update(collision.template bc_as().timestamp()); + } if (isPosTPCOnly) { // Nota bene: positive is TPC-only -> this entire V0 merits treatment as photon candidate posTrackPar.setPID(o2::track::PID::Electron); @@ -1368,6 +1371,9 @@ class BuilderModule pvX = collision.posX(); pvY = collision.posY(); pvZ = collision.posZ(); + if (v0BuilderOpts.moveTPCOnlyTracks && collision.has_bc()) { + mVDriftMgr.update(collision.template bc_as().timestamp()); + } } auto const& posTrack = tracks.rawIteratorAt(v0.posTrackId); auto const& negTrack = tracks.rawIteratorAt(v0.negTrackId); From 10e594588a68293c8096a55f21600f64ba1308c4 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Fri, 6 Mar 2026 15:58:16 +0100 Subject: [PATCH 199/347] [PWGEM/Dilepton] add an option for ITSsa in MC (#15291) --- PWGEM/Dilepton/Core/DielectronCut.h | 45 ++++++++++--------- PWGEM/Dilepton/Core/SingleTrackQCMC.h | 2 + .../TableProducer/skimmerPrimaryElectron.cxx | 37 +++++++++------ 3 files changed, 48 insertions(+), 36 deletions(-) diff --git a/PWGEM/Dilepton/Core/DielectronCut.h b/PWGEM/Dilepton/Core/DielectronCut.h index 5c629c3f45d..916cb5898ad 100644 --- a/PWGEM/Dilepton/Core/DielectronCut.h +++ b/PWGEM/Dilepton/Core/DielectronCut.h @@ -225,34 +225,35 @@ class DielectronCut : public TNamed } } - // if (!mIncludeITSsa && (!track.hasITS() || !track.hasTPC())) { // track has to be ITS-TPC matched track - // return false; - // } + if (!mIncludeITSsa && (!track.hasITS() || !track.hasTPC())) { // track has to be ITS-TPC matched track + return false; + } // if ((track.hasITS() && !track.hasTPC() && !track.hasTRD() && !track.hasTOF()) && track.pt() > mMaxPtITSsa) { // ITSsa // return false; // } // TPC cuts - if (!IsSelectedTrack(track, DielectronCuts::kTPCNCls)) { - return false; - } - if (!IsSelectedTrack(track, DielectronCuts::kTPCCrossedRows)) { - return false; - } - if (!IsSelectedTrack(track, DielectronCuts::kTPCCrossedRowsOverNCls)) { - return false; - } - if (!IsSelectedTrack(track, DielectronCuts::kTPCFracSharedClusters)) { - return false; - } - if (!IsSelectedTrack(track, DielectronCuts::kRelDiffPin)) { - return false; - } - if (!IsSelectedTrack(track, DielectronCuts::kTPCChi2NDF)) { - return false; + if (track.hasTPC()) { + if (!IsSelectedTrack(track, DielectronCuts::kTPCNCls)) { + return false; + } + if (!IsSelectedTrack(track, DielectronCuts::kTPCCrossedRows)) { + return false; + } + if (!IsSelectedTrack(track, DielectronCuts::kTPCCrossedRowsOverNCls)) { + return false; + } + if (!IsSelectedTrack(track, DielectronCuts::kTPCFracSharedClusters)) { + return false; + } + if (!IsSelectedTrack(track, DielectronCuts::kRelDiffPin)) { + return false; + } + if (!IsSelectedTrack(track, DielectronCuts::kTPCChi2NDF)) { + return false; + } } - if (mApplyPF && !IsSelectedTrack(track, DielectronCuts::kPrefilter)) { return false; } @@ -609,7 +610,7 @@ class DielectronCut : public TNamed float mMinMeanClusterSizeITS{0.0}, mMaxMeanClusterSizeITS{1e10f}; // x cos(lmabda) // float mMinP_ITSClusterSize{0.0}, mMaxP_ITSClusterSize{0.0}; bool mIncludeITSsa{false}; - float mMaxPtITSsa{0.15}; + float mMaxPtITSsa{1e+10}; // pid cuts int mPIDScheme{-1}; diff --git a/PWGEM/Dilepton/Core/SingleTrackQCMC.h b/PWGEM/Dilepton/Core/SingleTrackQCMC.h index c10f2936601..ee683925809 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQCMC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQCMC.h @@ -181,6 +181,7 @@ struct SingleTrackQCMC { Configurable cfg_min_pin_pirejTPC{"cfg_min_pin_pirejTPC", 0.f, "min. pin for pion rejection in TPC"}; Configurable cfg_max_pin_pirejTPC{"cfg_max_pin_pirejTPC", 1e+10, "max. pin for pion rejection in TPC"}; Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; + Configurable includeITSsa{"includeITSsa", false, "Flag to include ITSsa tracks only for MC. switch ON only if needed."}; // configuration for PID ML Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; @@ -519,6 +520,7 @@ struct SingleTrackQCMC { fDielectronCut.RequireITSib1st(dielectroncuts.cfg_require_itsib_1st); fDielectronCut.SetChi2TOF(0.0, dielectroncuts.cfg_max_chi2tof); fDielectronCut.SetRelDiffPin(dielectroncuts.cfg_min_rel_diff_pin, dielectroncuts.cfg_max_rel_diff_pin); + fDielectronCut.IncludeITSsa(dielectroncuts.includeITSsa, 1e+10); // for eID fDielectronCut.SetPIDScheme(dielectroncuts.cfg_pid_scheme); diff --git a/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx index 8148a855f6d..dcc367c9ba3 100644 --- a/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx +++ b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx @@ -81,6 +81,8 @@ struct skimmerPrimaryElectron { Configurable min_tpc_cr_findable_ratio{"min_tpc_cr_findable_ratio", 0.8, "min. TPC Ncr/Nf ratio"}; Configurable min_ncluster_its{"min_ncluster_its", 4, "min ncluster its"}; Configurable min_ncluster_itsib{"min_ncluster_itsib", 1, "min ncluster itsib"}; + Configurable minchi2tpc{"minchi2tpc", 0.0, "min. chi2/NclsTPC"}; + Configurable minchi2its{"minchi2its", 0.0, "min. chi2/NclsITS"}; Configurable maxchi2tpc{"maxchi2tpc", 5.0, "max. chi2/NclsTPC"}; Configurable maxchi2its{"maxchi2its", 6.0, "max. chi2/NclsITS"}; Configurable minpt{"minpt", 0.15, "min pt for ITS-TPC track"}; @@ -104,6 +106,7 @@ struct skimmerPrimaryElectron { Configurable maxMeanITSClusterSize{"maxMeanITSClusterSize", 16, "max x cos(lambda)"}; Configurable storeOnlyTrueElectronMC{"storeOnlyTrueElectronMC", false, "Flag to store only true electron in MC"}; Configurable minNelectron{"minNelectron", 0, "min number of electron candidates per collision"}; + Configurable includeITSsa{"includeITSsa", false, "Flag to include ITSsa tracks only for MC. switch ON only if needed."}; Configurable useTOFNSigmaDeltaBC{"useTOFNSigmaDeltaBC", false, "Flag to shift delta BC for TOF n sigma (only with TTCA)"}; // configuration for PID ML @@ -288,11 +291,11 @@ struct skimmerPrimaryElectron { return false; } - if (!track.hasITS() || !track.hasTPC()) { + if (!track.hasITS()) { return false; } - if (track.itsChi2NCl() < 0.f || maxchi2its < track.itsChi2NCl()) { + if (track.itsChi2NCl() < minchi2its || maxchi2its < track.itsChi2NCl()) { return false; } if (track.itsNCls() < min_ncluster_its) { @@ -302,24 +305,30 @@ struct skimmerPrimaryElectron { return false; } - if (track.tpcChi2NCl() < 0.f || maxchi2tpc < track.tpcChi2NCl()) { + if (!includeITSsa && (!track.hasITS() || !track.hasTPC())) { return false; } - if (track.tpcNClsFound() < min_ncluster_tpc) { - return false; - } + if (track.hasTPC()) { + if (track.tpcChi2NCl() < minchi2tpc || maxchi2tpc < track.tpcChi2NCl()) { + return false; + } - if (track.tpcNClsCrossedRows() < mincrossedrows) { - return false; - } + if (track.tpcNClsFound() < min_ncluster_tpc) { + return false; + } - if (track.tpcCrossedRowsOverFindableCls() < min_tpc_cr_findable_ratio) { - return false; - } + if (track.tpcNClsCrossedRows() < mincrossedrows) { + return false; + } - if (track.tpcFractionSharedCls() > max_frac_shared_clusters_tpc) { - return false; + if (track.tpcCrossedRowsOverFindableCls() < min_tpc_cr_findable_ratio) { + return false; + } + + if (track.tpcFractionSharedCls() > max_frac_shared_clusters_tpc) { + return false; + } } o2::dataformats::DCA mDcaInfoCov; From c419513c7f460e94d6bab9cc2160764015a6b814 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Fri, 6 Mar 2026 16:09:04 +0100 Subject: [PATCH 200/347] [PWGEM/Dilepton] fix in muon tree MC (#15292) --- PWGEM/Dilepton/DataModel/lmeeMLTables.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/PWGEM/Dilepton/DataModel/lmeeMLTables.h b/PWGEM/Dilepton/DataModel/lmeeMLTables.h index 9803a79ac62..ebc5309fe00 100644 --- a/PWGEM/Dilepton/DataModel/lmeeMLTables.h +++ b/PWGEM/Dilepton/DataModel/lmeeMLTables.h @@ -55,6 +55,10 @@ DECLARE_SOA_COLUMN(TPCNClsPID, tpcNClsPID, uint8_t); //! DECLARE_SOA_COLUMN(IsForValidation, isForValidation, bool); //! DECLARE_SOA_COLUMN(Sign, sign, short); //! DECLARE_SOA_COLUMN(P, p, float); //! +DECLARE_SOA_COLUMN(PtGen, ptGen, float); //! +DECLARE_SOA_COLUMN(EtaGen, etaGen, float); //! +DECLARE_SOA_COLUMN(PhiGen, phiGen, float); //! + // DECLARE_SOA_DYNAMIC_COLUMN(P, p, [](float pt, float eta) -> float { return pt * std::cosh(eta); }); DECLARE_SOA_DYNAMIC_COLUMN(MeanClusterSizeITS, meanClusterSizeITS, [](uint32_t itsClusterSizes) -> float { int total_cluster_size = 0, nl = 0; @@ -141,7 +145,7 @@ DECLARE_SOA_TABLE_VERSIONED(EMFwdTracksForML_000, "AOD", "EMFWDTRKML", 0, //! fwdtrack::Chi2, fwdtrack::Chi2MatchMCHMID, fwdtrack::Chi2MatchMCHMFT, // fwdtrack::MCHBitMap, fwdtrack::MIDBitMap, fwdtrack::MIDBoards, fwdtrack::MFTClusterSizesAndTrackFlags, emmlfwdtrack::Chi2MFT, emmlfwdtrack::NClustersMFT, mcparticle::PdgCode, emmlfwdtrack::IsPrimary, emmlfwdtrack::IsCorrectMatchMFTMCH, - mcparticle::Pt, mcparticle::Eta, mcparticle::Phi); + emmltrack::PtGen, emmltrack::EtaGen, emmltrack::PhiGen); using EMFwdTracksForML = EMFwdTracksForML_000; // iterators From 1777a03f907c900e8f2c562afcadfa1dd0931b9a Mon Sep 17 00:00:00 2001 From: Stefanie Mrozinski <63045530+Steffimro@users.noreply.github.com> Date: Fri, 6 Mar 2026 18:55:14 +0100 Subject: [PATCH 201/347] [PWGLF,PWGMM] Add new BC classifications (#15298) --- PWGMM/Lumi/Tasks/lumiStabilityLightIons.cxx | 699 ++++++++++++++------ 1 file changed, 499 insertions(+), 200 deletions(-) diff --git a/PWGMM/Lumi/Tasks/lumiStabilityLightIons.cxx b/PWGMM/Lumi/Tasks/lumiStabilityLightIons.cxx index a43b13b530a..8ad19ef30a6 100644 --- a/PWGMM/Lumi/Tasks/lumiStabilityLightIons.cxx +++ b/PWGMM/Lumi/Tasks/lumiStabilityLightIons.cxx @@ -12,7 +12,8 @@ /// \file lumiStabilityLightIons.cxx /// \brief Analysis over BCs to study the luminosity stability along time /// -/// \author Nicolas Strangmann (nicolas.strangmann@cern.ch) - Goethe University Frankfurt, Stefanie Mrozinski (stefanie.mrozinski@cern.ch) - Goethe University Frankfurt +/// \author Nicolas Strangmann (nicolas.strangmann@cern.ch) - Goethe University Frankfurt +/// \author Stefanie Mrozinski (stefanie.mrozinski@cern.ch) - Goethe University Frankfurt #include "Common/CCDB/ctpRateFetcher.h" #include "Common/Core/MetadataHelper.h" @@ -27,8 +28,11 @@ #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" +#include +#include #include #include +#include #include #include @@ -36,7 +40,7 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -o2::common::core::MetadataHelper metadataInfo; // Metadata helper +o2::common::core::MetadataHelper metadataInfo; namespace o2::aod { @@ -49,7 +53,13 @@ DECLARE_SOA_COLUMN(TimeZNC, timeZNC, float); DECLARE_SOA_COLUMN(AmplitudeZNA, amplitudeZNA, float); DECLARE_SOA_COLUMN(AmplitudeZNC, amplitudeZNC, float); } // namespace myBc_aod -DECLARE_SOA_TABLE(MyBCaod, "AOD", "MYBCAOD", myBc_aod::Timestamp, myBc_aod::BCid, myBc_aod::TimeZNA, myBc_aod::TimeZNC, myBc_aod::AmplitudeZNA, myBc_aod::AmplitudeZNC); +DECLARE_SOA_TABLE(MyBCaod, "AOD", "MYBCAOD", + myBc_aod::Timestamp, + myBc_aod::BCid, + myBc_aod::TimeZNA, + myBc_aod::TimeZNC, + myBc_aod::AmplitudeZNA, + myBc_aod::AmplitudeZNC); } // namespace o2::aod using MyBCs = soa::Join; @@ -62,102 +72,156 @@ struct LumiStabilityLightIons { Configurable cfgDoFDD{"cfgDoFDD", true, "Create and fill histograms for the FDD trigger"}; Configurable cfgDo1ZNC{"cfgDo1ZNC", true, "Create and fill histograms for the 1ZNC trigger"}; - Configurable cfgDoBCA{"cfgDoBCA", false, "Create and fill histograms for the BCs of type A"}; + Configurable cfgDoBCA{"cfgDoBCA", true, "Create and fill histograms for the BCs of type A"}; Configurable cfgDoBCB{"cfgDoBCB", true, "Create and fill histograms for the BCs of type B"}; - Configurable cfgDoBCC{"cfgDoBCC", false, "Create and fill histograms for the BCs of type C"}; - Configurable cfgDoBCE{"cfgDoBCE", false, "Create and fill histograms for the BCs of type E"}; - Configurable cfgDoBCL{"cfgDoBCL", false, "Create and fill histograms for leading BCs of type B"}; - Configurable cfgDoBCSL{"cfgDoBCSL", false, "Create and fill histograms for super-leading BCs (no preceding FT0/FDD activity) of type B"}; - - Configurable cfgRequireZDCTriggerForZDCQA{"cfgRequireZDCTriggerForZDCQA", false, "Require ZDC trigger (1ZNC) for filling QA histograms"}; - Configurable cfgRequireTVXTriggerForZDCQA{"cfgRequireTVXTriggerForZDCQA", false, "Require FT0 vertex trigger (MTVX) for filling ZDC QA histograms"}; - Configurable cfgRequireZEDTriggerForZDCQA{"cfgRequireZEDTriggerForZDCQA", false, "Require ZED trigger (1ZNC||1ZNA) for filling QA histograms"}; + Configurable cfgDoBCC{"cfgDoBCC", true, "Create and fill histograms for the BCs of type C"}; + Configurable cfgDoBCE{"cfgDoBCE", true, "Create and fill histograms for the BCs of type E"}; + Configurable cfgDoBCL{"cfgDoBCL", true, "Create and fill histograms for leading BCs of type B (non-B BCs before)"}; + Configurable cfgDoBCLE{"cfgDoBCLE", true, "Create and fill histograms for leading BCs of type B (strictly empty BCs before)"}; + Configurable cfgDoBCNL{"cfgDoBCNL", true, "Create and fill histograms for non-leading BCs of type B (complement of BCL)"}; + Configurable cfgDoBCNLE{"cfgDoBCNLE", true, "Create and fill histograms for non-leading BCs of type B (complement of BCLE)"}; + Configurable cfgDoBCSLFDD{"cfgDoBCSLFDD", true, "Create and fill histograms for super-leading BCs w.r.t. FDD activity"}; + Configurable cfgDoBCSLFT0{"cfgDoBCSLFT0", true, "Create and fill histograms for super-leading BCs w.r.t. FT0 activity"}; + Configurable cfgDoBCNSLFDD{"cfgDoBCNSLFDD", true, "Create and fill histograms for non-super-leading BCs w.r.t. FDD activity"}; + Configurable cfgDoBCNSLFT0{"cfgDoBCNSLFT0", true, "Create and fill histograms for non-super-leading BCs w.r.t. FT0 activity"}; + + Configurable cfgRequireZDCTriggerForZDCQA{"cfgRequireZDCTriggerForZDCQA", true, "Require ZDC trigger (1ZNC) for filling QA histograms"}; + Configurable cfgRequireTVXTriggerForZDCQA{"cfgRequireTVXTriggerForZDCQA", true, "Require FT0 vertex trigger (MTVX) for filling ZDC QA histograms"}; + Configurable cfgRequireZEDTriggerForZDCQA{"cfgRequireZEDTriggerForZDCQA", true, "Require ZED trigger (1ZNC||1ZNA) for filling QA histograms"}; Configurable cfgRequireNoT0ForSLBC{"cfgRequireNoT0ForSLBC", false, "Require no T0 signal for definition of super leading BC (otherwise only no FDD)"}; - Configurable cfgEmptyBCsBeforeLeadingBC{"cfgEmptyBCsBeforeLeadingBC", 5, "Minimum number of empty BCs before a leading BC to identify it as such"}; + Configurable cfgEmptyBCsBeforeLeadingBC{"cfgEmptyBCsBeforeLeadingBC", 5, "Minimum number of non-B BCs before a BCL leading BC"}; + Configurable cfgEmptyBCsBeforeLeadingBCLE{"cfgEmptyBCsBeforeLeadingBCLE", 5, "Minimum number of strictly empty (E-type) BCs before a BCLE leading BC"}; + Configurable cfgBCsBeforeSuperLeading{"cfgBCsBeforeSuperLeading", 5, "Minimum number of BCs without FDD/FT0 activity before a super-leading BC"}; - // Configurables specific to VdM analysis: output ao2d with timestamps and ZDC times Configurable cfgFillBCao2d{"cfgFillBCao2d", false, "Fill BC ao2d with timestamps and ZDC times"}; Configurable cfgTstampStartFillingBCao2d{"cfgTstampStartFillingBCao2d", 0, "Minimum value of timestamp for output bc ao2d to be filled"}; Configurable cfgTstampEndFillingBCao2d{"cfgTstampEndFillingBCao2d", 0, "Maximum value of timestamp for output bc ao2d to be filled"}; - std::bitset beamPatternA, beamPatternC; - std::bitset bcPatternA, bcPatternC, bcPatternB, bcPatternE, bcPatternL; + Configurable cfgBcShiftFDDForData2023{"cfgBcShiftFDDForData2023", 7, "Number of BCs to shift FDD, applied for 2023 data only"}; - std::string strLPMProductionTag = ""; // MC production tag to be retrieved from AO2D metadata + std::bitset beamPatternA, beamPatternC; + std::bitset bcPatternA, bcPatternC, bcPatternB, bcPatternE; + std::bitset bcPatternL; + std::bitset bcPatternLE; + std::string strLPMProductionTag = ""; const int nBCsPerOrbit = 3564; parameters::GRPLHCIFData* mLHCIFdata = nullptr; int mRunNumber = -1; + bool isData23 = false; + int mBcShiftFDD = 0; ctpRateFetcher mRateFetcher; - bool isLeadingBC = false; HistogramRegistry mHistManager{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; - const int nTriggers = 5; - enum TriggerAliases { kAllBCs = 0, - kFT0Vtx = 1, - kFT0CE = 2, - kFDD = 3, - k1ZNC = 4 }; - - const int nBCCategories = 6; - enum BCCategories { kBCA = 0, // A side BCs (bunch-crossings that had beam only from A side) - kBCB = 1, // B type BCs (bunch-crossings that had beam from both sides) - kBCC = 2, // C side BCs (bunch-crossings that had beam only from C side) - kBCE = 3, // empty BCs (bunch-crossings that did not have beam from either side) - kBCL = 4, // leading BCs (bunch-crossings that did not have interacting bunches for a configurable number of preceding BCs) - kBCSL = 5 }; // super-leading BCs (bunch-crossings that did not have FDD/FT0 activity for a configurable number of preceding BCs) - - static constexpr std::string_view NBCsVsTimeHistNames[5][6] = - {{"AllBCs/BC_A/nBCsVsTime", "AllBCs/BC_B/nBCsVsTime", "AllBCs/BC_C/nBCsVsTime", "AllBCs/BC_E/nBCsVsTime", "AllBCs/BC_L/nBCsVsTime", "AllBCs/BC_SL/nBCsVsTime"}, - {"FT0VTx/BC_A/nBCsVsTime", "FT0VTx/BC_B/nBCsVsTime", "FT0VTx/BC_C/nBCsVsTime", "FT0VTx/BC_E/nBCsVsTime", "FT0VTx/BC_L/nBCsVsTime", "FT0VTx/BC_SL/nBCsVsTime"}, - {"FT0CE/BC_A/nBCsVsTime", "FT0CE/BC_B/nBCsVsTime", "FT0CE/BC_C/nBCsVsTime", "FT0CE/BC_E/nBCsVsTime", "FT0CE/BC_L/nBCsVsTime", "FT0CE/BC_SL/nBCsVsTime"}, - {"FDD/BC_A/nBCsVsTime", "FDD/BC_B/nBCsVsTime", "FDD/BC_C/nBCsVsTime", "FDD/BC_E/nBCsVsTime", "FDD/BC_L/nBCsVsTime", "FDD/BC_SL/nBCsVsTime"}, - {"1ZNC/BC_A/nBCsVsTime", "1ZNC/BC_B/nBCsVsTime", "1ZNC/BC_C/nBCsVsTime", "1ZNC/BC_E/nBCsVsTime", "1ZNC/BC_L/nBCsVsTime", "1ZNC/BC_SL/nBCsVsTime"}}; - - static constexpr std::string_view NBCsVsBCIDHistNames[5][6] = - {{"AllBCs/BC_A/nBCsVsBCID", "AllBCs/BC_B/nBCsVsBCID", "AllBCs/BC_C/nBCsVsBCID", "AllBCs/BC_E/nBCsVsBCID", "AllBCs/BC_L/nBCsVsBCID", "AllBCs/BC_SL/nBCsVsBCID"}, - {"FT0VTx/BC_A/nBCsVsBCID", "FT0VTx/BC_B/nBCsVsBCID", "FT0VTx/BC_C/nBCsVsBCID", "FT0VTx/BC_E/nBCsVsBCID", "FT0VTx/BC_L/nBCsVsBCID", "FT0VTx/BC_SL/nBCsVsBCID"}, - {"FT0CE/BC_A/nBCsVsBCID", "FT0CE/BC_B/nBCsVsBCID", "FT0CE/BC_C/nBCsVsBCID", "FT0CE/BC_E/nBCsVsBCID", "FT0CE/BC_L/nBCsVsBCID", "FT0CE/BC_SL/nBCsVsBCID"}, - {"FDD/BC_A/nBCsVsBCID", "FDD/BC_B/nBCsVsBCID", "FDD/BC_C/nBCsVsBCID", "FDD/BC_E/nBCsVsBCID", "FDD/BC_L/nBCsVsBCID", "FDD/BC_SL/nBCsVsBCID"}, - {"1ZNC/BC_A/nBCsVsBCID", "1ZNC/BC_B/nBCsVsBCID", "1ZNC/BC_C/nBCsVsBCID", "1ZNC/BC_E/nBCsVsBCID", "1ZNC/BC_L/nBCsVsBCID", "1ZNC/BC_SL/nBCsVsBCID"}}; - - int64_t bcSOR; - int nBCsPerTF; + static constexpr int nTriggers = 5; + enum TriggerAliases { + kAllBCs = 0, + kFT0Vtx = 1, + kFT0CE = 2, + kFDD = 3, + k1ZNC = 4 + }; + + static constexpr int nBCCategories = 12; + enum BCCategories { + kBCA = 0, + kBCB = 1, + kBCC = 2, + kBCE = 3, + kBCL = 4, + kBCLE = 5, + kBCNL = 6, + kBCNLE = 7, + kBCSLFDD = 8, + kBCSLFT0 = 9, + kBCNSLFDD = 10, + kBCNSLFT0 = 11 + }; + + static constexpr std::string_view NBCsVsTimeHistNames[6][12] = { + {"AllBCs/BC_A/nBCsVsTime", "AllBCs/BC_B/nBCsVsTime", "AllBCs/BC_C/nBCsVsTime", "AllBCs/BC_E/nBCsVsTime", "AllBCs/BC_L/nBCsVsTime", "AllBCs/BC_LE/nBCsVsTime", "AllBCs/BC_NL/nBCsVsTime", "AllBCs/BC_NLE/nBCsVsTime", "AllBCs/BC_SL_FDD/nBCsVsTime", "AllBCs/BC_SL_FT0/nBCsVsTime", "AllBCs/BC_NSL_FDD/nBCsVsTime", "AllBCs/BC_NSL_FT0/nBCsVsTime"}, + {"FT0VTx/BC_A/nBCsVsTime", "FT0VTx/BC_B/nBCsVsTime", "FT0VTx/BC_C/nBCsVsTime", "FT0VTx/BC_E/nBCsVsTime", "FT0VTx/BC_L/nBCsVsTime", "FT0VTx/BC_LE/nBCsVsTime", "FT0VTx/BC_NL/nBCsVsTime", "FT0VTx/BC_NLE/nBCsVsTime", "FT0VTx/BC_SL_FDD/nBCsVsTime", "FT0VTx/BC_SL_FT0/nBCsVsTime", "FT0VTx/BC_NSL_FDD/nBCsVsTime", "FT0VTx/BC_NSL_FT0/nBCsVsTime"}, + {"FT0CE/BC_A/nBCsVsTime", "FT0CE/BC_B/nBCsVsTime", "FT0CE/BC_C/nBCsVsTime", "FT0CE/BC_E/nBCsVsTime", "FT0CE/BC_L/nBCsVsTime", "FT0CE/BC_LE/nBCsVsTime", "FT0CE/BC_NL/nBCsVsTime", "FT0CE/BC_NLE/nBCsVsTime", "FT0CE/BC_SL_FDD/nBCsVsTime", "FT0CE/BC_SL_FT0/nBCsVsTime", "FT0CE/BC_NSL_FDD/nBCsVsTime", "FT0CE/BC_NSL_FT0/nBCsVsTime"}, + {"FDD/BC_A/nBCsVsTime", "FDD/BC_B/nBCsVsTime", "FDD/BC_C/nBCsVsTime", "FDD/BC_E/nBCsVsTime", "FDD/BC_L/nBCsVsTime", "FDD/BC_LE/nBCsVsTime", "FDD/BC_NL/nBCsVsTime", "FDD/BC_NLE/nBCsVsTime", "FDD/BC_SL_FDD/nBCsVsTime", "FDD/BC_SL_FT0/nBCsVsTime", "FDD/BC_NSL_FDD/nBCsVsTime", "FDD/BC_NSL_FT0/nBCsVsTime"}, + {"1ZNC/BC_A/nBCsVsTime", "1ZNC/BC_B/nBCsVsTime", "1ZNC/BC_C/nBCsVsTime", "1ZNC/BC_E/nBCsVsTime", "1ZNC/BC_L/nBCsVsTime", "1ZNC/BC_LE/nBCsVsTime", "1ZNC/BC_NL/nBCsVsTime", "1ZNC/BC_NLE/nBCsVsTime", "1ZNC/BC_SL_FDD/nBCsVsTime", "1ZNC/BC_SL_FT0/nBCsVsTime", "1ZNC/BC_NSL_FDD/nBCsVsTime", "1ZNC/BC_NSL_FT0/nBCsVsTime"}}; + + static constexpr std::string_view NBCsVsBCIDHistNames[5][12] = { + {"AllBCs/BC_A/nBCsVsBCID", "AllBCs/BC_B/nBCsVsBCID", "AllBCs/BC_C/nBCsVsBCID", "AllBCs/BC_E/nBCsVsBCID", "AllBCs/BC_L/nBCsVsBCID", "AllBCs/BC_LE/nBCsVsBCID", "AllBCs/BC_NL/nBCsVsBCID", "AllBCs/BC_NLE/nBCsVsBCID", "AllBCs/BC_SL_FDD/nBCsVsBCID", "AllBCs/BC_SL_FT0/nBCsVsBCID", "AllBCs/BC_NSL_FDD/nBCsVsBCID", "AllBCs/BC_NSL_FT0/nBCsVsBCID"}, + {"FT0VTx/BC_A/nBCsVsBCID", "FT0VTx/BC_B/nBCsVsBCID", "FT0VTx/BC_C/nBCsVsBCID", "FT0VTx/BC_E/nBCsVsBCID", "FT0VTx/BC_L/nBCsVsBCID", "FT0VTx/BC_LE/nBCsVsBCID", "FT0VTx/BC_NL/nBCsVsBCID", "FT0VTx/BC_NLE/nBCsVsBCID", "FT0VTx/BC_SL_FDD/nBCsVsBCID", "FT0VTx/BC_SL_FT0/nBCsVsBCID", "FT0VTx/BC_NSL_FDD/nBCsVsBCID", "FT0VTx/BC_NSL_FT0/nBCsVsBCID"}, + {"FT0CE/BC_A/nBCsVsBCID", "FT0CE/BC_B/nBCsVsBCID", "FT0CE/BC_C/nBCsVsBCID", "FT0CE/BC_E/nBCsVsBCID", "FT0CE/BC_L/nBCsVsBCID", "FT0CE/BC_LE/nBCsVsBCID", "FT0CE/BC_NL/nBCsVsBCID", "FT0CE/BC_NLE/nBCsVsBCID", "FT0CE/BC_SL_FDD/nBCsVsBCID", "FT0CE/BC_SL_FT0/nBCsVsBCID", "FT0CE/BC_NSL_FDD/nBCsVsBCID", "FT0CE/BC_NSL_FT0/nBCsVsBCID"}, + {"FDD/BC_A/nBCsVsBCID", "FDD/BC_B/nBCsVsBCID", "FDD/BC_C/nBCsVsBCID", "FDD/BC_E/nBCsVsBCID", "FDD/BC_L/nBCsVsBCID", "FDD/BC_LE/nBCsVsBCID", "FDD/BC_NL/nBCsVsBCID", "FDD/BC_NLE/nBCsVsBCID", "FDD/BC_SL_FDD/nBCsVsBCID", "FDD/BC_SL_FT0/nBCsVsBCID", "FDD/BC_NSL_FDD/nBCsVsBCID", "FDD/BC_NSL_FT0/nBCsVsBCID"}, + {"1ZNC/BC_A/nBCsVsBCID", "1ZNC/BC_B/nBCsVsBCID", "1ZNC/BC_C/nBCsVsBCID", "1ZNC/BC_E/nBCsVsBCID", "1ZNC/BC_L/nBCsVsBCID", "1ZNC/BC_LE/nBCsVsBCID", "1ZNC/BC_NL/nBCsVsBCID", "1ZNC/BC_NLE/nBCsVsBCID", "1ZNC/BC_SL_FDD/nBCsVsBCID", "1ZNC/BC_SL_FT0/nBCsVsBCID", "1ZNC/BC_NSL_FDD/nBCsVsBCID", "1ZNC/BC_NSL_FT0/nBCsVsBCID"}}; + + static constexpr std::string_view NBCsInspectedVsBCIDHistNames[5][12] = { + {"AllBCs/BC_A/nBCsInspectedVsBCID", "AllBCs/BC_B/nBCsInspectedVsBCID", "AllBCs/BC_C/nBCsInspectedVsBCID", "AllBCs/BC_E/nBCsInspectedVsBCID", "AllBCs/BC_L/nBCsInspectedVsBCID", "AllBCs/BC_LE/nBCsInspectedVsBCID", "AllBCs/BC_NL/nBCsInspectedVsBCID", "AllBCs/BC_NLE/nBCsInspectedVsBCID", "AllBCs/BC_SL_FDD/nBCsInspectedVsBCID", "AllBCs/BC_SL_FT0/nBCsInspectedVsBCID", "AllBCs/BC_NSL_FDD/nBCsInspectedVsBCID", "AllBCs/BC_NSL_FT0/nBCsInspectedVsBCID"}, + {"FT0VTx/BC_A/nBCsInspectedVsBCID", "FT0VTx/BC_B/nBCsInspectedVsBCID", "FT0VTx/BC_C/nBCsInspectedVsBCID", "FT0VTx/BC_E/nBCsInspectedVsBCID", "FT0VTx/BC_L/nBCsInspectedVsBCID", "FT0VTx/BC_LE/nBCsInspectedVsBCID", "FT0VTx/BC_NL/nBCsInspectedVsBCID", "FT0VTx/BC_NLE/nBCsInspectedVsBCID", "FT0VTx/BC_SL_FDD/nBCsInspectedVsBCID", "FT0VTx/BC_SL_FT0/nBCsInspectedVsBCID", "FT0VTx/BC_NSL_FDD/nBCsInspectedVsBCID", "FT0VTx/BC_NSL_FT0/nBCsInspectedVsBCID"}, + {"FT0CE/BC_A/nBCsInspectedVsBCID", "FT0CE/BC_B/nBCsInspectedVsBCID", "FT0CE/BC_C/nBCsInspectedVsBCID", "FT0CE/BC_E/nBCsInspectedVsBCID", "FT0CE/BC_L/nBCsInspectedVsBCID", "FT0CE/BC_LE/nBCsInspectedVsBCID", "FT0CE/BC_NL/nBCsInspectedVsBCID", "FT0CE/BC_NLE/nBCsInspectedVsBCID", "FT0CE/BC_SL_FDD/nBCsInspectedVsBCID", "FT0CE/BC_SL_FT0/nBCsInspectedVsBCID", "FT0CE/BC_NSL_FDD/nBCsInspectedVsBCID", "FT0CE/BC_NSL_FT0/nBCsInspectedVsBCID"}, + {"FDD/BC_A/nBCsInspectedVsBCID", "FDD/BC_B/nBCsInspectedVsBCID", "FDD/BC_C/nBCsInspectedVsBCID", "FDD/BC_E/nBCsInspectedVsBCID", "FDD/BC_L/nBCsInspectedVsBCID", "FDD/BC_LE/nBCsInspectedVsBCID", "FDD/BC_NL/nBCsInspectedVsBCID", "FDD/BC_NLE/nBCsInspectedVsBCID", "FDD/BC_SL_FDD/nBCsInspectedVsBCID", "FDD/BC_SL_FT0/nBCsInspectedVsBCID", "FDD/BC_NSL_FDD/nBCsInspectedVsBCID", "FDD/BC_NSL_FT0/nBCsInspectedVsBCID"}, + {"1ZNC/BC_A/nBCsInspectedVsBCID", "1ZNC/BC_B/nBCsInspectedVsBCID", "1ZNC/BC_C/nBCsInspectedVsBCID", "1ZNC/BC_E/nBCsInspectedVsBCID", "1ZNC/BC_L/nBCsInspectedVsBCID", "1ZNC/BC_LE/nBCsInspectedVsBCID", "1ZNC/BC_NL/nBCsInspectedVsBCID", "1ZNC/BC_NLE/nBCsInspectedVsBCID", "1ZNC/BC_SL_FDD/nBCsInspectedVsBCID", "1ZNC/BC_SL_FT0/nBCsInspectedVsBCID", "1ZNC/BC_NSL_FDD/nBCsInspectedVsBCID", "1ZNC/BC_NSL_FT0/nBCsInspectedVsBCID"}}; + + std::array, nBCCategories>, nTriggers> mInspectedHistos{}; + + int64_t bcSOR = 0; + int nBCsPerTF = 0; int64_t currentTFid = -1; + int64_t globalBCIdOfLastBCWithActivityFDD{std::numeric_limits::min() / 2}; + int64_t globalBCIdOfLastBCWithActivityFT0{std::numeric_limits::min() / 2}; + int64_t globalBCLastInspectedBC{-1}; + + using DenomCounter = std::vector, nTriggers>>; + + bool hasAnyFDDTrigger(const std::bitset<64>& ctpInputMask) const + { + return ctpInputMask.test(12) || ctpInputMask.test(14) || ctpInputMask.test(15) || + ctpInputMask.test(16) || ctpInputMask.test(17); + } + + bool hasAnyFT0Trigger(const std::bitset<64>& ctpInputMask) const + { + return ctpInputMask.test(0) || ctpInputMask.test(1) || ctpInputMask.test(2) || + ctpInputMask.test(3) || ctpInputMask.test(4); + } + void init(InitContext&) { - strLPMProductionTag = metadataInfo.get("LPMProductionTag"); // to extract info from ccdb by the tag + strLPMProductionTag = metadataInfo.get("LPMProductionTag"); LOG(info) << "strLPMProductionTag: " << strLPMProductionTag; - AxisSpec timeAxis{1440, 0., 1440., "#bf{t-t_{SOF} (min)}"}, bcIDAxis{3600, 0., 3600., "#bf{BC ID in orbit}"}; + AxisSpec timeAxis{1440, 0., 1440., "#bf{t-t_{SOF} (min)}"}; + AxisSpec bcIDAxis{3600, 0., 3600., "#bf{BC ID in orbit}"}; for (int iTrigger = 0; iTrigger < nTriggers; iTrigger++) { if ((iTrigger == kAllBCs) || (iTrigger == kFT0Vtx && cfgDoFT0Vtx) || (iTrigger == kFT0CE && cfgDoFT0CE) || (iTrigger == kFDD && cfgDoFDD) || (iTrigger == k1ZNC && cfgDo1ZNC)) { for (int iBCCategory = 0; iBCCategory < nBCCategories; iBCCategory++) { - if ((iBCCategory == kBCA && cfgDoBCA) || (iBCCategory == kBCB && cfgDoBCB) || (iBCCategory == kBCC && cfgDoBCC) || (iBCCategory == kBCE && cfgDoBCE) || (iBCCategory == kBCL && cfgDoBCL)) { + if ((iBCCategory == kBCA && cfgDoBCA) || (iBCCategory == kBCB && cfgDoBCB) || (iBCCategory == kBCC && cfgDoBCC) || (iBCCategory == kBCE && cfgDoBCE) || + (iBCCategory == kBCL && cfgDoBCL) || (iBCCategory == kBCLE && cfgDoBCLE) || + (iBCCategory == kBCNL && cfgDoBCNL) || (iBCCategory == kBCNLE && cfgDoBCNLE) || + (iBCCategory == kBCSLFDD && cfgDoBCSLFDD) || (iBCCategory == kBCSLFT0 && cfgDoBCSLFT0) || + (iBCCategory == kBCNSLFDD && cfgDoBCNSLFDD) || (iBCCategory == kBCNSLFT0 && cfgDoBCNSLFT0)) { mHistManager.add(Form("%s", std::string(NBCsVsTimeHistNames[iTrigger][iBCCategory]).c_str()), "Time of triggered BCs since the start of fill;#bf{t-t_{SOF} (min)};#bf{#it{N}_{BC}}", HistType::kTH1D, {timeAxis}); mHistManager.add(Form("%s", std::string(NBCsVsBCIDHistNames[iTrigger][iBCCategory]).c_str()), "BC ID of triggered BCs;#bf{BC ID in orbit};#bf{#it{N}_{BC}}", HistType::kTH1D, {bcIDAxis}); + mInspectedHistos[iTrigger][iBCCategory] = mHistManager.add( + Form("%s", std::string(NBCsInspectedVsBCIDHistNames[iTrigger][iBCCategory]).c_str()), + "Inspected BC ID (denominator for mu);#bf{BC ID in orbit};#bf{#it{N}_{BC}}", + HistType::kTH1D, {bcIDAxis}); } } - if (cfgDoBCSL && (iTrigger == kFT0Vtx || iTrigger == kFDD || iTrigger == kAllBCs)) { // only for FT0Vtx and FDD fill super-leading BC histograms - mHistManager.add(Form("%s", std::string(NBCsVsTimeHistNames[iTrigger][5]).c_str()), "Time of triggered BCs since the start of fill;#bf{t-t_{SOF} (min)};#bf{#it{N}_{BC}}", HistType::kTH1D, {timeAxis}); - mHistManager.add(Form("%s", std::string(NBCsVsBCIDHistNames[iTrigger][5]).c_str()), "BC ID of triggered BCs;#bf{BC ID in orbit};#bf{#it{N}_{BC}}", HistType::kTH1D, {bcIDAxis}); - } } } - if (cfgDoBCSL) { + if (cfgDoBCSLFDD || cfgDoBCSLFT0 || cfgDoBCNSLFDD || cfgDoBCNSLFT0) { mHistManager.add("FITQA/BCHasFT0", "Does the BC have FT0?;BC has FT0;TVX triggered according to CTP;#bf{#it{N}_{BC}}", HistType::kTH2D, {{2, -0.5, 1.5}, {2, -0.5, 1.5}}); mHistManager.get(HIST("FITQA/BCHasFT0")).get()->GetYaxis()->SetBinLabel(1, "No CTP trigger"); mHistManager.get(HIST("FITQA/BCHasFT0")).get()->GetYaxis()->SetBinLabel(2, "CTP triggered"); mHistManager.get(HIST("FITQA/BCHasFT0")).get()->GetXaxis()->SetBinLabel(1, "No found FT0"); mHistManager.get(HIST("FITQA/BCHasFT0")).get()->GetXaxis()->SetBinLabel(2, "Found FT0"); + mHistManager.add("FITQA/BCHasFDD", "Does the BC have FDD?;BC has FDD;FDD triggered according to CTP;#bf{#it{N}_{BC}}", HistType::kTH2D, {{2, -0.5, 1.5}, {2, -0.5, 1.5}}); mHistManager.get(HIST("FITQA/BCHasFDD")).get()->GetYaxis()->SetBinLabel(1, "No CTP trigger"); mHistManager.get(HIST("FITQA/BCHasFDD")).get()->GetYaxis()->SetBinLabel(2, "CTP triggered"); @@ -185,18 +249,27 @@ struct LumiStabilityLightIons { void setLHCIFData(const auto& bc) { - if (mRunNumber == bc.runNumber()) + if (mRunNumber == bc.runNumber()) { return; + } auto& ccdbMgr = o2::ccdb::BasicCCDBManager::instance(); uint64_t timeStamp = bc.timestamp(); + const int runStart2023{535069}; + const int runStop2023{543113}; + isData23 = (bc.runNumber() >= runStart2023 && bc.runNumber() <= runStop2023); + mBcShiftFDD = isData23 ? static_cast(cfgBcShiftFDDForData2023) : 0; + std::map metadata; mLHCIFdata = ccdbMgr.getSpecific("GLO/Config/GRPLHCIF", timeStamp, metadata); - if (mLHCIFdata == nullptr) + if (mLHCIFdata == nullptr) { LOG(fatal) << "GRPLHCIFData not in database, timestamp:" << timeStamp; + } + mRunNumber = bc.runNumber(); - LOG(info) << "LHCIF data fetched for run " << mRunNumber << " and timestamp " << timeStamp; + LOG(info) << "LHCIF data fetched for run " << mRunNumber << " and timestamp " << timeStamp + << " (isData23=" << isData23 << ", bcShiftFDD=" << mBcShiftFDD << ")"; beamPatternA = mLHCIFdata->getBunchFilling().getBeamPattern(0); beamPatternC = mLHCIFdata->getBunchFilling().getBeamPattern(1); @@ -205,42 +278,60 @@ struct LumiStabilityLightIons { bcPatternB = beamPatternA & beamPatternC; bcPatternE = ~beamPatternA & ~beamPatternC; - // Create bcPatternL: leading BCs of type B that follow at least "cfgEmptyBCsBeforeLeadingBC" empty BCs - bcPatternL.reset(); // Initialize all bits to false - LOG(info) << "Starting to create bcPatternL from bcPatternB"; - LOG(info) << "Total number of BCs to check: " << o2::constants::lhc::LHCMaxBunches; + bcPatternL.reset(); + bcPatternLE.reset(); + + int totalLeadingBCsL = 0; + int totalLeadingBCsLE = 0; - int totalLeadingBCs = 0; for (int iBC = 0; iBC < o2::constants::lhc::LHCMaxBunches; iBC++) { - if (bcPatternB[iBC]) { // Check if current BC is of type B - int emptyBCsBefore = 0; // Count how many consecutive BCs before this one are NOT type B - for (int j = 1; j <= cfgEmptyBCsBeforeLeadingBC; j++) { - int prevBC = (iBC - j + o2::constants::lhc::LHCMaxBunches) % o2::constants::lhc::LHCMaxBunches; // Protection for BCs at small indices to check the end of the orbit - if (!bcPatternB[prevBC]) { - emptyBCsBefore++; - } else { - break; // Stop counting if we hit a type B BC - } + if (!bcPatternB[iBC]) { + continue; + } + + int nonBBefore = 0; + int emptyBefore = 0; + + for (int j = 1; j <= cfgEmptyBCsBeforeLeadingBC; j++) { + int prevBC = (iBC - j + o2::constants::lhc::LHCMaxBunches) % o2::constants::lhc::LHCMaxBunches; + if (!bcPatternB[prevBC]) { + nonBBefore++; + } else { + break; } - if (emptyBCsBefore >= cfgEmptyBCsBeforeLeadingBC) { // If we found at least cfgEmptyBCsBeforeLeadingBC empty BCs before this one, mark it as leading - bcPatternL[iBC] = true; - totalLeadingBCs++; + } + + for (int j = 1; j <= cfgEmptyBCsBeforeLeadingBCLE; j++) { + int prevBC = (iBC - j + o2::constants::lhc::LHCMaxBunches) % o2::constants::lhc::LHCMaxBunches; + if (bcPatternE[prevBC]) { + emptyBefore++; + } else { + break; } } + + if (nonBBefore >= cfgEmptyBCsBeforeLeadingBC) { + bcPatternL[iBC] = true; + totalLeadingBCsL++; + } + if (emptyBefore >= cfgEmptyBCsBeforeLeadingBCLE) { + bcPatternLE[iBC] = true; + totalLeadingBCsLE++; + } } - LOG(info) << "bcPatternL creation complete. Total leading BCs found: " << totalLeadingBCs; + + LOG(info) << "bcPatternL (non-B before) complete. Leading BCs found: " << totalLeadingBCsL; + LOG(info) << "bcPatternLE (empty before) complete. Leading BCs found: " << totalLeadingBCsLE; auto runInfo = o2::parameters::AggregatedRunInfo::buildAggregatedRunInfo(o2::ccdb::BasicCCDBManager::instance(), mRunNumber, strLPMProductionTag); - bcSOR = runInfo.orbitSOR * nBCsPerOrbit; // first bc of the first orbit + bcSOR = runInfo.orbitSOR * nBCsPerOrbit; LOG(info) << "BC SOR: " << bcSOR << " (orbit SOR: " << runInfo.orbitSOR << ") NBCs per orbit: " << nBCsPerOrbit; - nBCsPerTF = runInfo.orbitsPerTF * nBCsPerOrbit; // duration of TF in bcs - - return; + nBCsPerTF = runInfo.orbitsPerTF * nBCsPerOrbit; } float getTimeSinceSOF(const auto& bc) { - return (bc.timestamp() - mLHCIFdata->getFillNumberTime()) / 1e3 / 60; // Convert to minutes + return (bc.timestamp() - mLHCIFdata->getFillNumberTime()) / 1e3 / 60.f; } template @@ -250,49 +341,133 @@ struct LumiStabilityLightIons { mHistManager.fill(HIST(NBCsVsBCIDHistNames[iTrigger][iBCCategory]), localBC); } + template + void countInspectedBC(DenomCounter& nBCsPerBcId, + int iLBC, + int iLBCFDD, + int64_t iGBC, + int64_t lastFT0ActivityBC, + int64_t lastFDDActivityBC) + { + if constexpr (iTrigger == kFDD) { + if (bcPatternA[iLBCFDD]) { + nBCsPerBcId[iLBCFDD][iTrigger][kBCA]++; + } + if (bcPatternB[iLBCFDD]) { + nBCsPerBcId[iLBCFDD][iTrigger][kBCB]++; + } + if (bcPatternC[iLBCFDD]) { + nBCsPerBcId[iLBCFDD][iTrigger][kBCC]++; + } + if (bcPatternE[iLBCFDD]) { + nBCsPerBcId[iLBCFDD][iTrigger][kBCE]++; + } + if (bcPatternL[iLBCFDD]) { + nBCsPerBcId[iLBCFDD][iTrigger][kBCL]++; + } + if (bcPatternLE[iLBCFDD]) { + nBCsPerBcId[iLBCFDD][iTrigger][kBCLE]++; + } + if (bcPatternB[iLBCFDD] && !bcPatternL[iLBCFDD]) { + nBCsPerBcId[iLBCFDD][iTrigger][kBCNL]++; + } + if (bcPatternB[iLBCFDD] && !bcPatternLE[iLBCFDD]) { + nBCsPerBcId[iLBCFDD][iTrigger][kBCNLE]++; + } + if (bcPatternB[iLBCFDD]) { + const bool slFDD = ((iGBC + mBcShiftFDD) - lastFDDActivityBC >= cfgBCsBeforeSuperLeading); + nBCsPerBcId[iLBCFDD][iTrigger][slFDD ? kBCSLFDD : kBCNSLFDD]++; + + const bool slFT0 = (iGBC - lastFT0ActivityBC >= cfgBCsBeforeSuperLeading); + nBCsPerBcId[iLBCFDD][iTrigger][slFT0 ? kBCSLFT0 : kBCNSLFT0]++; + } + } else { + if (bcPatternA[iLBC]) { + nBCsPerBcId[iLBC][iTrigger][kBCA]++; + } + if (bcPatternB[iLBC]) { + nBCsPerBcId[iLBC][iTrigger][kBCB]++; + } + if (bcPatternC[iLBC]) { + nBCsPerBcId[iLBC][iTrigger][kBCC]++; + } + if (bcPatternE[iLBC]) { + nBCsPerBcId[iLBC][iTrigger][kBCE]++; + } + if (bcPatternL[iLBC]) { + nBCsPerBcId[iLBC][iTrigger][kBCL]++; + } + if (bcPatternLE[iLBC]) { + nBCsPerBcId[iLBC][iTrigger][kBCLE]++; + } + if (bcPatternB[iLBC] && !bcPatternL[iLBC]) { + nBCsPerBcId[iLBC][iTrigger][kBCNL]++; + } + if (bcPatternB[iLBC] && !bcPatternLE[iLBC]) { + nBCsPerBcId[iLBC][iTrigger][kBCNLE]++; + } + if (bcPatternB[iLBC]) { + const bool slFT0 = (iGBC - lastFT0ActivityBC >= cfgBCsBeforeSuperLeading); + nBCsPerBcId[iLBC][iTrigger][slFT0 ? kBCSLFT0 : kBCNSLFT0]++; + } + if (bcPatternB[iLBCFDD]) { + const bool slFDD = ((iGBC + mBcShiftFDD) - lastFDDActivityBC >= cfgBCsBeforeSuperLeading); + nBCsPerBcId[iLBCFDD][iTrigger][slFDD ? kBCSLFDD : kBCNSLFDD]++; + } + } + } + void processZDCQA(MyBCs const& bcs, aod::Zdcs const&) { - const int maxTimeZDC = 50; // Maximum time the histogram allows before setting a dummy value - const int dummyZDCTime = 42.f; // Time value to indicate missing ZDC time - for (const auto& bc : bcs) { + const int maxTimeZDC = 50; + const float dummyZDCTime = 42.f; + for (const auto& bc : bcs) { std::bitset<64> ctpInputMask(bc.inputMask()); - if (cfgRequireTVXTriggerForZDCQA && !(ctpInputMask.test(2))) // 2 = 3 - 1 -> MTVX + + if (cfgRequireTVXTriggerForZDCQA && !(ctpInputMask.test(2))) { continue; - if (cfgRequireZDCTriggerForZDCQA && !(ctpInputMask.test(25))) // 25 = 26 - 1 -> 1ZNC + } + if (cfgRequireZDCTriggerForZDCQA && !(ctpInputMask.test(25))) { continue; - if (cfgRequireZEDTriggerForZDCQA && !(ctpInputMask.test(24))) // 24 = 25 - 1 -> 1ZED + } + if (cfgRequireZEDTriggerForZDCQA && !(ctpInputMask.test(24))) { continue; + } bool zdcHit = !bc.has_zdc() ? 0 : ((bc.zdc().energyCommonZNC() > -1 && std::abs(bc.zdc().timeZNC()) < 1E5) ? 1 : 0); mHistManager.fill(HIST("ZDCQA/BCHasZDC"), zdcHit, ctpInputMask.test(25) ? 1 : 0); - if (!bc.has_zdc()) + + if (!bc.has_zdc()) { continue; + } - mHistManager.fill(HIST("ZDCQA/ZNCTimeVsEnergy"), bc.zdc().energyCommonZNC() > -1 ? bc.zdc().energyCommonZNC() : -1, std::abs(bc.zdc().timeZNC()) < maxTimeZDC ? bc.zdc().timeZNC() : dummyZDCTime); + mHistManager.fill(HIST("ZDCQA/ZNCTimeVsEnergy"), + bc.zdc().energyCommonZNC() > -1 ? bc.zdc().energyCommonZNC() : -1, + std::abs(bc.zdc().timeZNC()) < maxTimeZDC ? bc.zdc().timeZNC() : dummyZDCTime); float timeZNA = bc.zdc().timeZNA(); float timeZNC = bc.zdc().timeZNC(); if (std::abs(timeZNA) > maxTimeZDC) { - timeZNA = dummyZDCTime; // set dummy value for missing ZDC times to be able to plot them + timeZNA = dummyZDCTime; mHistManager.fill(HIST("ZDCQA/ZNCTime"), timeZNC); } if (std::abs(timeZNC) > maxTimeZDC) { - timeZNC = dummyZDCTime; // set dummy value for missing ZDC times to be able to plot them - if (timeZNA != dummyZDCTime) // If ZNA and ZNC are both missing, do not fill the ZNA histogram with the dummy value + timeZNC = dummyZDCTime; + if (timeZNA != dummyZDCTime) { mHistManager.fill(HIST("ZDCQA/ZNATime"), timeZNA); + } } mHistManager.fill(HIST("ZDCQA/ZDCTimes"), timeZNA, timeZNC); - // For VdM analysis: fill timestamps and ZDC times in output tree, if enabled - // Fill BC idx and ZNA and ZNC amplitudes as well uint64_t timestamp = bc.timestamp(); int64_t globalBC = bc.globalBC(); int localBC = globalBC % nBCsPerOrbit; float amplitudeZNA = bc.zdc().amplitudeZNA(); float amplitudeZNC = bc.zdc().amplitudeZNC(); + if (cfgFillBCao2d && timestamp >= cfgTstampStartFillingBCao2d && timestamp <= cfgTstampEndFillingBCao2d) { BCaod(timestamp, localBC, timeZNA, timeZNC, amplitudeZNA, amplitudeZNC); } @@ -300,140 +475,264 @@ struct LumiStabilityLightIons { } PROCESS_SWITCH(LumiStabilityLightIons, processZDCQA, "process QA for the ZDC triggers (light ions and PbPb)", false); - void processSLBunches(MyBCs const& bcs, aod::FT0s const&, aod::FDDs const&) + void process(MyBCs const& bcs, aod::FT0s const&, aod::FDDs const&) { - int64_t globalBCIdOfLastBCWithActivity = 0; + DenomCounter nBCsPerBcId(nBCsPerOrbit); + for (auto& triggerArr : nBCsPerBcId) { + for (auto& catArr : triggerArr) { + catArr.fill(0); + } + } + for (const auto& bc : bcs) { - if (bc.timestamp() == 0) + if (bc.timestamp() == 0) { continue; + } setLHCIFData(bc); - std::bitset<64> ctpInputMask(bc.inputMask()); + float timeSinceSOF = getTimeSinceSOF(bc); - mHistManager.fill(HIST("FITQA/BCHasFT0"), bc.has_ft0(), ctpInputMask.test(2)); - mHistManager.fill(HIST("FITQA/BCHasFDD"), bc.has_fdd(), ctpInputMask.test(15)); + if (bc.selection_bit(aod::evsel::kIsTriggerTVX)) { + mHistManager.fill(HIST("FT0Vtx_EvSel/nBCsVsTime"), timeSinceSOF); + } int64_t globalBC = bc.globalBC(); + int localBC = static_cast(globalBC % nBCsPerOrbit); - if (globalBC - globalBCIdOfLastBCWithActivity < cfgEmptyBCsBeforeLeadingBC) - continue; // not a super-leading BC + int64_t globalBCFDD = globalBC + mBcShiftFDD; + int localBCFDD = static_cast((globalBCFDD % nBCsPerOrbit + nBCsPerOrbit) % nBCsPerOrbit); - if (bc.has_fdd() || (cfgRequireNoT0ForSLBC && bc.has_ft0())) - globalBCIdOfLastBCWithActivity = globalBC; + int64_t thisTFid = (globalBC - bcSOR) / nBCsPerTF; + if (thisTFid != currentTFid) { + currentTFid = thisTFid; + mHistManager.fill(HIST("TFsPerMinute"), timeSinceSOF); + } - float timeSinceSOF = getTimeSinceSOF(bc); + std::bitset<64> ctpInputMask(bc.inputMask()); - int localBC = globalBC % nBCsPerOrbit; + const bool anyFT0Trigger = hasAnyFT0Trigger(ctpInputMask); + const bool anyFDDTrigger = hasAnyFDDTrigger(ctpInputMask); - if (!bcPatternB[localBC]) - continue; + bool isSuperLeadingBcFDD = bcPatternB[localBCFDD] && + (globalBCFDD - globalBCIdOfLastBCWithActivityFDD >= cfgBCsBeforeSuperLeading); - fillHistograms(timeSinceSOF, localBC); + bool isSuperLeadingBcFT0 = bcPatternB[localBC] && + (globalBC - globalBCIdOfLastBCWithActivityFT0 >= cfgBCsBeforeSuperLeading); - if (ctpInputMask.test(2)) - fillHistograms(timeSinceSOF, localBC); - if (ctpInputMask.test(15)) - fillHistograms(timeSinceSOF, localBC); - } - } - PROCESS_SWITCH(LumiStabilityLightIons, processSLBunches, "process trigger counting of TVX and FDD for bunches without preceding single-arm activity", false); + if (cfgDoBCSLFDD || cfgDoBCSLFT0 || cfgDoBCNSLFDD || cfgDoBCNSLFT0) { + mHistManager.fill(HIST("FITQA/BCHasFT0"), bc.has_ft0(), ctpInputMask.test(2)); + mHistManager.fill(HIST("FITQA/BCHasFDD"), bc.has_fdd(), anyFDDTrigger); + } - void process(MyBCs const& bcs, aod::FT0s const&) - { - for (const auto& bc : bcs) { + int64_t globalBCStart = (globalBCLastInspectedBC >= 0 && globalBCLastInspectedBC < globalBC) ? globalBCLastInspectedBC + 1 : globalBC; + const int64_t maxBcGap = 2LL * nBCsPerOrbit; + if (globalBC - globalBCStart > maxBcGap) { + globalBCStart = globalBC; + } - if (bc.timestamp() == 0) - continue; + for (int64_t iGBC = globalBCStart; iGBC <= globalBC; ++iGBC) { + const int iLBC = static_cast((iGBC % nBCsPerOrbit + nBCsPerOrbit) % nBCsPerOrbit); + const int iLBCFDD = static_cast(((iGBC + mBcShiftFDD) % nBCsPerOrbit + nBCsPerOrbit) % nBCsPerOrbit); - setLHCIFData(bc); + countInspectedBC(nBCsPerBcId, iLBC, iLBCFDD, iGBC, + globalBCIdOfLastBCWithActivityFT0, + globalBCIdOfLastBCWithActivityFDD); - float timeSinceSOF = getTimeSinceSOF(bc); + if (cfgDoFT0Vtx && ctpInputMask.test(2)) { + countInspectedBC(nBCsPerBcId, iLBC, iLBCFDD, iGBC, + globalBCIdOfLastBCWithActivityFT0, + globalBCIdOfLastBCWithActivityFDD); + } - if (bc.selection_bit(aod::evsel::kIsTriggerTVX)) - mHistManager.fill(HIST("FT0Vtx_EvSel/nBCsVsTime"), timeSinceSOF); + if (cfgDoFT0CE && ctpInputMask.test(4)) { + countInspectedBC(nBCsPerBcId, iLBC, iLBCFDD, iGBC, + globalBCIdOfLastBCWithActivityFT0, + globalBCIdOfLastBCWithActivityFDD); + } - int64_t globalBC = bc.globalBC(); - int localBC = globalBC % nBCsPerOrbit; + if (cfgDoFDD && anyFDDTrigger) { + countInspectedBC(nBCsPerBcId, iLBC, iLBCFDD, iGBC, + globalBCIdOfLastBCWithActivityFT0, + globalBCIdOfLastBCWithActivityFDD); + } - int64_t thisTFid = (globalBC - bcSOR) / nBCsPerTF; + if (cfgDo1ZNC && ctpInputMask.test(25)) { + countInspectedBC(nBCsPerBcId, iLBC, iLBCFDD, iGBC, + globalBCIdOfLastBCWithActivityFT0, + globalBCIdOfLastBCWithActivityFDD); + } + } - if (thisTFid != currentTFid) { - currentTFid = thisTFid; - mHistManager.fill(HIST("TFsPerMinute"), timeSinceSOF); + if (anyFDDTrigger) { + globalBCIdOfLastBCWithActivityFDD = globalBCFDD; + } + if (anyFT0Trigger) { + globalBCIdOfLastBCWithActivityFT0 = globalBC; } - std::bitset<64> ctpInputMask(bc.inputMask()); + globalBCLastInspectedBC = globalBC; + + if (cfgDoBCA && bcPatternA[localBC]) { + fillHistograms(timeSinceSOF, localBC); + } + if (cfgDoBCB && bcPatternB[localBC]) { + fillHistograms(timeSinceSOF, localBC); + } + if (cfgDoBCC && bcPatternC[localBC]) { + fillHistograms(timeSinceSOF, localBC); + } + if (cfgDoBCE && bcPatternE[localBC]) { + fillHistograms(timeSinceSOF, localBC); + } + if (cfgDoBCL && bcPatternL[localBC]) { + fillHistograms(timeSinceSOF, localBC); + } + if (cfgDoBCLE && bcPatternLE[localBC]) { + fillHistograms(timeSinceSOF, localBC); + } + if (cfgDoBCNL && bcPatternB[localBC] && !bcPatternL[localBC]) { + fillHistograms(timeSinceSOF, localBC); + } + if (cfgDoBCNLE && bcPatternB[localBC] && !bcPatternLE[localBC]) { + fillHistograms(timeSinceSOF, localBC); + } + if (cfgDoBCSLFDD && isSuperLeadingBcFDD) { + fillHistograms(timeSinceSOF, localBCFDD); + } + if (cfgDoBCSLFT0 && isSuperLeadingBcFT0) { + fillHistograms(timeSinceSOF, localBC); + } + if (cfgDoBCNSLFDD && bcPatternB[localBCFDD] && !isSuperLeadingBcFDD) { + fillHistograms(timeSinceSOF, localBCFDD); + } + if (cfgDoBCNSLFT0 && bcPatternB[localBC] && !isSuperLeadingBcFT0) { + fillHistograms(timeSinceSOF, localBC); + } + + if (cfgDoFT0Vtx && ctpInputMask.test(2)) { + if (cfgDoBCA && bcPatternA[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCB && bcPatternB[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCC && bcPatternC[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCE && bcPatternE[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCL && bcPatternL[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCLE && bcPatternLE[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCNL && bcPatternB[localBC] && !bcPatternL[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCNLE && bcPatternB[localBC] && !bcPatternLE[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCSLFDD && isSuperLeadingBcFDD) + fillHistograms(timeSinceSOF, localBCFDD); + if (cfgDoBCSLFT0 && isSuperLeadingBcFT0) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCNSLFDD && bcPatternB[localBCFDD] && !isSuperLeadingBcFDD) + fillHistograms(timeSinceSOF, localBCFDD); + if (cfgDoBCNSLFT0 && bcPatternB[localBC] && !isSuperLeadingBcFT0) + fillHistograms(timeSinceSOF, localBC); + } + + if (cfgDoFT0CE && ctpInputMask.test(4)) { + if (cfgDoBCA && bcPatternA[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCB && bcPatternB[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCC && bcPatternC[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCE && bcPatternE[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCL && bcPatternL[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCLE && bcPatternLE[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCNL && bcPatternB[localBC] && !bcPatternL[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCNLE && bcPatternB[localBC] && !bcPatternLE[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCSLFDD && isSuperLeadingBcFDD) + fillHistograms(timeSinceSOF, localBCFDD); + if (cfgDoBCSLFT0 && isSuperLeadingBcFT0) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCNSLFDD && bcPatternB[localBCFDD] && !isSuperLeadingBcFDD) + fillHistograms(timeSinceSOF, localBCFDD); + if (cfgDoBCNSLFT0 && bcPatternB[localBC] && !isSuperLeadingBcFT0) + fillHistograms(timeSinceSOF, localBC); + } + + if (cfgDoFDD && anyFDDTrigger) { + if (cfgDoBCA && bcPatternA[localBCFDD]) + fillHistograms(timeSinceSOF, localBCFDD); + if (cfgDoBCB && bcPatternB[localBCFDD]) + fillHistograms(timeSinceSOF, localBCFDD); + if (cfgDoBCC && bcPatternC[localBCFDD]) + fillHistograms(timeSinceSOF, localBCFDD); + if (cfgDoBCE && bcPatternE[localBCFDD]) + fillHistograms(timeSinceSOF, localBCFDD); + if (cfgDoBCL && bcPatternL[localBCFDD]) + fillHistograms(timeSinceSOF, localBCFDD); + if (cfgDoBCLE && bcPatternLE[localBCFDD]) + fillHistograms(timeSinceSOF, localBCFDD); + if (cfgDoBCNL && bcPatternB[localBCFDD] && !bcPatternL[localBCFDD]) + fillHistograms(timeSinceSOF, localBCFDD); + if (cfgDoBCNLE && bcPatternB[localBCFDD] && !bcPatternLE[localBCFDD]) + fillHistograms(timeSinceSOF, localBCFDD); + if (cfgDoBCSLFDD && isSuperLeadingBcFDD) + fillHistograms(timeSinceSOF, localBCFDD); + if (cfgDoBCSLFT0 && bcPatternB[localBCFDD] && isSuperLeadingBcFT0) + fillHistograms(timeSinceSOF, localBCFDD); + if (cfgDoBCNSLFDD && bcPatternB[localBCFDD] && !isSuperLeadingBcFDD) + fillHistograms(timeSinceSOF, localBCFDD); + if (cfgDoBCNSLFT0 && bcPatternB[localBCFDD] && !isSuperLeadingBcFT0) + fillHistograms(timeSinceSOF, localBCFDD); + } + + if (cfgDo1ZNC && ctpInputMask.test(25)) { + if (cfgDoBCA && bcPatternA[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCB && bcPatternB[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCC && bcPatternC[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCE && bcPatternE[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCL && bcPatternL[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCLE && bcPatternLE[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCNL && bcPatternB[localBC] && !bcPatternL[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCNLE && bcPatternB[localBC] && !bcPatternLE[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCSLFDD && isSuperLeadingBcFDD) + fillHistograms(timeSinceSOF, localBCFDD); + if (cfgDoBCSLFT0 && isSuperLeadingBcFT0) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCNSLFDD && bcPatternB[localBCFDD] && !isSuperLeadingBcFDD) + fillHistograms(timeSinceSOF, localBCFDD); + if (cfgDoBCNSLFT0 && bcPatternB[localBC] && !isSuperLeadingBcFT0) + fillHistograms(timeSinceSOF, localBC); + } + + mHistManager.fill(HIST("nBCsVsBCID"), localBC); + } - for (int iTrigger = 0; iTrigger < nTriggers; iTrigger++) { - if ((iTrigger == kAllBCs) || (iTrigger == kFT0Vtx && cfgDoFT0Vtx) || (iTrigger == kFT0CE && cfgDoFT0CE) || (iTrigger == kFDD && cfgDoFDD) || (iTrigger == k1ZNC && cfgDo1ZNC)) { - for (int iBCCategory = 0; iBCCategory < nBCCategories - 1; iBCCategory++) { // Don't do SL BCs here - if ((iBCCategory == kBCA && cfgDoBCA) || (iBCCategory == kBCB && cfgDoBCB) || (iBCCategory == kBCC && cfgDoBCC) || (iBCCategory == kBCE && cfgDoBCE) || (iBCCategory == kBCL && cfgDoBCL)) { - if (iTrigger == kAllBCs) { - if (iBCCategory == kBCA && bcPatternA[localBC]) - fillHistograms(timeSinceSOF, localBC); - if (iBCCategory == kBCB && bcPatternB[localBC]) - fillHistograms(timeSinceSOF, localBC); - if (iBCCategory == kBCC && bcPatternC[localBC]) - fillHistograms(timeSinceSOF, localBC); - if (iBCCategory == kBCE && bcPatternE[localBC]) - fillHistograms(timeSinceSOF, localBC); - if (iBCCategory == kBCL && bcPatternL[localBC]) - fillHistograms(timeSinceSOF, localBC); - } - if (iTrigger == kFT0Vtx && ctpInputMask.test(2)) { - if (iBCCategory == kBCA && bcPatternA[localBC]) - fillHistograms(timeSinceSOF, localBC); - if (iBCCategory == kBCB && bcPatternB[localBC]) - fillHistograms(timeSinceSOF, localBC); - if (iBCCategory == kBCC && bcPatternC[localBC]) - fillHistograms(timeSinceSOF, localBC); - if (iBCCategory == kBCE && bcPatternE[localBC]) - fillHistograms(timeSinceSOF, localBC); - if (iBCCategory == kBCL && bcPatternL[localBC]) - fillHistograms(timeSinceSOF, localBC); - } - if (iTrigger == kFT0CE && ctpInputMask.test(4)) { - if (iBCCategory == kBCA && bcPatternA[localBC]) - fillHistograms(timeSinceSOF, localBC); - if (iBCCategory == kBCB && bcPatternB[localBC]) - fillHistograms(timeSinceSOF, localBC); - if (iBCCategory == kBCC && bcPatternC[localBC]) - fillHistograms(timeSinceSOF, localBC); - if (iBCCategory == kBCE && bcPatternE[localBC]) - fillHistograms(timeSinceSOF, localBC); - if (iBCCategory == kBCL && bcPatternL[localBC]) - fillHistograms(timeSinceSOF, localBC); - } - if (iTrigger == kFDD && ctpInputMask.test(15)) { - if (iBCCategory == kBCA && bcPatternA[localBC]) - fillHistograms(timeSinceSOF, localBC); - if (iBCCategory == kBCB && bcPatternB[localBC]) - fillHistograms(timeSinceSOF, localBC); - if (iBCCategory == kBCC && bcPatternC[localBC]) - fillHistograms(timeSinceSOF, localBC); - if (iBCCategory == kBCE && bcPatternE[localBC]) - fillHistograms(timeSinceSOF, localBC); - if (iBCCategory == kBCL && bcPatternL[localBC]) - fillHistograms(timeSinceSOF, localBC); - } - if (iTrigger == k1ZNC && ctpInputMask.test(25)) { - if (iBCCategory == kBCA && bcPatternA[localBC]) - fillHistograms(timeSinceSOF, localBC); - if (iBCCategory == kBCB && bcPatternB[localBC]) - fillHistograms(timeSinceSOF, localBC); - if (iBCCategory == kBCC && bcPatternC[localBC]) - fillHistograms(timeSinceSOF, localBC); - if (iBCCategory == kBCE && bcPatternE[localBC]) - fillHistograms(timeSinceSOF, localBC); - if (iBCCategory == kBCL && bcPatternL[localBC]) - fillHistograms(timeSinceSOF, localBC); - } - } + for (int iT = 0; iT < nTriggers; ++iT) { + for (int iC = 0; iC < nBCCategories; ++iC) { + if (!mInspectedHistos[iT][iC]) { + continue; + } + for (int iBcId = 0; iBcId < nBCsPerOrbit; ++iBcId) { + const int value = nBCsPerBcId[iBcId][iT][iC]; + if (value > 0) { + mInspectedHistos[iT][iC]->Fill(iBcId, value); } } } - mHistManager.fill(HIST("nBCsVsBCID"), localBC); } } }; From 8068278cd40739367ddf858aee75f4acf7c41b90 Mon Sep 17 00:00:00 2001 From: Sushanta Tripathy Date: Sat, 7 Mar 2026 11:58:17 +0100 Subject: [PATCH 202/347] [PWGCF] Fixing minor bugs (#15277) Co-authored-by: Sushanta Tripathy --- .../Tasks/nucleibalance.cxx | 128 ++++++++++++++---- 1 file changed, 98 insertions(+), 30 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/nucleibalance.cxx b/PWGCF/TwoParticleCorrelations/Tasks/nucleibalance.cxx index 6eb1425355d..c905bda396d 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/nucleibalance.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/nucleibalance.cxx @@ -24,18 +24,18 @@ #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/MathConstants.h" -#include "CommonConstants/PhysicsConstants.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Framework/StepTHn.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -1707,7 +1707,8 @@ struct Lambdastarproxy { Configurable lstarMixZvtxMax{"lstarMixZvtxMax", float{MixZvtxMaxDefault}, "Max |Δzvtx| (cm) for event mixing"}; Configurable lstarMixMultMax{"lstarMixMultMax", float{MixMultMaxDefault}, "Max |Δmult| for event mixing"}; Configurable lstarEnablePidQA{"lstarEnablePidQA", 0, "Enable PID QA histograms (dE/dx, TOF #beta, proxy invariant-mass QA, etc.): 1 = ON, 0 = OFF"}; - Configurable lstarEnableSparse{"lstarEnableSparse", 0, "Enable THnSparse invariant-mass histograms (#Lambda^{*} pK and proxy); 1 = ON, 0 = OFF"}; + Configurable lstarEnableSparse{"lstarEnableSparse", 1, "Enable THnSparse invariant-mass histograms (#Lambda^{*} pK and proxy); 1 = ON, 0 = OFF"}; + Configurable lstarLambdaAbsYMax{"lstarLambdaAbsYMax", 0.5f, "Max |y_{pK}| (or y_{proxy K}) for #Lambda^{*} candidates"}; struct KaonCand { float px, py, pz; @@ -1719,6 +1720,11 @@ struct Lambdastarproxy { int charge; int tid; }; + struct ProtonCand { + float px, py, pz; + int charge; + int tid; + }; // Helpers for invariant-mass kinematics static float phiFromPxPy(float px, float py) @@ -2004,7 +2010,7 @@ struct Lambdastarproxy { // Deuteron-proxy invariant mass (p_{proxy} from d/2 combined with K) histos.add("hDeuteronProxyMass", - "#Lambda^{*} proxy invariant mass from (d/2 + K);M_{pK} (GeV/c^{2});Counts", + "#Lambda^{*} proxy invariant mass from (d/2 + K);M_{p_{proxy}K} (GeV/c^{2});Counts", HistType::kTH1F, {massAxis}); // TPC dE/dx vs total momentum @@ -2405,8 +2411,10 @@ struct Lambdastarproxy { std::vector kaonCands; std::vector proxyCands; + std::vector protonCands; kaonCands.reserve(128); proxyCands.reserve(32); + protonCands.reserve(128); float eventMultFallback = 0.f; // fallback mixing variable: number of selected charged tracks (after quality cuts) @@ -2507,7 +2515,9 @@ struct Lambdastarproxy { // PID for deuteron candidates const float nsTPCDe = trkD.tpcNSigmaDe(); const float nsTOFDe = trkD.tofNSigmaDe(); - const bool isDeuteron = (std::abs(nsTPCDe) < lstarCutNsigmaTPCDe.value) && (std::abs(nsTOFDe) < lstarCutNsigmaTOFDe.value); + const bool hasTofDe = hasTOFMatch(trkD); + const bool isDeuteron = (std::abs(nsTPCDe) < lstarCutNsigmaTPCDe.value) && + (!hasTofDe || (std::abs(nsTOFDe) < lstarCutNsigmaTOFDe.value)); if (!isDeuteron) { continue; } @@ -2537,6 +2547,38 @@ struct Lambdastarproxy { proxyCands.push_back(ProxyCand{pxProxy, pyProxy, pzProxy, static_cast(trkD.sign()), static_cast(trkD.globalIndex())}); } + // Proton candidates (for genuine pK #Lambda^{*} reconstruction) + for (auto const& trkP : tracks) { + if (trkP.pt() < lstarCutPtMin.value || std::abs(trkP.eta()) > lstarCutEtaMax.value) { + continue; + } + if (!passTrackQuality(trkP)) { + continue; + } + if (trkP.sign() == 0) { + continue; + } + + const float nsTPCPr = trkP.tpcNSigmaPr(); + const float nsTOFPr = trkP.tofNSigmaPr(); + const bool hasTofPr = hasTOFMatch(trkP); + const bool isProton = (std::abs(nsTPCPr) < lstarCutNsigmaTPCPr.value) && + (!hasTofPr || (std::abs(nsTOFPr) < lstarCutNsigmaTOFPr.value)); + if (!isProton) { + continue; + } + + const float ptP = trkP.pt(); + const float etaP = trkP.eta(); + const float phiP = trkP.phi(); + + const float pxP = ptP * std::cos(phiP); + const float pyP = ptP * std::sin(phiP); + const float pzP = ptP * std::sinh(etaP); + + protonCands.push_back(ProtonCand{pxP, pyP, pzP, static_cast(trkP.sign()), static_cast(trkP.globalIndex())}); + } + // Kaon candidates for (auto const& trkK : tracks) { if (trkK.pt() < lstarCutPtMin.value || std::abs(trkK.eta()) > lstarCutEtaMax.value) { @@ -2552,7 +2594,9 @@ struct Lambdastarproxy { // PID for kaon candidates const float nsTPCK = trkK.tpcNSigmaKa(); const float nsTOFK = trkK.tofNSigmaKa(); - const bool isKaon = (std::abs(nsTPCK) < lstarCutNsigmaTPCKaon.value) && (std::abs(nsTOFK) < lstarCutNsigmaTOFKaon.value); + const bool hasTofK = hasTOFMatch(trkK); + const bool isKaon = (std::abs(nsTPCK) < lstarCutNsigmaTPCKaon.value) && + (!hasTofK || (std::abs(nsTOFK) < lstarCutNsigmaTOFKaon.value)); if (!isKaon) { continue; } @@ -2595,12 +2639,14 @@ struct Lambdastarproxy { return; } - // --- SAME-EVENT: proxy (d/2) + K --- - for (auto const& pr : proxyCands) { + // --- SAME-EVENT: genuine pK #Lambda^{*} candidates --- + for (auto const& pr : protonCands) { for (auto const& k : kaonCands) { - if (pr.tid == k.tid) - continue; // sanity check: should never match, but just in case of bug in candidate-building logic - const double mass = invariantMass(pr.px, pr.py, pr.pz, MassProton, k.px, k.py, k.pz, MassKaonCharged); + if (pr.tid == k.tid) { + continue; + } + const double mass = invariantMass(pr.px, pr.py, pr.pz, MassProton, + k.px, k.py, k.pz, MassKaonCharged); const float pxTot = pr.px + k.px; const float pyTot = pr.py + k.py; @@ -2608,17 +2654,16 @@ struct Lambdastarproxy { const float ptPair = std::sqrt(pxTot * pxTot + pyTot * pyTot); const float phiPair = phiFromPxPy(pxTot, pyTot); - const double eTot = std::sqrt(mass * mass + static_cast(pxTot) * pxTot + static_cast(pyTot) * pyTot + static_cast(pzTot) * pzTot); + const double eTot = std::sqrt(mass * mass + static_cast(pxTot) * pxTot + + static_cast(pyTot) * pyTot + static_cast(pzTot) * pzTot); const float yPair = rapidityFromEPz(eTot, pzTot); - // Inclusive invariant-mass spectrum for the #Lambda^{*} proxy - histos.fill(HIST("hDeuteronProxyMass"), mass); - if (lstarEnableSparse.value != 0) { - histos.fill(HIST("hLambdaStarProxySparse"), mass, ptPair, yPair, phiPair, eventMult); + if (std::abs(yPair) > lstarLambdaAbsYMax.value) { + continue; } - const bool unlikeSign = (pr.charge * k.charge) < 0; - if (unlikeSign) { + const bool unlikeSignPK = (pr.charge * k.charge) < 0; + if (unlikeSignPK) { histos.fill(HIST("hInvMassPKUnlike"), mass); histos.fill(HIST("hInvMassPKUnlikeVsPt"), mass, ptPair); if (lstarEnableSparse.value != 0) { @@ -2634,6 +2679,30 @@ struct Lambdastarproxy { } } + // --- SAME-EVENT: proxy (d/2) + K --- + for (auto const& pr : proxyCands) { + for (auto const& k : kaonCands) { + if (pr.tid == k.tid) + continue; // sanity check: should never match, but just in case of bug in candidate-building logic + const double mass = invariantMass(pr.px, pr.py, pr.pz, MassProton, k.px, k.py, k.pz, MassKaonCharged); + + const float pxTot = pr.px + k.px; + const float pyTot = pr.py + k.py; + const float pzTot = pr.pz + k.pz; + const float ptPair = std::sqrt(pxTot * pxTot + pyTot * pyTot); + const float phiPair = phiFromPxPy(pxTot, pyTot); + + const double eTot = std::sqrt(mass * mass + static_cast(pxTot) * pxTot + static_cast(pyTot) * pyTot + static_cast(pzTot) * pzTot); + const float yPair = rapidityFromEPz(eTot, pzTot); + + // Inclusive invariant-mass spectrum for the #Lambda^{*} proxy (d/2 + K) + histos.fill(HIST("hDeuteronProxyMass"), mass); + if (lstarEnableSparse.value != 0) { + histos.fill(HIST("hLambdaStarProxySparse"), mass, ptPair, yPair, phiPair, eventMult); + } + } + } + // --- MIXED-EVENT: current proxies + previous-event kaons --- for (auto const& prev : mLStarMixEvents) { if (std::abs(prev.zvtx - collision.posZ()) > lstarMixZvtxMax.value) @@ -2664,9 +2733,8 @@ struct Lambdastarproxy { const double eTot = std::sqrt(mass * mass + static_cast(pxTot) * pxTot + static_cast(pyTot) * pyTot + static_cast(pzTot) * pzTot); const float yPair = rapidityFromEPz(eTot, pzTot); - // Fill mixed-event THnSparse + // Fill mixed-event THnSparse (proxy only) if (lstarEnableSparse.value != 0) { - histos.fill(HIST("hLambdaStarPKMixedSparse"), mass, ptPair, yPair, phiPair, eventMult); histos.fill(HIST("hLambdaStarProxyMixedSparse"), mass, ptPair, yPair, phiPair, eventMult); } } From 5e66b542dc9f364ff4e250ef41e02910892ed059 Mon Sep 17 00:00:00 2001 From: Preet-Bhanjan Date: Sat, 7 Mar 2026 13:37:50 +0100 Subject: [PATCH 203/347] [PWGCF] Addition of dEdx distributions after PID cut (#15297) Co-authored-by: Preet Pati Co-authored-by: ALICE Action Bot --- .../Tasks/pidDiHadron.cxx | 36 ++++++++++++++++--- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/pidDiHadron.cxx b/PWGCF/TwoParticleCorrelations/Tasks/pidDiHadron.cxx index 58e5162ba1e..2ae92312225 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/pidDiHadron.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/pidDiHadron.cxx @@ -120,7 +120,7 @@ struct PidDiHadron { O2_DEFINE_CONFIGURABLE(cfgGetNsigmaQA, bool, true, "Get QA histograms for selection of pions, kaons, and protons") O2_DEFINE_CONFIGURABLE(cfgGetdEdx, bool, true, "Get dEdx histograms for pions, kaons, and protons") O2_DEFINE_CONFIGURABLE(cfgUseAntiLambda, bool, true, "Use AntiLambda candidates for analysis") - O2_DEFINE_CONFIGURABLE(cfgPIDUseRejection, bool, true, "Turn off and on the exclusion criteria for PID determination") + O2_DEFINE_CONFIGURABLE(cfgPIDUseRejection, bool, true, "True: use exclusion exclusion criteria for PID determination, false: don't use exclusion") struct : ConfigurableGroup { O2_DEFINE_CONFIGURABLE(cfgMultCentHighCutFunction, std::string, "[0] + [1]*x + [2]*x*x + [3]*x*x*x + [4]*x*x*x*x + 10.*([5] + [6]*x + [7]*x*x + [8]*x*x*x + [9]*x*x*x*x)", "Functional for multiplicity correlation cut"); @@ -504,6 +504,10 @@ struct PidDiHadron { histos.add("TpcdEdx_ptwise", "", {HistType::kTHnSparseD, {{axisPt, axisTpcSignal, axisNsigmaTOF}}}); histos.add("ExpTpcdEdx_ptwise", "", {HistType::kTHnSparseD, {{axisPt, axisTpcSignal, axisNsigmaTOF}}}); histos.add("ExpSigma_ptwise", "", {HistType::kTHnSparseD, {{axisPt, axisSigma, axisNsigmaTOF}}}); + + histos.add("TpcdEdx_ptwise_afterCut", "", {HistType::kTHnSparseD, {{axisPt, axisTpcSignal, axisNsigmaTOF}}}); + histos.add("ExpTpcdEdx_ptwise_afterCut", "", {HistType::kTHnSparseD, {{axisPt, axisTpcSignal, axisNsigmaTOF}}}); + histos.add("ExpSigma_ptwise_afterCut", "", {HistType::kTHnSparseD, {{axisPt, axisSigma, axisNsigmaTOF}}}); } } // TPC-TOF PID QA hists if (cfgUseItsPID) { @@ -792,20 +796,44 @@ struct PidDiHadron { { switch (pid) { case 1: // For Pions - if (!cfgUseItsPID) + if (!cfgUseItsPID) { + if (cfgGetdEdx) { + double tpcExpSignalPi = track1.tpcSignal() - (track1.tpcNSigmaPi() * track1.tpcExpSigmaPi()); + + histos.fill(HIST("TpcdEdx_ptwise_afterCut"), track1.pt(), track1.tpcSignal(), track1.tofNSigmaPi()); + histos.fill(HIST("ExpTpcdEdx_ptwise_afterCut"), track1.pt(), tpcExpSignalPi, track1.tofNSigmaPi()); + histos.fill(HIST("ExpSigma_ptwise_afterCut"), track1.pt(), track1.tpcExpSigmaPi(), track1.tofNSigmaPi()); + } histos.fill(HIST("TofTpcNsigma_after"), track1.tpcNSigmaPi(), track1.tofNSigmaPi(), track1.pt()); + } if (cfgUseItsPID) histos.fill(HIST("TofItsNsigma_after"), itsResponse.nSigmaITS(track1), track1.tofNSigmaPi(), track1.pt()); break; case 2: // For Kaons - if (!cfgUseItsPID) + if (!cfgUseItsPID) { + if (cfgGetdEdx) { + double tpcExpSignalKa = track1.tpcSignal() - (track1.tpcNSigmaKa() * track1.tpcExpSigmaKa()); + + histos.fill(HIST("TpcdEdx_ptwise_afterCut"), track1.pt(), track1.tpcSignal(), track1.tofNSigmaKa()); + histos.fill(HIST("ExpTpcdEdx_ptwise_afterCut"), track1.pt(), tpcExpSignalKa, track1.tofNSigmaKa()); + histos.fill(HIST("ExpSigma_ptwise_afterCut"), track1.pt(), track1.tpcExpSigmaKa(), track1.tofNSigmaKa()); + } histos.fill(HIST("TofTpcNsigma_after"), track1.tpcNSigmaKa(), track1.tofNSigmaKa(), track1.pt()); + } if (cfgUseItsPID) histos.fill(HIST("TofItsNsigma_after"), itsResponse.nSigmaITS(track1), track1.tofNSigmaKa(), track1.pt()); break; case 3: // For Protons - if (!cfgUseItsPID) + if (!cfgUseItsPID) { + if (cfgGetdEdx) { + double tpcExpSignalPr = track1.tpcSignal() - (track1.tpcNSigmaPr() * track1.tpcExpSigmaPr()); + + histos.fill(HIST("TpcdEdx_ptwise_afterCut"), track1.pt(), track1.tpcSignal(), track1.tofNSigmaPr()); + histos.fill(HIST("ExpTpcdEdx_ptwise_afterCut"), track1.pt(), tpcExpSignalPr, track1.tofNSigmaPr()); + histos.fill(HIST("ExpSigma_ptwise_afterCut"), track1.pt(), track1.tpcExpSigmaPr(), track1.tofNSigmaPr()); + } histos.fill(HIST("TofTpcNsigma_after"), track1.tpcNSigmaPr(), track1.tofNSigmaPr(), track1.pt()); + } if (cfgUseItsPID) histos.fill(HIST("TofItsNsigma_after"), itsResponse.nSigmaITS(track1), track1.tofNSigmaPr(), track1.pt()); break; From c6666cd7d20332457983d1b4f3697098059e3283 Mon Sep 17 00:00:00 2001 From: Thorkj <154221526+Thorkj@users.noreply.github.com> Date: Sat, 7 Mar 2026 13:41:54 +0100 Subject: [PATCH 204/347] [PWGCF] Added corrections and Mft reassociated tracks (#15293) Co-authored-by: ALICE Action Bot --- .../Tasks/corrSparse.cxx | 347 +++++++++++++----- 1 file changed, 247 insertions(+), 100 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/corrSparse.cxx b/PWGCF/TwoParticleCorrelations/Tasks/corrSparse.cxx index 441f35da404..e0c75ff22a6 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/corrSparse.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/corrSparse.cxx @@ -80,6 +80,7 @@ struct CorrSparse { O2_DEFINE_CONFIGURABLE(cfgUseAdditionalEventCut, bool, false, "Use additional event cut on mult correlations") O2_DEFINE_CONFIGURABLE(cfgZVtxCut, float, 10.0f, "Accepted z-vertex range") + O2_DEFINE_CONFIGURABLE(cfgQaCheck, bool, false, "Fill QA histograms for multiplicity and zVtx for events used in the analysis") struct : ConfigurableGroup{ O2_DEFINE_CONFIGURABLE(cfgPtCutMin, float, 0.2f, "minimum accepted track pT") @@ -156,6 +157,7 @@ struct CorrSparse { O2_DEFINE_CONFIGURABLE(cfgCentralityWeight, std::string, "", "CCDB path to centrality weight object") O2_DEFINE_CONFIGURABLE(cfgLocalEfficiency, bool, false, "Use local efficiency object") O2_DEFINE_CONFIGURABLE(cfgUseEventWeights, bool, false, "Use event weights for mixed event") + O2_DEFINE_CONFIGURABLE(cfgCollType, int, 0, "Collision type: 0 = pp, 1 = pPb, 2 = pO, 3 = OO") struct : ConfigurableGroup { O2_DEFINE_CONFIGURABLE(cfgMultCentHighCutFunction, std::string, "[0] + [1]*x + [2]*x*x + [3]*x*x*x + [4]*x*x*x*x + 10.*([5] + [6]*x + [7]*x*x + [8]*x*x*x + [9]*x*x*x*x)", "Functional for multiplicity correlation cut"); @@ -219,11 +221,6 @@ struct CorrSparse { ConfigurableAxis multMix{"multMix", {VARIABLE_WIDTH, 0, 5, 10, 15, 20, 25, 30, 35, 40, 50, 60, 80, 100}, "multiplicity / centrality axis for mixed event histograms"}; ConfigurableAxis axisSample{"axisSample", {cfgSampleSize, 0, cfgSampleSize}, "sample axis for histograms"}; - ConfigurableAxis axisNsigmaTPC{"axisNsigmaTPC", {80, -5, 5}, "nsigmaTPC axis"}; - ConfigurableAxis axisNsigmaTOF{"axisNsigmaTOF", {80, -5, 5}, "nsigmaTOF axis"}; - ConfigurableAxis axisNsigmaITS{"axisNsigmaITS", {80, -5, 5}, "nsigmaITS axis"}; - ConfigurableAxis axisTpcSignal{"axisTpcSignal", {250, 0, 250}, "dEdx axis for TPC"}; - ConfigurableAxis axisVertexEfficiency{"axisVertexEfficiency", {10, -10, 10}, "vertex axis for efficiency histograms"}; ConfigurableAxis axisEtaEfficiency{"axisEtaEfficiency", {20, -1.0, 1.0}, "eta axis for efficiency histograms"}; ConfigurableAxis axisPtEfficiency{"axisPtEfficiency", {VARIABLE_WIDTH, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.25, 1.5, 1.75, 2.0, 2.25, 2.5, 2.75, 3.0, 3.25, 3.5, 3.75, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0}, "pt axis for efficiency histograms"}; @@ -301,20 +298,6 @@ struct CorrSparse { kNEventCuts }; - enum MftTrackAmbiguityStep { - AllMftTracks = 0, - AfterTrackSelection, - NumberOfAmbiguousTracks, - NumberOfNonAmbiguousTracks, - NMftAmbiguitySteps - }; - - enum ReassociationMftTracks { - NotReassociatedMftTracks = 0, - ReassociatedMftTracks, - NReassociationMftTracksSteps - }; - enum EventType { SameEvent = 1, MixedEvent = 3 @@ -357,7 +340,7 @@ struct CorrSparse { LOGF(info, "Starting init"); // Event Counter - if ((doprocessSameTpcFIT || doprocessSameTpcMft || doprocessSameTPC || doprocessSameMFTFIT || doprocessSameTpcMftReassociated2D || doprocessSameTpcMftReassociated3D) && cfgUseAdditionalEventCut) { + if ((doprocessSameTpcFIT || doprocessSameTpcMft || doprocessSameTPC || doprocessSameMFTFIT || doprocessSameTpcMftReassociated2D || doprocessSameTpcMftReassociated3D || doprocessSameMftReassociated2DFIT) && cfgUseAdditionalEventCut) { registry.add("hEventCountSpecific", "Number of Event;; Count", {HistType::kTH1D, {{13, 0, 13}}}); registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(1, "after sel8"); registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(2, "kNoSameBunchPileup"); @@ -374,26 +357,25 @@ struct CorrSparse { registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(13, "cfgEvSelV0AT0ACut"); } - if (doprocessSameTpcMftReassociated2D || doprocessSameTpcMftReassociated3D) { - registry.add("hEventCountMftReassoc", "Number of Event;; Count", {HistType::kTH1D, {{5, 0, 5}}}); + if (doprocessSameTpcMftReassociated2D || doprocessSameTpcMftReassociated3D || doprocessSameMftReassociated2DFIT) { + registry.add("hEventCountMftReassoc", "Number of Events;; Count", {HistType::kTH1D, {{4, 0, 4}}}); registry.get(HIST("hEventCountMftReassoc"))->GetXaxis()->SetBinLabel(1, "all MFT tracks"); registry.get(HIST("hEventCountMftReassoc"))->GetXaxis()->SetBinLabel(2, "MFT tracks after selection"); registry.get(HIST("hEventCountMftReassoc"))->GetXaxis()->SetBinLabel(3, "ambiguous MFT tracks"); registry.get(HIST("hEventCountMftReassoc"))->GetXaxis()->SetBinLabel(4, "non-ambiguous MFT tracks"); - registry.get(HIST("hEventCountMftReassoc"))->GetXaxis()->SetBinLabel(5, "Reassociated MFT tracks"); - registry.add("ReassociatedMftTracks", "Reassociated MFT tracks", {HistType::kTH1D, {{3, 0, 3}}}); + registry.add("ReassociatedMftTracks", "Reassociated MFT tracks", {HistType::kTH1D, {{2, 0, 2}}}); registry.get(HIST("ReassociatedMftTracks"))->GetXaxis()->SetBinLabel(1, "Not Reassociated MFT tracks"); registry.get(HIST("ReassociatedMftTracks"))->GetXaxis()->SetBinLabel(2, "Reassociated MFT tracks"); } // Make histograms to check the distributions after cuts - if (doprocessSameTpcFIT || doprocessSameTpcMft || doprocessSameTPC || doprocessSameMFTFIT || doprocessSameTpcMftReassociated2D || doprocessSameTpcMftReassociated3D) { + if (doprocessSameTpcFIT || doprocessSameTpcMft || doprocessSameTPC || doprocessSameMFTFIT || doprocessSameTpcMftReassociated2D || doprocessSameTpcMftReassociated3D || doprocessSameMftReassociated2DFIT) { registry.add("Phi", "Phi", {HistType::kTH1D, {axisPhi}}); if (doprocessSameMFTFIT) { registry.add("Eta", "EtaMFT", {HistType::kTH1D, {axisEtaMft}}); } - if (doprocessSameTpcFIT || doprocessSameTPC || doprocessSameTpcMftReassociated2D || doprocessSameTpcMftReassociated3D) { + if (doprocessSameTpcFIT || doprocessSameTpcMft || doprocessSameTPC || doprocessSameTpcMftReassociated2D || doprocessSameTpcMftReassociated3D) { registry.add("Eta", "Eta", {HistType::kTH1D, {axisEta}}); } registry.add("EtaCorrected", "EtaCorrected", {HistType::kTH1D, {axisEta}}); @@ -404,7 +386,7 @@ struct CorrSparse { registry.add("zVtx", "zVtx", {HistType::kTH1D, {axisVertex}}); registry.add("zVtx_used", "zVtx_used", {HistType::kTH1D, {axisVertex}}); - if (doprocessSameTpcFIT || doprocessSameMFTFIT) { + if (doprocessSameTpcFIT || doprocessSameMFTFIT || doprocessSameMftReassociated2DFIT) { registry.add("FT0Amp", "", {HistType::kTH2F, {axisChID, axisFit}}); registry.add("FV0Amp", "", {HistType::kTH2F, {axisChID, axisFit}}); registry.add("FT0AmpCorrect", "", {HistType::kTH2F, {axisChID, axisFit}}); @@ -436,7 +418,7 @@ struct CorrSparse { } } - if (doprocessSameMFTFIT) { + if (doprocessSameMFTFIT || doprocessSameMftReassociated2DFIT) { if (cfgDetectorConfig.processFT0A) { registry.add("deltaEta_deltaPhi_same_MFT_FT0A", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaMftFt0a}}); // check to see the delta eta and delta phi distribution @@ -464,13 +446,13 @@ struct CorrSparse { if (doprocessSameTpcMft || doprocessSameTpcMftReassociated2D || doprocessSameTpcMftReassociated3D) { registry.add("deltaEta_deltaPhi_same_TPC_MFT", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaTpcMft}}); // check to see the delta eta and delta phi distribution registry.add("deltaEta_deltaPhi_mixed_TPC_MFT", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaTpcMft}}); - registry.add("Trig_hist_TPC_MFT", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisPtTrigger}}}); + registry.add("Trig_hist", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisPtTrigger}}}); } if (doprocessSameTPC) { registry.add("deltaEta_deltaPhi_same_TPC_TPC", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEta}}); // check to see the delta eta and delta phi distribution registry.add("deltaEta_deltaPhi_mixed_TPC_TPC", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEta}}); - registry.add("Trig_hist_TPC_TPC", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisPtTrigger}}}); + registry.add("Trig_hist", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisPtTrigger}}}); } registry.add("eventcount", "bin", {HistType::kTH1F, {{4, 0, 4, "bin"}}}); // histogram to see how many events are in the same and mixed event @@ -483,6 +465,7 @@ struct CorrSparse { {axisPtAssoc, "p_{T} (GeV/c)"}, {axisDeltaPhi, "#Delta#varphi (rad)"}, {axisDeltaEtaTpcFt0c, "#Delta#eta"}}; + std::vector effAxis = { {axisEtaEfficiency, "#eta"}, {axisPtEfficiency, "p_{T} (GeV/c)"}, @@ -572,6 +555,21 @@ struct CorrSparse { } } + if (doprocessSameMftReassociated2DFIT) { + if (cfgDetectorConfig.processFT0A) { + same.setObject(new CorrelationContainer("sameEvent_MFT_Reassociated2D_FT0A", "sameEvent_MFT_Reassociated2D_FT0A", corrAxisMftFt0a, effAxis, userAxis)); + mixed.setObject(new CorrelationContainer("mixedEvent_MFT_Reassociated2D_FT0A", "mixedEvent_MFT_Reassociated2D_FT0A", corrAxisMftFt0a, effAxis, userAxis)); + } + if (cfgDetectorConfig.processFT0C) { + same.setObject(new CorrelationContainer("sameEvent_MFT_Reassociated2D_FT0C", "sameEvent_MFT_Reassociated2D_FT0C", corrAxisMftFt0c, effAxis, userAxis)); + mixed.setObject(new CorrelationContainer("mixedEvent_MFT_Reassociated2D_FT0C", "mixedEvent_MFT_Reassociated2D_FT0C", corrAxisMftFt0c, effAxis, userAxis)); + } + if (cfgDetectorConfig.processFV0) { + same.setObject(new CorrelationContainer("sameEvent_MFT_Reassociated2D_FV0", "sameEvent_MFT_Reassociated2D_FV0", corrAxisMftFv0, effAxis, userAxis)); + mixed.setObject(new CorrelationContainer("mixedEvent_MFT_Reassociated2D_FV0", "mixedEvent_MFT_Reassociated2D_FV0", corrAxisMftFv0, effAxis, userAxis)); + } + } + if (doprocessSameTPC) { same.setObject(new CorrelationContainer("sameEvent_TPC_TPC", "sameEvent_TPC_TPC", corrAxisTpcTpc, effAxis, userAxis)); mixed.setObject(new CorrelationContainer("mixedEvent_TPC_TPC", "mixedEvent_TPC_TPC", corrAxisTpcTpc, effAxis, userAxis)); @@ -842,6 +840,27 @@ struct CorrSparse { } } + template + void getChannelWithGain(TFT0s const& ft0, std::size_t const& iCh, int& id, float& ampl, int fitType) + { + if (fitType == kFT0C) { + id = ft0.channelC()[iCh]; + id = id + Ft0IndexA; + ampl = ft0.amplitudeC()[iCh]; + registry.fill(HIST("FT0Amp"), id, ampl); + ampl = ampl / cstFT0RelGain[id]; + registry.fill(HIST("FT0AmpCorrect"), id, ampl); + } else if (fitType == kFT0A) { + id = ft0.channelA()[iCh]; + ampl = ft0.amplitudeA()[iCh]; + registry.fill(HIST("FT0Amp"), id, ampl); + ampl = ampl / cstFT0RelGain[id]; + registry.fill(HIST("FT0AmpCorrect"), id, ampl); + } else { + LOGF(fatal, "Cor Index %d out of range", fitType); + } + } + void loadCorrection(uint64_t timestamp) { if (correctionsLoaded) { @@ -1001,9 +1020,12 @@ struct CorrSparse { float triggerWeight = 1.0f; // loop over all tracks + if (cfgQaCheck) { - if (system == SameEvent) { - registry.fill(HIST("Nch_used"), multiplicity); + if (system == SameEvent) { + registry.fill(HIST("Nch_used"), multiplicity); + registry.fill(HIST("zVtx_used"), posZ); + } } for (auto const& track1 : tracks1) { @@ -1069,7 +1091,7 @@ struct CorrSparse { for (std::size_t iCh = 0; iCh < channelSize; iCh++) { int channelID = 0; float amplitude = 0.; - getChannelFT0(tracks2, iCh, channelID, amplitude, corType); + getChannelWithGain(tracks2, iCh, channelID, amplitude, corType); // reject depending on FT0C/FT0A rings if (corType == kFT0C) { @@ -1115,73 +1137,126 @@ struct CorrSparse { } } ////////////////////////// - //////////TPC-MFT///////// + //////////MFT-Reassociated///////// ////////////////////////// - template - void fillCorrelationsMFT(TTracks tracks1, TTracksAssoc tracks2, float posZ, int system, int magneticField) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms - { + template + void fillCorrelationsMftReassociatedFIT(TTracks tracks1, TTracksAssociated tracks2, FITs const&, float posZ, int system, int corType, float multiplicity, bool cutAmbiguousTracks) + { int fSampleIndex = gRandom->Uniform(0, cfgSampleSize); float triggerWeight = 1.0f; - if (system == SameEvent) { - registry.fill(HIST("Nch_used"), tracks1.size()); - } // loop over all tracks + if (cfgQaCheck) { + + if (system == SameEvent) { + registry.fill(HIST("Nch_used"), multiplicity); + registry.fill(HIST("zVtx_used"), posZ); + } + } + for (auto const& track1 : tracks1) { - if (!trackSelected(track1)) - continue; + auto reassociatedMftTrack = track1.template mfttrack_as(); - if (!getEfficiencyCorrection(triggerWeight, track1.eta(), track1.pt(), posZ)) + if (!isAcceptedMftTrack(reassociatedMftTrack)) { continue; + } + + if (isAmbiguousMftTrack(track1, false)) { + if (cutAmbiguousTracks) { + continue; + } + } if (system == SameEvent) { - registry.fill(HIST("Trig_hist_TPC_MFT"), fSampleIndex, posZ, track1.pt(), triggerWeight); + + registry.fill(HIST("Trig_hist"), fSampleIndex, posZ, reassociatedMftTrack.pt(), triggerWeight); } - for (auto const& track2 : tracks2) { - if constexpr (std::is_same_v) - continue; + if constexpr (std::is_same_v) { - if (!isAcceptedMftTrack(track2)) { - continue; - } + std::size_t channelSize = tracks2.channel().size(); + for (std::size_t iCh = 0; iCh < channelSize; iCh++) { + int channelID = 0; + float amplitude = 0.; - float deltaPhi = RecoDecay::constrainAngle(track1.phi() - track2.phi(), -PIHalf); - float deltaEta = track1.eta() - track2.eta(); + getChannelFV0(tracks2, iCh, channelID, amplitude); - if (cfgApplyTwoTrackEfficiency && std::abs(deltaEta) < cfgMergingCut) { + auto phi = getPhiFV0(channelID); + auto eta = getEtaFV0(channelID); - double dPhiStarHigh = getDPhiStar(track1, track2, cfgRadiusHigh, magneticField); - double dPhiStarLow = getDPhiStar(track1, track2, cfgRadiusLow, magneticField); + float deltaPhi = RecoDecay::constrainAngle(reassociatedMftTrack.phi() - phi, -PIHalf); + float deltaEta = reassociatedMftTrack.eta() - eta; - const double kLimit = 3.0 * cfgMergingCut; + if (system == SameEvent) { + registry.fill(HIST("Assoc_amp_same"), channelID, amplitude); + same->getPairHist()->Fill(step, fSampleIndex, posZ, reassociatedMftTrack.pt(), reassociatedMftTrack.pt(), deltaPhi, deltaEta, amplitude * triggerWeight); + registry.fill(HIST("deltaEta_deltaPhi_same_MFT_FV0"), deltaPhi, deltaEta, amplitude * triggerWeight); + } else if (system == MixedEvent) { + registry.fill(HIST("Assoc_amp_mixed"), channelID, amplitude); + mixed->getPairHist()->Fill(step, fSampleIndex, posZ, reassociatedMftTrack.pt(), reassociatedMftTrack.pt(), deltaPhi, deltaEta, amplitude); + registry.fill(HIST("deltaEta_deltaPhi_mixed_MFT_FV0"), deltaPhi, deltaEta, amplitude); + } + } + } - bool bIsBelow = false; + // if using FT0A and FT0C for correlations / using FT0A and FT0C as associated particles + if constexpr (std::is_same_v) { - if (std::abs(dPhiStarLow) < kLimit || std::abs(dPhiStarHigh) < kLimit || dPhiStarLow * dPhiStarHigh < 0) { - for (double rad(cfgRadiusLow); rad < cfgRadiusHigh; rad += 0.01) { - double dPhiStar = getDPhiStar(track1, track2, rad, magneticField); - if (std::abs(dPhiStar) < kLimit) { - bIsBelow = true; - break; - } - } - if (bIsBelow) + std::size_t channelSize = 0; + if (corType == kFT0C) { + channelSize = tracks2.channelC().size(); + } else if (corType == kFT0A) { + channelSize = tracks2.channelA().size(); + } else { + LOGF(fatal, "Cor Index %d out of range", corType); + } + + for (std::size_t iCh = 0; iCh < channelSize; iCh++) { + int channelID = 0; + float amplitude = 0.; + getChannelWithGain(tracks2, iCh, channelID, amplitude, corType); + + // reject depending on FT0C/FT0A rings + if (corType == kFT0C) { + if ((cfgFITConfig.cfgRejectFT0CInside && (channelID >= kFT0CInnerRingMin && channelID <= kFT0CInnerRingMax)) || (cfgFITConfig.cfgRejectFT0COutside && (channelID >= kFT0COuterRingMin && channelID <= kFT0COuterRingMax))) + continue; + } + if (corType == kFT0A) { + if ((cfgFITConfig.cfgRejectFT0AInside && (channelID >= kFT0AInnerRingMin && channelID <= kFT0AInnerRingMax)) || (cfgFITConfig.cfgRejectFT0AOutside && (channelID >= kFT0AOuterRingMin && channelID <= kFT0AOuterRingMax))) continue; } - } - // fill the right sparse and histograms - if (system == SameEvent) { + auto phi = getPhiFT0(channelID, corType); + auto eta = getEtaFT0(channelID, corType); - same->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track2.pt(), deltaPhi, deltaEta); - registry.fill(HIST("deltaEta_deltaPhi_same_TPC_MFT"), deltaPhi, deltaEta); - } else if (system == MixedEvent) { + float deltaPhi = RecoDecay::constrainAngle(reassociatedMftTrack.phi() - phi, -PIHalf); + float deltaEta = reassociatedMftTrack.eta() - eta; - mixed->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track2.pt(), deltaPhi, deltaEta); - registry.fill(HIST("deltaEta_deltaPhi_mixed_TPC_MFT"), deltaPhi, deltaEta); + if (system == SameEvent) { + if (corType == kFT0A) { + registry.fill(HIST("Assoc_amp_same"), channelID, amplitude); + same->getPairHist()->Fill(step, fSampleIndex, posZ, reassociatedMftTrack.pt(), reassociatedMftTrack.pt(), deltaPhi, deltaEta, amplitude * triggerWeight); + registry.fill(HIST("deltaEta_deltaPhi_same_MFT_FT0A"), deltaPhi, deltaEta, amplitude * triggerWeight); + } + if (corType == kFT0C) { + registry.fill(HIST("Assoc_amp_same"), channelID, amplitude); + same->getPairHist()->Fill(step, fSampleIndex, posZ, reassociatedMftTrack.pt(), reassociatedMftTrack.pt(), deltaPhi, deltaEta, amplitude * triggerWeight); + registry.fill(HIST("deltaEta_deltaPhi_same_MFT_FT0C"), deltaPhi, deltaEta, amplitude * triggerWeight); + } + } else if (system == MixedEvent) { + if (corType == kFT0A) { + registry.fill(HIST("Assoc_amp_mixed"), channelID, amplitude); + mixed->getPairHist()->Fill(step, fSampleIndex, posZ, reassociatedMftTrack.pt(), reassociatedMftTrack.pt(), deltaPhi, deltaEta, amplitude); + registry.fill(HIST("deltaEta_deltaPhi_mixed_MFT_FT0A"), deltaPhi, deltaEta, amplitude); + } + if (corType == kFT0C) { + registry.fill(HIST("Assoc_amp_mixed"), channelID, amplitude); + mixed->getPairHist()->Fill(step, fSampleIndex, posZ, reassociatedMftTrack.pt(), reassociatedMftTrack.pt(), deltaPhi, deltaEta, amplitude); + registry.fill(HIST("deltaEta_deltaPhi_mixed_MFT_FT0C"), deltaPhi, deltaEta, amplitude); + } + } } } } @@ -1195,11 +1270,13 @@ struct CorrSparse { float triggerWeight = 1.0f; auto loopCounter = 0; + if (cfgQaCheck) { - if (system == SameEvent) { - registry.fill(HIST("Nch_used"), multiplicity); + if (system == SameEvent) { + registry.fill(HIST("Nch_used"), multiplicity); + registry.fill(HIST("zVtx_used"), posZ); + } } - // loop over all tracks for (auto const& track1 : tracks1) { @@ -1212,17 +1289,17 @@ struct CorrSparse { continue; if (system == SameEvent) { - registry.fill(HIST("Trig_hist_TPC_MFT"), fSampleIndex, posZ, track1.pt(), triggerWeight); + registry.fill(HIST("Trig_hist"), fSampleIndex, posZ, track1.pt(), triggerWeight); } for (auto const& track2 : tracks2) { - auto reassociatedMftTrack = track2.template mfttrack_as(); - if (!cutAmbiguousTracks && system == SameEvent && (loopCounter == 1)) { registry.fill(HIST("hEventCountMftReassoc"), 0.5); // fill histogram for events with at least one reassociated track); } + auto reassociatedMftTrack = track2.template mfttrack_as(); + if (!isAcceptedMftTrack(reassociatedMftTrack)) { continue; } @@ -1290,34 +1367,43 @@ struct CorrSparse { //////////TPC-TPC and TPC-MFT///////// ///////////////////////////////////// template - void fillCorrelationsTpc(TTracks tracks1, TTracksAssoc tracks2, float posZ, int system, int magneticField) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms + void fillCorrelations(TTracks tracks1, TTracksAssoc tracks2, float posZ, float multiplicity, int system, int magneticField) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms { int fSampleIndex = gRandom->Uniform(0, cfgSampleSize); float triggerWeight = 1.0f; + if (cfgQaCheck) { + if (system == SameEvent) { + registry.fill(HIST("Nch_used"), multiplicity); + registry.fill(HIST("zVtx_used"), posZ); + } + } // loop over all tracks for (auto const& track1 : tracks1) { - if (!trackSelected(track1)) - continue; + if constexpr (std::is_same_v) { + if (!isAcceptedMftTrack(track1)) { + continue; + } + } else { + if (!trackSelected(track1)) + continue; - if (!getEfficiencyCorrection(triggerWeight, track1.eta(), track1.pt(), posZ)) - continue; + if (!getEfficiencyCorrection(triggerWeight, track1.eta(), track1.pt(), posZ)) + continue; + } if (system == SameEvent) { - registry.fill(HIST("Nch_used"), tracks1.size()); - registry.fill(HIST("Trig_hist_TPC_TPC"), fSampleIndex, posZ, track1.pt(), triggerWeight); + registry.fill(HIST("Trig_hist"), fSampleIndex, posZ, track1.pt(), triggerWeight); } for (auto const& track2 : tracks2) { - if (cfgDetectorConfig.processMFT) { - if constexpr (std::is_same_v) { - if (!isAcceptedMftTrack(track2)) { - continue; - } + if constexpr (std::is_same_v) { + if (!isAcceptedMftTrack(track2)) { + continue; } } else { if (!trackSelected(track2)) @@ -1387,6 +1473,7 @@ struct CorrSparse { if (!collision.sel8()) return; + auto bc = collision.bc_as(); if (cfgUseAdditionalEventCut && !eventSelected(collision, tpctracks.size(), true)) @@ -1395,12 +1482,15 @@ struct CorrSparse { if (!collision.has_foundFT0()) return; loadAlignParam(bc.timestamp()); - // loadGain(bc); + loadGain(bc); loadCorrection(bc.timestamp()); if ((tpctracks.size() < cfgEventSelection.cfgMinMult || tpctracks.size() >= cfgEventSelection.cfgMaxMult)) { return; } + if (mfts.size() == 0) { + return; + } registry.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin fillYield(collision, mfts); @@ -1430,6 +1520,59 @@ struct CorrSparse { } PROCESS_SWITCH(CorrSparse, processSameMFTFIT, "Process same event for MFT-FIT correlation", true); + void processSameMftReassociated2DFIT(AodCollisions::iterator const& collision, AodTracks const& tpctracks, + soa::SmallGroups const& reassociatedMftTracks, + FilteredMftTracks const&, + aod::FT0s const& ft0as, aod::FV0As const& fv0as, aod::BCsWithTimestamps const&) + { + if (!collision.sel8()) + return; + + auto bc = collision.bc_as(); + + if (cfgUseAdditionalEventCut && !eventSelected(collision, tpctracks.size(), true)) + return; + + if (!collision.has_foundFT0()) + return; + loadAlignParam(bc.timestamp()); + loadGain(bc); + loadCorrection(bc.timestamp()); + + if ((tpctracks.size() < cfgEventSelection.cfgMinMult || tpctracks.size() >= cfgEventSelection.cfgMaxMult)) { + return; + } + if (reassociatedMftTracks.size() == 0) { + return; + } + + registry.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin + const auto& multiplicity = tpctracks.size(); + + if (cfgDetectorConfig.processFV0) { + if (collision.has_foundFV0()) { + same->fillEvent(reassociatedMftTracks.size(), CorrelationContainer::kCFStepReconstructed); + const auto& fv0 = collision.foundFV0(); + fillCorrelationsMftReassociatedFIT(reassociatedMftTracks, fv0, fv0as, collision.posZ(), SameEvent, kFV0, multiplicity, false); + } + } + if (cfgDetectorConfig.processFT0C) { + if (collision.has_foundFT0()) { + same->fillEvent(reassociatedMftTracks.size(), CorrelationContainer::kCFStepReconstructed); + const auto& ft0 = collision.foundFT0(); + fillCorrelationsMftReassociatedFIT(reassociatedMftTracks, ft0, ft0as, collision.posZ(), SameEvent, kFT0C, multiplicity, false); + } + } + if (cfgDetectorConfig.processFT0A) { + if (collision.has_foundFT0()) { + same->fillEvent(reassociatedMftTracks.size(), CorrelationContainer::kCFStepReconstructed); + const auto& ft0 = collision.foundFT0(); + fillCorrelationsMftReassociatedFIT(reassociatedMftTracks, ft0, ft0as, collision.posZ(), SameEvent, kFT0A, multiplicity, false); + } + } + } + PROCESS_SWITCH(CorrSparse, processSameMftReassociated2DFIT, "Process same event for MFT-FIT correlation with reassociated tracks", true); + ///////////////////////// ////////Mid-Mid////////// //////////////////////// @@ -1454,7 +1597,7 @@ struct CorrSparse { loadCorrection(bc.timestamp()); fillYield(collision, tracks); - fillCorrelationsTpc(tracks, tracks, collision.posZ(), SameEvent, getMagneticField(bc.timestamp())); + fillCorrelations(tracks, tracks, collision.posZ(), tracks.size(), SameEvent, getMagneticField(bc.timestamp())); } PROCESS_SWITCH(CorrSparse, processSameTPC, "Process same event for TPC-TPC correlation", false); @@ -1510,12 +1653,14 @@ struct CorrSparse { { if (!collision.sel8()) return; + auto bc = collision.bc_as(); if (cfgUseAdditionalEventCut && !eventSelected(collision, tracks.size(), true)) return; loadCorrection(bc.timestamp()); + registry.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin fillYield(collision, tracks); @@ -1524,7 +1669,7 @@ struct CorrSparse { return; } - fillCorrelationsMFT(tracks, mfts, collision.posZ(), SameEvent, getMagneticField(bc.timestamp())); + fillCorrelations(tracks, mfts, collision.posZ(), tracks.size(), SameEvent, getMagneticField(bc.timestamp())); } PROCESS_SWITCH(CorrSparse, processSameTpcMft, "Process same event for TPC-MFT correlation", false); @@ -1535,21 +1680,23 @@ struct CorrSparse { { if (!collision.sel8()) return; + auto bc = collision.bc_as(); if (cfgUseAdditionalEventCut && !eventSelected(collision, tracks.size(), true)) return; + loadCorrection(bc.timestamp()); + registry.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin - loadCorrection(bc.timestamp()); fillYield(collision, tracks); if (tracks.size() < cfgEventSelection.cfgMinMult || tracks.size() >= cfgEventSelection.cfgMaxMult) { return; } - fillCorrelationsMftReassociatedTracks(tracks, reassociatedMftTracks, collision.posZ(), tracks.size(), SameEvent, getMagneticField(bc.timestamp()), true); + fillCorrelationsMftReassociatedTracks(tracks, reassociatedMftTracks, tracks.size(), collision.posZ(), SameEvent, getMagneticField(bc.timestamp()), false); } PROCESS_SWITCH(CorrSparse, processSameTpcMftReassociated2D, "Process same event for TPC-MFT correlation with reassociated tracks", false); @@ -1572,7 +1719,7 @@ struct CorrSparse { return; } - fillCorrelationsMftReassociatedTracks(tracks, reassociatedMftTracks, collision.posZ(), tracks.size(), SameEvent, getMagneticField(bc.timestamp()), true); + fillCorrelationsMftReassociatedTracks(tracks, reassociatedMftTracks, tracks.size(), collision.posZ(), SameEvent, getMagneticField(bc.timestamp()), false); } PROCESS_SWITCH(CorrSparse, processSameTpcMftReassociated3D, "Process same event for TPC-MFT correlation with reassociated tracks", false); @@ -1692,7 +1839,7 @@ struct CorrSparse { if (cfgUseAdditionalEventCut && !eventSelected(collision2, tracks2.size(), false)) continue; - fillCorrelationsTpc(tracks1, tracks2, collision1.posZ(), MixedEvent, getMagneticField(bc.timestamp())); + fillCorrelations(tracks1, tracks2, collision1.posZ(), tracks1.size(), MixedEvent, getMagneticField(bc.timestamp())); } } PROCESS_SWITCH(CorrSparse, processMixedTpcTpc, "Process mixed events for TPC-TPC correlation", false); @@ -1792,7 +1939,7 @@ struct CorrSparse { if ((tracks1.size() < cfgEventSelection.cfgMinMult || tracks1.size() >= cfgEventSelection.cfgMaxMult)) continue; - fillCorrelationsMFT(tracks1, tracks2, collision1.posZ(), MixedEvent, getMagneticField(bc.timestamp())); + fillCorrelations(tracks1, tracks2, collision1.posZ(), tracks1.size(), MixedEvent, getMagneticField(bc.timestamp())); } } PROCESS_SWITCH(CorrSparse, processMixedTpcMFT, "Process mixed events for TPC-MFT correlation", false); From 8fae7817515ad9fc0f4e3fbb6c008237f837babc Mon Sep 17 00:00:00 2001 From: Fan Si <147278151+fsii@users.noreply.github.com> Date: Sat, 7 Mar 2026 13:44:23 +0100 Subject: [PATCH 205/347] [PWGCF] Add centrality QA (#15283) --- PWGCF/EbyEFluctuations/Tasks/partNumFluc.cxx | 46 ++++++++++++-------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/PWGCF/EbyEFluctuations/Tasks/partNumFluc.cxx b/PWGCF/EbyEFluctuations/Tasks/partNumFluc.cxx index 314f3dcd5ec..d201fb6edf7 100644 --- a/PWGCF/EbyEFluctuations/Tasks/partNumFluc.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/partNumFluc.cxx @@ -735,7 +735,7 @@ struct PartNumFluc { Configurable cfgFlagRejectionRunBad{"cfgFlagRejectionRunBad", true, "Bad run rejection flag"}; Configurable cfgFlagRejectionRunBadMc{"cfgFlagRejectionRunBadMc", false, "MC bad run rejection flag"}; Configurable cfgLabelFlagsRct{"cfgLabelFlagsRct", "CBT_hadronPID", "RCT flags label"}; - Configurable cfgBitsSelectionEvent{"cfgBitsSelectionEvent", 0b10000000001101110100000000000000000000000000000000ULL, "Event selection bits"}; + Configurable cfgBitsSelectionEvent{"cfgBitsSelectionEvent", 0b10000000001101000000000000000000000000000000000000ULL, "Event selection bits"}; Configurable cfgFlagInelEvent{"cfgFlagInelEvent", true, "Flag of requiring inelastic event"}; Configurable cfgFlagInelEventMc{"cfgFlagInelEventMc", false, "Flag of requiring inelastic MC event"}; Configurable cfgCutMaxAbsVertexZ{"cfgCutMaxAbsVertexZ", 6., "Maximum absolute vertex z position (cm)"}; @@ -1086,8 +1086,11 @@ struct PartNumFluc { hrQaRun.add("QaRun/pRunIndexVx", ";;#LT#it{V}_{#it{x}}#GT (cm)", hcsQaRun); hrQaRun.add("QaRun/pRunIndexVy", ";;#LT#it{V}_{#it{y}}#GT (cm)", hcsQaRun); hrQaRun.add("QaRun/pRunIndexVz", ";;#LT#it{V}_{#it{z}}#GT (cm)", hcsQaRun); - hrQaRun.add("QaRun/pRunIndexMultFt0a", ";;FT0A #LTMultiplicity#GT", hcsQaRun); - hrQaRun.add("QaRun/pRunIndexMultFt0c", ";;FT0C #LTMultiplicity#GT", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexMultiplicityFt0a", ";;FT0A #LTMultiplicity#GT", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexMultiplicityFt0c", ";;FT0C #LTMultiplicity#GT", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexCentralityFt0a", ";;FT0A #LTCentrality#GT", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexCentralityFt0c", ";;FT0C #LTCentrality#GT", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexCentralityFt0m", ";;FT0M #LTCentrality#GT", hcsQaRun); hrQaRun.add("QaRun/pRunIndexNGlobalTracks_p", ";;#LTnGlobalTracks#GT (#it{q}>0)", hcsQaRun); hrQaRun.add("QaRun/pRunIndexNGlobalTracks_m", ";;#LTnGlobalTracks#GT (#it{q}<0)", hcsQaRun); hrQaRun.add("QaRun/pRunIndexNPvContributors_p", ";;#LTnPvContributors#GT (#it{q}>0)", hcsQaRun); @@ -1237,7 +1240,7 @@ struct PartNumFluc { } if (groupAnalysis.cfgFlagQaAcceptancePr.value) { - LOG(info) << "Enabling proton acceptance QA."; + LOG(info) << "Enabling (anti)proton acceptance QA."; hrQaAcceptance.add("QaAcceptance/hRapidityPt_tpcEdgePrP", "", hcsQaAcceptance); hrQaAcceptance.add("QaAcceptance/hRapidityPt_tpcEdgePrM", "", hcsQaAcceptance); @@ -1317,7 +1320,7 @@ struct PartNumFluc { } if (groupAnalysis.cfgFlagQaPhiPr.value) { - LOG(info) << "Enabling proton phi QA."; + LOG(info) << "Enabling (anti)proton phi QA."; if (doprocessMc.value) { hrQaPhi.add("QaPhi/hCentralityPtEtaPhiMc_mcPrP", "", hcsQaPhi); @@ -1397,7 +1400,7 @@ struct PartNumFluc { } if (groupAnalysis.cfgFlagQaPidPr.value) { - LOG(info) << "Enabling proton PID QA."; + LOG(info) << "Enabling (anti)proton PID QA."; if (doprocessMc.value) { hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaPr_mcPrP", "", {HistType::kTHnSparseF, {asCentrality, asPt, asEta, {200, -10., 10., "TPC #it{n}#it{#sigma}_{p}"}}}); @@ -1478,7 +1481,7 @@ struct PartNumFluc { } if (groupAnalysis.cfgFlagCalculationYieldPr.value) { - LOG(info) << "Enabling proton yield calculation."; + LOG(info) << "Enabling (anti)proton yield calculation."; if (doprocessMc.value) { hrCalculationYield.add("CalculationYield/hVzCentralityPtEtaMc_mcPrP", "", hcsCalculationYield); @@ -2294,8 +2297,17 @@ struct PartNumFluc { hrQaRun.fill(HIST("QaRun/pRunIndexVx"), holderEvent.runIndex, collision.posX()); hrQaRun.fill(HIST("QaRun/pRunIndexVy"), holderEvent.runIndex, collision.posY()); hrQaRun.fill(HIST("QaRun/pRunIndexVz"), holderEvent.runIndex, holderEvent.vz); - hrQaRun.fill(HIST("QaRun/pRunIndexMultFt0a"), holderEvent.runIndex, collision.multZeqFT0A()); - hrQaRun.fill(HIST("QaRun/pRunIndexMultFt0c"), holderEvent.runIndex, collision.multZeqFT0C()); + hrQaRun.fill(HIST("QaRun/pRunIndexMultiplicityFt0a"), holderEvent.runIndex, collision.multZeqFT0A()); + hrQaRun.fill(HIST("QaRun/pRunIndexMultiplicityFt0c"), holderEvent.runIndex, collision.multZeqFT0C()); + if (0. <= collision.centFT0A() && collision.centFT0A() <= 100.) { + hrQaRun.fill(HIST("QaRun/pRunIndexCentralityFt0a"), holderEvent.runIndex, collision.centFT0A()); + } + if (0. <= collision.centFT0C() && collision.centFT0C() <= 100.) { + hrQaRun.fill(HIST("QaRun/pRunIndexCentralityFt0c"), holderEvent.runIndex, collision.centFT0C()); + } + if (0. <= collision.centFT0M() && collision.centFT0M() <= 100.) { + hrQaRun.fill(HIST("QaRun/pRunIndexCentralityFt0m"), holderEvent.runIndex, collision.centFT0M()); + } } for (const auto& track : tracks) { @@ -2969,9 +2981,9 @@ struct PartNumFluc { if (groupAnalysis.cfgFlagQaPhi.value) { if (holderMcParticle.charge > 0) { - hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_mcP"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhiMc_mcP"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); } else if (holderMcParticle.charge < 0) { - hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_mcM"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhiMc_mcM"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); } } @@ -2979,7 +2991,7 @@ struct PartNumFluc { switch (holderMcParticle.pdgCode) { case PDG_t::kPiPlus: if (groupAnalysis.cfgFlagQaPhiPi.value) { - hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_mcPiP"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhiMc_mcPiP"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); } if (groupAnalysis.cfgFlagCalculationYieldPi.value) { hrCalculationYield.fill(HIST("CalculationYield/hVzCentralityPtEtaMc_mcPiP"), holderEvent.vz, holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta); @@ -2990,7 +3002,7 @@ struct PartNumFluc { break; case PDG_t::kPiMinus: if (groupAnalysis.cfgFlagQaPhiPi.value) { - hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_mcPiM"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhiMc_mcPiM"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); } if (groupAnalysis.cfgFlagCalculationYieldPi.value) { hrCalculationYield.fill(HIST("CalculationYield/hVzCentralityPtEtaMc_mcPiM"), holderEvent.vz, holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta); @@ -3001,7 +3013,7 @@ struct PartNumFluc { break; case PDG_t::kKPlus: if (groupAnalysis.cfgFlagQaPhiKa.value) { - hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_mcKaP"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhiMc_mcKaP"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); } if (groupAnalysis.cfgFlagCalculationYieldKa.value) { hrCalculationYield.fill(HIST("CalculationYield/hVzCentralityPtEtaMc_mcKaP"), holderEvent.vz, holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta); @@ -3015,7 +3027,7 @@ struct PartNumFluc { break; case PDG_t::kKMinus: if (groupAnalysis.cfgFlagQaPhiKa.value) { - hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_mcKaM"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhiMc_mcKaM"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); } if (groupAnalysis.cfgFlagCalculationYieldKa.value) { hrCalculationYield.fill(HIST("CalculationYield/hVzCentralityPtEtaMc_mcKaM"), holderEvent.vz, holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta); @@ -3029,7 +3041,7 @@ struct PartNumFluc { break; case PDG_t::kProton: if (groupAnalysis.cfgFlagQaPhiPr.value) { - hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_mcPrP"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhiMc_mcPrP"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); } if (groupAnalysis.cfgFlagCalculationYieldPr.value) { hrCalculationYield.fill(HIST("CalculationYield/hVzCentralityPtEtaMc_mcPrP"), holderEvent.vz, holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta); @@ -3043,7 +3055,7 @@ struct PartNumFluc { break; case PDG_t::kProtonBar: if (groupAnalysis.cfgFlagQaPhiPr.value) { - hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_mcPrM"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhiMc_mcPrM"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); } if (groupAnalysis.cfgFlagCalculationYieldPr.value) { hrCalculationYield.fill(HIST("CalculationYield/hVzCentralityPtEtaMc_mcPrM"), holderEvent.vz, holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta); From bc13c01720a53cb3d0de9a676b547237ca99a435 Mon Sep 17 00:00:00 2001 From: hernasab Date: Sat, 7 Mar 2026 06:46:37 -0600 Subject: [PATCH 206/347] =?UTF-8?q?[PWGCF]=20removed=20obsolete=20zdc=20se?= =?UTF-8?q?ctor=20information=20and=20added=20new=20ZDC=20correlation?= =?UTF-8?q?=E2=80=A6=20(#15282)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Sabrina Hernandez --- PWGCF/Flow/Tasks/flowZdcTask.cxx | 266 ++++++++++++++----------------- 1 file changed, 119 insertions(+), 147 deletions(-) diff --git a/PWGCF/Flow/Tasks/flowZdcTask.cxx b/PWGCF/Flow/Tasks/flowZdcTask.cxx index 5bfa4c09495..a0a424172dd 100644 --- a/PWGCF/Flow/Tasks/flowZdcTask.cxx +++ b/PWGCF/Flow/Tasks/flowZdcTask.cxx @@ -66,6 +66,7 @@ struct FlowZdcTask { Configurable minNch{"minNch", 0, "Min Nch (|eta|<0.8)"}; Configurable maxNch{"maxNch", 2500, "Max Nch (|eta|<0.8)"}; Configurable nBinsTDC{"nBinsTDC", 150, "nbinsTDC"}; + Configurable nBinsCent{"nBinsCent", 10, "nBinsCent"}; Configurable minTdcZn{"minTdcZn", 4.0, "minimum TDC for ZN"}; Configurable maxTdcZn{"maxTdcZn", 4.0, "maximum TDC for ZN"}; Configurable minTdcZp{"minTdcZp", -4.0, "minimum TDC for ZP"}; @@ -80,6 +81,7 @@ struct FlowZdcTask { Configurable maxEta{"maxEta", +0.8, "maximum eta"}; Configurable minT0CcentCut{"minT0CcentCut", 0.0, "Min T0C Cent. cut"}; Configurable maxT0CcentCut{"maxT0CcentCut", 90.0, "Max T0C Cent. cut"}; + Configurable maxCent{"maxCent", 90.0, "Max T0C cent"}; // event selection Configurable isNoCollInTimeRangeStrict{"isNoCollInTimeRangeStrict", true, "isNoCollInTimeRangeStrict?"}; Configurable isNoCollInTimeRangeStandard{"isNoCollInTimeRangeStandard", false, "isNoCollInTimeRangeStandard?"}; @@ -198,24 +200,28 @@ struct FlowZdcTask { histos.add("ZNVsFT0C", ";T0C (#times 1/100);ZNA+ZNC Amplitude;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0}, {nBinsZDC, -0.5, maxZn}}}); histos.add("ZNVsFT0M", ";T0A+T0C (#times 1/100);ZNA+ZNC Amplitude;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0M}, {nBinsZDC, -0.5, maxZn}}}); histos.add("CommonZNVsFT0M", ";T0A+T0C (#times 1/100);ZNA+ZNC Common Energy;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0M}, {nBinsZDC, -0.5, maxZn}}}); - histos.add("SectorZNVsFT0M", ";T0A+T0C (#times 1/100);ZNA+ZNC Sector Energy;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0M}, {nBinsZDC, -0.5, maxZn}}}); + histos.add("ZNVsCent", ";T0C cent;ZNA + ZNC Amplitude;", kTH2F, {{{nBinsCent, 0., maxCent}, {nBinsZDC, -0.5, maxZn}}}); histos.add("ZPVsFT0A", ";T0A (#times 1/100);ZPA+ZPC Amplitude;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0}, {nBinsZDC, -0.5, maxZp}}}); histos.add("ZPVsFT0C", ";T0C (#times 1/100);ZPA+ZPC Amplitude;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0}, {nBinsZDC, -0.5, maxZp}}}); histos.add("ZPVsFT0M", ";T0A+T0C (#times 1/100);ZPA+ZPC Amplitude;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0M}, {nBinsZDC, -0.5, maxZp}}}); + histos.add("ZPVsCent", ";T0C cent;ZPA + ZPC Amplitude;", kTH2F, {{{nBinsCent, 0., maxCent}, {nBinsZDC, -0.5, maxZp}}}); histos.add("CommonZPVsFT0M", ";T0A+T0C (#times 1/100);ZPA+ZPC Common Energy;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0M}, {nBinsZDC, -0.5, maxZp}}}); - histos.add("SectorZPVsFT0M", ";T0A+T0C (#times 1/100);ZPA+ZPC Sector Energy;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0M}, {nBinsZDC, -0.5, maxZp}}}); histos.add("ZNAVsFT0A", ";T0A (#times 1/100);ZNA Amplitude;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0}, {nBinsZDC, -0.5, maxZn}}}); histos.add("ZNAVsFT0C", ";T0C (#times 1/100);ZNA Amplitude;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0}, {nBinsZDC, -0.5, maxZn}}}); + histos.add("ZNAVsCent", ";T0C cent;ZNA Amplitude;", kTH2F, {{{nBinsCent, 0., maxCent}, {nBinsZDC, -0.5, maxZn}}}); histos.add("ZNAVsFT0M", ";T0A+T0C (#times 1/100);ZNA Amplitude;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0M}, {nBinsZDC, -0.5, maxZn}}}); histos.add("ZNCVsFT0A", ";T0A (#times 1/100);ZNC Amplitude;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0}, {nBinsZDC, -0.5, maxZn}}}); histos.add("ZNCVsFT0C", ";T0C (#times 1/100);ZNC Amplitude;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0}, {nBinsZDC, -0.5, maxZn}}}); histos.add("ZNCVsFT0M", ";T0A+T0C (#times 1/100);ZNC Amplitude;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0M}, {nBinsZDC, -0.5, maxZn}}}); + histos.add("ZNCVsCent", ";T0C cent;ZNC Amplitude;", kTH2F, {{{nBinsCent, 0., maxCent}, {nBinsZDC, -0.5, maxZn}}}); histos.add("ZPAVsFT0A", ";T0A (#times 1/100);ZPA Amplitude;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0}, {nBinsZDC, -0.5, maxZp}}}); histos.add("ZPAVsFT0C", ";T0C (#times 1/100);ZPA Amplitude;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0}, {nBinsZDC, -0.5, maxZp}}}); histos.add("ZPAVsFT0M", ";T0A+T0C (#times 1/100);ZPA Amplitude;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0M}, {nBinsZDC, -0.5, maxZp}}}); + histos.add("ZPAVsCent", ";T0C cent;ZPA Amplitude;", kTH2F, {{{nBinsCent, 0., maxCent}, {nBinsZDC, -0.5, maxZp}}}); histos.add("ZPCVsFT0A", ";T0A (#times 1/100);ZPC Amplitude;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0}, {nBinsZDC, -0.5, maxZp}}}); histos.add("ZPCVsFT0C", ";T0C (#times 1/100);ZPC Amplitude;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0}, {nBinsZDC, -0.5, maxZp}}}); histos.add("ZPCVsFT0M", ";T0A+T0C (#times 1/100);ZPC Amplitude;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0M}, {nBinsZDC, -0.5, maxZp}}}); + histos.add("ZPCVsCent", ";T0C cent;ZPC Amplitude;", kTH2F, {{{nBinsCent, 0., maxCent}, {nBinsZDC, -0.5, maxZp}}}); histos.add("ZN", ";ZNA+ZNC;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZn}}); histos.add("ZNA", ";ZNA Amplitude;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZn}}); histos.add("ZPA", ";ZPA Amplitude;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZp}}); @@ -233,10 +239,6 @@ struct FlowZdcTask { histos.add("CommonZPAVsZPC", ";Common ZPC;Common ZPA;", kTH2F, {{{nBinsZDC, -0.5, maxZp}, {nBinsZDC, -0.5, maxZp}}}); histos.add("CommonZNAVsZPA", ";Common ZPA;Common ZNA;", kTH2F, {{{nBinsZDC, -0.5, maxZp}, {nBinsZDC, -0.5, maxZn}}}); histos.add("CommonZNCVsZPC", ";Common ZPC;Common ZNC;", kTH2F, {{{nBinsZDC, -0.5, maxZp}, {nBinsZDC, -0.5, maxZn}}}); - histos.add("ZNASector", ";ZNA;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZn}}); - histos.add("ZPASector", ";ZPA;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZp}}); - histos.add("ZNCSector", ";ZNC;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZn}}); - histos.add("ZPCSector", ";ZPC;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZp}}); histos.add("ZNCcvsZNCsum", ";ZNC common;ZNC sum towers;", kTH2F, {{{30, -0.5, maxZn}, {30, -0.5, maxZn}}}); histos.add("ZNAcvsZNAsum", ";ZNA common;ZNA sum towers;", kTH2F, {{{30, -0.5, maxZn}, {30, -0.5, maxZn}}}); histos.add("ZPCcvsZPCsum", ";ZPC common;ZPC sum towers;", kTH2F, {{{30, -0.5, maxZp}, {30, -0.5, maxZp}}}); @@ -266,8 +268,10 @@ struct FlowZdcTask { histos.add("NchVsITStracks", ";ITS tracks nCls >= 5;TITS+TPC tracks (|#eta|<0.8);", kTH2F, {{{300, -0.5, 5999.5}, {nBinsNch, minNch, maxNch}}}); histos.add("ZNCVsNch", ";#it{N}_{ch} (|#eta|<0.8);ZNC;", kTH2F, {{{nBinsNch, minNch, maxNch}, {nBinsZDC, minNch, maxZn}}}); histos.add("ZNAVsNch", ";#it{N}_{ch} (|#eta|<0.8);ZNA;", kTH2F, {{{nBinsNch, minNch, maxNch}, {nBinsZDC, minNch, maxZn}}}); + histos.add("ZPAVsNch", ";#it{N}_{ch} (|#eta|<0.8);ZPA;", kTH2F, {{{nBinsNch, minNch, maxNch}, {nBinsZDC, minNch, maxZp}}}); + histos.add("ZPCVsNch", ";#it{N}_{ch} (|#eta|<0.8);ZPA;", kTH2F, {{{nBinsNch, minNch, maxNch}, {nBinsZDC, minNch, maxZp}}}); histos.add("ZNVsNch", ";#it{N}_{ch} (|#eta|<0.8);ZNA+ZNC;", kTH2F, {{{nBinsNch, minNch, maxNch}, {nBinsZDC, minNch, maxZn}}}); - histos.add("ZNDifVsNch", ";#it{N}_{ch} (|#eta|<0.8);ZNA-ZNC;", kTH2F, {{{nBinsNch, minNch, maxNch}, {100, -50., 50.}}}); + histos.add("ZPVsNch", ";#it{N}_{ch} (|#eta|<0.8);ZPA+ZPC;", kTH2F, {{{nBinsNch, minNch, maxNch}, {nBinsZDC, minNch, maxZp}}}); } if (doprocessZdc) { histos.add("ampZna", ";ZNA Amplitude;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZn}}); @@ -278,10 +282,6 @@ struct FlowZdcTask { histos.add("commonZpa", ";ZPA Common;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZp}}); histos.add("commonZnc", ";ZNC Common;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZn}}); histos.add("commonZpc", ";ZPC Common;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZp}}); - histos.add("sectorSumZna", ";ZNA Sector Sum;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZn}}); - histos.add("sectorSumZnc", ";ZNC Sector Sum;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZn}}); - histos.add("sectorSumZpa", ";ZPA Sector Sum;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZp}}); - histos.add("sectorSumZpc", ";ZPC Sector Sum;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZp}}); histos.add("ampZEM1", ";ZEM1 Amplitude;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZem}}); histos.add("ampZEM2", ";ZEM2 Amplitude;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZem}}); histos.add("ZnVsZem", "ZnVsZEM; ZEM; ZNA + ZNC", kTH2F, {{{nBinsZDC, -0.5, maxZem}, {nBinsZDC, -0.5, maxZn}}}); @@ -289,10 +289,6 @@ struct FlowZdcTask { histos.add("ZpaVsZpc", "ZPAvsZPC; ZPC; ZPA;", kTH2F, {{{nBinsZDC, -0.5, maxZp}, {nBinsZDC, -0.5, maxZp}}}); histos.add("ZnaVsZpa", "ZNAvsZPA; ZNA; ZPA;", kTH2F, {{{nBinsZDC, -0.5, maxZn}, {nBinsZDC, -0.5, maxZp}}}); histos.add("ZncVsZpc", "ZNCvsZPC; ZNC; ZPC;", kTH2F, {{{nBinsZDC, -0.5, maxZn}, {nBinsZDC, -0.5, maxZp}}}); - histos.add("ZnccVsZncSum", "ZNCcVsZNCsum; ZNCC ADC; ZNCsum", kTH2F, {{{nBinsADC, -0.5, 3. * maxZn}, {nBinsADC, -0.5, 3. * maxZn}}}); - histos.add("ZnacVsZnaSum", "ZNAcVsZNAsum; ZNAC ADC; ZNAsum", kTH2F, {{{nBinsADC, -0.5, 3. * maxZn}, {nBinsADC, -0.5, 3. * maxZn}}}); - histos.add("ZpacVsZpaSum", "ZPAcVsZPAsum; ZPAC ADC; ZPAsum", kTH2F, {{{nBinsADC, -0.5, 3. * maxZp}, {nBinsADC, -0.5, 3. * maxZp}}}); - histos.add("ZpccVsZpcSum", "ZPCcVsZPCsum; ZPCC ADC; ZPCsum", kTH2F, {{{nBinsADC, -0.5, 3. * maxZp}, {nBinsADC, -0.5, 3. * maxZp}}}); histos.add("ZncVsTdc", "ZNCvsTDC; ZNC Amp; ZNC TDC", kTH2F, {{{480, -13.5, 11.45}, {nBinsZDC, -0.5, maxZn}}}); histos.add("ZnaVsTdc", "ZNAvsTDC; ZNA Amp; ZNA TDC", kTH2F, {{{480, -13.5, 11.45}, {nBinsZDC, -0.5, maxZn}}}); histos.add("ZpcVsTdc", "ZPCvsTDC; ZPC Amp; ZPC TDC", kTH2F, {{{480, -13.5, 11.45}, {nBinsZDC, -0.5, maxZp}}}); @@ -409,6 +405,7 @@ struct FlowZdcTask { } histos.fill(HIST("hEventCounter"), EvCutLabel::Zdc); auto zdc = foundBC.zdc(); + auto cent = collision.centFT0C(); float aT0A = 0., aT0C = 0., aV0A = 0.; if (foundBC.has_ft0()) { @@ -425,11 +422,95 @@ struct FlowZdcTask { aV0A += amplitude; } } + const double normT0M{(aT0A + aT0C) / 100.}; + float et = 0., meanpt = 0.; + int itsTracks = 0, glbTracks = 0; + for (const auto& track : tracks) { + if (track.hasITS() && ((track.eta() > minEta) && (track.eta() < maxEta))) { + itsTracks++; + } + // Track Selection + if (!track.isGlobalTrack()) { + continue; + } + if ((track.pt() < minPt) || (track.pt() > maxPt)) { + continue; + } + if ((track.eta() < minEta) || (track.eta() > maxEta)) { + continue; + } + glbTracks++; + } + bool skipEvent{false}; + if (useMidRapNchSel) { + auto hMeanNch = ccdb->getForTimeStamp(paTHmeanNch.value, foundBC.timestamp()); + auto hSigmaNch = ccdb->getForTimeStamp(paTHsigmaNch.value, foundBC.timestamp()); + if (!hMeanNch) { + LOGF(info, "hMeanNch NOT LOADED!"); + return; + } + if (!hSigmaNch) { + LOGF(info, "hSigmaNch NOT LOADED!"); + return; + } + + const int binT0M{hMeanNch->FindBin(normT0M)}; + const double meanNch{hMeanNch->GetBinContent(binT0M)}; + const double sigmaNch{hSigmaNch->GetBinContent(binT0M)}; + const double nSigmaSelection{nSigmaNchCut * sigmaNch}; + const double diffMeanNch{meanNch - glbTracks}; + + if (!(std::abs(diffMeanNch) < nSigmaSelection)) { + histos.fill(HIST("ExcludedEvtVsNch"), glbTracks); + } else { + skipEvent = true; + } + } else { + skipEvent = true; + } + if (!skipEvent) { + return; + } + + for (const auto& track : tracks) { + // Track Selection + if (!track.isGlobalTrack()) { + continue; + } + if ((track.pt() < minPt) || (track.pt() > maxPtSpectra)) { + continue; + } + if ((track.eta() < minEta) || (track.eta() > maxEta)) { + continue; + } + histos.fill(HIST("ZposVsEta"), collision.posZ(), track.eta()); + histos.fill(HIST("EtaVsPhi"), track.eta(), track.phi()); + histos.fill(HIST("dcaXYvspT"), track.dcaXY(), track.pt()); + et += std::sqrt(std::pow(track.pt(), 2.) + std::pow(o2::constants::physics::MassPionCharged, 2.)); + meanpt += track.pt(); + } + histos.fill(HIST("zPos"), collision.posZ()); + histos.fill(HIST("T0Ccent"), collision.centFT0C()); + histos.fill(HIST("GlbTracks"), glbTracks); + histos.fill(HIST("ampFT0C"), aT0C / 100.); + histos.fill(HIST("ampFT0A"), aT0A / 100.); + histos.fill(HIST("ampFT0M"), (aT0A + aT0C) / 100.); + histos.fill(HIST("ampFV0A"), aV0A / 100.); + // charged particle correlations + histos.fill(HIST("NchVsFV0A"), aV0A / 100., glbTracks); + histos.fill(HIST("NchVsFT0A"), aT0A / 100., glbTracks); + histos.fill(HIST("NchVsFT0C"), aT0C / 100., glbTracks); + histos.fill(HIST("NchVsFT0M"), (aT0A + aT0C) / 100., glbTracks); + histos.fill(HIST("hNchvsNPV"), collision.multNTracksPVeta1(), tracks.size()); + histos.fill(HIST("NchVsEt"), et, glbTracks); + histos.fill(HIST("NchVsITStracks"), itsTracks, glbTracks); + if (glbTracks >= minNchSel) { + histos.fill(HIST("NchVsMeanPt"), glbTracks, meanpt / glbTracks); + } float tZNA{zdc.timeZNA()}; float tZNC{zdc.timeZNC()}; float tZPA{zdc.timeZPA()}; float tZPC{zdc.timeZPC()}; - const double normT0M{(aT0A + aT0C) / 100.}; float znA = zdc.amplitudeZNA(); float znC = zdc.amplitudeZNC(); float zpA = zdc.amplitudeZPA(); @@ -438,19 +519,13 @@ struct FlowZdcTask { float commonSumZna = zdc.energyCommonZNA(); float commonSumZpc = zdc.energyCommonZPC(); float commonSumZpa = zdc.energyCommonZPA(); - float sumZNC = ((zdc.energySectorZNC())[0] + (zdc.energySectorZNC())[1] + (zdc.energySectorZNC())[2] + (zdc.energySectorZNC())[3]); - float sumZNA = ((zdc.energySectorZNA())[0] + (zdc.energySectorZNA())[1] + (zdc.energySectorZNA())[2] + (zdc.energySectorZNA())[3]); - float sumZPC = ((zdc.energySectorZPC())[0] + (zdc.energySectorZPC())[1] + (zdc.energySectorZPC())[2] + (zdc.energySectorZPC())[3]); - float sumZPA = ((zdc.energySectorZPA())[0] + (zdc.energySectorZPA())[1] + (zdc.energySectorZPA())[2] + (zdc.energySectorZPA())[3]); if (applyZdcCorrection) { const float a = zpaCoeff; const float b = zpcCoeff; zpA = zpA - a * znA; commonSumZpa = commonSumZpa - a * commonSumZna; - sumZPA = sumZPA - a * sumZNA; zpC = zpC - b * znC; commonSumZpc = commonSumZpc - b * commonSumZnc; - sumZPC = sumZPC - b * sumZNC; } float aZEM1{zdc.amplitudeZEM1()}; float aZEM2{zdc.amplitudeZEM2()}; @@ -464,34 +539,38 @@ struct FlowZdcTask { if ((tZNA >= minTdcZn) && (tZNA <= maxTdcZn)) { histos.fill(HIST("ZNA"), znA); histos.fill(HIST("ZNACommon"), commonSumZna); - histos.fill(HIST("ZNASector"), sumZNA); histos.fill(HIST("ZNAVsFT0A"), aT0A / 100., znA); histos.fill(HIST("ZNAVsFT0C"), aT0C / 100., znA); histos.fill(HIST("ZNAVsFT0M"), (aT0A + aT0C) / 100., znA); + histos.fill(HIST("ZNAVsCent"), cent, znA); + histos.fill(HIST("ZNAVsNch"), glbTracks, znA); } if ((tZNC >= minTdcZn) && (tZNC <= maxTdcZn)) { histos.fill(HIST("ZNC"), znC); histos.fill(HIST("ZNCCommon"), commonSumZnc); - histos.fill(HIST("ZNCSector"), sumZNC); histos.fill(HIST("ZNCVsFT0A"), aT0A / 100., znC); histos.fill(HIST("ZNCVsFT0C"), aT0C / 100., znC); histos.fill(HIST("ZNCVsFT0M"), (aT0A + aT0C) / 100., znC); + histos.fill(HIST("ZNCVsCent"), cent, znC); + histos.fill(HIST("ZNCVsNch"), glbTracks, znC); } if ((tZPA >= minTdcZp) && (tZPA <= maxTdcZp)) { histos.fill(HIST("ZPA"), zpA); histos.fill(HIST("ZPACommon"), commonSumZpa); - histos.fill(HIST("ZPASector"), sumZPA); histos.fill(HIST("ZPAVsFT0A"), aT0A / 100., zpA); histos.fill(HIST("ZPAVsFT0C"), aT0C / 100., zpA); histos.fill(HIST("ZPAVsFT0M"), (aT0A + aT0C) / 100., zpA); + histos.fill(HIST("ZPAVsCent"), cent, zpA); + histos.fill(HIST("ZPAVsNch"), glbTracks, zpA); } if ((tZPC >= minTdcZp) && (tZPC <= maxTdcZp)) { histos.fill(HIST("ZPC"), zpC); histos.fill(HIST("ZPCCommon"), commonSumZpc); - histos.fill(HIST("ZPCSector"), sumZPC); histos.fill(HIST("ZPCVsFT0A"), aT0A / 100., zpC); histos.fill(HIST("ZPCVsFT0C"), aT0C / 100., zpC); histos.fill(HIST("ZPCVsFT0M"), (aT0A + aT0C) / 100., zpC); + histos.fill(HIST("ZPCVsCent"), cent, zpC); + histos.fill(HIST("ZPCVsNch"), glbTracks, zpC); } if (((tZNA >= minTdcZn) && (tZNA <= maxTdcZn)) && ((tZNC >= minTdcZn) && (tZNC <= maxTdcZn))) histos.fill(HIST("ZNVsZEM"), sumZEMs, sumZNs); @@ -502,7 +581,8 @@ struct FlowZdcTask { histos.fill(HIST("ZNVsFT0C"), aT0C / 100., znA + znC); histos.fill(HIST("ZNVsFT0M"), (aT0A + aT0C) / 100., znA + znC); histos.fill(HIST("CommonZNVsFT0M"), (aT0A + aT0C) / 100., commonSumZna + commonSumZnc); - histos.fill(HIST("SectorZNVsFT0M"), (aT0A + aT0C) / 100., sumZNA + sumZNC); + histos.fill(HIST("ZNVsCent"), cent, znA + znC); + histos.fill(HIST("ZNVsNch"), glbTracks, znA + znC); } if (((tZPA >= minTdcZp) && (tZPA <= maxTdcZp)) && ((tZPC >= minTdcZp) && (tZPC <= maxTdcZp))) { histos.fill(HIST("ZPAVsZPC"), zpC, zpA); @@ -511,7 +591,8 @@ struct FlowZdcTask { histos.fill(HIST("ZPVsFT0C"), aT0C / 100., zpA + zpC); histos.fill(HIST("ZPVsFT0M"), (aT0A + aT0C) / 100., zpA + zpC); histos.fill(HIST("CommonZPVsFT0M"), (aT0A + aT0C) / 100., commonSumZpa + commonSumZpc); - histos.fill(HIST("SectorZPVsFT0M"), (aT0A + aT0C) / 100., sumZPA + sumZPC); + histos.fill(HIST("ZPVsCent"), cent, zpA + zpC); + histos.fill(HIST("ZPVsNch"), glbTracks, zpA + zpC); } if (((tZNA >= minTdcZn) && (tZNA <= maxTdcZn)) && ((tZPA >= minTdcZp) && (tZPA <= maxTdcZp))) { histos.fill(HIST("ZNAVsZPA"), zpA, znA); @@ -536,26 +617,20 @@ struct FlowZdcTask { histos.fill(HIST("CommonZNAVsZPA"), commonSumZpa, commonSumZna); histos.fill(HIST("CommonZNCVsZPC"), commonSumZpc, commonSumZnc); histos.fill(HIST("ZNACommon"), commonSumZna); - histos.fill(HIST("ZNASector"), sumZNA); histos.fill(HIST("ZNCCommon"), commonSumZnc); - histos.fill(HIST("ZNCSector"), sumZNC); histos.fill(HIST("ZPACommon"), commonSumZpa); - histos.fill(HIST("ZPASector"), sumZPA); histos.fill(HIST("ZPCCommon"), commonSumZpc); - histos.fill(HIST("ZPCSector"), sumZPC); histos.fill(HIST("ZN"), znA + znC); histos.fill(HIST("ZPVsFT0A"), aT0A / 100., zpA + zpC); histos.fill(HIST("ZPVsFT0C"), aT0C / 100., zpA + zpC); histos.fill(HIST("ZPVsFT0M"), (aT0A + aT0C) / 100., zpA + zpC); histos.fill(HIST("CommonZPVsFT0M"), (aT0A + aT0C) / 100., commonSumZpa + commonSumZpc); - histos.fill(HIST("SectorZPVsFT0M"), (aT0A + aT0C) / 100., sumZPA + sumZPC); histos.fill(HIST("ZPAVsFT0A"), aT0A / 100., zpA); histos.fill(HIST("ZPAVsFT0C"), aT0C / 100., zpA); histos.fill(HIST("ZPAVsFT0M"), (aT0A + aT0C) / 100., zpA); histos.fill(HIST("ZNVsFT0C"), aT0C / 100., znA + znC); histos.fill(HIST("ZNVsFT0M"), (aT0A + aT0C) / 100., znA + znC); histos.fill(HIST("CommonZNVsFT0M"), (aT0A + aT0C) / 100., commonSumZna + commonSumZnc); - histos.fill(HIST("SectorZNVsFT0M"), (aT0A + aT0C) / 100., sumZNA + sumZNC); histos.fill(HIST("ZPCVsFT0A"), aT0A / 100., zpC); histos.fill(HIST("ZPCVsFT0C"), aT0C / 100., zpC); histos.fill(HIST("ZPCVsFT0M"), (aT0A + aT0C) / 100., zpC); @@ -565,6 +640,16 @@ struct FlowZdcTask { histos.fill(HIST("ZNAVsFT0A"), aT0A / 100., znA); histos.fill(HIST("ZNAVsFT0C"), aT0C / 100., znA); histos.fill(HIST("ZNAVsFT0M"), (aT0A + aT0C) / 100., znA); + histos.fill(HIST("ZNAVsCent"), cent, znA); + histos.fill(HIST("ZNCVsCent"), cent, znC); + histos.fill(HIST("ZPVsCent"), cent, zpA + zpC); + histos.fill(HIST("ZPAVsCent"), cent, zpA); + histos.fill(HIST("ZPCVsCent"), cent, zpC); + histos.fill(HIST("ZPAVsNch"), glbTracks, zpA); + histos.fill(HIST("ZPCVsNch"), glbTracks, zpC); + histos.fill(HIST("ZNVsNch"), glbTracks, znA + znC); + histos.fill(HIST("ZNCVsNch"), glbTracks, znC); + histos.fill(HIST("ZNAVsNch"), glbTracks, znA); } histos.fill(HIST("ZEM1"), aZEM1); histos.fill(HIST("ZEM2"), aZEM2); @@ -576,103 +661,6 @@ struct FlowZdcTask { histos.fill(HIST("ZEM2Vstdc"), tZEM2, aZEM2); histos.fill(HIST("debunch"), tZNA - tZNC, tZNA + tZNC); } - float et = 0., meanpt = 0.; - int itsTracks = 0, glbTracks = 0; - for (const auto& track : tracks) { - if (track.hasITS() && ((track.eta() > minEta) && (track.eta() < maxEta))) { - itsTracks++; - } - // Track Selection - if (!track.isGlobalTrack()) { - continue; - } - if ((track.pt() < minPt) || (track.pt() > maxPt)) { - continue; - } - if ((track.eta() < minEta) || (track.eta() > maxEta)) { - continue; - } - glbTracks++; - } - bool skipEvent{false}; - if (useMidRapNchSel) { - auto hMeanNch = ccdb->getForTimeStamp(paTHmeanNch.value, foundBC.timestamp()); - auto hSigmaNch = ccdb->getForTimeStamp(paTHsigmaNch.value, foundBC.timestamp()); - if (!hMeanNch) { - LOGF(info, "hMeanNch NOT LOADED!"); - return; - } - if (!hSigmaNch) { - LOGF(info, "hSigmaNch NOT LOADED!"); - return; - } - - const int binT0M{hMeanNch->FindBin(normT0M)}; - const double meanNch{hMeanNch->GetBinContent(binT0M)}; - const double sigmaNch{hSigmaNch->GetBinContent(binT0M)}; - const double nSigmaSelection{nSigmaNchCut * sigmaNch}; - const double diffMeanNch{meanNch - glbTracks}; - - if (!(std::abs(diffMeanNch) < nSigmaSelection)) { - histos.fill(HIST("ExcludedEvtVsNch"), glbTracks); - } else { - skipEvent = true; - } - } else { - skipEvent = true; - } - if (!skipEvent) { - return; - } - - for (const auto& track : tracks) { - // Track Selection - if (!track.isGlobalTrack()) { - continue; - } - if ((track.pt() < minPt) || (track.pt() > maxPtSpectra)) { - continue; - } - if ((track.eta() < minEta) || (track.eta() > maxEta)) { - continue; - } - histos.fill(HIST("ZposVsEta"), collision.posZ(), track.eta()); - histos.fill(HIST("EtaVsPhi"), track.eta(), track.phi()); - histos.fill(HIST("dcaXYvspT"), track.dcaXY(), track.pt()); - et += std::sqrt(std::pow(track.pt(), 2.) + std::pow(o2::constants::physics::MassPionCharged, 2.)); - meanpt += track.pt(); - } - histos.fill(HIST("zPos"), collision.posZ()); - histos.fill(HIST("T0Ccent"), collision.centFT0C()); - histos.fill(HIST("GlbTracks"), glbTracks); - - if (sumZEMs > zemCut) { - // ZDC Correlations - histos.fill(HIST("ZNAVsNch"), glbTracks, znA); - histos.fill(HIST("ZNCVsNch"), glbTracks, znC); - histos.fill(HIST("ZNVsNch"), glbTracks, sumZNs); - histos.fill(HIST("ZNDifVsNch"), glbTracks, znA - znC); - histos.fill(HIST("ZNCcvsZNCsum"), sumZNC, zdc.energyCommonZNC()); - histos.fill(HIST("ZNAcvsZNAsum"), sumZNA, zdc.energyCommonZNA()); - histos.fill(HIST("ZPCcvsZPCsum"), sumZPC, zdc.energyCommonZPC()); - histos.fill(HIST("ZPAcvsZPAsum"), sumZPA, zdc.energyCommonZPA()); - } - - histos.fill(HIST("ampFT0C"), aT0C / 100.); - histos.fill(HIST("ampFT0A"), aT0A / 100.); - histos.fill(HIST("ampFT0M"), (aT0A + aT0C) / 100.); - histos.fill(HIST("ampFV0A"), aV0A / 100.); - // charged particle correlations - histos.fill(HIST("NchVsFV0A"), aV0A / 100., glbTracks); - histos.fill(HIST("NchVsFT0A"), aT0A / 100., glbTracks); - histos.fill(HIST("NchVsFT0C"), aT0C / 100., glbTracks); - histos.fill(HIST("NchVsFT0M"), (aT0A + aT0C) / 100., glbTracks); - histos.fill(HIST("hNchvsNPV"), collision.multNTracksPVeta1(), tracks.size()); - histos.fill(HIST("NchVsEt"), et, glbTracks); - histos.fill(HIST("NchVsITStracks"), itsTracks, glbTracks); - if (glbTracks >= minNchSel) { - histos.fill(HIST("NchVsMeanPt"), glbTracks, meanpt / glbTracks); - } } void processZdc( @@ -688,10 +676,6 @@ struct FlowZdcTask { auto znC = zdc.amplitudeZNC(); auto zpA = zdc.amplitudeZPA(); auto zpC = zdc.amplitudeZPC(); - float sectorSumZNC = ((zdc.energySectorZNC())[0] + (zdc.energySectorZNC())[1] + (zdc.energySectorZNC())[2] + (zdc.energySectorZNC())[3]); - float sectorSumZNA = ((zdc.energySectorZNA())[0] + (zdc.energySectorZNA())[1] + (zdc.energySectorZNA())[2] + (zdc.energySectorZNA())[3]); - float sectorSumZPC = ((zdc.energySectorZPC())[0] + (zdc.energySectorZPC())[1] + (zdc.energySectorZPC())[2] + (zdc.energySectorZPC())[3]); - float sectorSumZPA = ((zdc.energySectorZPA())[0] + (zdc.energySectorZPA())[1] + (zdc.energySectorZPA())[2] + (zdc.energySectorZPA())[3]); float commonSumZnc = zdc.energyCommonZNC(); float commonSumZna = zdc.energyCommonZNA(); float commonSumZpc = zdc.energyCommonZPC(); @@ -707,22 +691,18 @@ struct FlowZdcTask { if ((tZNA >= minTdcZn) && (tZNA <= maxTdcZn)) { histos.fill(HIST("ampZna"), znA); histos.fill(HIST("commonZna"), commonSumZna); - histos.fill(HIST("sectorSumZna"), sectorSumZNA); } if ((tZNC >= minTdcZn) && (tZNC <= maxTdcZn)) { histos.fill(HIST("ampZnc"), znC); histos.fill(HIST("commonZnc"), commonSumZnc); - histos.fill(HIST("sectorSumZnc"), sectorSumZNC); } if ((tZPA >= minTdcZp) && (tZPA <= maxTdcZp)) { histos.fill(HIST("ampZpa"), zpA); histos.fill(HIST("commonZpa"), commonSumZpa); - histos.fill(HIST("sectorSumZpa"), sectorSumZPA); } if ((tZPC >= minTdcZp) && (tZPC <= maxTdcZp)) { histos.fill(HIST("ampZpc"), zpC); histos.fill(HIST("commonZpc"), commonSumZpc); - histos.fill(HIST("sectorSumZpc"), sectorSumZPC); } if (((tZNC >= minTdcZn) && (tZNC <= maxTdcZn)) && ((tZNA >= minTdcZn) && (tZNA <= maxTdcZn))) histos.fill(HIST("ZnVsZem"), sumZEMs, znC + znA); @@ -743,10 +723,6 @@ struct FlowZdcTask { histos.fill(HIST("commonZnc"), commonSumZnc); histos.fill(HIST("commonZpa"), commonSumZpa); histos.fill(HIST("commonZpc"), commonSumZpc); - histos.fill(HIST("sectorSumZna"), sectorSumZNA); - histos.fill(HIST("sectorSumZnc"), sectorSumZNC); - histos.fill(HIST("sectorSumZpa"), sectorSumZPA); - histos.fill(HIST("sectorSumZpc"), sectorSumZPC); histos.fill(HIST("ZnVsZem"), sumZEMs, znC + znA); histos.fill(HIST("ZnaVsZnc"), znA, znC); histos.fill(HIST("ZpaVsZpc"), zpA, zpC); @@ -755,10 +731,6 @@ struct FlowZdcTask { } histos.fill(HIST("ampZEM1"), aZEM1); histos.fill(HIST("ampZEM2"), aZEM2); - histos.fill(HIST("ZnccVsZncSum"), sectorSumZNC, commonSumZnc); - histos.fill(HIST("ZnacVsZnaSum"), sectorSumZNA, commonSumZna); - histos.fill(HIST("ZpccVsZpcSum"), sectorSumZPC, commonSumZpc); - histos.fill(HIST("ZpacVsZpaSum"), sectorSumZPA, commonSumZpa); histos.fill(HIST("ZncVsTdc"), zdc.timeZNC(), znC); histos.fill(HIST("ZnaVsTdc"), zdc.timeZNA(), znA); histos.fill(HIST("ZpcVsTdc"), zdc.timeZPC(), zpC); From 774ad9d03a7cef627d2dc4bf2875d8bf8a8ce1a0 Mon Sep 17 00:00:00 2001 From: lcernusa Date: Sat, 7 Mar 2026 13:48:11 +0100 Subject: [PATCH 207/347] [PWGCF] Flow-decorrelations bug fix (#15276) --- PWGCF/TwoParticleCorrelations/Tasks/flowDecorrelation.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/flowDecorrelation.cxx b/PWGCF/TwoParticleCorrelations/Tasks/flowDecorrelation.cxx index c8bde3aea57..61eb715a0a1 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/flowDecorrelation.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/flowDecorrelation.cxx @@ -145,7 +145,7 @@ struct FlowDecorrelation { ConfigurableAxis axisDeltaEtaTpcFt0a{"axisDeltaEtaTpcFt0a", {32, -5.8, -2.6}, "delta eta axis, -5.8~-2.6 for TPC-FT0A,"}; ConfigurableAxis axisDeltaEtaTpcFt0c{"axisDeltaEtaTpcFt0c", {32, 1.2, 4.2}, "delta eta axis, 1.2~4.2 for TPC-FT0C"}; ConfigurableAxis axisDeltaEtaTpcMft{"axisDeltaEtaTpcMft", {32, 1.3, 4.8}, "delta eta axis, 1.3~4.8 for TPC-MFT"}; - ConfigurableAxis axisDeltaEtaTpcFv0{"axisDeltaEtaTpcFv0", {32, -1.2, -6.1}, "delta eta axis for TPC-FV0 histograms"}; + ConfigurableAxis axisDeltaEtaTpcFv0{"axisDeltaEtaTpcFv0", {32, -6.1, -1.2}, "delta eta axis for TPC-FV0 histograms"}; ConfigurableAxis axisEtaTrigger{"axisEtaTrigger", {VARIABLE_WIDTH, -3.3, -2.1, -0.8, -0.6, -0.4, -0.2, 0, 0.2, 0.4, 0.6, 0.8, 3.5, 4.9}, "eta trigger axis for histograms"}; ConfigurableAxis axisEtaAssoc{"axisEtaAssoc", {VARIABLE_WIDTH, -3.3, -2.1, -0.8, -0.6, -0.4, -0.2, 0, 0.2, 0.4, 0.6, 0.8, 3.5, 4.9}, "eta associated axis for histograms"}; ConfigurableAxis axisVtxMix{"axisVtxMix", {VARIABLE_WIDTH, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "vertex axis for mixed event histograms"}; @@ -250,7 +250,7 @@ struct FlowDecorrelation { LOGF(info, "Starting init"); // Event Counter - if ((doprocessSameTpcFt0a || doprocessSameTpcFt0c || doprocessSameTpcMft) && cfgUseAdditionalEventCut) { + if ((doprocessSameTpcFt0a || doprocessSameTpcFt0c || doprocessSameTpcMft || doprocessSameTpcFv0) && cfgUseAdditionalEventCut) { registry.add("hEventCountSpecific", "Number of Event;; Count", {HistType::kTH1D, {{12, 0, 12}}}); registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(1, "after sel8"); registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(2, "kNoSameBunchPileup"); From bfb3ada93f9749e399d06e900e9d4dcdd912fa83 Mon Sep 17 00:00:00 2001 From: spolitan <59452587+stefanopolitano@users.noreply.github.com> Date: Sat, 7 Mar 2026 14:45:04 +0100 Subject: [PATCH 208/347] [PWGHF] Add alternative FT0c centrality estimator in HF centrality (#15261) Co-authored-by: ALICE Action Bot --- PWGHF/Core/CentralityEstimation.h | 27 ++++++++++++++++++++++++ PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx | 18 +++++++++++++--- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/PWGHF/Core/CentralityEstimation.h b/PWGHF/Core/CentralityEstimation.h index 71cdc0ebffd..33ee20266f4 100644 --- a/PWGHF/Core/CentralityEstimation.h +++ b/PWGHF/Core/CentralityEstimation.h @@ -30,6 +30,7 @@ enum CentralityEstimator { FT0M, FV0A, NTracksPV, + FT0CVariant2, NCentralityEstimators }; @@ -43,6 +44,11 @@ concept HasFT0CCent = requires(T collision) { collision.centFT0C(); }; +template +concept HasFT0CVariant2Cent = requires(T collision) { + collision.centFT0CVariant2(); +}; + template concept HasFT0MCent = requires(T collision) { collision.centFT0M(); @@ -76,6 +82,15 @@ float getCentralityColl(const TCollision& collision) return collision.centFT0C(); } +/// Evaluate centrality/multiplicity percentile using FT0C variant 1 estimator +/// \param candidate is candidate +/// \return centrality/multiplicity percentile of the collision +template +float getCentralityColl(const TCollision& collision) +{ + return collision.centFT0CVariant2(); +} + /// Evaluate centrality/multiplicity percentile using FT0M estimator /// \param candidate is candidate /// \return centrality/multiplicity percentile of the collision @@ -144,6 +159,18 @@ float getCentralityColl(const TCollision& collision, const int centEstimator) } LOG(fatal) << "Collision does not have centFV0A()."; break; + case CentralityEstimator::NTracksPV: + if constexpr (HasNTracksPvCent) { + return collision.centNTPV(); + } + LOG(fatal) << "Collision does not have centNTPV()."; + break; + case CentralityEstimator::FT0CVariant2: + if constexpr (HasFT0CVariant2Cent) { + return collision.centFT0CVariant2(); + } + LOG(fatal) << "Collision does not have centFT0CVariant2()."; + break; default: LOG(fatal) << "Centrality estimator not valid. See CentralityEstimator for valid values."; break; diff --git a/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx b/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx index 46d7da749fc..78462e10a73 100644 --- a/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx +++ b/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx @@ -109,7 +109,7 @@ struct HfTaskFlowCharmHadrons { Configurable harmonic{"harmonic", 2, "harmonic number"}; Configurable qVecDetector{"qVecDetector", 3, "Detector for Q vector estimation (FV0A: 0, FT0M: 1, FT0A: 2, FT0C: 3, TPC Pos: 4, TPC Neg: 5, TPC Tot: 6)"}; - Configurable centEstimator{"centEstimator", 2, "Centrality estimation (FT0A: 1, FT0C: 2, FT0M: 3, FV0A: 4)"}; + Configurable centEstimator{"centEstimator", 2, "Centrality estimation (FT0A: 1, FT0C: 2, FT0M: 3, FV0A: 4, NTracksPV: 5, FT0CVariant2: 6)"}; Configurable selectionFlag{"selectionFlag", 1, "Selection Flag for hadron (e.g. 1 for skimming, 3 for topo. and kine., 7 for PID)"}; Configurable centralityMin{"centralityMin", 0., "Minimum centrality accepted in SP/EP computation (not applied in resolution process)"}; Configurable centralityMax{"centralityMax", 100., "Maximum centrality accepted in SP/EP computation (not applied in resolution process)"}; @@ -124,6 +124,8 @@ struct HfTaskFlowCharmHadrons { Configurable storeEpCosSin{"storeEpCosSin", false, "Flag to store cos and sin of EP angle in ThnSparse"}; Configurable storeCandEta{"storeCandEta", false, "Flag to store candidates eta"}; Configurable storeCandSign{"storeCandSign", false, "Flag to store candidates sign"}; + Configurable storeCentSparse{"storeCentSparse", false, "Flag to store up to 4 centrality estimators comparison sparse (only applied in resolution process)"}; + Configurable> centEstimatorsForSparse{"centEstimatorsForSparse", {1, 2, 3, 4}, "Centrality estimators to be stored in the centrality sparse (FT0A: 1, FT0C: 2, FT0M: 3, FV0A: 4). Up to 4 estimators can be configured."}; Configurable occEstimator{"occEstimator", 0, "Occupancy estimation (0: None, 1: ITS, 2: FT0C)"}; Configurable saveEpResoHisto{"saveEpResoHisto", false, "Flag to save event plane resolution histogram"}; Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; @@ -146,7 +148,7 @@ struct HfTaskFlowCharmHadrons { using CandXic0DataWMl = soa::Filtered>; using CandD0DataWMl = soa::Filtered>; using CandD0Data = soa::Filtered>; - using CollsWithQvecs = soa::Join; + using CollsWithQvecs = soa::Join; using TracksWithExtra = soa::Join; Filter filterSelectDsCandidates = aod::hf_sel_candidate_ds::isSelDsToKKPi >= selectionFlag || aod::hf_sel_candidate_ds::isSelDsToPiKK >= selectionFlag; @@ -254,6 +256,11 @@ struct HfTaskFlowCharmHadrons { registry.add("hCentEventWithCand", "Centrality distributions with charm candidates;Cent;entries", HistType::kTH1F, {{100, 0.f, 100.f}}); registry.add("hCentEventWithCandInSigRegion", "Centrality distributions with charm candidates in signal range;Cent;entries", HistType::kTH1F, {{100, 0.f, 100.f}}); + if (storeCentSparse) { + std::vector axesCent = {thnAxisCent, thnAxisCent, thnAxisCent, thnAxisCent}; + registry.add("hSparseCentEstimators", "THn with different centrality estimators; Centrality 0; Centrality 1; Centrality 2; Centrality 3", {HistType::kTHnSparseF, axesCent}); + } + if (occEstimator != 0) { registry.add("trackOccVsFT0COcc", "trackOccVsFT0COcc; trackOcc; FT0COcc", {HistType::kTH2F, {thnAxisOccupancyITS, thnAxisOccupancyFT0C}}); } @@ -878,7 +885,7 @@ struct HfTaskFlowCharmHadrons { float const xQVecBTot = collision.qvecBTotRe(); float const yQVecBTot = collision.qvecBTotIm(); - centrality = o2::hf_centrality::getCentralityColl(collision, o2::hf_centrality::CentralityEstimator::FT0C); + centrality = o2::hf_centrality::getCentralityColl(collision, centEstimator); if (storeResoOccu) { const auto occupancy = o2::hf_occupancy::getOccupancyColl(collision, occEstimator); registry.fill(HIST("trackOccVsFT0COcc"), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange()); @@ -890,6 +897,11 @@ struct HfTaskFlowCharmHadrons { occupancy, evtSelFlags[0], evtSelFlags[1], evtSelFlags[2], evtSelFlags[3], evtSelFlags[4]); } + if (storeCentSparse) { + registry.fill(HIST("hSparseCentEstimators"), o2::hf_centrality::getCentralityColl(collision, centEstimatorsForSparse->at(0)), o2::hf_centrality::getCentralityColl(collision, centEstimatorsForSparse->at(1)), + o2::hf_centrality::getCentralityColl(collision, centEstimatorsForSparse->at(2)), o2::hf_centrality::getCentralityColl(collision, centEstimatorsForSparse->at(3))); + } + if (!isCollSelected(collision, bcs, centrality)) { // no selection on the centrality is applied, but on event selection flags return; From e6ac6d4ad0f1e1065b7cd5986b18f33a76a89580 Mon Sep 17 00:00:00 2001 From: skundu692 <86804743+skundu692@users.noreply.github.com> Date: Sat, 7 Mar 2026 14:55:21 +0100 Subject: [PATCH 209/347] [PWGLF] Fix event mixing sliding for spin correlation (#15300) --- .../Strangeness/lambdaspincorrderived.cxx | 35 ++++++++----------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx b/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx index 07fbd5434f4..a6845963d35 100644 --- a/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx +++ b/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx @@ -207,6 +207,7 @@ struct lambdaspincorrderived { Configurable cfgV5NeighborPt{"cfgV5NeighborPt", 0, "v5: neighbor bins in pT (use symmetric ±N, edge-safe)"}; Configurable cfgV5NeighborEta{"cfgV5NeighborEta", 0, "v5: neighbor bins in eta (use symmetric ±N, edge-safe)"}; Configurable cfgV5NeighborPhi{"cfgV5NeighborPhi", 0, "v5: neighbor bins in phi (use symmetric ±N, periodic wrap)"}; + Configurable cfgV5MaxMatches{"cfgV5MaxMatches", 50, "v5: max ME replacements per SE pair (after all cuts)"}; Configurable cfgMixSeed{"cfgMixSeed", 0xdecafbadULL, "RNG seed for downsampling matches (deterministic)"}; Configurable centMin{"centMin", 0, "Minimum Centrality"}; @@ -1866,9 +1867,10 @@ struct lambdaspincorrderived { } } - // Neighbor policy (continuous mixing) - constexpr int nN_pt = 1; // ±1 pt-bin - constexpr int nN_eta = 1; // ±1 eta/y-bin (can make configurable later) + // Neighbor policy from configurables + const int nN_pt = std::max(0, cfgV5NeighborPt.value); + const int nN_eta = std::max(0, cfgV5NeighborEta.value); + const int nN_phi = std::max(0, cfgV5NeighborPhi.value); std::vector ptBins, etaBins, phiBins; std::vector matches; @@ -1926,7 +1928,7 @@ struct lambdaspincorrderived { collectNeighborBinsClamp(ptB, nPt, nN_pt, ptBins); collectNeighborBinsClamp(etaB, nEta, nN_eta, etaBins); - collectPhiBinsWithEdgeWrap(phiB, nPhi, phiBins); + collectNeighborBinsPhi(phiB, nPhi, nN_phi, phiBins); matches.clear(); @@ -1947,12 +1949,10 @@ struct lambdaspincorrderived { continue; } - // extra strict kinematic check (uses eta or rapidity based on userapidity) if (!checkKinematics(t1, tX)) { continue; } - // safety (should be redundant because different event) if (tX.globalIndex() == t1.globalIndex()) continue; if (tX.globalIndex() == t2.globalIndex()) @@ -1968,7 +1968,6 @@ struct lambdaspincorrderived { continue; } - // dedupe std::sort(matches.begin(), matches.end(), [](auto const& a, auto const& b) { return std::tie(a.collisionIdx, a.rowIndex) < std::tie(b.collisionIdx, b.rowIndex); @@ -1982,9 +1981,8 @@ struct lambdaspincorrderived { continue; } - // unbiased cap (cfgV5MaxMatches==1 => pick-one mode) if (cfgV5MaxMatches.value > 0 && (int)matches.size() > cfgV5MaxMatches.value) { - uint64_t seed = 0; + uint64_t seed = cfgMixSeed.value; seed ^= splitmix64((uint64_t)t1.globalIndex()); seed ^= splitmix64((uint64_t)t2.globalIndex() + 0x1234567ULL); seed ^= splitmix64((uint64_t)curColIdx + 0x9abcULL); @@ -2027,8 +2025,6 @@ struct lambdaspincorrderived { void processMCMEV5(EventCandidatesMC const& collisions, AllTrackCandidatesMC const& V0sMC) { - // Buffer binning: v0etaMixBuffer = max(|eta|) or max(|y|) if userapidity - // etaMix = step for that axis (and also your matching window inside checkKinematicsMC) MixBinner mb{ ptMin.value, ptMax.value, ptMix.value, v0etaMixBuffer.value, etaMix.value, @@ -2037,7 +2033,7 @@ struct lambdaspincorrderived { const int nCol = colBinning.getAllBinsCount(); const int nStat = N_STATUS; const int nPt = mb.nPt(); - const int nEta = mb.nEta(); // logical "nY" if userapidity=true + const int nEta = mb.nEta(); const int nPhi = mb.nPhi(); const size_t nKeys = static_cast(nCol) * nStat * nPt * nEta * nPhi; @@ -2096,8 +2092,9 @@ struct lambdaspincorrderived { } } - constexpr int nN_pt = 1; - constexpr int nN_eta = 1; + const int nN_pt = std::max(0, cfgV5NeighborPt.value); + const int nN_eta = std::max(0, cfgV5NeighborEta.value); + const int nN_phi = std::max(0, cfgV5NeighborPhi.value); std::vector ptBins, etaBins, phiBins; std::vector matches; @@ -2123,7 +2120,6 @@ struct lambdaspincorrderived { continue; } - // no shared daughters if (mcacc::prIdx(t1) == mcacc::prIdx(t2)) continue; if (mcacc::piIdx(t1) == mcacc::piIdx(t2)) @@ -2154,7 +2150,7 @@ struct lambdaspincorrderived { collectNeighborBinsClamp(ptB, nPt, nN_pt, ptBins); collectNeighborBinsClamp(etaB, nEta, nN_eta, etaBins); - collectPhiBinsWithEdgeWrap(phiB, nPhi, phiBins); + collectNeighborBinsPhi(phiB, nPhi, nN_phi, phiBins); matches.clear(); @@ -2165,7 +2161,7 @@ struct lambdaspincorrderived { for (auto const& bc : vec) { if (bc.collisionIdx == curColIdx) { - continue; // different event + continue; } auto tX = V0sMC.iteratorAt(static_cast(bc.rowIndex)); @@ -2176,7 +2172,6 @@ struct lambdaspincorrderived { continue; } - // safety (should be redundant due to different event) if (tX.globalIndex() == t1.globalIndex()) continue; if (tX.globalIndex() == t2.globalIndex()) @@ -2192,7 +2187,6 @@ struct lambdaspincorrderived { continue; } - // dedupe std::sort(matches.begin(), matches.end(), [](auto const& a, auto const& b) { return std::tie(a.collisionIdx, a.rowIndex) < std::tie(b.collisionIdx, b.rowIndex); @@ -2206,9 +2200,8 @@ struct lambdaspincorrderived { continue; } - // unbiased cap (cfgV5MaxMatches==1 => pick-one mode) if (cfgV5MaxMatches.value > 0 && (int)matches.size() > cfgV5MaxMatches.value) { - uint64_t seed = 0; + uint64_t seed = cfgMixSeed.value; seed ^= splitmix64((uint64_t)t1.globalIndex()); seed ^= splitmix64((uint64_t)t2.globalIndex() + 0x1234567ULL); seed ^= splitmix64((uint64_t)curColIdx + 0x9abcULL); From 5289103b7999270452455d90ada4ab7fe0f9b20e Mon Sep 17 00:00:00 2001 From: omvazque Date: Sat, 7 Mar 2026 08:05:33 -0600 Subject: [PATCH 210/347] [PWGLF] Adds histograms: type FT0 vs TVX (#15299) --- PWGLF/Tasks/Nuspex/piKpRAA.cxx | 153 +++++++++++++++++++++++++-------- 1 file changed, 117 insertions(+), 36 deletions(-) diff --git a/PWGLF/Tasks/Nuspex/piKpRAA.cxx b/PWGLF/Tasks/Nuspex/piKpRAA.cxx index c28ce0955db..52475e98a9e 100644 --- a/PWGLF/Tasks/Nuspex/piKpRAA.cxx +++ b/PWGLF/Tasks/Nuspex/piKpRAA.cxx @@ -275,6 +275,7 @@ struct PiKpRAA { enum EvCutLabel { All = 1, + HasFT0, SelEigth, SelTriggerTVX, SelNoITSROFrameBorder, @@ -289,7 +290,6 @@ struct PiKpRAA { NoHighMultCollInPrevRof, NoCollInTimeRangeNarrow, OccuCut, - HasFT0, Centrality, NchSel, INELgt0 @@ -398,9 +398,11 @@ struct PiKpRAA { const char* latexEta[kNEtaHists] = {"-0.8<#eta<-0.6", "-0.6<#eta<-0.4", "-0.4<#eta<-0.2", "-0.2<#eta<0", "0<#eta<0.2", "0.2<#eta<0.4", "0.4<#eta<0.6", "0.6<#eta<0.8"}; registry.add("EventCounter", ";;Events", kTH1F, {axisEvent}); + registry.add("HasFT0AndTVX", "AllEvents=1 | HasFT0=2 | HasFT0&TVX=3;;", kTH1F, {{3, 0.5, 3.5}}); registry.add("zPos", "With Event Selection;;Entries;", kTH1F, {axisZpos}); registry.add("T0Ccent", ";;Entries", kTH1F, {axisCent}); registry.add("T0CcentVsFoundFT0", "Found(=1.5) NOT Found(=0.5);;Status;", kTH2F, {{{axisCent}, {2, 0, 2}}}); + registry.add("T0CcentVsFoundFT0AndTVX", "Found(=1.5) NOT Found(=0.5);;Status;", kTH2F, {{{axisCent}, {2, 0, 2}}}); registry.add("NchVsCent", "Measured Nch v.s. Centrality (At least Once Rec. Coll. + Sel. criteria);;Nch", kTH2F, {{axisCent, {nBinsNch, minNch, maxNch}}}); registry.add("NclVsEtaPID", ";#eta;Ncl used for PID", kTH2F, {{{axisEta}, {161, -0.5, 160.5}}}); registry.add("NclVsEtaPIDp", ";#eta;#LTNcl#GT used for PID", kTProfile, {axisEta}); @@ -410,21 +412,21 @@ struct PiKpRAA { auto hstat = registry.get(HIST("EventCounter")); auto* x = hstat->GetXaxis(); x->SetBinLabel(1, "All"); - x->SetBinLabel(2, "SelEigth"); - x->SetBinLabel(3, "SelTriggerTVX"); - x->SetBinLabel(4, "SelNoITSROFrameBorder"); - x->SetBinLabel(5, "SelNoTimeFrameBorder"); - x->SetBinLabel(6, "VtxZ Sel."); - x->SetBinLabel(7, "GoodZvtxFT0vsPV"); - x->SetBinLabel(8, "NoSameBunchPileup"); - x->SetBinLabel(9, "NoCollInTimeRangeStrict"); - x->SetBinLabel(10, "NoCollInTimeRangeStandard"); - x->SetBinLabel(11, "NoCollInRofStrict"); - x->SetBinLabel(12, "NoCollInRofStandard"); - x->SetBinLabel(13, "NoHighMultCollInPrevRof"); - x->SetBinLabel(14, "NoCollInTimeRangeNarrow"); - x->SetBinLabel(15, "Occupancy Cut"); - x->SetBinLabel(16, "Has FT0?"); + x->SetBinLabel(2, "Has FT0?"); + x->SetBinLabel(3, "SelEigth"); + x->SetBinLabel(4, "SelTriggerTVX"); + x->SetBinLabel(5, "SelNoITSROFrameBorder"); + x->SetBinLabel(6, "SelNoTimeFrameBorder"); + x->SetBinLabel(7, "VtxZ Sel."); + x->SetBinLabel(8, "GoodZvtxFT0vsPV"); + x->SetBinLabel(9, "NoSameBunchPileup"); + x->SetBinLabel(10, "NoCollInTimeRangeStrict"); + x->SetBinLabel(11, "NoCollInTimeRangeStandard"); + x->SetBinLabel(12, "NoCollInRofStrict"); + x->SetBinLabel(13, "NoCollInRofStandard"); + x->SetBinLabel(14, "NoHighMultCollInPrevRof"); + x->SetBinLabel(15, "NoCollInTimeRangeNarrow"); + x->SetBinLabel(16, "Occupancy Cut"); x->SetBinLabel(17, "Cent. Sel."); x->SetBinLabel(18, "Nch Sel."); x->SetBinLabel(19, "INEL > 0"); @@ -585,6 +587,10 @@ struct PiKpRAA { registry.add("PtKaVsNchMC_WithRecoEvt", "Generated Events With at least One Rec. Collision;;Gen. Nch (|#eta|<0.8);", kTH2F, {{axisPt, {nBinsNch, minNch, maxNch}}}); registry.add("PtPrVsNchMC_WithRecoEvt", "Generated Events With at least One Rec. Collision;;Gen. Nch (|#eta|<0.8);", kTH2F, {{axisPt, {nBinsNch, minNch, maxNch}}}); + registry.add("PtPiVsNchMC_WithRecoEvt_has_FT0_and_TVX", "Generated Events With at least One Rec. Collision;;Gen. Nch (|#eta|<0.8);", kTH2F, {{axisPt, {nBinsNch, minNch, maxNch}}}); + registry.add("PtKaVsNchMC_WithRecoEvt_has_FT0_and_TVX", "Generated Events With at least One Rec. Collision;;Gen. Nch (|#eta|<0.8);", kTH2F, {{axisPt, {nBinsNch, minNch, maxNch}}}); + registry.add("PtPrVsNchMC_WithRecoEvt_has_FT0_and_TVX", "Generated Events With at least One Rec. Collision;;Gen. Nch (|#eta|<0.8);", kTH2F, {{axisPt, {nBinsNch, minNch, maxNch}}}); + // Needed to calculate the denominator of the Signal Loss correction registry.add("PtPiVsNchMC_AllGen", "All Generated Events;;Gen. Nch (|#eta|<0.8);", kTH2F, {{axisPt, {nBinsNch, minNch, maxNch}}}); registry.add("PtKaVsNchMC_AllGen", "All Generated Events;;Gen. Nch (|#eta|<0.8);", kTH2F, {{axisPt, {nBinsNch, minNch, maxNch}}}); @@ -1250,10 +1256,36 @@ struct PiKpRAA { bestCollisionIndex = collision.globalIndex(); } + if (selHasFT0 && !collision.has_foundFT0()) + continue; + + if (useSel8 && !collision.sel8()) + continue; + + // kIsTriggerTVX + if (selTriggerTVX && !collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) + continue; + + // kNoITSROFrameBorder + if (selNoITSROFrameBorder && !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) + continue; + + // kNoTimeFrameBorder + if (selNoTimeFrameBorder && !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) + continue; + + // Zvtx + if (isZvtxPosSel && std::fabs(collision.posZ()) > posZcut) + continue; + + if (selIsGoodZvtxFT0vsPV && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) + continue; + + if (selNoSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) + continue; + // Needed to calculate denominator of the Event Splitting correction - if (isEventSelected(collision)) { - registry.fill(HIST("Centrality_AllRecoEvt"), centrality); - } + registry.fill(HIST("Centrality_AllRecoEvt"), centrality); } //--------------------------- @@ -1264,15 +1296,6 @@ struct PiKpRAA { const float centrality{isT0Ccent ? collision.centFT0C() : collision.centFT0M()}; - //--------------------------- - // Reject collisions if has_foundFT0() returns false - //--------------------------- - if (selHasFT0 && !collision.has_foundFT0()) { - registry.fill(HIST("T0CcentVsFoundFT0"), centrality, 0.5); - continue; - } - registry.fill(HIST("T0CcentVsFoundFT0"), centrality, 1.5); - //--------------------------- // Pick the collisions with the largest number of contributors //--------------------------- @@ -1301,7 +1324,6 @@ struct PiKpRAA { //--------------------------- // Needed to construct the correlation between MC Nch v.s. centrality //--------------------------- - registry.fill(HIST("Centrality_WRecoEvt"), centrality); registry.fill(HIST("zPosMC"), mccollision.posZ()); @@ -1319,6 +1341,22 @@ struct PiKpRAA { registry.fill(HIST("zPos"), collision.posZ()); registry.fill(HIST("T0Ccent"), centrality); + //--------------------------- + // has_foundFT0() ? + //--------------------------- + if (collision.has_foundFT0()) { + registry.fill(HIST("HasFT0AndTVX"), 2.0); + registry.fill(HIST("T0CcentVsFoundFT0"), centrality, 1.5); + } else { + registry.fill(HIST("T0CcentVsFoundFT0"), centrality, 0.5); + } + if (collision.has_foundFT0() && collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + registry.fill(HIST("HasFT0AndTVX"), 3.0); + registry.fill(HIST("T0CcentVsFoundFT0AndTVX"), centrality, 1.5); + } else { + registry.fill(HIST("T0CcentVsFoundFT0AndTVX"), centrality, 0.5); + } + //--------------------------- // All Generated events with at least one associated reconstructed collision // The Generated events are not subjected to any selection criteria @@ -1366,6 +1404,47 @@ struct PiKpRAA { } } // Loop over generated particles per generated collision + // Generated events with FT0 information but not TVX triggered + if (selHasFT0 && collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + for (const auto& particle : mcParticles) { + if (particle.eta() < v0Selections.minEtaDaughter || particle.eta() > v0Selections.maxEtaDaughter) + continue; + + if (particle.pt() < v0Selections.minPt || particle.pt() > v0Selections.maxPt) + continue; + + auto charge{0.}; + // Get the MC particle + auto* pdgParticle = pdg->GetParticle(particle.pdgCode()); + if (pdgParticle != nullptr) { + charge = pdgParticle->Charge(); + } else { + continue; + } + + // Is it a charged particle? + if (std::abs(charge) < kMinCharge) + continue; + + // Is it a primary particle? + bool isPrimary{true}; + if (!particle.isPhysicalPrimary()) + isPrimary = false; + + if (isPrimary) { + if (particle.pdgCode() == PDG_t::kPiPlus || particle.pdgCode() == PDG_t::kPiMinus) { + registry.fill(HIST("PtPiVsNchMC_WithRecoEvt_has_FT0_and_TVX"), particle.pt(), nChMCEta08); // Numerator of signal loss + } else if (particle.pdgCode() == PDG_t::kKPlus || particle.pdgCode() == PDG_t::kKMinus) { + registry.fill(HIST("PtKaVsNchMC_WithRecoEvt_has_FT0_and_TVX"), particle.pt(), nChMCEta08); + } else if (particle.pdgCode() == PDG_t::kProton || particle.pdgCode() == PDG_t::kProtonBar) { + registry.fill(HIST("PtPrVsNchMC_WithRecoEvt_has_FT0_and_TVX"), particle.pt(), nChMCEta08); + } else { + continue; + } + } + } // Loop over generated particles per generated collision + } + const auto& groupedTracks{tracksMC.sliceBy(perCollision, collision.globalIndex())}; //--------------------------- @@ -1990,6 +2069,15 @@ struct PiKpRAA { bool isEventSelected(CheckCol const& col) { registry.fill(HIST("EventCounter"), EvCutLabel::All); + registry.fill(HIST("HasFT0AndTVX"), EvCutLabel::All); + + // Has FT0 information? + if (selHasFT0) { + if (!col.has_foundFT0()) { + return false; + } + registry.fill(HIST("EventCounter"), EvCutLabel::HasFT0); + } if (useSel8) { if (!col.sel8()) { @@ -2096,13 +2184,6 @@ struct PiKpRAA { registry.fill(HIST("EventCounter"), EvCutLabel::OccuCut); } - if (selHasFT0) { - if (!col.has_foundFT0()) { - return false; - } - registry.fill(HIST("EventCounter"), EvCutLabel::HasFT0); - } - if (isCentSel) { if (col.centFT0C() < minT0CcentCut || col.centFT0C() > maxT0CcentCut) { return false; From 2ffd9640fce6c46c185a4a485020024d41638ecb Mon Sep 17 00:00:00 2001 From: alcaliva <32872606+alcaliva@users.noreply.github.com> Date: Sat, 7 Mar 2026 15:06:04 +0100 Subject: [PATCH 211/347] [PWGLF] Add histograms for closure test (#15287) Co-authored-by: ALICE Action Bot --- PWGLF/Tasks/Nuspex/antinucleiInJets.cxx | 85 +++++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx b/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx index cedb442bd4e..42fad20fff2 100644 --- a/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx +++ b/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx @@ -137,6 +137,10 @@ struct JetMatching { struct AntinucleiInJets { + // Random engine + std::mt19937 rng; + std::uniform_int_distribution generateRandomNr{0, 1}; + // Histogram registries for data, MC, quality control, multiplicity and correlations HistogramRegistry registryData{"registryData", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; HistogramRegistry registryMC{"registryMC", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; @@ -276,6 +280,9 @@ struct AntinucleiInJets { auto timeSeed = std::chrono::high_resolution_clock::now().time_since_epoch().count(); mRand.SetSeed(timeSeed); + // Set seed of random engine + rng.seed(12345); + // Load reweighting histograms from CCDB if antinuclei efficiency processing is enabled if (doprocessAntinucleiEfficiency || doprocessJetsMCgen || doprocessJetsMCrec) { ccdb->setURL(urlToCcdb.value); @@ -389,6 +396,12 @@ struct AntinucleiInJets { registryMC.add("antiproton_gen_ue", "antiproton_gen_ue", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); registryMC.add("antiproton_gen_full", "antiproton_gen_full", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + // Generated spectra of antiprotons for closure test + registryMC.add("antiproton_gen_jet_data", "antiproton_gen_jet_data", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_gen_ue_data", "antiproton_gen_ue_data", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_gen_jet_mc", "antiproton_gen_jet_mc", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_gen_ue_mc", "antiproton_gen_ue_mc", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + // Normalization histogram registryMC.add("antiproton_deltay_deltaphi_jet", "antiproton_deltay_deltaphi_jet", HistType::kTH2F, {{2000, -1.0, 1.0, "#Delta#it{y}"}, {2000, 0.0, 2.0, "#Delta#phi"}}); registryMC.add("antiproton_deltay_deltaphi_ue", "antiproton_deltay_deltaphi_ue", HistType::kTH2F, {{2000, -1.0, 1.0, "#Delta#it{y}"}, {2000, 0.0, 2.0, "#Delta#phi"}}); @@ -416,6 +429,16 @@ struct AntinucleiInJets { registryMC.add("antiproton_rec_tpc_full", "antiproton_rec_tpc_full", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); registryMC.add("antiproton_rec_tof_full", "antiproton_rec_tof_full", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + // Reconstructed spectra of antiprotons for closure test + registryMC.add("antiproton_rec_tpc_jet_data", "antiproton_rec_tpc_jet_data", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_rec_tof_jet_data", "antiproton_rec_tof_jet_data", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_rec_tpc_ue_data", "antiproton_rec_tpc_ue_data", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_rec_tof_ue_data", "antiproton_rec_tof_ue_data", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_rec_tpc_jet_mc", "antiproton_rec_tpc_jet_mc", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_rec_tof_jet_mc", "antiproton_rec_tof_jet_mc", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_rec_tpc_ue_mc", "antiproton_rec_tpc_ue_mc", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_rec_tof_ue_mc", "antiproton_rec_tof_ue_mc", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + // Fraction of primary antiprotons registryMC.add("antiproton_prim_jet", "antiproton_prim_jet", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); registryMC.add("antiproton_incl_jet", "antiproton_incl_jet", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); @@ -2044,6 +2067,10 @@ struct AntinucleiInJets { // Get particles in this MC collision const auto mcParticlesThisMcColl = mcParticles.sliceBy(mcParticlesPerMcCollision, collision.globalIndex()); + // Generate random number to decide if simulated event has to be considered as data or MC in the closure test + int sample = generateRandomNr(rng); + bool isPseudoData = (sample == 0); + // Loop over MC particles for (const auto& particle : mcParticlesThisMcColl) { @@ -2134,6 +2161,13 @@ struct AntinucleiInJets { // Fill histogram for generated antiprotons registryMC.fill(HIST("antiproton_gen_jet"), particle.pt(), weightJet); + // Fill histograms for generated antiprotons for closure test + if (isPseudoData) { + registryMC.fill(HIST("antiproton_gen_jet_data"), particle.pt()); + } else { + registryMC.fill(HIST("antiproton_gen_jet_mc"), particle.pt()); + } + // Fill 2d (pt,eta) distribution of antiprotons registryMC.fill(HIST("antiproton_eta_pt_jet"), particle.pt(), particle.eta(), weightJet); } @@ -2182,12 +2216,24 @@ struct AntinucleiInJets { // Fill histogram for antiprotons in the UE registryMC.fill(HIST("antiproton_gen_ue"), protonVec.Pt(), weightUe); + // Fill histograms for generated antiprotons for closure test + if (sample == 0) { + registryMC.fill(HIST("antiproton_gen_ue_data"), protonVec.Pt()); + } else { + registryMC.fill(HIST("antiproton_gen_ue_mc"), protonVec.Pt()); + } + // Fill 2d (pt,eta) distribution of antiprotons registryMC.fill(HIST("antiproton_eta_pt_ue"), protonVec.Pt(), protonVec.Eta(), weightUe); } } if (isAtLeastOneJetSelected) { registryMC.fill(HIST("genEvents"), 3.5); + if (isPseudoData) { + registryMC.fill(HIST("genEvents"), 4.5); + } else { + registryMC.fill(HIST("genEvents"), 5.5); + } } // Shrink large vectors @@ -2269,6 +2315,10 @@ struct AntinucleiInJets { // Get tracks in this MC collision const auto mcTracksThisMcColl = mcTracks.sliceBy(mcTracksPerMcCollision, collision.globalIndex()); + // Generate random number to decide if simulated event has to be considered as data or MC in the closure test + int sample = generateRandomNr(rng); + bool isPseudoData = (sample == 0); + // Loop over reconstructed tracks int id(-1); for (auto const& track : mcTracksThisMcColl) { @@ -2433,8 +2483,23 @@ struct AntinucleiInJets { // Fill histograms (TPC and TOF) only for selected candidates if (passedItsPidProt && nsigmaTPCPr > minNsigmaTpc && nsigmaTPCPr < maxNsigmaTpc) { registryMC.fill(HIST("antiproton_rec_tpc_jet"), pt, weightJet); + + // Fill histograms for reconstructed antiprotons for closure test + if (isPseudoData) { + registryMC.fill(HIST("antiproton_rec_tpc_jet_data"), pt); + } else { + registryMC.fill(HIST("antiproton_rec_tpc_jet_mc"), pt); + } + if (track.hasTOF() && nsigmaTOFPr > minNsigmaTof && nsigmaTOFPr < maxNsigmaTof) { registryMC.fill(HIST("antiproton_rec_tof_jet"), pt, weightJet); + + // Fill histograms for reconstructed antiprotons for closure test + if (isPseudoData) { + registryMC.fill(HIST("antiproton_rec_tof_jet_data"), pt); + } else { + registryMC.fill(HIST("antiproton_rec_tof_jet_mc"), pt); + } } } } @@ -2515,14 +2580,34 @@ struct AntinucleiInJets { // Fill histograms (TPC and TOF) only for selected candidates if (passedItsPidProt && nsigmaTPCPr > minNsigmaTpc && nsigmaTPCPr < maxNsigmaTpc) { registryMC.fill(HIST("antiproton_rec_tpc_ue"), pt, weightUe); + + // Fill histograms for reconstructed antiprotons for closure test + if (isPseudoData) { + registryMC.fill(HIST("antiproton_rec_tpc_ue_data"), pt); + } else { + registryMC.fill(HIST("antiproton_rec_tpc_ue_mc"), pt); + } + if (track.hasTOF() && nsigmaTOFPr > minNsigmaTof && nsigmaTOFPr < maxNsigmaTof) { registryMC.fill(HIST("antiproton_rec_tof_ue"), pt, weightUe); + + // Fill histograms for reconstructed antiprotons for closure test + if (isPseudoData) { + registryMC.fill(HIST("antiproton_rec_tof_ue_data"), pt); + } else { + registryMC.fill(HIST("antiproton_rec_tof_ue_mc"), pt); + } } } } } if (isAtLeastOneJetSelected) { registryMC.fill(HIST("recEvents"), 9.5); + if (isPseudoData) { + registryMC.fill(HIST("recEvents"), 10.5); + } else { + registryMC.fill(HIST("recEvents"), 11.5); + } } // Shrink large vectors From 81aba18dfbcf6fbc457a51e9dfd224d2b1b0a231 Mon Sep 17 00:00:00 2001 From: Victor Gonzalez Date: Sat, 7 Mar 2026 17:12:18 +0100 Subject: [PATCH 212/347] [PWGCF] DptDpt - Fine tune on the fly second pass (#15301) Co-authored-by: Victor --- PWGCF/TableProducer/dptDptFilter.cxx | 52 +++++++++++++++++++++++----- PWGCF/TableProducer/dptDptFilter.h | 47 ++++++++++++++----------- 2 files changed, 70 insertions(+), 29 deletions(-) diff --git a/PWGCF/TableProducer/dptDptFilter.cxx b/PWGCF/TableProducer/dptDptFilter.cxx index 81b811da6c0..440e88292b8 100644 --- a/PWGCF/TableProducer/dptDptFilter.cxx +++ b/PWGCF/TableProducer/dptDptFilter.cxx @@ -128,7 +128,7 @@ static constexpr float MultiplicityUpperLimitBase[11][8] = { }; /* helpers for the multiplicity/centrality correlations exclusion formulae */ -static const std::string multiplicityCentralityCorrelationsFormulaBase[11][1] = { +static const std::string multiplicityCentralityCorrelationsFormulaBase[11][1] = { // NOLINT /* no system */ {""}, /* pp Run2 */ {""}, /* pPb Run2 */ {""}, @@ -142,7 +142,7 @@ static const std::string multiplicityCentralityCorrelationsFormulaBase[11][1] = /* pO Run3 */ {""}}; /* helpers for the system type assignment */ -static const std::string periodsOnSystemType[11][1] = { +static const std::string periodsOnSystemType[11][1] = { // NOLINT /* no system */ {""}, /* pp Run2 */ {""}, /* pPb Run2 */ {""}, @@ -316,8 +316,8 @@ struct Multiplicity { MultEst classestimator = kV0M; - static constexpr float kForMultiplicityPtLowLimit = 0.001f; - static constexpr float kForMultiplicityPtHighLimit = 50.0f; + static constexpr float KForMultiplicityPtLowLimit = 0.001f; + static constexpr float KForMultiplicityPtHighLimit = 50.0f; float multiplicityClass = -1.0; float multiplicity = 0.0; bool inelgth0 = false; @@ -353,7 +353,7 @@ struct Multiplicity { void setMultiplicityPercentiles(TList* list) { - LOGF(info, "setMultiplicityPercentiles()", "From list %s", list->GetName()); + LOGF(info, "setMultiplicityPercentiles(). From list %s", list->GetName()); fhV0MMultPercentile = reinterpret_cast(list->FindObject("V0MCentMult")); fhCL1MultPercentile = reinterpret_cast(list->FindObject("CL1MCentMult")); fhCL1EtaGapMultPercentile = reinterpret_cast(list->FindObject("CL1EtaGapMCentMult")); @@ -385,7 +385,7 @@ struct Multiplicity { case kProton: /* not clear if we should use IsPhysicalPrimary here */ /* TODO: adapt to FT0M Run 3 and other estimators */ - if (kForMultiplicityPtLowLimit < p.pt() && p.pt() < kForMultiplicityPtHighLimit) { + if (KForMultiplicityPtLowLimit < p.pt() && p.pt() < KForMultiplicityPtHighLimit) { if (p.eta() < 1.0f && -1.0f < p.eta()) { inelgth0 = true; } @@ -545,8 +545,10 @@ struct DptDptFilter { Configurable url{"url", "http://ccdb-test.cern.ch:8080", "The CCDB url for the input file"}; Configurable pathNameCorrections{"pathNameCorrections", "", "The CCDB path for the corrections file. Default \"\", i.e. don't load from CCDB"}; Configurable pathNamePID{"pathNamePID", "", "The CCDB path for the PID adjusts file. Default \"\", i.e. don't load from CCDB"}; + Configurable pathNameOTF{"pathNameOTF", "", "The CCDB path for the OTF configuration file. Default \"\", i.e. don't load from CCDB"}; Configurable dateCorrections{"dateCorrections", "20220307", "The CCDB date for the corrections input file"}; Configurable datePID{"datePID", "20220307", "The CCDB date for the PID adjustments input file"}; + Configurable dateOTF{"dateOTF", "20260306", "The CCDB date for the OTF configuration file"}; Configurable suffix{"suffix", "", "Dataset period suffix for metadata discrimination"}; } cfginputfile; Configurable cfgFullDerivedData{"cfgFullDerivedData", false, "Produce the full derived data for external storage. Default false"}; @@ -595,9 +597,12 @@ struct DptDptFilter { Produces gencollisionsinfo; Multiplicity multiplicity; + std::string otfGenerator; + Service ccdb; + bool storedCcdbInfo = false; Preslice perCollision = aod::track::collisionId; - void init(InitContext const&) + void init(InitContext& initContext) { using namespace dptdptfilter; @@ -645,8 +650,18 @@ struct DptDptFilter { /* get the data type and the system type */ fDataType = getDataType(cfgDataType); - fSystem = getSystemType(cfgSystemForPeriod.value); - fLhcRun = multRunForSystemMap.at(fSystem); + if (fDataType != kOnTheFly) { + fSystem = getSystemType(cfgSystemForPeriod.value); + fLhcRun = multRunForSystemMap.at(fSystem); + } else { + std::string tmpstr; + getTaskOptionValue(initContext, "generator-task", "configFile", tmpstr, false); + TString fullPath = tmpstr; + auto tokens = fullPath.Tokenize("/"); + otfGenerator = TString(tokens->At(tokens->GetEntries() - 1)->GetName()).ReplaceAll(".ini", ""); + delete tokens; + LOGF(info, "The generator configuration file: %s", otfGenerator.c_str()); + } /* the multiplicities outliers exclusion */ multiplicityCentralityCorrelationsExclusion = getExclusionFormula(cfgEventSelection.multiplicitiesExclusionFormula->getData()[fSystem][0].c_str()); @@ -766,6 +781,23 @@ struct DptDptFilter { fOutputList->Add(fhTrueVertexZAA); } } + /* initialize access to the CCDB */ + ccdb->setURL(cfginputfile.url); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + } + + void getCCDBInformation() + { + /* let's get a potential OTF configuration */ + if ((cfginputfile.dateOTF.value.length() > 0) && (cfginputfile.pathNameOTF.value.length() > 0) && !storedCcdbInfo) { + LOGF(info, "Getting information for OTF configuration from %s, at %s", cfginputfile.pathNameOTF.value.c_str(), cfginputfile.dateOTF.value.c_str()); + TList* otfinfo = getCCDBInput(ccdb, cfginputfile.pathNameOTF.value.c_str(), cfginputfile.dateOTF.value.c_str(), true, otfGenerator); + if (otfinfo != nullptr) { + multiplicity.setMultiplicityPercentiles(otfinfo); + } + storedCcdbInfo = true; + } } template @@ -1056,6 +1088,8 @@ void DptDptFilter::processOnTheFlyGeneratorLevel(aod::McCollision const& mccolli fhTrueVertexZB->Fill(mccollision.posZ()); /* we assign a default value for the time being */ float centormult = 50.0f; + /* ask for configuration */ + getCCDBInformation(); if (isEventSelected(mccollision, centormult)) { acceptedEvent = true; multiplicity.extractMultiplicity(mcparticles); diff --git a/PWGCF/TableProducer/dptDptFilter.h b/PWGCF/TableProducer/dptDptFilter.h index d584938e927..63a49a5c7b8 100644 --- a/PWGCF/TableProducer/dptDptFilter.h +++ b/PWGCF/TableProducer/dptDptFilter.h @@ -809,6 +809,23 @@ struct DptDptTrackSelection { bool requirePvContributor = false; }; +SystemType fSystem = SystemNoSystem; +MultRunType fLhcRun = MultRunRUN1RUN2; +DataType fDataType = kData; +CentMultEstimatorType fCentMultEstimator = CentMultV0M; +OccupancyEstimationType fOccupancyEstimation = OccupancyNOOCC; /* the occupancy estimator to use */ + +float fMinOccupancy = 0.0f; /* the minimum allowed occupancy */ +float fMaxOccupancy = 1e6f; /* the maximum allowed occupancy */ + +/* adaptations for the pp nightly checks */ +analysis::CheckRangeCfg traceDCAOutliers; +bool traceOutOfSpeciesParticles = false; +int recoIdMethod = 0; +float particleMaxDCAxy = 999.9f; +float particleMaxDCAZ = 999.9f; +bool traceCollId0 = false; + inline TList* getCCDBInput(auto& ccdb, const char* ccdbpath, const char* ccdbdate, bool periodInPath = false, const std::string& suffix = "") { std::tm cfgtm = {}; @@ -826,13 +843,20 @@ inline TList* getCCDBInput(auto& ccdb, const char* ccdbpath, const char* ccdbdat return tmpStr; }; - std::string actualPeriod = cleanPeriod(metadataInfo.get("LPMProductionTag")); + std::string actualPeriod; + if (fDataType != kOnTheFly) { + actualPeriod = cleanPeriod(metadataInfo.get("LPMProductionTag")); + } else { + actualPeriod = suffix; + } std::string actualPath = ccdbpath; if (periodInPath) { actualPath = actualPath + "/" + actualPeriod; } - if (suffix.length() > 0) { - actualPeriod = actualPeriod + "_" + suffix; + if (fDataType != kOnTheFly) { + if (suffix.length() > 0) { + actualPeriod = actualPeriod + "_" + suffix; + } } TList* lst = nullptr; @@ -846,23 +870,6 @@ inline TList* getCCDBInput(auto& ccdb, const char* ccdbpath, const char* ccdbdat return lst; } -SystemType fSystem = SystemNoSystem; -MultRunType fLhcRun = MultRunRUN1RUN2; -DataType fDataType = kData; -CentMultEstimatorType fCentMultEstimator = CentMultV0M; -OccupancyEstimationType fOccupancyEstimation = OccupancyNOOCC; /* the occupancy estimator to use */ - -float fMinOccupancy = 0.0f; /* the minimum allowed occupancy */ -float fMaxOccupancy = 1e6f; /* the maximum allowed occupancy */ - -/* adaptations for the pp nightly checks */ -analysis::CheckRangeCfg traceDCAOutliers; -bool traceOutOfSpeciesParticles = false; -int recoIdMethod = 0; -float particleMaxDCAxy = 999.9f; -float particleMaxDCAZ = 999.9f; -bool traceCollId0 = false; - inline std::bitset<32> getTriggerSelection(std::string_view const& triggstr) { std::bitset<32> flags; From 9af0ebcc1f6925807824313bff560680d1ed887d Mon Sep 17 00:00:00 2001 From: feisenhu <53603353+feisenhu@users.noreply.github.com> Date: Sat, 7 Mar 2026 17:25:12 +0100 Subject: [PATCH 213/347] [PWGEM] SingleTrackQCMC adapt axis labels (#15294) --- PWGEM/Dilepton/Core/SingleTrackQCMC.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/PWGEM/Dilepton/Core/SingleTrackQCMC.h b/PWGEM/Dilepton/Core/SingleTrackQCMC.h index ee683925809..8cfef51da2c 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQCMC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQCMC.h @@ -285,16 +285,16 @@ struct SingleTrackQCMC { fRegistry.add("Track/PromptLF/positive/hDCAxyRes_Pt", "DCA_{xy} resolution vs. pT;p_{T} (GeV/c);DCA_{xy} resolution (#mum)", kTH2F, {{200, 0, 10}, {500, 0., 500}}, false); fRegistry.add("Track/PromptLF/positive/hDCAzRes_Pt", "DCA_{z} resolution vs. pT;p_{T} (GeV/c);DCA_{z} resolution (#mum)", kTH2F, {{200, 0, 10}, {500, 0., 500}}, false); fRegistry.add("Track/PromptLF/positive/hDCA3dRes_Pt", "DCA_{3D} resolution vs. pT;p_{T} (GeV/c);DCA_{3D} resolution (#mum)", kTH2F, {{200, 0, 10}, {500, 0., 500}}, false); - fRegistry.add("Track/PromptLF/positive/hNclsTPC_Pt", "number of TPC clusters;p_{T,e} (GeV/c);;TPC N_{cls}", kTH2F, {axis_pt, {161, -0.5, 160.5}}, false); - fRegistry.add("Track/PromptLF/positive/hNcrTPC_Pt", "number of TPC crossed rows;p_{T,e} (GeV/c);;TPC N_{CR}", kTH2F, {axis_pt, {161, -0.5, 160.5}}, false); - fRegistry.add("Track/PromptLF/positive/hChi2TPC", "chi2/number of TPC clusters", kTH1F, {{100, 0, 10}}, false); - fRegistry.add("Track/PromptLF/positive/hTPCNcr2Nf", "TPC Ncr/Nfindable", kTH1F, {{200, 0, 2}}, false); - fRegistry.add("Track/PromptLF/positive/hTPCNcls2Nf", "TPC Ncls/Nfindable", kTH1F, {{200, 0, 2}}, false); + fRegistry.add("Track/PromptLF/positive/hNclsTPC_Pt", "number of TPC clusters;p_{T,e} (GeV/c);TPC N_{cls}", kTH2F, {axis_pt, {161, -0.5, 160.5}}, false); + fRegistry.add("Track/PromptLF/positive/hNcrTPC_Pt", "number of TPC crossed rows;p_{T,e} (GeV/c);TPC N_{CR}", kTH2F, {axis_pt, {161, -0.5, 160.5}}, false); + fRegistry.add("Track/PromptLF/positive/hChi2TPC", "chi2/number of TPC clusters;TPC #chi^{2}/N_{CR}", kTH1F, {{100, 0, 10}}, false); + fRegistry.add("Track/PromptLF/positive/hTPCNcr2Nf", "TPC Ncr/Nfindable;TPC N_{CR}/N_{cls}^{findable}", kTH1F, {{200, 0, 2}}, false); + fRegistry.add("Track/PromptLF/positive/hTPCNcls2Nf", "TPC Ncls/Nfindable;TPC N_{cls}/N_{cls}^{findable}", kTH1F, {{200, 0, 2}}, false); fRegistry.add("Track/PromptLF/positive/hTPCNclsShared", "TPC Ncls shared/Ncls;p_{T} (GeV/c);N_{cls}^{shared}/N_{cls} in TPC", kTH2F, {{1000, 0, 10}, {100, 0, 1}}, false); - fRegistry.add("Track/PromptLF/positive/hNclsITS", "number of ITS clusters", kTH1F, {{8, -0.5, 7.5}}, false); - fRegistry.add("Track/PromptLF/positive/hChi2ITS", "chi2/number of ITS clusters", kTH1F, {{100, 0, 10}}, false); + fRegistry.add("Track/PromptLF/positive/hNclsITS", "number of ITS clusters;ITS N_{cls}", kTH1F, {{8, -0.5, 7.5}}, false); + fRegistry.add("Track/PromptLF/positive/hChi2ITS", "chi2/number of ITS clusters;ITS #chi^{2}/N_{cls}", kTH1F, {{100, 0, 10}}, false); fRegistry.add("Track/PromptLF/positive/hDeltaPin", "p_{in} vs. p_{pv};p_{in} (GeV/c);(p_{pv} - p_{in})/p_{in}", kTH2F, {{1000, 0, 10}, {200, -1, +1}}, false); - fRegistry.add("Track/PromptLF/positive/hChi2TOF", "TOF Chi2;p_{pv} (GeV/c);chi2", kTH2F, {{1000, 0, 10}, {100, 0, 10}}, false); + fRegistry.add("Track/PromptLF/positive/hChi2TOF", "TOF Chi2;p_{pv} (GeV/c);TOF #chi^{2}", kTH2F, {{1000, 0, 10}, {100, 0, 10}}, false); fRegistry.add("Track/PromptLF/positive/hITSClusterMap", "ITS cluster map", kTH1F, {{128, -0.5, 127.5}}, false); fRegistry.add("Track/PromptLF/positive/hPIDForTracking", "PID for trackng", kTH1F, {{9, -0.5, 8.5}}, false); // see numbering in O2/DataFormats/Reconstruction/include/ReconstructionDataFormats/PID.h fRegistry.add("Track/PromptLF/positive/hPtGen_DeltaPtOverPtGen", "electron p_{T} resolution;p_{T}^{gen} (GeV/c);(p_{T}^{rec} - p_{T}^{gen})/p_{T}^{gen}", kTH2F, {{200, 0, 10}, {200, -1.0f, 1.0f}}, true); From 7d61abcb39710850f720ea66edb6574ff4acedc1 Mon Sep 17 00:00:00 2001 From: skundu692 <86804743+skundu692@users.noreply.github.com> Date: Sun, 8 Mar 2026 15:52:06 +0100 Subject: [PATCH 214/347] [PWGLF] Change Phi binning range and add QA histogram to monitor centrality distribution (#15305) --- .../Strangeness/lambdaspincorrderived.cxx | 72 +++++++++++++++---- 1 file changed, 58 insertions(+), 14 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx b/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx index a6845963d35..0ff87544f97 100644 --- a/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx +++ b/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx @@ -191,7 +191,9 @@ struct lambdaspincorrderived { TH3D* hweight22; TH3D* hweight32; TH3D* hweight42; + TH2D* hweightCentPair = nullptr; + Configurable ConfWeightPathCentPair{"ConfWeightPathCentPair", "", "Centrality x pair-type weight path"}; Configurable ConfWeightPathLL{"ConfWeightPathLL", "Users/s/skundu/My/Object/spincorr/cent010LL", "Weight path"}; Configurable ConfWeightPathALAL{"ConfWeightPathALAL", "Users/s/skundu/My/Object/spincorr/cent010LL", "Weight path"}; Configurable ConfWeightPathLAL{"ConfWeightPathLAL", "Users/s/skundu/My/Object/spincorr/cent010LL", "Weight path"}; @@ -278,6 +280,9 @@ struct lambdaspincorrderived { histos.add("ptCent", "ptCent", HistType::kTH2D, {{100, 0.0, 10.0}, {8, 0.0, 80.0}}, true); histos.add("etaCent", "etaCent", HistType::kTH2D, {{32, -0.8, 0.8}, {8, 0.0, 80.0}}, true); + histos.add("hCentPairTypeSE", "SE pair-weighted centrality;Centrality;PairType", kTH2D, {{110, 0.0, 110.0}, {4, -0.5, 3.5}}); + histos.add("hCentPairTypeME", "ME pair-weighted centrality;Centrality;PairType", kTH2D, {{110, 0.0, 110.0}, {4, -0.5, 3.5}}); + // --- 3D SE/ME pair-space maps per category (LL, LAL, ALL, ALAL) histos.add("SE_LL", "SE pairs", HistType::kTH3D, {ax_dphi_h, ax_deta, ax_ptpair}, true); histos.add("SE_LAL", "SE pairs", HistType::kTH3D, {ax_dphi_h, ax_deta, ax_ptpair}, true); @@ -368,6 +373,9 @@ struct lambdaspincorrderived { hweight32 = ccdb->getForTimeStamp(ConfWeightPathALL2.value, cfgCcdbParam.nolaterthan.value); hweight42 = ccdb->getForTimeStamp(ConfWeightPathALAL2.value, cfgCcdbParam.nolaterthan.value); } + if (!ConfWeightPathCentPair.value.empty()) { + hweightCentPair = ccdb->getForTimeStamp(ConfWeightPathCentPair.value, cfgCcdbParam.nolaterthan.value); + } } template @@ -694,6 +702,18 @@ struct lambdaspincorrderived { } } + static inline int pairTypeCode(int tag1, int tag2) + { + if (tag1 == 0 && tag2 == 0) { + return 0; // LL + } else if (tag1 == 0 && tag2 == 1) { + return 1; // LAL + } else if (tag1 == 1 && tag2 == 0) { + return 2; // ALL + } else { + return 3; // ALAL + } + } ROOT::Math::PtEtaPhiMVector lambda0, proton0; ROOT::Math::PtEtaPhiMVector lambda, proton; ROOT::Math::PtEtaPhiMVector lambda2, proton2; @@ -737,6 +757,8 @@ struct lambdaspincorrderived { proton2 = ROOT::Math::PtEtaPhiMVector(v02.protonPt(), v02.protonEta(), v02.protonPhi(), o2::constants::physics::MassProton); lambda2 = ROOT::Math::PtEtaPhiMVector(v02.lambdaPt(), v02.lambdaEta(), v02.lambdaPhi(), v02.lambdaMass()); histos.fill(HIST("deltaPhiSame"), RecoDecay::constrainAngle(v0.lambdaPhi() - v02.lambdaPhi(), -TMath::Pi(), harmonicDphi)); + const int ptype = pairTypeCode(v0.v0Status(), v02.v0Status()); + histos.fill(HIST("hCentPairTypeSE"), collision.cent(), ptype, 1.0); if (v0.v0Status() == 0 && v02.v0Status() == 0) { fillHistograms(0, 0, lambda, lambda2, proton, proton2, 0, 1.0); } @@ -1030,7 +1052,8 @@ struct lambdaspincorrderived { MixBinner(float ptMin_, float ptMax_, float ptStep_, float etaAbsMax, float etaStep_, float phiStep_) - : ptMin(ptMin_), ptMax(ptMax_), ptStep(ptStep_), etaMin(-etaAbsMax), etaMax(+etaAbsMax), etaStep(etaStep_), phiMin(0.f), phiMax(static_cast(2.0 * TMath::Pi())), phiStep(phiStep_) + : ptMin(ptMin_), ptMax(ptMax_), ptStep(ptStep_), etaMin(-etaAbsMax), etaMax(+etaAbsMax), etaStep(etaStep_), phiMin(-static_cast(TMath::Pi())), phiMax(+static_cast(TMath::Pi())), phiStep(phiStep_) + // : ptMin(ptMin_), ptMax(ptMax_), ptStep(ptStep_), etaMin(-etaAbsMax), etaMax(+etaAbsMax), etaStep(etaStep_), phiMin(0.f), phiMax(static_cast(2.0 * TMath::Pi())), phiStep(phiStep_) { ptStep = (ptStep > 0.f ? ptStep : 0.1f); etaStep = (etaStep > 0.f ? etaStep : 0.1f); @@ -1138,7 +1161,7 @@ struct lambdaspincorrderived { // Bin kinematics (φ already constrained via your call-site) const int ptB = mb.ptBin(t.lambdaPt()); const int etaB = mb.etaBin(t.lambdaEta()); - const int phiB = mb.phiBin(RecoDecay::constrainAngle(t.lambdaPhi(), 0.0F, harmonic)); + const int phiB = mb.phiBin(RecoDecay::constrainAngle(t.lambdaPhi(), -TMath::Pi(), harmonic)); const int mB = mb.massBin(t.lambdaMass()); if (ptB < 0 || etaB < 0 || phiB < 0 || mB < 0) continue; @@ -1187,7 +1210,7 @@ struct lambdaspincorrderived { // Bin of t1 defines where to search (exact bin, but handle φ wrap at edges) const int ptB = mb.ptBin(t1.lambdaPt()); const int etaB = mb.etaBin(t1.lambdaEta()); - const int phiB = mb.phiBin(RecoDecay::constrainAngle(t1.lambdaPhi(), 0.0F, harmonic)); + const int phiB = mb.phiBin(RecoDecay::constrainAngle(t1.lambdaPhi(), -TMath::Pi(), harmonic)); const int mB = mb.massBin(t1.lambdaMass()); if (ptB < 0 || etaB < 0 || phiB < 0 || mB < 0) continue; @@ -1410,6 +1433,8 @@ struct lambdaspincorrderived { RecoDecay::constrainAngle(mcacc::lamPhi(v0) - mcacc::lamPhi(v02), -TMath::Pi(), harmonicDphi)); + const int ptype = pairTypeCode(mcacc::v0Status(v0), mcacc::v0Status(v02)); + histos.fill(HIST("hCentPairTypeSE"), mcacc::cent(collision), ptype, 1.0); // datatype=0 (same event) fillHistograms(mcacc::v0Status(v0), mcacc::v0Status(v02), lambda, lambda2, proton, proton2, @@ -1573,7 +1598,7 @@ struct lambdaspincorrderived { const int ptB = mb.ptBin(mcacc::lamPt(t)); const int etaB = mb.etaBin(mcacc::lamEta(t)); - const int phiB = mb.phiBin(RecoDecay::constrainAngle(mcacc::lamPhi(t), 0.0F, harmonic)); + const int phiB = mb.phiBin(RecoDecay::constrainAngle(mcacc::lamPhi(t), -TMath::Pi(), harmonic)); const int mB = mb.massBin(mcacc::lamMass(t)); if (ptB < 0 || etaB < 0 || phiB < 0 || mB < 0) { continue; @@ -1625,7 +1650,7 @@ struct lambdaspincorrderived { const int ptB = mb.ptBin(mcacc::lamPt(t1)); const int etaB = mb.etaBin(mcacc::lamEta(t1)); - const int phiB = mb.phiBin(RecoDecay::constrainAngle(mcacc::lamPhi(t1), 0.0F, harmonic)); + const int phiB = mb.phiBin(RecoDecay::constrainAngle(mcacc::lamPhi(t1), -TMath::Pi(), harmonic)); const int mB = mb.massBin(mcacc::lamMass(t1)); if (ptB < 0 || etaB < 0 || phiB < 0 || mB < 0) { continue; @@ -1846,7 +1871,7 @@ struct lambdaspincorrderived { etaB = mb.etaBin(lv.Rapidity()); // treat "eta axis" as rapidity axis } - const int phiB = mb.phiBin(RecoDecay::constrainAngle(t.lambdaPhi(), 0.0F, harmonic)); + const int phiB = mb.phiBin(RecoDecay::constrainAngle(t.lambdaPhi(), -TMath::Pi(), harmonic)); const int mB = mb.massBin(t.lambdaMass()); if (ptB < 0 || etaB < 0 || phiB < 0 || mB < 0) { @@ -1919,7 +1944,7 @@ struct lambdaspincorrderived { etaB = mb.etaBin(lv1.Rapidity()); } - const int phiB = mb.phiBin(RecoDecay::constrainAngle(t1.lambdaPhi(), 0.0F, harmonic)); + const int phiB = mb.phiBin(RecoDecay::constrainAngle(t1.lambdaPhi(), -TMath::Pi(), harmonic)); const int mB = mb.massBin(t1.lambdaMass()); if (ptB < 0 || etaB < 0 || phiB < 0 || mB < 0) { @@ -2011,12 +2036,22 @@ struct lambdaspincorrderived { auto lambda2 = ROOT::Math::PtEtaPhiMVector(t2.lambdaPt(), t2.lambdaEta(), t2.lambdaPhi(), t2.lambdaMass()); + const int ptype = pairTypeCode(tX.v0Status(), t2.v0Status()); + double centPairWeight = 1.0; + if (hweightCentPair) { + const int bin = hweightCentPair->FindBin(col1.cent(), ptype); + centPairWeight = hweightCentPair->GetBinContent(bin); + if (centPairWeight <= 0.0) { + centPairWeight = 1.0; + } + } + const float meWeight = wBase * centPairWeight; const float dPhi = deltaPhiMinusPiToPi((float)lambda.Phi(), (float)lambda2.Phi()); histos.fill(HIST("deltaPhiMix"), dPhi, wBase); - + histos.fill(HIST("hCentPairTypeME"), col1.cent(), ptype, wBase); fillHistograms(tX.v0Status(), t2.v0Status(), lambda, lambda2, proton, proton2, - /*datatype=*/1, /*mixpairweight=*/wBase); + /*datatype=*/1, /*mixpairweight=*/meWeight); } } } @@ -2076,7 +2111,7 @@ struct lambdaspincorrderived { etaB = mb.etaBin(lv.Rapidity()); } - const int phiB = mb.phiBin(phi0To2Pi(mcacc::lamPhi(t))); + const int phiB = mb.phiBin(RecoDecay::constrainAngle(mcacc::lamPhi(t), -TMath::Pi(), harmonic)); if (ptB < 0 || etaB < 0 || phiB < 0) { continue; } @@ -2142,8 +2177,7 @@ struct lambdaspincorrderived { mcacc::lamPhi(t1), mcacc::lamMass(t1)); etaB = mb.etaBin(lv1.Rapidity()); } - - const int phiB = mb.phiBin(phi0To2Pi(mcacc::lamPhi(t1))); + const int phiB = mb.phiBin(RecoDecay::constrainAngle(mcacc::lamPhi(t1), -TMath::Pi(), harmonic)); if (ptB < 0 || etaB < 0 || phiB < 0) { continue; } @@ -2230,12 +2264,22 @@ struct lambdaspincorrderived { auto l2 = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(t2), mcacc::lamEta(t2), mcacc::lamPhi(t2), mcacc::lamMass(t2)); + const int ptype = pairTypeCode(mcacc::v0Status(tX), mcacc::v0Status(t2)); + double centPairWeight = 1.0; + if (hweightCentPair) { + const int bin = hweightCentPair->FindBin(mcacc::cent(col1), ptype); + centPairWeight = hweightCentPair->GetBinContent(bin); + if (centPairWeight <= 0.0) { + centPairWeight = 1.0; + } + } + const float meWeight = wBase * centPairWeight; const float dPhi = deltaPhiMinusPiToPi((float)lX.Phi(), (float)l2.Phi()); histos.fill(HIST("deltaPhiMix"), dPhi, wBase); - + histos.fill(HIST("hCentPairTypeME"), mcacc::cent(col1), ptype, wBase); fillHistograms(mcacc::v0Status(tX), mcacc::v0Status(t2), lX, l2, pX, p2, - /*datatype=*/1, /*mixpairweight=*/wBase); + /*datatype=*/1, /*mixpairweight=*/meWeight); } } } From 7656603967823d378f66eb75099a1970424985fd Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Sun, 8 Mar 2026 16:57:11 +0100 Subject: [PATCH 215/347] [PWGEM/Dilepton] update TOF recalculate for electrons (#15306) --- .../TableProducer/skimmerPrimaryElectron.cxx | 401 ++++++++++++++---- .../TableProducer/skimmerPrimaryTrack.cxx | 2 +- PWGEM/Dilepton/Tasks/eventQC.cxx | 3 - 3 files changed, 315 insertions(+), 91 deletions(-) diff --git a/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx index dcc367c9ba3..cfebeffe399 100644 --- a/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx +++ b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx @@ -59,12 +59,40 @@ using MyTrack = MyTracks::iterator; using MyTracksMC = soa::Join; using MyTrackMC = MyTracksMC::iterator; +namespace o2::aod +{ +namespace pwgem::dilepton::recalculatedtofpid +{ +DECLARE_SOA_COLUMN(BetaRecalculated, betaRecalculated, float); +DECLARE_SOA_COLUMN(TOFNSigmaElRecalculated, tofNSigmaElRecalculated, float); +} // namespace pwgem::dilepton::recalculatedtofpid + +DECLARE_SOA_TABLE(EMTOFNSigmas, "AOD", "EMTOFNSIGMA", // make std::map in your tasks later. // Don't store this table in the derived data. + o2::aod::emprimaryelectron::CollisionId, o2::aod::emprimaryelectron::TrackId, + o2::aod::pwgem::dilepton::recalculatedtofpid::BetaRecalculated, o2::aod::pwgem::dilepton::recalculatedtofpid::TOFNSigmaElRecalculated); + +using EMTOFNSigma = EMTOFNSigmas::iterator; + +namespace pwgem::dilepton::mlpid +{ +DECLARE_SOA_COLUMN(BDTScore, bdtScore, float); +} // namespace pwgem::dilepton::mlpid + +DECLARE_SOA_TABLE(EMMLPIDs, "AOD", "EMMLPID", // make std::map in your tasks later. // Don't store this table in the derived data. + o2::aod::emprimaryelectron::CollisionId, o2::aod::emprimaryelectron::TrackId, o2::aod::pwgem::dilepton::mlpid::BDTScore); +using EMMLPID = EMMLPIDs::iterator; + +} // namespace o2::aod + struct skimmerPrimaryElectron { SliceCache cache; Preslice perCol = o2::aod::track::collisionId; Produces emprimaryelectrons; Produces emprimaryelectronscov; + Produces emtofs; + Produces emmlpids; + // Configurables Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; @@ -113,10 +141,10 @@ struct skimmerPrimaryElectron { Configurable usePIDML{"usePIDML", false, "Flag to use PID ML"}; Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; Configurable> onnxPathsCCDB{"onnxPathsCCDB", std::vector{"path"}, "Paths of models on CCDB"}; - Configurable> binsMl{"binsMl", std::vector{-999999., 999999.}, "Bin limits for ML application"}; - Configurable> cutsMl{"cutsMl", std::vector{0.95}, "ML cuts per bin"}; - Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"feature"}, "Names of ML model input features"}; - Configurable nameBinningFeature{"nameBinningFeature", "pt", "Names of ML model binning feature"}; + Configurable> binsMl{"binsMl", std::vector{0.1, 0.15, 0.2, 0.25, 0.4, 0.8, 1.6, 2.0, 20}, "Bin limits for ML application"}; + Configurable> cutsMl{"cutsMl", std::vector{0.95, 0.95, 0.7, 0.7, 0.8, 0.8, 0.7, 0.7}, "ML cuts per bin"}; + Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"tpcInnerParam", "tpcNClsFound", "tpcChi2NCl", "tpcNSigmaEl", "tofNSigmaEl", "meanClusterSizeITSobCos"}, "Names of ML model input features"}; + Configurable nameBinningFeature{"nameBinningFeature", "tpcInnerParam", "Names of ML model binning feature"}; Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB. Exceptions: > 0 for the specific timestamp, 0 gets the run dependent timestamp"}; Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; Configurable enableOptimizations{"enableOptimizations", false, "Enables the ONNX extended model-optimization: sessionOptions.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED)"}; @@ -381,25 +409,21 @@ struct skimmerPrimaryElectron { } template - bool isElectron(TCollision const& collision, TTrack const& track, float& probaEl) + void fillMLPIDTable(TCollision const& collision, TTrack const& track) { - probaEl = 1.f; if (usePIDML) { - if (!isElectron_TOFif(track, collision)) { - probaEl = 0.0; - return false; - } o2::dataformats::DCA mDcaInfoCov; mDcaInfoCov.set(999, 999, 999, 999, 999); auto trackParCov = getTrackParCov(track); trackParCov.setPID(o2::track::PID::Electron); - mVtx.setPos({collision.posX(), collision.posY(), collision.posZ()}); - mVtx.setCov(collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()); - bool isPropOK = o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, trackParCov, 2.f, matCorr, &mDcaInfoCov); - if (!isPropOK) { - probaEl = 0.0; - return false; - } + + // mVtx.setPos({collision.posX(), collision.posY(), collision.posZ()}); + // mVtx.setCov(collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()); + // bool isPropOK = o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, trackParCov, 2.f, matCorr, &mDcaInfoCov); + // if (!isPropOK) { + // probaEl = 0.0; + // return false; + // } std::vector inputFeatures = mlResponseSingleTrack.getInputFeatures(track, trackParCov, collision, mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())], mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]); float binningFeature = mlResponseSingleTrack.getBinningFeature(track, trackParCov, collision, mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())], mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]); @@ -411,10 +435,47 @@ struct skimmerPrimaryElectron { } // LOGF(info, "track.tpcInnerParam() = %f (GeV/c), pbin = %d", track.tpcInnerParam(), pbin); - probaEl = mlResponseSingleTrack.getModelOutput(inputFeatures, pbin)[1]; // 0: hadron, 1:electron - return probaEl > cutsMl.value[pbin]; + float probaEl = mlResponseSingleTrack.getModelOutput(inputFeatures, pbin)[1]; // 0: hadron, 1:electron + mapProbaEl[std::make_pair(collision.globalIndex(), track.globalIndex())] = probaEl; + emmlpids(collision.globalIndex(), track.globalIndex(), probaEl); + } else { + mapProbaEl[std::make_pair(collision.globalIndex(), track.globalIndex())] = 1.0; + emmlpids(collision.globalIndex(), track.globalIndex(), 1.0); + } + } + + template + bool isElectron(TCollision const& collision, TTrack const& track) + { + if (usePIDML) { + if (isElectron_TOFif(track, collision)) { + auto trackParCov = getTrackParCov(track); + // trackParCov.setPID(o2::track::PID::Electron); + // o2::dataformats::DCA mDcaInfoCov; + // mDcaInfoCov.set(999, 999, 999, 999, 999); + // mVtx.setPos({collision.posX(), collision.posY(), collision.posZ()}); + // mVtx.setCov(collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()); + // bool isPropOK = o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, trackParCov, 2.f, matCorr, &mDcaInfoCov); + // if (!isPropOK) { + // probaEl = 0.0; + // return false; + // } + // std::vector inputFeatures = mlResponseSingleTrack.getInputFeatures(track, trackParCov, collision, mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())], mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]); + float binningFeature = mlResponseSingleTrack.getBinningFeature(track, trackParCov, collision, mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())], mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]); + + int pbin = lower_bound(binsMl.value.begin(), binsMl.value.end(), binningFeature) - binsMl.value.begin() - 1; + if (pbin < 0) { + pbin = 0; + } else if (static_cast(binsMl.value.size()) - 2 < pbin) { + pbin = static_cast(binsMl.value.size()) - 2; + } + // LOGF(info, "track.tpcInnerParam() = %f (GeV/c), pbin = %d", track.tpcInnerParam(), pbin); + + return mapProbaEl[std::make_pair(collision.globalIndex(), track.globalIndex())] > cutsMl.value[pbin]; + } else { + return false; + } } else { - probaEl = 1.f; return isElectron_TPChadrej(track, collision) || isElectron_TOFreq(track, collision); } } @@ -465,7 +526,7 @@ struct skimmerPrimaryElectron { } template - void fillTrackTable(TCollision const& collision, TTrack const& track, const float probaEl) + void fillTrackTable(TCollision const& collision, TTrack const& track) { if (std::find(stored_trackIds.begin(), stored_trackIds.end(), std::pair{collision.globalIndex(), track.globalIndex()}) == stored_trackIds.end()) { o2::dataformats::DCA mDcaInfoCov; @@ -488,6 +549,7 @@ struct skimmerPrimaryElectron { float tofNSigmaEl = mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]; float beta = mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]; + float probaEl = mapProbaEl[std::make_pair(collision.globalIndex(), track.globalIndex())]; bool isAssociatedToMPC = collision.globalIndex() == track.collisionId(); float mcTunedTPCSignal = 0.f; @@ -621,11 +683,12 @@ struct skimmerPrimaryElectron { float beta = track.length() / (track.tofSignalInAnotherBC(bcTrack.globalBC(), bcCollision.globalBC()) - mapCollisionTime[collision.globalIndex()]) / (TMath::C() * 1e+2 * 1e-12); mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = tofNSigmaEl; mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = beta; + emtofs(collision.globalIndex(), track.globalIndex(), mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())], mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]); } else { mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.tofNSigmaEl(); mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.beta(); + emtofs(collision.globalIndex(), track.globalIndex(), mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())], mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]); } - } // end of track loop } // end of collision loop } else { @@ -637,6 +700,7 @@ struct skimmerPrimaryElectron { } mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.tofNSigmaEl(); mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.beta(); + emtofs(collision.globalIndex(), track.globalIndex(), mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())], mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]); } } // end of track loop } // end of collision loop @@ -651,6 +715,7 @@ struct skimmerPrimaryElectron { } mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.tofNSigmaEl(); mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.beta(); + emtofs(collision.globalIndex(), track.globalIndex(), mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())], mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]); } // end of track loop } // end of collision loop } else { @@ -662,6 +727,7 @@ struct skimmerPrimaryElectron { } mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.tofNSigmaEl(); mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.beta(); + emtofs(collision.globalIndex(), track.globalIndex(), mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())], mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]); } } // end of track loop } // end of collision loop @@ -676,14 +742,14 @@ struct skimmerPrimaryElectron { Partition posTracks = o2::aod::track::signed1Pt > 0.f; Partition negTracks = o2::aod::track::signed1Pt < 0.f; - std::map, float> mapProbEl; // map pair(collisionId, trackId) -> probaEl std::unordered_multimap multiMapTracksPerCollision; // collisionId -> trackIds std::unordered_map mapCollisionTime; std::unordered_map mapCollisionTimeError; - std::map, float> mapTOFNsigmaReassociated; - std::map, float> mapTOFBetaReassociated; + std::map, float> mapProbaEl; // map pair(collisionId, trackId) -> probaEl + std::map, float> mapTOFNsigmaReassociated; // map pair(collisionId, trackId) -> tof n sigma + std::map, float> mapTOFBetaReassociated; // map pair(collisionId, trackId) -> tof beta // ---------- for data ---------- @@ -706,14 +772,13 @@ struct skimmerPrimaryElectron { auto tracks_per_coll = tracks.sliceBy(perCol, collision.globalIndex()); for (const auto& track : tracks_per_coll) { - float probaEl = 1.0; + fillMLPIDTable(collision, track); if (!checkTrack(collision, track)) { continue; } - if (!isElectron(collision, track, probaEl)) { + if (!isElectron(collision, track)) { continue; } - mapProbEl[std::make_pair(collision.globalIndex(), track.globalIndex())] = probaEl; multiMapTracksPerCollision.insert(std::make_pair(collision.globalIndex(), track.globalIndex())); } } // end of collision loop @@ -727,12 +792,12 @@ struct skimmerPrimaryElectron { auto range_electrons = multiMapTracksPerCollision.equal_range(collision.globalIndex()); for (auto it = range_electrons.first; it != range_electrons.second; it++) { auto track = tracks.rawIteratorAt(it->second); - fillTrackTable(collision, track, mapProbEl[std::make_pair(collision.globalIndex(), track.globalIndex())]); + fillTrackTable(collision, track); } } } // end of collision loop - mapProbEl.clear(); + mapProbaEl.clear(); multiMapTracksPerCollision.clear(); stored_trackIds.clear(); stored_trackIds.shrink_to_fit(); @@ -772,14 +837,13 @@ struct skimmerPrimaryElectron { for (const auto& trackId : trackIdsThisCollision) { auto track = trackId.template track_as(); - float probaEl = 1.0; + fillMLPIDTable(collision, track); if (!checkTrack(collision, track)) { continue; } - if (!isElectron(collision, track, probaEl)) { + if (!isElectron(collision, track)) { continue; } - mapProbEl[std::make_pair(collision.globalIndex(), track.globalIndex())] = probaEl; multiMapTracksPerCollision.insert(std::make_pair(collision.globalIndex(), track.globalIndex())); } } // end of collision loop @@ -793,12 +857,12 @@ struct skimmerPrimaryElectron { auto range_electrons = multiMapTracksPerCollision.equal_range(collision.globalIndex()); for (auto it = range_electrons.first; it != range_electrons.second; it++) { auto track = tracks.rawIteratorAt(it->second); - fillTrackTable(collision, track, mapProbEl[std::make_pair(collision.globalIndex(), track.globalIndex())]); + fillTrackTable(collision, track); } } } // end of collision loop - mapProbEl.clear(); + mapProbaEl.clear(); multiMapTracksPerCollision.clear(); stored_trackIds.clear(); stored_trackIds.shrink_to_fit(); @@ -830,14 +894,13 @@ struct skimmerPrimaryElectron { auto tracks_per_coll = tracks.sliceBy(perCol, collision.globalIndex()); for (const auto& track : tracks_per_coll) { - float probaEl = 1.0; + fillMLPIDTable(collision, track); if (!checkTrack(collision, track)) { continue; } - if (!isElectron(collision, track, probaEl)) { + if (!isElectron(collision, track)) { continue; } - mapProbEl[std::make_pair(collision.globalIndex(), track.globalIndex())] = probaEl; multiMapTracksPerCollision.insert(std::make_pair(collision.globalIndex(), track.globalIndex())); } @@ -852,12 +915,12 @@ struct skimmerPrimaryElectron { auto range_electrons = multiMapTracksPerCollision.equal_range(collision.globalIndex()); for (auto it = range_electrons.first; it != range_electrons.second; it++) { auto track = tracks.rawIteratorAt(it->second); - fillTrackTable(collision, track, mapProbEl[std::make_pair(collision.globalIndex(), track.globalIndex())]); + fillTrackTable(collision, track); } } } // end of collision loop - mapProbEl.clear(); + mapProbaEl.clear(); multiMapTracksPerCollision.clear(); stored_trackIds.clear(); stored_trackIds.shrink_to_fit(); @@ -897,14 +960,13 @@ struct skimmerPrimaryElectron { for (const auto& trackId : trackIdsThisCollision) { auto track = trackId.template track_as(); - float probaEl = 1.0; + fillMLPIDTable(collision, track); if (!checkTrack(collision, track)) { continue; } - if (!isElectron(collision, track, probaEl)) { + if (!isElectron(collision, track)) { continue; } - mapProbEl[std::make_pair(collision.globalIndex(), track.globalIndex())] = probaEl; multiMapTracksPerCollision.insert(std::make_pair(collision.globalIndex(), track.globalIndex())); } } // end of collision loop @@ -918,12 +980,12 @@ struct skimmerPrimaryElectron { auto range_electrons = multiMapTracksPerCollision.equal_range(collision.globalIndex()); for (auto it = range_electrons.first; it != range_electrons.second; it++) { auto track = tracks.rawIteratorAt(it->second); - fillTrackTable(collision, track, mapProbEl[std::make_pair(collision.globalIndex(), track.globalIndex())]); + fillTrackTable(collision, track); } } } // end of collision loop - mapProbEl.clear(); + mapProbaEl.clear(); multiMapTracksPerCollision.clear(); stored_trackIds.clear(); stored_trackIds.shrink_to_fit(); @@ -959,14 +1021,13 @@ struct skimmerPrimaryElectron { auto tracks_per_coll = tracks.sliceBy(perCol, collision.globalIndex()); for (const auto& track : tracks_per_coll) { - float probaEl = 1.0; + fillMLPIDTable(collision, track); if (!checkTrack(collision, track)) { continue; } - if (!isElectron(collision, track, probaEl)) { + if (!isElectron(collision, track)) { continue; } - mapProbEl[std::make_pair(collision.globalIndex(), track.globalIndex())] = probaEl; multiMapTracksPerCollision.insert(std::make_pair(collision.globalIndex(), track.globalIndex())); } } // end of collision loop @@ -980,12 +1041,12 @@ struct skimmerPrimaryElectron { auto range_electrons = multiMapTracksPerCollision.equal_range(collision.globalIndex()); for (auto it = range_electrons.first; it != range_electrons.second; it++) { auto track = tracks.rawIteratorAt(it->second); - fillTrackTable(collision, track, mapProbEl[std::make_pair(collision.globalIndex(), track.globalIndex())]); + fillTrackTable(collision, track); } } } // end of collision loop - mapProbEl.clear(); + mapProbaEl.clear(); multiMapTracksPerCollision.clear(); stored_trackIds.clear(); stored_trackIds.shrink_to_fit(); @@ -1025,14 +1086,13 @@ struct skimmerPrimaryElectron { for (const auto& trackId : trackIdsThisCollision) { auto track = trackId.template track_as(); - float probaEl = 1.0; + fillMLPIDTable(collision, track); if (!checkTrack(collision, track)) { continue; } - if (!isElectron(collision, track, probaEl)) { + if (!isElectron(collision, track)) { continue; } - mapProbEl[std::make_pair(collision.globalIndex(), track.globalIndex())] = probaEl; multiMapTracksPerCollision.insert(std::make_pair(collision.globalIndex(), track.globalIndex())); } } // end of collision loop @@ -1046,12 +1106,12 @@ struct skimmerPrimaryElectron { auto range_electrons = multiMapTracksPerCollision.equal_range(collision.globalIndex()); for (auto it = range_electrons.first; it != range_electrons.second; it++) { auto track = tracks.rawIteratorAt(it->second); - fillTrackTable(collision, track, mapProbEl[std::make_pair(collision.globalIndex(), track.globalIndex())]); + fillTrackTable(collision, track); } } } // end of collision loop - mapProbEl.clear(); + mapProbaEl.clear(); multiMapTracksPerCollision.clear(); stored_trackIds.clear(); stored_trackIds.shrink_to_fit(); @@ -1084,22 +1144,38 @@ struct prefilterPrimaryElectron { Configurable fillQAHistogram{"fillQAHistogram", false, "flag to fill QA histograms"}; Configurable max_dcaxy{"max_dcaxy", 1.0, "DCAxy To PV for loose track sample"}; Configurable max_dcaz{"max_dcaz", 1.0, "DCAz To PV for loose track sample"}; - Configurable minpt{"minpt", 0.1, "min pt for ITS-TPC track"}; - Configurable maxeta{"maxeta", 1.2, "eta acceptance for loose track sample"}; + Configurable minpt{"minpt", 0.01, "min pt for ITS-TPC track"}; + Configurable maxeta{"maxeta", 0.9, "eta acceptance for loose track sample"}; Configurable min_ncluster_tpc{"min_ncluster_tpc", 0, "min ncluster tpc"}; - Configurable mincrossedrows{"mincrossedrows", 70, "min crossed rows"}; - Configurable max_frac_shared_clusters_tpc{"max_frac_shared_clusters_tpc", 999.f, "max fraction of shared clusters in TPC"}; + Configurable mincrossedrows{"mincrossedrows", 40, "min crossed rows"}; + Configurable max_frac_shared_clusters_tpc{"max_frac_shared_clusters_tpc", 0.7f, "max fraction of shared clusters in TPC"}; Configurable min_tpc_cr_findable_ratio{"min_tpc_cr_findable_ratio", 0.8, "min. TPC Ncr/Nf ratio"}; Configurable maxchi2tpc{"maxchi2tpc", 5.0, "max chi2/NclsTPC"}; Configurable maxchi2its{"maxchi2its", 36.0, "max chi2/NclsITS"}; - Configurable min_ncluster_its{"min_ncluster_its", 4, "min ncluster its"}; + Configurable min_ncluster_its{"min_ncluster_its", 2, "min ncluster its"}; Configurable min_ncluster_itsib{"min_ncluster_itsib", 1, "min ncluster itsib"}; Configurable minTPCNsigmaEl{"minTPCNsigmaEl", -2.0, "min. TPC n sigma for electron inclusion"}; Configurable maxTPCNsigmaEl{"maxTPCNsigmaEl", 3.0, "max. TPC n sigma for electron inclusion"}; + Configurable maxTOFNsigmaEl{"maxTOFNsigmaEl", 3.0, "max. TOF n sigma for electron inclusion"}; // TOFif + Configurable maxTPCNsigmaPi{"maxTPCNsigmaPi", 0, "max. TPC n sigma for pion exclusion"}; + Configurable minTPCNsigmaPi{"minTPCNsigmaPi", 0, "min. TPC n sigma for pion exclusion"}; + Configurable maxTPCNsigmaKa{"maxTPCNsigmaKa", 0, "max. TPC n sigma for kaon exclusion"}; + Configurable minTPCNsigmaKa{"minTPCNsigmaKa", 0, "min. TPC n sigma for kaon exclusion"}; + Configurable maxTPCNsigmaPr{"maxTPCNsigmaPr", 0, "max. TPC n sigma for proton exclusion"}; + Configurable minTPCNsigmaPr{"minTPCNsigmaPr", 0, "min. TPC n sigma for proton exclusion"}; + Configurable min_pin_for_pion_rejection{"min_pin_for_pion_rejection", 0.0, "pion rejection is applied above this pin"}; // this is used only in TOFreq + Configurable max_pin_for_pion_rejection{"max_pin_for_pion_rejection", 0.5, "pion rejection is applied below this pin"}; Configurable slope{"slope", 0.0185, "slope for m vs. phiv"}; Configurable intercept{"intercept", -0.0280, "intercept for m vs. phiv"}; Configurable maxMeanITSClusterSize{"maxMeanITSClusterSize", 16, "max x cos(lambda)"}; + // Configurable useTOFNSigmaDeltaBC{"useTOFNSigmaDeltaBC", false, "Flag to shift delta BC for TOF n sigma (only with TTCA)"}; + Configurable usePIDML{"usePIDML", false, "Flag to use PID ML"}; + Configurable> binsMl{"binsMl", std::vector{0.1, 0.15, 0.2, 0.25, 0.4, 0.8, 1.6, 2.0, 20}, "Bin limits for ML application"}; + Configurable> cutsMl{"cutsMl", std::vector{0.85, 0.85, 0.6, 0.6, 0.7, 0.7, 0.6, 0.6}, "ML cuts per bin"}; + Configurable nameBinningFeature{"nameBinningFeature", "tpcInnerParam", "Names of ML model binning feature"}; + + o2::analysis::MlResponseO2Track mlResponseSingleTrack; HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; const std::vector max_mee_vec{0.02, 0.04, 0.06, 0.08, 0.10, 0.12, 0.14}; @@ -1112,7 +1188,7 @@ struct prefilterPrimaryElectron { const o2::dataformats::MeanVertexObject* mMeanVtx = nullptr; o2::base::MatLayerCylSet* lut = nullptr; - void init(InitContext&) + void init(InitContext& initContext) { mRunNumber = 0; d_bz = 0; @@ -1125,13 +1201,52 @@ struct prefilterPrimaryElectron { if (!doprocessDummy && fillQAHistogram) { addHistograms(); } + + // BDT files are inherited from skimmer-primary-electron task above. + getTaskOptionValue(initContext, "skimmer-primary-electron", "usePIDML", usePIDML.value, true); + // getTaskOptionValue(initContext, "skimmer-primary-electron", "useTOFNSigmaDeltaBC", useTOFNSigmaDeltaBC.value, true); + + if (usePIDML) { + getTaskOptionValue(initContext, "skimmer-primary-electron", "binsMl.value", binsMl.value, true); + // getTaskOptionValue(initContext, "skimmer-primary-electron", "cutsMl.value", cutsMl.value, true); + getTaskOptionValue(initContext, "skimmer-primary-electron", "nameBinningFeature", nameBinningFeature.value, true); + } + + if (usePIDML) { + static constexpr int nClassesMl = 2; + const std::vector cutDirMl = {o2::cuts_ml::CutNot, o2::cuts_ml::CutSmaller}; + const std::vector labelsClasses = {"Background", "Signal"}; + const uint32_t nBinsMl = binsMl.value.size() - 1; + const std::vector labelsBins(nBinsMl, "bin"); + double cutsMlArr[nBinsMl][nClassesMl]; + for (uint32_t i = 0; i < nBinsMl; i++) { + cutsMlArr[i][0] = 0.0; + cutsMlArr[i][1] = cutsMl.value[i]; + } + o2::framework::LabeledArray cutsMl = {cutsMlArr[0], nBinsMl, nClassesMl, labelsBins, labelsClasses}; + + mlResponseSingleTrack.configure(binsMl.value, cutsMl, cutDirMl, nClassesMl); + + // if (loadModelsFromCCDB) { + // ccdbApi.init(ccdburl); + // mlResponseSingleTrack.setModelPathsCCDB(onnxFileNames.value, ccdbApi, onnxPathsCCDB.value, timestampCCDB.value); + // } else { + // mlResponseSingleTrack.setModelPathsLocal(onnxFileNames.value); + // } + // mlResponseSingleTrack.cacheInputFeaturesIndices(namesInputFeatures); + mlResponseSingleTrack.cacheBinningIndex(nameBinningFeature); + // mlResponseSingleTrack.init(enableOptimizations.value); + // mlResponseSingleTrack.useReassociatedTOF(useTOFNSigmaDeltaBC.value); + } // end of PID ML } void addHistograms() { fRegistry.add("Track/hPt", "pT;p_{T} (GeV/c)", kTH1F, {{1000, 0.0f, 10}}, false); - fRegistry.add("Track/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{90, 0, 2 * M_PI}, {80, -2.0f, 2.0f}}, false); + fRegistry.add("Track/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{90, 0, 2 * M_PI}, {40, -1.0f, 1.0f}}, false); fRegistry.add("Track/hTPCNsigmaEl", "loose track TPC PID", kTH2F, {{1000, 0.f, 10}, {100, -5, +5}}); + fRegistry.add("Track/hTOFNsigmaEl", "loose track TOF PID", kTH2F, {{1000, 0.f, 10}, {100, -5, +5}}); + fRegistry.add("Track/hProbElBDT", "BDT score", kTH2F, {{1000, 0.f, 10}, {100, 0, 1}}); fRegistry.add("Pair/before/uls/hMvsPt", "mass vs. pT;m_{ee} (GeV/c^{2});p_{T,ee} (GeV/c)", kTH2F, {{500, 0, 0.5}, {100, 0, 1}}); fRegistry.add("Pair/before/uls/hMvsPhiV", "mass vs. phiv;#varphi_{V} (rad.);m_{ee} (GeV/c^{2})", kTH2F, {{90, 0.f, M_PI}, {100, 0, 0.1}}); fRegistry.addClone("Pair/before/uls/", "Pair/before/lspp/"); @@ -1212,9 +1327,10 @@ struct prefilterPrimaryElectron { return false; } - if (track.tpcNSigmaEl() < minTPCNsigmaEl || maxTPCNsigmaEl < track.tpcNSigmaEl()) { - return false; - } + // if (track.tpcNSigmaEl() < minTPCNsigmaEl || maxTPCNsigmaEl < track.tpcNSigmaEl()) { + // return false; + // } + if (track.tpcNClsFound() < min_ncluster_tpc) { return false; } @@ -1268,6 +1384,87 @@ struct prefilterPrimaryElectron { return true; } + template + bool isElectron(TCollision const& collision, TTrack const& track) + { + if (usePIDML) { + if (isElectron_TOFif(track, collision)) { + auto trackParCov = getTrackParCov(track); + // trackParCov.setPID(o2::track::PID::Electron); + // o2::dataformats::DCA mDcaInfoCov; + // mDcaInfoCov.set(999, 999, 999, 999, 999); + // mVtx.setPos({collision.posX(), collision.posY(), collision.posZ()}); + // mVtx.setCov(collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()); + // bool isPropOK = o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, trackParCov, 2.f, matCorr, &mDcaInfoCov); + // if (!isPropOK) { + // probaEl = 0.0; + // return false; + // } + // std::vector inputFeatures = mlResponseSingleTrack.getInputFeatures(track, trackParCov, collision, mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())], mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]); + float binningFeature = mlResponseSingleTrack.getBinningFeature(track, trackParCov, collision, mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())], mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]); + + int pbin = lower_bound(binsMl.value.begin(), binsMl.value.end(), binningFeature) - binsMl.value.begin() - 1; + if (pbin < 0) { + pbin = 0; + } else if (static_cast(binsMl.value.size()) - 2 < pbin) { + pbin = static_cast(binsMl.value.size()) - 2; + } + // LOGF(info, "track.tpcInnerParam() = %f (GeV/c), pbin = %d", track.tpcInnerParam(), pbin); + + return mapProbaEl[std::make_pair(collision.globalIndex(), track.globalIndex())] > cutsMl.value[pbin]; + } else { + return false; + } + } else { + return isElectron_TPChadrej(track, collision) || isElectron_TOFreq(track, collision); + } + } + + template + bool isElectron_TOFif(TTrack const& track, TCollision const& collision) + { + // collisionId must be collisionId after reassociation. + // track.tofSignalInAnotherBC(bcTrack.globalBC(), bcCascade.globalBC()) + float tofNSigmaEl = mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]; + bool is_EL_TPC = minTPCNsigmaEl < track.tpcNSigmaEl() && track.tpcNSigmaEl() < maxTPCNsigmaEl; + bool is_EL_TOF = track.hasTOF() ? (std::fabs(tofNSigmaEl) < maxTOFNsigmaEl) : true; // TOFif + return is_EL_TPC && is_EL_TOF; + } + + template + bool isElectron_TPChadrej(TTrack const& track, TCollision const& collision) + { + float tofNSigmaEl = mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]; + + if (track.tpcNSigmaEl() < minTPCNsigmaEl || maxTPCNsigmaEl < track.tpcNSigmaEl()) { + return false; + } + if (minTPCNsigmaPi < track.tpcNSigmaPi() && track.tpcNSigmaPi() < maxTPCNsigmaPi && track.tpcInnerParam() < max_pin_for_pion_rejection) { + return false; + } + if (minTPCNsigmaKa < track.tpcNSigmaKa() && track.tpcNSigmaKa() < maxTPCNsigmaKa) { + return false; + } + if (minTPCNsigmaPr < track.tpcNSigmaPr() && track.tpcNSigmaPr() < maxTPCNsigmaPr) { + return false; + } + if (track.hasTOF() && (maxTOFNsigmaEl < std::fabs(tofNSigmaEl))) { + return false; + } + return true; + } + + template + bool isElectron_TOFreq(TTrack const& track, TCollision const& collision) + { + float tofNSigmaEl = mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]; + + if (minTPCNsigmaPi < track.tpcNSigmaPi() && track.tpcNSigmaPi() < maxTPCNsigmaPi && (min_pin_for_pion_rejection < track.tpcInnerParam() && track.tpcInnerParam() < max_pin_for_pion_rejection)) { + return false; + } + return minTPCNsigmaEl < track.tpcNSigmaEl() && track.tpcNSigmaEl() < maxTPCNsigmaEl && std::fabs(tofNSigmaEl) < maxTOFNsigmaEl; + } + template bool reconstructPC(TCollision const& collision, TTrack1 const& ele, TTrack2 const& pos) { @@ -1315,6 +1512,10 @@ struct prefilterPrimaryElectron { } } + std::map, float> mapProbaEl; // map pair(collisionId, trackId) -> probaEl + std::map, float> mapTOFNsigmaReassociated; // map pair(collisionId, trackId) -> tof n sigma + std::map, float> mapTOFBetaReassociated; // map pair(collisionId, trackId) -> tof beta + Preslice trackIndicesPerCollision = aod::track_association::collisionId; Filter trackFilter = ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) == true && ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::TPC) == true; @@ -1325,8 +1526,16 @@ struct prefilterPrimaryElectron { Partition positrons = o2::aod::emprimaryelectron::sign > int8_t(0); Partition electrons = o2::aod::emprimaryelectron::sign < int8_t(0); - void processPrefilter_TTCA(MyCollisions const& collisions, aod::BCsWithTimestamps const&, MyTracks const&, aod::EMPrimaryElectrons const& primaryelectrons, aod::TrackAssoc const& trackIndices) + void processPrefilter_TTCA(MyCollisions const& collisions, aod::BCsWithTimestamps const&, MyTracks const&, aod::EMPrimaryElectrons const& primaryelectrons, aod::TrackAssoc const& trackIndices, aod::EMTOFNSigmas const& emtofs, aod::EMMLPIDs const& emmlpids) { + for (const auto& emtof : emtofs) { + mapTOFNsigmaReassociated[std::make_pair(emtof.collisionId(), emtof.trackId())] = emtof.tofNSigmaElRecalculated(); + mapTOFBetaReassociated[std::make_pair(emtof.collisionId(), emtof.trackId())] = emtof.betaRecalculated(); + } + for (const auto& emmlpid : emmlpids) { + mapProbaEl[std::make_pair(emmlpid.collisionId(), emmlpid.trackId())] = emmlpid.bdtScore(); + } + std::unordered_map pfb_map; // map track.globalIndex -> prefilter bit for (const auto& collision : collisions) { @@ -1350,9 +1559,15 @@ struct prefilterPrimaryElectron { if (!checkTrack(collision, track)) { continue; } + if (!isElectron(collision, track)) { + continue; + } if (fillQAHistogram) { fRegistry.fill(HIST("Track/hPt"), track.pt()); fRegistry.fill(HIST("Track/hEtaPhi"), track.phi(), track.eta()); + fRegistry.fill(HIST("Track/hTPCNsigmaEl"), track.tpcInnerParam(), track.tpcNSigmaEl()); + fRegistry.fill(HIST("Track/hTOFNsigmaEl"), track.tpcInnerParam(), mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]); + fRegistry.fill(HIST("Track/hProbElBDT"), track.tpcInnerParam(), mapProbaEl[std::make_pair(collision.globalIndex(), track.globalIndex())]); } if (track.sign() > 0) { posTracks_per_coll.emplace_back(track); @@ -1391,11 +1606,6 @@ struct prefilterPrimaryElectron { fRegistry.fill(HIST("Pair/before/uls/hMvsPhiV"), phiv, v12.M()); fRegistry.fill(HIST("Pair/before/uls/hMvsPt"), v12.M(), v12.Pt()); } - if (v12.M() < max_mee_vec.at(static_cast(max_mee_vec.size()) - 1)) { - if (fillQAHistogram) { - fRegistry.fill(HIST("Track/hTPCNsigmaEl"), ele.tpcInnerParam(), ele.tpcNSigmaEl()); - } - } for (int i = 0; i < static_cast(max_mee_vec.size()); i++) { if (v12.M() < max_mee_vec.at(i)) { pfb_map[empos.globalIndex()] |= (uint8_t(1) << (static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_20MeV) + i)); @@ -1438,11 +1648,6 @@ struct prefilterPrimaryElectron { fRegistry.fill(HIST("Pair/before/uls/hMvsPhiV"), phiv, v12.M()); fRegistry.fill(HIST("Pair/before/uls/hMvsPt"), v12.M(), v12.Pt()); } - if (v12.M() < max_mee_vec.at(static_cast(max_mee_vec.size()) - 1)) { - if (fillQAHistogram) { - fRegistry.fill(HIST("Track/hTPCNsigmaEl"), pos.tpcInnerParam(), pos.tpcNSigmaEl()); - } - } for (int i = 0; i < static_cast(max_mee_vec.size()); i++) { if (v12.M() < max_mee_vec.at(i)) { pfb_map[emele.globalIndex()] |= (uint8_t(1) << (static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_20MeV) + i)); @@ -1556,8 +1761,16 @@ struct prefilterPrimaryElectron { } PROCESS_SWITCH(prefilterPrimaryElectron, processPrefilter_TTCA, "process prefilter with TTCA", false); - void processPrefilter_SA(MyCollisions const& collisions, aod::BCsWithTimestamps const&, MyFilteredTracks const&, aod::EMPrimaryElectrons const& primaryelectrons) + void processPrefilter_SA(MyCollisions const& collisions, aod::BCsWithTimestamps const&, MyFilteredTracks const&, aod::EMPrimaryElectrons const& primaryelectrons, aod::EMTOFNSigmas const& emtofs, aod::EMMLPIDs const& emmlpids) { + for (const auto& emtof : emtofs) { + mapTOFNsigmaReassociated[std::make_pair(emtof.collisionId(), emtof.trackId())] = emtof.tofNSigmaElRecalculated(); + mapTOFBetaReassociated[std::make_pair(emtof.collisionId(), emtof.trackId())] = emtof.betaRecalculated(); + } + for (const auto& emmlpid : emmlpids) { + mapProbaEl[std::make_pair(emmlpid.collisionId(), emmlpid.trackId())] = emmlpid.bdtScore(); + } + std::unordered_map pfb_map; // map track.globalIndex -> prefilter bit for (const auto& collision : collisions) { @@ -1577,18 +1790,30 @@ struct prefilterPrimaryElectron { if (!checkTrack(collision, pos)) { // track cut is applied to loose sample continue; } + if (!isElectron(collision, pos)) { + continue; + } if (fillQAHistogram) { fRegistry.fill(HIST("Track/hPt"), pos.pt()); fRegistry.fill(HIST("Track/hEtaPhi"), pos.phi(), pos.eta()); + fRegistry.fill(HIST("Track/hTPCNsigmaEl"), pos.tpcInnerParam(), pos.tpcNSigmaEl()); + fRegistry.fill(HIST("Track/hTOFNsigmaEl"), pos.tpcInnerParam(), mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), pos.globalIndex())]); + fRegistry.fill(HIST("Track/hProbElBDT"), pos.tpcInnerParam(), mapProbaEl[std::make_pair(collision.globalIndex(), pos.globalIndex())]); } } for (const auto& neg : negTracks_per_coll) { if (!checkTrack(collision, neg)) { // track cut is applied to loose sample continue; } + if (!isElectron(collision, neg)) { + continue; + } if (fillQAHistogram) { fRegistry.fill(HIST("Track/hPt"), neg.pt()); fRegistry.fill(HIST("Track/hEtaPhi"), neg.phi(), neg.eta()); + fRegistry.fill(HIST("Track/hTPCNsigmaEl"), neg.tpcInnerParam(), neg.tpcNSigmaEl()); + fRegistry.fill(HIST("Track/hTOFNsigmaEl"), neg.tpcInnerParam(), mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), neg.globalIndex())]); + fRegistry.fill(HIST("Track/hProbElBDT"), neg.tpcInnerParam(), mapProbaEl[std::make_pair(collision.globalIndex(), neg.globalIndex())]); } } @@ -1597,6 +1822,9 @@ struct prefilterPrimaryElectron { if (!checkTrack(collision, ele)) { // track cut is applied to loose sample continue; } + if (!isElectron(collision, ele)) { + continue; + } if (empos.trackId() == ele.globalIndex()) { continue; } @@ -1609,11 +1837,6 @@ struct prefilterPrimaryElectron { fRegistry.fill(HIST("Pair/before/uls/hMvsPhiV"), phiv, v12.M()); fRegistry.fill(HIST("Pair/before/uls/hMvsPt"), v12.M(), v12.Pt()); } - if (v12.M() < max_mee_vec.at(static_cast(max_mee_vec.size()) - 1)) { - if (fillQAHistogram) { - fRegistry.fill(HIST("Track/hTPCNsigmaEl"), ele.tpcInnerParam(), ele.tpcNSigmaEl()); - } - } for (int i = 0; i < static_cast(max_mee_vec.size()); i++) { if (v12.M() < max_mee_vec.at(i)) { pfb_map[empos.globalIndex()] |= (uint8_t(1) << (static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_20MeV) + i)); @@ -1631,6 +1854,9 @@ struct prefilterPrimaryElectron { if (!checkTrack(collision, pos)) { // track cut is applied to loose sample continue; } + if (!isElectron(collision, pos)) { + continue; + } if (emele.trackId() == pos.globalIndex()) { continue; } @@ -1643,11 +1869,6 @@ struct prefilterPrimaryElectron { fRegistry.fill(HIST("Pair/before/uls/hMvsPhiV"), phiv, v12.M()); fRegistry.fill(HIST("Pair/before/uls/hMvsPt"), v12.M(), v12.Pt()); } - if (v12.M() < max_mee_vec.at(static_cast(max_mee_vec.size()) - 1)) { - if (fillQAHistogram) { - fRegistry.fill(HIST("Track/hTPCNsigmaEl"), pos.tpcInnerParam(), pos.tpcNSigmaEl()); - } - } for (int i = 0; i < static_cast(max_mee_vec.size()); i++) { if (v12.M() < max_mee_vec.at(i)) { pfb_map[emele.globalIndex()] |= (uint8_t(1) << (static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_20MeV) + i)); @@ -1665,6 +1886,9 @@ struct prefilterPrimaryElectron { if (!checkTrack(collision, pos)) { // track cut is applied to loose sample continue; } + if (!isElectron(collision, pos)) { + continue; + } if (empos.trackId() == pos.globalIndex()) { continue; } @@ -1684,6 +1908,9 @@ struct prefilterPrimaryElectron { if (!checkTrack(collision, ele)) { // track cut is applied to loose sample continue; } + if (!isElectron(collision, ele)) { + continue; + } if (emele.trackId() == ele.globalIndex()) { continue; } diff --git a/PWGEM/Dilepton/TableProducer/skimmerPrimaryTrack.cxx b/PWGEM/Dilepton/TableProducer/skimmerPrimaryTrack.cxx index 2460adf58d5..b217cae9548 100644 --- a/PWGEM/Dilepton/TableProducer/skimmerPrimaryTrack.cxx +++ b/PWGEM/Dilepton/TableProducer/skimmerPrimaryTrack.cxx @@ -18,7 +18,7 @@ #include "Common/Core/TableHelper.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/CollisionAssociationTables.h" -#include "Common/DataModel/PIDResponseITS.h" +// #include "Common/DataModel/PIDResponseITS.h" #include "CCDB/BasicCCDBManager.h" #include "CommonConstants/PhysicsConstants.h" diff --git a/PWGEM/Dilepton/Tasks/eventQC.cxx b/PWGEM/Dilepton/Tasks/eventQC.cxx index 0b1f4b3e0ef..c21d08c6248 100644 --- a/PWGEM/Dilepton/Tasks/eventQC.cxx +++ b/PWGEM/Dilepton/Tasks/eventQC.cxx @@ -14,14 +14,11 @@ // This code is for event QC for PWG-EM. // Please write to: daiki.sekihata@cern.ch -// #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" - #include "Common/Core/RecoDecay.h" #include "Common/Core/Zorro.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/PIDResponseITS.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/Qvectors.h" From b5473280d43343b4255cf60ea3b1edfcec81fbdf Mon Sep 17 00:00:00 2001 From: "Q.Y. Xia" <91366503+huinaibing@users.noreply.github.com> Date: Mon, 9 Mar 2026 04:19:55 +0800 Subject: [PATCH 216/347] [PWGCF] Use ITS only track for mean pt calculation (#15290) --- PWGCF/Flow/Tasks/pidFlowPtCorr.cxx | 562 +++++++++++++++++++++-------- 1 file changed, 412 insertions(+), 150 deletions(-) diff --git a/PWGCF/Flow/Tasks/pidFlowPtCorr.cxx b/PWGCF/Flow/Tasks/pidFlowPtCorr.cxx index ea938dd55a8..cb0fe7b46d0 100644 --- a/PWGCF/Flow/Tasks/pidFlowPtCorr.cxx +++ b/PWGCF/Flow/Tasks/pidFlowPtCorr.cxx @@ -112,13 +112,20 @@ struct PidFlowPtCorr { } dcaCutOpts; O2_DEFINE_CONFIGURABLE(cfgNSigmapid, std::vector, (std::vector{3, 3, 3, 9, 9, 9, 9, 9, 9}), "tpc, tof and its NSigma for Pion Proton Kaon") - O2_DEFINE_CONFIGURABLE(cfgMeanPtcent, std::vector, (std::vector{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}), "mean Pt in different cent bin") struct : ConfigurableGroup { std::string prefix = "correctionPathOpts"; O2_DEFINE_CONFIGURABLE(cfgAcceptancePath, std::vector, (std::vector{"Users/f/fcui/NUA/NUAREFPartical", "Users/f/fcui/NUA/NUAK0s", "Users/f/fcui/NUA/NUALambda", "Users/f/fcui/NUA/NUAXi", "Users/f/fcui/NUA/NUAOmega"}), "CCDB path to acceptance object") + O2_DEFINE_CONFIGURABLE(cfgEfficiencyPath, std::vector, (std::vector{"PathtoRef"}), "CCDB path to efficiency object") O2_DEFINE_CONFIGURABLE(cfgEfficiency2DPath, std::vector, (std::vector{"PathtoRef"}), "CCDB path to efficiency(pt, cent) object") + O2_DEFINE_CONFIGURABLE(cfgPidEfficiencyPath, std::vector, (std::vector{"PathtoRef"}), "Pi, Ka, Pr, CCDB path to PID efficiency(pt, cent) object") + + O2_DEFINE_CONFIGURABLE(cfgEfficiencyPath4ITSOnly, std::vector, (std::vector{"PathtoRef"}), "CCDB path to efficiency object") + O2_DEFINE_CONFIGURABLE(cfgEfficiency2DPath4ITSOnly, std::vector, (std::vector{"PathtoRef"}), "CCDB path to efficiency(pt, cent) object") + O2_DEFINE_CONFIGURABLE(cfgPidEfficiencyPath4ITSOnly, std::vector, (std::vector{"PathtoRef"}), "Pi, Ka, Pr, CCDB path to PID efficiency(pt, cent) object") + + O2_DEFINE_CONFIGURABLE(cfgNUEOption, int, 1, "do NUE, 1: use 1D eff, 2: Using Eff(pt, cent), 3: use pid 1D eff, 4: use pid 2D eff, other: dont do NUE") } correctionPathOpts; O2_DEFINE_CONFIGURABLE(cfgRunNumbers, std::vector, (std::vector{544095, 544098, 544116, 544121, 544122, 544123, 544124}), "Preconfigured run numbers") @@ -126,15 +133,13 @@ struct PidFlowPtCorr { O2_DEFINE_CONFIGURABLE(cfgFlowNbootstrap, int, 30, "Number of subsamples for bootstrap") // switch - O2_DEFINE_CONFIGURABLE(cfgDoAccEffCorr, bool, false, "do acc and eff corr") O2_DEFINE_CONFIGURABLE(cfgDoLocDenCorr, bool, false, "do local density corr") O2_DEFINE_CONFIGURABLE(cfgOutputNUAWeights, bool, false, "Fill and output NUA weights") - O2_DEFINE_CONFIGURABLE(cfgOutputrunbyrun, bool, false, "Fill and output NUA weights run by run") + O2_DEFINE_CONFIGURABLE(cfgOutputrunbyrun, bool, false, "OPEN IF USE FUNCTION(fillcorrectiongraph) Fill and output NUA weights run by run") O2_DEFINE_CONFIGURABLE(cfgOutPutMC, bool, false, "Fill MC graphs, note that if the processMCgen is open,this MUST be open") O2_DEFINE_CONFIGURABLE(cfgOutputLocDenWeights, bool, false, "Fill and output local density weights") - O2_DEFINE_CONFIGURABLE(cfgOutputQA, bool, false, "do QA") + O2_DEFINE_CONFIGURABLE(cfgOutputQA, bool, false, "OPEN IF USE FUNCTION(detectorPidQa) do QA") - O2_DEFINE_CONFIGURABLE(cfgUsePtCentNUECorr, bool, true, "do NUA NUE, Using Eff(pt, cent) to do NUE") O2_DEFINE_CONFIGURABLE(cfgDebugMyCode, bool, false, "output some graph for code debug") O2_DEFINE_CONFIGURABLE(cfgOutPutPtSpectra, bool, false, "output pt spectra for data, MC and RECO") @@ -184,7 +189,7 @@ struct PidFlowPtCorr { // filter and using // data Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; - Filter trackFilter = (nabs(aod::track::eta) < trkQualityOpts.cfgCutEta.value) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)); + Filter trackFilter = (nabs(aod::track::eta) < trkQualityOpts.cfgCutEta.value); using TracksPID = soa::Join; // data tracks filter @@ -226,12 +231,11 @@ struct PidFlowPtCorr { // define global variables GFW* fGFW = new GFW(); // GFW class used from main src std::vector corrconfigs; + std::vector cfgAcceptance; - std::vector cfgEfficiency; - std::vector cfgEfficiency2D; + std::vector cfgMultPVCutPara; std::vector cfgNSigma; - std::vector cfgMeanPt; std::vector runNumbers; std::map>> th1sList; std::map>> th3sList; @@ -263,9 +267,11 @@ struct PidFlowPtCorr { funcNumber }; + // graphs for NUE / NUA std::vector mAcceptance; - std::vector mEfficiency; - std::vector mEfficiency2D; + std::vector mEfficiency; + std::vector mEfficiency4ITSOnly; + bool correctionsLoaded = false; TF1* fMultPVCutLow = nullptr; @@ -316,10 +322,8 @@ struct PidFlowPtCorr { ccdb->setCreatedNotAfter(cfgnolaterthan.value); cfgAcceptance = correctionPathOpts.cfgAcceptancePath.value; - cfgEfficiency = correctionPathOpts.cfgEfficiencyPath.value; - cfgEfficiency2D = correctionPathOpts.cfgEfficiency2DPath.value; + cfgNSigma = cfgNSigmapid; - cfgMeanPt = cfgMeanPtcent; cfgMultPVCutPara = evtSeleOpts.cfgMultPVCut; // Set the pt, mult and phi Axis; @@ -353,6 +357,7 @@ struct PidFlowPtCorr { registry.add("hEtaPhiVtxzREF", "", {HistType::kTH3D, {cfgaxisPhi, cfgaxisEta, {20, -10, 10}}}); registry.add("hNTracksPVvsCentrality", "", {HistType::kTH2D, {{5000, 0, 5000}, axisMultiplicity}}); + registry.add("hNchUnCorrectedVSNchCorrected", "", {HistType::kTH2D, {cfgaxisNch, cfgaxisNch}}); runNumbers = cfgRunNumbers; // TPC vs TOF vs its, comparation graphs, check the PID performance in difference pt if (cfgOutputQA) { @@ -396,6 +401,8 @@ struct PidFlowPtCorr { // hist for NUE correction registry.add("correction/hPtCentMcRec", "", {HistType::kTH2D, {cfgaxisPt, axisMultiplicity}}); registry.add("correction/hPtCentMcGen", "", {HistType::kTH2D, {cfgaxisPt, axisMultiplicity}}); + // ITS only + registry.add("correction/hPtCentMcRec4ITSOnly", "", {HistType::kTH2D, {cfgaxisPt, axisMultiplicity}}); // hist for Pi eff registry.add("correction/hPtCentMcRecPi", "", {HistType::kTH2D, {cfgaxisPt, axisMultiplicity}}); @@ -604,6 +611,13 @@ struct PidFlowPtCorr { corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiKaN08 {3} poiKaP08 {-3}", "KaKa08gap22", kFALSE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPrN08 {3} poiPrP08 {-3}", "PrPr08gap22", kFALSE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPiN {2} refP {-2}", "Pion0gap22a", kFALSE)); // 35 + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPiP {2} refN {-2}", "Pion0gap22b", kFALSE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiKaN {2} refP {-2}", "Kaon0gap22a", kFALSE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiKaP {2} refN {-2}", "Kaon0gap22b", kFALSE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPrN {2} refP {-2}", "Prot0gap22a", kFALSE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPrP {2} refN {-2}", "Prot0gap22b", kFALSE)); // 40 + fGFW->CreateRegions(); // finalize the initialization // used for event selection @@ -617,16 +631,10 @@ struct PidFlowPtCorr { fT0AV0ASigma = new TF1("fT0AV0ASigma", "[0]+[1]*x+[2]*x*x+[3]*x*x*x+[4]*x*x*x*x", 0, 200000); fT0AV0ASigma->SetParameters(463.4144, 6.796509e-02, -9.097136e-07, 7.971088e-12, -2.600581e-17); - // fWeight output - if (cfgOutputNUAWeights) { - fWeightsREF->setPtBins(nPtBins, &(axisPt.binEdges)[0]); - fWeightsREF->init(true, false); - } - std::vector pTEffBins = {0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.4, 1.8, 2.2, 2.6, 3.0}; hFindPtBin = new TH1D("hFindPtBin", "hFindPtBin", pTEffBins.size() - 1, &pTEffBins[0]); funcEff.resize(pTEffBins.size() - 1); - // LHC24g3 Eff + std::vector f1p0 = cfgTrackDensityP0; std::vector f1p1 = cfgTrackDensityP1; for (uint ifunc = 0; ifunc < pTEffBins.size() - 1; ifunc++) { @@ -967,78 +975,217 @@ struct PidFlowPtCorr { } // end load NUA - // load NUE 1d - if (cfgEfficiency.size() == static_cast(nspecies)) { - for (int i = 0; i <= nspecies - 1; i++) { - mEfficiency.push_back(ccdb->getForTimeStamp(cfgEfficiency[i], timestamp)); - } - if (mEfficiency.size() == static_cast(nspecies)) - LOGF(info, "Loaded efficiency histogram"); - else - LOGF(fatal, "Could not load efficiency histogram"); - } - // end load NUE1d + /// @note dont modify load NUA!, just modify NUE + // here needs to load 2 NUE graph selected from 6 ccdb path + /// @note when using eff 2D, convert TH1* to (TH2D *) + // pid eff is not available now... + std::vector effPath1D = correctionPathOpts.cfgEfficiencyPath.value; + std::vector effPath2D = correctionPathOpts.cfgEfficiency2DPath.value; + std::vector effPathPid = correctionPathOpts.cfgPidEfficiencyPath.value; + + std::vector effPath1D4ITSOnly = correctionPathOpts.cfgEfficiencyPath4ITSOnly.value; + std::vector effPath2D4ITSOnly = correctionPathOpts.cfgEfficiency2DPath4ITSOnly.value; + std::vector effPathPid4ITSOnly = correctionPathOpts.cfgPidEfficiencyPath4ITSOnly.value; + + switch (correctionPathOpts.cfgNUEOption.value) { + case 1: // use 1D eff + // load 1d eff for global track + if (effPath1D.size() != static_cast(1)) { + LOGF(warning, "eff path 1d size != 1, skip eff 1d load"); + break; + } + mEfficiency.push_back(ccdb->getForTimeStamp(effPath1D[0], timestamp)); + if (mEfficiency.size() == static_cast(1)) { + LOGF(info, "Loaded efficiency histogram"); + } else { + LOGF(fatal, "Could not load efficiency histogram"); + } + // end load 1d eff for global track - // load NUE 2D - if (cfgEfficiency2D.size() == static_cast(nspecies)) { - for (int i = 0; i <= nspecies - 1; i++) { - mEfficiency2D.push_back(ccdb->getForTimeStamp(cfgEfficiency2D[i], timestamp)); - } - if (mEfficiency2D.size() == static_cast(nspecies)) - LOGF(info, "Loaded efficiency2D histogram"); - else - LOGF(fatal, "Could not load efficiency2D histogram"); - } - // end load NUE 2D + // load 1d eff for ITS only + if (effPath1D4ITSOnly.size() != static_cast(1)) { + LOGF(warning, "eff path for its 1d size != 1, skip its eff 1d load"); + break; + } + mEfficiency4ITSOnly.push_back(ccdb->getForTimeStamp(effPath1D4ITSOnly[0], timestamp)); + if (mEfficiency4ITSOnly.size() == static_cast(1)) { + LOGF(info, "Loaded ITS only efficiency histogram"); + } else { + LOGF(fatal, "Could not load ITS only efficiency histogram"); + } + // end load 1d eff for its only + + break; + // end use 1d eff + + case 2: // Use 2D eff + // load 2d eff for global track + if (effPath2D.size() != static_cast(1)) { + LOGF(warning, "eff path 2d size != 1, skip eff 2d load"); + break; + } + mEfficiency.push_back(ccdb->getForTimeStamp(effPath2D[0], timestamp)); + if (mEfficiency.size() == static_cast(1)) { + LOGF(info, "Loaded 2D efficiency histogram"); + } else { + LOGF(fatal, "Could not load 2D efficiency histogram"); + } + // end load 2d eff for global track + + // load 2d eff for ITS only + if (effPath2D4ITSOnly.size() != static_cast(1)) { + LOGF(warning, "eff path for its 2d size != 1, skip its eff 2d load"); + break; + } + mEfficiency4ITSOnly.push_back(ccdb->getForTimeStamp(effPath2D4ITSOnly[0], timestamp)); + if (mEfficiency4ITSOnly.size() == static_cast(1)) { + LOGF(info, "Loaded ITS only 2D efficiency histogram"); + } else { + LOGF(fatal, "Could not load ITS only 2D efficiency histogram"); + } + // end load 2d eff for its only + + break; + // end use 2d eff + + case 3: // use pid 1D eff + // load pid 1d eff for ITS + global track + if (effPathPid.size() != static_cast(3)) { + LOGF(warning, "eff path pid 1d size != 3, skip pid eff 1d load"); + break; + } + for (int i = 0; i < 3; i++) { + mEfficiency.push_back(ccdb->getForTimeStamp(effPathPid[i], timestamp)); + } + if (mEfficiency.size() == static_cast(3)) { + LOGF(info, "Loaded PID efficiency histogram"); + } else { + LOGF(fatal, "Could not load PID efficiency histogram"); + } + // end load pid 1d eff for ITS + global track + + // load pid 1d eff for ITS only + if (effPathPid4ITSOnly.size() != static_cast(3)) { + LOGF(warning, "eff path for its pid 1d size != 3, skip its pid eff 1d load"); + break; + } + for (int i = 0; i < 3; i++) { + mEfficiency4ITSOnly.push_back(ccdb->getForTimeStamp(effPathPid4ITSOnly[i], timestamp)); + } + if (mEfficiency4ITSOnly.size() == static_cast(3)) { + LOGF(info, "Loaded ITS only PID efficiency histogram"); + } else { + LOGF(fatal, "Could not load ITS only PID efficiency histogram"); + } + // end load pid 1d eff for its only + + break; + // end use pid 1d eff + + default: // not do NUE + break; + } // end switch load eff correctionsLoaded = true; } template - bool setCurrentParticleWeights(float& weight_nue, float& weight_nua, TrackObject& track, float vtxz, int ispecies) + bool setParticleNUAWeight(float& weight_nua, TrackObject& track, float vtxz) { - float eff = 1.; - int nspecies = 1; - if (mEfficiency.size() == static_cast(nspecies)) - eff = mEfficiency[ispecies]->GetBinContent(mEfficiency[ispecies]->FindBin(track.pt())); - else - eff = 1.0; - if (eff == 0) { - return false; - } - weight_nue = 1. / eff; - if (mAcceptance.size() == static_cast(nspecies)) - weight_nua = mAcceptance[ispecies]->getNUA(track.phi(), track.eta(), vtxz); + if (mAcceptance.size() == static_cast(1)) + weight_nua = mAcceptance[0]->getNUA(track.phi(), track.eta(), vtxz); else weight_nua = 1; return true; } + /** + * @brief Set the Particle Nue Weight, for global track and ITS track, use different eff path + * + * @tparam TrackObject + * @param weight_nue + * @param track + * @param cent + * @param isGlobalTrack + * @return true weight setted succesfully, note that weight == 1 also return true; + * @return false eff got from graph == 0 + */ template - bool setCurrentParticleWeights(float& weight_nue, float& weight_nua, TrackObject& track, float vtxz, int ispecies, double cent) + bool setParticleNUEWeight(float& weight_nue, TrackObject& track, double cent, bool isGlobalTrack) { float eff = 1.; - int nspecies = 1; - // eff 2d - if (mEfficiency2D.size() == static_cast(nspecies)) { - int ptBin = mEfficiency2D[ispecies]->GetXaxis()->FindBin(track.pt()); - int centBin = mEfficiency2D[ispecies]->GetYaxis()->FindBin(cent); - eff = mEfficiency2D[ispecies]->GetBinContent(ptBin, centBin); - } - if (eff == 0) { - return false; + uint64_t sizeOfEffVec = mEfficiency.size(); + uint64_t sizeOfEffVec4ITS = mEfficiency4ITSOnly.size(); + + TH2* eff2D = 0; + TH2* eff2D4ITS = 0; + + /// @note 1. size check 2. load eff 3. dividezero check + switch (correctionPathOpts.cfgNUEOption.value) { + case 1: // 1d + if (sizeOfEffVec != 1) + break; + if (sizeOfEffVec4ITS != 1) + break; + + if (isGlobalTrack) + eff = mEfficiency[0]->GetBinContent(mEfficiency[0]->FindBin(track.pt())); + else + eff = mEfficiency4ITSOnly[0]->GetBinContent(mEfficiency4ITSOnly[0]->FindBin(track.pt())); + + if (eff == 0.) + return false; + + break; + // end 1d + + case 2: // 2d + if (sizeOfEffVec != 1) + break; + if (sizeOfEffVec4ITS != 1) + break; + + eff2D = dynamic_cast(mEfficiency[0]); + eff2D4ITS = dynamic_cast(mEfficiency4ITSOnly[0]); + + if (!eff2D || !eff2D4ITS) { + LOGF(warning, "failed while converting TH1 to TH2! skip eff apply"); + break; + } + + if (isGlobalTrack) { + int ptBin = eff2D->GetXaxis()->FindBin(track.pt()); + int centBin = eff2D->GetYaxis()->FindBin(cent); + eff = eff2D->GetBinContent(ptBin, centBin); + } else { + int ptBin = eff2D4ITS->GetXaxis()->FindBin(track.pt()); + int centBin = eff2D4ITS->GetYaxis()->FindBin(cent); + eff = eff2D4ITS->GetBinContent(ptBin, centBin); + } + + if (eff == 0.) + return false; + + break; + // end 2d + + /// @todo add pid NUE eff + case 3: // pid + if (sizeOfEffVec != 3) + break; + if (sizeOfEffVec4ITS != 3) + break; + + break; + // end pid + + default: + break; } - weight_nue = 1. / eff; - // end eff 2d - // acc - if (mAcceptance.size() == static_cast(nspecies)) - weight_nua = mAcceptance[ispecies]->getNUA(track.phi(), track.eta(), vtxz); - else - weight_nua = 1; + weight_nue = 1. / eff; return true; - // end acc } /** @@ -1046,8 +1193,7 @@ struct PidFlowPtCorr { * @note include * 1. eta cut * 2. pt cut - * 3. primaryparticle check - * 4. stable partccle + * 3. stable partccle * * @tparam mcParticle * @param particle @@ -1065,9 +1211,6 @@ struct PidFlowPtCorr { return false; if (particle.pt() > trkQualityOpts.cfgCutPtMax.value) return false; - // primary particle - if (!particle.isPhysicalPrimary()) - return false; // stable particle if (!isStable(particle.pdgCode())) return false; @@ -1076,16 +1219,12 @@ struct PidFlowPtCorr { } /** - * @brief track selection + * @brief global track selection, cut for specified detector is not include * @note include: 1. dcaxy - * 2. its ncls - * 3. tpc cross row - * 4. tpc ncls - * 5. pt cut - * 6. eta - * 7. tpc chi2 - * 8. dcaz - * 9. its CHI2 + * 2. pt cut + * 3. eta + * 4. dcaz + * * * @tparam TTrack * @param track @@ -1093,33 +1232,45 @@ struct PidFlowPtCorr { * @return false reject track */ template - bool trackSelected(TTrack& track) + bool trackSelectedGlobal(TTrack& track) { // dca xy cut // note that z cut is in filter if (dcaCutOpts.cfgDCAxyNSigma && (std::fabs(track.dcaXY()) > dcaCutOpts.fPtDepDCAxy->Eval(track.pt()))) return false; - // its ncls cut - if (track.itsNCls() <= trkQualityOpts.cfgITSNCls.value) - return false; - // tpc crossedrows cut - if (track.tpcNClsCrossedRows() <= trkQualityOpts.cfgTPCCrossedRows.value) - return false; - // tpc ncls cut - if (track.tpcNClsFound() <= trkQualityOpts.cfgTPCNCls.value) - return false; + // pt if (!((track.pt() > trkQualityOpts.cfgCutPtMin.value) && (track.pt() < trkQualityOpts.cfgCutPtMax.value))) return false; + // eta if (std::fabs(track.eta()) > trkQualityOpts.cfgCutEta.value) return false; - // tpc chi2 - if (track.tpcChi2NCl() > cfgCutChi2prTPCcls) - return false; + // dca z if (std::fabs(track.dcaZ()) > dcaCutOpts.cfgCutDCAz.value) return false; + + return true; + } + + /** + * @brief cut for ITS, include: + * 1. its n cluster + * 2. its chi2 + * + * @tparam TTrack + * @param track + * @return true + * @return false + */ + template + bool trackSelected4ITS(TTrack& track) + { + // its ncls cut + if (track.itsNCls() <= trkQualityOpts.cfgITSNCls.value) + return false; + // its chi2 if (track.itsChi2NCl() > trkQualityOpts.cfgITSChi2NDF.value) return false; @@ -1127,6 +1278,33 @@ struct PidFlowPtCorr { return true; } + /** + * @brief cut for TPC, include + * 1. TPC cross rows + * 2. tpc n cluster + * 3. tpc chi2 + * + * @tparam TTrack + * @param track + * @return true + * @return false + */ + template + bool trackSelected4TPC(TTrack& track) + { + // tpc crossedrows cut + if (track.tpcNClsCrossedRows() <= trkQualityOpts.cfgTPCCrossedRows.value) + return false; + // tpc ncls cut + if (track.tpcNClsFound() <= trkQualityOpts.cfgTPCNCls.value) + return false; + // tpc chi2 + if (track.tpcChi2NCl() > cfgCutChi2prTPCcls) + return false; + + return true; + } + /** * @brief fill eventCount for different function * @@ -1335,26 +1513,71 @@ struct PidFlowPtCorr { v4 = funcV4->Eval(cent); } // cfgDoLocDenCorr - float weff = 1; - float wacc = 1; double ptSum = 0; double ptSumw2 = 0; double nch = 0; double nchSquare = 0; double ptSquareSum = 0; - // fill GFW ref flow + double nchCorrectedPassed = 0; + double nchPassedSelection = 0; + + if (cfgDebugMyCode) { + LOGF(info, "===================================="); + } + + /// @note calculate pt + /// use ITS only for (const auto& track : tracks) { - if (cfgDoAccEffCorr) { - if (cfgUsePtCentNUECorr) { - // true - if (!setCurrentParticleWeights(weff, wacc, track, vtxz, 0, cent)) - continue; - } else { - // false - if (!setCurrentParticleWeights(weff, wacc, track, vtxz, 0)) - continue; - } // cfgUsePtCentNUECorr - } // cfgDoAccEffCorr + float weff = 1; + + // do nue + setParticleNUEWeight(weff, track, cent, false); + // end do nue + + // track cut ITS only + if (!trackSelectedGlobal(track)) + continue; + if (!trackSelected4ITS(track)) + continue; + if (track.hasTPC()) + continue; + // end track cut its only + + // calculate ncharged(nch with weight) and pt + if (std::fabs(track.eta()) < trkQualityOpts.cfgRangeEta.value) { + nch += weff; + nchSquare += weff * weff; + ptSum += weff * track.pt(); + ptSumw2 += weff * weff * track.pt(); + ptSquareSum += weff * weff * track.pt() * track.pt(); + } + // end calculate nch and pt + + nchCorrectedPassed += weff; + nchPassedSelection += 1; + + if (weff == 1. && cfgDebugMyCode) { + LOGF(info, "weff is 1, if nue opt is open and this message appears a lot, check!"); + } + } + // end pt calculation using ITS only + + if (cfgDebugMyCode) { + LOGF(info, Form("its only track num %f", nchPassedSelection)); + } + + int totalGlobalTrack = 0; + + // fill v2 flow + // use global track + for (const auto& track : tracks) { + float weff = 1; + float wacc = 1; + + // do NUE && NUA + setParticleNUAWeight(wacc, track, vtxz); + setParticleNUEWeight(weff, track, cent, true); + // end do NUE && NUA if (cfgDoLocDenCorr) { bool withinPtRef = (trkQualityOpts.cfgCutPtMin.value < track.pt()) && (track.pt() < trkQualityOpts.cfgCutPtMax.value); @@ -1412,10 +1635,28 @@ struct PidFlowPtCorr { // end thn wacc graph } // cfgDebugMycode - // track cut - if (!trackSelected(track)) + // track cut, global + ITS + TPC + if (!trackSelectedGlobal(track)) + continue; + if (!track.hasITS()) + continue; + if (!track.hasTPC()) continue; + if (!trackSelected4ITS(track)) + continue; + if (!trackSelected4TPC(track)) + continue; + // end track cut + totalGlobalTrack++; + + if (cfgDebugMyCode && weff == 1.) { + LOGF(info, "weff for global track is 1, if NUE is open and this appears a lot, check!"); + } + + if (cfgDebugMyCode && wacc == 1.) { + LOGF(info, "wacc for global track is 1, if NUA is open and this appears alot, check!"); + } // fill QA hist registry.fill(HIST("hPhi"), track.phi()); @@ -1446,11 +1687,6 @@ struct PidFlowPtCorr { registry.fill(HIST("ptSpectra/hPtCentDataNegEtaNegCh"), track.pt(), cent); } - // track pt cut - if (!((track.pt() > trkQualityOpts.cfgCutPtMin.value) && (track.pt() < trkQualityOpts.cfgCutPtMax.value))) - continue; - // end track pt cut - // fill GFW // bit mask 1: fill CHARGED PARTICLES fGFW->Fill(track.eta(), 0, track.phi(), wacc * weff, 1); //(eta, ptbin, phi, wacc*weff, bitmask) @@ -1473,20 +1709,13 @@ struct PidFlowPtCorr { // fill PROTONS and overlap Protons } // end fill GFW + } // end track loop for v2 calculation - if (cfgOutputNUAWeights) - fWeightsREF->fill(track.phi(), track.eta(), vtxz, track.pt(), cent, 0); + if (cfgDebugMyCode) { + LOGF(info, Form("global track num %d", totalGlobalTrack)); + } - // calculate ncharged(nch with weight) and pt - if (std::fabs(track.eta()) < trkQualityOpts.cfgRangeEta.value) { - nch += weff; - nchSquare += weff * weff; - ptSum += weff * track.pt(); - ptSumw2 += weff * weff * track.pt(); - ptSquareSum += weff * weff * track.pt() * track.pt(); - } - // end calculate nch and pt - } // end track loop + registry.fill(HIST("hNchUnCorrectedVSNchCorrected"), nchPassedSelection, nchCorrectedPassed); // fill hist using fGFW if (nch > 0) { @@ -1496,6 +1725,13 @@ struct PidFlowPtCorr { fillFC(MyParticleType::kCharged, corrconfigs.at(3), cent, rndm, "c32"); fillFC(MyParticleType::kCharged, corrconfigs.at(4), cent, rndm, "c34"); + fillFC(MyParticleType::kPion, corrconfigs.at(35), cent, rndm, "c22Full"); + fillFC(MyParticleType::kPion, corrconfigs.at(36), cent, rndm, "c22Full"); + fillFC(MyParticleType::kKaon, corrconfigs.at(37), cent, rndm, "c22Full"); + fillFC(MyParticleType::kKaon, corrconfigs.at(38), cent, rndm, "c22Full"); + fillFC(MyParticleType::kProton, corrconfigs.at(39), cent, rndm, "c22Full"); + fillFC(MyParticleType::kProton, corrconfigs.at(40), cent, rndm, "c22Full"); + fillFC(MyParticleType::kPion, corrconfigs.at(5), cent, rndm, "c22"); fillFC(MyParticleType::kPion, corrconfigs.at(6), cent, rndm, "c22"); fillFC(MyParticleType::kKaon, corrconfigs.at(7), cent, rndm, "c22"); @@ -1626,7 +1862,15 @@ struct PidFlowPtCorr { // loop all the track for (const auto& track : tracks) { // track cut - if (!trackSelected(track)) + if (!trackSelectedGlobal(track)) + continue; + if (!track.hasITS()) + continue; + if (!track.hasTPC()) + continue; + if (!trackSelected4ITS(track)) + continue; + if (!trackSelected4TPC(track)) continue; // end track cut @@ -1699,7 +1943,15 @@ struct PidFlowPtCorr { // start filling graphs for (const auto& track : tracks) { // track cut - if (!trackSelected(track)) + if (!trackSelectedGlobal(track)) + continue; + if (!track.hasITS()) + continue; + if (!track.hasTPC()) + continue; + if (!trackSelected4ITS(track)) + continue; + if (!trackSelected4TPC(track)) continue; // end track cut @@ -1759,7 +2011,7 @@ struct PidFlowPtCorr { // loop tracks for (const auto& track : tracks) { // track cut - if (!trackSelected(track)) + if (!trackSelectedGlobal(track)) continue; // end track cut @@ -1768,20 +2020,30 @@ struct PidFlowPtCorr { auto mcParticle = track.mcParticle(); // fill graph if (particleSelected(mcParticle)) { - // graph for all particles - registry.fill(HIST("correction/hPtCentMcRec"), track.pt(), cent); - - // identify particle and fill graph - if (isPion(track)) { - registry.fill(HIST("correction/hPtCentMcRecPi"), track.pt(), cent); - } - if (isKaon(track)) { - registry.fill(HIST("correction/hPtCentMcRecKa"), track.pt(), cent); + /// @note global track, fill rec hist + if (track.hasITS() && track.hasTPC() && trackSelected4ITS(track) && trackSelected4TPC(track)) { + // graph for all particles + registry.fill(HIST("correction/hPtCentMcRec"), track.pt(), cent); + + // identify particle and fill graph + if (isPion(track)) { + registry.fill(HIST("correction/hPtCentMcRecPi"), track.pt(), cent); + } + if (isKaon(track)) { + registry.fill(HIST("correction/hPtCentMcRecKa"), track.pt(), cent); + } + if (isProton(track)) { + registry.fill(HIST("correction/hPtCentMcRecPr"), track.pt(), cent); + } + // end identify particle and fill graph } - if (isProton(track)) { - registry.fill(HIST("correction/hPtCentMcRecPr"), track.pt(), cent); + // end global track, fill rec hist + + /// @note ITS track. fill rec hist + if (track.hasITS() && !track.hasTPC() && trackSelected4ITS(track)) { + registry.fill(HIST("correction/hPtCentMcRec4ITSOnly"), track.pt(), cent); } - // end identify particle and fill graph + // end ITS track. fill rec hist } // end fill graph } @@ -1837,7 +2099,7 @@ struct PidFlowPtCorr { // loop mc particles for (const auto& mcParticle : mcParticles) { // fill graph - if (particleSelected(mcParticle)) { + if (particleSelected(mcParticle) && mcParticle.isPhysicalPrimary()) { // graph for all particles registry.fill(HIST("correction/hPtCentMcGen"), mcParticle.pt(), cent); From 90f89f5c7264afd82aeffb39dda37e610ddb7aff Mon Sep 17 00:00:00 2001 From: somabhatta <48771326+somabhatta@users.noreply.github.com> Date: Sun, 8 Mar 2026 21:23:38 +0100 Subject: [PATCH 217/347] [PWGCF] add 2D event selection limits and PID safety cuts (#15304) --- .../Tasks/radialFlowDecorr.cxx | 402 ++++++++++-------- 1 file changed, 223 insertions(+), 179 deletions(-) diff --git a/PWGCF/EbyEFluctuations/Tasks/radialFlowDecorr.cxx b/PWGCF/EbyEFluctuations/Tasks/radialFlowDecorr.cxx index 33b16fb7c06..4f710a0e788 100644 --- a/PWGCF/EbyEFluctuations/Tasks/radialFlowDecorr.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/radialFlowDecorr.cxx @@ -130,7 +130,7 @@ struct RadialFlowDecorr { KNsp }; - const std::vector pidSuffix = {"", "_PiMinus", "_PiPlus", "_PiAll", "_KaMinus", "_KaPlus", "_KaAll", "_AntiPr", "_Pr", "_PrAll"}; + inline static const std::vector pidSuffix = {"", "_PiMinus", "_PiPlus", "_PiAll", "_KaMinus", "_KaPlus", "_KaAll", "_AntiPr", "_Pr", "_PrAll"}; struct PIDMeanSigmaMap { static constexpr int MaxCentBins = 100; @@ -155,10 +155,10 @@ struct RadialFlowDecorr { kpp = 4 }; static constexpr float KinvalidCentrality = -1.0f; - const std::vector etaLw = { + inline static const std::vector etaLw = { -0.8, -0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.1, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7}; - const std::vector etaUp = { + inline static const std::vector etaUp = { 0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.1, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8}; @@ -202,13 +202,20 @@ struct RadialFlowDecorr { Configurable cfgCutPtUpperPID{"cfgCutPtUpperPID", 6.0f, "Higher pT cut for identified particle analysis"}; Configurable cfgCutEta{"cfgCutEta", 0.8f, "absolute Eta cut"}; Configurable cfgNsubsample{"cfgNsubsample", 10, "Number of subsamples"}; - Configurable cfgCentralityChoice{"cfgCentralityChoice", 2, "Which centrality estimator? 1-->FT0C, 2-->FT0M, 3-->FDDM, 4-->FV0A"}; + Configurable cfgCentralityChoice{"cfgCentralityChoice", 1, "Which centrality estimator? 1-->FT0C, 2-->FT0M, 3-->FDDM, 4-->FV0A"}; Configurable cfgEvSelNoSameBunchPileup{"cfgEvSelNoSameBunchPileup", true, "Pileup removal"}; Configurable cfgUseGoodITSLayerAllCut{"cfgUseGoodITSLayerAllCut", true, "Remove time interval with dead ITS zone"}; Configurable cfgIsGoodZvtxFT0VsPV{"cfgIsGoodZvtxFT0VsPV", true, "Good Vertexing cut"}; - Configurable cfgNchPbMax{"cfgNchPbMax", 6000, "Max Nch range for PbPb collisions"}; - Configurable cfgNchOMax{"cfgNchOMax", 600, "Max Nch range for OO collisions"}; + Configurable cfgPupnSig{"cfgPupnSig", 3.0f, "Additional Pileup Cut"}; + Configurable cfgApplySigPupCut{"cfgApplySigPupCut", 0, "nSig Pileup Cut"}; + Configurable cfgApplyLinPupCut{"cfgApplyLinPupCut", 0, "Lin Pileup Cut"}; + + Configurable cfgLinPupParam0{"cfgLinPupParam0", 3.0f, "Linear Pileup Cut Const"}; + Configurable cfgLinPupParam1{"cfgLinPupParam1", 3.0f, "Linear Pileup Slope"}; + + Configurable cfgNchPbMax{"cfgNchPbMax", 10000, "Max Nch range for PbPb collisions"}; + Configurable cfgNchOMax{"cfgNchOMax", 1000, "Max Nch range for OO collisions"}; Configurable cfgSys{"cfgSys", 1, "Efficiency to be used for which system? 1-->PbPb, 2-->NeNe, 3-->OO, 4-->pp"}; Configurable cfgFlat{"cfgFlat", false, "Whether to use flattening weights"}; @@ -266,6 +273,9 @@ struct RadialFlowDecorr { std::array hFake{}; std::array hFlatWeight{}; + std::vector> mLimitsNchCent; + float mMinXNchCent = 0, mMaxXNchCent = 0; + TProfile3D* pmeanTruNchEtabinSpbinStep2 = nullptr; TProfile3D* pmeanRecoNchEtabinSpbinStep2 = nullptr; TProfile3D* pmeanRecoEffcorrNchEtabinSpbinStep2 = nullptr; @@ -287,7 +297,6 @@ struct RadialFlowDecorr { { float pt = track.pt(); auto sign = track.sign(); - // --- Generic Inclusive --- histos.fill(HIST("h3DnsigmaTpcVsPtBefCut_Cent"), cent, pt, track.tpcNSigmaPi()); histos.fill(HIST("h3DnsigmaTofVsPtBefCut_Cent"), cent, pt, track.tofNSigmaPi()); histos.fill(HIST("h3DnsigmaTpcVsTofBefCut_Cent"), cent, track.tofNSigmaPi(), track.tpcNSigmaPi()); @@ -397,39 +406,62 @@ struct RadialFlowDecorr { // Returns: 0 = Unknown/Reject, 1 = Pion, 2 = Kaon, 3 = Proton template - int identifyTrack(const T& candidate, int centBin) + int identifyTrack(const T& candidate, int cent) { - // Initial sanity checks if (!candidate.hasTPC()) return 0; + float pt = candidate.pt(); if (pt <= cfgCutPtLower || pt >= cfgCutPtUpperPID) return 0; // Out of bounds - // Determine species indices based on charge + + if (!pidMeanSigmaMap) + return 0; + + int centBin = cent + 0.5; auto charge = candidate.sign(); int piIdx = (charge > 0) ? kPiPlusIdx : kPiMinusIdx; int kaIdx = (charge > 0) ? kKaPlusIdx : kKaMinusIdx; int prIdx = (charge > 0) ? kPrIdx : kAntiPrIdx; - // Fetch Calibration Data (Means and Sigmas) + // TPC - float mPiTpc = pidMeanSigmaMap ? pidMeanSigmaMap->meanTPC[piIdx][centBin] : 0.f; - float sPiTpc = pidMeanSigmaMap ? pidMeanSigmaMap->sigmaTPC[piIdx][centBin] : 1.f; - float mKaTpc = pidMeanSigmaMap ? pidMeanSigmaMap->meanTPC[kaIdx][centBin] : 0.f; - float sKaTpc = pidMeanSigmaMap ? pidMeanSigmaMap->sigmaTPC[kaIdx][centBin] : 1.f; - float mPrTpc = pidMeanSigmaMap ? pidMeanSigmaMap->meanTPC[prIdx][centBin] : 0.f; - float sPrTpc = pidMeanSigmaMap ? pidMeanSigmaMap->sigmaTPC[prIdx][centBin] : 1.f; + float mPiTpc = pidMeanSigmaMap->meanTPC[piIdx][centBin]; + float sPiTpc = pidMeanSigmaMap->sigmaTPC[piIdx][centBin]; + + float mKaTpc = pidMeanSigmaMap->meanTPC[kaIdx][centBin]; + float sKaTpc = pidMeanSigmaMap->sigmaTPC[kaIdx][centBin]; + + float mPrTpc = pidMeanSigmaMap->meanTPC[prIdx][centBin]; + float sPrTpc = pidMeanSigmaMap->sigmaTPC[prIdx][centBin]; + // TOF - float mPiTof = pidMeanSigmaMap ? pidMeanSigmaMap->meanTOF[piIdx][centBin] : 0.f; - float sPiTof = pidMeanSigmaMap ? pidMeanSigmaMap->sigmaTOF[piIdx][centBin] : 1.f; - float mKaTof = pidMeanSigmaMap ? pidMeanSigmaMap->meanTOF[kaIdx][centBin] : 0.f; - float sKaTof = pidMeanSigmaMap ? pidMeanSigmaMap->sigmaTOF[kaIdx][centBin] : 1.f; - float mPrTof = pidMeanSigmaMap ? pidMeanSigmaMap->meanTOF[prIdx][centBin] : 0.f; - float sPrTof = pidMeanSigmaMap ? pidMeanSigmaMap->sigmaTOF[prIdx][centBin] : 1.f; + float mPiTof = pidMeanSigmaMap->meanTOF[piIdx][centBin]; + float sPiTof = pidMeanSigmaMap->sigmaTOF[piIdx][centBin]; + + float mKaTof = pidMeanSigmaMap->meanTOF[kaIdx][centBin]; + float sKaTof = pidMeanSigmaMap->sigmaTOF[kaIdx][centBin]; + + float mPrTof = pidMeanSigmaMap->meanTOF[prIdx][centBin]; + float sPrTof = pidMeanSigmaMap->sigmaTOF[prIdx][centBin]; + + static int debugLogCounter = 0; + if (debugLogCounter < KConstTen) { + LOGF(info, "[PID DEBUG] CentBin: %d, Charge: %d", centBin, charge); + LOGF(info, " -> TPC USED | Pi (\u03bc=%.3f, \u03c3=%.3f) | Ka (\u03bc=%.3f, \u03c3=%.3f) | Pr (\u03bc=%.3f, \u03c3=%.3f)", + mPiTpc, sPiTpc, mKaTpc, sKaTpc, mPrTpc, sPrTpc); + + if (candidate.hasTOF()) { + LOGF(info, " -> TOF USED | Pi (\u03bc=%.3f, \u03c3=%.3f) | Ka (\u03bc=%.3f, \u03c3=%.3f) | Pr (\u03bc=%.3f, \u03c3=%.3f)", + mPiTof, sPiTof, mKaTof, sKaTof, mPrTof, sPrTof); + } else { + LOGF(info, " -> TOF USED | Track has no TOF signal."); + } + debugLogCounter++; + } // Fetch Raw nSigma Values float rawTpcPi = candidate.tpcNSigmaPi(); float rawTpcKa = candidate.tpcNSigmaKa(); float rawTpcPr = candidate.tpcNSigmaPr(); - float rawTpcEl = candidate.tpcNSigmaEl(); float rawTofPi = 0.f, rawTofKa = 0.f, rawTofPr = 0.f; if (candidate.hasTOF()) { @@ -437,13 +469,6 @@ struct RadialFlowDecorr { rawTofKa = candidate.tofNSigmaKa(); rawTofPr = candidate.tofNSigmaPr(); } - // ELECTRON REJECTION: Reject if it is > cTpcRejCut from ALL hadron hypotheses AND falls within the electron band [-3, 5] - if (std::abs(rawTpcPi - mPiTpc) > cfgTpcElRejCut && - std::abs(rawTpcKa - mKaTpc) > cfgTpcElRejCut && - std::abs(rawTpcPr - mPrTpc) > cfgTpcElRejCut && - rawTpcEl > cfgTpcElRejCutMin && rawTpcEl < cfgTpcElRejCutMax) { - return 0; // It's an electron, reject it! - } // --- Low PT Regime --- if (pt <= cfgCutPtUpperTPC) { @@ -451,10 +476,12 @@ struct RadialFlowDecorr { bool inTpcPi = std::abs(rawTpcPi - mPiTpc) < (cfgnSigmaCutTPC * sPiTpc); bool inTpcKa = std::abs(rawTpcKa - mKaTpc) < (cfgnSigmaCutTPC * sKaTpc); bool inTpcPr = std::abs(rawTpcPr - mPrTpc) < (cfgnSigmaCutTPC * sPrTpc); + // Combined passing check (adds TOF if available) bool passPi = inTpcPi && (!candidate.hasTOF() || std::abs(rawTofPi - mPiTof) < (cfgnSigmaCutTOF * sPiTof)); bool passKa = inTpcKa && (!candidate.hasTOF() || std::abs(rawTofKa - mKaTof) < (cfgnSigmaCutTOF * sKaTof)); bool passPr = inTpcPr && (!candidate.hasTOF() || std::abs(rawTofPr - mPrTof) < (cfgnSigmaCutTOF * sPrTof)); + // Uniqueness check: Must pass target cut, and NOT fall into the TPC range of the others if (passPi && !passKa && !passPr) return 1; @@ -465,16 +492,19 @@ struct RadialFlowDecorr { return 0; // Ambiguous or failed all cuts } + // --- High PT Regime--- if (candidate.hasTOF() && pt > cfgCutPtUpperTPC) { // Calculate 2D Normalized Distance (Elliptical distance normalized by sigma) float dPi = std::hypot((rawTpcPi - mPiTpc) / sPiTpc, (rawTofPi - mPiTof) / sPiTof); float dKa = std::hypot((rawTpcKa - mKaTpc) / sKaTpc, (rawTofKa - mKaTof) / sKaTof); float dPr = std::hypot((rawTpcPr - mPrTpc) / sPrTpc, (rawTofPr - mPrTof) / sPrTof); + // Count how many particles are within the ambiguity radius int competitors = (dPi < cfgnSigmaOtherParticles) + (dKa < cfgnSigmaOtherParticles) + (dPr < cfgnSigmaOtherParticles); + // If 1 or fewer are in the ambiguity region, pick the absolute best match if (competitors <= 1) { if (dPi <= dKa && dPi <= dPr && dPi < cfgnSigmaCutCombTPCTOF) @@ -512,6 +542,29 @@ struct RadialFlowDecorr { if (cfgIsGoodZvtxFT0VsPV && !col.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) return false; histos.fill(HIST("hEvtCount"), 5.5); + return true; + } + + bool isPassAddPileup(int multPV, int trksize, float cent) + { + auto checkLimits = [](float x, float y, const std::vector>& limits, float xM, float xMx) { + if (limits.empty()) + return true; + int bin = 1 + static_cast((x - xM) / (xMx - xM) * (limits.size() - 2)); + if (bin < 1 || bin >= static_cast(limits.size() - 1)) + return false; + return (y >= limits[bin].first && y <= limits[bin].second); + }; + if (cfgApplySigPupCut) { + if (!checkLimits(trksize, cent, state.mLimitsNchCent, state.mMinXNchCent, state.mMaxXNchCent)) + return false; + } + histos.fill(HIST("hEvtCount"), 6.5); + if (cfgApplyLinPupCut) { + if (trksize > (cfgLinPupParam0 + cfgLinPupParam1 * multPV)) + return false; + } + histos.fill(HIST("hEvtCount"), 7.5); return true; } @@ -771,20 +824,22 @@ struct RadialFlowDecorr { histos.add("hVtxZ_after_sel", ";z_{vtx} (cm)", kTH1F, {{KNbinsZvtx, KZvtxMin, KZvtxMax}}); histos.add("hVtxZ", ";z_{vtx} (cm)", kTH1F, {{KNbinsZvtx, KZvtxMin, KZvtxMax}}); histos.add("hCentrality", ";centrality (%)", kTH1F, {{centAxis1Per}}); - histos.add("Hist2D_globalTracks_PVTracks", ";N_{global};N_{PV}", kTH2F, {{nChAxis2}, {nChAxis2}}); - histos.add("Hist2D_cent_nch", ";N_{PV};cent (%)", kTH2F, {{nChAxis2}, {centAxis1Per}}); + histos.add("Hist2D_globalTracks_PVTracks", ";N_{global};N_{PV}", kTH2F, {{nChAxis}, {nChAxis}}); + histos.add("Hist2D_cent_nch", ";N_{PV};cent (%)", kTH2F, {{nChAxis}, {centAxis1Per}}); histos.add("hP", ";p (GeV/c)", kTH1F, {{KNbinsPt, KPMin, KPMax}}); histos.add("hPt", ";p_{T} (GeV/c)", kTH1F, {{KNbinsPt, KPtMin, KPtMax}}); histos.add("hEta", ";#eta", kTH1F, {{KNbinsEtaFine, KEtaMin, KEtaMax}}); histos.add("hPhi", ";#phi", kTH1F, {{KNbinsPhi, KPhiMin, TwoPI}}); - histos.add("hEvtCount", "Number of Event;; Count", kTH1F, {{7, 0, 7}}); + histos.add("hEvtCount", "Number of Event;; Count", kTH1F, {{9, 0, 9}}); histos.get(HIST("hEvtCount"))->GetXaxis()->SetBinLabel(1, "all Events"); histos.get(HIST("hEvtCount"))->GetXaxis()->SetBinLabel(2, "after sel8"); histos.get(HIST("hEvtCount"))->GetXaxis()->SetBinLabel(3, "after VertexZ Cut"); histos.get(HIST("hEvtCount"))->GetXaxis()->SetBinLabel(4, "after kNoSameBunchPileup"); histos.get(HIST("hEvtCount"))->GetXaxis()->SetBinLabel(5, "after kIsGoodZvtxFT0vsPV"); histos.get(HIST("hEvtCount"))->GetXaxis()->SetBinLabel(6, "after kIsGoodITSLayersAll"); + histos.get(HIST("hEvtCount"))->GetXaxis()->SetBinLabel(7, "after PVTracksCent Pileup Cut"); + histos.get(HIST("hEvtCount"))->GetXaxis()->SetBinLabel(8, "after Linear Pileup Cut"); histos.add("hTrkCount", "Number of Tracks;; Count", kTH1F, {{11, 0, 11}}); histos.get(HIST("hTrkCount"))->GetXaxis()->SetBinLabel(1, "all Tracks"); @@ -1193,50 +1248,48 @@ struct RadialFlowDecorr { } } - if (cfgRunGetEff || cfgRunGetMCFlat || cfgRunMCMean || cfgRunMCFluc) { - TList* pidList = ccdb->getForTimeStamp(pathNsig, now); + bool requiresMCMap = (cfgRunGetEff || cfgRunGetMCFlat || cfgRunMCMean || cfgRunMCFluc); + bool requiresDataMap = (cfgRunGetDataFlat || cfgRunDataMean || cfgRunDataFluc); + + if (requiresMCMap || requiresDataMap) { + std::string currentPath = requiresMCMap ? pathNsig : pathDataNsig; + TList* pidList = ccdb->getForTimeStamp(currentPath, now); if (!pidList) { - LOGF(warn, "nSigma maps required but CCDB list is null at %s! Using raw values.", pathNsig.c_str()); + LOGF(warn, "nSigma maps required but CCDB list is null at %s! Using raw values.", currentPath.c_str()); } else { - if (!pidMeanSigmaMap) + if (!pidMeanSigmaMap) { pidMeanSigmaMap = new PIDMeanSigmaMap(); - + } LOGF(info, "Performing 2D Gaussian fits on PID maps from CCDB..."); - auto loadPIDMeans = [&](PIDIdx pidType) { std::string suffix = pidSuffix[pidType]; std::string hName = "h3DnsigmaTpcVsTofBefCut_Cent" + suffix; auto* h3 = reinterpret_cast(pidList->FindObject(hName.c_str())); - if (!h3) { LOGF(warn, " [!] PID Hist %s not found in CCDB list.", hName.c_str()); return; } - int nCentBins = std::min(h3->GetXaxis()->GetNbins(), PIDMeanSigmaMap::MaxCentBins - 1); LOGF(info, " -> Species: %s (Bins: %d)", hName.c_str(), nCentBins); - for (int iCent = 1; iCent <= nCentBins; ++iCent) { h3->GetXaxis()->SetRange(iCent, iCent); // Projecting: Z(TPC) vs Y(TOF). Result: X_axis=TOF, Y_axis=TPC std::unique_ptr h2(reinterpret_cast(h3->Project3D("zy"))); if (h2) { + int binX, binY, binZ; + h2->GetMaximumBin(binX, binY, binZ); + double guessMeanTOF = h2->GetXaxis()->GetBinCenter(binX); + double guessMeanTPC = h2->GetYaxis()->GetBinCenter(binY); TF2 f2("f2", "[0]*TMath::Gaus(x,[1],[2])*TMath::Gaus(y,[3],[4])", -3, 3, -3, 3); - // Initial Parameters: Amp, MeanTOF, SigmaTOF, MeanTPC, SigmaTPC - f2.SetParameter(0, h2->GetMaximum()); - f2.SetParameter(1, 0.0); - f2.SetParLimits(1, -2, 2); - - h2->Fit(&f2, "QRN"); + f2.SetParameters(h2->GetMaximum(), guessMeanTOF, 1.0, guessMeanTPC, 1.0); + h2->Fit(&f2, "QRN"); // Q=Quiet, R=Range, N=NoDraw pidMeanSigmaMap->meanTOF[pidType][iCent - 1] = f2.GetParameter(1); pidMeanSigmaMap->meanTPC[pidType][iCent - 1] = f2.GetParameter(3); pidMeanSigmaMap->sigmaTOF[pidType][iCent - 1] = std::abs(f2.GetParameter(2)); pidMeanSigmaMap->sigmaTPC[pidType][iCent - 1] = std::abs(f2.GetParameter(4)); - if (iCent % KConstTen == 0) { - LOGF(info, " Bin %d: Mean TOF = %.3f, Mean TPC = %.3f", - iCent - 1, f2.GetParameter(1), f2.GetParameter(3)); + LOGF(info, " Derived: For Species: %s (Bins: %d), Mean TOF = %.3f, Mean TPC = %.3f, Sigma TOF = %.3f, Sigma TPC = %.3f", hName.c_str(), iCent - 1, f2.GetParameter(1), f2.GetParameter(3), f2.GetParameter(2), f2.GetParameter(4)); } } } @@ -1244,60 +1297,23 @@ struct RadialFlowDecorr { for (int i = 0; i < KNsp; ++i) { loadPIDMeans(static_cast(i)); } - } - } - - if (cfgRunGetDataFlat || cfgRunDataMean || cfgRunDataFluc) { - TList* pidList = ccdb->getForTimeStamp(pathDataNsig, now); - - if (!pidList) { - LOGF(warn, "nSigma maps required but CCDB list is null at %s! Using raw values.", pathDataNsig.c_str()); - } else { - if (!pidMeanSigmaMap) - pidMeanSigmaMap = new PIDMeanSigmaMap(); - - LOGF(info, "Performing 2D Gaussian fits on PID maps from CCDB..."); - - auto loadPIDMeans = [&](PIDIdx pidType) { - std::string suffix = pidSuffix[pidType]; - std::string hName = "h3DnsigmaTpcVsTofBefCut_Cent" + suffix; - auto* h3 = reinterpret_cast(pidList->FindObject(hName.c_str())); - - if (!h3) { - LOGF(warn, " [!] PID Hist %s not found in CCDB list.", hName.c_str()); - return; - } - - int nCentBins = std::min(h3->GetXaxis()->GetNbins(), PIDMeanSigmaMap::MaxCentBins - 1); - LOGF(info, " -> Species: %s (Bins: %d)", hName.c_str(), nCentBins); - - for (int iCent = 1; iCent <= nCentBins; ++iCent) { - h3->GetXaxis()->SetRange(iCent, iCent); - // Projecting: Z(TPC) vs Y(TOF). Result: X_axis=TOF, Y_axis=TPC - std::unique_ptr h2(reinterpret_cast(h3->Project3D("zy"))); - if (h2) { - TF2 f2("f2", "[0]*TMath::Gaus(x,[1],[2])*TMath::Gaus(y,[3],[4])", -3, 3, -3, 3); - // Initial Parameters: Amp, MeanTOF, SigmaTOF, MeanTPC, SigmaTPC - f2.SetParameter(0, h2->GetMaximum()); - f2.SetParameter(1, 0.0); - f2.SetParLimits(1, -2, 2); - - h2->Fit(&f2, "QRN"); - pidMeanSigmaMap->meanTOF[pidType][iCent - 1] = f2.GetParameter(1); - pidMeanSigmaMap->meanTPC[pidType][iCent - 1] = f2.GetParameter(3); - pidMeanSigmaMap->sigmaTOF[pidType][iCent - 1] = std::abs(f2.GetParameter(2)); - pidMeanSigmaMap->sigmaTPC[pidType][iCent - 1] = std::abs(f2.GetParameter(4)); - if (iCent % KConstTen == 0) { - LOGF(info, " Bin %d: Mean TOF = %.3f, Mean TPC = %.3f", - iCent - 1, f2.GetParameter(1), f2.GetParameter(3)); - } - } + auto loadLimits = [&](const char* name, std::vector>& limits, float& xMin, float& xMax) { + auto* h2 = reinterpret_cast(pidList->FindObject(name)); + if (!h2) + return; // Skip if missing + int nBins = h2->GetXaxis()->GetNbins(); + xMin = h2->GetXaxis()->GetXmin(); + xMax = h2->GetXaxis()->GetXmax(); + limits.assign(nBins + 2, {-9999.f, 99999.f}); + for (int i = 1; i <= nBins; ++i) { + std::unique_ptr proj(h2->ProjectionY("_py", i, i)); + float m = proj->GetMean(); + float s = proj->GetRMS(); + limits[i] = {m - cfgPupnSig * s, m + cfgPupnSig * s}; } }; - for (int i = 0; i < KNsp; ++i) { - loadPIDMeans(static_cast(i)); - } + loadLimits("Hist2D_cent_nch", state.mLimitsNchCent, state.mMinXNchCent, state.mMaxXNchCent); } } @@ -1446,15 +1462,16 @@ struct RadialFlowDecorr { if (cent > KCentMax) continue; float multPV = col.multNTracksPV(); + + histos.fill(HIST("hVtxZ_after_sel"), col.posZ()); + histos.fill(HIST("hCentrality"), cent); + + histos.fill(HIST("Hist2D_globalTracks_PVTracks"), multPV, trackSlice.size()); + histos.fill(HIST("Hist2D_cent_nch"), trackSlice.size(), cent); + for (const auto& particle : partSlice) { if (!isParticleSelected(particle) || !particle.isPhysicalPrimary()) continue; - histos.fill(HIST("hVtxZ_after_sel"), col.posZ()); - histos.fill(HIST("hCentrality"), cent); - - histos.fill(HIST("Hist2D_globalTracks_PVTracks"), multPV, trackSlice.size()); - histos.fill(HIST("Hist2D_cent_nch"), trackSlice.size(), cent); - for (const auto& track : trackSlice) { if (!isTrackSelected(track)) continue; @@ -1490,6 +1507,15 @@ struct RadialFlowDecorr { float multPV = col.multNTracksPV(); float vz = col.posZ(); + if (!isPassAddPileup(multPV, trackSlice.size(), cent)) + continue; + + histos.fill(HIST("hVtxZ_after_sel"), col.posZ()); + histos.fill(HIST("hCentrality"), cent); + + histos.fill(HIST("Hist2D_globalTracks_PVTracks"), multPV, trackSlice.size()); + histos.fill(HIST("Hist2D_cent_nch"), trackSlice.size(), cent); + for (const auto& particle : partSlice) { if (!isParticleSelected(particle) || !particle.isPhysicalPrimary()) continue; @@ -1499,16 +1525,16 @@ struct RadialFlowDecorr { float pt = particle.pt(), eta = particle.eta(); bool isSpecies[KNsp] = { - true, // kInclusiveIdx - pdg == -KPiPlus, // kPiMinusIdx - pdg == KPiPlus, // kPiPlusIdx - absPdg == KPiPlus, // kPiAllIdx - pdg == -KKPlus, // kKaMinusIdx - pdg == KKPlus, // kKaPlusIdx - absPdg == KKPlus, // kKaAllIdx - pdg == -KProton, // kAntiPrIdx - pdg == KProton, // kPrIdx - absPdg == KProton // kPrAllIdx + (absPdg == KPiPlus || absPdg == KKPlus || absPdg == KProton), // kInclusiveIdx + pdg == -KPiPlus, // kPiMinusIdx + pdg == KPiPlus, // kPiPlusIdx + absPdg == KPiPlus, // kPiAllIdx + pdg == -KKPlus, // kKaMinusIdx + pdg == KKPlus, // kKaPlusIdx + absPdg == KKPlus, // kKaAllIdx + pdg == -KProton, // kAntiPrIdx + pdg == KProton, // kPrIdx + absPdg == KProton // kPrAllIdx }; histos.fill(HIST("h3_AllPrimary"), multPV, pt, eta); @@ -1534,12 +1560,6 @@ struct RadialFlowDecorr { histos.fill(HIST("h3_AllPrimary_PrAll"), multPV, pt, eta); } - histos.fill(HIST("hVtxZ_after_sel"), col.posZ()); - histos.fill(HIST("hCentrality"), cent); - - histos.fill(HIST("Hist2D_globalTracks_PVTracks"), multPV, trackSlice.size()); - histos.fill(HIST("Hist2D_cent_nch"), trackSlice.size(), cent); - for (const auto& track : trackSlice) { if (!isTrackSelected(track)) continue; @@ -1548,14 +1568,14 @@ struct RadialFlowDecorr { auto sign = track.sign(); fillNSigmaBefCut(track, cent); - int centBin = static_cast(cent); - int id = identifyTrack(track, centBin); + int id = identifyTrack(track, cent); bool isPi = (id == KPidPionOne); bool isKa = (id == KPidKaonTwo); bool isPr = (id == KPidProtonThree); + bool isAny = (isPi || isKa || isPr); // Only true if it passed PID! bool isSpecies[KNsp] = { - true, + isAny, isPi && sign < 0, isPi && sign > 0, isPi, isKa && sign < 0, isKa && sign > 0, isKa, isPr && sign < 0, isPr && sign > 0, isPr}; @@ -1749,6 +1769,7 @@ struct RadialFlowDecorr { continue; for (const auto& col : colSlice) { + histos.fill(HIST("hVtxZ"), col.posZ()); if (!col.has_mcCollision() || !isEventSelected(col)) continue; @@ -1763,6 +1784,8 @@ struct RadialFlowDecorr { float multPV = col.multNTracksPV(); float vz = col.posZ(); + if (!isPassAddPileup(multPV, trackSlice.size(), cent)) + continue; histos.fill(HIST("hVtxZ_after_sel"), col.posZ()); histos.fill(HIST("hCentrality"), cent); @@ -1774,14 +1797,14 @@ struct RadialFlowDecorr { float pt = track.pt(), eta = track.eta(), phi = track.phi(); auto sign = track.sign(); - int centBin = static_cast(cent); - int id = identifyTrack(track, centBin); + int id = identifyTrack(track, cent); bool isPi = (id == KPidPionOne); bool isKa = (id == KPidKaonTwo); bool isPr = (id == KPidProtonThree); + bool isAny = (isPi || isKa || isPr); // Only true if it passed PID! bool isSpecies[KNsp] = { - true, + isAny, isPi && sign < 0, isPi && sign > 0, isPi, isKa && sign < 0, isKa && sign > 0, isKa, isPr && sign < 0, isPr && sign > 0, isPr}; @@ -1856,6 +1879,7 @@ struct RadialFlowDecorr { continue; for (const auto& col : colSlice) { + histos.fill(HIST("hVtxZ"), col.posZ()); if (!col.has_mcCollision() || !isEventSelected(col)) continue; @@ -1870,6 +1894,15 @@ struct RadialFlowDecorr { float multPV = col.multNTracksPV(); float vz = col.posZ(); + if (!isPassAddPileup(multPV, trackSlice.size(), cent)) + continue; + + histos.fill(HIST("hVtxZ_after_sel"), col.posZ()); + histos.fill(HIST("hCentrality"), cent); + + histos.fill(HIST("Hist2D_globalTracks_PVTracks"), col.multNTracksPV(), trackSlice.size()); + histos.fill(HIST("Hist2D_cent_nch"), trackSlice.size(), cent); + memset(sumWiTruth, 0, sizeof(sumWiTruth)); memset(sumWiptiTruth, 0, sizeof(sumWiptiTruth)); memset(sumWiReco, 0, sizeof(sumWiReco)); @@ -1887,16 +1920,16 @@ struct RadialFlowDecorr { int absPdg = std::abs(pdgCode); bool isSpecies[KNsp] = { - true, // kInclusiveIdx - pdgCode == -KPiPlus, // kPiMinusIdx - pdgCode == KPiPlus, // kPiPlusIdx - absPdg == KPiPlus, // kPiAllIdx - pdgCode == -KKPlus, // kKaMinusIdx - pdgCode == KKPlus, // kKaPlusIdx - absPdg == KKPlus, // kKaAllIdx - pdgCode == -KProton, // kAntiPrIdx - pdgCode == KProton, // kPrIdx - absPdg == KProton // kPrAllIdx + (absPdg == KPiPlus || absPdg == KKPlus || absPdg == KProton), // kInclusiveIdx + pdgCode == -KPiPlus, // kPiMinusIdx + pdgCode == KPiPlus, // kPiPlusIdx + absPdg == KPiPlus, // kPiAllIdx + pdgCode == -KKPlus, // kKaMinusIdx + pdgCode == KKPlus, // kKaPlusIdx + absPdg == KKPlus, // kKaAllIdx + pdgCode == -KProton, // kAntiPrIdx + pdgCode == KProton, // kPrIdx + absPdg == KProton // kPrAllIdx }; for (int ieta = 0; ieta < KNEta; ++ieta) { @@ -1921,12 +1954,6 @@ struct RadialFlowDecorr { } } - histos.fill(HIST("hVtxZ_after_sel"), col.posZ()); - histos.fill(HIST("hCentrality"), cent); - - histos.fill(HIST("Hist2D_globalTracks_PVTracks"), col.multNTracksPV(), trackSlice.size()); - histos.fill(HIST("Hist2D_cent_nch"), trackSlice.size(), cent); - for (const auto& track : trackSlice) { if (!isTrackSelected(track)) continue; @@ -1934,14 +1961,13 @@ struct RadialFlowDecorr { if (pt <= cfgPtMin || pt > cfgPtMax) continue; auto sign = track.sign(); - int centBin = static_cast(cent); - int id = identifyTrack(track, centBin); + int id = identifyTrack(track, cent); bool isPi = (id == KPidPionOne); bool isKa = (id == KPidKaonTwo); bool isPr = (id == KPidProtonThree); - + bool isAny = (isPi || isKa || isPr); // Only true if it passed PID! bool isSpecies[KNsp] = { - true, + isAny, isPi && sign < 0, isPi && sign > 0, isPi, isKa && sign < 0, isKa && sign > 0, isKa, isPr && sign < 0, isPr && sign > 0, isPr}; @@ -2220,6 +2246,15 @@ struct RadialFlowDecorr { continue; float multPV = col.multNTracksPV(); + if (!isPassAddPileup(multPV, trackSlice.size(), cent)) + continue; + + histos.fill(HIST("hVtxZ_after_sel"), col.posZ()); + histos.fill(HIST("hCentrality"), cent); + + histos.fill(HIST("Hist2D_globalTracks_PVTracks"), col.multNTracksPV(), trackSlice.size()); + histos.fill(HIST("Hist2D_cent_nch"), trackSlice.size(), cent); + memset(sumPmwkTru, 0, sizeof(sumPmwkTru)); memset(sumWkTru, 0, sizeof(sumWkTru)); memset(sumPmwkReco, 0, sizeof(sumPmwkReco)); @@ -2260,16 +2295,16 @@ struct RadialFlowDecorr { int absPdg = std::abs(pdgCode); bool isSpecies[KNsp] = { - true, // kInclusiveIdx - pdgCode == -KPiPlus, // kPiMinusIdx - pdgCode == KPiPlus, // kPiPlusIdx - absPdg == KPiPlus, // kPiAllIdx - pdgCode == -KKPlus, // kKaMinusIdx - pdgCode == KKPlus, // kKaPlusIdx - absPdg == KKPlus, // kKaAllIdx - pdgCode == -KProton, // kAntiPrIdx - pdgCode == KProton, // kPrIdx - absPdg == KProton // kPrAllIdx + (absPdg == KPiPlus || absPdg == KKPlus || absPdg == KProton), // kInclusiveIdx + pdgCode == -KPiPlus, // kPiMinusIdx + pdgCode == KPiPlus, // kPiPlusIdx + absPdg == KPiPlus, // kPiAllIdx + pdgCode == -KKPlus, // kKaMinusIdx + pdgCode == KKPlus, // kKaPlusIdx + absPdg == KKPlus, // kKaAllIdx + pdgCode == -KProton, // kAntiPrIdx + pdgCode == KProton, // kPrIdx + absPdg == KProton // kPrAllIdx }; for (int ieta = 0; ieta < KNEta; ++ieta) { @@ -2289,12 +2324,6 @@ struct RadialFlowDecorr { } // end truth loop float vz = col.posZ(); - histos.fill(HIST("hVtxZ_after_sel"), col.posZ()); - histos.fill(HIST("hCentrality"), cent); - - histos.fill(HIST("Hist2D_globalTracks_PVTracks"), col.multNTracksPV(), trackSlice.size()); - histos.fill(HIST("Hist2D_cent_nch"), trackSlice.size(), cent); - for (const auto& track : trackSlice) { if (!isTrackSelected(track)) continue; @@ -2305,14 +2334,14 @@ struct RadialFlowDecorr { float eta = track.eta(); float phi = track.phi(); auto sign = track.sign(); - int centBin = static_cast(cent); - int id = identifyTrack(track, centBin); + int id = identifyTrack(track, cent); bool isPi = (id == KPidPionOne); bool isKa = (id == KPidKaonTwo); bool isPr = (id == KPidProtonThree); + bool isAny = (isPi || isKa || isPr); // Only true if it passed PID! bool isSpecies[KNsp] = { - true, + isAny, isPi && sign < 0, isPi && sign > 0, isPi, isKa && sign < 0, isKa && sign > 0, isKa, isPr && sign < 0, isPr && sign > 0, isPr}; @@ -3006,6 +3035,9 @@ struct RadialFlowDecorr { if (cent > KCentMax) return; + if (!isPassAddPileup(coll.multNTracksPV(), tracks.size(), cent)) + return; + histos.fill(HIST("hVtxZ_after_sel"), coll.posZ()); histos.fill(HIST("hCentrality"), cent); @@ -3028,14 +3060,14 @@ struct RadialFlowDecorr { if (eta > etaLw[0] && eta < etaUp[0]) ntrk++; fillNSigmaBefCut(track, cent); - int centBin = static_cast(cent); - int id = identifyTrack(track, centBin); + int id = identifyTrack(track, cent); bool isPi = (id == KPidPionOne); bool isKa = (id == KPidKaonTwo); bool isPr = (id == KPidProtonThree); + bool isAny = (isPi || isKa || isPr); // Only true if it passed PID! bool isSpecies[KNsp] = { - true, + isAny, isPi && sign < 0, isPi && sign > 0, isPi, isKa && sign < 0, isKa && sign > 0, isKa, isPr && sign < 0, isPr && sign > 0, isPr}; @@ -3125,6 +3157,9 @@ struct RadialFlowDecorr { if (cent > KCentMax) return; + if (!isPassAddPileup(coll.multNTracksPV(), tracks.size(), cent)) + return; + histos.fill(HIST("hVtxZ_after_sel"), coll.posZ()); histos.fill(HIST("hCentrality"), cent); @@ -3153,14 +3188,14 @@ struct RadialFlowDecorr { histos.fill(HIST("hPt"), pt); histos.fill(HIST("hEta"), eta); histos.fill(HIST("hPhi"), phi); - int centBin = static_cast(cent); - int id = identifyTrack(track, centBin); + int id = identifyTrack(track, cent); bool isPi = (id == KPidPionOne); bool isKa = (id == KPidKaonTwo); bool isPr = (id == KPidProtonThree); + bool isAny = (isPi || isKa || isPr); // Only true if it passed PID! bool isSpecies[KNsp] = { - true, + isAny, isPi && sign < 0, isPi && sign > 0, isPi, isKa && sign < 0, isKa && sign > 0, isKa, isPr && sign < 0, isPr && sign > 0, isPr}; @@ -3317,6 +3352,15 @@ struct RadialFlowDecorr { if (cent > KCentMax) return; + if (!isPassAddPileup(coll.multNTracksPV(), tracks.size(), cent)) + return; + + histos.fill(HIST("hVtxZ_after_sel"), coll.posZ()); + histos.fill(HIST("hCentrality"), cent); + + histos.fill(HIST("Hist2D_globalTracks_PVTracks"), coll.multNTracksPV(), tracks.size()); + histos.fill(HIST("Hist2D_cent_nch"), tracks.size(), cent); + if (!state.pmeanNchEtabinSpbinStep2 || !state.pmeanMultNchEtabinSpbinStep2) { LOGF(warning, "Data fluc: Mean pT or Mult map missing"); return; @@ -3354,14 +3398,14 @@ struct RadialFlowDecorr { if (pt <= cfgPtMin || pt > cfgPtMax) continue; - int centBin = static_cast(cent); - int id = identifyTrack(track, centBin); + int id = identifyTrack(track, cent); bool isPi = (id == KPidPionOne); bool isKa = (id == KPidKaonTwo); bool isPr = (id == KPidProtonThree); + bool isAny = (isPi || isKa || isPr); // Only true if it passed PID! bool isSpecies[KNsp] = { - true, + isAny, isPi && sign < 0, isPi && sign > 0, isPi, isKa && sign < 0, isKa && sign > 0, isKa, isPr && sign < 0, isPr && sign > 0, isPr}; From 40e8b328edeef083989c1270b2632269b5112398 Mon Sep 17 00:00:00 2001 From: Fan Si <147278151+fsii@users.noreply.github.com> Date: Sun, 8 Mar 2026 21:27:19 +0100 Subject: [PATCH 218/347] [PWGCF] Add configurable for recalibrated DCA cut (#15307) --- PWGCF/EbyEFluctuations/Tasks/partNumFluc.cxx | 319 ++++++++++--------- 1 file changed, 171 insertions(+), 148 deletions(-) diff --git a/PWGCF/EbyEFluctuations/Tasks/partNumFluc.cxx b/PWGCF/EbyEFluctuations/Tasks/partNumFluc.cxx index d201fb6edf7..a92d235b395 100644 --- a/PWGCF/EbyEFluctuations/Tasks/partNumFluc.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/partNumFluc.cxx @@ -544,6 +544,8 @@ struct HolderMcEvent { }; struct HolderEvent { + static constexpr std::pair RangeCentrality = {0., 100.}; + std::int32_t runNumber = 0; std::int32_t runIndex = 0; std::int32_t runGroupIndex = 0; @@ -633,7 +635,7 @@ struct HolderMcParticle { struct HolderTrack { static constexpr double TruncationAbsNSigmaPid = 999.; - static constexpr double truncateNSigmaPid(const double value) { return (!(std::fabs(value) < TruncationAbsNSigmaPid) ? -TruncationAbsNSigmaPid : value); } + static constexpr double truncateNSigmaPid(const double value) { return (!(std::abs(value) < TruncationAbsNSigmaPid) ? -TruncationAbsNSigmaPid : value); } double dcaXY = 0.; double dcaZ = 0.; @@ -755,6 +757,7 @@ struct PartNumFluc { Configurable cfgCutMaxTpcNClsSharedRatio{"cfgCutMaxTpcNClsSharedRatio", 0.25, "Maximum ratio of shared clusters over clusters TPC"}; Configurable cfgCutMinTpcNCrossedRows{"cfgCutMinTpcNCrossedRows", 75, "Minimum number of crossed rows TPC"}; Configurable cfgCutMinTpcNCrossedRowsRatio{"cfgCutMinTpcNCrossedRowsRatio", 0.8, "Minimum ratio of crossed rows over findable clusters TPC"}; + Configurable cfgFlagRecalibrationDca{"cfgFlagRecalibrationDca", false, "DCA recalibration flag"}; Configurable cfgCutMaxAbsNSigmaDcaXy{"cfgCutMaxAbsNSigmaDcaXy", 2.5, "Maximum absolute nSigma of DCAxy (cm)"}; Configurable cfgCutMaxAbsNSigmaDcaZ{"cfgCutMaxAbsNSigmaDcaZ", 2.5, "Maximum absolute nSigma of DCAz (cm)"}; Configurable cfgCutMinPt{"cfgCutMinPt", 0.4, "Minimum pT (GeV/c)"}; @@ -847,7 +850,7 @@ struct PartNumFluc { LOG(fatal) << "Invalid ccdb_object!"; } - const TGraph* const gRunNumberGroupIndex = static_cast(ccdbObject->FindObject("gRunNumberGroupIndex")); + const TGraph* const gRunNumberGroupIndex = dynamic_cast(ccdbObject->FindObject("gRunNumberGroupIndex")); if (!gRunNumberGroupIndex || gRunNumberGroupIndex->IsA() != TGraph::Class()) { LOG(fatal) << "Invalid gRunNumberGroupIndex!"; } @@ -911,59 +914,63 @@ struct PartNumFluc { break; } - holderCcdb.fPtMeanDcaXyP.resize(nRunGroups); - holderCcdb.fPtMeanDcaXyM.resize(nRunGroups); - holderCcdb.fPtMeanDcaZP.resize(nRunGroups); - holderCcdb.fPtMeanDcaZM.resize(nRunGroups); - holderCcdb.fPtSigmaDcaXyP.resize(nRunGroups); - holderCcdb.fPtSigmaDcaXyM.resize(nRunGroups); - holderCcdb.fPtSigmaDcaZP.resize(nRunGroups); - holderCcdb.fPtSigmaDcaZM.resize(nRunGroups); - for (std::int32_t const& iRunGroup : std::views::iota(0, nRunGroups)) { - const TList* const lRunGroup = static_cast(ccdbObject->FindObject(Form("lRunGroup_%d", iRunGroup + 1))); - if (!lRunGroup || lRunGroup->IsA() != TList::Class()) { - LOG(fatal) << "Invalid " << Form("lRunGroup_%d", iRunGroup + 1) << "!"; - } - holderCcdb.fPtMeanDcaXyP[iRunGroup] = static_cast(lRunGroup->FindObject(Form("fPtMeanDcaXyP%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1))); - if (!holderCcdb.fPtMeanDcaXyP[iRunGroup] || holderCcdb.fPtMeanDcaXyP[iRunGroup]->IsA() != TFormula::Class()) { - LOG(fatal) << "Invalid " << Form("fPtMeanDcaXyP%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1) << "!"; - } - LOG(info) << "Reading from CCDB: " << holderCcdb.fPtMeanDcaXyP[iRunGroup]->GetName() << " \"" << holderCcdb.fPtMeanDcaXyP[iRunGroup]->GetExpFormula("clingp") << "\""; - holderCcdb.fPtMeanDcaXyM[iRunGroup] = static_cast(lRunGroup->FindObject(Form("fPtMeanDcaXyM%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1))); - if (!holderCcdb.fPtMeanDcaXyM[iRunGroup] || holderCcdb.fPtMeanDcaXyM[iRunGroup]->IsA() != TFormula::Class()) { - LOG(fatal) << "Invalid " << Form("fPtMeanDcaXyM%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1) << "!"; - } - LOG(info) << "Reading from CCDB: " << holderCcdb.fPtMeanDcaXyM[iRunGroup]->GetName() << " \"" << holderCcdb.fPtMeanDcaXyM[iRunGroup]->GetExpFormula("clingp") << "\""; - holderCcdb.fPtMeanDcaZP[iRunGroup] = static_cast(lRunGroup->FindObject(Form("fPtMeanDcaZP%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1))); - if (!holderCcdb.fPtMeanDcaZP[iRunGroup] || holderCcdb.fPtMeanDcaZP[iRunGroup]->IsA() != TFormula::Class()) { - LOG(fatal) << "Invalid " << Form("fPtMeanDcaZP%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1) << "!"; - } - LOG(info) << "Reading from CCDB: " << holderCcdb.fPtMeanDcaZP[iRunGroup]->GetName() << " \"" << holderCcdb.fPtMeanDcaZP[iRunGroup]->GetExpFormula("clingp") << "\""; - holderCcdb.fPtMeanDcaZM[iRunGroup] = static_cast(lRunGroup->FindObject(Form("fPtMeanDcaZM%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1))); - if (!holderCcdb.fPtMeanDcaZM[iRunGroup] || holderCcdb.fPtMeanDcaZM[iRunGroup]->IsA() != TFormula::Class()) { - LOG(fatal) << "Invalid " << Form("fPtMeanDcaZM%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1) << "!"; - } - LOG(info) << "Reading from CCDB: " << holderCcdb.fPtMeanDcaZM[iRunGroup]->GetName() << " \"" << holderCcdb.fPtMeanDcaZM[iRunGroup]->GetExpFormula("clingp") << "\""; - holderCcdb.fPtSigmaDcaXyP[iRunGroup] = static_cast(lRunGroup->FindObject(Form("fPtSigmaDcaXyP%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1))); - if (!holderCcdb.fPtSigmaDcaXyP[iRunGroup] || holderCcdb.fPtSigmaDcaXyP[iRunGroup]->IsA() != TFormula::Class()) { - LOG(fatal) << "Invalid " << Form("fPtSigmaDcaXyP%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1) << "!"; - } - LOG(info) << "Reading from CCDB: " << holderCcdb.fPtSigmaDcaXyP[iRunGroup]->GetName() << " \"" << holderCcdb.fPtSigmaDcaXyP[iRunGroup]->GetExpFormula("clingp") << "\""; - holderCcdb.fPtSigmaDcaXyM[iRunGroup] = static_cast(lRunGroup->FindObject(Form("fPtSigmaDcaXyM%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1))); - if (!holderCcdb.fPtSigmaDcaXyM[iRunGroup] || holderCcdb.fPtSigmaDcaXyM[iRunGroup]->IsA() != TFormula::Class()) { - LOG(fatal) << "Invalid " << Form("fPtSigmaDcaXyM%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1) << "!"; - } - LOG(info) << "Reading from CCDB: " << holderCcdb.fPtSigmaDcaXyM[iRunGroup]->GetName() << " \"" << holderCcdb.fPtSigmaDcaXyM[iRunGroup]->GetExpFormula("clingp") << "\""; - holderCcdb.fPtSigmaDcaZP[iRunGroup] = static_cast(lRunGroup->FindObject(Form("fPtSigmaDcaZP%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1))); - if (!holderCcdb.fPtSigmaDcaZP[iRunGroup] || holderCcdb.fPtSigmaDcaZP[iRunGroup]->IsA() != TFormula::Class()) { - LOG(fatal) << "Invalid " << Form("fPtSigmaDcaZP%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1) << "!"; - } - LOG(info) << "Reading from CCDB: " << holderCcdb.fPtSigmaDcaZP[iRunGroup]->GetName() << " \"" << holderCcdb.fPtSigmaDcaZP[iRunGroup]->GetExpFormula("clingp") << "\""; - holderCcdb.fPtSigmaDcaZM[iRunGroup] = static_cast(lRunGroup->FindObject(Form("fPtSigmaDcaZM%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1))); - if (!holderCcdb.fPtSigmaDcaZM[iRunGroup] || holderCcdb.fPtSigmaDcaZM[iRunGroup]->IsA() != TFormula::Class()) { - LOG(fatal) << "Invalid " << Form("fPtSigmaDcaZM%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1) << "!"; - } - LOG(info) << "Reading from CCDB: " << holderCcdb.fPtSigmaDcaZM[iRunGroup]->GetName() << " \"" << holderCcdb.fPtSigmaDcaZM[iRunGroup]->GetExpFormula("clingp") << "\""; + if (groupTrack.cfgFlagRecalibrationDca.value) { + LOG(info) << "Enabling DCA recalibration."; + + holderCcdb.fPtMeanDcaXyP.resize(nRunGroups); + holderCcdb.fPtMeanDcaXyM.resize(nRunGroups); + holderCcdb.fPtMeanDcaZP.resize(nRunGroups); + holderCcdb.fPtMeanDcaZM.resize(nRunGroups); + holderCcdb.fPtSigmaDcaXyP.resize(nRunGroups); + holderCcdb.fPtSigmaDcaXyM.resize(nRunGroups); + holderCcdb.fPtSigmaDcaZP.resize(nRunGroups); + holderCcdb.fPtSigmaDcaZM.resize(nRunGroups); + for (std::int32_t const& iRunGroup : std::views::iota(0, nRunGroups)) { + const TList* const lRunGroup = dynamic_cast(ccdbObject->FindObject(Form("lRunGroup_%d", iRunGroup + 1))); + if (!lRunGroup || lRunGroup->IsA() != TList::Class()) { + LOG(fatal) << "Invalid " << Form("lRunGroup_%d", iRunGroup + 1) << "!"; + } + holderCcdb.fPtMeanDcaXyP[iRunGroup] = dynamic_cast(lRunGroup->FindObject(Form("fPtMeanDcaXyP%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1))); + if (!holderCcdb.fPtMeanDcaXyP[iRunGroup] || holderCcdb.fPtMeanDcaXyP[iRunGroup]->IsA() != TFormula::Class()) { + LOG(fatal) << "Invalid " << Form("fPtMeanDcaXyP%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1) << "!"; + } + LOG(info) << "Reading from CCDB: " << holderCcdb.fPtMeanDcaXyP[iRunGroup]->GetName() << " \"" << holderCcdb.fPtMeanDcaXyP[iRunGroup]->GetExpFormula("clingp") << "\""; + holderCcdb.fPtMeanDcaXyM[iRunGroup] = dynamic_cast(lRunGroup->FindObject(Form("fPtMeanDcaXyM%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1))); + if (!holderCcdb.fPtMeanDcaXyM[iRunGroup] || holderCcdb.fPtMeanDcaXyM[iRunGroup]->IsA() != TFormula::Class()) { + LOG(fatal) << "Invalid " << Form("fPtMeanDcaXyM%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1) << "!"; + } + LOG(info) << "Reading from CCDB: " << holderCcdb.fPtMeanDcaXyM[iRunGroup]->GetName() << " \"" << holderCcdb.fPtMeanDcaXyM[iRunGroup]->GetExpFormula("clingp") << "\""; + holderCcdb.fPtMeanDcaZP[iRunGroup] = dynamic_cast(lRunGroup->FindObject(Form("fPtMeanDcaZP%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1))); + if (!holderCcdb.fPtMeanDcaZP[iRunGroup] || holderCcdb.fPtMeanDcaZP[iRunGroup]->IsA() != TFormula::Class()) { + LOG(fatal) << "Invalid " << Form("fPtMeanDcaZP%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1) << "!"; + } + LOG(info) << "Reading from CCDB: " << holderCcdb.fPtMeanDcaZP[iRunGroup]->GetName() << " \"" << holderCcdb.fPtMeanDcaZP[iRunGroup]->GetExpFormula("clingp") << "\""; + holderCcdb.fPtMeanDcaZM[iRunGroup] = dynamic_cast(lRunGroup->FindObject(Form("fPtMeanDcaZM%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1))); + if (!holderCcdb.fPtMeanDcaZM[iRunGroup] || holderCcdb.fPtMeanDcaZM[iRunGroup]->IsA() != TFormula::Class()) { + LOG(fatal) << "Invalid " << Form("fPtMeanDcaZM%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1) << "!"; + } + LOG(info) << "Reading from CCDB: " << holderCcdb.fPtMeanDcaZM[iRunGroup]->GetName() << " \"" << holderCcdb.fPtMeanDcaZM[iRunGroup]->GetExpFormula("clingp") << "\""; + holderCcdb.fPtSigmaDcaXyP[iRunGroup] = dynamic_cast(lRunGroup->FindObject(Form("fPtSigmaDcaXyP%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1))); + if (!holderCcdb.fPtSigmaDcaXyP[iRunGroup] || holderCcdb.fPtSigmaDcaXyP[iRunGroup]->IsA() != TFormula::Class()) { + LOG(fatal) << "Invalid " << Form("fPtSigmaDcaXyP%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1) << "!"; + } + LOG(info) << "Reading from CCDB: " << holderCcdb.fPtSigmaDcaXyP[iRunGroup]->GetName() << " \"" << holderCcdb.fPtSigmaDcaXyP[iRunGroup]->GetExpFormula("clingp") << "\""; + holderCcdb.fPtSigmaDcaXyM[iRunGroup] = dynamic_cast(lRunGroup->FindObject(Form("fPtSigmaDcaXyM%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1))); + if (!holderCcdb.fPtSigmaDcaXyM[iRunGroup] || holderCcdb.fPtSigmaDcaXyM[iRunGroup]->IsA() != TFormula::Class()) { + LOG(fatal) << "Invalid " << Form("fPtSigmaDcaXyM%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1) << "!"; + } + LOG(info) << "Reading from CCDB: " << holderCcdb.fPtSigmaDcaXyM[iRunGroup]->GetName() << " \"" << holderCcdb.fPtSigmaDcaXyM[iRunGroup]->GetExpFormula("clingp") << "\""; + holderCcdb.fPtSigmaDcaZP[iRunGroup] = dynamic_cast(lRunGroup->FindObject(Form("fPtSigmaDcaZP%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1))); + if (!holderCcdb.fPtSigmaDcaZP[iRunGroup] || holderCcdb.fPtSigmaDcaZP[iRunGroup]->IsA() != TFormula::Class()) { + LOG(fatal) << "Invalid " << Form("fPtSigmaDcaZP%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1) << "!"; + } + LOG(info) << "Reading from CCDB: " << holderCcdb.fPtSigmaDcaZP[iRunGroup]->GetName() << " \"" << holderCcdb.fPtSigmaDcaZP[iRunGroup]->GetExpFormula("clingp") << "\""; + holderCcdb.fPtSigmaDcaZM[iRunGroup] = dynamic_cast(lRunGroup->FindObject(Form("fPtSigmaDcaZM%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1))); + if (!holderCcdb.fPtSigmaDcaZM[iRunGroup] || holderCcdb.fPtSigmaDcaZM[iRunGroup]->IsA() != TFormula::Class()) { + LOG(fatal) << "Invalid " << Form("fPtSigmaDcaZM%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1) << "!"; + } + LOG(info) << "Reading from CCDB: " << holderCcdb.fPtSigmaDcaZM[iRunGroup]->GetName() << " \"" << holderCcdb.fPtSigmaDcaZM[iRunGroup]->GetExpFormula("clingp") << "\""; + } } if (groupTrack.cfgFlagRecalibrationNSigmaPi.value || groupTrack.cfgFlagRecalibrationNSigmaKa.value || groupTrack.cfgFlagRecalibrationNSigmaPr.value) { @@ -975,26 +982,26 @@ struct PartNumFluc { holderCcdb.hCentralityPtEtaShiftTofNSigmaPiP.resize(nRunGroups); holderCcdb.hCentralityPtEtaShiftTofNSigmaPiM.resize(nRunGroups); for (std::int32_t const& iRunGroup : std::views::iota(0, nRunGroups)) { - const TList* const lRunGroup = static_cast(ccdbObject->FindObject(Form("lRunGroup_%d", iRunGroup + 1))); + const TList* const lRunGroup = dynamic_cast(ccdbObject->FindObject(Form("lRunGroup_%d", iRunGroup + 1))); if (!lRunGroup || lRunGroup->IsA() != TList::Class()) { LOG(fatal) << "Invalid " << Form("lRunGroup_%d", iRunGroup + 1) << "!"; } - holderCcdb.hCentralityPtEtaShiftTpcNSigmaPiP[iRunGroup] = static_cast(lRunGroup->FindObject(Form("hCentralityPtEtaShiftTpcNSigmaPiP%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1))); + holderCcdb.hCentralityPtEtaShiftTpcNSigmaPiP[iRunGroup] = dynamic_cast(lRunGroup->FindObject(Form("hCentralityPtEtaShiftTpcNSigmaPiP%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1))); if (!holderCcdb.hCentralityPtEtaShiftTpcNSigmaPiP[iRunGroup] || !holderCcdb.hCentralityPtEtaShiftTpcNSigmaPiP[iRunGroup]->InheritsFrom(TH3::Class())) { LOG(fatal) << "Invalid " << Form("hCentralityPtEtaShiftTpcNSigmaPiP%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1) << "!"; } LOG(info) << "Reading from CCDB: " << holderCcdb.hCentralityPtEtaShiftTpcNSigmaPiP[iRunGroup]->GetName(); - holderCcdb.hCentralityPtEtaShiftTpcNSigmaPiM[iRunGroup] = static_cast(lRunGroup->FindObject(Form("hCentralityPtEtaShiftTpcNSigmaPiM%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1))); + holderCcdb.hCentralityPtEtaShiftTpcNSigmaPiM[iRunGroup] = dynamic_cast(lRunGroup->FindObject(Form("hCentralityPtEtaShiftTpcNSigmaPiM%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1))); if (!holderCcdb.hCentralityPtEtaShiftTpcNSigmaPiM[iRunGroup] || !holderCcdb.hCentralityPtEtaShiftTpcNSigmaPiM[iRunGroup]->InheritsFrom(TH3::Class())) { LOG(fatal) << "Invalid " << Form("hCentralityPtEtaShiftTpcNSigmaPiM%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1) << "!"; } LOG(info) << "Reading from CCDB: " << holderCcdb.hCentralityPtEtaShiftTpcNSigmaPiM[iRunGroup]->GetName(); - holderCcdb.hCentralityPtEtaShiftTofNSigmaPiP[iRunGroup] = static_cast(lRunGroup->FindObject(Form("hCentralityPtEtaShiftTofNSigmaPiP%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1))); + holderCcdb.hCentralityPtEtaShiftTofNSigmaPiP[iRunGroup] = dynamic_cast(lRunGroup->FindObject(Form("hCentralityPtEtaShiftTofNSigmaPiP%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1))); if (!holderCcdb.hCentralityPtEtaShiftTofNSigmaPiP[iRunGroup] || !holderCcdb.hCentralityPtEtaShiftTofNSigmaPiP[iRunGroup]->InheritsFrom(TH3::Class())) { LOG(fatal) << "Invalid " << Form("hCentralityPtEtaShiftTofNSigmaPiP%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1) << "!"; } LOG(info) << "Reading from CCDB: " << holderCcdb.hCentralityPtEtaShiftTofNSigmaPiP[iRunGroup]->GetName(); - holderCcdb.hCentralityPtEtaShiftTofNSigmaPiM[iRunGroup] = static_cast(lRunGroup->FindObject(Form("hCentralityPtEtaShiftTofNSigmaPiM%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1))); + holderCcdb.hCentralityPtEtaShiftTofNSigmaPiM[iRunGroup] = dynamic_cast(lRunGroup->FindObject(Form("hCentralityPtEtaShiftTofNSigmaPiM%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1))); if (!holderCcdb.hCentralityPtEtaShiftTofNSigmaPiM[iRunGroup] || !holderCcdb.hCentralityPtEtaShiftTofNSigmaPiM[iRunGroup]->InheritsFrom(TH3::Class())) { LOG(fatal) << "Invalid " << Form("hCentralityPtEtaShiftTofNSigmaPiM%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1) << "!"; } @@ -1010,26 +1017,26 @@ struct PartNumFluc { holderCcdb.hCentralityPtEtaShiftTofNSigmaKaP.resize(nRunGroups); holderCcdb.hCentralityPtEtaShiftTofNSigmaKaM.resize(nRunGroups); for (std::int32_t const& iRunGroup : std::views::iota(0, nRunGroups)) { - const TList* const lRunGroup = static_cast(ccdbObject->FindObject(Form("lRunGroup_%d", iRunGroup + 1))); + const TList* const lRunGroup = dynamic_cast(ccdbObject->FindObject(Form("lRunGroup_%d", iRunGroup + 1))); if (!lRunGroup || lRunGroup->IsA() != TList::Class()) { LOG(fatal) << "Invalid " << Form("lRunGroup_%d", iRunGroup + 1) << "!"; } - holderCcdb.hCentralityPtEtaShiftTpcNSigmaKaP[iRunGroup] = static_cast(lRunGroup->FindObject(Form("hCentralityPtEtaShiftTpcNSigmaKaP%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1))); + holderCcdb.hCentralityPtEtaShiftTpcNSigmaKaP[iRunGroup] = dynamic_cast(lRunGroup->FindObject(Form("hCentralityPtEtaShiftTpcNSigmaKaP%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1))); if (!holderCcdb.hCentralityPtEtaShiftTpcNSigmaKaP[iRunGroup] || !holderCcdb.hCentralityPtEtaShiftTpcNSigmaKaP[iRunGroup]->InheritsFrom(TH3::Class())) { LOG(fatal) << "Invalid " << Form("hCentralityPtEtaShiftTpcNSigmaKaP%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1) << "!"; } LOG(info) << "Reading from CCDB: " << holderCcdb.hCentralityPtEtaShiftTpcNSigmaKaP[iRunGroup]->GetName(); - holderCcdb.hCentralityPtEtaShiftTpcNSigmaKaM[iRunGroup] = static_cast(lRunGroup->FindObject(Form("hCentralityPtEtaShiftTpcNSigmaKaM%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1))); + holderCcdb.hCentralityPtEtaShiftTpcNSigmaKaM[iRunGroup] = dynamic_cast(lRunGroup->FindObject(Form("hCentralityPtEtaShiftTpcNSigmaKaM%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1))); if (!holderCcdb.hCentralityPtEtaShiftTpcNSigmaKaM[iRunGroup] || !holderCcdb.hCentralityPtEtaShiftTpcNSigmaKaM[iRunGroup]->InheritsFrom(TH3::Class())) { LOG(fatal) << "Invalid " << Form("hCentralityPtEtaShiftTpcNSigmaKaM%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1) << "!"; } LOG(info) << "Reading from CCDB: " << holderCcdb.hCentralityPtEtaShiftTpcNSigmaKaM[iRunGroup]->GetName(); - holderCcdb.hCentralityPtEtaShiftTofNSigmaKaP[iRunGroup] = static_cast(lRunGroup->FindObject(Form("hCentralityPtEtaShiftTofNSigmaKaP%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1))); + holderCcdb.hCentralityPtEtaShiftTofNSigmaKaP[iRunGroup] = dynamic_cast(lRunGroup->FindObject(Form("hCentralityPtEtaShiftTofNSigmaKaP%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1))); if (!holderCcdb.hCentralityPtEtaShiftTofNSigmaKaP[iRunGroup] || !holderCcdb.hCentralityPtEtaShiftTofNSigmaKaP[iRunGroup]->InheritsFrom(TH3::Class())) { LOG(fatal) << "Invalid " << Form("hCentralityPtEtaShiftTofNSigmaKaP%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1) << "!"; } LOG(info) << "Reading from CCDB: " << holderCcdb.hCentralityPtEtaShiftTofNSigmaKaP[iRunGroup]->GetName(); - holderCcdb.hCentralityPtEtaShiftTofNSigmaKaM[iRunGroup] = static_cast(lRunGroup->FindObject(Form("hCentralityPtEtaShiftTofNSigmaKaM%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1))); + holderCcdb.hCentralityPtEtaShiftTofNSigmaKaM[iRunGroup] = dynamic_cast(lRunGroup->FindObject(Form("hCentralityPtEtaShiftTofNSigmaKaM%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1))); if (!holderCcdb.hCentralityPtEtaShiftTofNSigmaKaM[iRunGroup] || !holderCcdb.hCentralityPtEtaShiftTofNSigmaKaM[iRunGroup]->InheritsFrom(TH3::Class())) { LOG(fatal) << "Invalid " << Form("hCentralityPtEtaShiftTofNSigmaKaM%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1) << "!"; } @@ -1045,26 +1052,26 @@ struct PartNumFluc { holderCcdb.hCentralityPtEtaShiftTofNSigmaPrP.resize(nRunGroups); holderCcdb.hCentralityPtEtaShiftTofNSigmaPrM.resize(nRunGroups); for (std::int32_t const& iRunGroup : std::views::iota(0, nRunGroups)) { - const TList* const lRunGroup = static_cast(ccdbObject->FindObject(Form("lRunGroup_%d", iRunGroup + 1))); + const TList* const lRunGroup = dynamic_cast(ccdbObject->FindObject(Form("lRunGroup_%d", iRunGroup + 1))); if (!lRunGroup || lRunGroup->IsA() != TList::Class()) { LOG(fatal) << "Invalid " << Form("lRunGroup_%d", iRunGroup + 1) << "!"; } - holderCcdb.hCentralityPtEtaShiftTpcNSigmaPrP[iRunGroup] = static_cast(lRunGroup->FindObject(Form("hCentralityPtEtaShiftTpcNSigmaPrP%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1))); + holderCcdb.hCentralityPtEtaShiftTpcNSigmaPrP[iRunGroup] = dynamic_cast(lRunGroup->FindObject(Form("hCentralityPtEtaShiftTpcNSigmaPrP%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1))); if (!holderCcdb.hCentralityPtEtaShiftTpcNSigmaPrP[iRunGroup] || !holderCcdb.hCentralityPtEtaShiftTpcNSigmaPrP[iRunGroup]->InheritsFrom(TH3::Class())) { LOG(fatal) << "Invalid " << Form("hCentralityPtEtaShiftTpcNSigmaPrP%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1) << "!"; } LOG(info) << "Reading from CCDB: " << holderCcdb.hCentralityPtEtaShiftTpcNSigmaPrP[iRunGroup]->GetName(); - holderCcdb.hCentralityPtEtaShiftTpcNSigmaPrM[iRunGroup] = static_cast(lRunGroup->FindObject(Form("hCentralityPtEtaShiftTpcNSigmaPrM%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1))); + holderCcdb.hCentralityPtEtaShiftTpcNSigmaPrM[iRunGroup] = dynamic_cast(lRunGroup->FindObject(Form("hCentralityPtEtaShiftTpcNSigmaPrM%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1))); if (!holderCcdb.hCentralityPtEtaShiftTpcNSigmaPrM[iRunGroup] || !holderCcdb.hCentralityPtEtaShiftTpcNSigmaPrM[iRunGroup]->InheritsFrom(TH3::Class())) { LOG(fatal) << "Invalid " << Form("hCentralityPtEtaShiftTpcNSigmaPrM%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1) << "!"; } LOG(info) << "Reading from CCDB: " << holderCcdb.hCentralityPtEtaShiftTpcNSigmaPrM[iRunGroup]->GetName(); - holderCcdb.hCentralityPtEtaShiftTofNSigmaPrP[iRunGroup] = static_cast(lRunGroup->FindObject(Form("hCentralityPtEtaShiftTofNSigmaPrP%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1))); + holderCcdb.hCentralityPtEtaShiftTofNSigmaPrP[iRunGroup] = dynamic_cast(lRunGroup->FindObject(Form("hCentralityPtEtaShiftTofNSigmaPrP%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1))); if (!holderCcdb.hCentralityPtEtaShiftTofNSigmaPrP[iRunGroup] || !holderCcdb.hCentralityPtEtaShiftTofNSigmaPrP[iRunGroup]->InheritsFrom(TH3::Class())) { LOG(fatal) << "Invalid " << Form("hCentralityPtEtaShiftTofNSigmaPrP%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1) << "!"; } LOG(info) << "Reading from CCDB: " << holderCcdb.hCentralityPtEtaShiftTofNSigmaPrP[iRunGroup]->GetName(); - holderCcdb.hCentralityPtEtaShiftTofNSigmaPrM[iRunGroup] = static_cast(lRunGroup->FindObject(Form("hCentralityPtEtaShiftTofNSigmaPrM%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1))); + holderCcdb.hCentralityPtEtaShiftTofNSigmaPrM[iRunGroup] = dynamic_cast(lRunGroup->FindObject(Form("hCentralityPtEtaShiftTofNSigmaPrM%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1))); if (!holderCcdb.hCentralityPtEtaShiftTofNSigmaPrM[iRunGroup] || !holderCcdb.hCentralityPtEtaShiftTofNSigmaPrM[iRunGroup]->InheritsFrom(TH3::Class())) { LOG(fatal) << "Invalid " << Form("hCentralityPtEtaShiftTofNSigmaPrM%s_runGroup%d", doprocessMc.value ? "_mc" : "", iRunGroup + 1) << "!"; } @@ -1156,7 +1163,7 @@ struct PartNumFluc { hrQaEvent.add("QaEvent/hVz", "", {HistType::kTH1D, {{300, -15., 15., "#it{V}_{#it{z}} (cm)"}}}); hrQaEvent.add("QaEvent/hNPvContributorsNGlobalTracks", "", {HistType::kTHnSparseF, {{200, -0.5, 199.5, "nPvContributors"}, asNGlobalTracks}}); hrQaEvent.add("QaEvent/hNGlobalTracksMeanDcaXy", "", {HistType::kTHnSparseF, {asNGlobalTracks, {200, -0.5, 0.5, "#LTDCA_{#it{xy}}#GT_{event} (cm)"}}}); - hrQaEvent.add("QaEvent/hNGlobalTracksMeanDcaXy_nPvContributorsCut", "", {HistType::kTHnSparseF, {asNGlobalTracks, {200, -2., 2., "#LTDCA_{#it{z}}#GT_{event} (cm)"}}}); + hrQaEvent.add("QaEvent/hNGlobalTracksMeanDcaXy_nPvContributorsCut", "", {HistType::kTHnSparseF, {asNGlobalTracks, {200, -0.5, 0.5, "#LTDCA_{#it{z}}#GT_{event} (cm)"}}}); hrQaEvent.add("QaEvent/hNGlobalTracksMeanDcaZ", "", {HistType::kTHnSparseF, {asNGlobalTracks, {200, -2., 2., "#LTDCA_{#it{z}}#GT_{event} (cm)"}}}); hrQaEvent.add("QaEvent/hNGlobalTracksMeanDcaZ_nPvContributorsCut", "", {HistType::kTHnSparseF, {asNGlobalTracks, {200, -2., 2., "#LTDCA_{#it{z}}#GT_{event} (cm)"}}}); hrQaEvent.add("QaEvent/hNTofBetaNGlobalTracks", "", {HistType::kTHnSparseF, {{200, -0.5, 199.5, "nTofBeta"}, asNGlobalTracks}}); @@ -1168,9 +1175,9 @@ struct PartNumFluc { const AxisSpec asCentrality(20, 0., 100., "Centrality (%)"); - hrQaCentrality.add("QaCentrality/hCentralityFt0a", "", {HistType::kTHnSparseF, {asCentrality, {1600, 0., 8000., "FT0A Multiplicity"}}}); - hrQaCentrality.add("QaCentrality/hCentralityFt0c", "", {HistType::kTHnSparseF, {asCentrality, {400, 0., 2000., "FT0C Multiplicity"}}}); - hrQaCentrality.add("QaCentrality/hCentralityFt0m", "", {HistType::kTHnSparseF, {asCentrality, {2000, 0., 10000., "FT0M Multiplicity"}}}); + hrQaCentrality.add("QaCentrality/hCentralityFt0a", "", {HistType::kTHnSparseF, {asCentrality, {12000, 0., 12000., "FT0A Multiplicity"}}}); + hrQaCentrality.add("QaCentrality/hCentralityFt0c", "", {HistType::kTHnSparseF, {asCentrality, {3000, 0., 3000., "FT0C Multiplicity"}}}); + hrQaCentrality.add("QaCentrality/hCentralityFt0m", "", {HistType::kTHnSparseF, {asCentrality, {15000, 0., 15000., "FT0M Multiplicity"}}}); } if (groupAnalysis.cfgFlagQaTrack.value) { @@ -1582,26 +1589,26 @@ struct PartNumFluc { holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofPiP.resize(nRunGroups); holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofPiM.resize(nRunGroups); for (std::int32_t const& iRunGroup : std::views::iota(0, nRunGroups)) { - const TList* const lRunGroup = static_cast(ccdbObject->FindObject(Form("lRunGroup_%d", iRunGroup + 1))); + const TList* const lRunGroup = dynamic_cast(ccdbObject->FindObject(Form("lRunGroup_%d", iRunGroup + 1))); if (!lRunGroup || lRunGroup->IsA() != TList::Class()) { LOG(fatal) << "Invalid " << Form("lRunGroup_%d", iRunGroup + 1) << "!"; } - holderCcdb.hVzCentralityPtEtaEfficiencyTpcPiP[iRunGroup] = static_cast(lRunGroup->FindObject(Form("hVzCentralityPtEtaEfficiencyTpcPiP_runGroup%d", iRunGroup + 1))); + holderCcdb.hVzCentralityPtEtaEfficiencyTpcPiP[iRunGroup] = dynamic_cast(lRunGroup->FindObject(Form("hVzCentralityPtEtaEfficiencyTpcPiP_runGroup%d", iRunGroup + 1))); if (!holderCcdb.hVzCentralityPtEtaEfficiencyTpcPiP[iRunGroup] || !holderCcdb.hVzCentralityPtEtaEfficiencyTpcPiP[iRunGroup]->InheritsFrom(THnBase::Class()) || holderCcdb.hVzCentralityPtEtaEfficiencyTpcPiP[iRunGroup]->GetNdimensions() != NDimensionsEfficiency) { LOG(fatal) << "Invalid " << Form("hVzCentralityPtEtaEfficiencyTpcPiP_runGroup%d", iRunGroup + 1) << "!"; } LOG(info) << "Reading from CCDB: " << holderCcdb.hVzCentralityPtEtaEfficiencyTpcPiP[iRunGroup]->GetName(); - holderCcdb.hVzCentralityPtEtaEfficiencyTpcPiM[iRunGroup] = static_cast(lRunGroup->FindObject(Form("hVzCentralityPtEtaEfficiencyTpcPiM_runGroup%d", iRunGroup + 1))); + holderCcdb.hVzCentralityPtEtaEfficiencyTpcPiM[iRunGroup] = dynamic_cast(lRunGroup->FindObject(Form("hVzCentralityPtEtaEfficiencyTpcPiM_runGroup%d", iRunGroup + 1))); if (!holderCcdb.hVzCentralityPtEtaEfficiencyTpcPiM[iRunGroup] || !holderCcdb.hVzCentralityPtEtaEfficiencyTpcPiM[iRunGroup]->InheritsFrom(THnBase::Class()) || holderCcdb.hVzCentralityPtEtaEfficiencyTpcPiM[iRunGroup]->GetNdimensions() != NDimensionsEfficiency) { LOG(fatal) << "Invalid " << Form("hVzCentralityPtEtaEfficiencyTpcPiM_runGroup%d", iRunGroup + 1) << "!"; } LOG(info) << "Reading from CCDB: " << holderCcdb.hVzCentralityPtEtaEfficiencyTpcPiM[iRunGroup]->GetName(); - holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofPiP[iRunGroup] = static_cast(lRunGroup->FindObject(Form("hVzCentralityPtEtaEfficiencyTpcTofPiP_runGroup%d", iRunGroup + 1))); + holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofPiP[iRunGroup] = dynamic_cast(lRunGroup->FindObject(Form("hVzCentralityPtEtaEfficiencyTpcTofPiP_runGroup%d", iRunGroup + 1))); if (!holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofPiP[iRunGroup] || !holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofPiP[iRunGroup]->InheritsFrom(THnBase::Class()) || holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofPiP[iRunGroup]->GetNdimensions() != NDimensionsEfficiency) { LOG(fatal) << "Invalid " << Form("hVzCentralityPtEtaEfficiencyTpcTofPiP_runGroup%d", iRunGroup + 1) << "!"; } LOG(info) << "Reading from CCDB: " << holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofPiP[iRunGroup]->GetName(); - holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofPiM[iRunGroup] = static_cast(lRunGroup->FindObject(Form("hVzCentralityPtEtaEfficiencyTpcTofPiM_runGroup%d", iRunGroup + 1))); + holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofPiM[iRunGroup] = dynamic_cast(lRunGroup->FindObject(Form("hVzCentralityPtEtaEfficiencyTpcTofPiM_runGroup%d", iRunGroup + 1))); if (!holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofPiM[iRunGroup] || !holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofPiM[iRunGroup]->InheritsFrom(THnBase::Class()) || holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofPiM[iRunGroup]->GetNdimensions() != NDimensionsEfficiency) { LOG(fatal) << "Invalid " << Form("hVzCentralityPtEtaEfficiencyTpcTofPiM_runGroup%d", iRunGroup + 1) << "!"; } @@ -1615,26 +1622,26 @@ struct PartNumFluc { holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofKaP.resize(nRunGroups); holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofKaM.resize(nRunGroups); for (std::int32_t const& iRunGroup : std::views::iota(0, nRunGroups)) { - const TList* const lRunGroup = static_cast(ccdbObject->FindObject(Form("lRunGroup_%d", iRunGroup + 1))); + const TList* const lRunGroup = dynamic_cast(ccdbObject->FindObject(Form("lRunGroup_%d", iRunGroup + 1))); if (!lRunGroup || lRunGroup->IsA() != TList::Class()) { LOG(fatal) << "Invalid " << Form("lRunGroup_%d", iRunGroup + 1) << "!"; } - holderCcdb.hVzCentralityPtEtaEfficiencyTpcKaP[iRunGroup] = static_cast(lRunGroup->FindObject(Form("hVzCentralityPtEtaEfficiencyTpcKaP_runGroup%d", iRunGroup + 1))); + holderCcdb.hVzCentralityPtEtaEfficiencyTpcKaP[iRunGroup] = dynamic_cast(lRunGroup->FindObject(Form("hVzCentralityPtEtaEfficiencyTpcKaP_runGroup%d", iRunGroup + 1))); if (!holderCcdb.hVzCentralityPtEtaEfficiencyTpcKaP[iRunGroup] || !holderCcdb.hVzCentralityPtEtaEfficiencyTpcKaP[iRunGroup]->InheritsFrom(THnBase::Class()) || holderCcdb.hVzCentralityPtEtaEfficiencyTpcKaP[iRunGroup]->GetNdimensions() != NDimensionsEfficiency) { LOG(fatal) << "Invalid " << Form("hVzCentralityPtEtaEfficiencyTpcKaP_runGroup%d", iRunGroup + 1) << "!"; } LOG(info) << "Reading from CCDB: " << holderCcdb.hVzCentralityPtEtaEfficiencyTpcKaP[iRunGroup]->GetName(); - holderCcdb.hVzCentralityPtEtaEfficiencyTpcKaM[iRunGroup] = static_cast(lRunGroup->FindObject(Form("hVzCentralityPtEtaEfficiencyTpcKaM_runGroup%d", iRunGroup + 1))); + holderCcdb.hVzCentralityPtEtaEfficiencyTpcKaM[iRunGroup] = dynamic_cast(lRunGroup->FindObject(Form("hVzCentralityPtEtaEfficiencyTpcKaM_runGroup%d", iRunGroup + 1))); if (!holderCcdb.hVzCentralityPtEtaEfficiencyTpcKaM[iRunGroup] || !holderCcdb.hVzCentralityPtEtaEfficiencyTpcKaM[iRunGroup]->InheritsFrom(THnBase::Class()) || holderCcdb.hVzCentralityPtEtaEfficiencyTpcKaM[iRunGroup]->GetNdimensions() != NDimensionsEfficiency) { LOG(fatal) << "Invalid " << Form("hVzCentralityPtEtaEfficiencyTpcKaM_runGroup%d", iRunGroup + 1) << "!"; } LOG(info) << "Reading from CCDB: " << holderCcdb.hVzCentralityPtEtaEfficiencyTpcKaM[iRunGroup]->GetName(); - holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofKaP[iRunGroup] = static_cast(lRunGroup->FindObject(Form("hVzCentralityPtEtaEfficiencyTpcTofKaP_runGroup%d", iRunGroup + 1))); + holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofKaP[iRunGroup] = dynamic_cast(lRunGroup->FindObject(Form("hVzCentralityPtEtaEfficiencyTpcTofKaP_runGroup%d", iRunGroup + 1))); if (!holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofKaP[iRunGroup] || !holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofKaP[iRunGroup]->InheritsFrom(THnBase::Class()) || holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofKaP[iRunGroup]->GetNdimensions() != NDimensionsEfficiency) { LOG(fatal) << "Invalid " << Form("hVzCentralityPtEtaEfficiencyTpcTofKaP_runGroup%d", iRunGroup + 1) << "!"; } LOG(info) << "Reading from CCDB: " << holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofKaP[iRunGroup]->GetName(); - holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofKaM[iRunGroup] = static_cast(lRunGroup->FindObject(Form("hVzCentralityPtEtaEfficiencyTpcTofKaM_runGroup%d", iRunGroup + 1))); + holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofKaM[iRunGroup] = dynamic_cast(lRunGroup->FindObject(Form("hVzCentralityPtEtaEfficiencyTpcTofKaM_runGroup%d", iRunGroup + 1))); if (!holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofKaM[iRunGroup] || !holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofKaM[iRunGroup]->InheritsFrom(THnBase::Class()) || holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofKaM[iRunGroup]->GetNdimensions() != NDimensionsEfficiency) { LOG(fatal) << "Invalid " << Form("hVzCentralityPtEtaEfficiencyTpcTofKaM_runGroup%d", iRunGroup + 1) << "!"; } @@ -1648,26 +1655,26 @@ struct PartNumFluc { holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofPrP.resize(nRunGroups); holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofPrM.resize(nRunGroups); for (std::int32_t const& iRunGroup : std::views::iota(0, nRunGroups)) { - const TList* const lRunGroup = static_cast(ccdbObject->FindObject(Form("lRunGroup_%d", iRunGroup + 1))); + const TList* const lRunGroup = dynamic_cast(ccdbObject->FindObject(Form("lRunGroup_%d", iRunGroup + 1))); if (!lRunGroup || lRunGroup->IsA() != TList::Class()) { LOG(fatal) << "Invalid " << Form("lRunGroup_%d", iRunGroup + 1) << "!"; } - holderCcdb.hVzCentralityPtEtaEfficiencyTpcPrP[iRunGroup] = static_cast(lRunGroup->FindObject(Form("hVzCentralityPtEtaEfficiencyTpcPrP_runGroup%d", iRunGroup + 1))); + holderCcdb.hVzCentralityPtEtaEfficiencyTpcPrP[iRunGroup] = dynamic_cast(lRunGroup->FindObject(Form("hVzCentralityPtEtaEfficiencyTpcPrP_runGroup%d", iRunGroup + 1))); if (!holderCcdb.hVzCentralityPtEtaEfficiencyTpcPrP[iRunGroup] || !holderCcdb.hVzCentralityPtEtaEfficiencyTpcPrP[iRunGroup]->InheritsFrom(THnBase::Class()) || holderCcdb.hVzCentralityPtEtaEfficiencyTpcPrP[iRunGroup]->GetNdimensions() != NDimensionsEfficiency) { LOG(fatal) << "Invalid " << Form("hVzCentralityPtEtaEfficiencyTpcPrP_runGroup%d", iRunGroup + 1) << "!"; } LOG(info) << "Reading from CCDB: " << holderCcdb.hVzCentralityPtEtaEfficiencyTpcPrP[iRunGroup]->GetName(); - holderCcdb.hVzCentralityPtEtaEfficiencyTpcPrM[iRunGroup] = static_cast(lRunGroup->FindObject(Form("hVzCentralityPtEtaEfficiencyTpcPrM_runGroup%d", iRunGroup + 1))); + holderCcdb.hVzCentralityPtEtaEfficiencyTpcPrM[iRunGroup] = dynamic_cast(lRunGroup->FindObject(Form("hVzCentralityPtEtaEfficiencyTpcPrM_runGroup%d", iRunGroup + 1))); if (!holderCcdb.hVzCentralityPtEtaEfficiencyTpcPrM[iRunGroup] || !holderCcdb.hVzCentralityPtEtaEfficiencyTpcPrM[iRunGroup]->InheritsFrom(THnBase::Class()) || holderCcdb.hVzCentralityPtEtaEfficiencyTpcPrM[iRunGroup]->GetNdimensions() != NDimensionsEfficiency) { LOG(fatal) << "Invalid " << Form("hVzCentralityPtEtaEfficiencyTpcPrM_runGroup%d", iRunGroup + 1) << "!"; } LOG(info) << "Reading from CCDB: " << holderCcdb.hVzCentralityPtEtaEfficiencyTpcPrM[iRunGroup]->GetName(); - holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofPrP[iRunGroup] = static_cast(lRunGroup->FindObject(Form("hVzCentralityPtEtaEfficiencyTpcTofPrP_runGroup%d", iRunGroup + 1))); + holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofPrP[iRunGroup] = dynamic_cast(lRunGroup->FindObject(Form("hVzCentralityPtEtaEfficiencyTpcTofPrP_runGroup%d", iRunGroup + 1))); if (!holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofPrP[iRunGroup] || !holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofPrP[iRunGroup]->InheritsFrom(THnBase::Class()) || holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofPrP[iRunGroup]->GetNdimensions() != NDimensionsEfficiency) { LOG(fatal) << "Invalid " << Form("hVzCentralityPtEtaEfficiencyTpcTofPrP_runGroup%d", iRunGroup + 1) << "!"; } LOG(info) << "Reading from CCDB: " << holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofPrP[iRunGroup]->GetName(); - holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofPrM[iRunGroup] = static_cast(lRunGroup->FindObject(Form("hVzCentralityPtEtaEfficiencyTpcTofPrM_runGroup%d", iRunGroup + 1))); + holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofPrM[iRunGroup] = dynamic_cast(lRunGroup->FindObject(Form("hVzCentralityPtEtaEfficiencyTpcTofPrM_runGroup%d", iRunGroup + 1))); if (!holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofPrM[iRunGroup] || !holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofPrM[iRunGroup]->InheritsFrom(THnBase::Class()) || holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofPrM[iRunGroup]->GetNdimensions() != NDimensionsEfficiency) { LOG(fatal) << "Invalid " << Form("hVzCentralityPtEtaEfficiencyTpcTofPrM_runGroup%d", iRunGroup + 1) << "!"; } @@ -1772,6 +1779,8 @@ struct PartNumFluc { if (!groupTrack.cfgFlagRecalibrationNSigmaPr.value) { return 0.; } + } else { + return 0.; } static const std::array*, 2>, 2>, static_cast(ParticleSpecies::kNSpecies)> pointersVectorHistogramShiftNSigmaPid = {{{{{&holderCcdb.hCentralityPtEtaShiftTpcNSigmaPiP, &holderCcdb.hCentralityPtEtaShiftTofNSigmaPiP}, {&holderCcdb.hCentralityPtEtaShiftTpcNSigmaPiM, &holderCcdb.hCentralityPtEtaShiftTofNSigmaPiM}}}, {{{&holderCcdb.hCentralityPtEtaShiftTpcNSigmaKaP, &holderCcdb.hCentralityPtEtaShiftTofNSigmaKaP}, {&holderCcdb.hCentralityPtEtaShiftTpcNSigmaKaM, &holderCcdb.hCentralityPtEtaShiftTofNSigmaKaM}}}, {{{&holderCcdb.hCentralityPtEtaShiftTpcNSigmaPrP, &holderCcdb.hCentralityPtEtaShiftTofNSigmaPrP}, {&holderCcdb.hCentralityPtEtaShiftTpcNSigmaPrM, &holderCcdb.hCentralityPtEtaShiftTofNSigmaPrM}}}}}; @@ -1780,7 +1789,12 @@ struct PartNumFluc { return 0.; } const TH3* const hCentralityPtEtaShiftNSigmaPid = pointersVectorHistogramShiftNSigmaPid[static_cast(particleSpecies)][holderTrack.sign > 0 ? 0 : 1][pidStrategy == PidStrategy::kTpc ? 0 : 1]->at(std::abs(holderEvent.runGroupIndex) - 1); - return hCentralityPtEtaShiftNSigmaPid ? hCentralityPtEtaShiftNSigmaPid->Interpolate(std::max(std::nextafter(hCentralityPtEtaShiftNSigmaPid->GetXaxis()->GetBinCenter(1), std::numeric_limits::infinity()), std::min(holderEvent.centrality, std::nextafter(hCentralityPtEtaShiftNSigmaPid->GetXaxis()->GetBinCenter(hCentralityPtEtaShiftNSigmaPid->GetNbinsX()), -std::numeric_limits::infinity()))), std::max(std::nextafter(hCentralityPtEtaShiftNSigmaPid->GetYaxis()->GetBinCenter(1), std::numeric_limits::infinity()), std::min(holderTrack.pt, std::nextafter(hCentralityPtEtaShiftNSigmaPid->GetYaxis()->GetBinCenter(hCentralityPtEtaShiftNSigmaPid->GetNbinsY()), -std::numeric_limits::infinity()))), std::max(std::nextafter(hCentralityPtEtaShiftNSigmaPid->GetZaxis()->GetBinCenter(1), std::numeric_limits::infinity()), std::min(holderTrack.eta, std::nextafter(hCentralityPtEtaShiftNSigmaPid->GetZaxis()->GetBinCenter(hCentralityPtEtaShiftNSigmaPid->GetNbinsZ()), -std::numeric_limits::infinity())))) : 0.; + auto clampInAxis = [](const double value, const TAxis* const axis) { + const std::int32_t first = std::clamp(axis->GetFirst(), 1, axis->GetNbins()); + const std::int32_t last = std::clamp(axis->GetLast(), 1, axis->GetNbins()); + return first == last ? axis->GetBinCenter(first) : std::clamp(value, std::nextafter(axis->GetBinCenter(first), std::numeric_limits::infinity()), std::nextafter(axis->GetBinCenter(last), -std::numeric_limits::infinity())); + }; + return hCentralityPtEtaShiftNSigmaPid ? hCentralityPtEtaShiftNSigmaPid->Interpolate(clampInAxis(holderEvent.centrality, hCentralityPtEtaShiftNSigmaPid->GetXaxis()), clampInAxis(holderTrack.pt, hCentralityPtEtaShiftNSigmaPid->GetYaxis()), clampInAxis(holderTrack.eta, hCentralityPtEtaShiftNSigmaPid->GetZaxis())) : 0.; } template @@ -1793,41 +1807,41 @@ struct PartNumFluc { if constexpr (pidStrategy == PidStrategy::kTpc) { if (doRejectingOthers) { - if (!(std::fabs(*pointersNSigmaPid[static_cast(particleSpecies)][0]) < std::min(groupTrack.cfgCutMaxAbsNSigmaPid.value, std::min(std::fabs(*pointersNSigmaPid[(static_cast(particleSpecies) + 1) % static_cast(ParticleSpecies::kNSpecies)][0]), std::fabs(*pointersNSigmaPid[(static_cast(particleSpecies) + 2) % static_cast(ParticleSpecies::kNSpecies)][0]))))) { + if (!(std::abs(*pointersNSigmaPid[static_cast(particleSpecies)][0]) < std::min({groupTrack.cfgCutMaxAbsNSigmaPid.value, std::abs(*pointersNSigmaPid[(static_cast(particleSpecies) + 1) % static_cast(ParticleSpecies::kNSpecies)][0]), std::abs(*pointersNSigmaPid[(static_cast(particleSpecies) + 2) % static_cast(ParticleSpecies::kNSpecies)][0])}))) { return 0; } } else { - if (!(std::fabs(*pointersNSigmaPid[static_cast(particleSpecies)][0]) < groupTrack.cfgCutMaxAbsNSigmaPid.value)) { + if (!(std::abs(*pointersNSigmaPid[static_cast(particleSpecies)][0]) < groupTrack.cfgCutMaxAbsNSigmaPid.value)) { return 0; } } } else if constexpr (pidStrategy == PidStrategy::kTof) { if (doRejectingOthers) { - if (!(std::fabs(*pointersNSigmaPid[static_cast(particleSpecies)][1]) < std::min(groupTrack.cfgCutMaxAbsNSigmaPid.value, std::min(std::fabs(*pointersNSigmaPid[(static_cast(particleSpecies) + 1) % static_cast(ParticleSpecies::kNSpecies)][1]), std::fabs(*pointersNSigmaPid[(static_cast(particleSpecies) + 2) % static_cast(ParticleSpecies::kNSpecies)][1]))))) { + if (!(std::abs(*pointersNSigmaPid[static_cast(particleSpecies)][1]) < std::min({groupTrack.cfgCutMaxAbsNSigmaPid.value, std::abs(*pointersNSigmaPid[(static_cast(particleSpecies) + 1) % static_cast(ParticleSpecies::kNSpecies)][1]), std::abs(*pointersNSigmaPid[(static_cast(particleSpecies) + 2) % static_cast(ParticleSpecies::kNSpecies)][1])}))) { return 0; } } else { - if (!(std::fabs(*pointersNSigmaPid[static_cast(particleSpecies)][1]) < groupTrack.cfgCutMaxAbsNSigmaPid.value)) { + if (!(std::abs(*pointersNSigmaPid[static_cast(particleSpecies)][1]) < groupTrack.cfgCutMaxAbsNSigmaPid.value)) { return 0; } } } else if constexpr (pidStrategy == PidStrategy::kTpcAndTof) { if (doRejectingOthers) { - if (!(std::fabs(*pointersNSigmaPid[static_cast(particleSpecies)][0]) < groupTrack.cfgCutMaxAbsNSigmaPid.value && std::fabs(*pointersNSigmaPid[static_cast(particleSpecies)][1]) < std::min(groupTrack.cfgCutMaxAbsNSigmaPid.value, std::min(std::fabs(*pointersNSigmaPid[(static_cast(particleSpecies) + 1) % static_cast(ParticleSpecies::kNSpecies)][1]), std::fabs(*pointersNSigmaPid[(static_cast(particleSpecies) + 2) % static_cast(ParticleSpecies::kNSpecies)][1]))))) { + if (!(std::abs(*pointersNSigmaPid[static_cast(particleSpecies)][0]) < groupTrack.cfgCutMaxAbsNSigmaPid.value && std::abs(*pointersNSigmaPid[static_cast(particleSpecies)][1]) < std::min({groupTrack.cfgCutMaxAbsNSigmaPid.value, std::abs(*pointersNSigmaPid[(static_cast(particleSpecies) + 1) % static_cast(ParticleSpecies::kNSpecies)][1]), std::abs(*pointersNSigmaPid[(static_cast(particleSpecies) + 2) % static_cast(ParticleSpecies::kNSpecies)][1])}))) { return 0; } } else { - if (!(std::fabs(*pointersNSigmaPid[static_cast(particleSpecies)][0]) < groupTrack.cfgCutMaxAbsNSigmaPid.value && std::fabs(*pointersNSigmaPid[static_cast(particleSpecies)][1]) < groupTrack.cfgCutMaxAbsNSigmaPid.value)) { + if (!(std::abs(*pointersNSigmaPid[static_cast(particleSpecies)][0]) < groupTrack.cfgCutMaxAbsNSigmaPid.value && std::abs(*pointersNSigmaPid[static_cast(particleSpecies)][1]) < groupTrack.cfgCutMaxAbsNSigmaPid.value)) { return 0; } } } else if constexpr (pidStrategy == PidStrategy::kTpcTof) { if (doRejectingOthers) { - if (!(std::fabs(*pointersNSigmaPid[static_cast(particleSpecies)][2]) < std::min(groupTrack.cfgCutMaxAbsNSigmaPid.value, std::min(std::fabs(*pointersNSigmaPid[(static_cast(particleSpecies) + 1) % static_cast(ParticleSpecies::kNSpecies)][2]), std::fabs(*pointersNSigmaPid[(static_cast(particleSpecies) + 2) % static_cast(ParticleSpecies::kNSpecies)][2]))))) { + if (!(std::abs(*pointersNSigmaPid[static_cast(particleSpecies)][2]) < std::min({groupTrack.cfgCutMaxAbsNSigmaPid.value, std::abs(*pointersNSigmaPid[(static_cast(particleSpecies) + 1) % static_cast(ParticleSpecies::kNSpecies)][2]), std::abs(*pointersNSigmaPid[(static_cast(particleSpecies) + 2) % static_cast(ParticleSpecies::kNSpecies)][2])}))) { return 0; } } else { - if (!(std::fabs(*pointersNSigmaPid[static_cast(particleSpecies)][2]) < groupTrack.cfgCutMaxAbsNSigmaPid.value)) { + if (!(std::abs(*pointersNSigmaPid[static_cast(particleSpecies)][2]) < groupTrack.cfgCutMaxAbsNSigmaPid.value)) { return 0; } } @@ -1844,14 +1858,14 @@ struct PartNumFluc { if (!(groupTrack.cfgCutMinPt.value < holderMcParticle.pt && holderMcParticle.pt < groupTrack.cfgCutMaxPt.value)) { return false; } - if (!(std::fabs(holderMcParticle.eta) < groupTrack.cfgCutMaxAbsEta.value)) { + if (!(std::abs(holderMcParticle.eta) < groupTrack.cfgCutMaxAbsEta.value)) { return false; } } else { if (!(groupTrack.cfgCutMinPt.value < holderTrack.pt && holderTrack.pt < groupTrack.cfgCutMaxPt.value)) { return false; } - if (!(std::fabs(holderTrack.eta) < groupTrack.cfgCutMaxAbsEta.value)) { + if (!(std::abs(holderTrack.eta) < groupTrack.cfgCutMaxAbsEta.value)) { return false; } } @@ -1860,18 +1874,27 @@ struct PartNumFluc { bool isGoodDca() { - if (holderTrack.sign == 0) { - return false; - } - const TFormula* const fPtMeanDcaXy = (holderTrack.sign > 0 ? holderCcdb.fPtMeanDcaXyP.at(std::abs(holderEvent.runGroupIndex) - 1) : holderCcdb.fPtMeanDcaXyM.at(std::abs(holderEvent.runGroupIndex) - 1)); - const TFormula* const fPtSigmaDcaXy = (holderTrack.sign > 0 ? holderCcdb.fPtSigmaDcaXyP.at(std::abs(holderEvent.runGroupIndex) - 1) : holderCcdb.fPtSigmaDcaXyM.at(std::abs(holderEvent.runGroupIndex) - 1)); - if (!fPtMeanDcaXy || !fPtSigmaDcaXy || !(std::fabs(holderTrack.dcaXY - fPtMeanDcaXy->Eval(holderTrack.pt)) < groupTrack.cfgCutMaxAbsNSigmaDcaXy.value * fPtSigmaDcaXy->Eval(holderTrack.pt))) { - return false; - } - const TFormula* const fPtMeanDcaZ = (holderTrack.sign > 0 ? holderCcdb.fPtMeanDcaZP.at(std::abs(holderEvent.runGroupIndex) - 1) : holderCcdb.fPtMeanDcaZM.at(std::abs(holderEvent.runGroupIndex) - 1)); - const TFormula* const fPtSigmaDcaZ = (holderTrack.sign > 0 ? holderCcdb.fPtSigmaDcaZP.at(std::abs(holderEvent.runGroupIndex) - 1) : holderCcdb.fPtSigmaDcaZM.at(std::abs(holderEvent.runGroupIndex) - 1)); - if (!fPtMeanDcaZ || !fPtSigmaDcaZ || !(std::fabs(holderTrack.dcaZ - fPtMeanDcaZ->Eval(holderTrack.pt)) < groupTrack.cfgCutMaxAbsNSigmaDcaZ.value * fPtSigmaDcaZ->Eval(holderTrack.pt))) { - return false; + if (!groupTrack.cfgFlagRecalibrationDca.value) { + if (!(std::abs(holderTrack.dcaXY) < groupTrack.cfgCutMaxAbsNSigmaDcaXy.value)) { + return false; + } + if (!(std::abs(holderTrack.dcaZ) < groupTrack.cfgCutMaxAbsNSigmaDcaZ.value)) { + return false; + } + } else { + if (holderTrack.sign == 0) { + return false; + } + const TFormula* const fPtMeanDcaXy = (holderTrack.sign > 0 ? holderCcdb.fPtMeanDcaXyP.at(std::abs(holderEvent.runGroupIndex) - 1) : holderCcdb.fPtMeanDcaXyM.at(std::abs(holderEvent.runGroupIndex) - 1)); + const TFormula* const fPtSigmaDcaXy = (holderTrack.sign > 0 ? holderCcdb.fPtSigmaDcaXyP.at(std::abs(holderEvent.runGroupIndex) - 1) : holderCcdb.fPtSigmaDcaXyM.at(std::abs(holderEvent.runGroupIndex) - 1)); + if (!fPtMeanDcaXy || !fPtSigmaDcaXy || !(std::abs(holderTrack.dcaXY - fPtMeanDcaXy->Eval(holderTrack.pt)) < groupTrack.cfgCutMaxAbsNSigmaDcaXy.value * fPtSigmaDcaXy->Eval(holderTrack.pt))) { + return false; + } + const TFormula* const fPtMeanDcaZ = (holderTrack.sign > 0 ? holderCcdb.fPtMeanDcaZP.at(std::abs(holderEvent.runGroupIndex) - 1) : holderCcdb.fPtMeanDcaZM.at(std::abs(holderEvent.runGroupIndex) - 1)); + const TFormula* const fPtSigmaDcaZ = (holderTrack.sign > 0 ? holderCcdb.fPtSigmaDcaZP.at(std::abs(holderEvent.runGroupIndex) - 1) : holderCcdb.fPtSigmaDcaZM.at(std::abs(holderEvent.runGroupIndex) - 1)); + if (!fPtMeanDcaZ || !fPtSigmaDcaZ || !(std::abs(holderTrack.dcaZ - fPtMeanDcaZ->Eval(holderTrack.pt)) < groupTrack.cfgCutMaxAbsNSigmaDcaZ.value * fPtSigmaDcaZ->Eval(holderTrack.pt))) { + return false; + } } return true; } @@ -1945,9 +1968,9 @@ struct PartNumFluc { holderTrack.tofNSigmaPi = holderTrack.tofNSigmaKa = holderTrack.tofNSigmaPr = HolderTrack::truncateNSigmaPid(HolderTrack::TruncationAbsNSigmaPid); } if (holderTrack.hasTpcPid && holderTrack.hasTofPid) { - holderTrack.tpcTofNSigmaPi = HolderTrack::truncateNSigmaPid(std::copysign(std::hypot(holderTrack.tpcNSigmaPi, holderTrack.tofNSigmaPi), std::fabs(holderTrack.tpcNSigmaPi) >= std::fabs(holderTrack.tofNSigmaPi) ? holderTrack.tpcNSigmaPi : holderTrack.tofNSigmaPi)); - holderTrack.tpcTofNSigmaKa = HolderTrack::truncateNSigmaPid(std::copysign(std::hypot(holderTrack.tpcNSigmaKa, holderTrack.tofNSigmaKa), std::fabs(holderTrack.tpcNSigmaKa) >= std::fabs(holderTrack.tofNSigmaKa) ? holderTrack.tpcNSigmaKa : holderTrack.tofNSigmaKa)); - holderTrack.tpcTofNSigmaPr = HolderTrack::truncateNSigmaPid(std::copysign(std::hypot(holderTrack.tpcNSigmaPr, holderTrack.tofNSigmaPr), std::fabs(holderTrack.tpcNSigmaPr) >= std::fabs(holderTrack.tofNSigmaPr) ? holderTrack.tpcNSigmaPr : holderTrack.tofNSigmaPr)); + holderTrack.tpcTofNSigmaPi = HolderTrack::truncateNSigmaPid(std::copysign(std::hypot(holderTrack.tpcNSigmaPi, holderTrack.tofNSigmaPi), std::abs(holderTrack.tpcNSigmaPi) >= std::abs(holderTrack.tofNSigmaPi) ? holderTrack.tpcNSigmaPi : holderTrack.tofNSigmaPi)); + holderTrack.tpcTofNSigmaKa = HolderTrack::truncateNSigmaPid(std::copysign(std::hypot(holderTrack.tpcNSigmaKa, holderTrack.tofNSigmaKa), std::abs(holderTrack.tpcNSigmaKa) >= std::abs(holderTrack.tofNSigmaKa) ? holderTrack.tpcNSigmaKa : holderTrack.tofNSigmaKa)); + holderTrack.tpcTofNSigmaPr = HolderTrack::truncateNSigmaPid(std::copysign(std::hypot(holderTrack.tpcNSigmaPr, holderTrack.tofNSigmaPr), std::abs(holderTrack.tpcNSigmaPr) >= std::abs(holderTrack.tofNSigmaPr) ? holderTrack.tpcNSigmaPr : holderTrack.tofNSigmaPr)); } else { holderTrack.tpcTofNSigmaPi = holderTrack.tpcTofNSigmaKa = holderTrack.tpcTofNSigmaPr = HolderTrack::truncateNSigmaPid(HolderTrack::TruncationAbsNSigmaPid); } @@ -2001,25 +2024,25 @@ struct PartNumFluc { hrQaRun.fill(HIST("QaRun/pRunIndexPhi_p"), holderEvent.runIndex, holderTrack.phi); if (holderTrack.hasTpcPid) { hrQaRun.fill(HIST("QaRun/pRunIndexTpcDeDx_p"), holderEvent.runIndex, track.tpcSignal()); - if (std::fabs(holderTrack.tpcNSigmaPi) < HolderTrack::TruncationAbsNSigmaPid) { + if (std::abs(holderTrack.tpcNSigmaPi) < HolderTrack::TruncationAbsNSigmaPid) { hrQaRun.fill(HIST("QaRun/pRunIndexTpcNSigmaPi_p"), holderEvent.runIndex, holderTrack.tpcNSigmaPi); } - if (std::fabs(holderTrack.tpcNSigmaKa) < HolderTrack::TruncationAbsNSigmaPid) { + if (std::abs(holderTrack.tpcNSigmaKa) < HolderTrack::TruncationAbsNSigmaPid) { hrQaRun.fill(HIST("QaRun/pRunIndexTpcNSigmaKa_p"), holderEvent.runIndex, holderTrack.tpcNSigmaKa); } - if (std::fabs(holderTrack.tpcNSigmaPr) < HolderTrack::TruncationAbsNSigmaPid) { + if (std::abs(holderTrack.tpcNSigmaPr) < HolderTrack::TruncationAbsNSigmaPid) { hrQaRun.fill(HIST("QaRun/pRunIndexTpcNSigmaPr_p"), holderEvent.runIndex, holderTrack.tpcNSigmaPr); } } if (holderTrack.hasTofPid) { hrQaRun.fill(HIST("QaRun/pRunIndexTofInverseBeta_p"), holderEvent.runIndex, 1. / track.beta()); - if (std::fabs(holderTrack.tofNSigmaPi) < HolderTrack::TruncationAbsNSigmaPid) { + if (std::abs(holderTrack.tofNSigmaPi) < HolderTrack::TruncationAbsNSigmaPid) { hrQaRun.fill(HIST("QaRun/pRunIndexTofNSigmaPi_p"), holderEvent.runIndex, holderTrack.tofNSigmaPi); } - if (std::fabs(holderTrack.tofNSigmaKa) < HolderTrack::TruncationAbsNSigmaPid) { + if (std::abs(holderTrack.tofNSigmaKa) < HolderTrack::TruncationAbsNSigmaPid) { hrQaRun.fill(HIST("QaRun/pRunIndexTofNSigmaKa_p"), holderEvent.runIndex, holderTrack.tofNSigmaKa); } - if (std::fabs(holderTrack.tofNSigmaPr) < HolderTrack::TruncationAbsNSigmaPid) { + if (std::abs(holderTrack.tofNSigmaPr) < HolderTrack::TruncationAbsNSigmaPid) { hrQaRun.fill(HIST("QaRun/pRunIndexTofNSigmaPr_p"), holderEvent.runIndex, holderTrack.tofNSigmaPr); } } @@ -2038,25 +2061,25 @@ struct PartNumFluc { hrQaRun.fill(HIST("QaRun/pRunIndexPhi_m"), holderEvent.runIndex, holderTrack.phi); if (holderTrack.hasTpcPid) { hrQaRun.fill(HIST("QaRun/pRunIndexTpcDeDx_m"), holderEvent.runIndex, track.tpcSignal()); - if (std::fabs(holderTrack.tpcNSigmaPi) < HolderTrack::TruncationAbsNSigmaPid) { + if (std::abs(holderTrack.tpcNSigmaPi) < HolderTrack::TruncationAbsNSigmaPid) { hrQaRun.fill(HIST("QaRun/pRunIndexTpcNSigmaPi_m"), holderEvent.runIndex, holderTrack.tpcNSigmaPi); } - if (std::fabs(holderTrack.tpcNSigmaKa) < HolderTrack::TruncationAbsNSigmaPid) { + if (std::abs(holderTrack.tpcNSigmaKa) < HolderTrack::TruncationAbsNSigmaPid) { hrQaRun.fill(HIST("QaRun/pRunIndexTpcNSigmaKa_m"), holderEvent.runIndex, holderTrack.tpcNSigmaKa); } - if (std::fabs(holderTrack.tpcNSigmaPr) < HolderTrack::TruncationAbsNSigmaPid) { + if (std::abs(holderTrack.tpcNSigmaPr) < HolderTrack::TruncationAbsNSigmaPid) { hrQaRun.fill(HIST("QaRun/pRunIndexTpcNSigmaPr_m"), holderEvent.runIndex, holderTrack.tpcNSigmaPr); } } if (holderTrack.hasTofPid) { hrQaRun.fill(HIST("QaRun/pRunIndexTofInverseBeta_m"), holderEvent.runIndex, 1. / track.beta()); - if (std::fabs(holderTrack.tofNSigmaPi) < HolderTrack::TruncationAbsNSigmaPid) { + if (std::abs(holderTrack.tofNSigmaPi) < HolderTrack::TruncationAbsNSigmaPid) { hrQaRun.fill(HIST("QaRun/pRunIndexTofNSigmaPi_m"), holderEvent.runIndex, holderTrack.tofNSigmaPi); } - if (std::fabs(holderTrack.tofNSigmaKa) < HolderTrack::TruncationAbsNSigmaPid) { + if (std::abs(holderTrack.tofNSigmaKa) < HolderTrack::TruncationAbsNSigmaPid) { hrQaRun.fill(HIST("QaRun/pRunIndexTofNSigmaKa_m"), holderEvent.runIndex, holderTrack.tofNSigmaKa); } - if (std::fabs(holderTrack.tofNSigmaPr) < HolderTrack::TruncationAbsNSigmaPid) { + if (std::abs(holderTrack.tofNSigmaPr) < HolderTrack::TruncationAbsNSigmaPid) { hrQaRun.fill(HIST("QaRun/pRunIndexTofNSigmaPr_m"), holderEvent.runIndex, holderTrack.tofNSigmaPr); } } @@ -2288,7 +2311,7 @@ struct PartNumFluc { hrQaEvent.fill(HIST("QaEvent/hVz"), holderEvent.vz); } - if (!(std::fabs(holderEvent.vz) < groupEvent.cfgCutMaxAbsVertexZ.value)) { + if (!(std::abs(holderEvent.vz) < groupEvent.cfgCutMaxAbsVertexZ.value)) { hrCounter.fill(HIST("hNEvents"), 6.); return false; } @@ -2299,13 +2322,13 @@ struct PartNumFluc { hrQaRun.fill(HIST("QaRun/pRunIndexVz"), holderEvent.runIndex, holderEvent.vz); hrQaRun.fill(HIST("QaRun/pRunIndexMultiplicityFt0a"), holderEvent.runIndex, collision.multZeqFT0A()); hrQaRun.fill(HIST("QaRun/pRunIndexMultiplicityFt0c"), holderEvent.runIndex, collision.multZeqFT0C()); - if (0. <= collision.centFT0A() && collision.centFT0A() <= 100.) { + if (HolderEvent::RangeCentrality.first <= collision.centFT0A() && collision.centFT0A() <= HolderEvent::RangeCentrality.second) { hrQaRun.fill(HIST("QaRun/pRunIndexCentralityFt0a"), holderEvent.runIndex, collision.centFT0A()); } - if (0. <= collision.centFT0C() && collision.centFT0C() <= 100.) { + if (HolderEvent::RangeCentrality.first <= collision.centFT0C() && collision.centFT0C() <= HolderEvent::RangeCentrality.second) { hrQaRun.fill(HIST("QaRun/pRunIndexCentralityFt0c"), holderEvent.runIndex, collision.centFT0C()); } - if (0. <= collision.centFT0M() && collision.centFT0M() <= 100.) { + if (HolderEvent::RangeCentrality.first <= collision.centFT0M() && collision.centFT0M() <= HolderEvent::RangeCentrality.second) { hrQaRun.fill(HIST("QaRun/pRunIndexCentralityFt0m"), holderEvent.runIndex, collision.centFT0M()); } } @@ -2646,7 +2669,7 @@ struct PartNumFluc { return false; } - if (!(std::fabs(holderMcEvent.vz) < groupEvent.cfgCutMaxAbsVertexZMc.value)) { + if (!(std::abs(holderMcEvent.vz) < groupEvent.cfgCutMaxAbsVertexZMc.value)) { hrCounter.fill(HIST("hNMcEvents"), 4.); return false; } @@ -3118,19 +3141,19 @@ struct PartNumFluc { if ((groupAnalysis.cfgFlagQaPhi.value || groupAnalysis.cfgFlagQaPhiPi.value || groupAnalysis.cfgFlagQaPhiKa.value || groupAnalysis.cfgFlagQaPhiPr.value) && (!groupTrack.cfgFlagMcParticlePhysicalPrimary.value || mcParticle.isPhysicalPrimary()) && holderTrack.hasTpcPid) { if (groupAnalysis.cfgFlagQaPhi.value) { if (holderTrack.sign > 0.) { - hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhiMc_tpcP"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); - hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_tpcP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhiMc_mcTpcP"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_mcTpcP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); } else if (holderTrack.sign < 0.) { - hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhiMc_tpcM"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); - hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_tpcM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhiMc_mcTpcM"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_mcTpcM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); } if (holderTrack.hasTofPid) { if (holderTrack.sign > 0.) { - hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhiMc_tpcTofP"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); - hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_tpcTofP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhiMc_mcTpcTofP"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_mcTpcTofP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); } else if (holderTrack.sign < 0.) { - hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhiMc_tpcTofM"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); - hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_tpcTofM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhiMc_mcTpcTofM"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_mcTpcTofM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); } } } @@ -3188,23 +3211,23 @@ struct PartNumFluc { if (groupAnalysis.cfgFlagQaPhiPr.value) { switch (holderMcParticle.pdgCode) { case PDG_t::kProton: - hrQaPhi.fill(HIST("QaPhi/hVzCentralityPtEtaPhiMc_mcTpcPrP"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); - hrQaPhi.fill(HIST("QaPhi/hVzCentralityPtEtaPhi_mcTpcPrP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhiMc_mcTpcPrP"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_mcTpcPrP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); break; case PDG_t::kProtonBar: - hrQaPhi.fill(HIST("QaPhi/hVzCentralityPtEtaPhiMc_mcTpcPrM"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); - hrQaPhi.fill(HIST("QaPhi/hVzCentralityPtEtaPhi_mcTpcPrM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhiMc_mcTpcPrM"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_mcTpcPrM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); break; } if (holderTrack.hasTofPid) { switch (holderMcParticle.pdgCode) { case PDG_t::kProton: - hrQaPhi.fill(HIST("QaPhi/hVzCentralityPtEtaPhiMc_mcTpcTofPrP"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); - hrQaPhi.fill(HIST("QaPhi/hVzCentralityPtEtaPhi_mcTpcTofPrP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhiMc_mcTpcTofPrP"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_mcTpcTofPrP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); break; case PDG_t::kProtonBar: - hrQaPhi.fill(HIST("QaPhi/hVzCentralityPtEtaPhiMc_mcTpcTofPrM"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); - hrQaPhi.fill(HIST("QaPhi/hVzCentralityPtEtaPhi_mcTpcTofPrM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhiMc_mcTpcTofPrM"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_mcTpcTofPrM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); break; } } From d217cb7e37d76301cff93b84e9fda0ee9204360d Mon Sep 17 00:00:00 2001 From: Victor Gonzalez Date: Mon, 9 Mar 2026 01:06:20 +0100 Subject: [PATCH 219/347] [PWGCF] DptDpt - Circumvent the inline generator configuration (#15308) Co-authored-by: Victor --- PWGCF/TableProducer/dptDptFilter.cxx | 7 ++++++- PWGCF/TableProducer/dptDptFilter.h | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/PWGCF/TableProducer/dptDptFilter.cxx b/PWGCF/TableProducer/dptDptFilter.cxx index 440e88292b8..dd703f3b3c3 100644 --- a/PWGCF/TableProducer/dptDptFilter.cxx +++ b/PWGCF/TableProducer/dptDptFilter.cxx @@ -658,7 +658,12 @@ struct DptDptFilter { getTaskOptionValue(initContext, "generator-task", "configFile", tmpstr, false); TString fullPath = tmpstr; auto tokens = fullPath.Tokenize("/"); - otfGenerator = TString(tokens->At(tokens->GetEntries() - 1)->GetName()).ReplaceAll(".ini", ""); + if (tokens->GetEntries() > 0) { + otfGenerator = TString(tokens->At(tokens->GetEntries() - 1)->GetName()).ReplaceAll(".ini", ""); + } else { + /* let's take it from the time being from the data type string */ + otfGenerator = TString(cfgDataType).ReplaceAll("OnTheFlyMC_", ""); + } delete tokens; LOGF(info, "The generator configuration file: %s", otfGenerator.c_str()); } diff --git a/PWGCF/TableProducer/dptDptFilter.h b/PWGCF/TableProducer/dptDptFilter.h index 63a49a5c7b8..9c51fbbf60a 100644 --- a/PWGCF/TableProducer/dptDptFilter.h +++ b/PWGCF/TableProducer/dptDptFilter.h @@ -944,7 +944,7 @@ inline DataType getDataType(std::string const& datastr) return kMC; } else if (datastr == "FastMC") { return kFastMC; - } else if (datastr == "OnTheFlyMC") { + } else if (datastr.starts_with("OnTheFlyMC")) { return kOnTheFly; } else { LOGF(fatal, "DptDptCorrelations::getDataType(). Wrong type of dat: %d", datastr.c_str()); From e97511a9125a48ef2c860be4061525eb99bd6345 Mon Sep 17 00:00:00 2001 From: Mattia Faggin Date: Mon, 9 Mar 2026 08:38:54 +0100 Subject: [PATCH 220/347] [PWGHF] Add gen. particles in Sigmac tree. (#15295) --- .../treeCreatorSigmacCorrBkg.cxx | 46 +++++++++++++++++-- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/PWGHF/TableProducer/treeCreatorSigmacCorrBkg.cxx b/PWGHF/TableProducer/treeCreatorSigmacCorrBkg.cxx index a3670cf6dfc..98fbc5f13c3 100644 --- a/PWGHF/TableProducer/treeCreatorSigmacCorrBkg.cxx +++ b/PWGHF/TableProducer/treeCreatorSigmacCorrBkg.cxx @@ -69,6 +69,7 @@ DECLARE_SOA_COLUMN(DecayLambdac, decayLambdac, int8_t); DECLARE_SOA_COLUMN(MlScoreFirstClass, mlScoreFirstClass, float); /// background score Λc DECLARE_SOA_COLUMN(MlScoreThirdClass, mlScoreThirdClass, float); /// non-prompt score Λc DECLARE_SOA_COLUMN(IsReflected, isReflected, int8_t); +DECLARE_SOA_COLUMN(Origin, origin, int8_t); } // namespace hf_sigmac_bkg DECLARE_SOA_TABLE(HfCorrBkgSc, "AOD", "HFCORRBKGSC", hf_sigmac_bkg::Y, @@ -83,11 +84,17 @@ DECLARE_SOA_TABLE(HfCorrBkgSc, "AOD", "HFCORRBKGSC", hf_sigmac_bkg::MlScoreFirstClass, hf_sigmac_bkg::MlScoreThirdClass, hf_sigmac_bkg::IsReflected); +DECLARE_SOA_TABLE(HfGenBkgSc, "AOD", "HFGENBKGSC", + hf_sigmac_bkg::Y, + hf_sigmac_bkg::Pt, + hf_sigmac_bkg::MotherPdg, + hf_sigmac_bkg::Origin); } // namespace o2::aod struct HfTreeCreatorSigmacCorrBkg { Produces rowCorrBkgSc; + Produces rowGenBkgSc; /// Selection of candidates Λc+ Configurable selectionFlagLc{"selectionFlagLc", 1, "Selection Flag for Lc"}; @@ -99,7 +106,13 @@ struct HfTreeCreatorSigmacCorrBkg { using ParticlesLcSigmac = soa::Join; /// @brief init function - void init(InitContext&) {} + void init(InitContext&) + { + std::array doprocesses{doprocessReco, doprocessGen}; + if (std::accumulate(doprocesses.begin(), doprocesses.end(), 0) == 0) { + LOGP(fatal, "No process function enabled. Aborting..."); + } + } /// void fillTable(RecoScMc::iterator candidateSc, RecoLcMc::iterator candLcDauSc, int motherPdg, int motherDecay = -1) @@ -166,10 +179,10 @@ struct HfTreeCreatorSigmacCorrBkg { } /// @brief process function to loop over the Σc reconstructed candidates and match them to corr. background sources in MC - void process(RecoScMc const& candidatesSc, - ParticlesLcSigmac const& particles, - RecoLcMc const&, - aod::TracksWMc const&) + void processReco(RecoScMc const& candidatesSc, + ParticlesLcSigmac const& particles, + RecoLcMc const&, + aod::TracksWMc const&) { /// loop over reconstructed Σc candidates for (auto const& candidateSc : candidatesSc) { @@ -335,6 +348,29 @@ struct HfTreeCreatorSigmacCorrBkg { } /// end loop over reconstructed Σc candidates } + PROCESS_SWITCH(HfTreeCreatorSigmacCorrBkg, processReco, "Process Reco MC", false); + + /// @brief process function to look for generated Σc and Λc±(2595, 2625) (needed to properly normalize the bkg templates) + void processGen(aod::McParticles const& particles) + { + /// loop over particles + for (auto const& particle : particles) { + int pdgCodeAbs = std::abs(particle.pdgCode()); + + /// keep only Σc and Λc±(2595, 2625) + if (pdgCodeAbs != o2::constants::physics::Pdg::kSigmaC0 && pdgCodeAbs != o2::constants::physics::Pdg::kSigmaCPlusPlus && pdgCodeAbs != o2::constants::physics::Pdg::kSigmaCStar0 && pdgCodeAbs != o2::constants::physics::Pdg::kSigmaCStarPlusPlus && pdgCodeAbs != aod::hf_sigmac_bkg::pdgCodeLambdac2595 && pdgCodeAbs != aod::hf_sigmac_bkg::pdgCodeLambdac2625) { + continue; + } + + /// if we arrive here, it means that the particle is either a Σc or Λc±(2595, 2625) + /// let's check the origin (prompt, non-prompt) + int8_t origin = static_cast(RecoDecay::getCharmHadronOrigin(particles, particle, false)); + + /// let's fill the table + rowGenBkgSc(particle.y(), particle.pt(), pdgCodeAbs, origin); + } /// end loop over particles + } + PROCESS_SWITCH(HfTreeCreatorSigmacCorrBkg, processGen, "Process generated MC", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) From 8ebb975431b506aff9374f071b5bcc19205a16e3 Mon Sep 17 00:00:00 2001 From: Kegang Xiong Date: Mon, 9 Mar 2026 16:54:35 +0800 Subject: [PATCH 221/347] [PWGCF] Add QA plots and update some configs (#15309) --- PWGCF/Flow/Tasks/flowZdcEnergy.cxx | 62 ++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 21 deletions(-) diff --git a/PWGCF/Flow/Tasks/flowZdcEnergy.cxx b/PWGCF/Flow/Tasks/flowZdcEnergy.cxx index 5feb8a01b80..11f9c2fe4c3 100644 --- a/PWGCF/Flow/Tasks/flowZdcEnergy.cxx +++ b/PWGCF/Flow/Tasks/flowZdcEnergy.cxx @@ -14,8 +14,6 @@ /// \since 03/2026 /// \brief A try to use the znc energy. -#include "PWGCF/DataModel/SPTableZDC.h" - #include "Common/Core/EventPlaneHelper.h" #include "Common/Core/RecoDecay.h" #include "Common/Core/TrackSelection.h" @@ -55,34 +53,38 @@ using namespace o2::aod::rctsel; struct flowZdcEnergy { - RCTFlagsChecker rctChecker; - - struct : ConfigurableGroup { - O2_DEFINE_CONFIGURABLE(cfgEvtUseRCTFlagChecker, bool, false, "Evt sel: use RCT flag checker"); - O2_DEFINE_CONFIGURABLE(cfgEvtRCTFlagCheckerLabel, std::string, "CBT_hadronPID", "Evt sel: RCT flag checker label (CBT, CBT_hadronPID)"); // all Labels can be found in Common/CCDB/RCTSelectionFlags.h - O2_DEFINE_CONFIGURABLE(cfgEvtRCTFlagCheckerZDCCheck, bool, false, "Evt sel: RCT flag checker ZDC check"); - O2_DEFINE_CONFIGURABLE(cfgEvtRCTFlagCheckerLimitAcceptAsBad, bool, false, "Evt sel: RCT flag checker treat Limited Acceptance As Bad"); - } rctFlags; - struct : ConfigurableGroup { // Additional event selections - O2_DEFINE_CONFIGURABLE(cfgMaxOccupancy, int, 10000, "Maximum occupancy of selected events"); O2_DEFINE_CONFIGURABLE(cfgCentMin, float, 0, "Minimum cenrality for selected events"); O2_DEFINE_CONFIGURABLE(cfgCentMax, float, 90, "Maximum cenrality for selected events"); + O2_DEFINE_CONFIGURABLE(cfgVtxZ, float, 10.0f, "Accepted z-vertex range for selected events") } EvSel; // Configurables containing vector - O2_DEFINE_CONFIGURABLE(cfgVtxZ, float, 10.0f, "Accepted z-vertex range") O2_DEFINE_CONFIGURABLE(cfgEtaMax, float, 0.8f, "Maximum track #eta") O2_DEFINE_CONFIGURABLE(cfgPtMin, float, 0.2f, "Minimum track #P_{t}") O2_DEFINE_CONFIGURABLE(cfgPtMax, float, 10.0f, "Maximum track #P_{t}") O2_DEFINE_CONFIGURABLE(cfgDcaXYMax, float, 0.2f, "Maximum DCAxy") O2_DEFINE_CONFIGURABLE(cfgDcaZMax, float, 2.0f, "Maximum DCAz") + enum SelectionCriteria { + evSel_AllEvent, + evSel_sel8, + evSel_Zvtx, + evSel_CentCuts, + evSel_BCHasZDC, + evSel_isSelectedZDC, + nEventSelections + }; + + ConfigurableAxis axisCent = {"axisCent", {100, 0, 100}, "Centrality(%)"}; + ConfigurableAxis axisEnergy = {"axisEnergy", {300, 0, 300}, "Energy"}; + ConfigurableAxis axisRescaledDiff = {"axisRescaledDiff", {400, -1, 1}, "(#E_{A}-#E_{C}) / (#E_{A}+#E_{C})"}; + // Filter trackFilter = nabs(aod::track::eta) < cfgEtaMax && aod::track::pt > cfgPtMin&& aod::track::pt < cfgPtMax && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)) && nabs(aod::track::dcaXY) < cfgDcaXYMax&& nabs(aod::track::dcaZ) < cfgDcaZMax; // using UsedTracks = soa::Filtered>; - using ZDCCollisions = soa::Join, aod::SPTableZDC>; + using ZDCCollisions = soa::Join; using BCsRun3 = soa::Join; // Connect to ccdb @@ -99,12 +101,15 @@ struct flowZdcEnergy { int64_t now = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); ccdb->setCreatedNotAfter(now); - rctChecker.init(rctFlags.cfgEvtRCTFlagCheckerLabel, rctFlags.cfgEvtRCTFlagCheckerZDCCheck, rctFlags.cfgEvtRCTFlagCheckerLimitAcceptAsBad); - - AxisSpec axisCent = {100, 0, 100, "Centrality(%)"}; - AxisSpec axisEnergy = {300, 0, 300, "Energy"}; - AxisSpec axisRescaledDiff = {40, -2, 2, "(#E_{A}-#E_{C}) / (#E_{A}+#E_{C})"}; - + // QA hist + registry.add("hEventCount", "Number of Event; Cut; #Events Passed Cut", {HistType::kTH1D, {{nEventSelections, 0, nEventSelections}}}); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_AllEvent + 1, "All events"); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_sel8 + 1, "Sel8"); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_Zvtx + 1, "Z vertex cut event"); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_CentCuts + 1, "Cenrality range"); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_BCHasZDC + 1, "BCHasZDC"); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_isSelectedZDC + 1, "isSelected"); + // ana hist registry.add("hEnergyWithCent_ZNA_Common", "", {HistType::kTH2D, {axisEnergy, axisCent}}); registry.add("hEnergyWithCent_ZNC_Common", "", {HistType::kTH2D, {axisEnergy, axisCent}}); registry.add("hEnergyWithCent_RescaledDiff", "", {HistType::kTH2D, {axisRescaledDiff, axisCent}}); @@ -126,16 +131,31 @@ struct flowZdcEnergy { double centrality = collision.centFT0C(); // event selection - if (centrality < EvSel.cfgCentMin || centrality > EvSel.cfgCentMax || !collision.sel8() || std::abs(collision.posZ()) > cfgVtxZ) { + registry.fill(HIST("hEventCount"), evSel_AllEvent); + if (!collision.sel8()) { + return; + } + registry.fill(HIST("hEventCount"), evSel_sel8); + if (std::abs(collision.posZ()) > EvSel.cfgVtxZ) { return; } + registry.fill(HIST("hEventCount"), evSel_Zvtx); + if (centrality < EvSel.cfgCentMin || centrality > EvSel.cfgCentMax) { + return; + } + registry.fill(HIST("hEventCount"), evSel_CentCuts); const auto& foundBC = collision.foundBC_as(); if (!foundBC.has_zdc()) { return; } + registry.fill(HIST("hEventCount"), evSel_BCHasZDC); const auto& zdcCol = foundBC.zdc(); + if (zdcCol.energyCommonZNA() <= 0 || zdcCol.energyCommonZNC() <= 0) { + return; + } + registry.fill(HIST("hEventCount"), evSel_isSelectedZDC); double SumEnergyZNA = zdcCol.energySectorZNA()[0] + zdcCol.energySectorZNA()[1] + zdcCol.energySectorZNA()[2] + zdcCol.energySectorZNA()[3]; double SumEnergyZNC = zdcCol.energySectorZNC()[0] + zdcCol.energySectorZNC()[1] + zdcCol.energySectorZNC()[2] + zdcCol.energySectorZNC()[3]; From 43c64143da6fe461fa1fdee88e233dde15830209 Mon Sep 17 00:00:00 2001 From: Lucia Anna Tarasovicova Date: Mon, 9 Mar 2026 09:57:42 +0100 Subject: [PATCH 222/347] [PWGLF] Configurable regrouping, new check in hStrangeCorrelation (#15296) Co-authored-by: Lucia Anna Tarasovicova --- .../Strangeness/hStrangeCorrelationFilter.cxx | 444 ++++++++---------- .../Tasks/Strangeness/hStrangeCorrelation.cxx | 302 ++++++------ 2 files changed, 353 insertions(+), 393 deletions(-) diff --git a/PWGLF/TableProducer/Strangeness/hStrangeCorrelationFilter.cxx b/PWGLF/TableProducer/Strangeness/hStrangeCorrelationFilter.cxx index cd825f1ffa4..f944b37749a 100644 --- a/PWGLF/TableProducer/Strangeness/hStrangeCorrelationFilter.cxx +++ b/PWGLF/TableProducer/Strangeness/hStrangeCorrelationFilter.cxx @@ -74,6 +74,7 @@ struct HStrangeCorrelationFilter { Configurable cfgCutOccupancyLow{"cfgCutOccupancyLow", 0, "Low cut on TPC occupancy"}; struct : ConfigurableGroup { + std::string prefix = "eventSelections"; // event filtering Configurable zVertexCut{"zVertexCut", 10, "Cut on PV position"}; Configurable selectINELgtZERO{"selectINELgtZERO", true, "select INEL>0 events"}; @@ -83,12 +84,23 @@ struct HStrangeCorrelationFilter { } eventSelections; struct : ConfigurableGroup { + std::string prefix = "generalSelections"; + + // Associated particle selections in phase space + Configurable assocEtaMin{"assocEtaMin", -0.8, "triggeretamin"}; + Configurable assocEtaMax{"assocEtaMax", 0.8, "triggeretamax"}; + Configurable assocPtCutMin{"assocPtCutMin", 0.2, "assocptmin"}; + Configurable assocPtCutMax{"assocPtCutMax", 10, "assocptmax"}; + // Trigger particle selections in phase space Configurable triggerEtaMin{"triggerEtaMin", -0.8, "triggeretamin"}; Configurable triggerEtaMax{"triggerEtaMax", 0.8, "triggeretamax"}; Configurable triggerPtCutMin{"triggerPtCutMin", 3, "triggerptmin"}; Configurable triggerPtCutMax{"triggerPtCutMax", 20, "triggerptmax"}; + } generalSelections; + struct : ConfigurableGroup { + std::string prefix = "trackSelections"; // Track quality Configurable minTPCNCrossedRows{"minTPCNCrossedRows", 70, "Minimum TPC crossed rows"}; Configurable triggerRequireITS{"triggerRequireITS", true, "require ITS signal in trigger tracks"}; @@ -96,77 +108,62 @@ struct HStrangeCorrelationFilter { Configurable triggerMaxTPCSharedClusters{"triggerMaxTPCSharedClusters", 200, "maximum number of shared TPC clusters (inclusive)"}; Configurable triggerRequireL0{"triggerRequireL0", false, "require ITS L0 cluster for trigger"}; - // Associated particle selections in phase space - Configurable assocEtaMin{"assocEtaMin", -0.8, "triggeretamin"}; - Configurable assocEtaMax{"assocEtaMax", 0.8, "triggeretamax"}; - Configurable assocPtCutMin{"assocPtCutMin", 0.2, "assocptmin"}; - Configurable assocPtCutMax{"assocPtCutMax", 10, "assocptmax"}; - // Associated pion identification Configurable pionMinBayesProb{"pionMinBayesProb", 0.95, "minimal Bayesian probability for pion ID"}; Configurable assocPionNSigmaTPCFOF{"assocPionNSigmaTPCFOF", 3, "minimal n sigma in TOF and TPC for Pion ID"}; Configurable rejectSigma{"rejectSigma", 1, "n sigma for rejecting pion candidates"}; + // primary particle DCAxy selections + // formula: |DCAxy| < 0.004f + (0.013f / pt) + Configurable dcaXYconstant{"dcaXYconstant", 0.004, "[0] in |DCAxy| < [0]+[1]/pT"}; + Configurable dcaXYpTdep{"dcaXYpTdep", 0.013, "[1] in |DCAxy| < [0]+[1]/pT"}; + } trackSelections; + struct : ConfigurableGroup { // V0 selections + std::string prefix = "v0Selection"; Configurable v0Cospa{"v0Cospa", 0.97, "V0 CosPA"}; // double -> N.B. dcos(x)/dx = 0 at x=0) Configurable dcaV0dau{"dcaV0dau", 1.0, "DCA V0 Daughters"}; Configurable dcaNegtopv{"dcaNegtopv", 0.06, "DCA Neg To PV"}; Configurable dcaPostopv{"dcaPostopv", 0.06, "DCA Pos To PV"}; + Configurable dcaBaryonToPV{"dcaBaryonToPV", 0.2, "DCA of baryon daughter track To PV"}; + Configurable dcaMesonToPV{"dcaMesonToPV", 0.05, "DCA of meson daughter track To PV"}; Configurable v0RadiusMin{"v0RadiusMin", 0.5, "v0radius"}; Configurable v0RadiusMax{"v0RadiusMax", 200, "v0radius"}; - // more V0 selections in PbPb + Configurable lifetimecutK0S{"lifetimecutK0S", 20, "lifetimecutK0S"}; Configurable lifetimecutLambda{"lifetimecutLambda", 30, "lifetimecutLambda"}; - Configurable dcanegtopvK0S{"dcanegtopvK0S", 0.1, "DCA Neg To PV"}; - Configurable dcapostopvK0S{"dcapostopvK0S", 0.1, "DCA Pos To PV"}; - Configurable dcanegtopvLambda{"dcanegtopvLambda", 0.05, "DCA Neg To PV"}; - Configurable dcapostopvLambda{"dcapostopvLambda", 0.2, "DCA Pos To PV"}; - Configurable dcanegtopvAntiLambda{"dcanegtopvAntiLambda", 0.2, "DCA Neg To PV"}; - Configurable dcapostopvAntiLambda{"dcapostopvAntiLambda", 0.05, "DCA Pos To PV"}; - // original equation: lArmPt*2>TMath::Abs(lArmAlpha) only for K0S Configurable armPodCut{"armPodCut", 5.0f, "pT * (cut) > |alpha|, AP cut. Negative: no cut"}; - // specific selections - Configurable lambdaCospa{"lambdaCospa", 0.995, "CosPA for lambda"}; // allows for tighter selection for Lambda - - // primary particle DCAxy selections - // formula: |DCAxy| < 0.004f + (0.013f / pt) - Configurable dcaXYconstant{"dcaXYconstant", 0.004, "[0] in |DCAxy| < [0]+[1]/pT"}; - Configurable dcaXYpTdep{"dcaXYpTdep", 0.013, "[1] in |DCAxy| < [0]+[1]/pT"}; - - // cascade selections - Configurable cascCospa{"cascCospa", 0.95, "cascCospa"}; - Configurable cascRadius{"cascRadius", 0.5, "cascRadius"}; - Configurable dcaCascdau{"dcaCascdau", 1.0, "dcaCascdau"}; - Configurable dcaBachtopv{"dcaBachtopv", 0.1, "dcaBachtopv"}; - Configurable cascV0masswindow{"cascV0masswindow", 0.01, "cascV0masswindow"}; - Configurable cascMindcav0topv{"cascMindcav0topv", 0.01, "cascMindcav0topv"}; - - // pt Range for pt dep cuts - Configurable highPtForCascDaugPtDep{"highPtForCascDaugPtDep", 4.0, "high pt range for pt dep cuts"}; - Configurable lowPtForCascDaugPtDep{"lowPtForCascDaugPtDep", 1.0, "low pt range for pt dep cuts"}; - } systCuts; + Configurable lambdaCospa{"lambdaCospa", 0.995, "Lambda CosPA, if needed to be stricter"}; // allows for tighter selection for Lambda + } v0Selection; struct : ConfigurableGroup { - // cascade selections in PbPb - Configurable cascDcacascdau{"cascDcacascdau", 1.0, "cascDcacascdau"}; - Configurable cascDcabachtopv{"cascDcabachtopv", 0.1, "cascDcabachtopv"}; + // cascade selections + std::string prefix = "cascSelection"; Configurable bachBaryonCosPA{"bachBaryonCosPA", 0.9999, "Bachelor baryon CosPA"}; Configurable bachBaryonDCAxyToPV{"bachBaryonDCAxyToPV", 0.08, "DCA bachelor baryon to PV"}; - Configurable dcaBaryonToPV{"dcaBaryonToPV", 0.05, "DCA of baryon doughter track To PV"}; - Configurable dcaMesonToPV{"dcaMesonToPV", 0.1, "DCA of meson doughter track To PV"}; Configurable dcaBachToPV{"dcaBachToPV", 0.07, "DCA Bach To PV"}; + Configurable cascDcaBaryonToPV{"cascDcaBaryonToPV", 0.2, "DCA of baryon daughter track To PV"}; + Configurable cascDcaMesonToPV{"cascDcaMesonToPV", 0.05, "DCA of meson daughter track To PV"}; Configurable cascdcaV0dau{"cascdcaV0dau", 0.5, "DCA V0 Daughters"}; Configurable dcaCacsDauPar0{"dcaCacsDauPar0", 0.8, " par for pt dep DCA cascade daughter cut, p_T < 1 GeV/c"}; Configurable dcaCacsDauPar1{"dcaCacsDauPar1", 0.5, " par for pt dep DCA cascade daughter cut, 1< p_T < 4 GeV/c"}; Configurable dcaCacsDauPar2{"dcaCacsDauPar2", 0.2, " par for pt dep DCA cascade daughter cut, p_T > 4 GeV/c"}; - Configurable cascdcaV0ToPV{"cascdcaV0ToPV", 0.06, "DCA V0 To PV"}; Configurable cascv0cospa{"cascv0cospa", 0.98, "V0 CosPA"}; Configurable cascv0RadiusMin{"cascv0RadiusMin", 2.5, "v0radius"}; Configurable proplifetime{"proplifetime", 3, "ctau/"}; Configurable lambdaMassWin{"lambdaMassWin", 0.005, "V0 Mass window limit"}; Configurable rejcomp{"rejcomp", 0.008, "Competing Cascade rejection"}; Configurable rapCut{"rapCut", 0.8, "Rapidity acceptance"}; - } MorePbPbsystCuts; + Configurable cascCospa{"cascCospa", 0.95, "cascCospa"}; + Configurable cascRadius{"cascRadius", 0.5, "cascRadius"}; + Configurable dcaCascdau{"dcaCascdau", 1.0, "DCA between V0 and bachelor track"}; + Configurable dcaBachtopv{"dcaBachtopv", 0.1, "DCA bachelor track to PV"}; + Configurable cascV0masswindow{"cascV0masswindow", 0.01, "V0 Mass window"}; + Configurable cascMindcav0topv{"cascMindcav0topv", 0.01, "Minimum DCA V0 to PV"}; + // pt Range for pt dep cuts + Configurable highPtForCascDaugPtDep{"highPtForCascDaugPtDep", 4.0, "high pt range for pt dep cuts"}; + Configurable lowPtForCascDaugPtDep{"lowPtForCascDaugPtDep", 1.0, "low pt range for pt dep cuts"}; + } cascSelection; Configurable ccdburl{"ccdburl", "http://alice-ccdb.cern.ch", "url of the ccdb repository to use"}; Configurable parameterCCDBPath{"parameterCCDBPath", "Users/k/kcui/LHC25b4a/parameter", "Path of the mean and sigma"}; @@ -186,11 +183,11 @@ struct HStrangeCorrelationFilter { // QA Configurable doTrueSelectionInMass{"doTrueSelectionInMass", false, "Fill mass histograms only with true primary Particles for MC"}; // Do declarative selections for DCAs, if possible - Filter preFilterTracks = nabs(aod::track::dcaXY) < systCuts.dcaXYconstant + systCuts.dcaXYpTdep * nabs(aod::track::signed1Pt); - Filter preFilterV0 = nabs(aod::v0data::dcapostopv) > systCuts.dcaPostopv&& - nabs(aod::v0data::dcanegtopv) > systCuts.dcaNegtopv&& aod::v0data::dcaV0daughters < systCuts.dcaV0dau; + Filter preFilterTracks = nabs(aod::track::dcaXY) < trackSelections.dcaXYconstant + trackSelections.dcaXYpTdep * nabs(aod::track::signed1Pt); + Filter preFilterV0 = nabs(aod::v0data::dcapostopv) > v0Selection.dcaPostopv&& + nabs(aod::v0data::dcanegtopv) > v0Selection.dcaNegtopv&& aod::v0data::dcaV0daughters < v0Selection.dcaV0dau; Filter preFilterCascade = - nabs(aod::cascdata::dcapostopv) > systCuts.dcaPostopv&& nabs(aod::cascdata::dcanegtopv) > systCuts.dcaNegtopv&& nabs(aod::cascdata::dcabachtopv) > systCuts.dcaBachtopv&& aod::cascdata::dcaV0daughters < systCuts.dcaV0dau&& aod::cascdata::dcacascdaughters < systCuts.dcaCascdau; + nabs(aod::cascdata::dcapostopv) > v0Selection.dcaPostopv&& nabs(aod::cascdata::dcanegtopv) > v0Selection.dcaNegtopv&& nabs(aod::cascdata::dcabachtopv) > cascSelection.dcaBachtopv&& aod::cascdata::dcaV0daughters < cascSelection.cascdcaV0dau&& aod::cascdata::dcacascdaughters < cascSelection.dcaCascdau; // using V0LinkedTagged = soa::Join; // using CascadesLinkedTagged = soa::Join; @@ -391,23 +388,23 @@ struct HStrangeCorrelationFilter { template bool isValidTrigger(TTrack track) { - if (track.eta() > systCuts.triggerEtaMax || track.eta() < systCuts.triggerEtaMin) { + if (track.eta() > generalSelections.triggerEtaMax || track.eta() < generalSelections.triggerEtaMin) { return false; } // if (track.sign()= 1 ) {continue;} - if (track.pt() > systCuts.triggerPtCutMax || track.pt() < systCuts.triggerPtCutMin) { + if (track.pt() > generalSelections.triggerPtCutMax || track.pt() < generalSelections.triggerPtCutMin) { return false; } - if (track.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRows) { + if (track.tpcNClsCrossedRows() < trackSelections.minTPCNCrossedRows) { return false; // crossed rows } - if (!track.hasITS() && systCuts.triggerRequireITS) { + if (!track.hasITS() && trackSelections.triggerRequireITS) { return false; // skip, doesn't have ITS signal (skips lots of TPC-only!) } - if (track.tpcNClsShared() > systCuts.triggerMaxTPCSharedClusters) { + if (track.tpcNClsShared() > trackSelections.triggerMaxTPCSharedClusters) { return false; // skip, has shared clusters } - if (!(BIT_CHECK(track.itsClusterMap(), 0)) && systCuts.triggerRequireL0) { + if (!(BIT_CHECK(track.itsClusterMap(), 0)) && trackSelections.triggerRequireL0) { return false; // skip, doesn't have cluster in ITS L0 } return true; @@ -415,16 +412,16 @@ struct HStrangeCorrelationFilter { template bool isValidAssocTrack(TTrack assoc) { - if (assoc.eta() > systCuts.assocEtaMax || assoc.eta() < systCuts.assocEtaMin) { + if (assoc.eta() > generalSelections.assocEtaMax || assoc.eta() < generalSelections.assocEtaMin) { return false; } - if (assoc.pt() > systCuts.assocPtCutMax || assoc.pt() < systCuts.assocPtCutMin) { + if (assoc.pt() > generalSelections.assocPtCutMax || assoc.pt() < generalSelections.assocPtCutMin) { return false; } - if (assoc.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRows) { + if (assoc.tpcNClsCrossedRows() < trackSelections.minTPCNCrossedRows) { return false; // crossed rows } - if (!assoc.hasITS() && systCuts.assocRequireITS) { + if (!assoc.hasITS() && trackSelections.assocRequireITS) { return false; // skip, doesn't have ITS signal (skips lots of TPC-only!) } @@ -432,26 +429,26 @@ struct HStrangeCorrelationFilter { float nSigmaTPCTOF[8] = {-10, -10, -10, -10, -10, -10, -10, -10}; if constexpr (requires { assoc.tofSignal(); } && !requires { assoc.mcParticle(); }) { if (assoc.tofSignal() > 0) { - if (std::sqrt(assoc.tofNSigmaPi() * assoc.tofNSigmaPi() + assoc.tpcNSigmaPi() * assoc.tpcNSigmaPi()) > systCuts.assocPionNSigmaTPCFOF) + if (std::sqrt(assoc.tofNSigmaPi() * assoc.tofNSigmaPi() + assoc.tpcNSigmaPi() * assoc.tpcNSigmaPi()) > trackSelections.assocPionNSigmaTPCFOF) return false; - if (assoc.tofNSigmaPr() < systCuts.rejectSigma) + if (assoc.tofNSigmaPr() < trackSelections.rejectSigma) return false; - if (assoc.tpcNSigmaPr() < systCuts.rejectSigma) + if (assoc.tpcNSigmaPr() < trackSelections.rejectSigma) return false; - if (assoc.tofNSigmaKa() < systCuts.rejectSigma) + if (assoc.tofNSigmaKa() < trackSelections.rejectSigma) return false; - if (assoc.tpcNSigmaKa() < systCuts.rejectSigma) + if (assoc.tpcNSigmaKa() < trackSelections.rejectSigma) return false; nSigmaTPCTOF[4] = assoc.tofNSigmaPi(); nSigmaTPCTOF[5] = assoc.tofNSigmaKa(); nSigmaTPCTOF[6] = assoc.tofNSigmaPr(); nSigmaTPCTOF[7] = assoc.tofNSigmaEl(); } else { - if (assoc.tpcNSigmaPi() > systCuts.assocPionNSigmaTPCFOF) + if (assoc.tpcNSigmaPi() > trackSelections.assocPionNSigmaTPCFOF) return false; - if (assoc.tpcNSigmaPr() < systCuts.rejectSigma) + if (assoc.tpcNSigmaPr() < trackSelections.rejectSigma) return false; - if (assoc.tpcNSigmaKa() < systCuts.rejectSigma) + if (assoc.tpcNSigmaKa() < trackSelections.rejectSigma) return false; } nSigmaTPCTOF[0] = assoc.tpcNSigmaPi(); @@ -495,39 +492,39 @@ struct HStrangeCorrelationFilter { bool cascadeSelectedPbPb(TCascade casc, float pvx, float pvy, float pvz) { // bachBaryonCosPA - if (casc.bachBaryonCosPA() < MorePbPbsystCuts.bachBaryonCosPA) + if (casc.bachBaryonCosPA() < cascSelection.bachBaryonCosPA) return false; // bachBaryonDCAxyToPV - if (std::abs(casc.bachBaryonDCAxyToPV()) > MorePbPbsystCuts.bachBaryonDCAxyToPV) + if (std::abs(casc.bachBaryonDCAxyToPV()) > cascSelection.bachBaryonDCAxyToPV) return false; // casccosPA - if (casc.casccosPA(pvx, pvy, pvz) < systCuts.cascCospa) + if (casc.casccosPA(pvx, pvy, pvz) < cascSelection.cascCospa) return false; // dcacascdaughters - float ptDepCut = MorePbPbsystCuts.dcaCacsDauPar0; - if (casc.pt() > systCuts.lowPtForCascDaugPtDep && casc.pt() < systCuts.highPtForCascDaugPtDep) - ptDepCut = MorePbPbsystCuts.dcaCacsDauPar1; - else if (casc.pt() > systCuts.highPtForCascDaugPtDep) - ptDepCut = MorePbPbsystCuts.dcaCacsDauPar2; + float ptDepCut = cascSelection.dcaCacsDauPar0; + if (casc.pt() > cascSelection.lowPtForCascDaugPtDep && casc.pt() < cascSelection.highPtForCascDaugPtDep) + ptDepCut = cascSelection.dcaCacsDauPar1; + else if (casc.pt() > cascSelection.highPtForCascDaugPtDep) + ptDepCut = cascSelection.dcaCacsDauPar2; if (casc.dcacascdaughters() > ptDepCut) return false; // dcaV0daughters - if (casc.dcaV0daughters() > systCuts.dcaV0dau) + if (casc.dcaV0daughters() > cascSelection.cascdcaV0dau) return false; // dcav0topv - if (std::abs(casc.dcav0topv(pvx, pvy, pvz)) < MorePbPbsystCuts.cascdcaV0ToPV) + if (std::abs(casc.dcav0topv(pvx, pvy, pvz)) < cascSelection.cascMindcav0topv) return false; // cascradius - if (casc.cascradius() < systCuts.cascRadius) + if (casc.cascradius() < cascSelection.cascRadius) return false; // v0radius - if (casc.v0radius() < MorePbPbsystCuts.cascv0RadiusMin) + if (casc.v0radius() < cascSelection.cascv0RadiusMin) return false; // v0cosPA - if (casc.v0cosPA(casc.x(), casc.y(), casc.z()) < MorePbPbsystCuts.cascv0cospa) + if (casc.v0cosPA(casc.x(), casc.y(), casc.z()) < cascSelection.cascv0cospa) return false; // lambdaMassWin - if (std::abs(casc.mLambda() - o2::constants::physics::MassLambda0) > MorePbPbsystCuts.lambdaMassWin) + if (std::abs(casc.mLambda() - o2::constants::physics::MassLambda0) > cascSelection.lambdaMassWin) return false; return true; } @@ -733,10 +730,10 @@ struct HStrangeCorrelationFilter { /// _________________________________________________ /// Populate table with associated V0s for (auto const& v0 : V0s) { - if (v0.v0radius() < systCuts.v0RadiusMin || v0.v0radius() > systCuts.v0RadiusMax || v0.eta() > systCuts.assocEtaMax || v0.eta() < systCuts.assocEtaMin || v0.v0cosPA() < systCuts.v0Cospa) { + if (v0.v0radius() < v0Selection.v0RadiusMin || v0.v0radius() > v0Selection.v0RadiusMax || v0.eta() > generalSelections.assocEtaMax || v0.eta() < generalSelections.assocEtaMin || v0.v0cosPA() < v0Selection.v0Cospa) { continue; } - if (v0.pt() > systCuts.assocPtCutMax || v0.pt() < systCuts.assocPtCutMin) { + if (v0.pt() > generalSelections.assocPtCutMax || v0.pt() < generalSelections.assocPtCutMin) { continue; } // check dE/dx compatibility @@ -747,76 +744,61 @@ struct HStrangeCorrelationFilter { auto posdau = v0.posTrack_as(); auto negdau = v0.negTrack_as(); - if (negdau.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRows) + if (negdau.tpcNClsCrossedRows() < trackSelections.minTPCNCrossedRows) continue; - if (posdau.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRows) + if (posdau.tpcNClsCrossedRows() < trackSelections.minTPCNCrossedRows) continue; + bool isGoodK0Short = (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short < v0Selection.lifetimecutK0S && + std::abs(v0.dcapostopv()) > v0Selection.dcaMesonToPV && std::abs(v0.dcanegtopv()) > v0Selection.dcaMesonToPV && + v0.qtarm() * v0Selection.armPodCut > std::abs(v0.alpha())); + bool isGoodLambda = (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassLambda0 < v0Selection.lifetimecutLambda && + std::abs(v0.dcapostopv()) > v0Selection.dcaBaryonToPV && std::abs(v0.dcanegtopv()) > v0Selection.dcaMesonToPV); + bool isGoodAntiLambda = (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassLambda0Bar < v0Selection.lifetimecutLambda && + std::abs(v0.dcapostopv()) > v0Selection.dcaMesonToPV && std::abs(v0.dcanegtopv()) > v0Selection.dcaBaryonToPV); if (std::abs(posdau.tpcNSigmaPi()) < strangedEdxNSigmaLoose && std::abs(negdau.tpcNSigmaPi()) < strangedEdxNSigmaLoose) { - if (doPPAnalysis || (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short < systCuts.lifetimecutK0S && - std::abs(v0.dcapostopv()) > systCuts.dcapostopvK0S && std::abs(v0.dcanegtopv()) > systCuts.dcanegtopvK0S && - v0.qtarm() * systCuts.armPodCut > std::abs(v0.alpha()))) { + if (doPPAnalysis || isGoodK0Short) { BIT_SET(compatibleK0Short, 0); } } if (std::abs(posdau.tpcNSigmaPi()) < strangedEdxNSigma && std::abs(negdau.tpcNSigmaPi()) < strangedEdxNSigma) { - if (doPPAnalysis || (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short < systCuts.lifetimecutK0S && - std::abs(v0.dcapostopv()) > systCuts.dcapostopvK0S && std::abs(v0.dcanegtopv()) > systCuts.dcanegtopvK0S && - v0.qtarm() * systCuts.armPodCut > std::abs(v0.alpha()))) { + if (doPPAnalysis || isGoodK0Short) { BIT_SET(compatibleK0Short, 1); } } if (std::abs(posdau.tpcNSigmaPi()) < strangedEdxNSigmaTight && std::abs(negdau.tpcNSigmaPi()) < strangedEdxNSigmaTight) { - if (doPPAnalysis || (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short < systCuts.lifetimecutK0S && - std::abs(v0.dcapostopv()) > systCuts.dcapostopvK0S && std::abs(v0.dcanegtopv()) > systCuts.dcanegtopvK0S && - v0.qtarm() * systCuts.armPodCut > std::abs(v0.alpha()))) { + if (doPPAnalysis || isGoodK0Short) { BIT_SET(compatibleK0Short, 2); } } - if (std::abs(posdau.tpcNSigmaPr()) < strangedEdxNSigmaLoose && std::abs(negdau.tpcNSigmaPi()) < strangedEdxNSigmaLoose) { - if (v0.v0cosPA() > systCuts.lambdaCospa) { - if (doPPAnalysis || (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short < systCuts.lifetimecutLambda && - std::abs(v0.dcapostopv()) > systCuts.dcapostopvLambda && std::abs(v0.dcanegtopv()) > systCuts.dcanegtopvLambda)) { + if (v0.v0cosPA() > v0Selection.lambdaCospa) { + if (std::abs(posdau.tpcNSigmaPr()) < strangedEdxNSigmaLoose && std::abs(negdau.tpcNSigmaPi()) < strangedEdxNSigmaLoose) { + if (doPPAnalysis || isGoodLambda) { BIT_SET(compatibleLambda, 0); } } - } - if (std::abs(posdau.tpcNSigmaPr()) < strangedEdxNSigma && std::abs(negdau.tpcNSigmaPi()) < strangedEdxNSigma) { - if (v0.v0cosPA() > systCuts.lambdaCospa) { - if (doPPAnalysis || (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short < systCuts.lifetimecutLambda && - std::abs(v0.dcapostopv()) > systCuts.dcapostopvLambda && std::abs(v0.dcanegtopv()) > systCuts.dcanegtopvLambda)) { + if (std::abs(posdau.tpcNSigmaPr()) < strangedEdxNSigma && std::abs(negdau.tpcNSigmaPi()) < strangedEdxNSigma) { + if (doPPAnalysis || isGoodLambda) { BIT_SET(compatibleLambda, 1); } } - } - if (std::abs(posdau.tpcNSigmaPr()) < strangedEdxNSigmaTight && std::abs(negdau.tpcNSigmaPi()) < strangedEdxNSigmaTight) { - if (v0.v0cosPA() > systCuts.lambdaCospa) { - if (doPPAnalysis || (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short < systCuts.lifetimecutLambda && - std::abs(v0.dcapostopv()) > systCuts.dcapostopvLambda && std::abs(v0.dcanegtopv()) > systCuts.dcanegtopvLambda)) { + if (std::abs(posdau.tpcNSigmaPr()) < strangedEdxNSigmaTight && std::abs(negdau.tpcNSigmaPi()) < strangedEdxNSigmaTight) { + if (doPPAnalysis || isGoodLambda) { BIT_SET(compatibleLambda, 2); } } - } - if (std::abs(posdau.tpcNSigmaPi()) < strangedEdxNSigmaLoose && std::abs(negdau.tpcNSigmaPr()) < strangedEdxNSigmaLoose) { - if (v0.v0cosPA() > systCuts.lambdaCospa) { - if (doPPAnalysis || (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short < systCuts.lifetimecutLambda && - std::abs(v0.dcapostopv()) > systCuts.dcapostopvAntiLambda && std::abs(v0.dcanegtopv()) > systCuts.dcanegtopvAntiLambda)) { + if (std::abs(posdau.tpcNSigmaPi()) < strangedEdxNSigmaLoose && std::abs(negdau.tpcNSigmaPr()) < strangedEdxNSigmaLoose) { + if (doPPAnalysis || isGoodAntiLambda) { BIT_SET(compatibleAntiLambda, 0); } } - } - if (std::abs(posdau.tpcNSigmaPi()) < strangedEdxNSigma && std::abs(negdau.tpcNSigmaPr()) < strangedEdxNSigma) { - if (v0.v0cosPA() > systCuts.lambdaCospa) { - if (doPPAnalysis || (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short < systCuts.lifetimecutLambda && - std::abs(v0.dcapostopv()) > systCuts.dcapostopvAntiLambda && std::abs(v0.dcanegtopv()) > systCuts.dcanegtopvAntiLambda)) { + if (std::abs(posdau.tpcNSigmaPi()) < strangedEdxNSigma && std::abs(negdau.tpcNSigmaPr()) < strangedEdxNSigma) { + if (doPPAnalysis || isGoodAntiLambda) { BIT_SET(compatibleAntiLambda, 1); } } - } - if (std::abs(posdau.tpcNSigmaPi()) < strangedEdxNSigmaTight && std::abs(negdau.tpcNSigmaPr()) < strangedEdxNSigmaTight) { - if (v0.v0cosPA() > systCuts.lambdaCospa) { - if (doPPAnalysis || (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short < systCuts.lifetimecutLambda && - std::abs(v0.dcapostopv()) > systCuts.dcapostopvAntiLambda && std::abs(v0.dcanegtopv()) > systCuts.dcanegtopvAntiLambda)) { + if (std::abs(posdau.tpcNSigmaPi()) < strangedEdxNSigmaTight && std::abs(negdau.tpcNSigmaPr()) < strangedEdxNSigmaTight) { + if (doPPAnalysis || isGoodAntiLambda) { BIT_SET(compatibleAntiLambda, 2); } } @@ -874,10 +856,10 @@ struct HStrangeCorrelationFilter { /// Populate table with associated V0s for (auto const& v0 : V0s) { - if (v0.v0radius() < systCuts.v0RadiusMin || v0.v0radius() > systCuts.v0RadiusMax || v0.eta() > systCuts.assocEtaMax || v0.eta() < systCuts.assocEtaMin || v0.v0cosPA() < systCuts.v0Cospa) { + if (v0.v0radius() < v0Selection.v0RadiusMin || v0.v0radius() > v0Selection.v0RadiusMax || v0.eta() > generalSelections.assocEtaMax || v0.eta() < generalSelections.assocEtaMin || v0.v0cosPA() < v0Selection.v0Cospa) { continue; } - if (v0.pt() > systCuts.assocPtCutMax || v0.pt() < systCuts.assocPtCutMin) { + if (v0.pt() > generalSelections.assocPtCutMax || v0.pt() < generalSelections.assocPtCutMin) { continue; } // check dE/dx compatibility @@ -888,76 +870,62 @@ struct HStrangeCorrelationFilter { auto posdau = v0.posTrack_as(); auto negdau = v0.negTrack_as(); - if (negdau.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRows) + if (negdau.tpcNClsCrossedRows() < trackSelections.minTPCNCrossedRows) continue; - if (posdau.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRows) + if (posdau.tpcNClsCrossedRows() < trackSelections.minTPCNCrossedRows) continue; + bool isGoodK0Short = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short < v0Selection.lifetimecutK0S && + std::abs(v0.dcapostopv()) > v0Selection.dcaMesonToPV && std::abs(v0.dcanegtopv()) > v0Selection.dcaMesonToPV && + v0.qtarm() * v0Selection.armPodCut > std::abs(v0.alpha()); + bool isGoodLambda = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassLambda0 < v0Selection.lifetimecutLambda && + std::abs(v0.dcapostopv()) > v0Selection.dcaBaryonToPV && std::abs(v0.dcanegtopv()) > v0Selection.dcaMesonToPV; + bool isGoodAntiLambda = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassLambda0Bar < v0Selection.lifetimecutLambda && + std::abs(v0.dcapostopv()) > v0Selection.dcaMesonToPV && std::abs(v0.dcanegtopv()) > v0Selection.dcaBaryonToPV; if (std::abs(posdau.tpcNSigmaPi()) < strangedEdxNSigmaLoose && std::abs(negdau.tpcNSigmaPi()) < strangedEdxNSigmaLoose) { - if (doPPAnalysis || (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short < systCuts.lifetimecutK0S && - std::abs(v0.dcapostopv()) > systCuts.dcapostopvK0S && std::abs(v0.dcanegtopv()) > systCuts.dcanegtopvK0S && - v0.qtarm() * systCuts.armPodCut > std::abs(v0.alpha()))) { + if (doPPAnalysis || isGoodK0Short) { BIT_SET(compatibleK0Short, 0); } } if (std::abs(posdau.tpcNSigmaPi()) < strangedEdxNSigma && std::abs(negdau.tpcNSigmaPi()) < strangedEdxNSigma) { - if (doPPAnalysis || (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short < systCuts.lifetimecutK0S && - std::abs(v0.dcapostopv()) > systCuts.dcapostopvK0S && std::abs(v0.dcanegtopv()) > systCuts.dcanegtopvK0S && - v0.qtarm() * systCuts.armPodCut > std::abs(v0.alpha()))) { + if (doPPAnalysis || isGoodK0Short) { BIT_SET(compatibleK0Short, 1); } } if (std::abs(posdau.tpcNSigmaPi()) < strangedEdxNSigmaTight && std::abs(negdau.tpcNSigmaPi()) < strangedEdxNSigmaTight) { - if (doPPAnalysis || (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short < systCuts.lifetimecutK0S && - std::abs(v0.dcapostopv()) > systCuts.dcapostopvK0S && std::abs(v0.dcanegtopv()) > systCuts.dcanegtopvK0S && - v0.qtarm() * systCuts.armPodCut > std::abs(v0.alpha()))) { + if (doPPAnalysis || isGoodK0Short) { BIT_SET(compatibleK0Short, 2); } } - if (std::abs(posdau.tpcNSigmaPr()) < strangedEdxNSigmaLoose && std::abs(negdau.tpcNSigmaPi()) < strangedEdxNSigmaLoose) { - if (v0.v0cosPA() > systCuts.lambdaCospa) { - if (doPPAnalysis || (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short < systCuts.lifetimecutLambda && - std::abs(v0.dcapostopv()) > systCuts.dcapostopvLambda && std::abs(v0.dcanegtopv()) > systCuts.dcanegtopvLambda)) { + if (v0.v0cosPA() > v0Selection.lambdaCospa) { + if (std::abs(posdau.tpcNSigmaPr()) < strangedEdxNSigmaLoose && std::abs(negdau.tpcNSigmaPi()) < strangedEdxNSigmaLoose) { + if (doPPAnalysis || isGoodLambda) { BIT_SET(compatibleLambda, 0); } } - } - if (std::abs(posdau.tpcNSigmaPr()) < strangedEdxNSigma && std::abs(negdau.tpcNSigmaPi()) < strangedEdxNSigma) { - if (v0.v0cosPA() > systCuts.lambdaCospa) { - if (doPPAnalysis || (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short < systCuts.lifetimecutLambda && - std::abs(v0.dcapostopv()) > systCuts.dcapostopvLambda && std::abs(v0.dcanegtopv()) > systCuts.dcanegtopvLambda)) { + if (std::abs(posdau.tpcNSigmaPr()) < strangedEdxNSigma && std::abs(negdau.tpcNSigmaPi()) < strangedEdxNSigma) { + if (doPPAnalysis || isGoodLambda) { BIT_SET(compatibleLambda, 1); } } - } - if (std::abs(posdau.tpcNSigmaPr()) < strangedEdxNSigmaTight && std::abs(negdau.tpcNSigmaPi()) < strangedEdxNSigmaTight) { - if (v0.v0cosPA() > systCuts.lambdaCospa) { - if (doPPAnalysis || (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short < systCuts.lifetimecutLambda && - std::abs(v0.dcapostopv()) > systCuts.dcapostopvLambda && std::abs(v0.dcanegtopv()) > systCuts.dcanegtopvLambda)) { + + if (std::abs(posdau.tpcNSigmaPr()) < strangedEdxNSigmaTight && std::abs(negdau.tpcNSigmaPi()) < strangedEdxNSigmaTight) { + if (doPPAnalysis || isGoodLambda) { BIT_SET(compatibleLambda, 2); } } - } - if (std::abs(posdau.tpcNSigmaPi()) < strangedEdxNSigmaLoose && std::abs(negdau.tpcNSigmaPr()) < strangedEdxNSigmaLoose) { - if (v0.v0cosPA() > systCuts.lambdaCospa) { - if (doPPAnalysis || (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short < systCuts.lifetimecutLambda && - std::abs(v0.dcapostopv()) > systCuts.dcapostopvAntiLambda && std::abs(v0.dcanegtopv()) > systCuts.dcanegtopvAntiLambda)) { + if (std::abs(posdau.tpcNSigmaPi()) < strangedEdxNSigmaLoose && std::abs(negdau.tpcNSigmaPr()) < strangedEdxNSigmaLoose) { + if (doPPAnalysis || isGoodAntiLambda) { BIT_SET(compatibleAntiLambda, 0); } } - } - if (std::abs(posdau.tpcNSigmaPi()) < strangedEdxNSigma && std::abs(negdau.tpcNSigmaPr()) < strangedEdxNSigma) { - if (v0.v0cosPA() > systCuts.lambdaCospa) { - if (doPPAnalysis || (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short < systCuts.lifetimecutLambda && - std::abs(v0.dcapostopv()) > systCuts.dcapostopvAntiLambda && std::abs(v0.dcanegtopv()) > systCuts.dcanegtopvAntiLambda)) { + if (std::abs(posdau.tpcNSigmaPi()) < strangedEdxNSigma && std::abs(negdau.tpcNSigmaPr()) < strangedEdxNSigma) { + if (doPPAnalysis || isGoodAntiLambda) { BIT_SET(compatibleAntiLambda, 1); } } - } - if (std::abs(posdau.tpcNSigmaPi()) < strangedEdxNSigmaTight && std::abs(negdau.tpcNSigmaPr()) < strangedEdxNSigmaTight) { - if (v0.v0cosPA() > systCuts.lambdaCospa) { - if (doPPAnalysis || (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short < systCuts.lifetimecutLambda && - std::abs(v0.dcapostopv()) > systCuts.dcapostopvAntiLambda && std::abs(v0.dcanegtopv()) > systCuts.dcanegtopvAntiLambda)) { + if (std::abs(posdau.tpcNSigmaPi()) < strangedEdxNSigmaTight && std::abs(negdau.tpcNSigmaPr()) < strangedEdxNSigmaTight) { + if (doPPAnalysis || isGoodAntiLambda) { BIT_SET(compatibleAntiLambda, 2); } } @@ -1026,31 +994,36 @@ struct HStrangeCorrelationFilter { /// _________________________________________________ /// Step 3: Populate table with associated Cascades for (auto const& casc : Cascades) { - if (casc.eta() > systCuts.assocEtaMax || casc.eta() < systCuts.assocEtaMin) { + if (casc.eta() > generalSelections.assocEtaMax || casc.eta() < generalSelections.assocEtaMin) { continue; } - if (casc.pt() > systCuts.assocPtCutMax || casc.pt() < systCuts.assocPtCutMin) { + if (casc.pt() > generalSelections.assocPtCutMax || casc.pt() < generalSelections.assocPtCutMin) { continue; } - if (doPPAnalysis && (casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) < systCuts.v0Cospa || - casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()) < systCuts.cascCospa || - casc.cascradius() < systCuts.cascRadius || - std::abs(casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ())) < systCuts.cascMindcav0topv || - std::abs(casc.mLambda() - o2::constants::physics::MassLambda0) > systCuts.cascV0masswindow)) + if (doPPAnalysis && (casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) < cascSelection.cascv0cospa || + casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()) < cascSelection.cascCospa || + casc.cascradius() < cascSelection.cascRadius || + std::abs(casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ())) < cascSelection.cascMindcav0topv || + std::abs(casc.mLambda() - o2::constants::physics::MassLambda0) > cascSelection.cascV0masswindow)) continue; auto bachTrackCast = casc.bachelor_as(); auto posTrackCast = casc.posTrack_as(); auto negTrackCast = casc.negTrack_as(); // minimum TPC crossed rows - if (bachTrackCast.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRows) + if (bachTrackCast.tpcNClsCrossedRows() < trackSelections.minTPCNCrossedRows) continue; - if (posTrackCast.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRows) + if (posTrackCast.tpcNClsCrossedRows() < trackSelections.minTPCNCrossedRows) continue; - if (negTrackCast.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRows) + if (negTrackCast.tpcNClsCrossedRows() < trackSelections.minTPCNCrossedRows) continue; if (!doPPAnalysis && !cascadeSelectedPbPb(casc, collision.posX(), collision.posY(), collision.posZ())) continue; + + bool isGoodNegCascadePbPb = std::abs(casc.dcabachtopv()) > cascSelection.dcaBachToPV && std::abs(casc.dcapostopv()) > cascSelection.cascDcaBaryonToPV && + std::abs(casc.dcanegtopv()) > cascSelection.cascDcaMesonToPV; + bool isGoodPosCascadePbPb = std::abs(casc.dcabachtopv()) > cascSelection.dcaBachToPV && std::abs(casc.dcapostopv()) > cascSelection.cascDcaMesonToPV && + std::abs(casc.dcanegtopv()) > cascSelection.cascDcaBaryonToPV; // check dE/dx compatibility int compatibleXiMinus = 0; int compatibleXiPlus = 0; @@ -1061,90 +1034,70 @@ struct HStrangeCorrelationFilter { float ctauXi = o2::constants::physics::MassXiMinus * cascpos / ((cascptotmom + 1e-13) * ctauxi); float ctauOmega = o2::constants::physics::MassOmegaMinus * cascpos / ((cascptotmom + 1e-13) * ctauomega); + bool isGoodXiPbPb = std::abs(casc.mOmega() - o2::constants::physics::MassOmegaMinus) > cascSelection.rejcomp && + ctauXi < cascSelection.proplifetime && std::abs(casc.yXi()) < cascSelection.rapCut; + bool isGoodOmegaPbPb = std::abs(casc.mXi() - o2::constants::physics::MassXiMinus) > cascSelection.rejcomp && + ctauOmega < cascSelection.proplifetime && std::abs(casc.yOmega()) < cascSelection.rapCut; if (std::abs(posTrackCast.tpcNSigmaPr()) < strangedEdxNSigmaLoose && std::abs(negTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaLoose && std::abs(bachTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaLoose && casc.sign() < 0) { - if (doPPAnalysis || (std::abs(casc.dcabachtopv()) > MorePbPbsystCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > MorePbPbsystCuts.dcaBaryonToPV && - std::abs(casc.dcanegtopv()) > MorePbPbsystCuts.dcaMesonToPV && std::abs(casc.mOmega() - o2::constants::physics::MassOmegaMinus) > MorePbPbsystCuts.rejcomp && - ctauXi < MorePbPbsystCuts.proplifetime && std::abs(casc.yXi()) < MorePbPbsystCuts.rapCut)) { + if (doPPAnalysis || (isGoodNegCascadePbPb && isGoodXiPbPb)) { BIT_SET(compatibleXiMinus, 0); } } if (std::abs(posTrackCast.tpcNSigmaPr()) < strangedEdxNSigma && std::abs(negTrackCast.tpcNSigmaPi()) < strangedEdxNSigma && std::abs(bachTrackCast.tpcNSigmaPi()) < strangedEdxNSigma && casc.sign() < 0) { - if (doPPAnalysis || (std::abs(casc.dcabachtopv()) > MorePbPbsystCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > MorePbPbsystCuts.dcaBaryonToPV && - std::abs(casc.dcanegtopv()) > MorePbPbsystCuts.dcaMesonToPV && std::abs(casc.mOmega() - o2::constants::physics::MassOmegaMinus) > MorePbPbsystCuts.rejcomp && - ctauXi < MorePbPbsystCuts.proplifetime && std::abs(casc.yXi()) < MorePbPbsystCuts.rapCut)) { + if (doPPAnalysis || (isGoodNegCascadePbPb && isGoodXiPbPb)) { BIT_SET(compatibleXiMinus, 1); } } if (std::abs(posTrackCast.tpcNSigmaPr()) < strangedEdxNSigmaTight && std::abs(negTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaTight && std::abs(bachTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaTight && casc.sign() < 0) { - if (doPPAnalysis || (std::abs(casc.dcabachtopv()) > MorePbPbsystCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > MorePbPbsystCuts.dcaBaryonToPV && - std::abs(casc.dcanegtopv()) > MorePbPbsystCuts.dcaMesonToPV && std::abs(casc.mOmega() - o2::constants::physics::MassOmegaMinus) > MorePbPbsystCuts.rejcomp && - ctauXi < MorePbPbsystCuts.proplifetime && std::abs(casc.yXi()) < MorePbPbsystCuts.rapCut)) { + if (doPPAnalysis || (isGoodNegCascadePbPb && isGoodXiPbPb)) { BIT_SET(compatibleXiMinus, 2); } } if (std::abs(posTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaLoose && std::abs(negTrackCast.tpcNSigmaPr()) < strangedEdxNSigmaLoose && std::abs(bachTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaLoose && casc.sign() > 0) { - if (doPPAnalysis || (std::abs(casc.dcabachtopv()) > MorePbPbsystCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > MorePbPbsystCuts.dcaBaryonToPV && - std::abs(casc.dcanegtopv()) > MorePbPbsystCuts.dcaMesonToPV && std::abs(casc.mOmega() - o2::constants::physics::MassOmegaMinus) > MorePbPbsystCuts.rejcomp && - ctauXi < MorePbPbsystCuts.proplifetime && std::abs(casc.yXi()) < MorePbPbsystCuts.rapCut)) { + if (doPPAnalysis || (isGoodPosCascadePbPb && isGoodXiPbPb)) { BIT_SET(compatibleXiPlus, 0); } } if (std::abs(posTrackCast.tpcNSigmaPi()) < strangedEdxNSigma && std::abs(negTrackCast.tpcNSigmaPr()) < strangedEdxNSigma && std::abs(bachTrackCast.tpcNSigmaPi()) < strangedEdxNSigma && casc.sign() > 0) { - if (doPPAnalysis || (std::abs(casc.dcabachtopv()) > MorePbPbsystCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > MorePbPbsystCuts.dcaBaryonToPV && - std::abs(casc.dcanegtopv()) > MorePbPbsystCuts.dcaMesonToPV && std::abs(casc.mOmega() - o2::constants::physics::MassOmegaMinus) > MorePbPbsystCuts.rejcomp && - ctauXi < MorePbPbsystCuts.proplifetime && std::abs(casc.yXi()) < MorePbPbsystCuts.rapCut)) { + if (doPPAnalysis || (isGoodPosCascadePbPb && isGoodXiPbPb)) { BIT_SET(compatibleXiPlus, 1); } } if (std::abs(posTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaTight && std::abs(negTrackCast.tpcNSigmaPr()) < strangedEdxNSigmaTight && std::abs(bachTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaTight && casc.sign() > 0) { - if (doPPAnalysis || (std::abs(casc.dcabachtopv()) > MorePbPbsystCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > MorePbPbsystCuts.dcaBaryonToPV && - std::abs(casc.dcanegtopv()) > MorePbPbsystCuts.dcaMesonToPV && std::abs(casc.mOmega() - o2::constants::physics::MassOmegaMinus) > MorePbPbsystCuts.rejcomp && - ctauXi < MorePbPbsystCuts.proplifetime && std::abs(casc.yXi()) < MorePbPbsystCuts.rapCut)) { + if (doPPAnalysis || (isGoodPosCascadePbPb && isGoodXiPbPb)) { BIT_SET(compatibleXiPlus, 2); } } if (std::abs(posTrackCast.tpcNSigmaPr()) < strangedEdxNSigmaLoose && std::abs(negTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaLoose && std::abs(bachTrackCast.tpcNSigmaKa()) < strangedEdxNSigmaLoose && casc.sign() < 0) { - if (doPPAnalysis || (std::abs(casc.dcabachtopv()) > MorePbPbsystCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > MorePbPbsystCuts.dcaBaryonToPV && - std::abs(casc.dcanegtopv()) > MorePbPbsystCuts.dcaMesonToPV && std::abs(casc.mXi() - o2::constants::physics::MassXiMinus) > MorePbPbsystCuts.rejcomp && - ctauOmega < MorePbPbsystCuts.proplifetime && std::abs(casc.yOmega()) < MorePbPbsystCuts.rapCut)) { + if (doPPAnalysis || (isGoodNegCascadePbPb && isGoodOmegaPbPb)) { BIT_SET(compatibleOmegaMinus, 0); } } if (std::abs(posTrackCast.tpcNSigmaPr()) < strangedEdxNSigma && std::abs(negTrackCast.tpcNSigmaPi()) < strangedEdxNSigma && std::abs(bachTrackCast.tpcNSigmaKa()) < strangedEdxNSigma && casc.sign() < 0) { - if (doPPAnalysis || (std::abs(casc.dcabachtopv()) > MorePbPbsystCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > MorePbPbsystCuts.dcaBaryonToPV && - std::abs(casc.dcanegtopv()) > MorePbPbsystCuts.dcaMesonToPV && std::abs(casc.mXi() - o2::constants::physics::MassXiMinus) > MorePbPbsystCuts.rejcomp && - ctauOmega < MorePbPbsystCuts.proplifetime && std::abs(casc.yOmega()) < MorePbPbsystCuts.rapCut)) { + if (doPPAnalysis || (isGoodNegCascadePbPb && isGoodOmegaPbPb)) { BIT_SET(compatibleOmegaMinus, 1); } } if (std::abs(posTrackCast.tpcNSigmaPr()) < strangedEdxNSigmaTight && std::abs(negTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaTight && std::abs(bachTrackCast.tpcNSigmaKa()) < strangedEdxNSigmaTight && casc.sign() < 0) { - if (doPPAnalysis || (std::abs(casc.dcabachtopv()) > MorePbPbsystCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > MorePbPbsystCuts.dcaBaryonToPV && - std::abs(casc.dcanegtopv()) > MorePbPbsystCuts.dcaMesonToPV && std::abs(casc.mXi() - o2::constants::physics::MassXiMinus) > MorePbPbsystCuts.rejcomp && - ctauOmega < MorePbPbsystCuts.proplifetime && std::abs(casc.yOmega()) < MorePbPbsystCuts.rapCut)) { + if (doPPAnalysis || (isGoodNegCascadePbPb && isGoodOmegaPbPb)) { BIT_SET(compatibleOmegaMinus, 2); } } if (std::abs(posTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaLoose && std::abs(negTrackCast.tpcNSigmaPr()) < strangedEdxNSigmaLoose && std::abs(bachTrackCast.tpcNSigmaKa()) < strangedEdxNSigmaLoose && casc.sign() > 0) { - if (doPPAnalysis || (std::abs(casc.dcabachtopv()) > MorePbPbsystCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > MorePbPbsystCuts.dcaMesonToPV && - std::abs(casc.dcanegtopv()) > MorePbPbsystCuts.dcaBaryonToPV && std::abs(casc.mXi() - o2::constants::physics::MassXiMinus) > MorePbPbsystCuts.rejcomp && - ctauOmega < MorePbPbsystCuts.proplifetime && std::abs(casc.yOmega()) < MorePbPbsystCuts.rapCut)) { + if (doPPAnalysis || (isGoodPosCascadePbPb && isGoodOmegaPbPb)) { BIT_SET(compatibleOmegaPlus, 0); } } if (std::abs(posTrackCast.tpcNSigmaPi()) < strangedEdxNSigma && std::abs(negTrackCast.tpcNSigmaPr()) < strangedEdxNSigma && std::abs(bachTrackCast.tpcNSigmaKa()) < strangedEdxNSigma && casc.sign() > 0) { - if (doPPAnalysis || (std::abs(casc.dcabachtopv()) > MorePbPbsystCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > MorePbPbsystCuts.dcaMesonToPV && - std::abs(casc.dcanegtopv()) > MorePbPbsystCuts.dcaBaryonToPV && std::abs(casc.mXi() - o2::constants::physics::MassXiMinus) > MorePbPbsystCuts.rejcomp && - ctauOmega < MorePbPbsystCuts.proplifetime && std::abs(casc.yOmega()) < MorePbPbsystCuts.rapCut)) { + if (doPPAnalysis || (isGoodPosCascadePbPb && isGoodOmegaPbPb)) { BIT_SET(compatibleOmegaPlus, 1); } } if (std::abs(posTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaTight && std::abs(negTrackCast.tpcNSigmaPr()) < strangedEdxNSigmaTight && std::abs(bachTrackCast.tpcNSigmaKa()) < strangedEdxNSigmaTight && casc.sign() > 0) { - if (doPPAnalysis || (std::abs(casc.dcabachtopv()) > MorePbPbsystCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > MorePbPbsystCuts.dcaMesonToPV && - std::abs(casc.dcanegtopv()) > MorePbPbsystCuts.dcaBaryonToPV && std::abs(casc.mXi() - o2::constants::physics::MassXiMinus) > MorePbPbsystCuts.rejcomp && - ctauOmega < MorePbPbsystCuts.proplifetime && std::abs(casc.yOmega()) < MorePbPbsystCuts.rapCut)) { + if (doPPAnalysis || (isGoodPosCascadePbPb && isGoodOmegaPbPb)) { BIT_SET(compatibleOmegaPlus, 2); } } @@ -1197,17 +1150,17 @@ struct HStrangeCorrelationFilter { /// _________________________________________________ /// Step 3: Populate table with associated Cascades for (auto const& casc : Cascades) { - if (casc.eta() > systCuts.assocEtaMax || casc.eta() < systCuts.assocEtaMin) { + if (casc.eta() > generalSelections.assocEtaMax || casc.eta() < generalSelections.assocEtaMin) { continue; } - if (casc.pt() > systCuts.assocPtCutMax || casc.pt() < systCuts.assocPtCutMin) { + if (casc.pt() > generalSelections.assocPtCutMax || casc.pt() < generalSelections.assocPtCutMin) { continue; } - if (doPPAnalysis && (casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) < systCuts.v0Cospa || - casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()) < systCuts.cascCospa || - casc.cascradius() < systCuts.cascRadius || - std::abs(casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ())) < systCuts.cascMindcav0topv || - std::abs(casc.mLambda() - o2::constants::physics::MassLambda0) > systCuts.cascV0masswindow)) + if (doPPAnalysis && (casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) < cascSelection.cascv0cospa || + casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()) < cascSelection.cascCospa || + casc.cascradius() < cascSelection.cascRadius || + std::abs(casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ())) < cascSelection.cascMindcav0topv || + std::abs(casc.mLambda() - o2::constants::physics::MassLambda0) > cascSelection.cascV0masswindow)) continue; auto bachTrackCast = casc.bachelor_as(); @@ -1215,15 +1168,18 @@ struct HStrangeCorrelationFilter { auto negTrackCast = casc.negTrack_as(); // minimum TPC crossed rows - if (bachTrackCast.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRows) + if (bachTrackCast.tpcNClsCrossedRows() < trackSelections.minTPCNCrossedRows) continue; - if (posTrackCast.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRows) + if (posTrackCast.tpcNClsCrossedRows() < trackSelections.minTPCNCrossedRows) continue; - if (negTrackCast.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRows) + if (negTrackCast.tpcNClsCrossedRows() < trackSelections.minTPCNCrossedRows) continue; if (!doPPAnalysis && !cascadeSelectedPbPb(casc, collision.posX(), collision.posY(), collision.posZ())) continue; - + bool isGoodNegCascadePbPb = (std::abs(casc.dcabachtopv()) > cascSelection.dcaBachToPV && std::abs(casc.dcapostopv()) > cascSelection.cascDcaBaryonToPV && + std::abs(casc.dcanegtopv()) > cascSelection.cascDcaMesonToPV); + bool isGoodPosCascadePbPb = (std::abs(casc.dcabachtopv()) > cascSelection.dcaBachToPV && std::abs(casc.dcapostopv()) > cascSelection.cascDcaMesonToPV && + std::abs(casc.dcanegtopv()) > cascSelection.cascDcaBaryonToPV); // check dE/dx compatibility int compatibleXiMinus = 0; int compatibleXiPlus = 0; @@ -1234,90 +1190,70 @@ struct HStrangeCorrelationFilter { float ctauXi = o2::constants::physics::MassXiMinus * cascpos / ((cascptotmom + 1e-13) * ctauxi); float ctauOmega = o2::constants::physics::MassOmegaMinus * cascpos / ((cascptotmom + 1e-13) * ctauomega); + bool iGoodXiPbPb = std::abs(casc.mOmega() - o2::constants::physics::MassOmegaMinus) > cascSelection.rejcomp && + ctauXi < cascSelection.proplifetime && std::abs(casc.yXi()) < cascSelection.rapCut; + bool isGoodOmegaPbPb = std::abs(casc.mXi() - o2::constants::physics::MassXiMinus) > cascSelection.rejcomp && + ctauOmega < cascSelection.proplifetime && std::abs(casc.yOmega()) < cascSelection.rapCut; if (std::abs(posTrackCast.tpcNSigmaPr()) < strangedEdxNSigmaLoose && std::abs(negTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaLoose && std::abs(bachTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaLoose && casc.sign() < 0) { - if (doPPAnalysis || (std::abs(casc.dcabachtopv()) > MorePbPbsystCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > MorePbPbsystCuts.dcaBaryonToPV && - std::abs(casc.dcanegtopv()) > MorePbPbsystCuts.dcaMesonToPV && std::abs(casc.mOmega() - o2::constants::physics::MassOmegaMinus) > MorePbPbsystCuts.rejcomp && - ctauXi < MorePbPbsystCuts.proplifetime && std::abs(casc.yXi()) < MorePbPbsystCuts.rapCut)) { + if (doPPAnalysis || (isGoodNegCascadePbPb && iGoodXiPbPb)) { BIT_SET(compatibleXiMinus, 0); } } if (std::abs(posTrackCast.tpcNSigmaPr()) < strangedEdxNSigma && std::abs(negTrackCast.tpcNSigmaPi()) < strangedEdxNSigma && std::abs(bachTrackCast.tpcNSigmaPi()) < strangedEdxNSigma && casc.sign() < 0) { - if (doPPAnalysis || (std::abs(casc.dcabachtopv()) > MorePbPbsystCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > MorePbPbsystCuts.dcaBaryonToPV && - std::abs(casc.dcanegtopv()) > MorePbPbsystCuts.dcaMesonToPV && std::abs(casc.mOmega() - o2::constants::physics::MassOmegaMinus) > MorePbPbsystCuts.rejcomp && - ctauXi < MorePbPbsystCuts.proplifetime && std::abs(casc.yXi()) < MorePbPbsystCuts.rapCut)) { + if (doPPAnalysis || (isGoodNegCascadePbPb && iGoodXiPbPb)) { BIT_SET(compatibleXiMinus, 1); } } if (std::abs(posTrackCast.tpcNSigmaPr()) < strangedEdxNSigmaTight && std::abs(negTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaTight && std::abs(bachTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaTight && casc.sign() < 0) { - if (doPPAnalysis || (std::abs(casc.dcabachtopv()) > MorePbPbsystCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > MorePbPbsystCuts.dcaBaryonToPV && - std::abs(casc.dcanegtopv()) > MorePbPbsystCuts.dcaMesonToPV && std::abs(casc.mOmega() - o2::constants::physics::MassOmegaMinus) > MorePbPbsystCuts.rejcomp && - ctauXi < MorePbPbsystCuts.proplifetime && std::abs(casc.yXi()) < MorePbPbsystCuts.rapCut)) { + if (doPPAnalysis || (isGoodNegCascadePbPb && iGoodXiPbPb)) { BIT_SET(compatibleXiMinus, 2); } } if (std::abs(posTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaLoose && std::abs(negTrackCast.tpcNSigmaPr()) < strangedEdxNSigmaLoose && std::abs(bachTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaLoose && casc.sign() > 0) { - if (doPPAnalysis || (std::abs(casc.dcabachtopv()) > MorePbPbsystCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > MorePbPbsystCuts.dcaBaryonToPV && - std::abs(casc.dcanegtopv()) > MorePbPbsystCuts.dcaMesonToPV && std::abs(casc.mOmega() - o2::constants::physics::MassOmegaMinus) > MorePbPbsystCuts.rejcomp && - ctauXi < MorePbPbsystCuts.proplifetime && std::abs(casc.yXi()) < MorePbPbsystCuts.rapCut)) { + if (doPPAnalysis || (isGoodPosCascadePbPb && iGoodXiPbPb)) { BIT_SET(compatibleXiPlus, 0); } } if (std::abs(posTrackCast.tpcNSigmaPi()) < strangedEdxNSigma && std::abs(negTrackCast.tpcNSigmaPr()) < strangedEdxNSigma && std::abs(bachTrackCast.tpcNSigmaPi()) < strangedEdxNSigma && casc.sign() > 0) { - if (doPPAnalysis || (std::abs(casc.dcabachtopv()) > MorePbPbsystCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > MorePbPbsystCuts.dcaBaryonToPV && - std::abs(casc.dcanegtopv()) > MorePbPbsystCuts.dcaMesonToPV && std::abs(casc.mOmega() - o2::constants::physics::MassOmegaMinus) > MorePbPbsystCuts.rejcomp && - ctauXi < MorePbPbsystCuts.proplifetime && std::abs(casc.yXi()) < MorePbPbsystCuts.rapCut)) { + if (doPPAnalysis || (isGoodPosCascadePbPb && iGoodXiPbPb)) { BIT_SET(compatibleXiPlus, 1); } } if (std::abs(posTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaTight && std::abs(negTrackCast.tpcNSigmaPr()) < strangedEdxNSigmaTight && std::abs(bachTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaTight && casc.sign() > 0) { - if (doPPAnalysis || (std::abs(casc.dcabachtopv()) > MorePbPbsystCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > MorePbPbsystCuts.dcaBaryonToPV && - std::abs(casc.dcanegtopv()) > MorePbPbsystCuts.dcaMesonToPV && std::abs(casc.mOmega() - o2::constants::physics::MassOmegaMinus) > MorePbPbsystCuts.rejcomp && - ctauXi < MorePbPbsystCuts.proplifetime && std::abs(casc.yXi()) < MorePbPbsystCuts.rapCut)) { + if (doPPAnalysis || (isGoodPosCascadePbPb && iGoodXiPbPb)) { BIT_SET(compatibleXiPlus, 2); } } if (std::abs(posTrackCast.tpcNSigmaPr()) < strangedEdxNSigmaLoose && std::abs(negTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaLoose && std::abs(bachTrackCast.tpcNSigmaKa()) < strangedEdxNSigmaLoose && casc.sign() < 0) { - if (doPPAnalysis || (std::abs(casc.dcabachtopv()) > MorePbPbsystCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > MorePbPbsystCuts.dcaBaryonToPV && - std::abs(casc.dcanegtopv()) > MorePbPbsystCuts.dcaMesonToPV && std::abs(casc.mXi() - o2::constants::physics::MassXiMinus) > MorePbPbsystCuts.rejcomp && - ctauOmega < MorePbPbsystCuts.proplifetime && std::abs(casc.yOmega()) < MorePbPbsystCuts.rapCut)) { + if (doPPAnalysis || (isGoodNegCascadePbPb && isGoodOmegaPbPb)) { BIT_SET(compatibleOmegaMinus, 0); } } if (std::abs(posTrackCast.tpcNSigmaPr()) < strangedEdxNSigma && std::abs(negTrackCast.tpcNSigmaPi()) < strangedEdxNSigma && std::abs(bachTrackCast.tpcNSigmaKa()) < strangedEdxNSigma && casc.sign() < 0) { - if (doPPAnalysis || (std::abs(casc.dcabachtopv()) > MorePbPbsystCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > MorePbPbsystCuts.dcaBaryonToPV && - std::abs(casc.dcanegtopv()) > MorePbPbsystCuts.dcaMesonToPV && std::abs(casc.mXi() - o2::constants::physics::MassXiMinus) > MorePbPbsystCuts.rejcomp && - ctauOmega < MorePbPbsystCuts.proplifetime && std::abs(casc.yOmega()) < MorePbPbsystCuts.rapCut)) { + if (doPPAnalysis || (isGoodNegCascadePbPb && isGoodOmegaPbPb)) { BIT_SET(compatibleOmegaMinus, 1); } } if (std::abs(posTrackCast.tpcNSigmaPr()) < strangedEdxNSigmaTight && std::abs(negTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaTight && std::abs(bachTrackCast.tpcNSigmaKa()) < strangedEdxNSigmaTight && casc.sign() < 0) { - if (doPPAnalysis || (std::abs(casc.dcabachtopv()) > MorePbPbsystCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > MorePbPbsystCuts.dcaBaryonToPV && - std::abs(casc.dcanegtopv()) > MorePbPbsystCuts.dcaMesonToPV && std::abs(casc.mXi() - o2::constants::physics::MassXiMinus) > MorePbPbsystCuts.rejcomp && - ctauOmega < MorePbPbsystCuts.proplifetime && std::abs(casc.yOmega()) < MorePbPbsystCuts.rapCut)) { + if (doPPAnalysis || (isGoodNegCascadePbPb && isGoodOmegaPbPb)) { BIT_SET(compatibleOmegaMinus, 2); } } if (std::abs(posTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaLoose && std::abs(negTrackCast.tpcNSigmaPr()) < strangedEdxNSigmaLoose && std::abs(bachTrackCast.tpcNSigmaKa()) < strangedEdxNSigmaLoose && casc.sign() > 0) { - if (doPPAnalysis || (std::abs(casc.dcabachtopv()) > MorePbPbsystCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > MorePbPbsystCuts.dcaMesonToPV && - std::abs(casc.dcanegtopv()) > MorePbPbsystCuts.dcaBaryonToPV && std::abs(casc.mXi() - o2::constants::physics::MassXiMinus) > MorePbPbsystCuts.rejcomp && - ctauOmega < MorePbPbsystCuts.proplifetime && std::abs(casc.yOmega()) < MorePbPbsystCuts.rapCut)) { + if (doPPAnalysis || (isGoodPosCascadePbPb && isGoodOmegaPbPb)) { BIT_SET(compatibleOmegaPlus, 0); } } if (std::abs(posTrackCast.tpcNSigmaPi()) < strangedEdxNSigma && std::abs(negTrackCast.tpcNSigmaPr()) < strangedEdxNSigma && std::abs(bachTrackCast.tpcNSigmaKa()) < strangedEdxNSigma && casc.sign() > 0) { - if (doPPAnalysis || (std::abs(casc.dcabachtopv()) > MorePbPbsystCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > MorePbPbsystCuts.dcaMesonToPV && - std::abs(casc.dcanegtopv()) > MorePbPbsystCuts.dcaBaryonToPV && std::abs(casc.mXi() - o2::constants::physics::MassXiMinus) > MorePbPbsystCuts.rejcomp && - ctauOmega < MorePbPbsystCuts.proplifetime && std::abs(casc.yOmega()) < MorePbPbsystCuts.rapCut)) { + if (doPPAnalysis || (isGoodPosCascadePbPb && isGoodOmegaPbPb)) { BIT_SET(compatibleOmegaPlus, 1); } } if (std::abs(posTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaTight && std::abs(negTrackCast.tpcNSigmaPr()) < strangedEdxNSigmaTight && std::abs(bachTrackCast.tpcNSigmaKa()) < strangedEdxNSigmaTight && casc.sign() > 0) { - if (doPPAnalysis || (std::abs(casc.dcabachtopv()) > MorePbPbsystCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > MorePbPbsystCuts.dcaMesonToPV && - std::abs(casc.dcanegtopv()) > MorePbPbsystCuts.dcaBaryonToPV && std::abs(casc.mXi() - o2::constants::physics::MassXiMinus) > MorePbPbsystCuts.rejcomp && - ctauOmega < MorePbPbsystCuts.proplifetime && std::abs(casc.yOmega()) < MorePbPbsystCuts.rapCut)) { + if (doPPAnalysis || (isGoodPosCascadePbPb && isGoodOmegaPbPb)) { BIT_SET(compatibleOmegaPlus, 2); } } diff --git a/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx b/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx index 159c2e492ce..0f9dfe5a616 100644 --- a/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx +++ b/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx @@ -69,6 +69,7 @@ struct HStrangeCorrelation { OutputObj zorroSummary{"zorroSummary"}; struct : ConfigurableGroup { + std::string prefix = "masterConfigurations"; Configurable doPPAnalysis{"doPPAnalysis", true, "if in pp, set to true"}; Configurable collisionHasTriggOrAssoc{"collisionHasTriggOrAssoc", 0, "require the collisions containing (0:no requirement 1:trig 2:assoc 3:trig or assoc 4:trig and assoc"}; Configurable doFullCorrelationStudy{"doFullCorrelationStudy", true, "if true, do full correlation study by creating all THnSparse histograms for the correlation function"}; @@ -112,6 +113,7 @@ struct HStrangeCorrelation { // Axes - configurable for smaller sizes struct : ConfigurableGroup { + std::string prefix = "axesConfigurations"; ConfigurableAxis axisMult{"axisMult", {VARIABLE_WIDTH, 0.0f, 0.01f, 1.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 70.0f, 100.0f}, "Mixing bins - multiplicity"}; ConfigurableAxis axisVtxZ{"axisVtxZ", {VARIABLE_WIDTH, -10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}, "Mixing bins - z-vertex"}; ConfigurableAxis axisPhi{"axisPhi", {72, 0, TwoPI}, "#phi"}; @@ -127,6 +129,7 @@ struct HStrangeCorrelation { // for topo var QA struct : ConfigurableGroup { + std::string prefix = "massWindowConfigurations"; Configurable maxPeakNSigma{"maxPeakNSigma", 5, "Peak region edge definition (in sigma)"}; Configurable minBgNSigma{"minBgNSigma", 5, "Bg region edge closest to peak (in sigma)"}; Configurable maxBgNSigma{"maxBgNSigma", 10, "Bg region edge furthest to peak (in sigma)"}; @@ -135,6 +138,7 @@ struct HStrangeCorrelation { // Implementation of on-the-spot efficiency correction struct : ConfigurableGroup { + std::string prefix = "efficiencyFlags"; Configurable applyEfficiencyCorrection{"applyEfficiencyCorrection", false, "apply efficiency correction"}; Configurable applyEfficiencyForTrigger{"applyEfficiencyForTrigger", false, "apply efficiency correction for the trigger particle"}; Configurable applyEfficiencyPropagation{"applyEfficiencyPropagation", false, "propagate also the efficiency uncertainty"}; @@ -147,9 +151,8 @@ struct HStrangeCorrelation { Configurable efficiencyCCDBPath{"efficiencyCCDBPath", "GLO/Config/GeometryAligned", "Path of the efficiency corrections"}; // Configurables for doing subwagon systematics - // Group all settings necessary for systematics in a specific ConfigurableGroup struct : ConfigurableGroup { - std::string prefix = "systematics"; + std::string prefix = "trackSelection"; // --- Track quality variations (single track, both trigger and assoc daughters) Configurable minTPCNCrossedRowsTrigger{"minTPCNCrossedRowsTrigger", 70, "Minimum TPC crossed rows (trigger)"}; Configurable minTPCNCrossedRowsAssociated{"minTPCNCrossedRowsAssociated", 70, "Minimum TPC crossed rows (associated)"}; @@ -159,16 +162,22 @@ struct HStrangeCorrelation { Configurable assocMaxTPCSharedClusters{"assocMaxTPCSharedClusters", 200, "maximum number of shared TPC clusters (inclusive) for assoc primary tracks"}; Configurable triggerRequireL0{"triggerRequireL0", false, "require ITS L0 cluster for trigger"}; Configurable assocRequireL0{"assocRequireL0", true, "require ITS L0 cluster for assoc primary track"}; - // Track quality in PbPb - Configurable tpcPidNsigmaCut{"tpcPidNsigmaCut", 5, "tpcPidNsigmaCut"}; + Configurable minTPCChi2PerClusterAssociated{"minTPCChi2PerClusterAssociated", 4.0f, "Minimum TPC chi2 per cluster for associated primary tracks"}; + Configurable checksRequireTPCChi2{"checksRequireTPCChi2", false, "require TPC chi2 per cluster for trigger and associated primary tracks"}; + Configurable requireClusterInITS{"requireClusterInITS", false, "require cluster in ITS for V0 and cascade daughter tracks"}; + Configurable minITSClustersForDaughterTracks{"minITSClustersForDaughterTracks", 1, "Minimum number of ITS clusters for V0 daughter tracks"}; // --- Trigger: DCA variation from basic formula: |DCAxy| < 0.004f + (0.013f / pt) Configurable dcaXYconstant{"dcaXYconstant", 0.004, "[0] in |DCAxy| < [0]+[1]/pT"}; Configurable dcaXYpTdep{"dcaXYpTdep", 0.013, "[1] in |DCAxy| < [0]+[1]/pT"}; - + // --- Assoc track: DCA variation from basic formula: |DCAxy| < 0.004f + (0.013f / pt) Configurable dcaXYconstantAssoc{"dcaXYconstantAssoc", 0.004, "[0] in |DCAxy| < [0]+[1]/pT"}; Configurable dcaXYpTdepAssoc{"dcaXYpTdepAssoc", 0.013, "[1] in |DCAxy| < [0]+[1]/pT"}; - + Configurable dEdxCompatibility{"dEdxCompatibility", 1, "0: loose, 1: normal, 2: tight. Defined in HStrangeCorrelationFilter"}; + } trackSelection; + struct : ConfigurableGroup { + std::string prefix = "v0Selection"; + // --- V0 selections (both K0Short and Lambda, but some can be Lambda specific, see below) // --- Associated: topological variable variation (OK to vary all-at-once, at least for first study) Configurable v0cospa{"v0cospa", 0.97, "V0 CosPA"}; // double -> N.B. dcos(x)/dx = 0 at x=0) Configurable dcaV0dau{"dcaV0dau", 1.0, "DCA V0 Daughters"}; @@ -176,50 +185,49 @@ struct HStrangeCorrelation { Configurable dcapostopv{"dcapostopv", 0.06, "DCA Pos To PV"}; Configurable v0RadiusMin{"v0RadiusMin", 0.5, "v0radius"}; Configurable v0RadiusMax{"v0RadiusMax", 200, "v0radius"}; - // more V0 selections in PbPb + Configurable dcaBaryonToPV{"dcaBaryonToPV", 0.2, "DCA of baryon daughter track To PV"}; + Configurable dcaMesonToPV{"dcaMesonToPV", 0.05, "DCA of meson daughter track To PV"}; Configurable lifetimecutK0S{"lifetimecutK0S", 20, "lifetimecutK0S"}; Configurable lifetimecutLambda{"lifetimecutLambda", 30, "lifetimecutLambda"}; - Configurable dcanegtopvK0S{"dcanegtopvK0S", 0.1, "DCA Neg To PV"}; - Configurable dcapostopvK0S{"dcapostopvK0S", 0.1, "DCA Pos To PV"}; - Configurable dcanegtopvLambda{"dcanegtopvLambda", 0.05, "DCA Neg To PV"}; - Configurable dcapostopvLambda{"dcapostopvLambda", 0.2, "DCA Pos To PV"}; - Configurable dcanegtopvAntiLambda{"dcanegtopvAntiLambda", 0.2, "DCA Neg To PV"}; - Configurable dcapostopvAntiLambda{"dcapostopvAntiLambda", 0.05, "DCA Pos To PV"}; // original equation: lArmPt*2>TMath::Abs(lArmAlpha) only for K0S Configurable armPodCut{"armPodCut", 5.0f, "pT * (cut) > |alpha|, AP cut. Negative: no cut"}; + } v0Selection; - // cascade selections + struct : ConfigurableGroup { + std::string prefix = "cascadeSelections"; Configurable cascCospa{"cascCospa", 0.95, "cascCospa"}; - Configurable cascDcacascdau{"cascDcacascdau", 1.0, "cascDcacascdau"}; - Configurable cascDcabachtopv{"cascDcabachtopv", 0.1, "cascDcabachtopv"}; + Configurable dcaCascDaughters{"dcaCascDaughters", 1.0, "DCA between the V0 candidate and the bachelor track"}; + // Configurable cascDcabachtopv{"cascDcabachtopv", 0.1, "cascDcabachtopv"}; Configurable cascRadius{"cascRadius", 0.5, "cascRadius"}; Configurable cascV0masswindow{"cascV0masswindow", 0.01, "cascV0masswindow"}; - Configurable cascMindcav0topv{"cascMindcav0topv", 0.01, "cascMindcav0topv"}; - // more cascade selections in PbPb Configurable bachBaryonCosPA{"bachBaryonCosPA", 0.9999, "Bachelor baryon CosPA"}; Configurable bachBaryonDCAxyToPV{"bachBaryonDCAxyToPV", 0.08, "DCA bachelor baryon to PV"}; - Configurable dcaBaryonToPV{"dcaBaryonToPV", 0.05, "DCA of baryon doughter track To PV"}; - Configurable dcaMesonToPV{"dcaMesonToPV", 0.1, "DCA of meson doughter track To PV"}; - Configurable dcaBachToPV{"dcaBachToPV", 0.07, "DCA Bach To PV"}; Configurable cascdcaV0dau{"cascdcaV0dau", 0.5, "DCA V0 Daughters"}; + Configurable proplifetime{"proplifetime", 3, "ctau/"}; + Configurable rejcomp{"rejcomp", 0.008, "Competing Cascade rejection"}; + Configurable rapCut{"rapCut", 0.8, "Rapidity acceptance"}; Configurable dcaCacsDauPar0{"dcaCacsDauPar0", 0.8, " par for pt dep DCA cascade daughter cut, p_T < 1 GeV/c"}; Configurable dcaCacsDauPar1{"dcaCacsDauPar1", 0.5, " par for pt dep DCA cascade daughter cut, 1< p_T < 4 GeV/c"}; Configurable dcaCacsDauPar2{"dcaCacsDauPar2", 0.2, " par for pt dep DCA cascade daughter cut, p_T > 4 GeV/c"}; Configurable cascdcaV0ToPV{"cascdcaV0ToPV", 0.06, "DCA V0 To PV"}; Configurable cascv0cospa{"cascv0cospa", 0.98, "V0 CosPA"}; Configurable cascv0RadiusMin{"cascv0RadiusMin", 2.5, "v0radius"}; - Configurable proplifetime{"proplifetime", 3, "ctau/"}; - Configurable lambdaMassWin{"lambdaMassWin", 0.005, "V0 Mass window limit"}; - Configurable rejcomp{"rejcomp", 0.008, "Competing Cascade rejection"}; - Configurable rapCut{"rapCut", 0.8, "Rapidity acceptance"}; - + Configurable dcaBaryonToPV{"dcaBaryonToPV", 0.05, "DCA of baryon doughter track To PV"}; + Configurable dcaMesonToPV{"dcaMesonToPV", 0.1, "DCA of meson doughter track To PV"}; + Configurable dcaBachToPV{"dcaBachToPV", 0.07, "DCA Bach To PV"}; // pt Range for pt dep cuts Configurable highPtForCascDaugPtDep{"highPtForCascDaugPtDep", 4.0, "high pt range for pt dep cuts"}; Configurable lowPtForCascDaugPtDep{"lowPtForCascDaugPtDep", 1.0, "low pt range for pt dep cuts"}; - // dE/dx for associated daughters - Configurable dEdxCompatibility{"dEdxCompatibility", 1, "0: loose, 1: normal, 2: tight. Defined in HStrangeCorrelationFilter"}; + } cascadeSelections; + struct : ConfigurableGroup { + std::string prefix = "`"; + // cascade selections + // more cascade selections in PbPb + // Configurable bachBaryonCosPA{"bachBaryonCosPA", 0.9999, "Bachelor baryon CosPA"}; + // Configurable bachBaryonDCAxyToPV{"bachBaryonDCAxyToPV", 0.08, "DCA bachelor baryon to PV"}; + // // on the fly correction instead of mixingParameter Configurable doOnTheFlyFlattening{"doOnTheFlyFlattening", 0, "enable an on-the-fly correction instead of using mixing"}; @@ -228,7 +236,7 @@ struct HStrangeCorrelation { Configurable transwerseDeltaEtaRangeMax{"transwerseDeltaEtaRangeMax", 2.0, "maximum delta eta for transverse region"}; Configurable towardDeltaEtaRange{"towardDeltaEtaRange", 0.8, "delta eta range for toward region"}; // (N.B.: sources that can be investigated in post are not listed!) - } systCuts; + } checks; struct ValidCollision { struct ValidParticle { @@ -432,26 +440,26 @@ struct HStrangeCorrelation { // proper lifetime , DCA daughter to prim.vtx if (masterConfigurations.doCorrelationK0Short) { // proper lifetime - if (v0.distovertotmom(pvx, pvy, pvz) * o2::constants::physics::MassK0Short < systCuts.lifetimecutK0S) + if (v0.distovertotmom(pvx, pvy, pvz) * o2::constants::physics::MassK0Short < v0Selection.lifetimecutK0S) SETBIT(bitMap, 0); // DCA daughter to prim.vtx and armenteros - if (std::abs(v0.dcapostopv()) > systCuts.dcapostopvK0S && std::abs(v0.dcanegtopv()) > systCuts.dcanegtopvK0S && v0.qtarm() * systCuts.armPodCut > std::abs(v0.alpha())) + if (std::abs(v0.dcapostopv()) > v0Selection.dcaMesonToPV && std::abs(v0.dcanegtopv()) > v0Selection.dcaMesonToPV && v0.qtarm() * v0Selection.armPodCut > std::abs(v0.alpha())) SETBIT(bitMap, 3); } if (masterConfigurations.doCorrelationLambda) { // proper lifetime - if (v0.distovertotmom(pvx, pvy, pvz) * o2::constants::physics::MassLambda0 < systCuts.lifetimecutLambda) + if (v0.distovertotmom(pvx, pvy, pvz) * o2::constants::physics::MassLambda0 < v0Selection.lifetimecutLambda) SETBIT(bitMap, 1); // DCA daughter to prim.vtx - if (std::abs(v0.dcapostopv()) > systCuts.dcapostopvLambda && std::abs(v0.dcanegtopv()) > systCuts.dcanegtopvLambda) + if (std::abs(v0.dcapostopv()) > v0Selection.dcaBaryonToPV && std::abs(v0.dcanegtopv()) > v0Selection.dcaMesonToPV) SETBIT(bitMap, 4); } if (masterConfigurations.doCorrelationAntiLambda) { // proper lifetime - if (v0.distovertotmom(pvx, pvy, pvz) * o2::constants::physics::MassLambda0 < systCuts.lifetimecutLambda) + if (v0.distovertotmom(pvx, pvy, pvz) * o2::constants::physics::MassLambda0 < v0Selection.lifetimecutLambda) SETBIT(bitMap, 2); // DCA daughter to prim.vtx - if (std::abs(v0.dcapostopv()) > systCuts.dcapostopvAntiLambda && std::abs(v0.dcanegtopv()) > systCuts.dcanegtopvAntiLambda) + if (std::abs(v0.dcapostopv()) > v0Selection.dcaMesonToPV && std::abs(v0.dcanegtopv()) > v0Selection.dcaBaryonToPV) SETBIT(bitMap, 5); } return bitMap; @@ -465,64 +473,65 @@ struct HStrangeCorrelation { float cascptotmom = std::hypot(casc.px(), casc.py(), casc.pz()); float ctauXi = o2::constants::physics::MassXiMinus * cascpos / ((cascptotmom + 1e-13) * ctauxi); float ctauOmega = o2::constants::physics::MassOmegaMinus * cascpos / ((cascptotmom + 1e-13) * ctauomega); + + bool isGoodDCANegCasc = std::abs(casc.dcabachtopv()) > cascadeSelections.dcaBachToPV && std::abs(casc.dcapostopv()) > cascadeSelections.dcaBaryonToPV && + std::abs(casc.dcanegtopv()) > cascadeSelections.dcaMesonToPV; + bool isGoodDCAPosCasc = std::abs(casc.dcabachtopv()) > cascadeSelections.dcaBachToPV && std::abs(casc.dcapostopv()) > cascadeSelections.dcaMesonToPV && + std::abs(casc.dcanegtopv()) > cascadeSelections.dcaBaryonToPV; // TPC PID and DCA daughter to prim.vtx and comopeting casc.rej and life time if (masterConfigurations.doCorrelationXiMinus) { // DCA daughter to prim.vtx - if (std::abs(casc.dcabachtopv()) > systCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > systCuts.dcaBaryonToPV && - std::abs(casc.dcanegtopv()) > systCuts.dcaMesonToPV) + if (isGoodDCANegCasc) SETBIT(bitMap, 0); // comopeting casc.rej - if (std::abs(casc.mOmega() - o2::constants::physics::MassOmegaMinus) > systCuts.rejcomp) + if (std::abs(casc.mOmega() - o2::constants::physics::MassOmegaMinus) > cascadeSelections.rejcomp) SETBIT(bitMap, 4); - if (ctauXi < systCuts.proplifetime) + if (ctauXi < cascadeSelections.proplifetime) SETBIT(bitMap, 8); // y cut - if (std::abs(casc.yXi()) < systCuts.rapCut) + if (std::abs(casc.yXi()) < cascadeSelections.rapCut) SETBIT(bitMap, 12); } if (masterConfigurations.doCorrelationXiPlus) { // DCA daughter to prim.vtx - if (std::abs(casc.dcabachtopv()) > systCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > systCuts.dcaMesonToPV && - std::abs(casc.dcanegtopv()) > systCuts.dcaBaryonToPV) + if (isGoodDCAPosCasc) SETBIT(bitMap, 1); // comopeting casc.rej - if (std::abs(casc.mOmega() - o2::constants::physics::MassOmegaMinus) > systCuts.rejcomp) + if (std::abs(casc.mOmega() - o2::constants::physics::MassOmegaMinus) > cascadeSelections.rejcomp) SETBIT(bitMap, 5); // life time - if (ctauXi < systCuts.proplifetime) + if (ctauXi < cascadeSelections.proplifetime) SETBIT(bitMap, 9); // y cut - if (std::abs(casc.yXi()) > systCuts.rapCut) + if (std::abs(casc.yXi()) > cascadeSelections.rapCut) SETBIT(bitMap, 13); } if (masterConfigurations.doCorrelationOmegaMinus) { // DCA daughter to prim.vtx - if (std::abs(casc.dcabachtopv()) > systCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > systCuts.dcaBaryonToPV && - std::abs(casc.dcanegtopv()) > systCuts.dcaMesonToPV) + if (isGoodDCANegCasc) SETBIT(bitMap, 2); // comopeting casc.rej - if (std::abs(casc.mXi() - o2::constants::physics::MassXiMinus) > systCuts.rejcomp) + if (std::abs(casc.mXi() - o2::constants::physics::MassXiMinus) > cascadeSelections.rejcomp) SETBIT(bitMap, 6); // life time - if (ctauOmega < systCuts.proplifetime) + if (ctauOmega < cascadeSelections.proplifetime) SETBIT(bitMap, 10); // y cut - if (std::abs(casc.yOmega()) < systCuts.rapCut) + if (std::abs(casc.yOmega()) < cascadeSelections.rapCut) SETBIT(bitMap, 14); } if (masterConfigurations.doCorrelationOmegaPlus) { // DCA daughter to prim.vtx - if (std::abs(casc.dcabachtopv()) > systCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > systCuts.dcaMesonToPV && - std::abs(casc.dcanegtopv()) > systCuts.dcaBaryonToPV) + if (isGoodDCAPosCasc) SETBIT(bitMap, 3); // comopeting casc.rej - if (std::abs(casc.mXi() - o2::constants::physics::MassXiMinus) > systCuts.rejcomp) + if (std::abs(casc.mXi() - o2::constants::physics::MassXiMinus) > cascadeSelections.rejcomp) SETBIT(bitMap, 7); // life time - if (ctauOmega < systCuts.proplifetime) + if (ctauOmega < cascadeSelections.proplifetime) SETBIT(bitMap, 11); // y cut - if (std::abs(casc.yOmega()) > systCuts.rapCut) + if (std::abs(casc.yOmega()) > cascadeSelections.rapCut) SETBIT(bitMap, 15); } return bitMap; @@ -531,20 +540,20 @@ struct HStrangeCorrelation { template bool isValidTrigger(TTrack track, bool isLeading) { - if (track.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRowsTrigger) { + if (track.tpcNClsCrossedRows() < trackSelection.minTPCNCrossedRowsTrigger) { return false; // crossed rows } - if (!track.hasITS() && systCuts.triggerRequireITS) { + if (!track.hasITS() && trackSelection.triggerRequireITS) { return false; // skip, doesn't have ITS signal (skips lots of TPC-only!) } - if (track.tpcNClsShared() > systCuts.triggerMaxTPCSharedClusters) { + if (track.tpcNClsShared() > trackSelection.triggerMaxTPCSharedClusters) { return false; // skip, has shared clusters } - if (!(TESTBIT(track.itsClusterMap(), 0)) && systCuts.triggerRequireL0) { + if (!(TESTBIT(track.itsClusterMap(), 0)) && trackSelection.triggerRequireL0) { return false; // skip, doesn't have cluster in ITS L0 } // systematic variations: trigger DCAxy - if (std::abs(track.dcaXY()) > systCuts.dcaXYconstant + systCuts.dcaXYpTdep * std::abs(track.signed1Pt())) { + if (std::abs(track.dcaXY()) > trackSelection.dcaXYconstant + trackSelection.dcaXYpTdep * std::abs(track.signed1Pt())) { return false; } if (track.pt() > axisRanges[3][1] || track.pt() < axisRanges[3][0]) { @@ -564,20 +573,20 @@ struct HStrangeCorrelation { template bool isValidAssocHadron(TTrack track) { - if (track.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRowsAssociated) { + if (track.tpcNClsCrossedRows() < trackSelection.minTPCNCrossedRowsAssociated) { return false; // crossed rows } - if (!track.hasITS() && systCuts.assocRequireITS) { + if (!track.hasITS() && trackSelection.assocRequireITS) { return false; // skip, doesn't have ITS signal (skips lots of TPC-only!) } - if (track.tpcNClsShared() > systCuts.assocMaxTPCSharedClusters) { + if (track.tpcNClsShared() > trackSelection.assocMaxTPCSharedClusters) { return false; // skip, has shared clusters } - if (!(TESTBIT(track.itsClusterMap(), 0)) && systCuts.assocRequireL0) { + if (!(TESTBIT(track.itsClusterMap(), 0)) && trackSelection.assocRequireL0) { return false; // skip, doesn't have cluster in ITS L0 } // systematic variations: trigger DCAxy - if (std::abs(track.dcaXY()) > systCuts.dcaXYconstantAssoc + systCuts.dcaXYpTdepAssoc * std::abs(track.signed1Pt())) { + if (std::abs(track.dcaXY()) > trackSelection.dcaXYconstantAssoc + trackSelection.dcaXYpTdepAssoc * std::abs(track.signed1Pt())) { return false; } if (track.pt() > axisRanges[2][1] || track.pt() < axisRanges[2][0]) { @@ -590,15 +599,15 @@ struct HStrangeCorrelation { bool v0SelectedPbPb(TV0 v0) { // v0radius - if (v0.v0radius() < systCuts.v0RadiusMin) + if (v0.v0radius() < v0Selection.v0RadiusMin) return false; - if (v0.v0radius() > systCuts.v0RadiusMax) + if (v0.v0radius() > v0Selection.v0RadiusMax) return false; // v0cosPA - if (v0.v0cosPA() < systCuts.v0cospa) + if (v0.v0cosPA() < v0Selection.v0cospa) return false; // dcaV0daughters - if (v0.dcaV0daughters() > systCuts.dcaV0dau) + if (v0.dcaV0daughters() > v0Selection.dcaV0dau) return false; return true; } @@ -608,39 +617,39 @@ struct HStrangeCorrelation { bool cascadeSelectedPbPb(TCascade casc, float pvx, float pvy, float pvz) { // bachBaryonCosPA - if (casc.bachBaryonCosPA() < systCuts.bachBaryonCosPA) + if (casc.bachBaryonCosPA() < cascadeSelections.bachBaryonCosPA) return false; // bachBaryonDCAxyToPV - if (std::abs(casc.bachBaryonDCAxyToPV()) > systCuts.bachBaryonDCAxyToPV) + if (std::abs(casc.bachBaryonDCAxyToPV()) > cascadeSelections.bachBaryonDCAxyToPV) return false; // casccosPA - if (casc.casccosPA(pvx, pvy, pvz) < systCuts.cascCospa) + if (casc.casccosPA(pvx, pvy, pvz) < cascadeSelections.cascCospa) return false; // dcacascdaughters - float ptDepCut = systCuts.dcaCacsDauPar0; - if (casc.pt() > systCuts.lowPtForCascDaugPtDep && casc.pt() < systCuts.highPtForCascDaugPtDep) - ptDepCut = systCuts.dcaCacsDauPar1; - else if (casc.pt() > systCuts.highPtForCascDaugPtDep) - ptDepCut = systCuts.dcaCacsDauPar2; + float ptDepCut = cascadeSelections.dcaCacsDauPar0; + if (casc.pt() > cascadeSelections.lowPtForCascDaugPtDep && casc.pt() < cascadeSelections.highPtForCascDaugPtDep) + ptDepCut = cascadeSelections.dcaCacsDauPar1; + else if (casc.pt() > cascadeSelections.highPtForCascDaugPtDep) + ptDepCut = cascadeSelections.dcaCacsDauPar2; if (casc.dcacascdaughters() > ptDepCut) return false; // dcaV0daughters - if (casc.dcaV0daughters() > systCuts.dcaV0dau) + if (casc.dcaV0daughters() > cascadeSelections.cascdcaV0dau) return false; // dcav0topv - if (std::abs(casc.dcav0topv(pvx, pvy, pvz)) < systCuts.cascdcaV0ToPV) + if (std::abs(casc.dcav0topv(pvx, pvy, pvz)) < cascadeSelections.cascdcaV0ToPV) return false; // cascradius - if (casc.cascradius() < systCuts.cascRadius) + if (casc.cascradius() < cascadeSelections.cascRadius) return false; // v0radius - if (casc.v0radius() < systCuts.cascv0RadiusMin) + if (casc.v0radius() < cascadeSelections.cascv0RadiusMin) return false; // v0cosPA - if (casc.v0cosPA(casc.x(), casc.y(), casc.z()) < systCuts.cascv0cospa) + if (casc.v0cosPA(casc.x(), casc.y(), casc.z()) < cascadeSelections.cascv0cospa) return false; // lambdaMassWin - if (std::abs(casc.mLambda() - o2::constants::physics::MassLambda0) > systCuts.lambdaMassWin) + if (std::abs(casc.mLambda() - o2::constants::physics::MassLambda0) > cascadeSelections.cascV0masswindow) return false; return true; } @@ -748,9 +757,9 @@ struct HStrangeCorrelation { auto assoc = assocCandidate.v0Core_as(); //---] syst cuts [--- - if ((masterConfigurations.doPPAnalysis && (assoc.v0radius() < systCuts.v0RadiusMin || assoc.v0radius() > systCuts.v0RadiusMax || - std::abs(assoc.dcapostopv()) < systCuts.dcapostopv || std::abs(assoc.dcanegtopv()) < systCuts.dcanegtopv || - assoc.v0cosPA() < systCuts.v0cospa || assoc.dcaV0daughters() > systCuts.dcaV0dau))) + if ((masterConfigurations.doPPAnalysis && (assoc.v0radius() < v0Selection.v0RadiusMin || assoc.v0radius() > v0Selection.v0RadiusMax || + std::abs(assoc.dcapostopv()) < v0Selection.dcapostopv || std::abs(assoc.dcanegtopv()) < v0Selection.dcanegtopv || + assoc.v0cosPA() < v0Selection.v0cospa || assoc.dcaV0daughters() > v0Selection.dcaV0dau))) continue; if (!masterConfigurations.doPPAnalysis && !v0SelectedPbPb(assoc)) @@ -775,7 +784,11 @@ struct HStrangeCorrelation { } //---] track quality check [--- - if (postrack.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRowsAssociated || negtrack.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRowsAssociated) + if (postrack.tpcNClsCrossedRows() < trackSelection.minTPCNCrossedRowsAssociated || negtrack.tpcNClsCrossedRows() < trackSelection.minTPCNCrossedRowsAssociated) + continue; + if (trackSelection.checksRequireTPCChi2 && (postrack.tpcChi2NCl() < trackSelection.minTPCChi2PerClusterAssociated || negtrack.tpcChi2NCl() < trackSelection.minTPCChi2PerClusterAssociated)) + continue; + if (trackSelection.requireClusterInITS && (postrack.itsNCls() < trackSelection.minITSClustersForDaughterTracks || negtrack.itsNCls() < trackSelection.minITSClustersForDaughterTracks)) continue; float deltaphi = computeDeltaPhi(trigg.phi(), assoc.phi()); @@ -809,7 +822,7 @@ struct HStrangeCorrelation { } float etaWeight = 1; - if (systCuts.doOnTheFlyFlattening) { + if (checks.doOnTheFlyFlattening) { float preWeight = 1 - std::abs(deltaeta) / 1.6; etaWeight = preWeight != 0 ? 1.0f / preWeight : 1.0f; } @@ -821,7 +834,7 @@ struct HStrangeCorrelation { double ptProton = postrack.pt(); double ptPion = negtrack.pt(); double signProton = postrack.sign(); - if (assocCandidate.compatible(2, systCuts.dEdxCompatibility)) { + if (assocCandidate.compatible(2, trackSelection.dEdxCompatibility)) { phiProton = negtrack.phi(); etaProton = negtrack.eta(); ptProton = negtrack.pt(); @@ -856,7 +869,7 @@ struct HStrangeCorrelation { } double binFillThn[6] = {deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult}; if (TESTBIT(doCorrelation, Index) && (!efficiencyFlags.applyEfficiencyCorrection || efficiency != 0) && (masterConfigurations.doPPAnalysis || (TESTBIT(selMap, Index) && TESTBIT(selMap, Index + 3)))) { - if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && -massWindowConfigurations.maxBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < -massWindowConfigurations.minBgNSigma) { + if (assocCandidate.compatible(Index, trackSelection.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && -massWindowConfigurations.maxBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < -massWindowConfigurations.minBgNSigma) { fillCorrelationHistogram(histos.get(HIST("sameEvent/LeftBg/") + HIST(V0names[Index])), binFillThn, etaWeight, efficiency * efficiencyTrigg, totalEffUncert, purityTrigg, purityTriggErr); if (doDeltaPhiStarCheck) { double deltaPhiStar = calculateAverageDeltaPhiStar(triggForDeltaPhiStar, assocForDeltaPhiStar, bField); @@ -874,13 +887,13 @@ struct HStrangeCorrelation { } } } - if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && -massWindowConfigurations.maxPeakNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxPeakNSigma) { + if (assocCandidate.compatible(Index, trackSelection.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && -massWindowConfigurations.maxPeakNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxPeakNSigma) { fillCorrelationHistogram(histos.get(HIST("sameEvent/Signal/") + HIST(V0names[Index])), binFillThn, etaWeight, efficiency * efficiencyTrigg, totalEffUncert, purityTrigg, purityTriggErr); - if (std::abs(deltaphi) < systCuts.towardDeltaEtaRange && doITSClustersQA) { + if (std::abs(deltaphi) < checks.towardDeltaEtaRange && doITSClustersQA) { histos.fill(HIST("hITSClusters") + HIST(V0names[Index]) + HIST("NegativeDaughterToward"), ptassoc, negtrack.itsNCls(), assoc.v0radius()); histos.fill(HIST("hITSClusters") + HIST(V0names[Index]) + HIST("PositiveDaughterToward"), ptassoc, postrack.itsNCls(), assoc.v0radius()); } - if (std::abs(deltaphi) > systCuts.transwerseDeltaEtaRangeMin && std::abs(deltaphi) < systCuts.transwerseDeltaEtaRangeMax && doITSClustersQA) { + if (std::abs(deltaphi) > checks.transwerseDeltaEtaRangeMin && std::abs(deltaphi) < checks.transwerseDeltaEtaRangeMax && doITSClustersQA) { histos.fill(HIST("hITSClusters") + HIST(V0names[Index]) + HIST("NegativeDaughterTransverse"), ptassoc, negtrack.itsNCls(), assoc.v0radius()); histos.fill(HIST("hITSClusters") + HIST(V0names[Index]) + HIST("PositiveDaughterTransverse"), ptassoc, postrack.itsNCls(), assoc.v0radius()); } @@ -900,7 +913,7 @@ struct HStrangeCorrelation { } } } - if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && +massWindowConfigurations.minBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxBgNSigma) { + if (assocCandidate.compatible(Index, trackSelection.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && +massWindowConfigurations.minBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxBgNSigma) { fillCorrelationHistogram(histos.get(HIST("sameEvent/RightBg/") + HIST(V0names[Index])), binFillThn, etaWeight, efficiency * efficiencyTrigg, totalEffUncert, purityTrigg, purityTriggErr); if (doDeltaPhiStarCheck) { double deltaPhiStar = calculateAverageDeltaPhiStar(triggForDeltaPhiStar, assocForDeltaPhiStar, bField); @@ -918,21 +931,21 @@ struct HStrangeCorrelation { } } } - if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && -massWindowConfigurations.maxBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < -massWindowConfigurations.minBgNSigma) { + if (assocCandidate.compatible(Index, trackSelection.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && -massWindowConfigurations.maxBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < -massWindowConfigurations.minBgNSigma) { if (mixingInBf) { currentCollision.addValidParticle(assoc.eta(), assoc.phi(), assoc.pt(), 0, efficiency, efficiencyError, Index); } else { fillCorrelationHistogram(histos.get(HIST("mixedEvent/LeftBg/") + HIST(V0names[Index])), binFillThn, 1, efficiency * efficiencyTrigg, totalEffUncert, purityTrigg, purityTriggErr); } } - if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && -massWindowConfigurations.maxPeakNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxPeakNSigma) { + if (assocCandidate.compatible(Index, trackSelection.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && -massWindowConfigurations.maxPeakNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxPeakNSigma) { if (mixingInBf) { currentCollision.addValidParticle(assoc.eta(), assoc.phi(), assoc.pt(), 1, efficiencyTrigg, efficiencyError, Index); } else { fillCorrelationHistogram(histos.get(HIST("mixedEvent/Signal/") + HIST(V0names[Index])), binFillThn, 1, efficiency * efficiencyTrigg, totalEffUncert, purityTrigg, purityTriggErr); } } - if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && +massWindowConfigurations.minBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxBgNSigma) { + if (assocCandidate.compatible(Index, trackSelection.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && +massWindowConfigurations.minBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxBgNSigma) { if (mixingInBf) { currentCollision.addValidParticle(assoc.eta(), assoc.phi(), assoc.pt(), 2, efficiencyTrigg, efficiencyError, Index); } else { @@ -1073,16 +1086,16 @@ struct HStrangeCorrelation { auto assoc = assocCandidate.cascData(); //---] syst cuts [--- - if (masterConfigurations.doPPAnalysis && (std::abs(assoc.dcapostopv()) < systCuts.dcapostopv || - std::abs(assoc.dcanegtopv()) < systCuts.dcanegtopv || - std::abs(assoc.dcabachtopv()) < systCuts.cascDcabachtopv || - assoc.dcaV0daughters() > systCuts.dcaV0dau || - assoc.dcacascdaughters() > systCuts.cascDcacascdau || - assoc.v0cosPA(pvx, pvy, pvz) < systCuts.v0cospa || - assoc.casccosPA(pvx, pvy, pvz) < systCuts.cascCospa || - assoc.cascradius() < systCuts.cascRadius || - std::abs(assoc.dcav0topv(pvx, pvy, pvz)) < systCuts.cascMindcav0topv || - std::abs(assoc.mLambda() - o2::constants::physics::MassLambda0) > systCuts.cascV0masswindow)) + if (masterConfigurations.doPPAnalysis && (std::abs(assoc.dcapostopv()) < v0Selection.dcapostopv || + std::abs(assoc.dcanegtopv()) < v0Selection.dcanegtopv || + std::abs(assoc.dcabachtopv()) < cascadeSelections.dcaBachToPV || + assoc.dcaV0daughters() > cascadeSelections.cascdcaV0dau || + assoc.dcacascdaughters() > cascadeSelections.dcaCascDaughters || + assoc.v0cosPA(pvx, pvy, pvz) < cascadeSelections.cascv0cospa || + assoc.casccosPA(pvx, pvy, pvz) < cascadeSelections.cascCospa || + assoc.cascradius() < cascadeSelections.cascRadius || + std::abs(assoc.dcav0topv(pvx, pvy, pvz)) < cascadeSelections.cascdcaV0ToPV || + std::abs(assoc.mLambda() - o2::constants::physics::MassLambda0) > cascadeSelections.cascV0masswindow)) continue; if (!masterConfigurations.doPPAnalysis && !cascadeSelectedPbPb(assoc, pvx, pvy, pvz)) continue; @@ -1119,7 +1132,11 @@ struct HStrangeCorrelation { } double assocForDeltaPhiStar[] = {phiProton, ptProton, signProton}; //---] track quality check [--- - if (postrack.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRowsAssociated || negtrack.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRowsAssociated || bachtrack.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRowsAssociated) + if (postrack.tpcNClsCrossedRows() < trackSelection.minTPCNCrossedRowsAssociated || negtrack.tpcNClsCrossedRows() < trackSelection.minTPCNCrossedRowsAssociated || bachtrack.tpcNClsCrossedRows() < trackSelection.minTPCNCrossedRowsAssociated) + continue; + if (trackSelection.checksRequireTPCChi2 && (postrack.tpcChi2NCl() < trackSelection.minTPCChi2PerClusterAssociated || negtrack.tpcChi2NCl() < trackSelection.minTPCChi2PerClusterAssociated || bachtrack.tpcChi2NCl() < trackSelection.minTPCChi2PerClusterAssociated)) + continue; + if (trackSelection.requireClusterInITS && (postrack.itsNCls() < trackSelection.minITSClustersForDaughterTracks || negtrack.itsNCls() < trackSelection.minITSClustersForDaughterTracks || bachtrack.itsNCls() < trackSelection.minITSClustersForDaughterTracks)) continue; float deltaphi = computeDeltaPhi(trigg.phi(), assoc.phi()); @@ -1156,7 +1173,7 @@ struct HStrangeCorrelation { hEfficiencyUncertaintyCascade[3] = hEfficiencyUncertaintyOmegaPlus; float etaWeight = 1; - if (systCuts.doOnTheFlyFlattening) { + if (checks.doOnTheFlyFlattening) { float preWeight = 1 - std::abs(deltaeta) / 1.6; etaWeight = preWeight != 0 ? 1.0f / preWeight : 1.0f; } @@ -1187,7 +1204,7 @@ struct HStrangeCorrelation { } double binFillThn[6] = {deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult}; if (TESTBIT(doCorrelation, Index + 3) && (!efficiencyFlags.applyEfficiencyCorrection || efficiency != 0) && (masterConfigurations.doPPAnalysis || (TESTBIT(cascselMap, Index) && TESTBIT(cascselMap, Index + 4) && TESTBIT(cascselMap, Index + 8) && TESTBIT(cascselMap, Index + 12)))) { - if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && -massWindowConfigurations.maxBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < -massWindowConfigurations.minBgNSigma) { + if (assocCandidate.compatible(Index, trackSelection.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && -massWindowConfigurations.maxBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < -massWindowConfigurations.minBgNSigma) { fillCorrelationHistogram(histos.get(HIST("sameEvent/LeftBg/") + HIST(Cascadenames[Index])), binFillThn, etaWeight, efficiency * efficiencyTrigg, totalEffUncert, purityTrigg, purityTriggErr); if (doDeltaPhiStarCheck) { double deltaPhiStar = calculateAverageDeltaPhiStar(triggForDeltaPhiStar, assocForDeltaPhiStar, bField); @@ -1197,7 +1214,7 @@ struct HStrangeCorrelation { histos.fill(HIST("sameEvent/LeftBg/") + HIST(Cascadenames[Index]) + HIST("DeltaPhiStar"), deltaPhiStar, trigg.eta() - etaProton, -0.5); } } - if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && -massWindowConfigurations.maxPeakNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxPeakNSigma) { + if (assocCandidate.compatible(Index, trackSelection.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && -massWindowConfigurations.maxPeakNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxPeakNSigma) { fillCorrelationHistogram(histos.get(HIST("sameEvent/Signal/") + HIST(Cascadenames[Index])), binFillThn, etaWeight, efficiency * efficiencyTrigg, totalEffUncert, purityTrigg, purityTriggErr); if (doDeltaPhiStarCheck) { double deltaPhiStar = calculateAverageDeltaPhiStar(triggForDeltaPhiStar, assocForDeltaPhiStar, bField); @@ -1207,7 +1224,7 @@ struct HStrangeCorrelation { histos.fill(HIST("sameEvent/Signal/") + HIST(Cascadenames[Index]) + HIST("DeltaPhiStar"), deltaPhiStar, trigg.eta() - etaProton, -0.5); } } - if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && +massWindowConfigurations.minBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxBgNSigma) { + if (assocCandidate.compatible(Index, trackSelection.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && +massWindowConfigurations.minBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxBgNSigma) { fillCorrelationHistogram(histos.get(HIST("sameEvent/RightBg/") + HIST(Cascadenames[Index])), binFillThn, etaWeight, efficiency * efficiencyTrigg, totalEffUncert, purityTrigg, purityTriggErr); if (doDeltaPhiStarCheck) { double deltaPhiStar = calculateAverageDeltaPhiStar(triggForDeltaPhiStar, assocForDeltaPhiStar, bField); @@ -1217,21 +1234,21 @@ struct HStrangeCorrelation { histos.fill(HIST("sameEvent/RightBg/") + HIST(Cascadenames[Index]) + HIST("DeltaPhiStar"), deltaPhiStar, trigg.eta() - etaProton, -0.5); } } - if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && -massWindowConfigurations.maxBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < -massWindowConfigurations.minBgNSigma) { + if (assocCandidate.compatible(Index, trackSelection.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && -massWindowConfigurations.maxBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < -massWindowConfigurations.minBgNSigma) { if (mixingInBf) { currentCollision.addValidParticle(assoc.eta(), assoc.phi(), assoc.pt(), 0, efficiency, efficiencyError, Index); } else { fillCorrelationHistogram(histos.get(HIST("mixedEvent/LeftBg/") + HIST(Cascadenames[Index])), binFillThn, 1, efficiency * efficiencyTrigg, totalEffUncert, purityTrigg, purityTriggErr); } } - if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && -massWindowConfigurations.maxPeakNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxPeakNSigma) { + if (assocCandidate.compatible(Index, trackSelection.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && -massWindowConfigurations.maxPeakNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxPeakNSigma) { if (mixingInBf) { currentCollision.addValidParticle(assoc.eta(), assoc.phi(), assoc.pt(), 1, efficiency, efficiencyError, Index); } else { fillCorrelationHistogram(histos.get(HIST("mixedEvent/Signal/") + HIST(Cascadenames[Index])), binFillThn, 1, efficiency * efficiencyTrigg, totalEffUncert, purityTrigg, purityTriggErr); } } - if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && +massWindowConfigurations.minBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxBgNSigma) { + if (assocCandidate.compatible(Index, trackSelection.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && +massWindowConfigurations.minBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxBgNSigma) { if (mixingInBf) { currentCollision.addValidParticle(assoc.eta(), assoc.phi(), assoc.pt(), 2, efficiency, efficiencyError, Index); } else { @@ -1368,7 +1385,7 @@ struct HStrangeCorrelation { double assocForDeltaPhiStar[] = {assoc.phi(), assoc.pt(), assocSign}; float etaWeight = 1.; - if (systCuts.doOnTheFlyFlattening) { + if (checks.doOnTheFlyFlattening) { float preWeight = 1 - std::abs(deltaeta) / 1.6; etaWeight = preWeight != 0 ? 1.0f / preWeight : 1.0f; } @@ -2147,13 +2164,16 @@ struct HStrangeCorrelation { //---] track quality check [--- auto postrack = v0Data.posTrack_as(); auto negtrack = v0Data.negTrack_as(); - if (postrack.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRowsAssociated || negtrack.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRowsAssociated) + if (postrack.tpcNClsCrossedRows() < trackSelection.minTPCNCrossedRowsAssociated || negtrack.tpcNClsCrossedRows() < trackSelection.minTPCNCrossedRowsAssociated) + continue; + if (trackSelection.checksRequireTPCChi2 && (postrack.tpcChi2NCl() < trackSelection.minTPCChi2PerClusterAssociated || negtrack.tpcChi2NCl() < trackSelection.minTPCChi2PerClusterAssociated)) + continue; + if (trackSelection.requireClusterInITS && (postrack.itsNCls() < trackSelection.minITSClustersForDaughterTracks || negtrack.itsNCls() < trackSelection.minITSClustersForDaughterTracks)) continue; - //---] syst cuts [--- - if (masterConfigurations.doPPAnalysis && (v0Data.v0radius() < systCuts.v0RadiusMin || v0Data.v0radius() > systCuts.v0RadiusMax || - std::abs(v0Data.dcapostopv()) < systCuts.dcapostopv || std::abs(v0Data.dcanegtopv()) < systCuts.dcanegtopv || - v0Data.v0cosPA() < systCuts.v0cospa || v0Data.dcaV0daughters() > systCuts.dcaV0dau)) + if (masterConfigurations.doPPAnalysis && (v0Data.v0radius() < v0Selection.v0RadiusMin || v0Data.v0radius() > v0Selection.v0RadiusMax || + std::abs(v0Data.dcapostopv()) < v0Selection.dcapostopv || std::abs(v0Data.dcanegtopv()) < v0Selection.dcanegtopv || + v0Data.v0cosPA() < v0Selection.v0cospa || v0Data.dcaV0daughters() > v0Selection.dcaV0dau)) continue; if (!masterConfigurations.doPPAnalysis && !v0SelectedPbPb(v0Data)) continue; @@ -2176,7 +2196,7 @@ struct HStrangeCorrelation { efficiency = 1; } float weight = efficiencyFlags.applyEfficiencyCorrection ? 1. / efficiency : 1.0f; - if (v0.compatible(Index, systCuts.dEdxCompatibility) && (!masterConfigurations.doMCassociation || v0.mcTrue(Index)) && (!doAssocPhysicalPrimary || v0.mcPhysicalPrimary()) && (!efficiencyFlags.applyEfficiencyCorrection || efficiency != 0)) { + if (v0.compatible(Index, trackSelection.dEdxCompatibility) && (!masterConfigurations.doMCassociation || v0.mcTrue(Index)) && (!doAssocPhysicalPrimary || v0.mcPhysicalPrimary()) && (!efficiencyFlags.applyEfficiencyCorrection || efficiency != 0)) { if ((TESTBIT(doCorrelation, Index)) && (masterConfigurations.doPPAnalysis || (TESTBIT(selMap, Index) && TESTBIT(selMap, Index + 3)))) { histos.fill(HIST("h3d") + HIST(V0names[Index]) + HIST("Spectrum"), v0Data.pt(), cent, v0.invMassNSigma(Index), weight); if (std::abs(v0Data.rapidity(Index)) < ySel) { @@ -2281,16 +2301,16 @@ struct HStrangeCorrelation { auto cascData = casc.cascData(); //---] syst cuts [--- - if (masterConfigurations.doPPAnalysis && (std::abs(cascData.dcapostopv()) < systCuts.dcapostopv || - std::abs(cascData.dcanegtopv()) < systCuts.dcanegtopv || - std::abs(cascData.dcabachtopv()) < systCuts.cascDcabachtopv || - cascData.dcaV0daughters() > systCuts.dcaV0dau || - cascData.dcacascdaughters() > systCuts.cascDcacascdau || - cascData.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) < systCuts.v0cospa || - cascData.casccosPA(collision.posX(), collision.posY(), collision.posZ()) < systCuts.cascCospa || - cascData.cascradius() < systCuts.cascRadius || - std::abs(cascData.dcav0topv(collision.posX(), collision.posY(), collision.posZ())) < systCuts.cascMindcav0topv || - std::abs(cascData.mLambda() - o2::constants::physics::MassLambda0) > systCuts.cascV0masswindow)) + if (masterConfigurations.doPPAnalysis && (std::abs(cascData.dcapostopv()) < v0Selection.dcapostopv || + std::abs(cascData.dcanegtopv()) < v0Selection.dcanegtopv || + std::abs(cascData.dcabachtopv()) < cascadeSelections.dcaBachToPV || + cascData.dcaV0daughters() > cascadeSelections.cascdcaV0dau || + cascData.dcacascdaughters() > cascadeSelections.dcaCascDaughters || + cascData.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) < cascadeSelections.cascv0cospa || + cascData.casccosPA(collision.posX(), collision.posY(), collision.posZ()) < cascadeSelections.cascCospa || + cascData.cascradius() < cascadeSelections.cascRadius || + std::abs(cascData.dcav0topv(collision.posX(), collision.posY(), collision.posZ())) < cascadeSelections.cascdcaV0ToPV || + std::abs(cascData.mLambda() - o2::constants::physics::MassLambda0) > cascadeSelections.cascV0masswindow)) continue; if (!masterConfigurations.doPPAnalysis && !cascadeSelectedPbPb(cascData, collision.posX(), collision.posY(), collision.posZ())) continue; @@ -2299,12 +2319,16 @@ struct HStrangeCorrelation { auto postrack = cascData.posTrack_as(); auto negtrack = cascData.negTrack_as(); auto bachtrack = cascData.bachelor_as(); - if (postrack.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRowsAssociated || negtrack.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRowsAssociated || bachtrack.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRowsAssociated) + if (postrack.tpcNClsCrossedRows() < trackSelection.minTPCNCrossedRowsAssociated || negtrack.tpcNClsCrossedRows() < trackSelection.minTPCNCrossedRowsAssociated || bachtrack.tpcNClsCrossedRows() < trackSelection.minTPCNCrossedRowsAssociated) + continue; + if (trackSelection.checksRequireTPCChi2 && (postrack.tpcChi2NCl() < trackSelection.minTPCChi2PerClusterAssociated || negtrack.tpcChi2NCl() < trackSelection.minTPCChi2PerClusterAssociated || bachtrack.tpcChi2NCl() < trackSelection.minTPCChi2PerClusterAssociated)) + continue; + if (trackSelection.requireClusterInITS && (postrack.itsNCls() < trackSelection.minITSClustersForDaughterTracks || negtrack.itsNCls() < trackSelection.minITSClustersForDaughterTracks)) continue; static_for<0, 3>([&](auto i) { constexpr int Index = i.value; - if ((Index == IndexOmegaMinus || Index == IndexOmegaPlus) && casc.compatible(Index, systCuts.dEdxCompatibility) && std::abs(casc.invMassNSigma(Index - 2)) < massWindowConfigurations.nSigmaNearXiMassCenter) { + if ((Index == IndexOmegaMinus || Index == IndexOmegaPlus) && casc.compatible(Index, trackSelection.dEdxCompatibility) && std::abs(casc.invMassNSigma(Index - 2)) < massWindowConfigurations.nSigmaNearXiMassCenter) { return; } float efficiency = 1.0f; @@ -2320,7 +2344,7 @@ struct HStrangeCorrelation { efficiency = 1; } float weight = efficiencyFlags.applyEfficiencyCorrection ? 1. / efficiency : 1.0f; - if (casc.compatible(Index, systCuts.dEdxCompatibility) && (!masterConfigurations.doMCassociation || casc.mcTrue(Index)) && (!doAssocPhysicalPrimary || casc.mcPhysicalPrimary()) && (!efficiencyFlags.applyEfficiencyCorrection || efficiency != 0)) { + if (casc.compatible(Index, trackSelection.dEdxCompatibility) && (!masterConfigurations.doMCassociation || casc.mcTrue(Index)) && (!doAssocPhysicalPrimary || casc.mcPhysicalPrimary()) && (!efficiencyFlags.applyEfficiencyCorrection || efficiency != 0)) { if (TESTBIT(doCorrelation, Index + 3) && (masterConfigurations.doPPAnalysis || (TESTBIT(cascselMap, Index) && TESTBIT(cascselMap, Index + 4) && TESTBIT(cascselMap, Index + 8) && TESTBIT(cascselMap, Index + 12)))) { histos.fill(HIST("h3d") + HIST(Cascadenames[Index]) + HIST("Spectrum"), cascData.pt(), cent, casc.invMassNSigma(Index), weight); if (std::abs(cascData.rapidity(Index)) < ySel) { @@ -3040,13 +3064,13 @@ struct HStrangeCorrelation { //---] track quality check [--- auto postrack = v0Data.posTrack_as(); auto negtrack = v0Data.negTrack_as(); - if (postrack.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRowsAssociated || negtrack.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRowsAssociated) + if (postrack.tpcNClsCrossedRows() < trackSelection.minTPCNCrossedRowsAssociated || negtrack.tpcNClsCrossedRows() < trackSelection.minTPCNCrossedRowsAssociated) continue; //---] syst cuts [--- - if (v0Data.v0radius() < systCuts.v0RadiusMin || v0Data.v0radius() > systCuts.v0RadiusMax || - std::abs(v0Data.dcapostopv()) < systCuts.dcapostopv || std::abs(v0Data.dcanegtopv()) < systCuts.dcanegtopv || - v0Data.v0cosPA() < systCuts.v0cospa || v0Data.dcaV0daughters() > systCuts.dcaV0dau) + if (v0Data.v0radius() < v0Selection.v0RadiusMin || v0Data.v0radius() > v0Selection.v0RadiusMax || + std::abs(v0Data.dcapostopv()) < v0Selection.dcapostopv || std::abs(v0Data.dcanegtopv()) < v0Selection.dcanegtopv || + v0Data.v0cosPA() < v0Selection.v0cospa || v0Data.dcaV0daughters() > v0Selection.dcaV0dau) continue; if (v0Data.has_mcParticle()) { From 180ecb90ee705c13e6a8a4909106df29b059372d Mon Sep 17 00:00:00 2001 From: Cristian-Moscatelli Date: Mon, 9 Mar 2026 11:15:34 +0100 Subject: [PATCH 223/347] [PWGLF] Change Generated Event selection in NucleiSpectra.cxx (#15158) Co-authored-by: Cristian Moscatelli --- PWGLF/DataModel/LFSlimNucleiTables.h | 35 ++++++++++ PWGLF/TableProducer/Nuspex/nucleiSpectra.cxx | 73 ++++++++++++++++++-- 2 files changed, 104 insertions(+), 4 deletions(-) diff --git a/PWGLF/DataModel/LFSlimNucleiTables.h b/PWGLF/DataModel/LFSlimNucleiTables.h index b35355873f7..84a2da9966f 100644 --- a/PWGLF/DataModel/LFSlimNucleiTables.h +++ b/PWGLF/DataModel/LFSlimNucleiTables.h @@ -55,6 +55,7 @@ DECLARE_SOA_COLUMN(MotherPDGcode, MotherpdgCode, int); DECLARE_SOA_COLUMN(MotherDecRad, motherDecRad, float); DECLARE_SOA_COLUMN(AbsoDecL, absoDecL, float); DECLARE_SOA_COLUMN(McProcess, mcProcess, uint64_t); +DECLARE_SOA_COLUMN(gEventMask, genEventMask, uint8_t); DECLARE_SOA_COLUMN(NsigmaTpc, nsigmaTpc, uint8_t); DECLARE_SOA_COLUMN(NsigmaTof, nsigmaTof, uint8_t); @@ -206,6 +207,40 @@ DECLARE_SOA_TABLE(NucleiTableRed, "AOD", "NUCLEITABLERED", NucleiTableNS::PDGcode, NucleiTableNS::MotherPDGcode); +// Table for keeping track of selection of generated events +DECLARE_SOA_TABLE(GenEventMCSel, "AOD", "GENEVENTMCSEL", + NucleiTableNS::gEventMask); + +DECLARE_SOA_TABLE(NucleiTableMCExtension, "AOD", "NUCTABLEMCSEL", + NucleiTableNS::Pt, + NucleiTableNS::Eta, + NucleiTableNS::Phi, + NucleiTableNS::TPCInnerParam, + NucleiTableNS::Beta, + NucleiTableNS::Zvertex, + NucleiTableNS::NContrib, + NucleiTableNS::DCAxy, + NucleiTableNS::DCAz, + NucleiTableNS::TPCsignal, + NucleiTableNS::ITSchi2, + NucleiTableNS::TPCchi2, + NucleiTableNS::TOFchi2, + NucleiTableNS::Flags, + NucleiTableNS::TPCfindableCls, + NucleiTableNS::TPCcrossedRows, + NucleiTableNS::ITSclsMap, + NucleiTableNS::TPCnCls, + NucleiTableNS::TPCnClsShared, + NucleiTableNS::ITSclusterSizes, + NucleiTableNS::SurvivedEventSelection, + NucleiTableNS::gPt, + NucleiTableNS::gEta, + NucleiTableNS::gPhi, + NucleiTableNS::PDGcode, + NucleiTableNS::MotherPDGcode, + NucleiTableNS::MotherDecRad, + NucleiTableNS::AbsoDecL, + NucleiTableNS::gEventMask); // Extended table with central PID information DECLARE_SOA_TABLE(NucleiTableExt, "AOD", "NUCLEITABLEEXT", NucleiTableNS::NsigmaTpc, diff --git a/PWGLF/TableProducer/Nuspex/nucleiSpectra.cxx b/PWGLF/TableProducer/Nuspex/nucleiSpectra.cxx index 6ba0b483c46..f4422453858 100644 --- a/PWGLF/TableProducer/Nuspex/nucleiSpectra.cxx +++ b/PWGLF/TableProducer/Nuspex/nucleiSpectra.cxx @@ -21,6 +21,7 @@ #include "PWGLF/DataModel/EPCalibrationTables.h" #include "PWGLF/DataModel/LFSlimNucleiTables.h" +#include "PWGLF/Utils/inelGt.h" #include "Common/Core/EventPlaneHelper.h" #include "Common/Core/PID/PIDTOF.h" @@ -52,8 +53,10 @@ #include "ReconstructionDataFormats/Track.h" #include +#include #include #include // for PDG codes +#include #include #include @@ -248,6 +251,13 @@ constexpr int EvSelDefault[9][1]{ {0}, {0}, {0}}; + +enum EvGenSel : uint8_t { + kGenTVX = 1 << 0, + kGenZvtx = 1 << 1, + kGenINELgt0 = 1 << 2, +}; + } // namespace nuclei struct nucleiSpectra { @@ -269,7 +279,9 @@ struct nucleiSpectra { Produces nucleiTable; Produces nucleiPairTable; Produces nucleiTableMC; + Produces nucleiTableMCExtension; Produces nucleiTableFlow; + Produces GenEventMCSel; Service ccdb; Zorro zorro; OutputObj zorroSummary{"zorroSummary"}; @@ -334,6 +346,7 @@ struct nucleiSpectra { ConfigurableAxis cfgNTPCClusBins{"cfgNTPCClusBins", {3, 89.5, 159.5}, "N TPC clusters binning"}; Configurable cfgSkimmedProcessing{"cfgSkimmedProcessing", false, "Skimmed dataset processing"}; + Configurable cfgTriggerList{"cfgTriggerList", "fHe", "Trigger List"}; // running variables for track tuner o2::dataformats::DCA mDcaInfoCov; @@ -453,7 +466,7 @@ struct nucleiSpectra { return; } if (cfgSkimmedProcessing) { - zorro.initCCDB(ccdb.service, bc.runNumber(), bc.timestamp(), "fHe"); + zorro.initCCDB(ccdb.service, bc.runNumber(), bc.timestamp(), cfgTriggerList); zorro.populateHistRegistry(spectra, bc.runNumber()); } auto timestamp = bc.timestamp(); @@ -911,13 +924,64 @@ struct nucleiSpectra { PROCESS_SWITCH(nucleiSpectra, processDataFlowAlternative, "Data analysis with flow - alternative framework", false); Preslice tracksPerCollisions = aod::track::collisionId; + Preslice particlesPerMcCollision = aod::mcparticle::mcCollisionId; void processMC(soa::Join const& collisions, aod::McCollisions const& mcCollisions, soa::Join const& tracks, aod::McParticles const& particlesMC, aod::BCsWithTimestamps const&) { nuclei::candidates.clear(); + + bool selectINELgt0 = cfgEventSelections->get(nuclei::evSel::kINELgt0); + std::vector goodCollisions(mcCollisions.size(), false); + std::vector eventMask(mcCollisions.size(), 0); + + auto* pdgDB = TDatabasePDG::Instance(); // Useful for evaluating the particle charge + for (const auto& c : mcCollisions) { + + uint8_t mask = 0; + + const auto& slicedParticles = particlesMC.sliceBy(particlesPerMcCollision, c.globalIndex()); + + bool hasHitFT0A(false); + bool hasHitFT0C(false); + + // TVX trigger + for (const auto& p : slicedParticles) { + if (!p.isPhysicalPrimary()) + continue; + + auto* pdg = pdgDB->GetParticle(p.pdgCode()); + if (!pdg || pdg->Charge() == 0) + continue; + + // Apply the TVX trigger condition + if (p.eta() > 3.5f && p.eta() < 4.9f) + hasHitFT0A = true; + else if (p.eta() > -3.3f && p.eta() < -2.1f) + hasHitFT0C = true; + + if (hasHitFT0A && hasHitFT0C) + break; + } + + if (hasHitFT0A && hasHitFT0C) + mask |= nuclei::kGenTVX; + + // |z| condition + if (std::abs(c.posZ()) < cfgCutVertex) + mask |= nuclei::kGenZvtx; + + // INEL > 0 selection + if (selectINELgt0) { + if (o2::pwglf::isINELgt0mc(slicedParticles, pdgDB)) { + mask |= nuclei::kGenINELgt0; + } + } + + eventMask[c.globalIndex()] = mask; + GenEventMCSel(mask); spectra.fill(HIST("hGenVtxZ"), c.posZ()); } - std::vector goodCollisions(mcCollisions.size(), false); + for (const auto& collision : collisions) { if (!eventSelectionWithHisto(collision)) { continue; @@ -926,6 +990,7 @@ struct nucleiSpectra { const auto& slicedTracks = tracks.sliceBy(tracksPerCollisions, collision.globalIndex()); fillDataInfo(collision, slicedTracks); } + std::vector isReconstructed(particlesMC.size(), false); for (auto& c : nuclei::candidates) { auto label = tracks.iteratorAt(c.globalIndex); @@ -987,7 +1052,7 @@ struct nucleiSpectra { isReconstructed[particle.globalIndex()] = true; float absoDecL = computeAbsoDecL(particle); - nucleiTableMC(c.pt, c.eta, c.phi, c.tpcInnerParam, c.beta, c.zVertex, c.nContrib, c.DCAxy, c.DCAz, c.TPCsignal, c.ITSchi2, c.TPCchi2, c.TOFchi2, c.flags, c.TPCfindableCls, c.TPCcrossedRows, c.ITSclsMap, c.TPCnCls, c.TPCnClsShared, c.clusterSizesITS, goodCollisions[particle.mcCollisionId()], particle.pt(), particle.eta(), particle.phi(), particle.pdgCode(), motherPdgCode, motherDecRadius, absoDecL); + nucleiTableMCExtension(c.pt, c.eta, c.phi, c.tpcInnerParam, c.beta, c.zVertex, c.nContrib, c.DCAxy, c.DCAz, c.TPCsignal, c.ITSchi2, c.TPCchi2, c.TOFchi2, c.flags, c.TPCfindableCls, c.TPCcrossedRows, c.ITSclsMap, c.TPCnCls, c.TPCnClsShared, c.clusterSizesITS, goodCollisions[particle.mcCollisionId()], particle.pt(), particle.eta(), particle.phi(), particle.pdgCode(), motherPdgCode, motherDecRadius, absoDecL, eventMask[particle.mcCollisionId()]); } int index{0}; @@ -1039,7 +1104,7 @@ struct nucleiSpectra { continue; // skip secondaries from material if not requested } float absDecL = computeAbsoDecL(particle); - nucleiTableMC(999., 999., 999., 0., 0., 999., -1, 999., 999., -1, -1, -1, -1, flags, 0, 0, 0, 0, 0, 0, goodCollisions[particle.mcCollisionId()], particle.pt(), particle.eta(), particle.phi(), particle.pdgCode(), motherPdgCode, motherDecRadius, absDecL); + nucleiTableMCExtension(999., 999., 999., 0., 0., 999., -1, 999., 999., -1, -1, -1, -1, flags, 0, 0, 0, 0, 0, 0, goodCollisions[particle.mcCollisionId()], particle.pt(), particle.eta(), particle.phi(), particle.pdgCode(), motherPdgCode, motherDecRadius, absDecL, eventMask[particle.mcCollisionId()]); } break; } From 70e8cee09e9377ee72348fa2fca1c9bdd39fb410 Mon Sep 17 00:00:00 2001 From: lucamicheletti93 <38209984+lucamicheletti93@users.noreply.github.com> Date: Mon, 9 Mar 2026 12:19:23 +0100 Subject: [PATCH 224/347] [PWGDQ] Fixing issue in the CCDB call in Mu calculation (#15310) Co-authored-by: Lucamicheletti93 --- PWGDQ/TableProducer/tableMaker_withAssoc.cxx | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/PWGDQ/TableProducer/tableMaker_withAssoc.cxx b/PWGDQ/TableProducer/tableMaker_withAssoc.cxx index 235632d9bff..7993444ad80 100644 --- a/PWGDQ/TableProducer/tableMaker_withAssoc.cxx +++ b/PWGDQ/TableProducer/tableMaker_withAssoc.cxx @@ -861,20 +861,15 @@ struct TableMaker { // Function to compute the mu for pileup estimation, taken from EM code double calculateMu(const auto& bc) { - auto& ccdbMgr = o2::ccdb::BasicCCDBManager::instance(); - uint64_t timeStamp = bc.timestamp(); - std::map metadata; - mLHCIFdata = ccdbMgr.getSpecific("GLO/Config/GRPLHCIF", timeStamp, metadata); - auto bfilling = mLHCIFdata->getBunchFilling(); double nbc = bfilling.getFilledBCs().size(); double tvxRate; if (fConfigHistOutput.fConfigIrEstimator.value.empty()) { - tvxRate = mRateFetcher.fetch(&ccdbMgr, timeStamp, bc.runNumber(), "T0VTX"); + tvxRate = mRateFetcher.fetch(fCCDB.service, timeStamp, bc.runNumber(), "T0VTX"); } else { - tvxRate = mRateFetcher.fetch(&ccdbMgr, timeStamp, bc.runNumber(), fConfigHistOutput.fConfigIrEstimator.value); + tvxRate = mRateFetcher.fetch(fCCDB.service, timeStamp, bc.runNumber(), fConfigHistOutput.fConfigIrEstimator.value); } double nTriggersPerFilledBC = tvxRate / nbc / o2::constants::lhc::LHCRevFreq; @@ -1700,6 +1695,9 @@ struct TableMaker { } else { VarManager::SetZShift(fConfigCCDB.fManualZShift.value); } + if (fConfigHistOutput.fConfigFillBcStat) { + mLHCIFdata = fCCDB->getSpecific("GLO/Config/GRPLHCIF", bcs.begin().timestamp()); + } if (fConfigVariousOptions.fPropMuon) { VarManager::SetupMuonMagField(); } From 4c30c374315aeaee6ca9933b1d099939e6cb3241 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Tiek=C3=B6tter?= Date: Mon, 9 Mar 2026 16:16:40 +0100 Subject: [PATCH 225/347] [PWGDQ] Added additional TOF only cut, added alice 3 track histograms. (#15264) --- PWGDQ/Core/CutsLibrary.cxx | 76 +++++++++++++++++++++++++++++++- PWGDQ/Core/HistogramsLibrary.cxx | 47 +++++++++++++++++--- PWGDQ/Core/VarManager.h | 3 ++ 3 files changed, 120 insertions(+), 6 deletions(-) diff --git a/PWGDQ/Core/CutsLibrary.cxx b/PWGDQ/Core/CutsLibrary.cxx index c4fa96705ac..cb9c124d418 100644 --- a/PWGDQ/Core/CutsLibrary.cxx +++ b/PWGDQ/Core/CutsLibrary.cxx @@ -3529,6 +3529,11 @@ AnalysisCompositeCut* o2::aod::dqcuts::GetCompositeCut(const char* cutName) return cut; } + if (!nameStr.compare("pairD0")) { + cut->AddCut(GetAnalysisCut("pairD0")); + return cut; + } + if (!nameStr.compare("pairD0HighPt1")) { cut->AddCut(GetAnalysisCut("pairLxyzProjected3sigma")); cut->AddCut(GetAnalysisCut("pairPtLow5")); @@ -3881,7 +3886,49 @@ AnalysisCompositeCut* o2::aod::dqcuts::GetCompositeCut(const char* cutName) } if (!nameStr.compare("alice3DielectronPID")) { - cut->AddCut(GetAnalysisCut("alice3StandardKine")); + cut->AddCut(GetAnalysisCut("alice3JpsiKine")); + cut->AddCut(GetAnalysisCut("alice3TrackQuality")); + cut->AddCut(GetAnalysisCut("alice3iTOFPIDEl")); + cut->AddCut(GetAnalysisCut("alice3oTOFPIDEl")); + cut->AddCut(GetAnalysisCut("alice3RICHPIDEl")); + return cut; + } + + if (!nameStr.compare("alice3DielectronPIDTOFOnly")) { + cut->AddCut(GetAnalysisCut("alice3JpsiKineTOFAcceptance")); + cut->AddCut(GetAnalysisCut("alice3TrackQuality")); + cut->AddCut(GetAnalysisCut("alice3iTOFPIDEl")); + cut->AddCut(GetAnalysisCut("alice3oTOFPIDEl")); + return cut; + } + + if (!nameStr.compare("alice3DielectronPIDRICHOnly")) { + cut->AddCut(GetAnalysisCut("alice3JpsiKineTOFAcceptance")); + cut->AddCut(GetAnalysisCut("alice3TrackQuality")); + cut->AddCut(GetAnalysisCut("alice3iTOFPIDEl")); + cut->AddCut(GetAnalysisCut("alice3oTOFPIDEl")); + return cut; + } + + if (!nameStr.compare("alice3DielectronPIDTOFOnly")) { + cut->AddCut(GetAnalysisCut("alice3JpsiKine")); + cut->AddCut(GetAnalysisCut("alice3TrackQuality")); + cut->AddCut(GetAnalysisCut("alice3iTOFPIDEl")); + cut->AddCut(GetAnalysisCut("alice3oTOFPIDEl")); + return cut; + } + + if (!nameStr.compare("alice3DielectronPIDTOFAcceptance")) { + cut->AddCut(GetAnalysisCut("alice3JpsiKineTOFAcceptance")); + cut->AddCut(GetAnalysisCut("alice3TrackQuality")); + cut->AddCut(GetAnalysisCut("alice3iTOFPIDEl")); + cut->AddCut(GetAnalysisCut("alice3oTOFPIDEl")); + cut->AddCut(GetAnalysisCut("alice3RICHPIDEl")); + return cut; + } + + if (!nameStr.compare("alice3DielectronPIDRICHAcceptance")) { + cut->AddCut(GetAnalysisCut("alice3JpsiKineRICHAcceptance")); cut->AddCut(GetAnalysisCut("alice3TrackQuality")); cut->AddCut(GetAnalysisCut("alice3iTOFPIDEl")); cut->AddCut(GetAnalysisCut("alice3oTOFPIDEl")); @@ -6732,6 +6779,11 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) return cut; } + if (!nameStr.compare("pairD0")) { + cut->AddCut(VarManager::kMass, 1.814, 1.914); + return cut; + } + if (!nameStr.compare("pairJpsi")) { cut->AddCut(VarManager::kMass, 2.8, 3.3); return cut; @@ -6975,13 +7027,35 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) return cut; } + if (!nameStr.compare("alice3JpsiKine")) { + cut->AddCut(VarManager::kPt, 1.0, 1000.0); + cut->AddCut(VarManager::kEta, -2.5, 2.5); // Total tracker acceptance in v3b geomety + return cut; + } + + if (!nameStr.compare("alice3JpsiKineTOFAcceptance")) { + cut->AddCut(VarManager::kPt, 1.0, 1000.0); + cut->AddCut(VarManager::kEta, -2.0, 2.0); // TOF acceptance in v3b geomety + return cut; + } + + if (!nameStr.compare("alice3JpsiKineRICHAcceptance")) { + cut->AddCut(VarManager::kPt, 1.0, 1000.0); + cut->AddCut(VarManager::kEta, -0.8, 0.8); // RICH acceptance in v3b geomety + return cut; + } + if (!nameStr.compare("alice3TrackQuality")) { + cut->AddCut(VarManager::kIsReconstructed, 0.5, 1.5); + cut->AddCut(VarManager::kNSiliconHits, 6.0, 12.0); cut->AddCut(VarManager::kTrackDCAxy, -3.0, 3.0); cut->AddCut(VarManager::kTrackDCAz, -3.0, 3.0); return cut; } if (!nameStr.compare("alice3TrackQualityTightDCA")) { + cut->AddCut(VarManager::kIsReconstructed, 0.5, 1.5); + cut->AddCut(VarManager::kNSiliconHits, 6.0, 12.0); cut->AddCut(VarManager::kTrackDCAxy, -1.0, 1.0); cut->AddCut(VarManager::kTrackDCAz, -1.0, 1.0); return cut; diff --git a/PWGDQ/Core/HistogramsLibrary.cxx b/PWGDQ/Core/HistogramsLibrary.cxx index d40e5dc9847..faedee1cb14 100644 --- a/PWGDQ/Core/HistogramsLibrary.cxx +++ b/PWGDQ/Core/HistogramsLibrary.cxx @@ -1041,19 +1041,21 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "Rapidity", "", false, 400, -4.0, 4.0, VarManager::kRap); } if (subGroupStr.Contains("alice3tracks")) { - hm->AddHistogram(histClass, "Pt_vs_PtMC", "pT vs MC pT", false, 200, 0.0, 20.0, VarManager::kPt, 200, 0.0, 20.0, VarManager::kMCPt); + hm->AddHistogram(histClass, "IsReconstructed", "IsReconstructed", false, 2, 0.5, 1.5, VarManager::kIsReconstructed); + hm->AddHistogram(histClass, "nSiliconHits", "Num silicon hits", false, 12, 0.0, 12.0, VarManager::kNSiliconHits); + hm->AddHistogram(histClass, "Pt_vs_PtMC", "pT vs MC pT", false, 200, 0.0, 100.0, VarManager::kPt, 200, 0.0, 20.0, VarManager::kMCPt); hm->AddHistogram(histClass, "Eta_vs_EtaMC", "#eta vs MC #eta", false, 150, -4.0, 4.0, VarManager::kEta, 150, -4.0, 4.0, VarManager::kMCEta); hm->AddHistogram(histClass, "Phi_vs_PhiMC", "#varphi vs MC #varphi", false, 50, 0.0, 2. * o2::constants::math::PI, VarManager::kPhi, 50, 0.0, 2. * o2::constants::math::PI, VarManager::kMCPhi); hm->AddHistogram(histClass, "Eta_DCAxy", "#eta vs DCA_{xy}", false, 80, -4.0, 4.0, VarManager::kEta, 400, -2.0, 2.0, VarManager::kTrackDCAxy); hm->AddHistogram(histClass, "Eta_DCAz", "#eta vs DCA_{z}", false, 80, -4.0, 4.0, VarManager::kEta, 800, -4.0, 4.0, VarManager::kTrackDCAz); } if (subGroupStr.Contains("resolutions")) { - hm->AddHistogram(histClass, "PtMC_vs_DeltaPt", "MC pT vs DeltaPt", false, 200, 0.0, 20.0, VarManager::kMCPt, 2000, -1.0, 1.0, VarManager::kDeltaPt); - hm->AddHistogram(histClass, "Pt_vs_DeltaPt", "pT vs pTRes", false, 200, 0.0, 20.0, VarManager::kPt, 2000, -1.0, 1.0, VarManager::kDeltaPt); + hm->AddHistogram(histClass, "PtMC_vs_DeltaPt", "MC pT vs DeltaPt", false, 200, 0.0, 100.0, VarManager::kMCPt, 2000, -1.0, 1.0, VarManager::kDeltaPt); + hm->AddHistogram(histClass, "Pt_vs_DeltaPt", "pT vs pTRes", false, 200, 0.0, 100.0, VarManager::kPt, 2000, -1.0, 1.0, VarManager::kDeltaPt); hm->AddHistogram(histClass, "EtaMC_vs_DeltaPt", "MC Eta vs DeltaPt", false, 200, -6.0, 6.0, VarManager::kMCEta, 2000, -1.0, 1.0, VarManager::kDeltaPt); hm->AddHistogram(histClass, "Eta_vs_DeltaPt", "MC Eta vs DeltaPt", false, 200, -6.0, 6.0, VarManager::kEta, 2000, -1.0, 1.0, VarManager::kDeltaPt); - hm->AddHistogram(histClass, "PtMC_vs_Res", "MC pT vs DeltaPt", false, 200, 0.0, 20.0, VarManager::kMCPt, 2000, -1.0, 1.0, VarManager::kPtResolution); - hm->AddHistogram(histClass, "Pt_vs_Res", "pT vs pTRes", false, 200, 0.0, 20.0, VarManager::kPt, 2000, -1.0, 1.0, VarManager::kPtResolution); + hm->AddHistogram(histClass, "PtMC_vs_Res", "MC pT vs DeltaPt", false, 200, 0.0, 100.0, VarManager::kMCPt, 2000, -1.0, 1.0, VarManager::kPtResolution); + hm->AddHistogram(histClass, "Pt_vs_Res", "pT vs pTRes", false, 200, 0.0, 100.0, VarManager::kPt, 2000, -1.0, 1.0, VarManager::kPtResolution); hm->AddHistogram(histClass, "EtaMC_vs_Res", "MC Eta vs pTRes", false, 200, -6.0, 6.0, VarManager::kMCEta, 2000, -1.0, 1.0, VarManager::kPtResolution); hm->AddHistogram(histClass, "Eta_vs_Res", "MC Eta vs pTRes", false, 200, -6.0, 6.0, VarManager::kEta, 2000, -1.0, 1.0, VarManager::kPtResolution); hm->AddHistogram(histClass, "PtRes", "pT Resolution", false, 2000, -1.0, 1.0, VarManager::kPtResolution); @@ -1207,6 +1209,29 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "Mass_MultFDDA", "Mass vs MultFDDA", false, 200, 2.0, 5.0, VarManager::kMass, 1000, 0, 25000.0, VarManager::kMultFDDA); hm->AddHistogram(histClass, "Mass_MultFDDC", "Mass vs MultFDDC", false, 200, 2.0, 5.0, VarManager::kMass, 1000, 0, 25000.0, VarManager::kMultFDDC); } + if (subGroupStr.Contains("mass_mult_pv")) { + double multAnalysisBins[4] = {0.0, 4.0, 8.0, 1000.0}; + + double multAnalsisMassBins[201] = {0.0}; + for (int i = 0; i <= 200; i++) { + multAnalsisMassBins[i] = 2.0 + i * 0.015; + } + + double multAnalysisPVBins[151] = {0.0}; + for (int i = 0; i <= 150; i++) { + multAnalysisPVBins[i] = i * 1.0; + } + + double multAnalysisFV0ABins[1001] = {0.0}; + for (int i = 0; i <= 1000; i++) { + multAnalysisFV0ABins[i] = i * 1.0; + } + + hm->AddHistogram(histClass, "Mass_VtxNcontribReal_Pt", "Mass vs VtxNcontribReal vs Pt", false, 200, multAnalsisMassBins, VarManager::kMass, 150, multAnalysisPVBins, VarManager::kVtxNcontribReal, 3, multAnalysisBins, VarManager::kPt); + hm->AddHistogram(histClass, "Mass_MultFV0A_Pt", "Mass vs MultFV0A vs Pt", false, 200, multAnalsisMassBins, VarManager::kMass, 1000, multAnalysisFV0ABins, VarManager::kMultFV0A, 3, multAnalysisBins, VarManager::kPt); + hm->AddHistogram(histClass, "Mass_MultFT0A_Pt", "Mass vs MultFT0A vs Pt", false, 200, multAnalsisMassBins, VarManager::kMass, 1000, multAnalysisFV0ABins, VarManager::kMultFT0A, 3, multAnalysisBins, VarManager::kPt); + hm->AddHistogram(histClass, "Mass_MultFT0C_Pt", "Mass vs MultFT0C vs Pt", false, 200, multAnalsisMassBins, VarManager::kMass, 1000, multAnalysisFV0ABins, VarManager::kMultFT0C, 3, multAnalysisBins, VarManager::kPt); + } if (subGroupStr.Contains("barrel")) { hm->AddHistogram(histClass, "Mass", "", false, 500, 0.0, 5.0, VarManager::kMass); hm->AddHistogram(histClass, "Mass_HighRange", "", false, 375, 0.0, 15.0, VarManager::kMass); @@ -1241,6 +1266,18 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "Mass_VtxNcontribReal_VtxZ", "Mass vs VtxNcontribReal vs VtxZ", false, 200, 2.0, 5.0, VarManager::kMass, 150, 0, 150.0, VarManager::kVtxNcontribReal, 20, -10.0, 10.0, VarManager::kVtxZ); hm->AddHistogram(histClass, "VtxZ_VtxNcontribReal", "VtxZ vs VtxNcontribReal", false, 240, -12.0, 12.0, VarManager::kVtxZ, 200, 0, 200.0, VarManager::kVtxNcontribReal); } + if (subGroupStr.Contains("alice3barrel")) { + double pTBins[21] = { + 0.1, 0.5, 1.0, 1.25, 1.5, 2.0, 2.5, 3.0, + 4.0, 5.0, 6.5, 8.0, 10.0, 12.0, 15.0, 20.0, + 30.0, 40.0, 60.0, 80.0, 100.0}; + + double massBins[501]; + for (int i = 0; i < 501; i++) { + massBins[i] = 0.01 * (i); + } + hm->AddHistogram(histClass, "Mass_PtLong", "", false, 500, massBins, VarManager::kMass, 20, pTBins, VarManager::kPt); + } if (subGroupStr.Contains("dielectron-polarization-he-pbpb")) { int varsHEpbpb[5] = {VarManager::kMass, VarManager::kPt, VarManager::kCentFT0C, VarManager::kCosThetaHE, VarManager::kPhiHE}; int binspT[5] = {100, 30, 10, 10, 10}; diff --git a/PWGDQ/Core/VarManager.h b/PWGDQ/Core/VarManager.h index 8731bdc4401..7193b643dd8 100644 --- a/PWGDQ/Core/VarManager.h +++ b/PWGDQ/Core/VarManager.h @@ -70,6 +70,7 @@ #include #include #include +#include #include #include @@ -6618,6 +6619,8 @@ void VarManager::FillTrackAlice3(T const& track, float* values) values[kITSClusterMap] = track.itsClusterMap(); } + values[kIsReconstructed] = track.isReconstructed(); + values[kNSiliconHits] = track.nSiliconHits(); values[kITSchi2] = track.itsChi2NCl(); } From f20085d04d2bf1ec54a7d93378efd20669d4c6a6 Mon Sep 17 00:00:00 2001 From: YazhenLin Date: Tue, 10 Mar 2026 00:53:40 +0800 Subject: [PATCH 226/347] [PWGDQ] Add a new file dqEnergyCorrelator_direct.cxx for the energy correlator analysis (#15253) --- PWGDQ/Core/VarManager.h | 112 +++ PWGDQ/Tasks/CMakeLists.txt | 5 + PWGDQ/Tasks/dqEnergyCorrelator_direct.cxx | 1014 +++++++++++++++++++++ 3 files changed, 1131 insertions(+) create mode 100644 PWGDQ/Tasks/dqEnergyCorrelator_direct.cxx diff --git a/PWGDQ/Core/VarManager.h b/PWGDQ/Core/VarManager.h index 7193b643dd8..487383bfc90 100644 --- a/PWGDQ/Core/VarManager.h +++ b/PWGDQ/Core/VarManager.h @@ -1363,6 +1363,10 @@ class VarManager : public TObject static void FillDileptonTrackVertexing(C const& collision, T1 const& lepton1, T1 const& lepton2, T1 const& track, float* values); template static void FillDileptonHadron(T1 const& dilepton, T2 const& hadron, float* values = nullptr, float hadronMass = 0.0f); + template + static void FillEnergyCorrelatorTriple(T1 const& lepton1, T2 const& lepton2, T3 const& hadron, float* values = nullptr, float Translow = 1. / 3, float Transhigh = 2. / 3, bool applyFitMass = false, float sidebandMass = 0.0f); + template + static void FillEnergyCorrelatorsUnfoldingTriple(T1 const& lepton1, T2 const& lepton2, T3 const& hadron, T4 const& track, T5 const& t1, float* values = nullptr); template static void FillEnergyCorrelator(T1 const& dilepton, T2 const& hadron, float* values = nullptr, float Translow = 1. / 3, float Transhigh = 2. / 3, bool applyFitMass = false, float sidebandMass = 0.0f); template @@ -5873,6 +5877,114 @@ void VarManager::FillEnergyCorrelator(T1 const& dilepton, T2 const& hadron, floa } } } + +template +void VarManager::FillEnergyCorrelatorTriple(T1 const& lepton1, T2 const& lepton2, T3 const& hadron, float* values, float Translow, float Transhigh, bool applyFitMass, float sidebandMass) +{ + float m1 = o2::constants::physics::MassElectron; + float m2 = o2::constants::physics::MassElectron; + + ROOT::Math::PtEtaPhiMVector v_lepton1(lepton1.pt(), lepton1.eta(), lepton1.phi(), m1); + ROOT::Math::PtEtaPhiMVector v_lepton2(lepton2.pt(), lepton2.eta(), lepton2.phi(), m2); + ROOT::Math::PtEtaPhiMVector dilepton = v_lepton1 + v_lepton2; + + float dileptonmass = o2::constants::physics::MassJPsi; + if (applyFitMass) { + dileptonmass = dilepton.mass(); + } + if (applyFitMass && sidebandMass > 0) { + dileptonmass = sidebandMass; + } + + if (fgUsedVars[kCosChi] || fgUsedVars[kECWeight] || fgUsedVars[kCosTheta] || fgUsedVars[kEWeight_before] || fgUsedVars[kPtDau] || fgUsedVars[kEtaDau] || fgUsedVars[kPhiDau] || fgUsedVars[kCosChi_randomPhi_trans] || fgUsedVars[kCosChi_randomPhi_toward] || fgUsedVars[kCosChi_randomPhi_away]) { + values[kdileptonmass] = dileptonmass; + ROOT::Math::PtEtaPhiMVector v1(dilepton.pt(), dilepton.eta(), dilepton.phi(), dileptonmass); + ROOT::Math::PtEtaPhiMVector v2(hadron.pt(), hadron.eta(), hadron.phi(), o2::constants::physics::MassPionCharged); + values[kCosChi] = LorentzTransformJpsihadroncosChi("coschi", v1, v2); + float E_boost = LorentzTransformJpsihadroncosChi("weight_boost", v1, v2); + values[kECWeight] = E_boost / v1.M(); + values[kCosTheta] = LorentzTransformJpsihadroncosChi("costheta", v1, v2); + values[kEWeight_before] = v2.Pt() / v1.M(); + values[kPtDau] = v2.pt(); + values[kEtaDau] = v2.eta(); + values[kPhiDau] = RecoDecay::constrainAngle(v2.phi(), -o2::constants::math::PIHalf); + + float deltaphi = RecoDecay::constrainAngle(v1.phi() - v2.phi(), -o2::constants::math::PI); + values[kDeltaPhi] = RecoDecay::constrainAngle(v1.phi() - v2.phi(), -o2::constants::math::PIHalf); + values[kDeltaEta] = v1.eta() - v2.eta(); + values[kCosChi_randomPhi_trans] = -999.9f; + values[kCosChi_randomPhi_toward] = -999.9f; + values[kCosChi_randomPhi_away] = -999.9f; + + values[kdeltaphi_randomPhi_trans] = -999.9f; + values[kdeltaphi_randomPhi_toward] = -999.9f; + values[kdeltaphi_randomPhi_away] = -999.9f; + + float randomPhi_trans = -o2::constants::math::PIHalf; + float randomPhi_toward = -o2::constants::math::PIHalf; + float randomPhi_away = -o2::constants::math::PIHalf; + + if ((deltaphi > -Transhigh * TMath::Pi() && deltaphi < -Translow * TMath::Pi()) || (deltaphi > Translow * TMath::Pi() && deltaphi < Transhigh * TMath::Pi())) { + randomPhi_trans = gRandom->Uniform(-o2::constants::math::PIHalf, 3. * o2::constants::math::PIHalf); + randomPhi_toward = gRandom->Uniform(-o2::constants::math::PIHalf, 3. * o2::constants::math::PIHalf); + randomPhi_away = gRandom->Uniform(-o2::constants::math::PIHalf, 3. * o2::constants::math::PIHalf); + + ROOT::Math::PtEtaPhiMVector v2_randomPhi_trans(v2.pt(), v2.eta(), randomPhi_trans, o2::constants::physics::MassPionCharged); + values[kCosChi_randomPhi_trans] = LorentzTransformJpsihadroncosChi("coschi", v1, v2_randomPhi_trans); + values[kWeight_randomPhi_trans] = LorentzTransformJpsihadroncosChi("weight_boost", v1, v2_randomPhi_trans) / v1.M(); + + ROOT::Math::PtEtaPhiMVector v2_randomPhi_toward(v2.pt(), v2.eta(), randomPhi_toward, o2::constants::physics::MassPionCharged); + values[kCosChi_randomPhi_toward] = LorentzTransformJpsihadroncosChi("coschi", v1, v2_randomPhi_toward); + values[kWeight_randomPhi_toward] = LorentzTransformJpsihadroncosChi("weight_boost", v1, v2_randomPhi_toward) / v1.M(); + + ROOT::Math::PtEtaPhiMVector v2_randomPhi_away(v2.pt(), v2.eta(), randomPhi_away, o2::constants::physics::MassPionCharged); + values[kCosChi_randomPhi_away] = LorentzTransformJpsihadroncosChi("coschi", v1, v2_randomPhi_away); + values[kWeight_randomPhi_away] = LorentzTransformJpsihadroncosChi("weight_boost", v1, v2_randomPhi_away) / v1.M(); + + values[kdeltaphi_randomPhi_trans] = RecoDecay::constrainAngle(v1.phi() - randomPhi_trans, -o2::constants::math::PIHalf); + values[kdeltaphi_randomPhi_toward] = RecoDecay::constrainAngle(v1.phi() - randomPhi_toward, -o2::constants::math::PIHalf); + values[kdeltaphi_randomPhi_away] = RecoDecay::constrainAngle(v1.phi() - randomPhi_away, -o2::constants::math::PIHalf); + } + } +} + +template +void VarManager::FillEnergyCorrelatorsUnfoldingTriple(T1 const& lepton1, T2 const& lepton2, T3 const& hadron, T4 const& track, T5 const& t1, float* values) +{ + if (fgUsedVars[kMCCosChi_gen] || fgUsedVars[kMCWeight_gen] || fgUsedVars[kMCdeltaeta_gen] || fgUsedVars[kMCCosChi_rec] || fgUsedVars[kMCWeight_rec] || fgUsedVars[kMCdeltaeta_rec]) { + // energy correlators + + float m1 = o2::constants::physics::MassElectron; + float m2 = o2::constants::physics::MassElectron; + + ROOT::Math::PtEtaPhiMVector v_lepton1(lepton1.pt(), lepton1.eta(), lepton1.phi(), m1); + ROOT::Math::PtEtaPhiMVector v_lepton2(lepton2.pt(), lepton2.eta(), lepton2.phi(), m2); + ROOT::Math::PtEtaPhiMVector dilepton = v_lepton1 + v_lepton2; + + float MassHadron; + if constexpr (pairType == kJpsiHadronMass) { + MassHadron = TMath::Sqrt(t1.e() * t1.e() - t1.p() * t1.p()); + } + if constexpr (pairType == kJpsiPionMass) { + MassHadron = o2::constants::physics::MassPionCharged; + } + ROOT::Math::PtEtaPhiMVector v1_gen(track.pt(), track.eta(), track.phi(), o2::constants::physics::MassJPsi); + ROOT::Math::PtEtaPhiMVector v2_gen(t1.pt(), t1.eta(), t1.phi(), MassHadron); + float E_boost_gen = LorentzTransformJpsihadroncosChi("weight_boost", v1_gen, v2_gen); + float CosChi_gen = LorentzTransformJpsihadroncosChi("coschi", v1_gen, v2_gen); + values[kMCCosChi_gen] = CosChi_gen; + values[kMCWeight_gen] = E_boost_gen / o2::constants::physics::MassJPsi; + values[kMCdeltaeta_gen] = track.eta() - t1.eta(); + + ROOT::Math::PtEtaPhiMVector v1_rec(dilepton.pt(), dilepton.eta(), dilepton.phi(), dilepton.mass()); + ROOT::Math::PtEtaPhiMVector v2_rec(hadron.pt(), hadron.eta(), hadron.phi(), o2::constants::physics::MassPionCharged); + values[kMCCosChi_rec] = LorentzTransformJpsihadroncosChi("coschi", v1_rec, v2_rec); + float E_boost_rec = LorentzTransformJpsihadroncosChi("weight_boost", v1_rec, v2_rec); + values[kMCWeight_rec] = E_boost_rec / v1_rec.M(); + values[kMCdeltaeta_rec] = dilepton.eta() - hadron.eta(); + } +} + template void VarManager::FillDileptonPhoton(T1 const& dilepton, T2 const& photon, float* values) { diff --git a/PWGDQ/Tasks/CMakeLists.txt b/PWGDQ/Tasks/CMakeLists.txt index cc660b53202..4bb0cf6d714 100644 --- a/PWGDQ/Tasks/CMakeLists.txt +++ b/PWGDQ/Tasks/CMakeLists.txt @@ -39,6 +39,11 @@ o2physics_add_dpl_workflow(efficiency-with-assoc-direct PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGDQCore O2::ReconstructionDataFormats O2::DetectorsCommonDataFormats O2::DetectorsVertexing COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(energy-correlator-direct + SOURCES dqEnergyCorrelator_direct.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGDQCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(filter-pp SOURCES filterPP.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGDQCore diff --git a/PWGDQ/Tasks/dqEnergyCorrelator_direct.cxx b/PWGDQ/Tasks/dqEnergyCorrelator_direct.cxx new file mode 100644 index 00000000000..4f6ef50524e --- /dev/null +++ b/PWGDQ/Tasks/dqEnergyCorrelator_direct.cxx @@ -0,0 +1,1014 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +// +// Contact: iarsene@cern.ch, i.c.arsene@fys.uio.no +// Configurable workflow for running several DQ or other PWG analyses + +#include "PWGDQ/Core/AnalysisCompositeCut.h" +#include "PWGDQ/Core/AnalysisCut.h" +#include "PWGDQ/Core/CutsLibrary.h" +#include "PWGDQ/Core/HistogramManager.h" +#include "PWGDQ/Core/HistogramsLibrary.h" +#include "PWGDQ/Core/MCSignal.h" +#include "PWGDQ/Core/MCSignalLibrary.h" +#include "PWGDQ/Core/MixingHandler.h" +#include "PWGDQ/Core/MixingLibrary.h" +#include "PWGDQ/Core/VarManager.h" +#include "PWGDQ/DataModel/ReducedInfoTables.h" + +#include "Common/Core/PID/PIDTOFParamService.h" +#include "Common/Core/TableHelper.h" +#include "Common/DataModel/CollisionAssociationTables.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/McCollisionExtra.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DetectorsBase/GeometryManager.h" +#include "DetectorsBase/Propagator.h" +#include "Field/MagneticField.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +#include "TGeoGlobalMagField.h" +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +using std::cout; +using std::endl; +using std::string; + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::aod; + +using MyEvents = soa::Join; +using MyBarrelTracksWithCov = soa::Join; + +// bit maps used for the Fill functions of the VarManager +constexpr static uint32_t gkEventFillMapWithMults = VarManager::ObjTypes::BC | VarManager::ObjTypes::Collision | VarManager::ObjTypes::CollisionMult | VarManager::ObjTypes::CollisionMultExtra; +constexpr static uint32_t gkTrackFillMapWithCov = VarManager::ObjTypes::Track | VarManager::ObjTypes::TrackExtra | VarManager::ObjTypes::TrackDCA | VarManager::ObjTypes::TrackCov | VarManager::ObjTypes::TrackPID; + +// Forward declarations +void DefineHistograms(HistogramManager* histMan, TString histClasses, const char* histGroups); // defines histograms for all tasks + +struct AnalysisEnergyCorrelator { + OutputObj fOutputList{"output"}; + + struct : ConfigurableGroup { // Event selection configurables + Configurable> fConfigZBins{"cfgZBins", std::vector{-10.0, -5.0, 0.0, 5.0, 10.0}, "Z vertex bins for mixing"}; + Configurable> fConfigMultBins{"cfgMultBins", std::vector{0.0, 20.0, 40.0, 60.0, 100.0}, "Multiplicity bins for mixing"}; + Configurable fConfigEventCuts{"cfgEventCuts", "eventStandard", "Event selection"}; + Configurable fConfigEventCutsJSON{"cfgEventCutsJSON", "", "Additional event cuts in JSON"}; + Configurable fConfigAddEventHistogram{"cfgAddEventHistogram", "", "Event histograms"}; + Configurable fConfigAddEventMCHistogram{"cfgAddEventMCHistogram", "generator", "MC Event histograms"}; + Configurable fConfigMixingDepth{"cfgMixingDepth", 5, "Event mixing pool depth"}; + Configurable fConfigEventfilterVtz{"cfgEventfilterVtz", 10.0, "Event filter Vtz"}; + Configurable fConfigEventQA{"cfgEventQA", false, "If true, fill Event QA histograms"}; + } fConfigEventOptions; + + struct : ConfigurableGroup { // Track selection configurables + Configurable fConfigTrackCuts{"cfgTrackCuts", "electronSelection1_ionut", "Comma separated list of barrel track cuts for electrons"}; + Configurable fConfigTrackCutsJSON{"cfgTrackCutsJSON", "", "Additional track cuts in JSON"}; + Configurable fConfigAddTrackHistogram{"cfgAddTrackHistogram", "", "Track histograms"}; + Configurable fConfigTrackQA{"cfgTrackQA", false, "If true, fill Track QA histograms"}; + } fConfigTrackOptions; + + struct : ConfigurableGroup { // Pair selection configurables + Configurable fConfigJpsiMassMin{"cfgJpsiMassMin", 2.8, "J/psi mass minimum"}; + Configurable fConfigJpsiMassMax{"cfgJpsiMassMax", 3.3, "J/psi mass maximum"}; + Configurable fConfigJpsiPtMin{"cfgJpsiPtMin", 0.0, "J/psi pt minimum"}; + Configurable fConfigJpsiPtMax{"cfgJpsiPtMax", 100.0, "J/psi pt maximum"}; + Configurable fConfigJpsiRapMax{"cfgJpsiRapMax", 0.9, "J/psi rapidity maximum"}; + Configurable fConfigAddSEPHistogram{"cfgAddSEPHistogram", "", "Comma separated list of histograms"}; + Configurable recSignals{"cfgMCRecSignals", "eeFromJpsi", "Comma separated list of MC signals (reconstructed)"}; + Configurable recSignalsJSON{"cfgMCRecSignalsJSON", "", "Comma separated list of MC signals (reconstructed) via JSON"}; + } fConfigPairOptions; + + struct : ConfigurableGroup { // Dilepton selection configurables + Configurable fConfigHadronCuts{"cfgHadronCuts", "NoPID", "Comma separated list of hadron track cuts"}; + Configurable fConfigHadronCutsJSON{"cfgHadronCutsJSON", "", "Additional hadron cuts in JSON"}; + Configurable fConfigApplyMassEC{"cfgApplyMassEC", false, "Apply fit mass for sideband for the energy correlator study"}; + Configurable> fConfigSavelessevents{"cfgSavelessevents", std::vector{1, 0}, "Save less events for the energy correlator study"}; + Configurable> fConfigTransRange{"cfgTransRange", std::vector{0.333333, 0.666667}, "Transverse region for the energy correlstor analysis"}; + Configurable fConfigAddDileptonHadronHistogram{"cfgAddDileptonHadronHistogram", "", "Dilepton-hadron histograms"}; + Configurable fConfigMCRecSignals{"cfgMCRecDileptonHadronSignals", "", "Comma separated list of MC signals (reconstructed)"}; + Configurable fConfigMCGenSignals{"cfgMCGenDileptonHadronSignals", "", "Comma separated list of MC signals (generated)"}; + Configurable fConfigMCRecSignalsJSON{"cfgMCRecDileptonHadronSignalsJSON", "", "Additional list of MC signals (reconstructed) via JSON"}; + Configurable fConfigMCGenSignalsJSON{"cfgMCGenDileptonHadronSignalsJSON", "", "Comma separated list of MC signals (generated) via JSON"}; + Configurable fConfigMCGenHadronEtaAbs{"cfgMCGenHadronEtaAbs", 0.9f, "eta abs range for the hadron"}; + Configurable fConfigMCGenHadronPtMin{"cfgMCGenHadronPtMin", 0.1f, "minimum pt for the hadron"}; + } fConfigDileptonHadronOptions; + + // Histogram configurables + Configurable fConfigAddJSONHistograms{"cfgAddJSONHistograms", "", "Histograms in JSON"}; + + // CCDB configurables + Configurable fConfigCcdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "CCDB url"}; + Configurable fConfigNoLaterThan{"ccdb-no-later-than", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "CCDB timestamp"}; + + // Member variables + HistogramManager* fHistMan = nullptr; + MixingHandler* fMixHandler = nullptr; + + AnalysisCompositeCut* fEventCut = nullptr; + std::vector fTrackCuts; // Electron cuts + std::vector fHadronCuts; // Hadron cuts + + std::vector fTrackCutNames; + std::vector fHadronCutNames; + std::vector fHistNamesReco; + + std::map> fTrackHistNames; + std::map> fBarrelHistNamesMCmatched; + std::map fSelMap; + + std::vector fRecMCSignals; // MC signals for reconstructed pairs + std::vector fGenMCSignals; + std::vector fRecMCTripleSignals; // MC signals for reconstructed triples + + Service fCCDB; + int fCurrentRun = -1; + + // Preslice for association table + Preslice preslice = aod::track_association::collisionId; + + using MixingBinning = ColumnBinningPolicy; + std::unique_ptr fMixingBinning; + + void init(o2::framework::InitContext& context) + { + std::vector zBins = fConfigEventOptions.fConfigZBins.value; + zBins.insert(zBins.begin(), VARIABLE_WIDTH); + + std::vector multBins = fConfigEventOptions.fConfigMultBins.value; + multBins.insert(multBins.begin(), VARIABLE_WIDTH); + + fMixingBinning = std::make_unique(std::array, 2>{zBins, multBins}, true); + + bool isBarrelME = context.mOptions.get("processBarrelMixedEvent"); + bool isMCGen_energycorrelators = context.mOptions.get("processMCGenEnergyCorrelators") || context.mOptions.get("processMCGenEnergyCorrelatorsPion"); + bool isMCGen_energycorrelatorsME = context.mOptions.get("processMCGenEnergyCorrelatorsME") || context.mOptions.get("processMCGenEnergyCorrelatorsPionME"); + + if (context.mOptions.get("processDummy")) { + return; + } + VarManager::SetDefaultVarNames(); + + // Setup Event Cuts + fEventCut = new AnalysisCompositeCut(true); + TString eventCutStr = fConfigEventOptions.fConfigEventCuts.value; + if (eventCutStr != "") { + AnalysisCut* cut = dqcuts::GetAnalysisCut(eventCutStr.Data()); + if (cut != nullptr) { + fEventCut->AddCut(cut); + } + } + // Additional cuts via JSON + TString eventCutJSONStr = fConfigEventOptions.fConfigEventCutsJSON.value; + if (eventCutJSONStr != "") { + std::vector jsonCuts = dqcuts::GetCutsFromJSON(eventCutJSONStr.Data()); + for (auto& cutIt : jsonCuts) { + fEventCut->AddCut(cutIt); + } + } + + // Setup Electron Track Cuts + TString trackCutStr = fConfigTrackOptions.fConfigTrackCuts.value; + if (!trackCutStr.IsNull()) { + std::unique_ptr objArrayTrack(trackCutStr.Tokenize(",")); + for (int icut = 0; icut < objArrayTrack->GetEntries(); ++icut) { + fTrackCuts.push_back(dqcuts::GetCompositeCut(objArrayTrack->At(icut)->GetName())); + fTrackCutNames.push_back(objArrayTrack->At(icut)->GetName()); + } + } + + TString trackCutsJSON = fConfigTrackOptions.fConfigTrackCutsJSON.value; + if (trackCutsJSON != "") { + std::vector addTrackCuts = dqcuts::GetCutsFromJSON(trackCutsJSON.Data()); + for (auto& t : addTrackCuts) { + fTrackCuts.push_back(reinterpret_cast(t)); + fTrackCutNames.push_back(t->GetName()); + } + } + + // Setting the MC rec signal names + TString sigNamesStr = fConfigPairOptions.recSignals.value; + std::unique_ptr objRecSigArray(sigNamesStr.Tokenize(",")); + for (int isig = 0; isig < objRecSigArray->GetEntries(); ++isig) { + MCSignal* sig = o2::aod::dqmcsignals::GetMCSignal(objRecSigArray->At(isig)->GetName()); + if (sig) { + if (sig->GetNProngs() != 2) { // NOTE: 2-prong signals required + continue; + } + fRecMCSignals.push_back(sig); + } + } + + TString sigNamesHadronStr = fConfigDileptonHadronOptions.fConfigMCRecSignals.value; + std::unique_ptr objRecSigTripleArray(sigNamesHadronStr.Tokenize(",")); + if (!sigNamesHadronStr.IsNull()) { + for (int isig = 0; isig < objRecSigTripleArray->GetEntries(); ++isig) { + MCSignal* sig = o2::aod::dqmcsignals::GetMCSignal(objRecSigTripleArray->At(isig)->GetName()); + if (sig) { + if (sig->GetNProngs() != 3) { + LOG(fatal) << "Signal at reconstructed level requested (" << sig->GetName() << ") " << "does not have 3 prongs! Fix it"; + } + fRecMCTripleSignals.push_back(sig); + } else { + LOG(fatal) << "Signal at reconstructed level requested (" << objRecSigTripleArray->At(isig)->GetName() << ") " << "could not be retrieved from the library! -> skipped"; + } + } + } + + // Add the MCSignals from the JSON config + TString addMCSignalsStr = fConfigPairOptions.recSignalsJSON.value; + if (addMCSignalsStr != "") { + std::vector addMCSignals = dqmcsignals::GetMCSignalsFromJSON(addMCSignalsStr.Data()); + for (auto& mcIt : addMCSignals) { + if (mcIt->GetNProngs() != 2) { // NOTE: only 2 prong signals + continue; + } + fRecMCSignals.push_back(mcIt); + } + } + + // Add the reco MCSignals from the JSON config + TString addMCTripleSignalsStr = fConfigDileptonHadronOptions.fConfigMCRecSignalsJSON.value; + if (addMCTripleSignalsStr != "") { + std::vector addMCTripleSignals = dqmcsignals::GetMCSignalsFromJSON(addMCTripleSignalsStr.Data()); + for (auto& mcIt : addMCTripleSignals) { + if (mcIt->GetNProngs() != 3) { + LOG(fatal) << "Signal at reconstructed level requested (" << mcIt->GetName() << ") " << "does not have 3 prongs! Fix it"; + } + fRecMCTripleSignals.push_back(mcIt); + } + } + + // Setup Hadron Cuts + TString hadronCutStr = fConfigDileptonHadronOptions.fConfigHadronCuts.value; + if (!hadronCutStr.IsNull()) { + std::unique_ptr objArrayHadron(hadronCutStr.Tokenize(",")); + for (int icut = 0; icut < objArrayHadron->GetEntries(); ++icut) { + TString cutName = objArrayHadron->At(icut)->GetName(); + fHadronCuts.push_back(dqcuts::GetCompositeCut(cutName.Data())); + fHadronCutNames.push_back(cutName); + } + } + TString hadronCutsJSON = fConfigDileptonHadronOptions.fConfigHadronCutsJSON.value; + if (hadronCutsJSON != "") { + std::vector addHadronCuts = dqcuts::GetCutsFromJSON(hadronCutsJSON.Data()); + for (auto& t : addHadronCuts) { + fHadronCuts.push_back(reinterpret_cast(t)); + fHadronCutNames.push_back(t->GetName()); + } + } + + // Add histogram classes for each specified MCsignal at the generator level + // TODO: create a std::vector of hist classes to be used at Fill time, to avoid using Form in the process function + TString sigGenNamesStr = fConfigDileptonHadronOptions.fConfigMCGenSignals.value; + std::unique_ptr objGenSigArray(sigGenNamesStr.Tokenize(",")); + for (int isig = 0; isig < objGenSigArray->GetEntries(); isig++) { + MCSignal* sig = o2::aod::dqmcsignals::GetMCSignal(objGenSigArray->At(isig)->GetName()); + if (sig) { + fGenMCSignals.push_back(sig); + } + } + + // Add the MCSignals from the JSON config + TString addMCSignalsGenStr = fConfigDileptonHadronOptions.fConfigMCGenSignalsJSON.value; + if (addMCSignalsGenStr != "") { + std::vector addMCSignals = dqmcsignals::GetMCSignalsFromJSON(addMCSignalsGenStr.Data()); + for (auto& mcIt : addMCSignals) { + if (mcIt->GetNProngs() > 2) { // NOTE: only 2 prong signals + continue; + } + fGenMCSignals.push_back(mcIt); + } + } + + VarManager::SetUseVars(AnalysisCut::fgUsedVars); + + fHistMan = new HistogramManager("analysisHistos", "", VarManager::kNVars); + fHistMan->SetUseDefaultVariableNames(true); + fHistMan->SetDefaultVarNames(VarManager::fgVariableNames, VarManager::fgVariableUnits); + + // Setup Histograms + if (fConfigEventOptions.fConfigEventQA) { + DefineHistograms(fHistMan, "TimeFrameStats;Event_BeforeCuts;Event_AfterCuts;", fConfigEventOptions.fConfigAddEventHistogram.value.data()); + DefineHistograms(fHistMan, "EventsMC", fConfigEventOptions.fConfigAddEventMCHistogram.value.data()); // mc + } + + if (fConfigTrackOptions.fConfigTrackQA) { + TString histClasses = "AssocsBarrel_BeforeCuts;"; + // Configure histogram classes for each track cut; + // Add histogram classes for each track cut and for each requested MC signal (reconstructed tracks with MC truth) + for (auto& cut : fTrackCuts) { + TString nameStr = Form("AssocsBarrel_%s", cut->GetName()); + fHistNamesReco.push_back(nameStr); + histClasses += Form("%s;", nameStr.Data()); + } + DefineHistograms(fHistMan, histClasses.Data(), fConfigTrackOptions.fConfigAddTrackHistogram.value.data()); + } + TString histNames = ""; + // check that the barrel track cuts array required in this task is not empty + if (!trackCutStr.IsNull()) { + // tokenize and loop over the barrel cuts produced by the barrel track selection task + std::unique_ptr objArray(trackCutStr.Tokenize(",")); + for (int icut = 0; icut < objArray->GetEntries(); ++icut) { + TString tempStr = objArray->At(icut)->GetName(); + // if the current barrel selection cut is required in this task, then switch on the corresponding bit in the mask + // and assign histogram directories + + // assign the pair hist directories for the current cut + std::vector names = { + Form("PairsBarrelSEPM_%s", objArray->At(icut)->GetName()), + Form("PairsBarrelSEPP_%s", objArray->At(icut)->GetName()), + Form("PairsBarrelSEMM_%s", objArray->At(icut)->GetName())}; + for (auto& n : names) { + histNames += Form("%s;", n.Data()); + } + fTrackHistNames[icut] = names; + // assign hist directories for the MC matched pairs for each (track cut,MCsignal) combination + if (!sigNamesStr.IsNull()) { + for (size_t isig = 0; isig < fRecMCSignals.size(); isig++) { + auto sig = fRecMCSignals.at(isig); + names = { + Form("PairsBarrelSEPM_%s_%s", objArray->At(icut)->GetName(), sig->GetName()), + Form("PairsBarrelSEPP_%s_%s", objArray->At(icut)->GetName(), sig->GetName()), + Form("PairsBarrelSEMM_%s_%s", objArray->At(icut)->GetName(), sig->GetName())}; + for (auto& n : names) { + histNames += Form("%s;", n.Data()); + } + fBarrelHistNamesMCmatched.try_emplace(icut * fRecMCSignals.size() + isig, names); + } // end loop over MC signals + } + } + DefineHistograms(fHistMan, histNames.Data(), fConfigPairOptions.fConfigAddSEPHistogram.value.data()); + } + + for (size_t iCutTrack = 0; iCutTrack < fTrackCutNames.size(); iCutTrack++) { + for (size_t iCutHadron = 0; iCutHadron < fHadronCutNames.size(); iCutHadron++) { + DefineHistograms(fHistMan, Form("DileptonTrack_%s_%s", fTrackCutNames[iCutTrack].Data(), fHadronCutNames[iCutHadron].Data()), fConfigDileptonHadronOptions.fConfigAddDileptonHadronHistogram.value.data()); + for (auto& sig : fRecMCTripleSignals) { + DefineHistograms(fHistMan, Form("DileptonTrackMCMatched_%s_%s_%s", fTrackCutNames[iCutTrack].Data(), fHadronCutNames[iCutHadron].Data(), sig->GetName()), fConfigDileptonHadronOptions.fConfigAddDileptonHadronHistogram.value.data()); + if (isBarrelME) { + DefineHistograms(fHistMan, Form("DileptonTrackMCMatchedME_%s_%s_%s", fTrackCutNames[iCutTrack].Data(), fHadronCutNames[iCutHadron].Data(), sig->GetName()), fConfigDileptonHadronOptions.fConfigAddDileptonHadronHistogram.value.data()); + } + } + } + } + + for (auto& sig : fGenMCSignals) { + if (sig->GetNProngs() == 1) { + if (isMCGen_energycorrelators) { + DefineHistograms(fHistMan, Form("MCTruthGenSel_%s", sig->GetName()), ""); + DefineHistograms(fHistMan, Form("MCTruthEenergyCorrelators_%s", sig->GetName()), ""); + } + if (isMCGen_energycorrelatorsME) { + DefineHistograms(fHistMan, Form("MCTruthEenergyCorrelatorsME_%s", sig->GetName()), ""); + } + } + } + + dqhistograms::AddHistogramsFromJSON(fHistMan, fConfigAddJSONHistograms.value.c_str()); // aditional histograms via JSON + + VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill + fOutputList.setObject(fHistMan->GetMainHistogramList()); + + fCCDB->setURL(fConfigCcdbUrl.value); + fCCDB->setCaching(true); + fCCDB->setLocalObjectValidityChecking(); + fCCDB->setCreatedNotAfter(fConfigNoLaterThan.value); + } + + template + void runDileptonHadron(TTrack1 const& track1, TTrack2 const& track2, int iEleCut, + THadron const& hadron, TEvent const& event, aod::McParticles const& /*mcParticles*/) + { + VarManager::ResetValues(0, VarManager::kNVars); // reset variables before filling + VarManager::FillEvent(event); + VarManager::FillTrack(hadron); + VarManager::FillTrackCollision(hadron, event); + + // Check that hadron is not one of the dilepton legs + if (hadron.globalIndex() == track1.globalIndex() || hadron.globalIndex() == track2.globalIndex()) { + return; + } + + if (!track1.has_mcParticle() || !track2.has_mcParticle() || !hadron.has_mcParticle()) { + return; + } + auto hadronMC = hadron.mcParticle(); + auto lepton1MC = track1.mcParticle(); + auto lepton2MC = track2.mcParticle(); + uint32_t mcDecision = 0; + int isig = 0; + for (auto sig = fRecMCTripleSignals.begin(); sig != fRecMCTripleSignals.end(); sig++, isig++) { + if ((*sig)->CheckSignal(true, lepton1MC, lepton2MC, hadronMC)) { + mcDecision |= (static_cast(1) << isig); + } + } + + auto motherParticle = lepton1MC.template mothers_first_as(); + // Fill dilepton-hadron variables + std::vector fTransRange = fConfigDileptonHadronOptions.fConfigTransRange; + VarManager::FillEnergyCorrelatorTriple(track1, track2, hadron, VarManager::fgValues, fTransRange[0], fTransRange[1], fConfigDileptonHadronOptions.fConfigApplyMassEC.value); + VarManager::FillEnergyCorrelatorsUnfoldingTriple(track1, track2, hadron, motherParticle, hadronMC, VarManager::fgValues); + + int iHadronCut = 0; + for (auto hCut = fHadronCuts.begin(); hCut != fHadronCuts.end(); hCut++, iHadronCut++) { + if (!(*hCut)->IsSelected(VarManager::fgValues)) { + continue; + } + // Fill the corresponding histogram + if (!MixedEvent) { + fHistMan->FillHistClass( + Form("DileptonTrack_%s_%s", fTrackCutNames[iEleCut].Data(), fHadronCutNames[iHadronCut].Data()), + VarManager::fgValues); + } + for (uint32_t isig = 0; isig < fRecMCTripleSignals.size(); isig++) { + if (mcDecision & (static_cast(1) << isig)) { + if (!MixedEvent) { + fHistMan->FillHistClass(Form("DileptonTrackMCMatched_%s_%s_%s", fTrackCutNames[iEleCut].Data(), fHadronCutNames[iHadronCut].Data(), fRecMCTripleSignals[isig]->GetName()), VarManager::fgValues); + } + if (MixedEvent) { + fHistMan->FillHistClass(Form("DileptonTrackMCMatchedME_%s_%s_%s", fTrackCutNames[iEleCut].Data(), fHadronCutNames[iHadronCut].Data(), fRecMCTripleSignals[isig]->GetName()), VarManager::fgValues); + } + } // end loop over MC signals + } + } + } + + // Template function to run same event pairing (barrel-barrel, muon-muon, barrel-muon) + template + void runSameEventPairing(TTrack1 const& t1, TTrack2 const& t2, int iEleCut, aod::McParticles const& /*mcParticles*/) + { + std::map> histNames = fTrackHistNames; + std::map> histNamesMC = fBarrelHistNamesMCmatched; + int sign1 = t1.sign(); + int sign2 = t2.sign(); + uint32_t mcDecision = static_cast(0); + // run MC matching for this pair + int isig = 0; + mcDecision = 0; + for (auto sig = fRecMCSignals.begin(); sig != fRecMCSignals.end(); sig++, isig++) { + if (t1.has_mcParticle() && t2.has_mcParticle()) { + if ((*sig)->CheckSignal(true, t1.mcParticle(), t2.mcParticle())) { + mcDecision |= (static_cast(1) << isig); + } + } + } // end loop over MC signals + + VarManager::FillPair(t1, t2); + + if (sign1 * sign2 < 0) { // +- pairs + fHistMan->FillHistClass(histNames[iEleCut][0].Data(), VarManager::fgValues); // reconstructed, unmatched + for (size_t isig = 0; isig < fRecMCSignals.size(); isig++) { // loop over MC signals + if (mcDecision & (static_cast(1) << isig)) { + fHistMan->FillHistClass(histNamesMC[iEleCut * fRecMCSignals.size() + isig][0].Data(), VarManager::fgValues); // matched signal + } + } + } else { + if (sign1 > 0) { // ++ pairs + fHistMan->FillHistClass(histNames[iEleCut][1].Data(), VarManager::fgValues); + for (size_t isig = 0; isig < fRecMCSignals.size(); isig++) { // loop over MC signals + if (mcDecision & (static_cast(1) << isig)) { + fHistMan->FillHistClass(histNamesMC[iEleCut * fRecMCSignals.size() + isig][1].Data(), VarManager::fgValues); + } + } + } else { // -- pairs + fHistMan->FillHistClass(histNames[iEleCut][2].Data(), VarManager::fgValues); + for (unsigned int isig = 0; isig < fRecMCSignals.size(); isig++) { // loop over MC signals + if (mcDecision & (static_cast(1) << isig)) { + fHistMan->FillHistClass(histNamesMC[iEleCut * fRecMCSignals.size() + isig][2].Data(), VarManager::fgValues); + } + } + } + } + } + + void processBarrel(MyEvents const& events, aod::TrackAssoc const& assocs, MyBarrelTracksWithCov const& /*tracks*/, soa::Join const& mcEvents, aod::McParticles const& mcParticles, BCsWithTimestamps const& bcs) + { + VarManager::ResetValues(0, VarManager::kNVars); + VarManager::FillTimeFrame(bcs); + VarManager::FillTimeFrame(events); + VarManager::FillTimeFrame(mcEvents); + + if (events.size() == 0) + return; + + // CCDB initialization + if (fCurrentRun != bcs.begin().runNumber()) { + fCurrentRun = bcs.begin().runNumber(); + } + + if (fConfigEventOptions.fConfigEventQA) { + fHistMan->FillHistClass("TimeFrameStats", VarManager::fgValues); + } + + for (auto& event : mcEvents) { + // Reset the fValues array and fill event observables + VarManager::FillEvent(event); + if (fConfigEventOptions.fConfigEventQA) { + fHistMan->FillHistClass("EventsMC", VarManager::fgValues); + } + } + + // Event loop + for (auto& event : events) { + // Fill event variables first + VarManager::ResetValues(0, VarManager::kNEventWiseVariables); + VarManager::FillEvent(event); + + if (fConfigEventOptions.fConfigEventQA) { + fHistMan->FillHistClass("Event_BeforeCuts", VarManager::fgValues); + } + + // Event selection + if (!fEventCut->IsSelected(VarManager::fgValues)) + continue; + + if (fConfigEventOptions.fConfigEventQA) { + fHistMan->FillHistClass("Event_AfterCuts", VarManager::fgValues); + } + + // saveless events for the energy correlator analysis + std::vector fSavelessevents = fConfigDileptonHadronOptions.fConfigSavelessevents.value; + if (fSavelessevents[0] > 1 && event.globalIndex() % fSavelessevents[0] == fSavelessevents[1]) { + continue; + } + + // Get associated tracks for this event + auto groupedAssocs = assocs.sliceBy(preslice, event.globalIndex()); + + // Triple loop: track1 (electron) x track2 (electron) x hadron + for (auto& a1 : groupedAssocs) { + auto t1 = a1.template track_as(); + + uint32_t filter1 = 0; + // Fill track variables + VarManager::FillTrack(t1); + VarManager::FillTrackCollision(t1, event); + if (t1.has_mcParticle()) { + VarManager::FillTrackMC(mcParticles, t1.mcParticle()); + } + + if (fConfigTrackOptions.fConfigTrackQA) { + fHistMan->FillHistClass("AssocsBarrel_BeforeCuts", VarManager::fgValues); + } + + // Apply electron cuts and fill histograms + int iCut1 = 0; + for (auto cut1 = fTrackCuts.begin(); cut1 != fTrackCuts.end(); cut1++, iCut1++) { + if ((*cut1)->IsSelected(VarManager::fgValues)) { + filter1 |= (static_cast(1) << iCut1); + if (fConfigTrackOptions.fConfigTrackQA) { + fHistMan->FillHistClass(fHistNamesReco[iCut1], VarManager::fgValues); + } + } + } + + // Check opposite charge with t2 + for (auto& a2 : groupedAssocs) { + auto t2 = a2.template track_as(); + + // Avoid double counting: use track globalIndex + if (t2.globalIndex() <= t1.globalIndex()) { + continue; + } + + // Fill track variables for t2 (only once per t2) + VarManager::FillTrack(t2); + VarManager::FillTrackCollision(t2, event); + + // Compute filter2: which cuts t2 passes + uint32_t filter2 = 0; + int iCut2 = 0; + for (auto cut2 = fTrackCuts.begin(); cut2 != fTrackCuts.end(); cut2++, iCut2++) { + if ((*cut2)->IsSelected(VarManager::fgValues)) { + filter2 |= (static_cast(1) << iCut2); + } + } + + // Both tracks must pass at least one common cut + uint32_t twoTrackFilter = filter1 & filter2; + if (!twoTrackFilter) { + continue; + } + + // Fill pair histograms for all cuts that both tracks pass + for (size_t iCut = 0; iCut < fTrackCuts.size(); iCut++) { + if (twoTrackFilter & (static_cast(1) << iCut)) { + runSameEventPairing(t1, t2, iCut, mcParticles); + } + } + + float mass = VarManager::fgValues[VarManager::kMass]; + float pt = VarManager::fgValues[VarManager::kPt]; + float rap = VarManager::fgValues[VarManager::kRap]; + + // Apply J/psi cuts + if (mass < fConfigPairOptions.fConfigJpsiMassMin.value || mass > fConfigPairOptions.fConfigJpsiMassMax.value || + pt < fConfigPairOptions.fConfigJpsiPtMin.value || pt > fConfigPairOptions.fConfigJpsiPtMax.value || + std::abs(rap) > fConfigPairOptions.fConfigJpsiRapMax.value) { + continue; + } + + if (t1.sign() * t2.sign() >= 0) { + continue; // Must be opposite charge + } + + // correlate J/psi with hadrons + for (auto& aHadron : groupedAssocs) { + auto hadron = aHadron.template track_as(); + // Process dilepton-hadron correlation for each common cut + for (size_t iCut = 0; iCut < fTrackCuts.size(); iCut++) { + if (twoTrackFilter & (static_cast(1) << iCut)) { + runDileptonHadron(t1, t2, iCut, hadron, event, mcParticles); + } + } + } // end hadron loop + } // end track2 loop + } // end track1 loop + } // end event loop + } + + Filter eventFilter = nabs(aod::collision::posZ) < fConfigEventOptions.fConfigEventfilterVtz && aod::evsel::sel8 == true; + void processBarrelMixedEvent(soa::Filtered& events, aod::TrackAssoc const& assocs, MyBarrelTracksWithCov const& /*tracks*/, aod::McCollisions const& /*mcCollisions*/, aod::McParticles const& mcParticles, BCsWithTimestamps const& bcs) + { + if (events.size() == 0) { + return; + } + + // CCDB initialization + if (fCurrentRun != bcs.begin().runNumber()) { + fCurrentRun = bcs.begin().runNumber(); + } + + fSelMap.clear(); + // Event loop + for (auto& event : events) { + VarManager::ResetValues(0, VarManager::kNVars); + VarManager::FillEvent(event); + if (event.has_mcCollision()) { + VarManager::FillEvent(event.mcCollision()); + } + bool decision = false; + if (fEventCut->IsSelected(VarManager::fgValues)) { + decision = true; + } + fSelMap[event.globalIndex()] = decision; + } + + for (auto& [event1, event2] : selfCombinations(*fMixingBinning, fConfigEventOptions.fConfigMixingDepth.value, -1, events, events)) { + VarManager::ResetValues(0, VarManager::kNVars); + if (!fSelMap[event1.globalIndex()] || !fSelMap[event2.globalIndex()]) { + continue; + } + + // save less events if configured + std::vector fSavelessevents = fConfigDileptonHadronOptions.fConfigSavelessevents.value; + if (fSavelessevents[0] > 1 && event1.globalIndex() % fSavelessevents[0] == fSavelessevents[1]) { + continue; + } + + // Get associated tracks for this event + auto groupedAssocs1 = assocs.sliceBy(preslice, event1.globalIndex()); + if (groupedAssocs1.size() < 2) { + continue; // Need at least 2 tracks for pairing + } + auto groupedAssocs2 = assocs.sliceBy(preslice, event2.globalIndex()); + + // Triple loop: track1 (electron) x track2 (electron) x hadron + for (auto& a1 : groupedAssocs1) { + auto t1 = a1.template track_as(); + + uint32_t filter1 = 0; + // Fill track variables + VarManager::FillTrack(t1); + VarManager::FillTrackCollision(t1, event1); + + // Apply electron cuts and fill histograms + int iCut1 = 0; + for (auto cut1 = fTrackCuts.begin(); cut1 != fTrackCuts.end(); cut1++, iCut1++) { + if ((*cut1)->IsSelected(VarManager::fgValues)) { + filter1 |= (static_cast(1) << iCut1); + } + } + + // Check opposite charge with t2 + for (auto& a2 : groupedAssocs1) { + auto t2 = a2.template track_as(); + + // Avoid double counting: use track globalIndex + if (t2.globalIndex() <= t1.globalIndex()) + continue; + + // Fill track variables for t2 (only once per t2) + VarManager::FillTrack(t2); + VarManager::FillTrackCollision(t2, event1); + + // Compute filter2: which cuts t2 passes + uint32_t filter2 = 0; + int iCut2 = 0; + for (auto cut2 = fTrackCuts.begin(); cut2 != fTrackCuts.end(); cut2++, iCut2++) { + if ((*cut2)->IsSelected(VarManager::fgValues)) { + filter2 |= (static_cast(1) << iCut2); + } + } + + // Both tracks must pass at least one common cut + uint32_t twoTrackFilter = filter1 & filter2; + if (!twoTrackFilter) { + continue; + } + // Fill pair variables for cut + VarManager::FillPair(t1, t2, VarManager::fgValues); + float mass = VarManager::fgValues[VarManager::kMass]; + float pt = VarManager::fgValues[VarManager::kPt]; + float rap = VarManager::fgValues[VarManager::kRap]; + // Apply J/psi cuts + if (mass < fConfigPairOptions.fConfigJpsiMassMin.value || mass > fConfigPairOptions.fConfigJpsiMassMax.value || + pt < fConfigPairOptions.fConfigJpsiPtMin.value || pt > fConfigPairOptions.fConfigJpsiPtMax.value || + std::abs(rap) > fConfigPairOptions.fConfigJpsiRapMax.value) { + continue; + } + if (t1.sign() * t2.sign() >= 0) { + continue; // Must be opposite charge + } + // correlate J/psi with hadrons from different events + for (auto& aHadron : groupedAssocs2) { + auto hadron = aHadron.template track_as(); + // Process dilepton-hadron correlation for each common cut + for (size_t iCut = 0; iCut < fTrackCuts.size(); iCut++) { + if (twoTrackFilter & (static_cast(1) << iCut)) { + runDileptonHadron(t1, t2, iCut, hadron, event2, mcParticles); + } + } + } // end hadron loop + } // end track2 loop + } // end track1 loop + } // end event loop + } + + PresliceUnsorted perReducedMcEvent = aod::mcparticle::mcCollisionId; + template + void runEnergyCorrelators(TEvent const& event1, TEvent const& event2, McParticles const& mcTracks) + { + auto groupedMCTracks1 = mcTracks.sliceBy(perReducedMcEvent, event1.mcCollisionId()); + auto groupedMCTracks2 = mcTracks.sliceBy(perReducedMcEvent, event2.mcCollisionId()); + groupedMCTracks1.bindInternalIndicesTo(&mcTracks); + groupedMCTracks2.bindInternalIndicesTo(&mcTracks); + for (auto& t1 : groupedMCTracks1) { + auto t1_raw = groupedMCTracks1.rawIteratorAt(t1.globalIndex()); + for (auto& sig : fGenMCSignals) { + if (sig->CheckSignal(true, t1_raw)) { + if (t1.mcCollisionId() != event1.mcCollisionId()) { // check that the mc track belongs to the same mc collision as the reconstructed event + continue; + } + VarManager::FillTrackMC(groupedMCTracks1, t1_raw); + if (!MixedEvent) { + fHistMan->FillHistClass(Form("MCTruthGenSel_%s", sig->GetName()), VarManager::fgValues); + } + } + } + // apply kinematic cuts for signal + if ((t1_raw.pt() < fConfigPairOptions.fConfigJpsiPtMin || t1_raw.pt() > fConfigPairOptions.fConfigJpsiPtMax)) + continue; + if (std::abs(t1_raw.y()) > fConfigPairOptions.fConfigJpsiRapMax) + continue; + // for the energy correlators + for (auto& t2 : groupedMCTracks2) { + auto t2_raw = groupedMCTracks2.rawIteratorAt(t2.globalIndex()); + if (t2.mcCollisionId() != event2.mcCollisionId()) { // check that the mc track belongs to the same mc collision as the reconstructed event + continue; + } + if (!t2_raw.isPhysicalPrimary()) { + continue; + } + if (t2_raw.has_mothers()) { + auto mother_raw = t2_raw.template mothers_first_as(); + if (mother_raw.globalIndex() == t1_raw.globalIndex()) { + continue; + } + } + if (t2_raw.pt() < fConfigDileptonHadronOptions.fConfigMCGenHadronPtMin.value || std::abs(t2_raw.eta()) > fConfigDileptonHadronOptions.fConfigMCGenHadronEtaAbs.value) { + continue; + } + std::vector fTransRange = fConfigDileptonHadronOptions.fConfigTransRange; + VarManager::FillEnergyCorrelatorsMC(t1_raw, t2_raw, VarManager::fgValues, fTransRange[0], fTransRange[1]); + for (auto& sig : fGenMCSignals) { + if (sig->CheckSignal(true, t1_raw)) { + if (!MixedEvent) { + fHistMan->FillHistClass(Form("MCTruthEenergyCorrelators_%s", sig->GetName()), VarManager::fgValues); + } + if (MixedEvent) { + fHistMan->FillHistClass(Form("MCTruthEenergyCorrelatorsME_%s", sig->GetName()), VarManager::fgValues); + } + } + } + } + } + } + + void processMCGenEnergyCorrelators(soa::Filtered& events, + McCollisions const& /*mcEvents*/, McParticles const& mcTracks) + { + if (events.size() == 0) { + LOG(warning) << "No events in this TF, going to the next one ..."; + return; + } + for (auto& event : events) { + // Fill event variables first + VarManager::ResetValues(0, VarManager::kNVars); + VarManager::FillEvent(event); + if (!fEventCut->IsSelected(VarManager::fgValues)) { + continue; + } + if (!event.has_mcCollision()) { + continue; + } + // saveless events for the energy correlator analysis + std::vector fSavelessevents = fConfigDileptonHadronOptions.fConfigSavelessevents.value; + if (fSavelessevents[0] > 1 && event.globalIndex() % fSavelessevents[0] == fSavelessevents[1]) { + continue; + } + runEnergyCorrelators(event, event, mcTracks); + } + } + + void processMCGenEnergyCorrelatorsME(soa::Filtered& events, + McCollisions const& /*mcEvents*/, McParticles const& mcTracks) + { + if (events.size() == 0) { + LOG(warning) << "No events in this TF, going to the next one ..."; + return; + } + // loop over two event comibnations + for (auto& [event1, event2] : selfCombinations(*fMixingBinning, fConfigEventOptions.fConfigMixingDepth.value, -1, events, events)) { + LOG(info) << "check1"; + VarManager::ResetValues(0, VarManager::kNVars); + VarManager::FillEvent(event1); + if (!fEventCut->IsSelected(VarManager::fgValues)) { + continue; + } + VarManager::FillEvent(event2); + if (!fEventCut->IsSelected(VarManager::fgValues)) { + continue; + } + if (!event1.has_mcCollision() || !event2.has_mcCollision()) { + continue; + } + // saveless events for the energy correlator analysis + std::vector fSavelessevents = fConfigDileptonHadronOptions.fConfigSavelessevents.value; + if (fSavelessevents[0] > 1 && event1.globalIndex() % fSavelessevents[0] == fSavelessevents[1]) { + continue; + } + runEnergyCorrelators(event1, event2, mcTracks); + } + } + + void processMCGenEnergyCorrelatorsPion(soa::Filtered& events, + McCollisions const& /*mcEvents*/, McParticles const& mcTracks) + { + if (events.size() == 0) { + LOG(warning) << "No events in this TF, going to the next one ..."; + return; + } + for (auto& event : events) { + // Fill event variables first + VarManager::ResetValues(0, VarManager::kNVars); + VarManager::FillEvent(event); + if (!fEventCut->IsSelected(VarManager::fgValues)) { + continue; + } + if (!event.has_mcCollision()) { + continue; + } + // saveless events for the energy correlator analysis + std::vector fSavelessevents = fConfigDileptonHadronOptions.fConfigSavelessevents.value; + if (fSavelessevents[0] > 1 && event.globalIndex() % fSavelessevents[0] == fSavelessevents[1]) { + continue; + } + runEnergyCorrelators(event, event, mcTracks); + } + } + + void processMCGenEnergyCorrelatorsPionME(soa::Filtered& events, + McCollisions const& /*mcEvents*/, McParticles const& mcTracks) + { + if (events.size() == 0) { + LOG(warning) << "No events in this TF, going to the next one ..."; + return; + } + // loop over two event comibnations + for (auto& [event1, event2] : selfCombinations(*fMixingBinning, fConfigEventOptions.fConfigMixingDepth.value, -1, events, events)) { + VarManager::ResetValues(0, VarManager::kNVars); + VarManager::FillEvent(event1); + if (!fEventCut->IsSelected(VarManager::fgValues)) { + continue; + } + VarManager::FillEvent(event2); + if (!fEventCut->IsSelected(VarManager::fgValues)) { + continue; + } + if (!event1.has_mcCollision() || !event2.has_mcCollision()) { + continue; + } + // saveless events for the energy correlator analysis + std::vector fSavelessevents = fConfigDileptonHadronOptions.fConfigSavelessevents.value; + if (fSavelessevents[0] > 1 && event1.globalIndex() % fSavelessevents[0] == fSavelessevents[1]) { + continue; + } + runEnergyCorrelators(event1, event2, mcTracks); + } + } + + void processDummy(aod::Collisions const&) + { + // Do nothing + } + + PROCESS_SWITCH(AnalysisEnergyCorrelator, processBarrel, "Process barrel analysis", false); + PROCESS_SWITCH(AnalysisEnergyCorrelator, processBarrelMixedEvent, "Run barrel dilepton-hadron mixed event pairing", false); + PROCESS_SWITCH(AnalysisEnergyCorrelator, processMCGenEnergyCorrelators, "Loop over MC particle stack and fill generator level histograms(energy correlators)", false); + PROCESS_SWITCH(AnalysisEnergyCorrelator, processMCGenEnergyCorrelatorsPion, "Loop over MC particle stack and fill generator level histograms(energy correlators)", false); + PROCESS_SWITCH(AnalysisEnergyCorrelator, processMCGenEnergyCorrelatorsME, "Loop over MC particle stack and fill generator level histograms(energy correlators)", false); + PROCESS_SWITCH(AnalysisEnergyCorrelator, processMCGenEnergyCorrelatorsPionME, "Loop over MC particle stack and fill generator level histograms(energy correlators)", false); + PROCESS_SWITCH(AnalysisEnergyCorrelator, processDummy, "Dummy process function", true); +}; + +// Histogram definitions +void DefineHistograms(HistogramManager* histMan, TString histClasses, const char* histGroups) +{ + std::unique_ptr objArray(histClasses.Tokenize(";")); + for (Int_t iclass = 0; iclass < objArray->GetEntries(); ++iclass) { + TString classStr = objArray->At(iclass)->GetName(); + histMan->AddHistClass(classStr.Data()); + TString histName = histGroups; + // NOTE: The level of detail for histogramming can be controlled via configurables + if (classStr.Contains("TimeFrameStats")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "timeframe"); + } + if (classStr.Contains("Event")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "event", histName); + } + if ((classStr.Contains("Track") || classStr.Contains("Assoc")) && !classStr.Contains("Pairs")) { + if (classStr.Contains("Barrel")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "track", histName); + } + } + if (classStr.Contains("Pairs")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "pair", histName); + } + if (classStr.Contains("DileptonTrack")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "dilepton-track", histName); + } + if (classStr.Contains("MCTruthEenergyCorrelators")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "energy-correlator-gen"); + } + if (classStr.Contains("MCTruthGenSel")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "mctruth_track"); + } + } // end loop over histogram classes +} + +// Workflow definition +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} From d38eec6a70190b01305214fdb70d2f2dca940316 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Mon, 9 Mar 2026 21:53:50 +0100 Subject: [PATCH 227/347] [PWGEM/Dilepton] implement dimuon prefilter (#15316) Co-authored-by: ALICE Action Bot --- PWGEM/Dilepton/Core/DielectronCut.cxx | 5 + PWGEM/Dilepton/Core/DielectronCut.h | 9 + PWGEM/Dilepton/Core/Dilepton.h | 53 +- PWGEM/Dilepton/Core/DileptonHadronMPC.h | 16 +- PWGEM/Dilepton/Core/DileptonMC.h | 49 +- PWGEM/Dilepton/Core/DileptonProducer.h | 7 + PWGEM/Dilepton/Core/DimuonCut.cxx | 5 + PWGEM/Dilepton/Core/DimuonCut.h | 9 + PWGEM/Dilepton/Core/SingleTrackQC.h | 24 +- PWGEM/Dilepton/Core/SingleTrackQCMC.h | 22 +- PWGEM/Dilepton/DataModel/dileptonTables.h | 7 +- PWGEM/Dilepton/TableProducer/CMakeLists.txt | 4 + .../TableProducer/prefilterDimuon.cxx | 465 ++++++++++++++++++ PWGEM/Dilepton/Tasks/checkMCPairTemplate.cxx | 7 + PWGEM/Dilepton/Tasks/prefilterDielectron.cxx | 7 +- PWGEM/Dilepton/Utils/EMTrackUtilities.h | 19 +- 16 files changed, 657 insertions(+), 51 deletions(-) create mode 100644 PWGEM/Dilepton/TableProducer/prefilterDimuon.cxx diff --git a/PWGEM/Dilepton/Core/DielectronCut.cxx b/PWGEM/Dilepton/Core/DielectronCut.cxx index b5ecd733985..85172723058 100644 --- a/PWGEM/Dilepton/Core/DielectronCut.cxx +++ b/PWGEM/Dilepton/Core/DielectronCut.cxx @@ -356,3 +356,8 @@ void DielectronCut::IncludeITSsa(bool flag, float max) mMaxPtITSsa = max; LOG(info) << "Dielectron Cut, include ITSsa tracks: " << mIncludeITSsa << ", mMaxPtITSsa = " << mMaxPtITSsa; } +void DielectronCut::EnableTTCA(bool flag) +{ + mEnableTTCA = flag; + LOG(info) << "Dielectron Cut, enable TTCA: " << mEnableTTCA; +} diff --git a/PWGEM/Dilepton/Core/DielectronCut.h b/PWGEM/Dilepton/Core/DielectronCut.h index 916cb5898ad..c7f57bce7ca 100644 --- a/PWGEM/Dilepton/Core/DielectronCut.h +++ b/PWGEM/Dilepton/Core/DielectronCut.h @@ -67,6 +67,7 @@ class DielectronCut : public TNamed kITSNCls, kITSChi2NDF, kITSClusterSize, + kTTCA, kPrefilter, kNCuts }; @@ -210,6 +211,9 @@ class DielectronCut : public TNamed if (!IsSelectedTrack(track, DielectronCuts::kITSClusterSize)) { return false; } + if (!IsSelectedTrack(track, DielectronCuts::kTTCA)) { + return false; + } if (mRequireITSibAny) { auto hits_ib = std::count_if(its_ib_any_Requirement.second.begin(), its_ib_any_Requirement.second.end(), [&](auto&& requiredLayer) { return track.itsClusterMap() & (1 << requiredLayer); }); @@ -470,6 +474,9 @@ class DielectronCut : public TNamed case DielectronCuts::kITSClusterSize: return mMinMeanClusterSizeITS < track.meanClusterSizeITS() * std::cos(std::atan(track.tgl())) && track.meanClusterSizeITS() * std::cos(std::atan(track.tgl())) < mMaxMeanClusterSizeITS; + case DielectronCuts::kTTCA: + return mEnableTTCA ? true : track.isAssociatedToMPC(); + case DielectronCuts::kPrefilter: return track.pfb() <= 0; @@ -538,6 +545,7 @@ class DielectronCut : public TNamed void ApplyPrefilter(bool flag); void ApplyPhiV(bool flag); void IncludeITSsa(bool flag, float maxpt); + void EnableTTCA(bool flag); void SetPIDMlResponse(o2::analysis::MlResponseDielectronSingleTrack* mlResponse) { @@ -628,6 +636,7 @@ class DielectronCut : public TNamed float mMinTOFNsigmaPi{-1e+10}, mMaxTOFNsigmaPi{+1e+10}; float mMinTOFNsigmaKa{-1e+10}, mMaxTOFNsigmaKa{+1e+10}; float mMinTOFNsigmaPr{-1e+10}, mMaxTOFNsigmaPr{+1e+10}; + bool mEnableTTCA{true}; // float mMinITSNsigmaEl{-1e+10}, mMaxITSNsigmaEl{+1e+10}; // float mMinITSNsigmaMu{-1e+10}, mMaxITSNsigmaMu{+1e+10}; diff --git a/PWGEM/Dilepton/Core/Dilepton.h b/PWGEM/Dilepton/Core/Dilepton.h index c4fc90372b1..f8182eea7af 100644 --- a/PWGEM/Dilepton/Core/Dilepton.h +++ b/PWGEM/Dilepton/Core/Dilepton.h @@ -78,7 +78,7 @@ using MyElectron = MyElectrons::iterator; using FilteredMyElectrons = soa::Filtered; using FilteredMyElectron = FilteredMyElectrons::iterator; -using MyMuons = soa::Join; +using MyMuons = soa::Join; using MyMuon = MyMuons::iterator; using FilteredMyMuons = soa::Filtered; using FilteredMyMuon = FilteredMyMuons::iterator; @@ -191,7 +191,7 @@ struct Dilepton { Configurable cfg_apply_cuts_from_prefilter{"cfg_apply_cuts_from_prefilter", false, "flag to apply prefilter set when producing derived data"}; Configurable cfg_prefilter_bits{"cfg_prefilter_bits", 0, "prefilter bits [kNone : 0, kElFromPC : 1, kElFromPi0_20MeV : 2, kElFromPi0_40MeV : 4, kElFromPi0_60MeV : 8, kElFromPi0_80MeV : 16, kElFromPi0_100MeV : 32, kElFromPi0_120MeV : 64, kElFromPi0_140MeV : 128] Please consider logical-OR among them."}; // see PairUtilities.h - Configurable cfg_apply_cuts_from_prefilter_derived{"cfg_apply_cuts_from_prefilter_derived", false, "flag to apply pair cut same as prefilter set in derived data"}; + Configurable cfg_apply_cuts_from_prefilter_derived{"cfg_apply_cuts_from_prefilter_derived", false, "flag to apply prefilter set in derived data"}; Configurable cfg_prefilter_bits_derived{"cfg_prefilter_bits_derived", 0, "prefilter bits [kNone : 0, kMee : 1, kPhiV : 2, kSplitOrMergedTrackLS : 4, kSplitOrMergedTrackULS : 8] Please consider logical-OR among them."}; // see PairUtilities.h Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.2, "min pT for single track"}; @@ -265,6 +265,9 @@ struct Dilepton { Configurable cfg_min_deta{"cfg_min_deta", 0.02, "min deta between 2 muons (elliptic cut)"}; Configurable cfg_min_dphi{"cfg_min_dphi", 0.02, "min dphi between 2 muons (elliptic cut)"}; + Configurable cfg_apply_cuts_from_prefilter_derived{"cfg_apply_cuts_from_prefilter_derived", false, "flag to apply prefilter set in derived data"}; + Configurable cfg_prefilter_bits_derived{"cfg_prefilter_bits_derived", 0, "prefilter bits [kNone : 0, kSplitOrMergedTrackLS : 4, kSplitOrMergedTrackULS : 8] Please consider logical-OR among them."}; // see PairUtilities.h + Configurable cfg_track_type{"cfg_track_type", 3, "muon track type [0: MFT-MCH-MID, 3: MCH-MID]"}; Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.2, "min pT for single track"}; Configurable cfg_max_pt_track{"cfg_max_pt_track", 1e+10, "max pT for single track"}; @@ -731,6 +734,7 @@ struct Dilepton { fDielectronCut.RequireITSib1st(dielectroncuts.cfg_require_itsib_1st); fDielectronCut.SetChi2TOF(0, dielectroncuts.cfg_max_chi2tof); // fDielectronCut.SetRelDiffPin(dielectroncuts.cfg_min_rel_diff_pin, dielectroncuts.cfg_max_rel_diff_pin); + fDielectronCut.EnableTTCA(dielectroncuts.enableTTCA); // for eID fDielectronCut.SetPIDScheme(dielectroncuts.cfg_pid_scheme); @@ -810,6 +814,7 @@ struct Dilepton { fDimuonCut.SetMaxPDCARabsDep([&](float rabs) { return (rabs < 26.5 ? 594.f : 324.f); }); fDimuonCut.SetMaxdPtdEtadPhiwrtMCHMID(dimuoncuts.cfg_max_relDPt_wrt_matchedMCHMID, dimuoncuts.cfg_max_DEta_wrt_matchedMCHMID, dimuoncuts.cfg_max_DPhi_wrt_matchedMCHMID); // this is relevant for global muons fDimuonCut.SetMFTHitMap(dimuoncuts.requireMFTHitMap, dimuoncuts.requiredMFTDisks); + fDimuonCut.EnableTTCA(dimuoncuts.enableTTCA); } template @@ -851,7 +856,7 @@ struct Dilepton { } template - bool fillPairInfo(TCollision const& collision, TTrack1 const& t1, TTrack2 const& t2, TCut const& cut, TAllTracks const& tracks) + bool fillPairInfo(TCollision const& collision, TTrack1 const& t1, TTrack2 const& t2, TCut const& cut, TAllTracks const&) { if constexpr (ev_id == 0) { if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { @@ -868,13 +873,16 @@ struct Dilepton { if (!cut.template IsSelectedTrack(t1) || !cut.template IsSelectedTrack(t2)) { return false; } - - if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t1, cut, tracks)) { - return false; - } - if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t2, cut, tracks)) { + if (!map_best_match_globalmuon[t1.globalIndex()] || !map_best_match_globalmuon[t2.globalIndex()]) { return false; } + + // if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t1, cut, tracks)) { + // return false; + // } + // if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t2, cut, tracks)) { + // return false; + // } } } @@ -1146,7 +1154,7 @@ struct Dilepton { Preslice perCollision_electron = aod::emprimaryelectron::emeventId; Filter trackFilter_electron = dielectroncuts.cfg_min_pt_track < o2::aod::track::pt && dielectroncuts.cfg_min_eta_track < o2::aod::track::eta && o2::aod::track::eta < dielectroncuts.cfg_max_eta_track && nabs(o2::aod::track::dcaXY) < dielectroncuts.cfg_max_dcaxy && nabs(o2::aod::track::dcaZ) < dielectroncuts.cfg_max_dcaz && o2::aod::track::itsChi2NCl < dielectroncuts.cfg_max_chi2its && o2::aod::track::tpcChi2NCl < dielectroncuts.cfg_max_chi2tpc; Filter pidFilter_electron = dielectroncuts.cfg_min_TPCNsigmaEl < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < dielectroncuts.cfg_max_TPCNsigmaEl; - Filter ttcaFilter_electron = ifnode(dielectroncuts.enableTTCA.node(), o2::aod::emprimaryelectron::isAssociatedToMPC == true || o2::aod::emprimaryelectron::isAssociatedToMPC == false, o2::aod::emprimaryelectron::isAssociatedToMPC == true); + Filter ttcaFilter_electron = ifnode(dielectroncuts.enableTTCA.node(), true, o2::aod::emprimaryelectron::isAssociatedToMPC == true); Filter prefilter_derived_electron = ifnode(dielectroncuts.cfg_apply_cuts_from_prefilter_derived.node() && dielectroncuts.cfg_prefilter_bits_derived.node() >= static_cast(1), ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kMee))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kMee))) <= static_cast(0), true) && ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kPhiV))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kPhiV))) <= static_cast(0), true) && @@ -1170,7 +1178,12 @@ struct Dilepton { Preslice perCollision_muon = aod::emprimarymuon::emeventId; Filter trackFilter_muon = o2::aod::fwdtrack::trackType == dimuoncuts.cfg_track_type && dimuoncuts.cfg_min_pt_track < o2::aod::fwdtrack::pt && o2::aod::fwdtrack::pt < dimuoncuts.cfg_max_pt_track && dimuoncuts.cfg_min_eta_track < o2::aod::fwdtrack::eta && o2::aod::fwdtrack::eta < dimuoncuts.cfg_max_eta_track; - Filter ttcaFilter_muon = ifnode(dimuoncuts.enableTTCA.node(), o2::aod::emprimarymuon::isAssociatedToMPC == true || o2::aod::emprimarymuon::isAssociatedToMPC == false, o2::aod::emprimarymuon::isAssociatedToMPC == true); + Filter ttcaFilter_muon = ifnode(dimuoncuts.enableTTCA.node(), true, o2::aod::emprimarymuon::isAssociatedToMPC == true); + Filter prefilter_derived_muon = ifnode(dimuoncuts.cfg_apply_cuts_from_prefilter_derived.node() && dimuoncuts.cfg_prefilter_bits_derived.node() >= static_cast(1), + ifnode((dimuoncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS))) > static_cast(0), (o2::aod::emprimarymuon::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS))) <= static_cast(0), true) && + ifnode((dimuoncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS))) > static_cast(0), (o2::aod::emprimarymuon::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS))) <= static_cast(0), true), + o2::aod::emprimarymuon::pfbderived >= static_cast(0)); + Partition positive_muons = o2::aod::emprimarymuon::sign > int8_t(0); Partition negative_muons = o2::aod::emprimarymuon::sign < int8_t(0); @@ -1178,6 +1191,7 @@ struct Dilepton { TEMH* emh_neg = nullptr; std::map, uint64_t> map_mixed_eventId_to_globalBC; + std::unordered_map map_best_match_globalmuon; std::vector used_trackIds_per_col; int ndf = 0; @@ -1412,7 +1426,7 @@ struct Dilepton { } // end of DF template - bool isPairOK(TTrack1 const& t1, TTrack2 const& t2, TCut const& cut, TAllTracks const& tracks) + bool isPairOK(TTrack1 const& t1, TTrack2 const& t2, TCut const& cut, TAllTracks const&) { if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { if (dielectroncuts.cfg_pid_scheme == static_cast(DielectronCut::PIDSchemes::kPIDML)) { @@ -1428,13 +1442,16 @@ struct Dilepton { if (!cut.IsSelectedTrack(t1) || !cut.IsSelectedTrack(t2)) { return false; } - - if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t1, cut, tracks)) { - return false; - } - if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t2, cut, tracks)) { + if (!map_best_match_globalmuon[t1.globalIndex()] || !map_best_match_globalmuon[t2.globalIndex()]) { return false; } + + // if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t1, cut, tracks)) { + // return false; + // } + // if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t2, cut, tracks)) { + // return false; + // } } if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { @@ -1567,12 +1584,14 @@ struct Dilepton { runPairing(collisions, positive_electrons, negative_electrons, o2::aod::emprimaryelectron::emeventId, fDielectronCut, electrons); } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { auto muons = std::get<0>(std::tie(args...)); + map_best_match_globalmuon = findBestMatchMap(muons, fDimuonCut); if (cfgApplyWeightTTCA) { fillPairWeightMap(collisions, positive_muons, negative_muons, o2::aod::emprimarymuon::emeventId, fDimuonCut, muons); } runPairing(collisions, positive_muons, negative_muons, o2::aod::emprimarymuon::emeventId, fDimuonCut, muons); } map_weight.clear(); + map_best_match_globalmuon.clear(); ndf++; } PROCESS_SWITCH(Dilepton, processAnalysis, "run dilepton analysis", true); @@ -1587,12 +1606,14 @@ struct Dilepton { runPairing(collisions, positive_electrons, negative_electrons, o2::aod::emprimaryelectron::emeventId, fDielectronCut, electrons); } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { auto muons = std::get<0>(std::tie(args...)); + map_best_match_globalmuon = findBestMatchMap(muons, fDimuonCut); if (cfgApplyWeightTTCA) { fillPairWeightMap(collisions, positive_muons, negative_muons, o2::aod::emprimarymuon::emeventId, fDimuonCut, muons); } runPairing(collisions, positive_muons, negative_muons, o2::aod::emprimarymuon::emeventId, fDimuonCut, muons); } map_weight.clear(); + map_best_match_globalmuon.clear(); ndf++; } PROCESS_SWITCH(Dilepton, processTriggerAnalysis, "run dilepton analysis on triggered data", false); diff --git a/PWGEM/Dilepton/Core/DileptonHadronMPC.h b/PWGEM/Dilepton/Core/DileptonHadronMPC.h index 08a607e75e0..2a6664e20b3 100644 --- a/PWGEM/Dilepton/Core/DileptonHadronMPC.h +++ b/PWGEM/Dilepton/Core/DileptonHadronMPC.h @@ -79,7 +79,7 @@ using MyElectron = MyElectrons::iterator; using FilteredMyElectrons = soa::Filtered; using FilteredMyElectron = FilteredMyElectrons::iterator; -using MyMuons = soa::Join; +using MyMuons = soa::Join; using MyMuon = MyMuons::iterator; using FilteredMyMuons = soa::Filtered; using FilteredMyMuon = FilteredMyMuons::iterator; @@ -252,6 +252,9 @@ struct DileptonHadronMPC { Configurable cfg_min_deta{"cfg_min_deta", 0.02, "min deta between 2 muons (elliptic cut)"}; Configurable cfg_min_dphi{"cfg_min_dphi", 0.02, "min dphi between 2 muons (elliptic cut)"}; + Configurable cfg_apply_cuts_from_prefilter_derived{"cfg_apply_cuts_from_prefilter_derived", false, "flag to apply prefilter set in derived data"}; + Configurable cfg_prefilter_bits_derived{"cfg_prefilter_bits_derived", 0, "prefilter bits [kNone : 0, kSplitOrMergedTrackLS : 4, kSplitOrMergedTrackULS : 8] Please consider logical-OR among them."}; // see PairUtilities.h + Configurable cfg_track_type{"cfg_track_type", 3, "muon track type [0: MFT-MCH-MID, 3: MCH-MID]"}; Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.2, "min pT for single track"}; Configurable cfg_max_pt_track{"cfg_max_pt_track", 1e+10, "max pT for single track"}; @@ -619,7 +622,8 @@ struct DileptonHadronMPC { fDielectronCut.RequireITSibAny(dielectroncuts.cfg_require_itsib_any); fDielectronCut.RequireITSib1st(dielectroncuts.cfg_require_itsib_1st); fDielectronCut.SetChi2TOF(0, dielectroncuts.cfg_max_chi2tof); - fDielectronCut.SetRelDiffPin(-1e+10, +1e+10); + // fDielectronCut.SetRelDiffPin(-1e+10, +1e+10); + fDielectronCut.EnableTTCA(dielectroncuts.enableTTCA); // for eID fDielectronCut.SetPIDScheme(dielectroncuts.cfg_pid_scheme); @@ -698,6 +702,7 @@ struct DileptonHadronMPC { fDimuonCut.SetMaxPDCARabsDep([&](float rabs) { return (rabs < 26.5 ? 594.f : 324.f); }); fDimuonCut.SetMaxdPtdEtadPhiwrtMCHMID(dimuoncuts.cfg_max_relDPt_wrt_matchedMCHMID, dimuoncuts.cfg_max_DEta_wrt_matchedMCHMID, dimuoncuts.cfg_max_DPhi_wrt_matchedMCHMID); // this is relevant for global muons fDimuonCut.SetMFTHitMap(dimuoncuts.requireMFTHitMap, dimuoncuts.requiredMFTDisks); + fDimuonCut.EnableTTCA(dimuoncuts.enableTTCA); } void DefineEMTrackCut() @@ -1021,7 +1026,12 @@ struct DileptonHadronMPC { Preslice perCollision_muon = aod::emprimarymuon::emeventId; Filter trackFilter_muon = o2::aod::fwdtrack::trackType == dimuoncuts.cfg_track_type && dimuoncuts.cfg_min_pt_track < o2::aod::fwdtrack::pt && o2::aod::fwdtrack::pt < dimuoncuts.cfg_max_pt_track && dimuoncuts.cfg_min_eta_track < o2::aod::fwdtrack::eta && o2::aod::fwdtrack::eta < dimuoncuts.cfg_max_eta_track && dimuoncuts.cfg_min_phi_track < o2::aod::fwdtrack::phi && o2::aod::fwdtrack::phi < dimuoncuts.cfg_max_phi_track; - Filter ttcaFilter_muon = ifnode(dimuoncuts.enableTTCA.node(), o2::aod::emprimarymuon::isAssociatedToMPC == true || o2::aod::emprimarymuon::isAssociatedToMPC == false, o2::aod::emprimarymuon::isAssociatedToMPC == true); + Filter ttcaFilter_muon = ifnode(dimuoncuts.enableTTCA.node(), true, o2::aod::emprimarymuon::isAssociatedToMPC == true); + Filter prefilter_derived_muon = ifnode(dimuoncuts.cfg_apply_cuts_from_prefilter_derived.node() && dimuoncuts.cfg_prefilter_bits_derived.node() >= static_cast(1), + ifnode((dimuoncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS))) > static_cast(0), (o2::aod::emprimarymuon::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS))) <= static_cast(0), true) && + ifnode((dimuoncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS))) > static_cast(0), (o2::aod::emprimarymuon::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS))) <= static_cast(0), true), + o2::aod::emprimarymuon::pfbderived >= static_cast(0)); + Partition positive_muons = o2::aod::emprimarymuon::sign > int8_t(0); Partition negative_muons = o2::aod::emprimarymuon::sign < int8_t(0); diff --git a/PWGEM/Dilepton/Core/DileptonMC.h b/PWGEM/Dilepton/Core/DileptonMC.h index 3dbafde4c86..d21392444fa 100644 --- a/PWGEM/Dilepton/Core/DileptonMC.h +++ b/PWGEM/Dilepton/Core/DileptonMC.h @@ -75,7 +75,7 @@ using MyMCElectron = MyMCElectrons::iterator; using FilteredMyMCElectrons = soa::Filtered; using FilteredMyMCElectron = FilteredMyMCElectrons::iterator; -using MyMCMuons = soa::Join; +using MyMCMuons = soa::Join; using MyMCMuon = MyMCMuons::iterator; using FilteredMyMCMuons = soa::Filtered; using FilteredMyMCMuon = FilteredMyMCMuons::iterator; @@ -267,6 +267,9 @@ struct DileptonMC { Configurable cfg_min_deta{"cfg_min_deta", 0.02, "min deta between 2 muons (elliptic cut)"}; Configurable cfg_min_dphi{"cfg_min_dphi", 0.02, "min dphi between 2 muons (elliptic cut)"}; + Configurable cfg_apply_cuts_from_prefilter_derived{"cfg_apply_cuts_from_prefilter_derived", false, "flag to apply prefilter set in derived data"}; + Configurable cfg_prefilter_bits_derived{"cfg_prefilter_bits_derived", 0, "prefilter bits [kNone : 0, kSplitOrMergedTrackLS : 4, kSplitOrMergedTrackULS : 8] Please consider logical-OR among them."}; // see PairUtilities.h + Configurable cfg_track_type{"cfg_track_type", 3, "muon track type [0: MFT-MCH-MID, 3: MCH-MID]"}; Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.2, "min pT for single track"}; Configurable cfg_max_pt_track{"cfg_max_pt_track", 1e+10, "max pT for single track"}; @@ -739,6 +742,7 @@ struct DileptonMC { fDielectronCut.RequireITSib1st(dielectroncuts.cfg_require_itsib_1st); fDielectronCut.SetChi2TOF(0.0, dielectroncuts.cfg_max_chi2tof); // fDielectronCut.SetRelDiffPin(dielectroncuts.cfg_min_rel_diff_pin, dielectroncuts.cfg_max_rel_diff_pin); + fDielectronCut.EnableTTCA(dielectroncuts.enableTTCA); // for eID fDielectronCut.SetPIDScheme(dielectroncuts.cfg_pid_scheme); @@ -818,6 +822,7 @@ struct DileptonMC { fDimuonCut.SetMaxPDCARabsDep([&](float rabs) { return (rabs < 26.5 ? 594.f : 324.f); }); fDimuonCut.SetMaxdPtdEtadPhiwrtMCHMID(dimuoncuts.cfg_max_relDPt_wrt_matchedMCHMID, dimuoncuts.cfg_max_DEta_wrt_matchedMCHMID, dimuoncuts.cfg_max_DPhi_wrt_matchedMCHMID); // this is relevant for global muons fDimuonCut.SetMFTHitMap(dimuoncuts.requireMFTHitMap, dimuoncuts.requiredMFTDisks); + fDimuonCut.EnableTTCA(dimuoncuts.enableTTCA); } template @@ -1396,7 +1401,7 @@ struct DileptonMC { } template - bool fillTruePairInfo(TCollision const& collision, TMCCollisions const&, TTrack1 const& t1, TTrack2 const& t2, TCut const& cut, TAllTracks const& tracks, TMCParticles const& mcparticles) + bool fillTruePairInfo(TCollision const& collision, TMCCollisions const&, TTrack1 const& t1, TTrack2 const& t2, TCut const& cut, TAllTracks const&, TMCParticles const& mcparticles) { auto t1mc = mcparticles.iteratorAt(t1.emmcparticleId()); auto t2mc = mcparticles.iteratorAt(t2.emmcparticleId()); @@ -1431,13 +1436,16 @@ struct DileptonMC { if (!cut.template IsSelectedTrack(t1) || !cut.template IsSelectedTrack(t2)) { return false; } - - if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t1, cut, tracks)) { - return false; - } - if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t2, cut, tracks)) { + if (!map_best_match_globalmuon[t1.globalIndex()] || !map_best_match_globalmuon[t2.globalIndex()]) { return false; } + + // if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t1, cut, tracks)) { + // return false; + // } + // if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t2, cut, tracks)) { + // return false; + // } if (dimuoncuts.acceptOnlyCorrectMatch) { if (t1.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) && t1.emmcparticleId() != t1.emmftmcparticleId()) { return false; @@ -2145,7 +2153,7 @@ struct DileptonMC { } template - bool isPairOK(TTrack1 const& t1, TTrack2 const& t2, TCut const& cut, TAllTracks const& tracks) + bool isPairOK(TTrack1 const& t1, TTrack2 const& t2, TCut const& cut, TAllTracks const&) { if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { if (dielectroncuts.cfg_pid_scheme == static_cast(DielectronCut::PIDSchemes::kPIDML)) { @@ -2161,12 +2169,15 @@ struct DileptonMC { if (!cut.template IsSelectedTrack(t1) || !cut.template IsSelectedTrack(t2)) { return false; } - if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t1, cut, tracks)) { - return false; - } - if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t2, cut, tracks)) { + if (!map_best_match_globalmuon[t1.globalIndex()] || !map_best_match_globalmuon[t2.globalIndex()]) { return false; } + // if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t1, cut, tracks)) { + // return false; + // } + // if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t2, cut, tracks)) { + // return false; + // } } if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { @@ -2492,11 +2503,13 @@ struct DileptonMC { } // end of collision loop } + std::unordered_map map_best_match_globalmuon; + SliceCache cache; Preslice perCollision_electron = aod::emprimaryelectron::emeventId; Filter trackFilter_electron = nabs(o2::aod::track::dcaXY) < dielectroncuts.cfg_max_dcaxy && nabs(o2::aod::track::dcaZ) < dielectroncuts.cfg_max_dcaz && o2::aod::track::itsChi2NCl < dielectroncuts.cfg_max_chi2its && o2::aod::track::tpcChi2NCl < dielectroncuts.cfg_max_chi2tpc; Filter pidFilter_electron = dielectroncuts.cfg_min_TPCNsigmaEl < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < dielectroncuts.cfg_max_TPCNsigmaEl; - Filter ttcaFilter_electron = ifnode(dielectroncuts.enableTTCA.node(), o2::aod::emprimaryelectron::isAssociatedToMPC == true || o2::aod::emprimaryelectron::isAssociatedToMPC == false, o2::aod::emprimaryelectron::isAssociatedToMPC == true); + Filter ttcaFilter_electron = ifnode(dielectroncuts.enableTTCA.node(), true, o2::aod::emprimaryelectron::isAssociatedToMPC == true); Filter prefilter_derived_electron = ifnode(dielectroncuts.cfg_apply_cuts_from_prefilter_derived.node() && dielectroncuts.cfg_prefilter_bits_derived.node() >= static_cast(1), ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kMee))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kMee))) <= static_cast(0), true) && ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kPhiV))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kPhiV))) <= static_cast(0), true) && @@ -2517,7 +2530,11 @@ struct DileptonMC { Preslice perCollision_muon = aod::emprimarymuon::emeventId; Filter trackFilter_muon = o2::aod::fwdtrack::trackType == dimuoncuts.cfg_track_type; - Filter ttcaFilter_muon = ifnode(dimuoncuts.enableTTCA.node(), o2::aod::emprimarymuon::isAssociatedToMPC == true || o2::aod::emprimarymuon::isAssociatedToMPC == false, o2::aod::emprimarymuon::isAssociatedToMPC == true); + Filter ttcaFilter_muon = ifnode(dimuoncuts.enableTTCA.node(), true, o2::aod::emprimarymuon::isAssociatedToMPC == true); + Filter prefilter_derived_muon = ifnode(dimuoncuts.cfg_apply_cuts_from_prefilter_derived.node() && dimuoncuts.cfg_prefilter_bits_derived.node() >= static_cast(1), + ifnode((dimuoncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS))) > static_cast(0), (o2::aod::emprimarymuon::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS))) <= static_cast(0), true) && + ifnode((dimuoncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS))) > static_cast(0), (o2::aod::emprimarymuon::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS))) <= static_cast(0), true), + o2::aod::emprimarymuon::pfbderived >= static_cast(0)); Filter collisionFilter_centrality = (eventcuts.cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < eventcuts.cfgCentMax) || (eventcuts.cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < eventcuts.cfgCentMax) || (eventcuts.cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < eventcuts.cfgCentMax); Filter collisionFilter_numContrib = eventcuts.cfgNumContribMin <= o2::aod::collision::numContrib && o2::aod::collision::numContrib < eventcuts.cfgNumContribMax; @@ -2551,6 +2568,7 @@ struct DileptonMC { fillUnfolding(collisions, positive_electrons, negative_electrons, o2::aod::emprimaryelectron::emeventId, fDielectronCut, leptons, mccollisions, mcparticles); } } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + map_best_match_globalmuon = findBestMatchMap(leptons, fDimuonCut); if (cfgApplyWeightTTCA) { fillPairWeightMap(collisions, positive_muons, negative_muons, o2::aod::emprimarymuon::emeventId, fDimuonCut, leptons, mccollisions, mcparticles); } @@ -2561,6 +2579,7 @@ struct DileptonMC { } } map_weight.clear(); + map_best_match_globalmuon.clear(); } PROCESS_SWITCH(DileptonMC, processAnalysis, "run dilepton mc analysis", true); @@ -2582,6 +2601,7 @@ struct DileptonMC { fillUnfolding(collisions, positive_electrons, negative_electrons, o2::aod::emprimaryelectron::emeventId, fDielectronCut, leptons, mccollisions, mcparticles_smeared); } } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + map_best_match_globalmuon = findBestMatchMap(leptons, fDimuonCut); if (cfgApplyWeightTTCA) { fillPairWeightMap(collisions, positive_muons, negative_muons, o2::aod::emprimarymuon::emeventId, fDimuonCut, leptons, mccollisions, mcparticles_smeared); } @@ -2592,6 +2612,7 @@ struct DileptonMC { } } map_weight.clear(); + map_best_match_globalmuon.clear(); } PROCESS_SWITCH(DileptonMC, processAnalysis_Smeared, "run dilepton mc analysis with smearing", false); diff --git a/PWGEM/Dilepton/Core/DileptonProducer.h b/PWGEM/Dilepton/Core/DileptonProducer.h index d28e616db13..63ca7bd1eaa 100644 --- a/PWGEM/Dilepton/Core/DileptonProducer.h +++ b/PWGEM/Dilepton/Core/DileptonProducer.h @@ -241,6 +241,9 @@ struct DileptonProducer { Configurable cfg_min_deta{"cfg_min_deta", 0.02, "min deta between 2 muons (elliptic cut)"}; Configurable cfg_min_dphi{"cfg_min_dphi", 0.02, "min dphi between 2 muons (elliptic cut)"}; + Configurable cfg_apply_cuts_from_prefilter_derived{"cfg_apply_cuts_from_prefilter_derived", false, "flag to apply prefilter set in derived data"}; + Configurable cfg_prefilter_bits_derived{"cfg_prefilter_bits_derived", 0, "prefilter bits [kNone : 0, kSplitOrMergedTrackLS : 4, kSplitOrMergedTrackULS : 8] Please consider logical-OR among them."}; // see PairUtilities.h + Configurable cfg_track_type{"cfg_track_type", 3, "muon track type [0: MFT-MCH-MID, 3: MCH-MID]"}; Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.2, "min pT for single track"}; Configurable cfg_max_pt_track{"cfg_max_pt_track", 1e+10, "max pT for single track"}; @@ -570,6 +573,10 @@ struct DileptonProducer { Preslice perCollision_muon = aod::emprimarymuon::emeventId; Filter trackFilter_muon = o2::aod::fwdtrack::trackType == dimuoncuts.cfg_track_type && dimuoncuts.cfg_min_pt_track < o2::aod::fwdtrack::pt && o2::aod::fwdtrack::pt < dimuoncuts.cfg_max_pt_track && dimuoncuts.cfg_min_eta_track < o2::aod::fwdtrack::eta && o2::aod::fwdtrack::eta < dimuoncuts.cfg_max_eta_track; Filter ttcaFilter_muon = ifnode(dimuoncuts.enableTTCA.node(), o2::aod::emprimarymuon::isAssociatedToMPC == true || o2::aod::emprimarymuon::isAssociatedToMPC == false, o2::aod::emprimarymuon::isAssociatedToMPC == true); + Filter prefilter_derived_muon = ifnode(dimuoncuts.cfg_apply_cuts_from_prefilter_derived.node() && dimuoncuts.cfg_prefilter_bits_derived.node() >= static_cast(1), + ifnode((dimuoncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS))) > static_cast(0), (o2::aod::emprimarymuon::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS))) <= static_cast(0), true) && + ifnode((dimuoncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS))) > static_cast(0), (o2::aod::emprimarymuon::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS))) <= static_cast(0), true), + o2::aod::emprimarymuon::pfbderived >= static_cast(0)); Partition positive_muons = o2::aod::emprimarymuon::sign > int8_t(0); Partition negative_muons = o2::aod::emprimarymuon::sign < int8_t(0); diff --git a/PWGEM/Dilepton/Core/DimuonCut.cxx b/PWGEM/Dilepton/Core/DimuonCut.cxx index 25db52f6052..c5e9743bf10 100644 --- a/PWGEM/Dilepton/Core/DimuonCut.cxx +++ b/PWGEM/Dilepton/Core/DimuonCut.cxx @@ -128,6 +128,11 @@ void DimuonCut::SetDCAxy(float min, float max) mMaxDcaXY = max; LOG(info) << "Dimuon Cut, set DCAxy range: " << mMinDcaXY << " - " << mMaxDcaXY; } +void DimuonCut::EnableTTCA(const bool flag) +{ + mEnableTTCA = flag; + LOG(info) << "Dimuon Cut, enable TTCA: " << mEnableTTCA; +} void DimuonCut::SetMaxPDCARabsDep(std::function RabsDepCut) { mMaxPDCARabsDep = RabsDepCut; diff --git a/PWGEM/Dilepton/Core/DimuonCut.h b/PWGEM/Dilepton/Core/DimuonCut.h index f474ee4c073..dd10561196d 100644 --- a/PWGEM/Dilepton/Core/DimuonCut.h +++ b/PWGEM/Dilepton/Core/DimuonCut.h @@ -64,6 +64,7 @@ class DimuonCut : public TNamed kPDCA, kMFTHitMap, kDPtDEtaDPhiwrtMCHMID, + kTTCA, kNCuts }; @@ -166,6 +167,9 @@ class DimuonCut : public TNamed if (!IsSelectedTrack(track, DimuonCuts::kRabs)) { return false; } + if (!IsSelectedTrack(track, DimuonCuts::kTTCA)) { + return false; + } if (mApplyMFTHitMap && track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) && !IsSelectedTrack(track, DimuonCuts::kMFTHitMap)) { return false; } @@ -220,6 +224,9 @@ class DimuonCut : public TNamed case DimuonCuts::kRabs: return mMinRabs < track.rAtAbsorberEnd() && track.rAtAbsorberEnd() < mMaxRabs; + case DimuonCuts::kTTCA: + return mEnableTTCA ? true : track.isAssociatedToMPC(); + case DimuonCuts::kMFTHitMap: { std::vector mftHitMap{checkMFTHitMap<0, 1>(track), checkMFTHitMap<2, 3>(track), checkMFTHitMap<4, 5>(track), checkMFTHitMap<6, 7>(track), checkMFTHitMap<8, 9>(track)}; for (const auto& iDisk : mRequiredMFTDisks) { @@ -261,6 +268,7 @@ class DimuonCut : public TNamed void SetMFTHitMap(bool flag, std::vector hitMap); void SetMaxdPtdEtadPhiwrtMCHMID(float reldPtMax, float dEtaMax, float dPhiMax); // this is relevant for global muons void SetMaxMatchingChi2MCHMFTPtDep(std::function PtDepCut); + void EnableTTCA(bool flag); private: // pair cuts @@ -271,6 +279,7 @@ class DimuonCut : public TNamed bool mApplydEtadPhi{false}; // flag to apply deta, dphi cut between 2 tracks float mMinDeltaEta{0.f}; float mMinDeltaPhi{0.f}; + bool mEnableTTCA{true}; // kinematic cuts float mMinTrackPt{0.f}, mMaxTrackPt{1e10f}; // range in pT diff --git a/PWGEM/Dilepton/Core/SingleTrackQC.h b/PWGEM/Dilepton/Core/SingleTrackQC.h index 0bf1734c7c4..64eb1e2ec5b 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQC.h @@ -78,7 +78,6 @@ struct SingleTrackQC { Configurable d_bz_input{"d_bz_input", -999, "bz field in kG, -999 is automatic"}; Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; - Configurable cfg_swt_name{"cfg_swt_name", "fHighTrackMult", "desired software trigger name"}; // 1 trigger name per 1 task. fHighTrackMult, fHighFt0Mult Configurable cfgApplyWeightTTCA{"cfgApplyWeightTTCA", false, "flag to apply weighting by 1/N"}; ConfigurableAxis ConfPtlBins{"ConfPtlBins", {VARIABLE_WIDTH, 0.00, 0.05, 0.10, 0.15, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90, 1.00, 1.10, 1.20, 1.30, 1.40, 1.50, 1.60, 1.70, 1.80, 1.90, 2.00, 2.50, 3.00, 3.50, 4.00, 4.50, 5.00, 6.00, 7.00, 8.00, 9.00, 10.00}, "pTl bins for output histograms"}; @@ -474,6 +473,7 @@ struct SingleTrackQC { fDielectronCut.RequireITSib1st(dielectroncuts.cfg_require_itsib_1st); fDielectronCut.SetChi2TOF(0.0, dielectroncuts.cfg_max_chi2tof); fDielectronCut.SetRelDiffPin(dielectroncuts.cfg_min_rel_diff_pin, dielectroncuts.cfg_max_rel_diff_pin); + fDielectronCut.EnableTTCA(dielectroncuts.enableTTCA); // for eID fDielectronCut.SetPIDScheme(dielectroncuts.cfg_pid_scheme); @@ -546,6 +546,7 @@ struct SingleTrackQC { fDimuonCut.SetMaxPDCARabsDep([&](float rabs) { return (rabs < 26.5 ? 594.f : 324.f); }); fDimuonCut.SetMaxdPtdEtadPhiwrtMCHMID(dimuoncuts.cfg_max_relDPt_wrt_matchedMCHMID, dimuoncuts.cfg_max_DEta_wrt_matchedMCHMID, dimuoncuts.cfg_max_DPhi_wrt_matchedMCHMID); // this is relevant for global muons fDimuonCut.SetMFTHitMap(dimuoncuts.requireMFTHitMap, dimuoncuts.requiredMFTDisks); + fDimuonCut.EnableTTCA(dimuoncuts.enableTTCA); } template @@ -775,9 +776,12 @@ struct SingleTrackQC { if (!cut.template IsSelectedTrack(track)) { continue; } - if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(track, cut, tracks)) { + if (!map_best_match_globalmuon[track.globalIndex()]) { continue; } + // if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(track, cut, tracks)) { + // continue; + // } fillMuonInfo(track, collision); } // end of track loop @@ -831,9 +835,12 @@ struct SingleTrackQC { if (!cut.template IsSelectedTrack(track)) { continue; } - if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(track, cut, tracks)) { + if (!map_best_match_globalmuon[track.globalIndex()]) { continue; } + // if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(track, cut, tracks)) { + // continue; + // } passed_trackIds.emplace_back(track.globalIndex()); } // end of track loop } @@ -869,15 +876,17 @@ struct SingleTrackQC { passed_trackIds.shrink_to_fit(); } + std::unordered_map map_best_match_globalmuon; + SliceCache cache; Preslice perCollision_electron = aod::emprimaryelectron::emeventId; Filter trackFilter_electron = dielectroncuts.cfg_min_pt_track < o2::aod::track::pt && dielectroncuts.cfg_min_eta_track < o2::aod::track::eta && o2::aod::track::eta < dielectroncuts.cfg_max_eta_track && o2::aod::track::tpcChi2NCl < dielectroncuts.cfg_max_chi2tpc && o2::aod::track::itsChi2NCl < dielectroncuts.cfg_max_chi2its && nabs(o2::aod::track::dcaXY) < dielectroncuts.cfg_max_dcaxy && nabs(o2::aod::track::dcaZ) < dielectroncuts.cfg_max_dcaz; Filter pidFilter_electron = dielectroncuts.cfg_min_TPCNsigmaEl < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < dielectroncuts.cfg_max_TPCNsigmaEl; - Filter ttcaFilter_electron = ifnode(dielectroncuts.enableTTCA.node(), o2::aod::emprimaryelectron::isAssociatedToMPC == true || o2::aod::emprimaryelectron::isAssociatedToMPC == false, o2::aod::emprimaryelectron::isAssociatedToMPC == true); + Filter ttcaFilter_electron = ifnode(dielectroncuts.enableTTCA.node(), true, o2::aod::emprimaryelectron::isAssociatedToMPC == true); Preslice perCollision_muon = aod::emprimarymuon::emeventId; Filter trackFilter_muon = o2::aod::fwdtrack::trackType == dimuoncuts.cfg_track_type && dimuoncuts.cfg_min_pt_track < o2::aod::fwdtrack::pt && o2::aod::fwdtrack::pt < dimuoncuts.cfg_max_pt_track && dimuoncuts.cfg_min_eta_track < o2::aod::fwdtrack::eta && o2::aod::fwdtrack::eta < dimuoncuts.cfg_max_eta_track && dimuoncuts.cfg_min_phi_track < o2::aod::fwdtrack::phi && o2::aod::fwdtrack::phi < dimuoncuts.cfg_max_phi_track; - Filter ttcaFilter_muon = ifnode(dimuoncuts.enableTTCA.node(), o2::aod::emprimarymuon::isAssociatedToMPC == true || o2::aod::emprimarymuon::isAssociatedToMPC == false, o2::aod::emprimarymuon::isAssociatedToMPC == true); + Filter ttcaFilter_muon = ifnode(dimuoncuts.enableTTCA.node(), true, o2::aod::emprimarymuon::isAssociatedToMPC == true); Filter collisionFilter_centrality = (eventcuts.cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < eventcuts.cfgCentMax) || (eventcuts.cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < eventcuts.cfgCentMax) || (eventcuts.cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < eventcuts.cfgCentMax); Filter collisionFilter_numContrib = eventcuts.cfgNumContribMin <= o2::aod::collision::numContrib && o2::aod::collision::numContrib < eventcuts.cfgNumContribMax; @@ -895,13 +904,14 @@ struct SingleTrackQC { runQC(collisions, electrons, perCollision_electron, fDielectronCut); } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { auto muons = std::get<0>(std::tie(args...)); + map_best_match_globalmuon = findBestMatchMap(muons, fDimuonCut); if (cfgApplyWeightTTCA) { fillTrackWeightMap(collisions, muons, perCollision_muon, fDimuonCut); } runQC(collisions, muons, perCollision_muon, fDimuonCut); } - map_weight.clear(); + map_best_match_globalmuon.clear(); } PROCESS_SWITCH(SingleTrackQC, processQC, "run single track QC", true); @@ -915,12 +925,14 @@ struct SingleTrackQC { runQC(collisions, electrons, perCollision_electron, fDielectronCut); } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { auto muons = std::get<0>(std::tie(args...)); + map_best_match_globalmuon = findBestMatchMap(muons, fDimuonCut); if (cfgApplyWeightTTCA) { fillTrackWeightMap(collisions, muons, perCollision_muon, fDimuonCut); } runQC(collisions, muons, perCollision_muon, fDimuonCut); } map_weight.clear(); + map_best_match_globalmuon.clear(); } PROCESS_SWITCH(SingleTrackQC, processQC_TriggeredData, "run single track QC on triggered data", false); diff --git a/PWGEM/Dilepton/Core/SingleTrackQCMC.h b/PWGEM/Dilepton/Core/SingleTrackQCMC.h index 8cfef51da2c..bde2c91649d 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQCMC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQCMC.h @@ -521,6 +521,7 @@ struct SingleTrackQCMC { fDielectronCut.SetChi2TOF(0.0, dielectroncuts.cfg_max_chi2tof); fDielectronCut.SetRelDiffPin(dielectroncuts.cfg_min_rel_diff_pin, dielectroncuts.cfg_max_rel_diff_pin); fDielectronCut.IncludeITSsa(dielectroncuts.includeITSsa, 1e+10); + fDielectronCut.EnableTTCA(dielectroncuts.enableTTCA); // for eID fDielectronCut.SetPIDScheme(dielectroncuts.cfg_pid_scheme); @@ -593,6 +594,7 @@ struct SingleTrackQCMC { fDimuonCut.SetMaxPDCARabsDep([&](float rabs) { return (rabs < 26.5 ? 594.f : 324.f); }); fDimuonCut.SetMaxdPtdEtadPhiwrtMCHMID(dimuoncuts.cfg_max_relDPt_wrt_matchedMCHMID, dimuoncuts.cfg_max_DEta_wrt_matchedMCHMID, dimuoncuts.cfg_max_DPhi_wrt_matchedMCHMID); // this is relevant for global muons fDimuonCut.SetMFTHitMap(dimuoncuts.requireMFTHitMap, dimuoncuts.requiredMFTDisks); + fDimuonCut.EnableTTCA(dimuoncuts.enableTTCA); } template @@ -892,9 +894,12 @@ struct SingleTrackQCMC { if (!cut.template IsSelectedTrack(track)) { continue; } - if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(track, cut, tracks)) { + if (!map_best_match_globalmuon[track.globalIndex()]) { continue; } + // if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(track, cut, tracks)) { + // continue; + // } if (dimuoncuts.acceptOnlyCorrectMatch && track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) && track.emmcparticleId() != track.emmftmcparticleId()) { continue; } @@ -1089,10 +1094,12 @@ struct SingleTrackQCMC { if (!cut.template IsSelectedTrack(track)) { continue; } - - if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(track, cut, tracks)) { + if (!map_best_match_globalmuon[track.globalIndex()]) { continue; } + // if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(track, cut, tracks)) { + // continue; + // } passed_trackIds.emplace_back(track.globalIndex()); } // end of track loop } @@ -1128,15 +1135,16 @@ struct SingleTrackQCMC { passed_trackIds.shrink_to_fit(); } + std::unordered_map map_best_match_globalmuon; SliceCache cache; Preslice perCollision_electron = aod::emprimaryelectron::emeventId; Filter trackFilter_electron = o2::aod::track::tpcChi2NCl < dielectroncuts.cfg_max_chi2tpc && o2::aod::track::itsChi2NCl < dielectroncuts.cfg_max_chi2its && nabs(o2::aod::track::dcaXY) < dielectroncuts.cfg_max_dcaxy && nabs(o2::aod::track::dcaZ) < dielectroncuts.cfg_max_dcaz; Filter pidFilter_electron = dielectroncuts.cfg_min_TPCNsigmaEl < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < dielectroncuts.cfg_max_TPCNsigmaEl; - Filter ttcaFilter_electron = ifnode(dielectroncuts.enableTTCA.node(), o2::aod::emprimaryelectron::isAssociatedToMPC == true || o2::aod::emprimaryelectron::isAssociatedToMPC == false, o2::aod::emprimaryelectron::isAssociatedToMPC == true); + Filter ttcaFilter_electron = ifnode(dielectroncuts.enableTTCA.node(), true, o2::aod::emprimaryelectron::isAssociatedToMPC == true); Preslice perCollision_muon = aod::emprimarymuon::emeventId; Filter trackFilter_muon = o2::aod::fwdtrack::trackType == dimuoncuts.cfg_track_type && dimuoncuts.cfg_min_phi_track < o2::aod::fwdtrack::phi && o2::aod::fwdtrack::phi < dimuoncuts.cfg_max_phi_track; - Filter ttcaFilter_muon = ifnode(dimuoncuts.enableTTCA.node(), o2::aod::emprimarymuon::isAssociatedToMPC == true || o2::aod::emprimarymuon::isAssociatedToMPC == false, o2::aod::emprimarymuon::isAssociatedToMPC == true); + Filter ttcaFilter_muon = ifnode(dimuoncuts.enableTTCA.node(), true, o2::aod::emprimarymuon::isAssociatedToMPC == true); Filter collisionFilter_centrality = (eventcuts.cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < eventcuts.cfgCentMax) || (eventcuts.cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < eventcuts.cfgCentMax) || (eventcuts.cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < eventcuts.cfgCentMax); Filter collisionFilter_numContrib = eventcuts.cfgNumContribMin <= o2::aod::collision::numContrib && o2::aod::collision::numContrib < eventcuts.cfgNumContribMax; @@ -1159,6 +1167,7 @@ struct SingleTrackQCMC { runQCMC(collisions, tracks, perCollision_electron, fDielectronCut, mccollisions, mcparticles); runGenInfo(collisions, electronsMC, mccollisions, mcparticles); } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + map_best_match_globalmuon = findBestMatchMap(tracks, fDimuonCut); if (cfgApplyWeightTTCA) { fillTrackWeightMap(collisions, tracks, perCollision_muon, fDimuonCut, mccollisions, mcparticles); } @@ -1166,6 +1175,7 @@ struct SingleTrackQCMC { runGenInfo(collisions, muonsMC, mccollisions, mcparticles); } map_weight.clear(); + map_best_match_globalmuon.clear(); } PROCESS_SWITCH(SingleTrackQCMC, processQCMC, "run single track QC MC", true); @@ -1181,6 +1191,7 @@ struct SingleTrackQCMC { runQCMC(collisions, tracks, perCollision_electron, fDielectronCut, mccollisions, mcparticles_smeared); runGenInfo(collisions, electronsMC_smeared, mccollisions, mcparticles_smeared); } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + map_best_match_globalmuon = findBestMatchMap(tracks, fDimuonCut); if (cfgApplyWeightTTCA) { fillTrackWeightMap(collisions, tracks, perCollision_muon, fDimuonCut, mccollisions, mcparticles_smeared); } @@ -1188,6 +1199,7 @@ struct SingleTrackQCMC { runGenInfo(collisions, muonsMC_smeared, mccollisions, mcparticles_smeared); } map_weight.clear(); + map_best_match_globalmuon.clear(); } PROCESS_SWITCH(SingleTrackQCMC, processQCMC_Smeared, "run single track QC MC with smearing", false); diff --git a/PWGEM/Dilepton/DataModel/dileptonTables.h b/PWGEM/Dilepton/DataModel/dileptonTables.h index 10252c7cc9d..882f714188e 100644 --- a/PWGEM/Dilepton/DataModel/dileptonTables.h +++ b/PWGEM/Dilepton/DataModel/dileptonTables.h @@ -1006,7 +1006,7 @@ DECLARE_SOA_TABLE(EMAmbiguousElectronSelfIds, "AOD", "EMAMBELSELFID", emprimarye // iterators using EMAmbiguousElectronSelfId = EMAmbiguousElectronSelfIds::iterator; -DECLARE_SOA_TABLE(EMPrimaryElectronsPrefilterBitDerived, "AOD", "PRMELPFBPI0", emprimaryelectron::PrefilterBitDerived); // To be joined with EMPrimaryElectrons table at analysis level. +DECLARE_SOA_TABLE(EMPrimaryElectronsPrefilterBitDerived, "AOD", "PRMELPFBDERIVED", emprimaryelectron::PrefilterBitDerived); // To be joined with EMPrimaryElectrons table at analysis level. // iterators using EMPrimaryElectronPrefilterBitDerived = EMPrimaryElectronsPrefilterBitDerived::iterator; @@ -1035,6 +1035,7 @@ DECLARE_SOA_COLUMN(IsAmbiguous, isAmbiguous, bool); //! is am DECLARE_SOA_COLUMN(IsCorrectMatchMFTMCH, isCorrectMatchMFTMCH, bool); //! is correct match between MFT and MCH, only for MC DECLARE_SOA_COLUMN(Sign, sign, int8_t); //! DECLARE_SOA_COLUMN(Chi2MFT, chi2MFT, float); //! chi2 of MFT standalone track +DECLARE_SOA_COLUMN(PrefilterBitDerived, pfbderived, uint16_t); //! DECLARE_SOA_DYNAMIC_COLUMN(Tgl, tgl, [](float eta) -> float { return std::tan(o2::constants::math::PIHalf - 2 * std::atan(std::exp(-eta))); }); DECLARE_SOA_DYNAMIC_COLUMN(Signed1Pt, signed1Pt, [](float pt, int8_t sign) -> float { return sign * 1. / pt; }); DECLARE_SOA_DYNAMIC_COLUMN(P, p, [](float pt, float eta) -> float { return pt * std::cosh(eta); }); @@ -1172,6 +1173,10 @@ using EMGlobalMuonSelfIds = EMGlobalMuonSelfIds_001; // iterators using EMGlobalMuonSelfId = EMGlobalMuonSelfIds::iterator; +DECLARE_SOA_TABLE(EMPrimaryMuonsPrefilterBitDerived, "AOD", "PRMMUPFBDERIVED", emprimarymuon::PrefilterBitDerived); // To be joined with EMPrimaryMuons table at analysis level. +// iterators +using EMPrimaryMuonPrefilterBitDerived = EMPrimaryMuonsPrefilterBitDerived::iterator; + DECLARE_SOA_TABLE(EMPrimaryMuonsMatchMC, "AOD", "EMMUONMATCHMC", emprimarymuon::IsCorrectMatchMFTMCH); // To be joined with EMPrimaryMuons table at analysis level. only for MC. // iterators using EMPrimaryMuonMatchMC = EMPrimaryMuonsMatchMC::iterator; diff --git a/PWGEM/Dilepton/TableProducer/CMakeLists.txt b/PWGEM/Dilepton/TableProducer/CMakeLists.txt index dd7b21fa91f..617d07a86d1 100644 --- a/PWGEM/Dilepton/TableProducer/CMakeLists.txt +++ b/PWGEM/Dilepton/TableProducer/CMakeLists.txt @@ -106,3 +106,7 @@ o2physics_add_dpl_workflow(qvector3-dummy-otf PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(prefilter-dimuon + SOURCES prefilterDimuon.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGEMDileptonCore + COMPONENT_NAME Analysis) diff --git a/PWGEM/Dilepton/TableProducer/prefilterDimuon.cxx b/PWGEM/Dilepton/TableProducer/prefilterDimuon.cxx new file mode 100644 index 00000000000..b2555503c2f --- /dev/null +++ b/PWGEM/Dilepton/TableProducer/prefilterDimuon.cxx @@ -0,0 +1,465 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +// +// ======================== +// +// This code produces information on prefilter for dimuons. +// Please write to: daiki.sekihata@cern.ch + +#include "PWGEM/Dilepton/Core/DimuonCut.h" +#include "PWGEM/Dilepton/Core/EMEventCut.h" +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" + +// #include "PWGEM/Dilepton/Utils/EMTrack.h" +// #include "PWGEM/Dilepton/Utils/EventHistograms.h" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" + +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +#include "Math/Vector4D.h" +#include "TString.h" + +// #include +#include +// #include +#include +#include + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; +using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; +using namespace o2::aod::pwgem::dilepton::utils::pairutil; + +struct prefilterDimuon { + using MyCollisions = soa::Join; + using MyCollision = MyCollisions::iterator; + + using MyTracks = soa::Join; + using MyTrack = MyTracks::iterator; + + Produces pfb_derived; + + // // Configurables + // Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + // Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; + // Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + // Configurable skipGRPOquery{"skipGRPOquery", true, "skip grpo query"}; + // Configurable d_bz_input{"d_bz_input", -999, "bz field in kG, -999 is automatic"}; + + Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; + Configurable cfgCentMin{"cfgCentMin", -1, "min. centrality"}; + Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; + + EMEventCut fEMEventCut; + struct : ConfigurableGroup { + std::string prefix = "eventcut_group"; + Configurable cfgZvtxMin{"cfgZvtxMin", -10.f, "min. Zvtx"}; + Configurable cfgZvtxMax{"cfgZvtxMax", +10.f, "max. Zvtx"}; + Configurable cfgRequireSel8{"cfgRequireSel8", false, "require sel8 in event cut"}; + Configurable cfgRequireFT0AND{"cfgRequireFT0AND", true, "require FT0AND in event cut"}; + Configurable cfgRequireNoTFB{"cfgRequireNoTFB", false, "require No time frame border in event cut"}; + Configurable cfgRequireNoITSROFB{"cfgRequireNoITSROFB", false, "require no ITS readout frame border in event cut"}; + Configurable cfgRequireNoSameBunchPileup{"cfgRequireNoSameBunchPileup", false, "require no same bunch pileup in event cut"}; + Configurable cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; + Configurable cfgTrackOccupancyMin{"cfgTrackOccupancyMin", -2, "min. occupancy"}; + Configurable cfgTrackOccupancyMax{"cfgTrackOccupancyMax", 1000000000, "max. occupancy"}; + Configurable cfgFT0COccupancyMin{"cfgFT0COccupancyMin", -2, "min. FT0C occupancy"}; + Configurable cfgFT0COccupancyMax{"cfgFT0COccupancyMax", 1000000000, "max. FT0C occupancy"}; + } eventcuts; + + DimuonCut fDimuonCut; + struct : ConfigurableGroup { + std::string prefix = "dimuoncut_group"; + + // for deta-dphi prefilter + Configurable cfg_apply_detadphi_uls{"cfg_apply_detadphi_uls", false, "flag to apply generator deta-dphi elliptic cut in ULS"}; // region to be rejected + Configurable cfg_apply_detadphi_ls{"cfg_apply_detadphi_ls", false, "flag to apply generator deta-dphi elliptic cut in LS"}; // region to be rejected + Configurable cfg_min_deta_ls{"cfg_min_deta_ls", 0.04, "deta between 2 electrons (elliptic cut)"}; // region to be rejected + Configurable cfg_min_dphi_ls{"cfg_min_dphi_ls", 0.2, "dphi between 2 electrons (elliptic cut)"}; // region to be rejected + Configurable cfg_min_deta_uls{"cfg_min_deta_uls", 0.04, "deta between 2 electrons (elliptic cut)"}; // region to be rejected + Configurable cfg_min_dphi_uls{"cfg_min_dphi_uls", 0.2, "dphi between 2 electrons (elliptic cut)"}; // region to be rejected + + Configurable cfg_track_type{"cfg_track_type", 3, "muon track type [0: MFT-MCH-MID, 3: MCH-MID]"}; + Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.2, "min pT for single track"}; + Configurable cfg_max_pt_track{"cfg_max_pt_track", 1e+10, "max pT for single track"}; + Configurable cfg_min_eta_track{"cfg_min_eta_track", -4.0, "min eta for single track"}; + Configurable cfg_max_eta_track{"cfg_max_eta_track", -2.5, "max eta for single track"}; + Configurable cfg_min_phi_track{"cfg_min_phi_track", 0.f, "min phi for single track"}; + Configurable cfg_max_phi_track{"cfg_max_phi_track", 6.3, "max phi for single track"}; + Configurable cfg_min_ncluster_mft{"cfg_min_ncluster_mft", 5, "min ncluster MFT"}; + Configurable cfg_min_ncluster_mch{"cfg_min_ncluster_mch", 5, "min ncluster MCH"}; + Configurable cfg_max_chi2{"cfg_max_chi2", 1e+6, "max chi2/ndf"}; + Configurable cfg_max_chi2mft{"cfg_max_chi2mft", 1e+6, "max chi2/ndf"}; + // Configurable cfg_max_matching_chi2_mftmch{"cfg_max_matching_chi2_mftmch", 40, "max chi2 for MFT-MCH matching"}; + Configurable cfg_border_pt_for_chi2mchmft{"cfg_border_pt_for_chi2mchmft", 0, "border pt for different max chi2 for MFT-MCH matching"}; + Configurable cfg_max_matching_chi2_mftmch_lowPt{"cfg_max_matching_chi2_mftmch_lowPt", 8, "max chi2 for MFT-MCH matching for low pT"}; + Configurable cfg_max_matching_chi2_mftmch_highPt{"cfg_max_matching_chi2_mftmch_highPt", 40, "max chi2 for MFT-MCH matching for high pT"}; + Configurable cfg_max_matching_chi2_mchmid{"cfg_max_matching_chi2_mchmid", 1e+10, "max chi2 for MCH-MID matching"}; + Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1e+10, "max dca XY for single track in cm"}; + Configurable cfg_min_rabs{"cfg_min_rabs", 17.6, "min Radius at the absorber end"}; + Configurable cfg_max_rabs{"cfg_max_rabs", 89.5, "max Radius at the absorber end"}; + Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; + Configurable cfg_max_relDPt_wrt_matchedMCHMID{"cfg_max_relDPt_wrt_matchedMCHMID", 1e+10f, "max. relative dpt between MFT-MCH-MID and MCH-MID"}; + Configurable cfg_max_DEta_wrt_matchedMCHMID{"cfg_max_DEta_wrt_matchedMCHMID", 1e+10f, "max. deta between MFT-MCH-MID and MCH-MID"}; + Configurable cfg_max_DPhi_wrt_matchedMCHMID{"cfg_max_DPhi_wrt_matchedMCHMID", 1e+10f, "max. dphi between MFT-MCH-MID and MCH-MID"}; + Configurable requireMFTHitMap{"requireMFTHitMap", false, "flag to apply MFT hit map"}; + Configurable> requiredMFTDisks{"requiredMFTDisks", std::vector{0}, "hit map on MFT disks [0,1,2,3,4]. logical-OR of each double-sided disk"}; + } dimuoncuts; + + // o2::ccdb::CcdbApi ccdbApi; + // Service ccdb; + // int mRunNumber; + // float d_bz; + // o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; + + HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; + + void init(InitContext& /*context*/) + { + DefineEMEventCut(); + DefineDimuonCut(); + addhistograms(); + + // mRunNumber = 0; + // d_bz = 0; + + // ccdb->setURL(ccdburl); + // ccdb->setCaching(true); + // ccdb->setLocalObjectValidityChecking(); + // ccdb->setFatalWhenNull(false); + } + + // template + // void initCCDB(TCollision const& collision) + // { + // if (mRunNumber == collision.runNumber()) { + // return; + // } + + // // In case override, don't proceed, please - no CCDB access required + // if (d_bz_input > -990) { + // d_bz = d_bz_input; + // o2::parameters::GRPMagField grpmag; + // if (fabs(d_bz) > 1e-5) { + // grpmag.setL3Current(30000.f / (d_bz / 5.0f)); + // } + // o2::base::Propagator::initFieldFromGRP(&grpmag); + // mRunNumber = collision.runNumber(); + // return; + // } + + // auto run3grp_timestamp = collision.timestamp(); + // o2::parameters::GRPObject* grpo = 0x0; + // o2::parameters::GRPMagField* grpmag = 0x0; + // if (!skipGRPOquery) + // grpo = ccdb->getForTimeStamp(grpPath, run3grp_timestamp); + // if (grpo) { + // o2::base::Propagator::initFieldFromGRP(grpo); + // // Fetch magnetic field from ccdb for current collision + // d_bz = grpo->getNominalL3Field(); + // LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; + // } else { + // grpmag = ccdb->getForTimeStamp(grpmagPath, run3grp_timestamp); + // if (!grpmag) { + // LOG(fatal) << "Got nullptr from CCDB for path " << grpmagPath << " of object GRPMagField and " << grpPath << " of object GRPObject for timestamp " << run3grp_timestamp; + // } + // o2::base::Propagator::initFieldFromGRP(grpmag); + // // Fetch magnetic field from ccdb for current collision + // d_bz = std::lround(5.f * grpmag->getL3Current() / 30000.f); + // LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; + // } + // mRunNumber = collision.runNumber(); + // } + + ~prefilterDimuon() {} + + void addhistograms() + { + const AxisSpec axis_mass{380, 0.2, 4, "m_{#mu#mu} (GeV/c^{2})"}; + const AxisSpec axis_pair_pt{100, 0, 10, "p_{T,#mu#mu} (GeV/c)"}; + + // for pair + fRegistry.add("Pair/before/uls/hMvsPt", "m_{#mu#mu} vs. p_{T,#mu#mu}", kTH2D, {axis_mass, axis_pair_pt}, true); + fRegistry.add("Pair/before/uls/hDeltaEtaDeltaPhi", "#Delta#eta-#Delta#varphi between 2 tracks;#Delta#varphi (rad.);#Delta#eta;", kTH2D, {{180, -M_PI, M_PI}, {400, -2, +2}}, true); + fRegistry.addClone("Pair/before/uls/", "Pair/before/lspp/"); + fRegistry.addClone("Pair/before/uls/", "Pair/before/lsmm/"); + fRegistry.addClone("Pair/before/", "Pair/after/"); + } + + void DefineEMEventCut() + { + fEMEventCut = EMEventCut("fEMEventCut", "fEMEventCut"); + fEMEventCut.SetRequireSel8(eventcuts.cfgRequireSel8); + fEMEventCut.SetRequireFT0AND(eventcuts.cfgRequireFT0AND); + fEMEventCut.SetZvtxRange(eventcuts.cfgZvtxMin, eventcuts.cfgZvtxMax); + fEMEventCut.SetRequireNoTFB(eventcuts.cfgRequireNoTFB); + fEMEventCut.SetRequireNoITSROFB(eventcuts.cfgRequireNoITSROFB); + fEMEventCut.SetRequireNoSameBunchPileup(eventcuts.cfgRequireNoSameBunchPileup); + fEMEventCut.SetRequireGoodZvtxFT0vsPV(eventcuts.cfgRequireGoodZvtxFT0vsPV); + } + + void DefineDimuonCut() + { + fDimuonCut = DimuonCut("fDimuonCut", "fDimuonCut"); + + // don't apply pair cut in prefilter! + + // for track + fDimuonCut.SetTrackType(dimuoncuts.cfg_track_type); + fDimuonCut.SetTrackPtRange(dimuoncuts.cfg_min_pt_track, dimuoncuts.cfg_max_pt_track); + fDimuonCut.SetTrackEtaRange(dimuoncuts.cfg_min_eta_track, dimuoncuts.cfg_max_eta_track); + fDimuonCut.SetTrackPhiRange(dimuoncuts.cfg_min_phi_track, dimuoncuts.cfg_max_phi_track); + fDimuonCut.SetNClustersMFT(dimuoncuts.cfg_min_ncluster_mft, 10); + fDimuonCut.SetNClustersMCHMID(dimuoncuts.cfg_min_ncluster_mch, 20); + fDimuonCut.SetChi2(0.f, dimuoncuts.cfg_max_chi2); + fDimuonCut.SetChi2MFT(0.f, dimuoncuts.cfg_max_chi2mft); + // fDimuonCut.SetMatchingChi2MCHMFT(0.f, dimuoncuts.cfg_max_matching_chi2_mftmch); + fDimuonCut.SetMaxMatchingChi2MCHMFTPtDep([&](float pt) { return (pt < dimuoncuts.cfg_border_pt_for_chi2mchmft ? dimuoncuts.cfg_max_matching_chi2_mftmch_lowPt : dimuoncuts.cfg_max_matching_chi2_mftmch_highPt); }); + fDimuonCut.SetMatchingChi2MCHMID(0.f, dimuoncuts.cfg_max_matching_chi2_mchmid); + fDimuonCut.SetDCAxy(0.f, dimuoncuts.cfg_max_dcaxy); + fDimuonCut.SetRabs(dimuoncuts.cfg_min_rabs, dimuoncuts.cfg_max_rabs); + fDimuonCut.SetMaxPDCARabsDep([&](float rabs) { return (rabs < 26.5 ? 594.f : 324.f); }); + fDimuonCut.SetMaxdPtdEtadPhiwrtMCHMID(dimuoncuts.cfg_max_relDPt_wrt_matchedMCHMID, dimuoncuts.cfg_max_DEta_wrt_matchedMCHMID, dimuoncuts.cfg_max_DPhi_wrt_matchedMCHMID); // this is relevant for global muons + fDimuonCut.SetMFTHitMap(dimuoncuts.requireMFTHitMap, dimuoncuts.requiredMFTDisks); + fDimuonCut.EnableTTCA(dimuoncuts.enableTTCA); + } + + std::unordered_map map_best_match_globalmuon; + std::unordered_map map_pfb; // map track.globalIndex -> prefilter bit + + SliceCache cache; + Preslice perCollision_track = aod::emprimarymuon::emeventId; + Partition posTracks = o2::aod::emprimarymuon::sign > int8_t(0); + Partition negTracks = o2::aod::emprimarymuon::sign < int8_t(0); + + Filter collisionFilter_centrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); + Filter collisionFilter_occupancy_track = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; + Filter collisionFilter_occupancy_ft0c = eventcuts.cfgFT0COccupancyMin <= o2::aod::evsel::ft0cOccupancyInTimeRange && o2::aod::evsel::ft0cOccupancyInTimeRange < eventcuts.cfgFT0COccupancyMax; + using FilteredMyCollisions = soa::Filtered; + + void processPFB(FilteredMyCollisions const& collisions, MyTracks const& tracks) + { + map_best_match_globalmuon = findBestMatchMap(tracks, fDimuonCut); + + for (const auto& track : tracks) { + map_pfb[track.globalIndex()] = 0; + } // end of track loop + + for (const auto& collision : collisions) { + // initCCDB(collision); + const float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; + bool is_cent_ok = true; + if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + is_cent_ok = false; + } + + auto posTracks_per_coll = posTracks->sliceByCached(o2::aod::emprimarymuon::emeventId, collision.globalIndex(), cache); + auto negTracks_per_coll = negTracks->sliceByCached(o2::aod::emprimarymuon::emeventId, collision.globalIndex(), cache); + + if (!fEMEventCut.IsSelected(collision) || !is_cent_ok) { + for (const auto& pos : posTracks_per_coll) { + map_pfb[pos.globalIndex()] = 0; + } + for (const auto& neg : negTracks_per_coll) { + map_pfb[neg.globalIndex()] = 0; + } + continue; + } + + // LOGF(info, "centrality = %f , posTracks_per_coll.size() = %d, negTracks_per_coll.size() = %d", centralities[cfgCentEstimator], posTracks_per_coll.size(), negTracks_per_coll.size()); + + for (const auto& [pos, neg] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS + if (!fDimuonCut.IsSelectedTrack(pos) || !fDimuonCut.IsSelectedTrack(neg)) { + continue; + } + if (!map_best_match_globalmuon[pos.globalIndex()] || !map_best_match_globalmuon[neg.globalIndex()]) { + continue; + } + + // don't apply pair cut when you produce prefilter bit. + + ROOT::Math::PtEtaPhiMVector v1(pos.pt(), pos.eta(), pos.phi(), o2::constants::physics::MassMuon); + ROOT::Math::PtEtaPhiMVector v2(neg.pt(), neg.eta(), neg.phi(), o2::constants::physics::MassMuon); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + float deta = pos.sign() * v1.Pt() > neg.sign() * v2.Pt() ? v1.Eta() - v2.Eta() : v2.Eta() - v1.Eta(); + float dphi = pos.sign() * v1.Pt() > neg.sign() * v2.Pt() ? v1.Phi() - v2.Phi() : v2.Phi() - v1.Phi(); + o2::math_utils::bringToPMPi(dphi); + + fRegistry.fill(HIST("Pair/before/uls/hMvsPt"), v12.M(), v12.Pt()); + fRegistry.fill(HIST("Pair/before/uls/hDeltaEtaDeltaPhi"), dphi, deta); + + if (dimuoncuts.cfg_apply_detadphi_uls && std::pow(deta / dimuoncuts.cfg_min_deta_uls, 2) + std::pow(dphi / dimuoncuts.cfg_min_dphi_uls, 2) < 1.f) { + map_pfb[pos.globalIndex()] |= 1 << static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS); + map_pfb[neg.globalIndex()] |= 1 << static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS); + } + } // end of ULS pairing + + for (const auto& [pos1, pos2] : combinations(CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { // LS++ + if (!fDimuonCut.IsSelectedTrack(pos1) || !fDimuonCut.IsSelectedTrack(pos2)) { + continue; + } + if (!map_best_match_globalmuon[pos1.globalIndex()] || !map_best_match_globalmuon[pos2.globalIndex()]) { + continue; + } + // don't apply pair cut when you produce prefilter bit. + + ROOT::Math::PtEtaPhiMVector v1(pos1.pt(), pos1.eta(), pos1.phi(), o2::constants::physics::MassMuon); + ROOT::Math::PtEtaPhiMVector v2(pos2.pt(), pos2.eta(), pos2.phi(), o2::constants::physics::MassMuon); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + float deta = pos1.sign() * v1.Pt() > pos2.sign() * v2.Pt() ? v1.Eta() - v2.Eta() : v2.Eta() - v1.Eta(); + float dphi = pos1.sign() * v1.Pt() > pos2.sign() * v2.Pt() ? v1.Phi() - v2.Phi() : v2.Phi() - v1.Phi(); + o2::math_utils::bringToPMPi(dphi); + + fRegistry.fill(HIST("Pair/before/lspp/hMvsPt"), v12.M(), v12.Pt()); + fRegistry.fill(HIST("Pair/before/lspp/hDeltaEtaDeltaPhi"), dphi, deta); + + if (dimuoncuts.cfg_apply_detadphi_ls && std::pow(deta / dimuoncuts.cfg_min_deta_ls, 2) + std::pow(dphi / dimuoncuts.cfg_min_dphi_ls, 2) < 1.f) { + map_pfb[pos1.globalIndex()] |= 1 << static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS); + map_pfb[pos2.globalIndex()] |= 1 << static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS); + } + } // end of LS++ pairing + + for (const auto& [neg1, neg2] : combinations(CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { // LS-- + if (!fDimuonCut.IsSelectedTrack(neg1) || !fDimuonCut.IsSelectedTrack(neg2)) { + continue; + } + if (!map_best_match_globalmuon[neg1.globalIndex()] || !map_best_match_globalmuon[neg2.globalIndex()]) { + continue; + } + // don't apply pair cut when you produce prefilter bit. + + ROOT::Math::PtEtaPhiMVector v1(neg1.pt(), neg1.eta(), neg1.phi(), o2::constants::physics::MassMuon); + ROOT::Math::PtEtaPhiMVector v2(neg2.pt(), neg2.eta(), neg2.phi(), o2::constants::physics::MassMuon); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + float deta = neg1.sign() * v1.Pt() > neg2.sign() * v2.Pt() ? v1.Eta() - v2.Eta() : v2.Eta() - v1.Eta(); + float dphi = neg1.sign() * v1.Pt() > neg2.sign() * v2.Pt() ? v1.Phi() - v2.Phi() : v2.Phi() - v1.Phi(); + o2::math_utils::bringToPMPi(dphi); + + fRegistry.fill(HIST("Pair/before/lsmm/hMvsPt"), v12.M(), v12.Pt()); + fRegistry.fill(HIST("Pair/before/lsmm/hDeltaEtaDeltaPhi"), dphi, deta); + + if (dimuoncuts.cfg_apply_detadphi_ls && std::pow(deta / dimuoncuts.cfg_min_deta_ls, 2) + std::pow(dphi / dimuoncuts.cfg_min_dphi_ls, 2) < 1.f) { + map_pfb[neg1.globalIndex()] |= 1 << static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS); + map_pfb[neg2.globalIndex()] |= 1 << static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS); + } + } // end of LS-- pairing + + } // end of collision loop + + for (const auto& track : tracks) { + // LOGF(info, "map_pfb[%d] = %d", track.globalIndex(), map_pfb[track.globalIndex()]); + pfb_derived(map_pfb[track.globalIndex()]); + } // end of track loop + + // check pfb. + for (const auto& collision : collisions) { + const float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; + if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + continue; + } + + auto posTracks_per_coll = posTracks->sliceByCached(o2::aod::emprimarymuon::emeventId, collision.globalIndex(), cache); + auto negTracks_per_coll = negTracks->sliceByCached(o2::aod::emprimarymuon::emeventId, collision.globalIndex(), cache); + + if (!fEMEventCut.IsSelected(collision)) { + continue; + } + + for (const auto& [pos, neg] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS + if (!fDimuonCut.IsSelectedTrack(pos) || !fDimuonCut.IsSelectedTrack(neg)) { + continue; + } + if (!map_best_match_globalmuon[pos.globalIndex()] || !map_best_match_globalmuon[neg.globalIndex()]) { + continue; + } + if (map_pfb[pos.globalIndex()] != 0 || map_pfb[neg.globalIndex()] != 0) { + continue; + } + + ROOT::Math::PtEtaPhiMVector v1(pos.pt(), pos.eta(), pos.phi(), o2::constants::physics::MassMuon); + ROOT::Math::PtEtaPhiMVector v2(neg.pt(), neg.eta(), neg.phi(), o2::constants::physics::MassMuon); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + float deta = pos.sign() * v1.Pt() > neg.sign() * v2.Pt() ? v1.Eta() - v2.Eta() : v2.Eta() - v1.Eta(); + float dphi = pos.sign() * v1.Pt() > neg.sign() * v2.Pt() ? v1.Phi() - v2.Phi() : v2.Phi() - v1.Phi(); + o2::math_utils::bringToPMPi(dphi); + + fRegistry.fill(HIST("Pair/after/uls/hMvsPt"), v12.M(), v12.Pt()); + fRegistry.fill(HIST("Pair/after/uls/hDeltaEtaDeltaPhi"), dphi, deta); + } + + for (const auto& [pos1, pos2] : combinations(CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { // LS++ + if (!fDimuonCut.IsSelectedTrack(pos1) || !fDimuonCut.IsSelectedTrack(pos2)) { + continue; + } + if (!map_best_match_globalmuon[pos1.globalIndex()] || !map_best_match_globalmuon[pos2.globalIndex()]) { + continue; + } + if (map_pfb[pos1.globalIndex()] != 0 || map_pfb[pos2.globalIndex()] != 0) { + continue; + } + + ROOT::Math::PtEtaPhiMVector v1(pos1.pt(), pos1.eta(), pos1.phi(), o2::constants::physics::MassMuon); + ROOT::Math::PtEtaPhiMVector v2(pos2.pt(), pos2.eta(), pos2.phi(), o2::constants::physics::MassMuon); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + float deta = pos1.sign() * v1.Pt() > pos2.sign() * v2.Pt() ? v1.Eta() - v2.Eta() : v2.Eta() - v1.Eta(); + float dphi = pos1.sign() * v1.Pt() > pos2.sign() * v2.Pt() ? v1.Phi() - v2.Phi() : v2.Phi() - v1.Phi(); + o2::math_utils::bringToPMPi(dphi); + + fRegistry.fill(HIST("Pair/after/lspp/hMvsPt"), v12.M(), v12.Pt()); + fRegistry.fill(HIST("Pair/after/lspp/hDeltaEtaDeltaPhi"), dphi, deta); + } + + for (const auto& [neg1, neg2] : combinations(CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { // LS-- + if (!fDimuonCut.IsSelectedTrack(neg1) || !fDimuonCut.IsSelectedTrack(neg2)) { + continue; + } + if (!map_best_match_globalmuon[neg1.globalIndex()] || !map_best_match_globalmuon[neg2.globalIndex()]) { + continue; + } + if (map_pfb[neg1.globalIndex()] != 0 || map_pfb[neg2.globalIndex()] != 0) { + continue; + } + + ROOT::Math::PtEtaPhiMVector v1(neg1.pt(), neg1.eta(), neg1.phi(), o2::constants::physics::MassMuon); + ROOT::Math::PtEtaPhiMVector v2(neg2.pt(), neg2.eta(), neg2.phi(), o2::constants::physics::MassMuon); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + float deta = neg1.sign() * v1.Pt() > neg2.sign() * v2.Pt() ? v1.Eta() - v2.Eta() : v2.Eta() - v1.Eta(); + float dphi = neg1.sign() * v1.Pt() > neg2.sign() * v2.Pt() ? v1.Phi() - v2.Phi() : v2.Phi() - v1.Phi(); + o2::math_utils::bringToPMPi(dphi); + + fRegistry.fill(HIST("Pair/after/lsmm/hMvsPt"), v12.M(), v12.Pt()); + fRegistry.fill(HIST("Pair/after/lsmm/hDeltaEtaDeltaPhi"), dphi, deta); + } + + } // end of collision loop + map_pfb.clear(); + map_best_match_globalmuon.clear(); + } // end of process + PROCESS_SWITCH(prefilterDimuon, processPFB, "produce prefilter bit", false); + + void processDummy(MyTracks const& tracks) + { + for (int i = 0; i < tracks.size(); i++) { + pfb_derived(0); + } + } + PROCESS_SWITCH(prefilterDimuon, processDummy, "dummy", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"prefilter-dimuon"})}; +} diff --git a/PWGEM/Dilepton/Tasks/checkMCPairTemplate.cxx b/PWGEM/Dilepton/Tasks/checkMCPairTemplate.cxx index 2c7ebf754c4..00e6ff121d0 100644 --- a/PWGEM/Dilepton/Tasks/checkMCPairTemplate.cxx +++ b/PWGEM/Dilepton/Tasks/checkMCPairTemplate.cxx @@ -266,6 +266,9 @@ struct checkMCPairTemplate { Configurable cfg_min_deta{"cfg_min_deta", 0.02, "min deta between 2 muons (elliptic cut)"}; Configurable cfg_min_dphi{"cfg_min_dphi", 0.02, "min dphi between 2 muons (elliptic cut)"}; + Configurable cfg_apply_cuts_from_prefilter_derived{"cfg_apply_cuts_from_prefilter_derived", false, "flag to apply prefilter set in derived data"}; + Configurable cfg_prefilter_bits_derived{"cfg_prefilter_bits_derived", 0, "prefilter bits [kNone : 0, kSplitOrMergedTrackLS : 4, kSplitOrMergedTrackULS : 8] Please consider logical-OR among them."}; // see PairUtilities.h + Configurable cfg_track_type{"cfg_track_type", 3, "muon track type [0: MFT-MCH-MID, 3: MCH-MID]"}; Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.2, "min pT for single track"}; Configurable cfg_max_pt_track{"cfg_max_pt_track", 1e+10, "max pT for single track"}; @@ -3101,6 +3104,10 @@ struct checkMCPairTemplate { Preslice perCollision_muon = aod::emprimarymuon::emeventId; Filter trackFilter_muon = o2::aod::fwdtrack::trackType == dimuoncuts.cfg_track_type; Filter ttcaFilter_muon = ifnode(dimuoncuts.enableTTCA.node(), o2::aod::emprimarymuon::isAssociatedToMPC == true || o2::aod::emprimarymuon::isAssociatedToMPC == false, o2::aod::emprimarymuon::isAssociatedToMPC == true); + Filter prefilter_derived_muon = ifnode(dimuoncuts.cfg_apply_cuts_from_prefilter_derived.node() && dimuoncuts.cfg_prefilter_bits_derived.node() >= static_cast(1), + ifnode((dimuoncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS))) > static_cast(0), (o2::aod::emprimarymuon::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS))) <= static_cast(0), true) && + ifnode((dimuoncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS))) > static_cast(0), (o2::aod::emprimarymuon::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS))) <= static_cast(0), true), + o2::aod::emprimarymuon::pfbderived >= static_cast(0)); Filter collisionFilter_centrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); Filter collisionFilter_numContrib = cfgNumContribMin <= o2::aod::collision::numContrib && o2::aod::collision::numContrib < cfgNumContribMax; diff --git a/PWGEM/Dilepton/Tasks/prefilterDielectron.cxx b/PWGEM/Dilepton/Tasks/prefilterDielectron.cxx index c384f47a749..e2292c07b07 100644 --- a/PWGEM/Dilepton/Tasks/prefilterDielectron.cxx +++ b/PWGEM/Dilepton/Tasks/prefilterDielectron.cxx @@ -129,8 +129,8 @@ struct prefilterDielectron { Configurable cfg_require_itsib_1st{"cfg_require_itsib_1st", false, "flag to require ITS ib 1st hit"}; Configurable cfg_min_its_cluster_size{"cfg_min_its_cluster_size", 0.f, "min ITS cluster size"}; Configurable cfg_max_its_cluster_size{"cfg_max_its_cluster_size", 16.f, "max ITS cluster size"}; - Configurable cfg_min_rel_diff_pin{"cfg_min_rel_diff_pin", -1e+10, "min rel. diff. between pin and ppv"}; - Configurable cfg_max_rel_diff_pin{"cfg_max_rel_diff_pin", +1e+10, "max rel. diff. between pin and ppv"}; + // Configurable cfg_min_rel_diff_pin{"cfg_min_rel_diff_pin", -1e+10, "min rel. diff. between pin and ppv"}; + // Configurable cfg_max_rel_diff_pin{"cfg_max_rel_diff_pin", +1e+10, "max rel. diff. between pin and ppv"}; // Configurable cfgRefR{"cfgRefR", 1.2, "reference R (in m) for extrapolation"}; // https://cds.cern.ch/record/1419204 Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DielectronCut::PIDSchemes::kTPChadrejORTOFreq), "pid scheme [kTOFreq : 0, kTPChadrej : 1, kTPChadrejORTOFreq : 2, kTPConly : 3, kTOFif : 4, kPIDML : 5, kTPChadrejORTOFreq_woTOFif : 6]"}; @@ -289,8 +289,9 @@ struct prefilterDielectron { fDielectronCut.RequireITSibAny(dielectroncuts.cfg_require_itsib_any); fDielectronCut.RequireITSib1st(dielectroncuts.cfg_require_itsib_1st); fDielectronCut.SetChi2TOF(0, dielectroncuts.cfg_max_chi2tof); - fDielectronCut.SetRelDiffPin(dielectroncuts.cfg_min_rel_diff_pin, dielectroncuts.cfg_max_rel_diff_pin); + // fDielectronCut.SetRelDiffPin(dielectroncuts.cfg_min_rel_diff_pin, dielectroncuts.cfg_max_rel_diff_pin); fDielectronCut.IncludeITSsa(dielectroncuts.includeITSsa, dielectroncuts.cfg_max_pt_track_ITSsa); + fDielectronCut.EnableTTCA(dielectroncuts.enableTTCA); // for eID fDielectronCut.SetPIDScheme(dielectroncuts.cfg_pid_scheme); diff --git a/PWGEM/Dilepton/Utils/EMTrackUtilities.h b/PWGEM/Dilepton/Utils/EMTrackUtilities.h index d2844c86517..54bc28eb012 100644 --- a/PWGEM/Dilepton/Utils/EMTrackUtilities.h +++ b/PWGEM/Dilepton/Utils/EMTrackUtilities.h @@ -22,6 +22,7 @@ #include #include #include +#include #include //_______________________________________________________________________ @@ -135,9 +136,11 @@ bool checkMFTHitMap(T const& track) return (clmap > 0); } //_______________________________________________________________________ -template +template bool isBestMatch(TTrack const& track, TCut const& cut, TTracks const& tracks) { + // find the best glboal muon without pt, eta cut (ie. without single track acceptance cut) to keep possibility for unfolding. + // this is only for global muons at forward rapidity // Be careful! tracks are fwdtracks per DF. if (track.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { @@ -150,7 +153,7 @@ bool isBestMatch(TTrack const& track, TCut const& cut, TTracks const& tracks) for (const auto& glmuonId : track.globalMuonsWithSameMFTIds()) { auto candidate = tracks.rawIteratorAt(glmuonId); if (candidate.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && candidate.emeventId() == track.emeventId() && candidate.mchtrackId() != track.mchtrackId()) { - if (cut.template IsSelectedTrack(candidate)) { + if (cut.template IsSelectedTrack(candidate)) { map_chi2MCHMFT[candidate.globalIndex()] = candidate.chi2MatchMCHMFT(); } } @@ -169,7 +172,7 @@ bool isBestMatch(TTrack const& track, TCut const& cut, TTracks const& tracks) for (const auto& glmuonId : track.globalMuonsWithSameMCHMIDIds()) { auto candidate = tracks.rawIteratorAt(glmuonId); if (candidate.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && candidate.emeventId() == track.emeventId() && candidate.mfttrackId() != track.mfttrackId()) { - if (cut.template IsSelectedTrack(candidate)) { + if (cut.template IsSelectedTrack(candidate)) { map_chi2MCHMFT[candidate.globalIndex()] = candidate.chi2MatchMCHMFT(); } } @@ -189,6 +192,16 @@ bool isBestMatch(TTrack const& track, TCut const& cut, TTracks const& tracks) } } //_______________________________________________________________________ +template +std::unordered_map findBestMatchMap(TTracks const& tracks, TCut const& cut) +{ + std::unordered_map map; + for (const auto& track : tracks) { + map[track.globalIndex()] = isBestMatch(track, cut, tracks); + } + return map; +} +//_______________________________________________________________________ // template // float sigmaPt(T const& track) // { From 8fe64004cb13dc49da186e3775dc4fe8b60d962b Mon Sep 17 00:00:00 2001 From: Marta Urioni <78807256+murioni@users.noreply.github.com> Date: Mon, 9 Mar 2026 23:13:27 +0100 Subject: [PATCH 228/347] [PWGLF] K*(892)0 PbPb analysis update (#15303) --- PWGLF/Tasks/Resonances/k892analysispbpb.cxx | 87 +++++++++++++++------ 1 file changed, 62 insertions(+), 25 deletions(-) diff --git a/PWGLF/Tasks/Resonances/k892analysispbpb.cxx b/PWGLF/Tasks/Resonances/k892analysispbpb.cxx index f0d2db3a2f7..93e1407027b 100644 --- a/PWGLF/Tasks/Resonances/k892analysispbpb.cxx +++ b/PWGLF/Tasks/Resonances/k892analysispbpb.cxx @@ -114,6 +114,7 @@ struct K892analysispbpb { Configurable cTPClowpt{"cTPClowpt", true, "apply TPC at low pt"}; Configurable cTOFonlyHighpt{"cTOFonlyHighpt", false, "apply TOF only at high pt"}; Configurable cTOFandTPCHighpt{"cTOFandTPCHighpt", false, "apply TOF and TPC at high pt"}; + Configurable circularCut{"circularCut", false, "apply TOF and TPC circular cut (applied only if cTOFandTPCHighpt is true)"}; // rotational bkg Configurable cfgNoRotations{"cfgNoRotations", 3, "Number of rotations per pair for rotbkg"}; @@ -409,10 +410,16 @@ struct K892analysispbpb { } else if (cTOFandTPCHighpt) { - if (candidate.hasTOF() && std::abs(candidate.tofNSigmaKa()) <= cMaxTOFnSigmaKaon && candidate.hasTPC() && std::abs(candidate.tpcNSigmaKa()) <= cMaxTPCnSigmaKaon) { // tof and tpc cut - return true; - } + if (circularCut) { + + if (candidate.hasTOF() && candidate.hasTPC() && std::sqrt(std::pow(candidate.tpcNSigmaKa(), 2) + std::pow(candidate.tofNSigmaKa(), 2)) <= cMaxTPCnSigmaKaon) // tof and tpc circular cut + return true; + } else { + + if (candidate.hasTOF() && std::abs(candidate.tofNSigmaKa()) <= cMaxTOFnSigmaKaon && candidate.hasTPC() && std::abs(candidate.tpcNSigmaKa()) <= cMaxTPCnSigmaKaon) // tof and tpc cut + return true; + } } else { if (candidate.hasTPC() && std::abs(candidate.tpcNSigmaKa()) <= cMaxTPCnSigmaKaon) { // tpc cut, tof when available @@ -447,8 +454,15 @@ struct K892analysispbpb { } else if (cTOFandTPCHighpt) { - if (candidate.hasTOF() && std::abs(candidate.tofNSigmaPi()) <= cMaxTOFnSigmaPion && candidate.hasTPC() && std::abs(candidate.tpcNSigmaPi()) <= cMaxTPCnSigmaPion) { // tof and tpc cut - return true; + if (circularCut) { + + if (candidate.hasTOF() && candidate.hasTPC() && std::sqrt(std::pow(candidate.tpcNSigmaPi(), 2) + std::pow(candidate.tofNSigmaPi(), 2)) <= cMaxTPCnSigmaPion) // tof and tpc circular cut + return true; + + } else { + + if (candidate.hasTOF() && std::abs(candidate.tofNSigmaPi()) <= cMaxTOFnSigmaPion && candidate.hasTPC() && std::abs(candidate.tpcNSigmaPi()) <= cMaxTPCnSigmaPion) // tof and tpc cut + return true; } } else { @@ -838,7 +852,7 @@ struct K892analysispbpb { Preslice trackPerCollision = aod::track::collisionId; - template + template void callFillHistoswithPartitions(const CollisionType& collision1, const TracksType&, const CollisionType& collision2, const TracksType&) { if (cTPClowpt) { @@ -846,39 +860,51 @@ struct K892analysispbpb { auto candPosPitpc = posPitpc->sliceByCached(aod::track::collisionId, collision1.globalIndex(), cache); auto candNegKatpc = negKatpc->sliceByCached(aod::track::collisionId, collision2.globalIndex(), cache); - fillHistograms(collision1, candPosPitpc, candNegKatpc); - //-+ auto candNegPitpc = negPitpc->sliceByCached(aod::track::collisionId, collision1.globalIndex(), cache); auto candPosKatpc = posKatpc->sliceByCached(aod::track::collisionId, collision2.globalIndex(), cache); - fillHistograms(collision1, candNegPitpc, candPosKatpc); + if constexpr (!isLikeSig) { + fillHistograms(collision1, candPosPitpc, candNegKatpc); + fillHistograms(collision1, candNegPitpc, candPosKatpc); + } else { + fillHistograms(collision1, candPosPitpc, candPosKatpc); + fillHistograms(collision1, candNegPitpc, candNegKatpc); + } } else if (cTOFandTPCHighpt) { //+- auto candPosPitoftpc = posPitoftpc->sliceByCached(aod::track::collisionId, collision1.globalIndex(), cache); auto candNegKatoftpc = negKatoftpc->sliceByCached(aod::track::collisionId, collision2.globalIndex(), cache); - fillHistograms(collision1, candPosPitoftpc, candNegKatoftpc); - //-+ auto candNegPitoftpc = negPitoftpc->sliceByCached(aod::track::collisionId, collision1.globalIndex(), cache); auto candPosKatoftpc = posKatoftpc->sliceByCached(aod::track::collisionId, collision2.globalIndex(), cache); - fillHistograms(collision1, candNegPitoftpc, candPosKatoftpc); + if constexpr (!isLikeSig) { + fillHistograms(collision1, candPosPitoftpc, candNegKatoftpc); + fillHistograms(collision1, candNegPitoftpc, candPosKatoftpc); + } else { + fillHistograms(collision1, candPosPitoftpc, candPosKatoftpc); + fillHistograms(collision1, candNegPitoftpc, candNegKatoftpc); + } } else if (cTOFonlyHighpt) { //+- auto candPosPitof = posPitof->sliceByCached(aod::track::collisionId, collision1.globalIndex(), cache); auto candNegKatof = negKatof->sliceByCached(aod::track::collisionId, collision2.globalIndex(), cache); - fillHistograms(collision1, candPosPitof, candNegKatof); - //-+ auto candNegPitof = negPitof->sliceByCached(aod::track::collisionId, collision1.globalIndex(), cache); auto candPosKatof = posKatof->sliceByCached(aod::track::collisionId, collision2.globalIndex(), cache); - fillHistograms(collision1, candNegPitof, candPosKatof); + if constexpr (!isLikeSig) { + fillHistograms(collision1, candPosPitof, candNegKatof); + fillHistograms(collision1, candNegPitof, candPosKatof); + } else { + fillHistograms(collision1, candPosPitof, candPosKatof); + fillHistograms(collision1, candNegPitof, candNegKatof); + } } } @@ -898,8 +924,8 @@ struct K892analysispbpb { histos.fill(HIST("TestME/hCollisionIndexSameE"), collision.globalIndex()); histos.fill(HIST("TestME/hnTrksSameE"), tracks.size()); } - // - callFillHistoswithPartitions(collision, tracks, collision, tracks); + // + callFillHistoswithPartitions(collision, tracks, collision, tracks); } PROCESS_SWITCH(K892analysispbpb, processSameEvent, "Process Same event", true); @@ -918,8 +944,8 @@ struct K892analysispbpb { histos.fill(HIST("TestME/hnTrksSameE"), tracks.size()); } - // - callFillHistoswithPartitions(collision, tracks, collision, tracks); + // + callFillHistoswithPartitions(collision, tracks, collision, tracks); } PROCESS_SWITCH(K892analysispbpb, processSameEventRun2, "Process Same event Run2", false); @@ -929,8 +955,8 @@ struct K892analysispbpb { if (!myEventSelections(collision)) return; - // - callFillHistoswithPartitions(collision, tracks, collision, tracks); + // + callFillHistoswithPartitions(collision, tracks, collision, tracks); } PROCESS_SWITCH(K892analysispbpb, processRotationalBkg, "Process Rotational Background", false); @@ -945,6 +971,17 @@ struct K892analysispbpb { } PROCESS_SWITCH(K892analysispbpb, processRotationalBkgMC, "Process Rotational Background MC", false); + void processLikeSign(EventCandidates::iterator const& collision, TrackCandidates const& tracks, aod::BCs const&) + { + + if (!myEventSelections(collision)) + return; + + // + callFillHistoswithPartitions(collision, tracks, collision, tracks); + } + PROCESS_SWITCH(K892analysispbpb, processLikeSign, "Process Like Sign", false); + void processMixedEvent(EventCandidates const& collisions, TrackCandidates const& tracks) { auto tracksTuple = std::make_tuple(tracks); @@ -966,8 +1003,8 @@ struct K892analysispbpb { histos.fill(HIST("TestME/hnTrksMixedE"), tracks1.size()); } - // - callFillHistoswithPartitions(collision1, tracks1, collision2, tracks2); + // + callFillHistoswithPartitions(collision1, tracks1, collision2, tracks2); } } PROCESS_SWITCH(K892analysispbpb, processMixedEvent, "Process Mixed event", true); @@ -991,8 +1028,8 @@ struct K892analysispbpb { histos.fill(HIST("TestME/hnTrksMixedE"), tracks1.size()); } - // - callFillHistoswithPartitions(collision1, tracks1, collision2, tracks2); + // + callFillHistoswithPartitions(collision1, tracks1, collision2, tracks2); } } PROCESS_SWITCH(K892analysispbpb, processMixedEventRun2, "Process Mixed event Run2", false); From 1a14e5db5c5e5129574037b1f967ed31644ad3f2 Mon Sep 17 00:00:00 2001 From: SCHOTTER Romain <47983209+romainschotter@users.noreply.github.com> Date: Tue, 10 Mar 2026 01:11:48 +0100 Subject: [PATCH 229/347] [PWGLF] Fix crash due to the update of the TPC drift manager (#15318) --- PWGLF/Utils/strangenessBuilderModule.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWGLF/Utils/strangenessBuilderModule.h b/PWGLF/Utils/strangenessBuilderModule.h index 7dc1bc57ace..06c2f969817 100644 --- a/PWGLF/Utils/strangenessBuilderModule.h +++ b/PWGLF/Utils/strangenessBuilderModule.h @@ -1371,7 +1371,7 @@ class BuilderModule pvX = collision.posX(); pvY = collision.posY(); pvZ = collision.posZ(); - if (v0BuilderOpts.moveTPCOnlyTracks && collision.has_bc()) { + if (v0BuilderOpts.generatePhotonCandidates && v0BuilderOpts.moveTPCOnlyTracks && collision.has_bc()) { mVDriftMgr.update(collision.template bc_as().timestamp()); } } From 45f8f3f43de5bbd6c5eb84c2ebd15f4852dccc40 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Tue, 10 Mar 2026 09:45:21 +0100 Subject: [PATCH 230/347] [Tutorial] add a test task for ccdb table (#15208) Co-authored-by: ALICE Action Bot --- Tutorials/CMakeLists.txt | 5 +++ Tutorials/src/ccdbtableaccess.cxx | 66 +++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 Tutorials/src/ccdbtableaccess.cxx diff --git a/Tutorials/CMakeLists.txt b/Tutorials/CMakeLists.txt index d99c71adc88..e99e99b9d9d 100644 --- a/Tutorials/CMakeLists.txt +++ b/Tutorials/CMakeLists.txt @@ -122,6 +122,11 @@ o2physics_add_dpl_workflow(ccdbaccess PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::CCDB O2::Framework O2Physics::AnalysisCore COMPONENT_NAME AnalysisTutorial) +o2physics_add_dpl_workflow(ccdbtableaccess + SOURCES src/ccdbtableaccess.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::CCDB O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME AnalysisTutorial) + o2physics_add_dpl_workflow(weak-decay-iteration SOURCES src/weakDecayIteration.cxx COMPONENT_NAME AnalysisTutorial) diff --git a/Tutorials/src/ccdbtableaccess.cxx b/Tutorials/src/ccdbtableaccess.cxx new file mode 100644 index 00000000000..52688bcebfc --- /dev/null +++ b/Tutorials/src/ccdbtableaccess.cxx @@ -0,0 +1,66 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +/// +/// \brief A tutorial task to retrieve objects from CCDB given a time stamp. +/// \author Daiki Sekihata +/// \since 2026-03-01 + +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsCalibration/MeanVertexObject.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +#include + +using namespace o2::framework; +using namespace o2::header; +using namespace o2; + +namespace o2::aod +{ +namespace testccdb +{ +DECLARE_SOA_CCDB_COLUMN(GRPMagField, grpMagField, o2::parameters::GRPMagField, "GLO/Config/GRPMagField"); //! +DECLARE_SOA_CCDB_COLUMN(MeanVertex, meanVertex, o2::dataformats::MeanVertexObject, "GLO/Calib/MeanVertex"); //! +} // namespace testccdb + +DECLARE_SOA_TIMESTAMPED_TABLE(MyCCDBObjects, aod::Timestamps, o2::aod::timestamp::Timestamp, 1, "MYCCDBOBJ", //! + testccdb::GRPMagField, testccdb::MeanVertex); +} // namespace o2::aod + +struct TestCCDBTable { + void init(o2::framework::InitContext&) {} + + using MyBCs = soa::Join; + + void process(MyBCs const& bcs) + { + int i = 0; + for (const auto& bc : bcs) { + if (i >= 5) { + return; + } + float l3current = bc.grpMagField().getL3Current(); + float zvtx = bc.meanVertex().getZ(); + LOGF(info, "bc.globalBC() = %llu, bc.timestamp() = %llu, L3 current = %f A, mean zvtx = %f cm", bc.globalBC(), bc.timestamp(), l3current, zvtx); + i++; + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc), + }; +} From 462efaf459f16e0c3b43edd79dc3e6ea0db45e26 Mon Sep 17 00:00:00 2001 From: "Cicero D. Muncinelli" <88810740+cmuncinelli@users.noreply.github.com> Date: Tue, 10 Mar 2026 06:23:59 -0300 Subject: [PATCH 231/347] [PWGLF] Fix derived data merging and optimizing workflow (#15321) Co-authored-by: ALICE Action Bot --- PWGLF/DataModel/lambdaJetPolarizationIons.h | 55 +-- .../Strangeness/lambdaJetPolarizationIons.cxx | 353 ++++++++++-------- .../lambdaJetPolarizationIonsDerived.cxx | 22 +- 3 files changed, 233 insertions(+), 197 deletions(-) diff --git a/PWGLF/DataModel/lambdaJetPolarizationIons.h b/PWGLF/DataModel/lambdaJetPolarizationIons.h index fef233231c0..fe1116ee525 100644 --- a/PWGLF/DataModel/lambdaJetPolarizationIons.h +++ b/PWGLF/DataModel/lambdaJetPolarizationIons.h @@ -17,32 +17,28 @@ // cicero.domenico.muncinelli@cern.ch // -#ifndef PWGLF_DATAMODEL_LAMBDAJETPOL_H_ -#define PWGLF_DATAMODEL_LAMBDAJETPOL_H_ +#ifndef PWGLF_DATAMODEL_LAMBDAJETPOLARIZATIONIONS_H_ +#define PWGLF_DATAMODEL_LAMBDAJETPOLARIZATIONIONS_H_ #include +#include + namespace o2::aod { namespace lambdajetpol { - -// DECLARE_SOA_COLUMN(CollIdx, collIdx, uint64_t); // Using a regular SOA column instead of an index column for convenience // Collision information: -DECLARE_SOA_INDEX_COLUMN(Collision, collision); DECLARE_SOA_COLUMN(CentFT0M, centFT0M, float); DECLARE_SOA_COLUMN(CentFT0C, centFT0C, float); -DECLARE_SOA_COLUMN(CentFT0CVariant1, centFT0CVariant1, float); -DECLARE_SOA_COLUMN(CentMFT, centMFT, float); -DECLARE_SOA_COLUMN(CentNGlobal, centNGlobal, float); DECLARE_SOA_COLUMN(CentFV0A, centFV0A, float); // Jet (and jet proxies) information: DECLARE_SOA_COLUMN(JetPt, jetPt, float); DECLARE_SOA_COLUMN(JetEta, jetEta, float); DECLARE_SOA_COLUMN(JetPhi, jetPhi, float); -DECLARE_SOA_COLUMN(JetNConstituents, jetNConstituents, uint64_t); +DECLARE_SOA_COLUMN(JetNConstituents, jetNConstituents, int); DECLARE_SOA_COLUMN(LeadParticlePt, leadParticlePt, float); DECLARE_SOA_COLUMN(LeadParticleEta, leadParticleEta, float); @@ -70,9 +66,9 @@ DECLARE_SOA_COLUMN(PosTPCNSigmaPi, posTPCNSigmaPi, float); DECLARE_SOA_COLUMN(NegTPCNSigmaPr, negTPCNSigmaPr, float); DECLARE_SOA_COLUMN(NegTPCNSigmaPi, negTPCNSigmaPi, float); -DECLARE_SOA_COLUMN(V0CosPA, v0cosPA, float); -DECLARE_SOA_COLUMN(V0Radius, v0radius, float); -DECLARE_SOA_COLUMN(DcaV0Daughters, dcaV0daughters, float); +DECLARE_SOA_COLUMN(V0CosPA, v0CosPA, float); +DECLARE_SOA_COLUMN(V0Radius, v0Radius, float); +DECLARE_SOA_COLUMN(DcaV0Daughters, dcaV0Daughters, float); DECLARE_SOA_COLUMN(DcaPosToPV, dcaPosToPV, float); DECLARE_SOA_COLUMN(DcaNegToPV, dcaNegToPV, float); @@ -90,32 +86,42 @@ DECLARE_SOA_DYNAMIC_COLUMN(LeadParticlePy, leadParticlePy, //! Leading particle [](float leadParticlePt, float leadParticlePhi) -> float { return leadParticlePt * std::sin(leadParticlePhi); }); DECLARE_SOA_DYNAMIC_COLUMN(LeadParticlePz, leadParticlePz, //! Leading particle pz [](float leadParticlePt, float leadParticleEta) -> float { return leadParticlePt * std::sinh(leadParticleEta); }); +} // namespace lambdajetpol + +DECLARE_SOA_TABLE(RingCollisions, "AOD", "RINGCOLLISIONS", + o2::soa::Index<>, // self-index: auto-assigned row number + lambdajetpol::CentFT0M, + lambdajetpol::CentFT0C, + lambdajetpol::CentFV0A); +namespace lambdajetpol +{ +DECLARE_SOA_INDEX_COLUMN(RingCollision, ringCollision); // Declare index after table is available } // namespace lambdajetpol -DECLARE_SOA_TABLE(RingJets, "AOD", "RINGJETS", // Renamed to follow convention on "s" at the end of table name. - lambdajetpol::CollisionId, // Changed to an internal O2 index, slightly different from usual o2::soa::Index<> though +DECLARE_SOA_TABLE(RingJets, "AOD", "RINGJETS", + lambdajetpol::RingCollisionId, // relational index -> RingCollisions lambdajetpol::JetPt, lambdajetpol::JetEta, lambdajetpol::JetPhi, lambdajetpol::JetNConstituents, - // Dynamic columns - lambdajetpol::JetPx, // Explicitly binding to static columns + // Dynamic columns (explicitly bound to their static inputs): + lambdajetpol::JetPx, lambdajetpol::JetPy, lambdajetpol::JetPz); -DECLARE_SOA_TABLE(RingLeadP, "AOD", "RINGLEADP", // Leading particle table - lambdajetpol::CollisionId, +DECLARE_SOA_TABLE(RingLeadP, "AOD", "RINGLEADP", + lambdajetpol::RingCollisionId, lambdajetpol::LeadParticlePt, lambdajetpol::LeadParticleEta, lambdajetpol::LeadParticlePhi, - // Dynamic columns + // Dynamic columns: lambdajetpol::LeadParticlePx, lambdajetpol::LeadParticlePy, lambdajetpol::LeadParticlePz); DECLARE_SOA_TABLE(RingLaV0s, "AOD", "RINGLAV0S", - lambdajetpol::CollisionId, + lambdajetpol::RingCollisionId, lambdajetpol::V0Pt, lambdajetpol::V0Eta, lambdajetpol::V0Phi, @@ -139,12 +145,7 @@ DECLARE_SOA_TABLE(RingLaV0s, "AOD", "RINGLAV0S", lambdajetpol::DcaPosToPV, lambdajetpol::DcaNegToPV); -DECLARE_SOA_TABLE(RingCollisions, "AOD", "RINGCOLLISIONS", - lambdajetpol::CollisionId, - lambdajetpol::CentFT0M, - lambdajetpol::CentFT0C, - lambdajetpol::CentFV0A); - +using RingCollision = RingCollisions::iterator; // Useful shorthand } // namespace o2::aod -#endif // PWGLF_DATAMODEL_LAMBDAJETPOL_H_ +#endif // PWGLF_DATAMODEL_LAMBDAJETPOLARIZATIONIONS_H_ diff --git a/PWGLF/TableProducer/Strangeness/lambdaJetPolarizationIons.cxx b/PWGLF/TableProducer/Strangeness/lambdaJetPolarizationIons.cxx index 14a1f4da3c4..7359008febf 100644 --- a/PWGLF/TableProducer/Strangeness/lambdaJetPolarizationIons.cxx +++ b/PWGLF/TableProducer/Strangeness/lambdaJetPolarizationIons.cxx @@ -17,7 +17,7 @@ // Jet Polarization Ions task // ================ // -// This code loops over a V0Cores table and produces standard derived +// This code loops over a V0Datas table and produces standard derived // data as output. In the post-processing stage, this analysis aims // to measure the formation of vorticity rings in HI collisions. // @@ -26,100 +26,93 @@ // cicero.domenico.muncinelli@cern.ch // -// O2 Framework -#include -#include -#include -#include -#include -#include +// Standard Library +#include +#include +#include +#include +#include +#include -// O2 CCDB / Conditions -#include "DataFormatsParameters/GRPMagField.h" -#include -#include +// PWGLF +#include "EventSelectionParams.h" +#include "RCTSelectionFlags.h" -// O2 Reconstruction Data Formats -#include +#include "PWGLF/DataModel/LFStrangenessPIDTables.h" +#include "PWGLF/DataModel/lambdaJetPolarizationIons.h" +// #include "Common/DataModel/PIDResponseTOF.h" // Maybe switch this around with LFStrangenessPIDTables? +#include "PWGLF/DataModel/LFStrangenessTables.h" // For V0TOFPIDs and NSigmas getters. Better for considering the daughters as coming from V0s instead of from PV: -// O2 Common Core -#include "Common/Core/RecoDecay.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/trackUtilities.h" +// // MC +// #include "Common/DataModel/CollisionAssociationTables.h" +// #include "Common/DataModel/McCollisionExtra.h" +// #include "PWGLF/DataModel/mcCentrality.h" -// O2 Common DataModel +// PWGJE +#include "PWGJE/Core/JetBkgSubUtils.h" +#include "PWGJE/Core/JetUtilities.h" + +// Common DataModel #include "Common/DataModel/Centrality.h" -#include "Common/DataModel/CollisionAssociationTables.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/McCollisionExtra.h" -#include "Common/DataModel/Multiplicity.h" // for pp +#include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponseTPC.h" -// For PID in raw data: -// #include "Common/DataModel/PIDResponseTOF.h" // Maybe switch this around with LFStrangenessPIDTables? -// #include "Common/DataModel/Qvectors.h" #include "Common/DataModel/TrackSelectionTables.h" -// PWGJE -#include "PWGJE/Core/JetBkgSubUtils.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/Core/JetUtilities.h" -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/DataModel/JetReducedData.h" +// Common Core +#include "Common/Core/RecoDecay.h" -// PWGLF -#include "PWGLF/DataModel/LFStrangenessPIDTables.h" -// For V0TOFPIDs and NSigmas getters. Better for considering the daughters as coming from V0s instead of from PV? -#include "PWGLF/DataModel/LFStrangenessTables.h" -#include "PWGLF/DataModel/lambdaJetPolarizationIons.h" -#include "PWGLF/DataModel/mcCentrality.h" +// Framework +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include -// External Libraries (FastJet) +// O2 subsystems +#include "Common/CCDB/ctpRateFetcher.h" + +#include +#include +#include + +// External libraries #include #include #include #include +#include #include -#include -#include -#include +#include -// ROOT Math -#include "Math/GenVector/Boost.h" -#include "Math/Vector3D.h" -#include "Math/Vector4D.h" - -// Standard Library -#include -#include -#include -#include +// ROOT math +#include +#include +#include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -using std::array; using namespace o2::aod::rctsel; ///// Aliases for joined tables /// Collisions: using SelCollisions = soa::Join; // Added PVMults to get MultNTracksPVeta1 as centrality estimator -using SelCollisionsSimple = soa::Join; // Simpler, for jets - /// V0s and Daughter tracks: -// using V0Candidates = soa::Join; -// using V0CandidatesSimple = soa::Join; // No TOF -/// To run in RAW data: -// using V0Candidates = aod::V0Datas; // TODO: possible quicker subscription for analysis that do not require TOF. using V0CandidatesWithTOF = soa::Join; // Tables created by o2-analysis-lf-strangenesstofpid -// using DauTracks = soa::Join; -// Actually used subscriptions (smaller memory usage): using DauTracks = soa::Join; - /// Jets: -using PseudoJetTracks = soa::Join; // Simpler tracks access. (Not using TracksIU and TracksCovIU. Did not use their info for now) - // , aod::pidTOFFullPi, aod::pidTOFFullKa, aod::pidTOFFullPr>; // Not using TOF right now due to some possible mismatches - +// using JetTracks = soa::Join; // Simpler tracks access, yet can't pass this and DauTracks as subscriptions simultaneously. /// MC: // using SimCollisions = soa::Join; // using DauTracksMC = soa::Join; @@ -658,7 +651,7 @@ struct lambdajetpolarizationions { addHypothesis(AntiLambda, analyseAntiLambda); auto hSelectionV0s = histos.add("GeneralQA/hSelectionV0s", "V0 #rightarrow #Lambda / #bar{#Lambda} selection flow", kTH1D, - {{(int)v0LambdaSelectionLabels.size(), -0.5, (double)v0LambdaSelectionLabels.size() - 0.5}}); + {{static_cast(v0LambdaSelectionLabels.size()), -0.5, static_cast(v0LambdaSelectionLabels.size()) - 0.5}}); for (size_t i = 0; i < v0LambdaSelectionLabels.size(); ++i) { auto lbl = v0LambdaSelectionLabels[i].label; if (!v0LambdaSelectionLabels[i].enabled) @@ -681,7 +674,7 @@ struct lambdajetpolarizationions { {"DCA_{xy} to PV (parametric)", pseudoJetCandidateTrackSelections.doDCAcuts.value}, }; auto hSelectionJetTracks = histos.add("GeneralQA/hSelectionJetTracks", "Charged pseudojet candidate selection flow", kTH1D, - {{(int)jetTrackSelectionLabels.size(), -0.5, (double)jetTrackSelectionLabels.size() - 0.5}}); + {{static_cast(jetTrackSelectionLabels.size()), -0.5, static_cast(jetTrackSelectionLabels.size()) - 0.5}}); for (size_t i = 0; i < jetTrackSelectionLabels.size(); ++i) { auto lbl = jetTrackSelectionLabels[i].label; if (!jetTrackSelectionLabels[i].enabled) @@ -778,7 +771,7 @@ struct lambdajetpolarizationions { if (analyseAntiLambda) { histos.add("hMassAntiLambda", "hMassAntiLambda", kTH1D, {axisConfigurations.axisLambdaMass}); histos.add("AntiLambda/hAntiLambdasPerEvent", "hAntiLambdasPerEvent", kTH1D, {{15, 0, 15}}); - }; + } if (analyseLambda && analyseAntiLambda) { histos.add("hAmbiguousLambdaCandidates", "hAmbiguousLambdaCandidates", kTH1D, {{1, 0, 1}}); histos.add("hAmbiguousPerEvent", "hAmbiguousPerEvent", kTH1D, {{15, 0, 15}}); @@ -870,6 +863,7 @@ struct lambdajetpolarizationions { histos.add("GeneralQA/h2dArmenterosFullSelected", "h2dArmenterosFullSelected", kTH2D, {axisConfigurations.axisAPAlpha, axisConfigurations.axisAPQt}); histos.add("GeneralQA/h2dArmenterosFullSelectedLambda", "h2dArmenterosFullSelectedLambda", kTH2D, {axisConfigurations.axisAPAlpha, axisConfigurations.axisAPQt}); histos.add("GeneralQA/h2dArmenterosFullSelectedAntiLambda", "h2dArmenterosFullSelectedAntiLambda", kTH2D, {axisConfigurations.axisAPAlpha, axisConfigurations.axisAPQt}); + histos.add("GeneralQA/h2dArmenterosFullSelectedNonAmbiguous", "h2dArmenterosFullSelectedNonAmbiguous", kTH2D, {axisConfigurations.axisAPAlpha, axisConfigurations.axisAPQt}); histos.add("GeneralQA/h2dArmenterosFullSelectedAmbiguous", "h2dArmenterosFullSelectedAmbiguous", kTH2D, {axisConfigurations.axisAPAlpha, axisConfigurations.axisAPQt}); // Jets histograms: @@ -987,9 +981,25 @@ struct lambdajetpolarizationions { HistogramRegistry* histos = nullptr; // Had to pass the histos group to this struct, as it was not visible to the members of this struct void resetForNewV0() { binValue = -1; } + // Advance to targetBinX, filling all intermediate bins. + // Use this for DISABLED cuts within a single hypothesis + // (shows pass-through count as a flat line, making it visually + // clear that the stage was not active). + // (Replaces N dummy fill() calls) + void fillUpTo(int targetBinX) + { + while (binValue < targetBinX) + histos->fill(HIST("GeneralQA/hSelectionV0s"), ++binValue); + } + + void advanceTo(int targetBinX) { binValue = targetBinX - 1; } // next fill() lands at targetBin. Needed to deal with early exits at isLambda vs isAntiLambda checks void fill() { histos->fill(HIST("GeneralQA/hSelectionV0s"), ++binValue); } // Hardcoded hSelectionV0s histogram, as it will not change. Increments before filling, by default }; - V0SelectionFlowCounter V0SelCounter{0, &histos}; + V0SelectionFlowCounter V0SelCounter{-1, &histos}; // Could initialize with any index (resetForNewV0 is always called for a new V0 anyways) + // Calculating some bins, for convenience: + int nGenericCuts = 31; // x=0 to x=30 + int nHypoCuts = 9; // per hypothesis (x=31..39 for Lambda) + int lambdaHypoEnd = nGenericCuts + nHypoCuts - 1; // x=39 // Minimal helper to fill hSelectionJetTracks, mirroring V0SelectionFlowCounter. // Reset once per track candidate, fill once per passed cut stage. @@ -999,7 +1009,7 @@ struct lambdajetpolarizationions { void resetForNewTrack() { binValue = -1; } void fill() { histos->fill(HIST("GeneralQA/hSelectionJetTracks"), ++binValue); } }; - JetTrackSelectionFlowCounter JetTrackSelCounter{0, &histos}; + JetTrackSelectionFlowCounter JetTrackSelCounter{-1, &histos}; // Short inlined helper to simplify QA inline void fillEventSelectionQA(int bin, float centrality) @@ -1237,6 +1247,9 @@ struct lambdajetpolarizationions { pseudoJetCandidateTrackSelections.dcaxyMaxTrackPar1 / std::pow(pt, pseudoJetCandidateTrackSelections.dcaxyMaxTrackPar2))) return false; JetTrackSelCounter.fill(); + } else { // Should fill counters an equal number of times to advance indices (future-proofing, but could do it by just advancing indices by hand in JetTrackSelectionFlowCounter) + JetTrackSelCounter.fill(); + JetTrackSelCounter.fill(); } return true; } @@ -1399,36 +1412,42 @@ struct lambdajetpolarizationions { return false; V0SelCounter.fill(); - // TOF PID in DeltaT (if TOF is not available, then uses the track. If is available, uses it. In this sense, TOF is optional) - // const bool posHasTOF = posTrackExtra.hasTOF(); // For the older version, which worked only for Lambdas - const bool protonHasTOF = protonTrack.hasTOF(); // Should work even without PIDResponseTOF.h, as it is a TracksExtra property - const bool pionHasTOF = pionTrack.hasTOF(); - - // Proton-like track - if (protonHasTOF && std::abs(Lambda_hypothesis ? v0.posTOFDeltaTLaPr() : v0.negTOFDeltaTLaPr()) > v0Selections.maxDeltaTimeProton) - return false; - V0SelCounter.fill(); - // Pion-like track - if (pionHasTOF && std::abs(Lambda_hypothesis ? v0.negTOFDeltaTLaPi() : v0.posTOFDeltaTLaPi()) > v0Selections.maxDeltaTimePion) - return false; - V0SelCounter.fill(); - - // TOF PID in NSigma (TODO: add asymmetric NSigma windows for purity tuning?) - // Proton-like track - if (protonHasTOF && std::fabs(v0.tofNSigmaLaPr()) > v0Selections.tofPidNsigmaCutLaPr) - return false; // (No need to select which candidate is which with the Lambda_hypothesis. Automatically done already!) - V0SelCounter.fill(); - // Pion-like track - if (pionHasTOF && std::fabs(v0.tofNSigmaLaPi()) > v0Selections.tofPidNsigmaCutLaPi) - return false; - V0SelCounter.fill(); + // Only do TOF checks when actually using TOF subscriptions: + // if (doprocessDataWithTOF) { + if constexpr (requires { v0.tofNSigmaLaPr(); }) { // Compile-time check is better in hot-loop + // TOF PID in DeltaT (if TOF is not available, then uses the track. If is available, uses it. In this sense, TOF is optional) + // const bool posHasTOF = posTrackExtra.hasTOF(); // For the older version, which worked only for Lambdas + const bool protonHasTOF = protonTrack.hasTOF(); // Should work even without PIDResponseTOF.h, as it is a TracksExtra property + const bool pionHasTOF = pionTrack.hasTOF(); - // (CAUTION!) You cannot use the getter for raw data's PIDResponseTOF.h instead of LFStrangenessPIDTables.h (as below) - // If you do use, TOF will just try to identify that track as a proton, instead of using the correct path length from the - // V0s PV-DCA and the such! In other words, it is a naive estimator of TOF PID, because it does not correct for the V0 - // mother's travel time and considers all tracks as if they came from the PV! - // if (protonHasTOF && std::fabs(protonTrack.tofNSigmaPr()) > v0Selections.tofPidNsigmaCutLaPr) return false; - // To properly use the LFStrangenessPIDTables version, you need to call o2-analysis-lf-strangenesstofpid too. + // Proton-like track + if (protonHasTOF && std::abs(Lambda_hypothesis ? v0.posTOFDeltaTLaPr() : v0.negTOFDeltaTLaPr()) > v0Selections.maxDeltaTimeProton) + return false; + V0SelCounter.fill(); + // Pion-like track + if (pionHasTOF && std::abs(Lambda_hypothesis ? v0.negTOFDeltaTLaPi() : v0.posTOFDeltaTLaPi()) > v0Selections.maxDeltaTimePion) + return false; + V0SelCounter.fill(); + + // TOF PID in NSigma (TODO: add asymmetric NSigma windows for purity tuning?) + // Proton-like track (notice usage of tofNSigmaLaPr vs tofNSigmaALaPr) + if (protonHasTOF && std::fabs(Lambda_hypothesis ? v0.tofNSigmaLaPr() : v0.tofNSigmaALaPr()) > v0Selections.tofPidNsigmaCutLaPr) + return false; // (No need to select which candidate is which with the Lambda_hypothesis. Automatically done already!) + V0SelCounter.fill(); + // Pion-like track + if (pionHasTOF && std::fabs(Lambda_hypothesis ? v0.tofNSigmaLaPi() : v0.tofNSigmaALaPi()) > v0Selections.tofPidNsigmaCutLaPi) + return false; + V0SelCounter.fill(); + + // (CAUTION!) You cannot use the getter for raw data's PIDResponseTOF.h instead of LFStrangenessPIDTables.h (as below) + // If you do use, TOF will just try to identify that track as a proton from the PV, instead of using the correct path + // length from the V0s PV-DCA and the such! In other words, it is a naive estimator of TOF PID, because it does not + // correct for the V0 mother's travel time and considers all tracks as if they came from the PV! + // if (protonHasTOF && std::fabs(protonTrack.tofNSigmaPr()) > v0Selections.tofPidNsigmaCutLaPr) return false; + // To properly use the LFStrangenessPIDTables version, you need to call o2-analysis-lf-strangenesstofpid too. + } else { // Should fill counters an equal number of times to advance indices + V0SelCounter.fillUpTo(V0SelCounter.binValue + 4); // Fills the 4 times "V0SelCounter.fill()" would be called + } // proper lifetime if (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassLambda0 > v0Selections.lambdaLifetimeCut) @@ -1462,20 +1481,9 @@ struct lambdajetpolarizationions { // else return -1; // AntiLambda // } - void processJetsData(SelCollisionsSimple::iterator const& collision, PseudoJetTracks const& tracks, aod::BCsWithTimestamps const& bcs) - { // Uses BCsWithTimestamps to get timestamps for rejectTPCsectorBoundary - float centrality = -1.0f; // Just a placeholder - - // For event QA the last two indices never change for NEv_withJets and NEv_withV0s - // (Not the best way to initialize this: runs once per collision! TODO: think of a better way to do it) - int lastBinEvSel = histos.get(HIST("hEventSelection"))->GetXaxis()->GetNbins(); - bool validJetAlreadyFound = false; // Do not fill Event QA more than once - - auto bc = bcs.iteratorAt(collision.bcId()); // Got the iteratorAt() idea from O2Physics/PWGUD/Core/UDHelpers.h - if (!isEventAccepted(collision, bc, centrality, false)) - return; // Uses return instead of continue, as there is no explicit loop here - const uint64_t collIdx = collision.globalIndex(); - + template + void jetsProcess(TJetTracks const& tracks, const int ringCollIdx, const float centrality) + { // Loop over reconstructed tracks: std::vector fjParticles; int leadingParticleIdx = -1; // Initialized as -1, but could leave it unitialized as well. We reject any invalid events where this could pose a problem (e.g., pT<=0) @@ -1505,15 +1513,16 @@ struct lambdajetpolarizationions { if (fjParticles.size() < 1) return; + int lastBinEvSel = histos.get(HIST("hEventSelection"))->GetXaxis()->GetNbins(); + auto const& leadingParticle = fjParticles[leadingParticleIdx]; if (leadingParticle.pt() > jetConfigurations.minLeadParticlePt) { // If not, leading particle is probably a bad proxy - tableLeadParticles(collIdx, leadingParticle.pt(), leadingParticle.eta(), leadingParticle.phi()); + tableLeadParticles(ringCollIdx, leadingParticle.pt(), leadingParticle.eta(), leadingParticle.phi()); } // Start jet clusterization: // Cluster particles using the anti-kt algorithm fastjet::JetDefinition jetDef(mapFJAlgorithm(jetConfigurations.jetAlgorithm), jetConfigurations.radiusJet, mapFJRecombScheme(jetConfigurations.jetRecombScheme)); - // std::vector jets_pt, jets_eta, jets_phi; // Not worth it to store 4-vectors: the tracks assume pion mass hypothesis, so energy and rapidity are not right. if (jetConfigurations.bkgSubtraction == kAreaBased) { fastjet::AreaDefinition areaDef(fastjet::active_area, fastjet::GhostedAreaSpec(jetConfigurations.GhostedAreaSpecRapidity)); fastjet::ClusterSequenceArea clustSeq(fjParticles, jetDef, areaDef); // Attributes an area for each pseudojet in the list @@ -1527,7 +1536,6 @@ struct lambdajetpolarizationions { int selectedJets = 0; fastjet::PseudoJet leadingJetSub; - // bool hasLeadingJet = false; // Not needed: if the event has any jet, that is the leading jet. Check is superseded by the selectedJets information float leadingJetPt = -1.f; for (const auto& jet : jets) { // Jet must be fully contained in the acceptance (0.9 for ITS+TPC barrel) @@ -1546,7 +1554,7 @@ struct lambdajetpolarizationions { selectedJets++; // Store jet: - tableJets(collIdx, + tableJets(ringCollIdx, jetMinusBkg.pt(), jetMinusBkg.eta(), // Using eta instead of rapidity jetMinusBkg.phi(), @@ -1563,9 +1571,8 @@ struct lambdajetpolarizationions { return; histos.fill(HIST("hEventsWithJet"), 0.5); // Another version of this counter, which is already integrated in the Event Selection flow: - if (doEventQA && !validJetAlreadyFound) + if (doEventQA) fillEventSelectionQA(lastBinEvSel - 1, centrality); // hasRingJet passes - validJetAlreadyFound = true; if (doJetKinematicsQA) { histos.fill(HIST("JetKinematicsQA/hLeadingJetPt"), leadingJetSub.pt()); @@ -1647,9 +1654,8 @@ struct lambdajetpolarizationions { return; histos.fill(HIST("hEventsWithJet"), 0.5); // Another version of this counter, which is already integrated in the Event Selection flow: - if (doEventQA && !validJetAlreadyFound) + if (doEventQA) fillEventSelectionQA(lastBinEvSel - 1, centrality); // hasRingJet passes - validJetAlreadyFound = true; const auto& leadingJet = jets[0]; for (const auto& jet : jets) { @@ -1658,7 +1664,7 @@ struct lambdajetpolarizationions { if (std::fabs(jet_eta) > (0.9f - jetConfigurations.radiusJet)) continue; - tableJets(collIdx, + tableJets(ringCollIdx, jet.pt(), jet_eta, // Using eta instead of rapidity jet.phi(), @@ -1735,10 +1741,9 @@ struct lambdajetpolarizationions { } } - // Had to include DauTracks in subscription, even though I don't loop in it, for the indices - // to resolve, avoiding " Exception while running: Index pointing to Tracks is not bound!" - // Added the compiler option [[maybe_unused]] to avoid triggering any warnings because of this - void processV0sData(SelCollisions::iterator const& collision, V0CandidatesWithTOF const& fullV0s, aod::BCsWithTimestamps const& bcs, [[maybe_unused]] DauTracks const& V0DauTracks) + // No longer use a separate JetTracks joined table -- it was mostly a subset of DauTracks + TracksIU (which was not used) + template + void dataProcess(TCollision const& collision, TV0Candidates const& V0s, TDaughterTracks const& V0DauTracks, aod::BCsWithTimestamps const& bcs) { float centrality = getCentrality(collision); // Strictly for QA. We save other types of centrality estimators in the derived data! @@ -1756,20 +1761,24 @@ struct lambdajetpolarizationions { if (doEventQA) fillCentralityProperties(collision, centrality); - const uint64_t collIdx = collision.globalIndex(); if (v0Selections.rejectTPCsectorBoundary) initCCDB(bc); // Substituted call from collision to bc for raw data // Fill event table: - tableCollisions(collIdx, - collision.centFT0M(), + tableCollisions(collision.centFT0M(), collision.centFT0C(), collision.centFV0A()); // (TODO: add InteractionRate info and other useful cuts for later on in the analysis?) + // Get the derived collision row index for this event: + const int ringCollIdx = tableCollisions.lastIndex(); + + // Call to jets process: + jetsProcess(V0DauTracks, ringCollIdx, centrality); // V0DauTracks takes the place of jetTracks now + uint NLambdas = 0; // Counting particles per event uint NAntiLambdas = 0; uint NAmbiguous = 0; - for (auto const& v0 : fullV0s) { + for (auto const& v0 : V0s) { V0SelCounter.resetForNewV0(); V0SelCounter.fill(); // Fill for all v0 candidates if (doArmenterosQA) @@ -1785,11 +1794,14 @@ struct lambdajetpolarizationions { bool isAntiLambda = false; if (analyseLambda) isLambda = passesLambdaLambdaBarHypothesis(v0, collision, true); - if (analyseAntiLambda) + if (analyseAntiLambda) { + if (analyseLambda) // We only need to advance when the Lambda hypothesis had an early exit on the counters + V0SelCounter.advanceTo(lambdaHypoEnd + 1); // sync to bin 41 (x=40 means bin 41, the first #bar{#Lambda} bin) isAntiLambda = passesLambdaLambdaBarHypothesis(v0, collision, false); + } if (!isLambda && !isAntiLambda) - continue; // Candidate is not considered to be a Lambda + continue; // Candidate is not considered to be a Lambda-like if (isLambda) NLambdas++; @@ -1803,6 +1815,10 @@ struct lambdajetpolarizationions { if (!isLambda && isAntiLambda) histos.fill(HIST("GeneralQA/h2dArmenterosFullSelectedAntiLambda"), v0.alpha(), v0.qtarm()); + // XOR check: + if (isLambda ^ isAntiLambda) + histos.fill(HIST("GeneralQA/h2dArmenterosFullSelectedNonAmbiguous"), v0.alpha(), v0.qtarm()); + // int lambdaIdx = -1; // No need to pass armenteros if (isLambda && isAntiLambda) { NAmbiguous++; @@ -1828,7 +1844,7 @@ struct lambdajetpolarizationions { auto const v0pt = v0.pt(); const auto posTrackExtra = v0.template posTrack_as(); const auto negTrackExtra = v0.template negTrack_as(); - tableV0s(collIdx, + tableV0s(ringCollIdx, v0pt, v0.eta(), v0.phi(), // Using eta instead of rapidity isLambda, isAntiLambda, v0.mLambda(), v0.mAntiLambda(), @@ -1912,19 +1928,21 @@ struct lambdajetpolarizationions { histos.fill(HIST("Lambda/h3dPosTPCsignalVsTrackPt"), centrality, v0.positivept(), posTrackExtra.tpcSignal()); histos.fill(HIST("Lambda/h3dNegTPCsignalVsTrackPt"), centrality, v0.negativept(), negTrackExtra.tpcSignal()); } - if (doTOFQA) { - histos.fill(HIST("Lambda/h3dPosNsigmaTOF"), centrality, v0pt, v0.tofNSigmaLaPr()); - histos.fill(HIST("Lambda/h3dNegNsigmaTOF"), centrality, v0pt, v0.tofNSigmaLaPi()); - histos.fill(HIST("Lambda/h3dPosTOFdeltaT"), centrality, v0pt, v0.posTOFDeltaTLaPr()); - histos.fill(HIST("Lambda/h3dNegTOFdeltaT"), centrality, v0pt, v0.negTOFDeltaTLaPi()); - histos.fill(HIST("Lambda/h3dPosNsigmaTOFvsTrackPtot"), centrality, v0.pfracpos() * v0.p(), v0.tofNSigmaLaPr()); - histos.fill(HIST("Lambda/h3dNegNsigmaTOFvsTrackPtot"), centrality, v0.pfracneg() * v0.p(), v0.tofNSigmaLaPi()); - histos.fill(HIST("Lambda/h3dPosTOFdeltaTvsTrackPtot"), centrality, v0.pfracpos() * v0.p(), v0.posTOFDeltaTLaPr()); - histos.fill(HIST("Lambda/h3dNegTOFdeltaTvsTrackPtot"), centrality, v0.pfracneg() * v0.p(), v0.negTOFDeltaTLaPi()); - histos.fill(HIST("Lambda/h3dPosNsigmaTOFvsTrackPt"), centrality, v0.positivept(), v0.tofNSigmaLaPr()); - histos.fill(HIST("Lambda/h3dNegNsigmaTOFvsTrackPt"), centrality, v0.negativept(), v0.tofNSigmaLaPi()); - histos.fill(HIST("Lambda/h3dPosTOFdeltaTvsTrackPt"), centrality, v0.positivept(), v0.posTOFDeltaTLaPr()); - histos.fill(HIST("Lambda/h3dNegTOFdeltaTvsTrackPt"), centrality, v0.negativept(), v0.negTOFDeltaTLaPi()); + if constexpr (requires { v0.tofNSigmaLaPr(); }) { + if (doTOFQA) { + histos.fill(HIST("Lambda/h3dPosNsigmaTOF"), centrality, v0pt, v0.tofNSigmaLaPr()); + histos.fill(HIST("Lambda/h3dNegNsigmaTOF"), centrality, v0pt, v0.tofNSigmaLaPi()); + histos.fill(HIST("Lambda/h3dPosTOFdeltaT"), centrality, v0pt, v0.posTOFDeltaTLaPr()); + histos.fill(HIST("Lambda/h3dNegTOFdeltaT"), centrality, v0pt, v0.negTOFDeltaTLaPi()); + histos.fill(HIST("Lambda/h3dPosNsigmaTOFvsTrackPtot"), centrality, v0.pfracpos() * v0.p(), v0.tofNSigmaLaPr()); + histos.fill(HIST("Lambda/h3dNegNsigmaTOFvsTrackPtot"), centrality, v0.pfracneg() * v0.p(), v0.tofNSigmaLaPi()); + histos.fill(HIST("Lambda/h3dPosTOFdeltaTvsTrackPtot"), centrality, v0.pfracpos() * v0.p(), v0.posTOFDeltaTLaPr()); + histos.fill(HIST("Lambda/h3dNegTOFdeltaTvsTrackPtot"), centrality, v0.pfracneg() * v0.p(), v0.negTOFDeltaTLaPi()); + histos.fill(HIST("Lambda/h3dPosNsigmaTOFvsTrackPt"), centrality, v0.positivept(), v0.tofNSigmaLaPr()); + histos.fill(HIST("Lambda/h3dNegNsigmaTOFvsTrackPt"), centrality, v0.negativept(), v0.tofNSigmaLaPi()); + histos.fill(HIST("Lambda/h3dPosTOFdeltaTvsTrackPt"), centrality, v0.positivept(), v0.posTOFDeltaTLaPr()); + histos.fill(HIST("Lambda/h3dNegTOFdeltaTvsTrackPt"), centrality, v0.negativept(), v0.negTOFDeltaTLaPi()); + } } if (doEtaPhiQA) { histos.fill(HIST("Lambda/h5dV0PhiVsEta"), centrality, v0pt, v0.mLambda(), v0.phi(), v0.eta()); @@ -1958,19 +1976,21 @@ struct lambdajetpolarizationions { histos.fill(HIST("AntiLambda/h3dPosTPCsignalVsTrackPt"), centrality, v0.positivept(), posTrackExtra.tpcSignal()); histos.fill(HIST("AntiLambda/h3dNegTPCsignalVsTrackPt"), centrality, v0.negativept(), negTrackExtra.tpcSignal()); } - if (doTOFQA) { - histos.fill(HIST("AntiLambda/h3dPosNsigmaTOF"), centrality, v0pt, v0.tofNSigmaALaPi()); - histos.fill(HIST("AntiLambda/h3dNegNsigmaTOF"), centrality, v0pt, v0.tofNSigmaALaPr()); - histos.fill(HIST("AntiLambda/h3dPosTOFdeltaT"), centrality, v0pt, v0.posTOFDeltaTLaPi()); - histos.fill(HIST("AntiLambda/h3dNegTOFdeltaT"), centrality, v0pt, v0.negTOFDeltaTLaPr()); - histos.fill(HIST("AntiLambda/h3dPosNsigmaTOFvsTrackPtot"), centrality, v0.pfracpos() * v0.p(), v0.tofNSigmaALaPi()); - histos.fill(HIST("AntiLambda/h3dNegNsigmaTOFvsTrackPtot"), centrality, v0.pfracneg() * v0.p(), v0.tofNSigmaALaPr()); - histos.fill(HIST("AntiLambda/h3dPosTOFdeltaTvsTrackPtot"), centrality, v0.pfracpos() * v0.p(), v0.posTOFDeltaTLaPi()); - histos.fill(HIST("AntiLambda/h3dNegTOFdeltaTvsTrackPtot"), centrality, v0.pfracneg() * v0.p(), v0.negTOFDeltaTLaPr()); - histos.fill(HIST("AntiLambda/h3dPosNsigmaTOFvsTrackPt"), centrality, v0.positivept(), v0.tofNSigmaALaPi()); - histos.fill(HIST("AntiLambda/h3dNegNsigmaTOFvsTrackPt"), centrality, v0.negativept(), v0.tofNSigmaALaPr()); - histos.fill(HIST("AntiLambda/h3dPosTOFdeltaTvsTrackPt"), centrality, v0.positivept(), v0.posTOFDeltaTLaPi()); - histos.fill(HIST("AntiLambda/h3dNegTOFdeltaTvsTrackPt"), centrality, v0.negativept(), v0.negTOFDeltaTLaPr()); + if constexpr (requires { v0.tofNSigmaLaPr(); }) { + if (doTOFQA) { + histos.fill(HIST("AntiLambda/h3dPosNsigmaTOF"), centrality, v0pt, v0.tofNSigmaALaPi()); + histos.fill(HIST("AntiLambda/h3dNegNsigmaTOF"), centrality, v0pt, v0.tofNSigmaALaPr()); + histos.fill(HIST("AntiLambda/h3dPosTOFdeltaT"), centrality, v0pt, v0.posTOFDeltaTLaPi()); + histos.fill(HIST("AntiLambda/h3dNegTOFdeltaT"), centrality, v0pt, v0.negTOFDeltaTLaPr()); + histos.fill(HIST("AntiLambda/h3dPosNsigmaTOFvsTrackPtot"), centrality, v0.pfracpos() * v0.p(), v0.tofNSigmaALaPi()); + histos.fill(HIST("AntiLambda/h3dNegNsigmaTOFvsTrackPtot"), centrality, v0.pfracneg() * v0.p(), v0.tofNSigmaALaPr()); + histos.fill(HIST("AntiLambda/h3dPosTOFdeltaTvsTrackPtot"), centrality, v0.pfracpos() * v0.p(), v0.posTOFDeltaTLaPi()); + histos.fill(HIST("AntiLambda/h3dNegTOFdeltaTvsTrackPtot"), centrality, v0.pfracneg() * v0.p(), v0.negTOFDeltaTLaPr()); + histos.fill(HIST("AntiLambda/h3dPosNsigmaTOFvsTrackPt"), centrality, v0.positivept(), v0.tofNSigmaALaPi()); + histos.fill(HIST("AntiLambda/h3dNegNsigmaTOFvsTrackPt"), centrality, v0.negativept(), v0.tofNSigmaALaPr()); + histos.fill(HIST("AntiLambda/h3dPosTOFdeltaTvsTrackPt"), centrality, v0.positivept(), v0.posTOFDeltaTLaPi()); + histos.fill(HIST("AntiLambda/h3dNegTOFdeltaTvsTrackPt"), centrality, v0.negativept(), v0.negTOFDeltaTLaPr()); + } } if (doEtaPhiQA) { histos.fill(HIST("AntiLambda/h5dV0PhiVsEta"), centrality, v0pt, v0.mAntiLambda(), v0.phi(), v0.eta()); @@ -1989,10 +2009,19 @@ struct lambdajetpolarizationions { histos.fill(HIST("AntiLambda/h2dNbrOfAntiLambdaVsCentrality"), centrality, NAntiLambdas); } - PROCESS_SWITCH(lambdajetpolarizationions, processJetsData, "Process jets and produce derived data in Run 3 Data", true); - PROCESS_SWITCH(lambdajetpolarizationions, processV0sData, "Process V0s and produce derived data in Run 3 Data", true); - // PROCESS_SWITCH(lambdajetpolarizationions, processJetsMC, "Process jets and produced derived data in Run 3 MC", true); - // PROCESS_SWITCH(lambdajetpolarizationions, processV0sMC, "Process V0s and produce derived data in Run 3 MC", true); + void processData(SelCollisions::iterator const& collision, aod::V0Datas const& V0s, DauTracks const& V0DauTracks, aod::BCsWithTimestamps const& bcs) + { + dataProcess(collision, V0s, V0DauTracks, bcs); // No longer need "JetTracks const& jetTracks" -- using DauTracks subscription instead + } + + void processDataWithTOF(SelCollisions::iterator const& collision, V0CandidatesWithTOF const& V0s, DauTracks const& V0DauTracks, aod::BCsWithTimestamps const& bcs) + { + dataProcess(collision, V0s, V0DauTracks, bcs); + } + + PROCESS_SWITCH(lambdajetpolarizationions, processData, "Process jets and V0s, produces derived data in Run 3 Data", true); + PROCESS_SWITCH(lambdajetpolarizationions, processDataWithTOF, "Process jets and V0s (with TOF), produces derived data in Run 3 Data", false); + // PROCESS_SWITCH(lambdajetpolarizationions, processMC, "Process jets and V0s, produces derived data in Run 3 MC", true); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGLF/Tasks/Strangeness/lambdaJetPolarizationIonsDerived.cxx b/PWGLF/Tasks/Strangeness/lambdaJetPolarizationIonsDerived.cxx index 3bff75a5a54..1681867e98b 100644 --- a/PWGLF/Tasks/Strangeness/lambdaJetPolarizationIonsDerived.cxx +++ b/PWGLF/Tasks/Strangeness/lambdaJetPolarizationIonsDerived.cxx @@ -30,27 +30,33 @@ // cicero.domenico.muncinelli@cern.ch // +#include +#include #include -#include #include #include -#include +#include +#include +#include +#include +#include #include // Custom data model: #include "PWGLF/DataModel/lambdaJetPolarizationIons.h" #include -#include +#include #include #include // #include // #include // New recommended format: -#include +#include // clang-tidy usually confuses this! Careful! #include #include +#include #include // For perpendicular jet direction QAs using namespace o2; @@ -424,14 +430,14 @@ struct lambdajetpolarizationionsderived { // Preslices for correct collisions association: // (TODO: test using custom grouping) - Preslice perColJets = o2::aod::lambdajetpol::collisionId; - Preslice perColV0s = o2::aod::lambdajetpol::collisionId; - Preslice perColLeadPs = o2::aod::lambdajetpol::collisionId; + Preslice perColJets = o2::aod::lambdajetpol::ringCollisionId; + Preslice perColV0s = o2::aod::lambdajetpol::ringCollisionId; + Preslice perColLeadPs = o2::aod::lambdajetpol::ringCollisionId; void processPolarizationData(o2::aod::RingCollisions const& collisions, o2::aod::RingJets const& jets, o2::aod::RingLaV0s const& v0s, o2::aod::RingLeadP const& leadPs) { for (auto const& collision : collisions) { - const auto collId = collision.collisionId(); + const auto collId = collision.globalIndex(); // The self-index accessor const double centrality = getCentrality(collision); // Slice jets, V0s and leading particle belonging to this collision: From 2f5843948b1f7e90041494b6be9fec1b003b3014 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Tue, 10 Mar 2026 11:40:52 +0100 Subject: [PATCH 232/347] [PWGEM/Dilepton] fix to clear clear map in prefilter (#15322) --- PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx index cfebeffe399..34c20624a9f 100644 --- a/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx +++ b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx @@ -1758,6 +1758,9 @@ struct prefilterPrimaryElectron { } // end of collision loop pfb_map.clear(); + mapTOFNsigmaReassociated.clear(); + mapTOFBetaReassociated.clear(); + mapProbaEl.clear(); } PROCESS_SWITCH(prefilterPrimaryElectron, processPrefilter_TTCA, "process prefilter with TTCA", false); @@ -1953,6 +1956,9 @@ struct prefilterPrimaryElectron { } // end of collision loop pfb_map.clear(); + mapTOFNsigmaReassociated.clear(); + mapTOFBetaReassociated.clear(); + mapProbaEl.clear(); } PROCESS_SWITCH(prefilterPrimaryElectron, processPrefilter_SA, "process prefilter standalone", false); From 8b4be34469978aa8c8281194f2cf7c979c959481 Mon Sep 17 00:00:00 2001 From: YazhenLin Date: Tue, 10 Mar 2026 20:35:11 +0800 Subject: [PATCH 233/347] [PWGDQ] Change the code dqEnergyCorrelator_direct.cxx for the energy correlator (#15325) --- PWGDQ/Tasks/dqEnergyCorrelator_direct.cxx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/PWGDQ/Tasks/dqEnergyCorrelator_direct.cxx b/PWGDQ/Tasks/dqEnergyCorrelator_direct.cxx index 4f6ef50524e..9f54bbe1980 100644 --- a/PWGDQ/Tasks/dqEnergyCorrelator_direct.cxx +++ b/PWGDQ/Tasks/dqEnergyCorrelator_direct.cxx @@ -50,6 +50,7 @@ #include #include #include +#include #include #include @@ -825,6 +826,9 @@ struct AnalysisEnergyCorrelator { continue; } } + if (std::abs(t2_raw.pdgCode()) != PDG_t::kPiPlus && std::abs(t2_raw.pdgCode()) != PDG_t::kKPlus && std::abs(t2_raw.pdgCode()) != PDG_t::kProton && std::abs(t2_raw.pdgCode()) != PDG_t::kElectron && std::abs(t2_raw.pdgCode()) != PDG_t::kMuonMinus) { + continue; + } if (t2_raw.pt() < fConfigDileptonHadronOptions.fConfigMCGenHadronPtMin.value || std::abs(t2_raw.eta()) > fConfigDileptonHadronOptions.fConfigMCGenHadronEtaAbs.value) { continue; } @@ -879,7 +883,6 @@ struct AnalysisEnergyCorrelator { } // loop over two event comibnations for (auto& [event1, event2] : selfCombinations(*fMixingBinning, fConfigEventOptions.fConfigMixingDepth.value, -1, events, events)) { - LOG(info) << "check1"; VarManager::ResetValues(0, VarManager::kNVars); VarManager::FillEvent(event1); if (!fEventCut->IsSelected(VarManager::fgValues)) { From be8b6fefc30dfa36b2d3ad485b904e85a32e8f06 Mon Sep 17 00:00:00 2001 From: Jan Fiete Date: Tue, 10 Mar 2026 15:22:54 +0100 Subject: [PATCH 234/347] [Common] avoid repeated CCDB calls (#15329) --- Common/Tasks/integrationTestCCDB.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Common/Tasks/integrationTestCCDB.cxx b/Common/Tasks/integrationTestCCDB.cxx index c7096d5774c..d1fe98d142c 100644 --- a/Common/Tasks/integrationTestCCDB.cxx +++ b/Common/Tasks/integrationTestCCDB.cxx @@ -103,12 +103,12 @@ struct integrationTestCCDB { lut = 0x0; const AxisSpec axis{1, 0.0f, 1.0f, ""}; histos.add("hDFs", "hDFs", HistType::kTH1F, {axis}); + + mRunNumber = 0; } void process(aod::BCsWithTimestamps const& bcs) { - mRunNumber = 0; - auto bc = bcs.begin(); // first element histos.fill(HIST("hDFs"), 0.5f); From e7193a61ff16d362f69d224b449ab55628e6bc0a Mon Sep 17 00:00:00 2001 From: choich08365 <157435123+choich08365@users.noreply.github.com> Date: Tue, 10 Mar 2026 23:30:54 +0900 Subject: [PATCH 235/347] =?UTF-8?q?[PWGJE]=20GNN=20b-jet=20histograms=20to?= =?UTF-8?q?=20investigate=20minor=20peak=20structure=20in=20Db,=20DCA=20c?= =?UTF-8?q?=E2=80=A6=20(#15328)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Changhwan Choi Co-authored-by: ALICE Action Bot --- PWGJE/Core/JetTaggingUtilities.h | 31 +++++++++++++- PWGJE/TableProducer/jetTaggerHF.cxx | 57 ++++++++++++++++++++----- PWGJE/Tasks/bjetTaggingGnn.cxx | 66 ++++++++++++++++++++++++++--- 3 files changed, 136 insertions(+), 18 deletions(-) diff --git a/PWGJE/Core/JetTaggingUtilities.h b/PWGJE/Core/JetTaggingUtilities.h index 4e685b41bf8..0e8b08c3fa2 100644 --- a/PWGJE/Core/JetTaggingUtilities.h +++ b/PWGJE/Core/JetTaggingUtilities.h @@ -1095,9 +1095,9 @@ void analyzeJetTrackInfo4MLnoSV(AnalysisJet const& analysisJet, AnyTracks const& std::sort(tracksParams.begin(), tracksParams.end(), compare); } -// Looping over the track info and putting them in the input vector (for GNN b-jet tagging) +// Looping over the track info and putting them in the input vector, with extra input features (for GNN b-jet tagging) template -void analyzeJetTrackInfo4GNN(AnalysisJet const& analysisJet, AnyTracks const& /*allTracks*/, AnyOriginalTracks const& /*origTracks*/, std::vector>& tracksParams, float trackPtMin = 0.5, float trackDcaXYMax = 10.0, float trackDcaZMax = 10.0, int64_t nMaxConstit = 40) +void analyzeJetTrackInfo4GNNwExtra(AnalysisJet const& analysisJet, AnyTracks const& /*allTracks*/, AnyOriginalTracks const& /*origTracks*/, std::vector>& tracksParams, float trackPtMin = 0.5, float trackDcaXYMax = 10.0, float trackDcaZMax = 10.0, int64_t nMaxConstit = 40) { for (const auto& constituent : analysisJet.template tracks_as()) { @@ -1124,6 +1124,33 @@ void analyzeJetTrackInfo4GNN(AnalysisJet const& analysisJet, AnyTracks const& /* } } +// Looping over the track info and putting them in the input vector (for GNN b-jet tagging) +template +void analyzeJetTrackInfo4GNN(AnalysisJet const& analysisJet, AnyTracks const& /*allTracks*/, std::vector>& tracksParams, float trackPtMin = 0.5, float trackDcaXYMax = 10.0, float trackDcaZMax = 10.0, int64_t nMaxConstit = 40) +{ + for (const auto& constituent : analysisJet.template tracks_as()) { + + if (constituent.pt() < trackPtMin || !trackAcceptanceWithDca(constituent, trackDcaXYMax, trackDcaZMax)) { + continue; + } + + int sign = getGeoSign(analysisJet, constituent); + + if (static_cast(tracksParams.size()) < nMaxConstit) { + tracksParams.emplace_back(std::vector{constituent.pt(), constituent.phi(), constituent.eta(), static_cast(constituent.sign()), std::abs(constituent.dcaXY()) * sign, constituent.sigmadcaXY(), std::abs(constituent.dcaZ()) * sign, constituent.sigmadcaZ()}); + } else { + // If there are more than nMaxConstit constituents in the jet, select only nMaxConstit constituents with the highest DCA_XY significance. + size_t minIdx = 0; + for (size_t i = 0; i < tracksParams.size(); ++i) { + if (tracksParams[i][4] / tracksParams[i][5] < tracksParams[minIdx][4] / tracksParams[minIdx][5]) + minIdx = i; + } + if (std::abs(constituent.dcaXY()) * sign / constituent.sigmadcaXY() > tracksParams[minIdx][4] / tracksParams[minIdx][5]) + tracksParams[minIdx] = std::vector{constituent.pt(), constituent.phi(), constituent.eta(), static_cast(constituent.sign()), std::abs(constituent.dcaXY()) * sign, constituent.sigmadcaXY(), std::abs(constituent.dcaZ()) * sign, constituent.sigmadcaZ()}; + } + } +} + // Discriminant value for GNN b-jet tagging template T getDb(const std::vector& logits, double fC = 0.018) diff --git a/PWGJE/TableProducer/jetTaggerHF.cxx b/PWGJE/TableProducer/jetTaggerHF.cxx index 90412b53207..6878544163a 100644 --- a/PWGJE/TableProducer/jetTaggerHF.cxx +++ b/PWGJE/TableProducer/jetTaggerHF.cxx @@ -277,7 +277,7 @@ struct JetTaggerHFTask { } } } - if (doprocessAlgorithmGNN) { + if (doprocessAlgorithmGNN || doprocessAlgorithmGNNwExtra) { if (jet.pt() >= jetpTMin) { float dbRange; if (scoreML[jet.globalIndex()] < dbMin) { @@ -513,7 +513,7 @@ struct JetTaggerHFTask { } } - if (doprocessAlgorithmML || doprocessAlgorithmGNN) { + if (doprocessAlgorithmML || doprocessAlgorithmGNN || doprocessAlgorithmGNNwExtra) { bMlResponse.configure(binsPtMl, cutsMl, cutDirMl, nClassesMl); if (loadModelsFromCCDB) { ccdbApi.init(ccdbUrl); @@ -525,7 +525,7 @@ struct JetTaggerHFTask { bMlResponse.init(); } - if (doprocessAlgorithmGNN) { + if (doprocessAlgorithmGNN || doprocessAlgorithmGNNwExtra) { tensorAlloc = o2::analysis::GNNBjetAllocator(nJetFeat.value, nTrkFeat.value, nClassesMl.value, nTrkOrigin.value, transformFeatureJetMean.value, transformFeatureJetStdev.value, transformFeatureTrkMean.value, transformFeatureTrkStdev.value, nJetConst, tfFuncTypeGNN.value); registry.add("h2_count_db", "#it{D}_{b} underflow/overflow;Jet flavour;#it{D}_{b} range", {HistType::kTH2F, {{4, 0., 4.}, {3, 0., 3.}}}); @@ -538,10 +538,10 @@ struct JetTaggerHFTask { h2CountDb->GetYaxis()->SetBinLabel(2, "in range"); h2CountDb->GetYaxis()->SetBinLabel(3, "overflow"); - registry.add("h_db_b", "#it{D}_{b} b-jet;#it{D}_{b}", {HistType::kTH1F, {{50, -10., 35.}}}); - registry.add("h_db_c", "#it{D}_{b} c-jet;#it{D}_{b}", {HistType::kTH1F, {{50, -10., 35.}}}); - registry.add("h_db_lf", "#it{D}_{b} lf-jet;#it{D}_{b}", {HistType::kTH1F, {{50, -10., 35.}}}); - registry.add("h2_pt_db", "#it{p}_{T} vs. #it{D}_{b};#it{p}_{T}^{ch jet} (GeV/#it{c}^{2});#it{D}_{b}", {HistType::kTH2F, {{100, 0., 200.}, {50, -10., 35.}}}); + registry.add("h_db_b", "#it{D}_{b} b-jet;#it{D}_{b}", {HistType::kTH1F, {{50, -20., 30.}}}); + registry.add("h_db_c", "#it{D}_{b} c-jet;#it{D}_{b}", {HistType::kTH1F, {{50, -20., 30.}}}); + registry.add("h_db_lf", "#it{D}_{b} lf-jet;#it{D}_{b}", {HistType::kTH1F, {{50, -20., 30.}}}); + registry.add("h2_pt_db", "#it{p}_{T} vs. #it{D}_{b};#it{p}_{T}^{ch jet} (GeV/#it{c}^{2});#it{D}_{b}", {HistType::kTH2F, {{100, 0., 200.}, {50, -20., 30.}}}); } } @@ -612,11 +612,40 @@ struct JetTaggerHFTask { } template - void analyzeJetAlgorithmGNN(AnyJets const& jets, AnyTracks const& tracks, AnyOriginalTracks const& origTracks) + void analyzeJetAlgorithmGNNwExtra(AnyJets const& jets, AnyTracks const& tracks, AnyOriginalTracks const& origTracks) { for (const auto& jet : jets) { std::vector> trkFeat; - jettaggingutilities::analyzeJetTrackInfo4GNN(jet, tracks, origTracks, trkFeat, trackPtMin, trackDcaXYMax, trackDcaZMax, nJetConst); + jettaggingutilities::analyzeJetTrackInfo4GNNwExtra(jet, tracks, origTracks, trkFeat, trackPtMin, trackDcaXYMax, trackDcaZMax, nJetConst); + + std::vector jetFeat{jet.pt(), jet.phi(), jet.eta(), jet.mass()}; + + if (trkFeat.size() > 0) { + std::vector feat; + std::vector gnnInput; + tensorAlloc.getGNNInput(jetFeat, trkFeat, feat, gnnInput); + + auto modelOutput = bMlResponse.getModelOutput(gnnInput, 0); + float db = jettaggingutilities::getDb(modelOutput, fC); + if (!std::isnan(db)) { + scoreML[jet.globalIndex()] = db; + } else { + scoreML[jet.globalIndex()] = 999.; + LOGF(debug, "doprocessAlgorithmGNNwExtra, Db is NaN (%d)", jet.globalIndex()); + } + } else { + scoreML[jet.globalIndex()] = -999.; + LOGF(debug, "doprocessAlgorithmGNNwExtra, trkFeat.size() <= 0 (%d)", jet.globalIndex()); + } + } + } + + template + void analyzeJetAlgorithmGNN(AnyJets const& jets, AnyTracks const& tracks) + { + for (const auto& jet : jets) { + std::vector> trkFeat; + jettaggingutilities::analyzeJetTrackInfo4GNN(jet, tracks, trkFeat, trackPtMin, trackDcaXYMax, trackDcaZMax, nJetConst); std::vector jetFeat{jet.pt(), jet.phi(), jet.eta(), jet.mass()}; @@ -684,9 +713,15 @@ struct JetTaggerHFTask { } PROCESS_SWITCH(JetTaggerHFTask, processAlgorithmMLnoSV, "Fill ML evaluation score for charged jets but without using SVs", false); - void processAlgorithmGNN(JetTable const& jets, JetTracksExt const& jtracks, OriginalTracks const& origTracks) + void processAlgorithmGNNwExtra(JetTable const& jets, JetTracksExt const& jtracks, OriginalTracks const& origTracks) + { + analyzeJetAlgorithmGNNwExtra(jets, jtracks, origTracks); + } + PROCESS_SWITCH(JetTaggerHFTask, processAlgorithmGNNwExtra, "Fill GNN evaluation score (D_b) for charged jets with extra input features", false); + + void processAlgorithmGNN(JetTable const& jets, JetTracksExt const& jtracks) { - analyzeJetAlgorithmGNN(jets, jtracks, origTracks); + analyzeJetAlgorithmGNN(jets, jtracks); } PROCESS_SWITCH(JetTaggerHFTask, processAlgorithmGNN, "Fill GNN evaluation score (D_b) for charged jets", false); diff --git a/PWGJE/Tasks/bjetTaggingGnn.cxx b/PWGJE/Tasks/bjetTaggingGnn.cxx index 27850fa3011..a11288129f5 100644 --- a/PWGJE/Tasks/bjetTaggingGnn.cxx +++ b/PWGJE/Tasks/bjetTaggingGnn.cxx @@ -15,12 +15,14 @@ /// \author Changhwan Choi , Pusan National University #include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetFindingUtilities.h" #include "PWGJE/Core/JetTaggingUtilities.h" #include "PWGJE/DataModel/Jet.h" #include "PWGJE/DataModel/JetReducedData.h" #include "PWGJE/DataModel/JetTagging.h" #include "Common/CCDB/TriggerAliases.h" +#include "Common/Core/RecoDecay.h" #include "Common/Core/Zorro.h" #include "Common/Core/ZorroSummary.h" #include "Common/DataModel/EventSelection.h" @@ -126,6 +128,7 @@ struct BjetTaggingGnn { Configurable pTHatExponent{"pTHatExponent", 6.0, "exponent of the event weight for the calculation of pTHat"}; // track level configurables + Configurable trackSelections{"trackSelections", "QualityTracks", "set track selections"}; Configurable trackPtMin{"trackPtMin", 0.15, "minimum track pT"}; Configurable trackPtMax{"trackPtMax", 1000.0, "maximum track pT"}; Configurable trackEtaMin{"trackEtaMin", -0.9, "minimum track eta"}; @@ -175,6 +178,8 @@ struct BjetTaggingGnn { std::vector eventSelectionBitsSelMC; std::vector eventSelectionBitsSel8; + int trackSelectionBits; + std::vector jetRadiiValues; void init(InitContext const&) @@ -186,6 +191,8 @@ struct BjetTaggingGnn { eventSelectionBitsSel8 = jetderiveddatautilities::initialiseEventSelectionBits("sel8"); eventSelectionBitsSelMC = jetderiveddatautilities::initialiseEventSelectionBits("selMC"); + trackSelectionBits = jetderiveddatautilities::initialiseTrackSelection(static_cast(trackSelections)); + if (doprocessDataJetsTrig) { zorroSummary.setObject(zorro.getZorroSummary()); } @@ -236,7 +243,7 @@ struct BjetTaggingGnn { const AxisSpec axisTrackpT{200, 0., 200., "#it{p}_{T} (GeV/#it{c})"}; const AxisSpec axisTrackpTFine{1000, 0., 10., "#it{p}_{T} (GeV/#it{c})"}; - const AxisSpec axisJetpT{200, 0., 200., "#it{p}_{T} (GeV/#it{c})"}; + const AxisSpec axisJetpT{250, 0., 250., "#it{p}_{T} (GeV/#it{c})"}; const AxisSpec axisJetEta{200, -0.8, 0.8, "#it{#eta}_{jet}"}; const AxisSpec axisDb{200, dbMin, dbMax, "#it{D}_{b}"}; const AxisSpec axisDbFine{dbNbins, dbMin, dbMax, "#it{D}_{b}"}; @@ -250,6 +257,7 @@ struct BjetTaggingGnn { registry.add("h_jetMass", "", {HistType::kTH1F, {axisJetMass}}); registry.add("h_Db", "", {HistType::kTH1F, {axisDbFine}}); registry.add("h2_jetpT_Db", "", {HistType::kTH2F, {axisJetpT, axisDb}}); + registry.add("h2_nTracks_Db", "", {HistType::kTH2F, {axisNTracks, axisDb}}); registry.add("h_gnnfeat_trackpT", "", {HistType::kTH1F, {{200, 0., 100., "#it{p}_{T} (GeV/#it{c})"}}}); registry.add("h_gnnfeat_trackPhi", "", {HistType::kTH1F, {{200, 0., 2. * M_PI, "#it{#phi}"}}}); @@ -278,6 +286,18 @@ struct BjetTaggingGnn { registry.add("h_partpT_matched_fine", "", {HistType::kTH1F, {axisTrackpTFine}}, callSumw2); registry.add("h_partpT", "", {HistType::kTH1F, {axisTrackpT}}, callSumw2); registry.add("h_partpT_fine", "", {HistType::kTH1F, {axisTrackpTFine}}, callSumw2); + registry.add("h_dcaXY_coll_matched", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_#it{xy}| (cm)"}}}, callSumw2); + registry.add("h_dcaXY_coll_matched_b", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_#it{xy}| (cm)"}}}, callSumw2); + registry.add("h_dcaXY_coll_matched_c", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_#it{xy}| (cm)"}}}, callSumw2); + registry.add("h_dcaXY_coll_matched_lf", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_#it{xy}| (cm)"}}}, callSumw2); + registry.add("h_dcaXY_coll_mismatched", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_#it{xy}| (cm)"}}}, callSumw2); + registry.add("h_dcaXY_npp", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_#it{xy}| (cm)"}}}, callSumw2); + registry.add("h_dcaZ_coll_matched", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_#it{z}| (cm)"}}}, callSumw2); + registry.add("h_dcaZ_coll_matched_b", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_#it{z}| (cm)"}}}, callSumw2); + registry.add("h_dcaZ_coll_matched_c", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_#it{z}| (cm)"}}}, callSumw2); + registry.add("h_dcaZ_coll_matched_lf", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_#it{z}| (cm)"}}}, callSumw2); + registry.add("h_dcaZ_coll_mismatched", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_#it{z}| (cm)"}}}, callSumw2); + registry.add("h_dcaZ_npp", "", {HistType::kTH1F, {{200, 0., 5., "|DCA_#it{z}| (cm)"}}}, callSumw2); } if (doprocessDataJetsSel || doprocessMCDJetsSel) { @@ -302,6 +322,9 @@ struct BjetTaggingGnn { registry.add("h2_jetpT_Db_b", "b-jet", {HistType::kTH2F, {axisJetpT, axisDb}}); registry.add("h2_jetpT_Db_c", "c-jet", {HistType::kTH2F, {axisJetpT, axisDb}}); registry.add("h2_jetpT_Db_lf", "lf-jet", {HistType::kTH2F, {axisJetpT, axisDb}}); + registry.add("h2_nTracks_Db_b", "b-jet", {HistType::kTH2F, {axisNTracks, axisDb}}); + registry.add("h2_nTracks_Db_c", "c-jet", {HistType::kTH2F, {axisNTracks, axisDb}}); + registry.add("h2_nTracks_Db_lf", "lf-jet", {HistType::kTH2F, {axisNTracks, axisDb}}); registry.add("h2_Response_DetjetpT_PartjetpT", "", {HistType::kTH2F, {axisJetpT, axisJetpT}}, callSumw2); registry.add("h2_Response_DetjetpT_PartjetpT_b", "b-jet", {HistType::kTH2F, {axisJetpT, axisJetpT}}, callSumw2); registry.add("h2_Response_DetjetpT_PartjetpT_c", "c-jet", {HistType::kTH2F, {axisJetpT, axisJetpT}}, callSumw2); @@ -513,6 +536,7 @@ struct BjetTaggingGnn { registry.fill(HIST("h_jetMass"), analysisJet.mass()); registry.fill(HIST("h_Db"), analysisJet.scoreML()); registry.fill(HIST("h2_jetpT_Db"), analysisJet.pt(), analysisJet.scoreML()); + registry.fill(HIST("h2_nTracks_Db"), nTracks, analysisJet.scoreML()); if (doDataDriven) { if (doDataDrivenExtra) { @@ -567,19 +591,23 @@ struct BjetTaggingGnn { registry.fill(HIST("h_jetMass"), analysisJet.mass(), weightEvt); registry.fill(HIST("h_Db"), analysisJet.scoreML(), weightEvt); registry.fill(HIST("h2_jetpT_Db"), analysisJet.pt(), analysisJet.scoreML(), weightEvt); + registry.fill(HIST("h2_nTracks_Db"), nTracks, analysisJet.scoreML(), weightEvt); if (jetFlavor == JetTaggingSpecies::beauty) { registry.fill(HIST("h_jetpT_b"), analysisJet.pt(), weightEvt); registry.fill(HIST("h_Db_b"), analysisJet.scoreML(), weightEvt); registry.fill(HIST("h2_jetpT_Db_b"), analysisJet.pt(), analysisJet.scoreML(), weightEvt); + registry.fill(HIST("h2_nTracks_Db_b"), nTracks, analysisJet.scoreML(), weightEvt); } else if (jetFlavor == JetTaggingSpecies::charm) { registry.fill(HIST("h_jetpT_c"), analysisJet.pt(), weightEvt); registry.fill(HIST("h_Db_c"), analysisJet.scoreML(), weightEvt); registry.fill(HIST("h2_jetpT_Db_c"), analysisJet.pt(), analysisJet.scoreML(), weightEvt); + registry.fill(HIST("h2_nTracks_Db_c"), nTracks, analysisJet.scoreML(), weightEvt); } else { registry.fill(HIST("h_jetpT_lf"), analysisJet.pt(), weightEvt); registry.fill(HIST("h_Db_lf"), analysisJet.scoreML(), weightEvt); registry.fill(HIST("h2_jetpT_Db_lf"), analysisJet.pt(), analysisJet.scoreML(), weightEvt); + registry.fill(HIST("h2_nTracks_Db_lf"), nTracks, analysisJet.scoreML(), weightEvt); if (jetFlavor == JetTaggingSpecies::none) { registry.fill(HIST("h2_jetpT_Db_lf_none"), analysisJet.pt(), analysisJet.scoreML(), weightEvt); } else { @@ -1061,7 +1089,7 @@ struct BjetTaggingGnn { bool matchedMcColl = collision.has_mcCollision() && std::fabs(collision.template mcCollision_as().posZ()) < vertexZCut; for (const auto& track : tracks) { - if (track.eta() <= trackEtaMin || track.eta() >= trackEtaMax) { + if (!jetderiveddatautilities::selectTrack(track, trackSelectionBits) || track.eta() <= trackEtaMin || track.eta() >= trackEtaMax) { continue; } registry.fill(HIST("h_trackpT"), track.pt(), weightEvt); @@ -1072,9 +1100,37 @@ struct BjetTaggingGnn { continue; } auto particle = track.template mcParticle_as(); - if (particle.isPhysicalPrimary() && particle.eta() > trackEtaMin && particle.eta() < trackEtaMax) { - registry.fill(HIST("h2_trackpT_partpT"), track.pt(), particle.pt(), weightEvt); - registry.fill(HIST("h_partpT_matched_fine"), particle.pt(), weightEvt); + if (particle.isPhysicalPrimary()) { + if (particle.eta() > trackEtaMin && particle.eta() < trackEtaMax) { + registry.fill(HIST("h2_trackpT_partpT"), track.pt(), particle.pt(), weightEvt); + registry.fill(HIST("h_partpT_matched_fine"), particle.pt(), weightEvt); + // Track association accuracy as a function of DCA + if (track.pt() >= trackPtMin) { + if (particle.mcCollisionId() == collision.mcCollisionId()) { + registry.fill(HIST("h_dcaXY_coll_matched"), std::fabs(track.dcaXY()), weightEvt); // Matched to particle from the same MC collision + registry.fill(HIST("h_dcaZ_coll_matched"), std::fabs(track.dcaZ()), weightEvt); + int origin = RecoDecay::getParticleOrigin(allParticles, particle, false); + if (origin == RecoDecay::OriginType::NonPrompt) { + registry.fill(HIST("h_dcaXY_coll_matched_b"), std::fabs(track.dcaXY()), weightEvt); + registry.fill(HIST("h_dcaZ_coll_matched_b"), std::fabs(track.dcaZ()), weightEvt); + } else if (origin == RecoDecay::OriginType::Prompt) { + registry.fill(HIST("h_dcaXY_coll_matched_c"), std::fabs(track.dcaXY()), weightEvt); + registry.fill(HIST("h_dcaZ_coll_matched_c"), std::fabs(track.dcaZ()), weightEvt); + } else { + registry.fill(HIST("h_dcaXY_coll_matched_lf"), std::fabs(track.dcaXY()), weightEvt); + registry.fill(HIST("h_dcaZ_coll_matched_lf"), std::fabs(track.dcaZ()), weightEvt); + } + } else { + registry.fill(HIST("h_dcaXY_coll_mismatched"), std::fabs(track.dcaXY()), weightEvt); // Matched to particle from a different MC collision + registry.fill(HIST("h_dcaZ_coll_mismatched"), std::fabs(track.dcaZ()), weightEvt); + } + } + } + } else { + if (particle.eta() > trackEtaMin && particle.eta() < trackEtaMax && track.pt() >= trackPtMin) { + registry.fill(HIST("h_dcaXY_npp"), std::fabs(track.dcaXY()), weightEvt); + registry.fill(HIST("h_dcaZ_npp"), std::fabs(track.dcaZ()), weightEvt); + } } } From dd1c62d6cc6288952a5ee7e911563a56b008cb45 Mon Sep 17 00:00:00 2001 From: AlexianL <123153896+AlexianL@users.noreply.github.com> Date: Tue, 10 Mar 2026 15:39:25 +0100 Subject: [PATCH 236/347] [PWGHF] taskFlow.cxx : solve issue with CorrelationContainer (#15279) --- PWGHF/HFC/Tasks/taskFlow.cxx | 87 ++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 43 deletions(-) diff --git a/PWGHF/HFC/Tasks/taskFlow.cxx b/PWGHF/HFC/Tasks/taskFlow.cxx index add129f9673..3591f8f3907 100644 --- a/PWGHF/HFC/Tasks/taskFlow.cxx +++ b/PWGHF/HFC/Tasks/taskFlow.cxx @@ -535,9 +535,10 @@ struct HfTaskFlow { std::vector const effAxis = {{configAxis.axisEtaEfficiency, "#eta"}, {configAxis.axisPtEfficiency, "p_{T} (GeV/c)"}, {configAxis.axisVertexEfficiency, "z-vtx (cm)"}}; - std::vector const userAxis = {{configAxis.axisSamples, "sampling"}}; - std::vector const hfUserAxis = {{configAxis.axisMass, "m_{inv} (GeV/c^{2})"}, - {configAxis.axisSamples, "sampling"}}; + std::vector const hfUserAxis = {{configAxis.axisMass, "m_{inv} (GeV/c^{2})"}}; + // std::vector const userAxis = {{configAxis.axisSamples, "sampling"}}; + // std::vector const hfUserAxis = {{configAxis.axisMass, "m_{inv} (GeV/c^{2})"}, + // {configAxis.axisSamples, "sampling"}}; // ========================= // Initialization of histograms and CorrelationContainers for TpcTpc cases @@ -546,8 +547,8 @@ struct HfTaskFlow { if (doprocessSameTpcTpcChCh) { addHistograms(); - sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, userAxis)); - mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, userAxis)); + sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, {})); + mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, {})); } if (doprocessSameTpcTpcD0Ch) { @@ -572,8 +573,8 @@ struct HfTaskFlow { addHistograms(); addMftHistograms(); - sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, userAxis)); - mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, userAxis)); + sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, {})); + mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, {})); } if (doprocessSameTpcMftD0Ch || doprocessSameTpcMftD0ChReassociated) { @@ -599,8 +600,8 @@ struct HfTaskFlow { if (doprocessSameTpcFv0aChCh) { addHistograms(); - sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, userAxis)); - mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, userAxis)); + sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, {})); + mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, {})); } if (doprocessSameTpcFv0aD0Ch) { @@ -626,8 +627,8 @@ struct HfTaskFlow { addHistograms(); addMftHistograms(); - sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, userAxis)); - mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, userAxis)); + sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, {})); + mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, {})); } // ========================= @@ -639,8 +640,8 @@ struct HfTaskFlow { registry.add("Data/FT0Amp", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); registry.add("Data/FT0AmpCorr", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); - sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, userAxis)); - mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, userAxis)); + sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, {})); + mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, {})); } if (doprocessSameTpcFt0aD0Ch) { @@ -671,8 +672,8 @@ struct HfTaskFlow { registry.add("Data/FT0Amp", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); registry.add("Data/FT0AmpCorr", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); - sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, userAxis)); - mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, userAxis)); + sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, {})); + mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, {})); } // ========================= @@ -684,8 +685,8 @@ struct HfTaskFlow { registry.add("Data/FT0Amp", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); registry.add("Data/FT0AmpCorr", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); - sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, userAxis)); - mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, userAxis)); + sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, {})); + mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, {})); } if (doprocessSameTpcFt0cD0Ch) { @@ -715,8 +716,8 @@ struct HfTaskFlow { registry.add("Data/FT0Amp", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); registry.add("Data/FT0AmpCorr", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); - sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, userAxis)); - mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, userAxis)); + sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, {})); + mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, {})); } } // End of init() function @@ -1156,7 +1157,7 @@ struct HfTaskFlow { auto triggerWeight = 1; auto associatedWeight = 1; auto loopCounter = 0; // To avoid filling associated tracks QA many times, I fill it only for the first trigger track of the collision - int sampleIndex = gRandom->Uniform(0, configTask.nSamples); + // int sampleIndex = gRandom->Uniform(0, configTask.nSamples); // TRIGGER PARTICLE for (const auto& track1 : tracks1) { @@ -1192,9 +1193,9 @@ struct HfTaskFlow { // fill single-track distributions if (!fillingHFcontainer) { // if not HF-h case - target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, sampleIndex, triggerWeight); + target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, triggerWeight); } else { - target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, invmass, sampleIndex, triggerWeight); + target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, invmass, triggerWeight); } // FILL QA PLOTS for trigger particle @@ -1319,10 +1320,10 @@ struct HfTaskFlow { if (!fillingHFcontainer) { // fill pair correlations - target->getPairHist()->Fill(step, sampleIndex, eta1 - eta2, pt2, pt1, multiplicity, deltaPhi, posZ, + target->getPairHist()->Fill(step, eta1 - eta2, pt2, pt1, multiplicity, deltaPhi, posZ, triggerWeight * associatedWeight); } else { - target->getPairHist()->Fill(step, sampleIndex, eta1 - eta2, pt2, pt1, multiplicity, deltaPhi, posZ, invmass, + target->getPairHist()->Fill(step, eta1 - eta2, pt2, pt1, multiplicity, deltaPhi, posZ, invmass, triggerWeight * associatedWeight); } @@ -1362,7 +1363,7 @@ struct HfTaskFlow { auto triggerWeight = 1; auto associatedWeight = 1; auto loopCounter = 0; // To avoid filling associated tracks QA many times, I fill it only for the first trigger track of the collision - int sampleIndex = gRandom->Uniform(0, configTask.nSamples); + // int sampleIndex = gRandom->Uniform(0, configTask.nSamples); // TRIGGER PARTICLE for (const auto& track1 : tracks1) { @@ -1394,9 +1395,9 @@ struct HfTaskFlow { // fill single-track distributions if (!fillingHFcontainer) { // if not HF-h case - target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, sampleIndex, triggerWeight); + target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, triggerWeight); } else { - target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, invmass, sampleIndex, triggerWeight); + target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, invmass, triggerWeight); } // FILL QA PLOTS for trigger particle @@ -1487,10 +1488,10 @@ struct HfTaskFlow { deltaPhi = RecoDecay::constrainAngle(deltaPhi, -PIHalf); if (!fillingHFcontainer) { - target->getPairHist()->Fill(step, sampleIndex, eta1 - eta2, pt2, pt1, multiplicity, deltaPhi, posZ, + target->getPairHist()->Fill(step, eta1 - eta2, pt2, pt1, multiplicity, deltaPhi, posZ, triggerWeight * associatedWeight); } else { - target->getPairHist()->Fill(step, sampleIndex, eta1 - eta2, pt2, pt1, multiplicity, deltaPhi, posZ, invmass, + target->getPairHist()->Fill(step, eta1 - eta2, pt2, pt1, multiplicity, deltaPhi, posZ, invmass, triggerWeight * associatedWeight); } @@ -1519,7 +1520,7 @@ struct HfTaskFlow { auto triggerWeight = 1; auto associatedWeight = 1; auto loopCounter = 0; // To avoid filling associated tracks QA many times, I fill it only for the first trigger track of the collision - int sampleIndex = gRandom->Uniform(0, configTask.nSamples); + // int sampleIndex = gRandom->Uniform(0, configTask.nSamples); // TRIGGER PARTICLE for (auto const& track1 : tracks1) { @@ -1558,9 +1559,9 @@ struct HfTaskFlow { // fill single-track distributions if (!fillingHFcontainer) { // if not HF-h case - target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, sampleIndex, triggerWeight); + target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, triggerWeight); } else { - target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, invmass, sampleIndex, triggerWeight); + target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, invmass, triggerWeight); } // FILL QA PLOTS for trigger particle @@ -1620,10 +1621,10 @@ struct HfTaskFlow { deltaPhi = RecoDecay::constrainAngle(deltaPhi, -PIHalf); // set range of delta phi in (-pi/2 , 3/2*pi) if (!fillingHFcontainer) { - target->getPairHist()->Fill(step, sampleIndex, eta1 - eta2, pt1, pt1, multiplicity, deltaPhi, posZ, + target->getPairHist()->Fill(step, eta1 - eta2, pt1, pt1, multiplicity, deltaPhi, posZ, triggerWeight * associatedWeight); } else { - target->getPairHist()->Fill(step, sampleIndex, eta1 - eta2, pt1, pt1, multiplicity, deltaPhi, posZ, invmass, + target->getPairHist()->Fill(step, eta1 - eta2, pt1, pt1, multiplicity, deltaPhi, posZ, invmass, triggerWeight * associatedWeight); } @@ -1668,10 +1669,10 @@ struct HfTaskFlow { deltaPhi = RecoDecay::constrainAngle(deltaPhi, -PIHalf); // set range of delta phi in (-pi/2 , 3/2*pi) if (!fillingHFcontainer) { - target->getPairHist()->Fill(step, sampleIndex, eta1 - eta2, pt1, pt1, multiplicity, deltaPhi, posZ, + target->getPairHist()->Fill(step, eta1 - eta2, pt1, pt1, multiplicity, deltaPhi, posZ, amplitude * triggerWeight * associatedWeight); } else { - target->getPairHist()->Fill(step, sampleIndex, eta1 - eta2, pt1, pt1, multiplicity, deltaPhi, posZ, invmass, + target->getPairHist()->Fill(step, eta1 - eta2, pt1, pt1, multiplicity, deltaPhi, posZ, invmass, amplitude * triggerWeight * associatedWeight); } @@ -1719,7 +1720,7 @@ struct HfTaskFlow { auto triggerWeight = 1; auto associatedWeight = 1; auto loopCounter = 0; // To avoid filling associated tracks QA many times, I fill it only for the first trigger track of the collision - int sampleIndex = gRandom->Uniform(0, configTask.nSamples); + // int sampleIndex = gRandom->Uniform(0, configTask.nSamples); // TRIGGER PARTICLE for (auto const& track1 : tracks1) { @@ -1742,7 +1743,7 @@ struct HfTaskFlow { float phi1 = reassociatedMftTrack.phi(); o2::math_utils::bringTo02Pi(phi1); - target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, sampleIndex, triggerWeight); + target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, triggerWeight); // FILL QA PLOTS for trigger particle if (sameEvent && (step == CorrelationContainer::kCFStepReconstructed)) { @@ -1766,7 +1767,7 @@ struct HfTaskFlow { float deltaPhi = phi1 - phi2; deltaPhi = RecoDecay::constrainAngle(deltaPhi, -PIHalf); // set range of delta phi in (-pi/2 , 3/2*pi) - target->getPairHist()->Fill(step, sampleIndex, eta1 - eta2, pt1, pt1, multiplicity, deltaPhi, posZ, + target->getPairHist()->Fill(step, eta1 - eta2, pt1, pt1, multiplicity, deltaPhi, posZ, triggerWeight * associatedWeight); // FILL QA PLOTS for associated particle @@ -1799,7 +1800,7 @@ struct HfTaskFlow { float deltaPhi = phi1 - phi2; deltaPhi = RecoDecay::constrainAngle(deltaPhi, -PIHalf); // set range of delta phi in (-pi/2 , 3/2*pi) - target->getPairHist()->Fill(step, sampleIndex, eta1 - eta2, pt1, pt1, multiplicity, deltaPhi, posZ, + target->getPairHist()->Fill(step, eta1 - eta2, pt1, pt1, multiplicity, deltaPhi, posZ, amplitude * triggerWeight * associatedWeight); // FILL QA PLOTS for associated particle @@ -1821,7 +1822,7 @@ struct HfTaskFlow { auto triggerWeight = 1; auto associatedWeight = 1; auto loopCounter = 0; // To avoid filling associated tracks QA many times, I fill it only for the first trigger track of the collision - int sampleIndex = gRandom->Uniform(0, configTask.nSamples); + // int sampleIndex = gRandom->Uniform(0, configTask.nSamples); // TRIGGER PARTICLE FROM FT0A for (std::size_t indexChannelA = 0; indexChannelA < ft0as.channelA().size(); indexChannelA++) { @@ -1832,7 +1833,7 @@ struct HfTaskFlow { auto phiA = getPhiFT0(channelIdA, isFT0A); auto etaA = getEtaFT0(channelIdA, isFT0A); - target->getTriggerHist()->Fill(step, 0.f, multiplicity, posZ, sampleIndex, amplitude * triggerWeight); + target->getTriggerHist()->Fill(step, 0.f, multiplicity, posZ, amplitude * triggerWeight); if (sameEvent && (step == CorrelationContainer::kCFStepReconstructed)) { fillTriggerQa(multiplicity, etaA, phiA, 0.f); @@ -1848,7 +1849,7 @@ struct HfTaskFlow { auto etaC = getEtaFT0(channelIdC, isFT0C); float deltaPhi = RecoDecay::constrainAngle(phiA - phiC, -PIHalf); - target->getPairHist()->Fill(step, sampleIndex, etaA - etaC, 0.f, 0.f, multiplicity, deltaPhi, posZ, + target->getPairHist()->Fill(step, etaA - etaC, 0.f, 0.f, multiplicity, deltaPhi, posZ, amplitude * triggerWeight * associatedWeight); if (sameEvent && (loopCounter == 1) && (step == CorrelationContainer::kCFStepReconstructed)) { From a463f09841aadb75838d6012ffc3c5776cfe8655 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Tue, 10 Mar 2026 15:51:13 +0100 Subject: [PATCH 237/347] [PWGEM/Dilepton] update matchingMFT.cxx (#15330) Co-authored-by: ALICE Action Bot --- PWGEM/Dilepton/Tasks/matchingMFT.cxx | 196 ++++++++++++++++++--------- 1 file changed, 135 insertions(+), 61 deletions(-) diff --git a/PWGEM/Dilepton/Tasks/matchingMFT.cxx b/PWGEM/Dilepton/Tasks/matchingMFT.cxx index 48db3215bfc..ca2f912594e 100644 --- a/PWGEM/Dilepton/Tasks/matchingMFT.cxx +++ b/PWGEM/Dilepton/Tasks/matchingMFT.cxx @@ -16,7 +16,6 @@ #include "TableHelper.h" #include "Common/CCDB/RCTSelectionFlags.h" -#include "Common/Core/RecoDecay.h" #include "Common/Core/fwdtrackUtilities.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/CollisionAssociationTables.h" @@ -52,7 +51,7 @@ using namespace o2::constants::physics; using namespace o2::aod::fwdtrackutils; struct matchingMFT { - using MyCollisions = soa::Join; + using MyCollisions = soa::Join; using MyFwdTracks = soa::Join; using MyMFTTracks = soa::Join; @@ -97,17 +96,44 @@ struct matchingMFT { Configurable matchingZ{"matchingZ", -77.5, "z position where matching is performed"}; Configurable cfgApplyPreselectionInBestMatch{"cfgApplyPreselectionInBestMatch", false, "flag to apply preselection in find best match function"}; - Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; - Configurable cfgCentMin{"cfgCentMin", -1.f, "min. centrality"}; - Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; - Configurable cfgZvtxMin{"cfgZvtxMin", -10.f, "min. Zvtx"}; - Configurable cfgZvtxMax{"cfgZvtxMax", 10.f, "max. Zvtx"}; - - // for RCT - Configurable cfgRequireGoodRCT{"cfgRequireGoodRCT", false, "require good detector flag in run condtion table"}; - Configurable cfgRCTLabel{"cfgRCTLabel", "CBT_muon_glo", "select 1 [CBT_muon, CBT_muon_glo] see O2Physics/Common/CCDB/RCTSelectionFlags.h"}; - Configurable cfgCheckZDC{"cfgCheckZDC", false, "set ZDC flag for PbPb"}; - Configurable cfgTreatLimitedAcceptanceAsBad{"cfgTreatLimitedAcceptanceAsBad", false, "reject all events where the detectors relevant for the specified Runlist are flagged as LimitedAcceptance"}; + struct : ConfigurableGroup { + std::string prefix = "eventcut_group"; + Configurable cfgZvtxMin{"cfgZvtxMin", -10.f, "min. Zvtx"}; + Configurable cfgZvtxMax{"cfgZvtxMax", +10.f, "max. Zvtx"}; + Configurable cfgRequireSel8{"cfgRequireSel8", false, "require sel8 in event cut"}; + Configurable cfgRequireFT0AND{"cfgRequireFT0AND", true, "require FT0AND in event cut"}; + Configurable cfgRequireNoTFB{"cfgRequireNoTFB", true, "require No time frame border in event cut"}; + Configurable cfgRequireNoITSROFB{"cfgRequireNoITSROFB", false, "require no ITS readout frame border in event cut"}; + Configurable cfgRequireNoSameBunchPileup{"cfgRequireNoSameBunchPileup", false, "require no same bunch pileup in event cut"}; + Configurable cfgRequireVertexITSTPC{"cfgRequireVertexITSTPC", false, "require Vertex ITSTPC in event cut"}; // ITS-TPC matched track contributes PV. + Configurable cfgRequireVertexTOFmatched{"cfgRequireVertexTOFmatched", false, "require Vertex TOFmatched in event cut"}; // ITS-TPC-TOF matched track contributes PV. + Configurable cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; + Configurable cfgTrackOccupancyMin{"cfgTrackOccupancyMin", -2, "min. occupancy"}; + Configurable cfgTrackOccupancyMax{"cfgTrackOccupancyMax", 1000000000, "max. occupancy"}; + Configurable cfgFT0COccupancyMin{"cfgFT0COccupancyMin", -2, "min. FT0C occupancy"}; + Configurable cfgFT0COccupancyMax{"cfgFT0COccupancyMax", 1000000000, "max. FT0C occupancy"}; + + // Configurable cfgRequireNoCollInTimeRangeStandard{"cfgRequireNoCollInTimeRangeStandard", false, "require no collision in time range standard"}; + // Configurable cfgRequireNoCollInTimeRangeStrict{"cfgRequireNoCollInTimeRangeStrict", false, "require no collision in time range strict"}; + // Configurable cfgRequireNoCollInITSROFStandard{"cfgRequireNoCollInITSROFStandard", false, "require no collision in time range standard"}; + // Configurable cfgRequireNoCollInITSROFStrict{"cfgRequireNoCollInITSROFStrict", false, "require no collision in time range strict"}; + // Configurable cfgRequireNoHighMultCollInPrevRof{"cfgRequireNoHighMultCollInPrevRof", false, "require no HM collision in previous ITS ROF"}; + // Configurable cfgRequireGoodITSLayer3{"cfgRequireGoodITSLayer3", false, "number of inactive chips on ITS layer 3 are below threshold "}; + // Configurable cfgRequireGoodITSLayer0123{"cfgRequireGoodITSLayer0123", false, "number of inactive chips on ITS layers 0-3 are below threshold "}; + // Configurable cfgRequireGoodITSLayersAll{"cfgRequireGoodITSLayersAll", false, "number of inactive chips on all ITS layers are below threshold "}; + + // for RCT + Configurable cfgRequireGoodRCT{"cfgRequireGoodRCT", false, "require good detector flag in run condtion table"}; + Configurable cfgRCTLabel{"cfgRCTLabel", "CBT_muon_glo", "select 1 [CBT_muon, CBT_muon_glo] see O2Physics/Common/CCDB/RCTSelectionFlags.h"}; + Configurable cfgCheckZDC{"cfgCheckZDC", false, "set ZDC flag for PbPb"}; + Configurable cfgTreatLimitedAcceptanceAsBad{"cfgTreatLimitedAcceptanceAsBad", false, "reject all events where the detectors relevant for the specified Runlist are flagged as LimitedAcceptance"}; + + Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2, NTPV:3, NGlobal:4"}; + Configurable cfgCentMin{"cfgCentMin", -1, "min. centrality"}; + Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; + // Configurable cfgNumContribMin{"cfgNumContribMin", 0, "min. numContrib"}; + // Configurable cfgNumContribMax{"cfgNumContribMax", 65000, "max. numContrib"}; + } eventcuts; o2::aod::rctsel::RCTFlagsChecker rctChecker; @@ -125,7 +151,7 @@ struct matchingMFT { ccdb->setLocalObjectValidityChecking(); ccdb->setFatalWhenNull(false); ccdbApi.init(ccdburl); - rctChecker.init(cfgRCTLabel.value, cfgCheckZDC.value, cfgTreatLimitedAcceptanceAsBad.value); + rctChecker.init(eventcuts.cfgRCTLabel.value, eventcuts.cfgCheckZDC.value, eventcuts.cfgTreatLimitedAcceptanceAsBad.value); addHistograms(); } @@ -186,6 +212,8 @@ struct matchingMFT { fRegistry.add("Event/hCentFT0A", "hCentFT0A;centrality FT0A (%)", kTH1F, {{110, 0, 110}}, false); fRegistry.add("Event/hCentFT0C", "hCentFT0C;centrality FT0C (%)", kTH1F, {{110, 0, 110}}, false); fRegistry.add("Event/hCentFT0M", "hCentFT0M;centrality FT0M (%)", kTH1F, {{110, 0, 110}}, false); + fRegistry.add("Event/hCentNTPV", "hCentNTPV;centrality NTPV (%)", kTH1F, {{110, 0, 110}}, false); + fRegistry.add("Event/hCentNGlo", "hCentNGlo;centrality NGlo (%)", kTH1F, {{110, 0, 110}}, false); fRegistry.add("Event/hCentFT0CvsMultNTracksPV", "hCentFT0CvsMultNTracksPV;centrality FT0C (%);N_{track} to PV", kTH2F, {{110, 0, 110}, {600, 0, 6000}}, false); fRegistry.add("Event/hMultFT0CvsMultNTracksPV", "hMultFT0CvsMultNTracksPV;mult. FT0C;N_{track} to PV", kTH2F, {{60, 0, 60000}, {600, 0, 6000}}, false); @@ -199,8 +227,8 @@ struct matchingMFT { const AxisSpec axis_pt{{0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2, 2.5, 3, 3.5, 4, 4.5, 5, 6, 7, 8, 9, 10}, "p_{T}^{gl} (GeV/c)"}; fRegistry.add("MFTMCHMID/primary/correct/hPt", "pT;p_{T} (GeV/c)", kTH1F, {{100, 0.0f, 10}}, false); - fRegistry.add("MFTMCHMID/primary/correct/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{180, 0, 2 * M_PI}, {80, -5.f, -1.f}}, false); - fRegistry.add("MFTMCHMID/primary/correct/hEtaPhi_MatchedMCHMID", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{180, 0, 2 * M_PI}, {80, -5.f, -1.f}}, false); + fRegistry.add("MFTMCHMID/primary/correct/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{180, 0, 2 * M_PI}, {200, -4.f, -2.f}}, false); + fRegistry.add("MFTMCHMID/primary/correct/hEtaPhi_MatchedMCHMID", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{180, 0, 2 * M_PI}, {200, -4.f, -2.f}}, false); fRegistry.add("MFTMCHMID/primary/correct/hsDelta", "diff. between GL and associated SA;p_{T}^{gl} (GeV/c);(p_{T}^{sa} - p_{T}^{gl})/p_{T}^{gl};#eta^{sa} - #eta^{gl};#varphi^{sa} - #varphi^{gl} (rad.);", kTHnSparseF, {axis_pt, {200, -0.5, +0.5}, {200, -1, +1}, {90, -M_PI / 4, M_PI / 4}}, false); fRegistry.add("MFTMCHMID/primary/correct/hsDeltaAtMP", "diff. XY between MFT and MCH-MID at MP;p_{T}^{gl} (GeV/c);X^{MCH-MID} - X^{MFT};Y^{MCH-MID} - Y^{MFT};", kTHnSparseF, {axis_pt, {100, -50, 50}, {100, -50, 50}}, false); fRegistry.add("MFTMCHMID/primary/correct/hDiffCollId", "difference in collision index;collisionId_{TTCA} - collisionId_{MP}", kTH1F, {{41, -20.5, +20.5}}, false); @@ -214,7 +242,7 @@ struct matchingMFT { fRegistry.add("MFTMCHMID/primary/correct/hChi2MFT_Pt", "chi2 MFT/ndf;p_{T,#mu} (GeV/c);chi2 MFT/ndf", kTH2F, {{100, 0, 10}, {100, 0.0f, 10}}, false); fRegistry.add("MFTMCHMID/primary/correct/hChi2MatchMCHMID_Pt", "chi2 match MCH-MID;p_{T,#mu} (GeV/c);chi2", kTH2F, {{100, 0, 10}, {100, 0.0f, 100}}, false); fRegistry.add("MFTMCHMID/primary/correct/hChi2MatchMCHMFT_Pt", "chi2 match MCH-MFT;p_{T,#mu} (GeV/c);chi2", kTH2F, {{100, 0, 10}, {100, 0.0f, 100}}, false); - fRegistry.add("MFTMCHMID/primary/correct/hDCAxy2D", "DCA x vs. y;DCA_{x} (cm);DCA_{y} (cm)", kTH2F, {{200, -0.5, 0.5}, {200, -0.5, +0.5}}, false); + fRegistry.add("MFTMCHMID/primary/correct/hDCAxy2D", "DCA x vs. y;DCA_{x} (cm);DCA_{y} (cm)", kTH2F, {{200, -0.1, 0.1}, {200, -0.1, +0.1}}, false); fRegistry.add("MFTMCHMID/primary/correct/hDCAxy2DinSigma", "DCA x vs. y in sigma;DCA_{x} (#sigma);DCA_{y} (#sigma)", kTH2F, {{200, -10, 10}, {200, -10, +10}}, false); fRegistry.add("MFTMCHMID/primary/correct/hDCAxy", "DCAxy;DCA_{xy} (cm);", kTH1F, {{100, 0, 1}}, false); fRegistry.add("MFTMCHMID/primary/correct/hDCAxyinSigma", "DCAxy in sigma;DCA_{xy} (#sigma);", kTH1F, {{100, 0, 10}}, false); @@ -227,7 +255,7 @@ struct matchingMFT { fRegistry.add("MFTMCHMID/primary/correct/hMIDBitMap", "MID bit map;MID bit map", kTH1F, {{256, -0.5, 255.5}}, false); fRegistry.add("MFTMCHMID/primary/correct/hdR_Chi2MatchMCHMFT", "dr vs. matching chi2 MCH-MFT;chi2 match MCH-MFT;#DeltaR;", kTH2F, {{200, 0, 50}, {200, 0, 0.5}}, false); fRegistry.add("MFTMCHMID/primary/correct/hCorrectAsocc", "correct fwdtrack-to-collision association", kTH1F, {{2, -0.5, +1.5}}, false); - fRegistry.add("MFTMCHMID/primary/correct/hIsCA", "cellular automaton;isCA", kTH1F, {{2, -0.5, 1.5}}, false); + fRegistry.add("MFTMCHMID/primary/correct/hIsCA", "cellular automaton;p_{T,#mu} (GeV/c);isCA", kTH2F, {{100, 0, 10}, {2, -0.5, 1.5}}, false); fRegistry.add("MFTMCHMID/primary/correct/hProdVtxZ", "prod. vtx Z of muon;V_{z} (cm)", kTH1F, {{200, -100, 100}}, false); fRegistry.add("MFTMCHMID/primary/correct/hRelDeltaPt", "pT resolution;p_{T}^{gen} (GeV/c);(p_{T}^{rec} - p_{T}^{gen})/p_{T}^{gen}", kTH2F, {{100, 0, 10}, {200, -1, +1}}, false); fRegistry.add("MFTMCHMID/primary/correct/hDeltaEta_Pos", "#eta resolution;p_{T}^{gen} (GeV/c);#eta^{rec} - #eta^{gen}", kTH2F, {{100, 0, 10}, {400, -0.2, +0.2}}, false); @@ -238,12 +266,13 @@ struct matchingMFT { fRegistry.addClone("MFTMCHMID/primary/", "MFTMCHMID/secondary/"); fRegistry.add("MFT/primary/hPt", "pT;p_{T} (GeV/c)", kTH1D, {{1000, 0.0f, 10}}, false); - fRegistry.add("MFT/primary/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2D, {{180, 0, 2 * M_PI}, {80, -5.f, -1.f}}, false); + fRegistry.add("MFT/primary/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2D, {{180, 0, 2 * M_PI}, {200, -4.f, -2.f}}, false); + fRegistry.add("MFT/primary/hXY", "inner most XY;X (cm);Y (cm)", kTH2D, {{300, -15, 15}, {300, -15, 15}}, false); fRegistry.add("MFT/primary/hSign", "sign;sign", kTH1D, {{3, -1.5, +1.5}}, false); fRegistry.add("MFT/primary/hChi2MFT", "chi2 MFT/ndf;chi2 MFT/ndf", kTH1D, {{100, 0.0f, 10}}, false); fRegistry.add("MFT/primary/hNclustersMFT", "NclustersMFT;Nclusters MFT", kTH1D, {{11, -0.5f, 10.5}}, false); fRegistry.add("MFT/primary/hMFTClusterMap", "MFT cluster map", kTH1D, {{1024, -0.5, 1023.5}}, false); - fRegistry.add("MFT/primary/hDCAxy2D", "DCA x vs. y;DCA_{x} (cm);DCA_{y} (cm)", kTH2D, {{200, -0.5, 0.5}, {200, -0.5, +0.5}}, false); + fRegistry.add("MFT/primary/hDCAxy2D", "DCA x vs. y;DCA_{x} (cm);DCA_{y} (cm)", kTH2D, {{200, -0.1, 0.1}, {200, -0.1, +0.1}}, false); fRegistry.add("MFT/primary/hDCAxy", "DCAxy;DCA_{xy} (cm);", kTH1D, {{100, 0, 1}}, false); fRegistry.add("MFT/primary/hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm);", kTH2D, {{100, 0, 1}, {200, -0.1, 0.1}}, false); fRegistry.add("MFT/primary/hProdVtxZ", "prod. vtx Z of track;V_{z} (cm)", kTH1D, {{200, -100, 100}}, false); @@ -253,10 +282,60 @@ struct matchingMFT { fRegistry.add("MFT/primary/hDeltaPhi_Pos", "#varphi resolution;p_{T}^{gen} (GeV/c);#varphi^{rec} - #varphi^{gen} (rad.)", kTH2D, {{200, 0, 10}, {400, -0.2, +0.2}}, false); fRegistry.add("MFT/primary/hDeltaPhi_Neg", "#varphi resolution;p_{T}^{gen} (GeV/c);#varphi^{rec} - #varphi^{gen} (rad.)", kTH2D, {{200, 0, 10}, {400, -0.2, +0.2}}, false); fRegistry.add("MFT/primary/hCorrectAsocc", "correct mfttrack-to-collision association", kTH1F, {{2, -0.5, +1.5}}, false); - fRegistry.add("MFT/primary/hIsCA", "cellular automaton;isCA", kTH1F, {{2, -0.5, 1.5}}, false); + fRegistry.add("MFT/primary/hIsCA", "cellular automaton;p_{T,#mu} (GeV/c);isCA", kTH2F, {{100, 0, 10}, {2, -0.5, 1.5}}, false); fRegistry.addClone("MFT/primary/", "MFT/secondary/"); } + template + bool isSelectedEvent(TCollision const& collision) + { + if (eventcuts.cfgRequireSel8 && !collision.sel8()) { + return false; + } + + if (collision.posZ() < eventcuts.cfgZvtxMin || eventcuts.cfgZvtxMax < collision.posZ()) { + return false; + } + + if (eventcuts.cfgRequireFT0AND && !collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + return false; + } + + if (eventcuts.cfgRequireNoTFB && !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + return false; + } + + if (eventcuts.cfgRequireNoITSROFB && !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + return false; + } + + if (eventcuts.cfgRequireNoSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + return false; + } + + if (eventcuts.cfgRequireGoodZvtxFT0vsPV && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + return false; + } + + if (eventcuts.cfgRequireVertexITSTPC && !collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + return false; + } + + if (eventcuts.cfgRequireVertexTOFmatched && !collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) { + return false; + } + + if (!(eventcuts.cfgTrackOccupancyMin <= collision.trackOccupancyInTimeRange() && collision.trackOccupancyInTimeRange() < eventcuts.cfgTrackOccupancyMax)) { + return false; + } + + if (!(eventcuts.cfgFT0COccupancyMin <= collision.ft0cOccupancyInTimeRange() && collision.ft0cOccupancyInTimeRange() < eventcuts.cfgFT0COccupancyMax)) { + return false; + } + + return true; + } + bool isSelected(const float pt, const float eta, const float rAtAbsorberEnd, const float pDCA, const float chi2_per_ndf, const uint8_t trackType, const float dcaXY) { if (pt < minPt || maxPt < pt) { @@ -343,26 +422,6 @@ struct matchingMFT { // } // } - // template - // float cpaRZ(TCollision const& collision, TTrackParCovFwd const& fwdtrack) - // { - // float lx = fwdtrack.getX() - collision.posX(); // flight length X - // float ly = fwdtrack.getY() - collision.posY(); // flight length Y - // float lz = fwdtrack.getZ() - collision.posZ(); // flight length Z - // float lt = RecoDecay::sqrtSumOfSquares(lx, ly); // flight length R, i.e. transverse plane. - - // float pt = fwdtrack.getPt(); - // float pz = fwdtrack.getPz(); - - // float cpaRZ = RecoDecay::dotProd(std::array{lt, lz}, std::array{pt, pz}) / (RecoDecay::sqrtSumOfSquares(lt, lz) * RecoDecay::sqrtSumOfSquares(pt, pz)); - // if (cpaRZ < -1.f) { - // return -1.f; - // } else if (cpaRZ > 1.f) { - // return 1.f; - // } - // return cpaRZ; - // } - template void getDxDyAtMatchingPlane(TCollision const& collision, TFwdTrack const& fwdtrack, TMFTrackCov const& mftCovs, float& dx, float& dy) { @@ -584,7 +643,7 @@ struct matchingMFT { fRegistry.fill(HIST("MFTMCHMID/primary/correct/hMCHBitMap"), fwdtrack.mchBitMap()); fRegistry.fill(HIST("MFTMCHMID/primary/correct/hMIDBitMap"), fwdtrack.midBitMap()); fRegistry.fill(HIST("MFTMCHMID/primary/correct/hCorrectAsocc"), mcParticle_MCHMID.mcCollisionId() == collision.mcCollisionId()); - fRegistry.fill(HIST("MFTMCHMID/primary/correct/hIsCA"), mfttrack.isCA()); + fRegistry.fill(HIST("MFTMCHMID/primary/correct/hIsCA"), pt, mfttrack.isCA()); fRegistry.fill(HIST("MFTMCHMID/primary/correct/hDCAxResolutionvsPt"), pt, std::sqrt(cXX) * 1e+4); // convert cm to um fRegistry.fill(HIST("MFTMCHMID/primary/correct/hDCAyResolutionvsPt"), pt, std::sqrt(cYY) * 1e+4); // convert cm to um fRegistry.fill(HIST("MFTMCHMID/primary/correct/hDCAxyResolutionvsPt"), pt, sigma_dcaXY * 1e+4); // convert cm to um @@ -624,7 +683,7 @@ struct matchingMFT { fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hMCHBitMap"), fwdtrack.mchBitMap()); fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hMIDBitMap"), fwdtrack.midBitMap()); fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hCorrectAsocc"), mcParticle_MCHMID.mcCollisionId() == collision.mcCollisionId()); - fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hIsCA"), mfttrack.isCA()); + fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hIsCA"), pt, mfttrack.isCA()); fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hDCAxResolutionvsPt"), pt, std::sqrt(cXX) * 1e+4); // convert cm to um fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hDCAyResolutionvsPt"), pt, std::sqrt(cYY) * 1e+4); // convert cm to um fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hDCAxyResolutionvsPt"), pt, sigma_dcaXY * 1e+4); // convert cm to um @@ -666,7 +725,7 @@ struct matchingMFT { fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hMCHBitMap"), fwdtrack.mchBitMap()); fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hMIDBitMap"), fwdtrack.midBitMap()); fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hCorrectAsocc"), mcParticle_MCHMID.mcCollisionId() == collision.mcCollisionId()); - fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hIsCA"), mfttrack.isCA()); + fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hIsCA"), pt, mfttrack.isCA()); fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hDCAxResolutionvsPt"), pt, std::sqrt(cXX) * 1e+4); // convert cm to um fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hDCAyResolutionvsPt"), pt, std::sqrt(cYY) * 1e+4); // convert cm to um fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hDCAxyResolutionvsPt"), pt, sigma_dcaXY * 1e+4); // convert cm to um @@ -706,7 +765,7 @@ struct matchingMFT { fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hMCHBitMap"), fwdtrack.mchBitMap()); fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hMIDBitMap"), fwdtrack.midBitMap()); fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hCorrectAsocc"), mcParticle_MCHMID.mcCollisionId() == collision.mcCollisionId()); - fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hIsCA"), mfttrack.isCA()); + fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hIsCA"), pt, mfttrack.isCA()); fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hDCAxResolutionvsPt"), pt, std::sqrt(cXX) * 1e+4); // convert cm to um fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hDCAyResolutionvsPt"), pt, std::sqrt(cYY) * 1e+4); // convert cm to um fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hDCAxyResolutionvsPt"), pt, sigma_dcaXY * 1e+4); // convert cm to um @@ -734,6 +793,8 @@ struct matchingMFT { fRegistry.fill(HIST("Event/hCentFT0A"), collision.centFT0A()); fRegistry.fill(HIST("Event/hCentFT0C"), collision.centFT0C()); fRegistry.fill(HIST("Event/hCentFT0M"), collision.centFT0M()); + fRegistry.fill(HIST("Event/hCentNTPV"), collision.centNTPV()); + fRegistry.fill(HIST("Event/hCentNGlo"), collision.centNGlobal()); fRegistry.fill(HIST("Event/hCentFT0CvsMultNTracksPV"), collision.centFT0C(), collision.multNTracksPV()); fRegistry.fill(HIST("Event/hMultFT0CvsMultNTracksPV"), collision.multFT0C(), collision.multNTracksPV()); } @@ -872,11 +933,11 @@ struct matchingMFT { if (!collision.has_mcCollision()) { continue; } - if (cfgRequireGoodRCT && !rctChecker.checkTable(collision)) { + if (eventcuts.cfgRequireGoodRCT && !rctChecker.checkTable(collision)) { continue; } - float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; - if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + float centralities[5] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV(), collision.centNGlobal()}; + if (centralities[eventcuts.cfgCentEstimator] < eventcuts.cfgCentMin || eventcuts.cfgCentMax < centralities[eventcuts.cfgCentEstimator]) { continue; } @@ -946,6 +1007,7 @@ struct matchingMFT { if (isPrimary) { fRegistry.fill(HIST("MFT/primary/hPt"), pt); fRegistry.fill(HIST("MFT/primary/hEtaPhi"), phi, eta); + fRegistry.fill(HIST("MFT/primary/hXY"), mfttrack.x(), mfttrack.y()); fRegistry.fill(HIST("MFT/primary/hSign"), mfttrack.sign()); fRegistry.fill(HIST("MFT/primary/hNclustersMFT"), mfttrack.nClusters()); fRegistry.fill(HIST("MFT/primary/hChi2MFT"), mfttrack.chi2() / ndf); @@ -954,7 +1016,7 @@ struct matchingMFT { fRegistry.fill(HIST("MFT/primary/hDCAxy"), dcaXY); fRegistry.fill(HIST("MFT/primary/hDCAxyz"), dcaXY, dcaZ); fRegistry.fill(HIST("MFT/primary/hCorrectAsocc"), mcParticle.mcCollisionId() == collision.mcCollisionId()); - fRegistry.fill(HIST("MFT/primary/hIsCA"), mfttrack.isCA()); + fRegistry.fill(HIST("MFT/primary/hIsCA"), pt, mfttrack.isCA()); fRegistry.fill(HIST("MFT/primary/hProdVtxZ"), mcParticle.vz()); fRegistry.fill(HIST("MFT/primary/hRelDeltaPt"), mcParticle.pt(), (pt - mcParticle.pt()) / mcParticle.pt()); @@ -969,6 +1031,7 @@ struct matchingMFT { } else { fRegistry.fill(HIST("MFT/secondary/hPt"), pt); fRegistry.fill(HIST("MFT/secondary/hEtaPhi"), phi, eta); + fRegistry.fill(HIST("MFT/secondary/hXY"), mfttrack.x(), mfttrack.y()); fRegistry.fill(HIST("MFT/secondary/hSign"), mfttrack.sign()); fRegistry.fill(HIST("MFT/secondary/hNclustersMFT"), mfttrack.nClusters()); fRegistry.fill(HIST("MFT/secondary/hChi2MFT"), mfttrack.chi2() / ndf); @@ -977,7 +1040,7 @@ struct matchingMFT { fRegistry.fill(HIST("MFT/secondary/hDCAxy"), dcaXY); fRegistry.fill(HIST("MFT/secondary/hDCAxyz"), dcaXY, dcaZ); fRegistry.fill(HIST("MFT/secondary/hCorrectAsocc"), mcParticle.mcCollisionId() == collision.mcCollisionId()); - fRegistry.fill(HIST("MFT/secondary/hIsCA"), mfttrack.isCA()); + fRegistry.fill(HIST("MFT/secondary/hIsCA"), pt, mfttrack.isCA()); fRegistry.fill(HIST("MFT/secondary/hProdVtxZ"), mcParticle.vz()); fRegistry.fill(HIST("MFT/secondary/hRelDeltaPt"), mcParticle.pt(), (pt - mcParticle.pt()) / mcParticle.pt()); @@ -1002,8 +1065,8 @@ struct matchingMFT { Preslice fwdtrackIndicesPerCollision = aod::track_association::collisionId; PresliceUnsorted fwdtrackIndicesPerFwdTrack = aod::track_association::fwdtrackId; - Filter collisionFilter_evsel = o2::aod::evsel::sel8 == true && (cfgZvtxMin < o2::aod::collision::posZ && o2::aod::collision::posZ < cfgZvtxMax); - Filter collisionFilter_centrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); + Filter collisionFilter_evsel = eventcuts.cfgZvtxMin < o2::aod::collision::posZ && o2::aod::collision::posZ < eventcuts.cfgZvtxMax; + Filter collisionFilter_centrality = (eventcuts.cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < eventcuts.cfgCentMax) || (eventcuts.cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < eventcuts.cfgCentMax) || (eventcuts.cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < eventcuts.cfgCentMax); using FilteredMyCollisions = soa::Filtered; void processWithoutFTTCA(FilteredMyCollisions const& collisions, MyFwdTracks const& fwdtracks, MyMFTTracks const& mfttracks, aod::BCsWithTimestamps const&, aod::McParticles const&) @@ -1028,11 +1091,16 @@ struct matchingMFT { if (!collision.has_mcCollision()) { continue; } - if (cfgRequireGoodRCT && !rctChecker.checkTable(collision)) { + + if (!isSelectedEvent(collision)) { + continue; + } + + if (eventcuts.cfgRequireGoodRCT && !rctChecker.checkTable(collision)) { continue; } - float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; - if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + float centralities[5] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV(), collision.centNGlobal()}; + if (centralities[eventcuts.cfgCentEstimator] < eventcuts.cfgCentMin || eventcuts.cfgCentMax < centralities[eventcuts.cfgCentEstimator]) { continue; } fRegistry.fill(HIST("Event/hCollisionCounter"), 1); @@ -1081,11 +1149,14 @@ struct matchingMFT { if (!collision.has_mcCollision()) { continue; } - if (cfgRequireGoodRCT && !rctChecker.checkTable(collision)) { + if (!isSelectedEvent(collision)) { + continue; + } + if (eventcuts.cfgRequireGoodRCT && !rctChecker.checkTable(collision)) { continue; } - float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; - if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + float centralities[5] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV(), collision.centNGlobal()}; + if (centralities[eventcuts.cfgCentEstimator] < eventcuts.cfgCentMin || eventcuts.cfgCentMax < centralities[eventcuts.cfgCentEstimator]) { continue; } fRegistry.fill(HIST("Event/hCollisionCounter"), 1); @@ -1141,11 +1212,14 @@ struct matchingMFT { if (!collision.has_mcCollision()) { continue; } - if (cfgRequireGoodRCT && !rctChecker.checkTable(collision)) { + if (!isSelectedEvent(collision)) { + continue; + } + if (eventcuts.cfgRequireGoodRCT && !rctChecker.checkTable(collision)) { continue; } - float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; - if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + float centralities[5] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV(), collision.centNGlobal()}; + if (centralities[eventcuts.cfgCentEstimator] < eventcuts.cfgCentMin || eventcuts.cfgCentMax < centralities[eventcuts.cfgCentEstimator]) { continue; } fRegistry.fill(HIST("Event/hCollisionCounter"), 1); From 2e071744104a8c5b81e43738d59a3de82ce77dca Mon Sep 17 00:00:00 2001 From: alcaliva <32872606+alcaliva@users.noreply.github.com> Date: Tue, 10 Mar 2026 17:01:21 +0100 Subject: [PATCH 238/347] [PWGLF] enlarge domain for pt resolution study (#15326) --- PWGLF/Tasks/Nuspex/antinucleiInJets.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx b/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx index 42fad20fff2..b2576226bce 100644 --- a/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx +++ b/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx @@ -155,7 +155,7 @@ struct AntinucleiInJets { Configurable isppRefAnalysis{"isppRefAnalysis", false, "Is ppRef analysis"}; Configurable cfgAreaFrac{"cfgAreaFrac", 0.6, "fraction of jet area"}; Configurable cfgEtaJetMax{"cfgEtaJetMax", 0.5, "max jet eta"}; - Configurable cfgMinPtTrack{"cfgMinPtTrack", 0.15, "minimum pt of tracks for jet reconstruction"}; + Configurable cfgMinPtTrack{"cfgMinPtTrack", 0.1, "minimum pt of tracks for jet reconstruction"}; Configurable alpha{"alpha", 0.3, "parameter to control jet matching"}; // Event selection criteria @@ -172,7 +172,7 @@ struct AntinucleiInJets { // Jet selection and event filtering parameters Configurable minJetPt{"minJetPt", 10.0, "Minimum pt of the jet after bkg subtraction"}; - Configurable maxJetPt{"maxJetPt", 1000.0, "Maximum pt of the jet after bkg subtraction"}; + Configurable maxJetPt{"maxJetPt", 1e+06, "Maximum pt of the jet after bkg subtraction"}; Configurable ptLeadingMin{"ptLeadingMin", 5.0, "pt Leading Min"}; Configurable rJet{"rJet", 0.4, "Jet resolution parameter R"}; Configurable zVtx{"zVtx", 10.0, "Maximum zVertex"}; @@ -534,7 +534,7 @@ struct AntinucleiInJets { // jet pt resolution if (doprocessJetPtResolution) { - registryMC.add("jetPtResolution", "jet Pt Resolution", HistType::kTH2F, {{200, 0, 20, "#it{p}^{jet}_{T,true} (GeV/#it{c})"}, {1000, -5, 5, "#Delta #it{p}^{jet}_{T} (GeV/#it{c})"}}); + registryMC.add("jetPtResolution", "jet Pt Resolution", HistType::kTH2F, {{1000, 0, 100, "#it{p}^{jet}_{T,true} (GeV/#it{c})"}, {1000, -20, 20, "#Delta #it{p}^{jet}_{T} (GeV/#it{c})"}}); } // Coalescence and Correlation analysis From f6474cf042ce7c864c16a2b04053c86351801e98 Mon Sep 17 00:00:00 2001 From: YazhenLin Date: Wed, 11 Mar 2026 00:49:42 +0800 Subject: [PATCH 239/347] [PWGDQ] Delete the unused code and fix some errors (#15331) --- PWGDQ/Core/VarManager.h | 94 ----- PWGDQ/Tasks/dqEfficiency_withAssoc_direct.cxx | 351 +----------------- PWGDQ/Tasks/tableReader_withAssoc.cxx | 18 +- 3 files changed, 15 insertions(+), 448 deletions(-) diff --git a/PWGDQ/Core/VarManager.h b/PWGDQ/Core/VarManager.h index 487383bfc90..14488385846 100644 --- a/PWGDQ/Core/VarManager.h +++ b/PWGDQ/Core/VarManager.h @@ -1329,8 +1329,6 @@ class VarManager : public TObject static void FillTrackMC(const U& mcStack, T const& track, float* values = nullptr); template static void FillEnergyCorrelatorsMC(T const& track, T1 const& t1, float* values = nullptr, float Translow = 1. / 3, float Transhigh = 2. / 3); - template - static void FillEnergyCorrelatorsMCUnfolding(T1 const& dilepton, T2 const& hadron, T const& track, T3 const& t1, float* values = nullptr); template static void FillPairPropagateMuon(T1 const& muon1, T2 const& muon2, const C& collision, float* values = nullptr); template @@ -1368,8 +1366,6 @@ class VarManager : public TObject template static void FillEnergyCorrelatorsUnfoldingTriple(T1 const& lepton1, T2 const& lepton2, T3 const& hadron, T4 const& track, T5 const& t1, float* values = nullptr); template - static void FillEnergyCorrelator(T1 const& dilepton, T2 const& hadron, float* values = nullptr, float Translow = 1. / 3, float Transhigh = 2. / 3, bool applyFitMass = false, float sidebandMass = 0.0f); - template static void FillDileptonPhoton(T1 const& dilepton, T2 const& photon, float* values = nullptr); template static void FillHadron(T const& hadron, float* values = nullptr, float hadronMass = 0.0f); @@ -3360,35 +3356,6 @@ void VarManager::FillEnergyCorrelatorsMC(T const& track, T1 const& t1, float* va } } -template -void VarManager::FillEnergyCorrelatorsMCUnfolding(T1 const& dilepton, T2 const& hadron, T const& track, T3 const& t1, float* values) -{ - if (fgUsedVars[kMCCosChi_gen] || fgUsedVars[kMCWeight_gen] || fgUsedVars[kMCdeltaeta_gen] || fgUsedVars[kMCCosChi_rec] || fgUsedVars[kMCWeight_rec] || fgUsedVars[kMCdeltaeta_rec]) { - // energy correlators - float MassHadron; - if constexpr (pairType == kJpsiHadronMass) { - MassHadron = TMath::Sqrt(t1.e() * t1.e() - t1.p() * t1.p()); - } - if constexpr (pairType == kJpsiPionMass) { - MassHadron = o2::constants::physics::MassPionCharged; - } - ROOT::Math::PtEtaPhiMVector v1_gen(track.pt(), track.eta(), track.phi(), o2::constants::physics::MassJPsi); - ROOT::Math::PtEtaPhiMVector v2_gen(t1.pt(), t1.eta(), t1.phi(), MassHadron); - float E_boost_gen = LorentzTransformJpsihadroncosChi("weight_boost", v1_gen, v2_gen); - float CosChi_gen = LorentzTransformJpsihadroncosChi("coschi", v1_gen, v2_gen); - values[kMCCosChi_gen] = CosChi_gen; - values[kMCWeight_gen] = E_boost_gen / o2::constants::physics::MassJPsi; - values[kMCdeltaeta_gen] = track.eta() - t1.eta(); - - ROOT::Math::PtEtaPhiMVector v1_rec(dilepton.pt(), dilepton.eta(), dilepton.phi(), dilepton.mass()); - ROOT::Math::PtEtaPhiMVector v2_rec(hadron.pt(), hadron.eta(), hadron.phi(), o2::constants::physics::MassPionCharged); - values[kMCCosChi_rec] = LorentzTransformJpsihadroncosChi("coschi", v1_rec, v2_rec); - float E_boost_rec = LorentzTransformJpsihadroncosChi("weight_boost", v1_rec, v2_rec); - values[kMCWeight_rec] = E_boost_rec / v1_rec.M(); - values[kMCdeltaeta_rec] = dilepton.eta() - hadron.eta(); - } -} - template void VarManager::FillPairPropagateMuon(T1 const& muon1, T2 const& muon2, const C& collision, float* values) { @@ -5817,67 +5784,6 @@ void VarManager::FillDileptonHadron(T1 const& dilepton, T2 const& hadron, float* } } -template -void VarManager::FillEnergyCorrelator(T1 const& dilepton, T2 const& hadron, float* values, float Translow, float Transhigh, bool applyFitMass, float sidebandMass) -{ - float dileptonmass = o2::constants::physics::MassJPsi; - if (applyFitMass) { - dileptonmass = dilepton.mass(); - } - if (applyFitMass && sidebandMass > 0) { - dileptonmass = sidebandMass; - } - - if (fgUsedVars[kCosChi] || fgUsedVars[kECWeight] || fgUsedVars[kCosTheta] || fgUsedVars[kEWeight_before] || fgUsedVars[kPtDau] || fgUsedVars[kEtaDau] || fgUsedVars[kPhiDau] || fgUsedVars[kCosChi_randomPhi_trans] || fgUsedVars[kCosChi_randomPhi_toward] || fgUsedVars[kCosChi_randomPhi_away]) { - values[kdileptonmass] = dileptonmass; - ROOT::Math::PtEtaPhiMVector v1(dilepton.pt(), dilepton.eta(), dilepton.phi(), dileptonmass); - ROOT::Math::PtEtaPhiMVector v2(hadron.pt(), hadron.eta(), hadron.phi(), o2::constants::physics::MassPionCharged); - values[kCosChi] = LorentzTransformJpsihadroncosChi("coschi", v1, v2); - float E_boost = LorentzTransformJpsihadroncosChi("weight_boost", v1, v2); - values[kECWeight] = E_boost / v1.M(); - values[kCosTheta] = LorentzTransformJpsihadroncosChi("costheta", v1, v2); - values[kEWeight_before] = v2.Pt() / v1.M(); - values[kPtDau] = v2.pt(); - values[kEtaDau] = v2.eta(); - values[kPhiDau] = RecoDecay::constrainAngle(v2.phi(), -o2::constants::math::PIHalf); - - float deltaphi = RecoDecay::constrainAngle(v1.phi() - v2.phi(), -o2::constants::math::PI); - values[kCosChi_randomPhi_trans] = -999.9f; - values[kCosChi_randomPhi_toward] = -999.9f; - values[kCosChi_randomPhi_away] = -999.9f; - - values[kdeltaphi_randomPhi_trans] = -999.9f; - values[kdeltaphi_randomPhi_toward] = -999.9f; - values[kdeltaphi_randomPhi_away] = -999.9f; - - float randomPhi_trans = -o2::constants::math::PIHalf; - float randomPhi_toward = -o2::constants::math::PIHalf; - float randomPhi_away = -o2::constants::math::PIHalf; - - if ((deltaphi > -Transhigh * TMath::Pi() && deltaphi < -Translow * TMath::Pi()) || (deltaphi > Translow * TMath::Pi() && deltaphi < Transhigh * TMath::Pi())) { - randomPhi_trans = gRandom->Uniform(-o2::constants::math::PIHalf, 3. * o2::constants::math::PIHalf); - randomPhi_toward = gRandom->Uniform(-o2::constants::math::PIHalf, 3. * o2::constants::math::PIHalf); - randomPhi_away = gRandom->Uniform(-o2::constants::math::PIHalf, 3. * o2::constants::math::PIHalf); - - ROOT::Math::PtEtaPhiMVector v2_randomPhi_trans(v2.pt(), v2.eta(), randomPhi_trans, o2::constants::physics::MassPionCharged); - values[kCosChi_randomPhi_trans] = LorentzTransformJpsihadroncosChi("coschi", v1, v2_randomPhi_trans); - values[kWeight_randomPhi_trans] = LorentzTransformJpsihadroncosChi("weight_boost", v1, v2_randomPhi_trans) / v1.M(); - - ROOT::Math::PtEtaPhiMVector v2_randomPhi_toward(v2.pt(), v2.eta(), randomPhi_toward, o2::constants::physics::MassPionCharged); - values[kCosChi_randomPhi_toward] = LorentzTransformJpsihadroncosChi("coschi", v1, v2_randomPhi_toward); - values[kWeight_randomPhi_toward] = LorentzTransformJpsihadroncosChi("weight_boost", v1, v2_randomPhi_toward) / v1.M(); - - ROOT::Math::PtEtaPhiMVector v2_randomPhi_away(v2.pt(), v2.eta(), randomPhi_away, o2::constants::physics::MassPionCharged); - values[kCosChi_randomPhi_away] = LorentzTransformJpsihadroncosChi("coschi", v1, v2_randomPhi_away); - values[kWeight_randomPhi_away] = LorentzTransformJpsihadroncosChi("weight_boost", v1, v2_randomPhi_away) / v1.M(); - - values[kdeltaphi_randomPhi_trans] = RecoDecay::constrainAngle(v1.phi() - randomPhi_trans, -o2::constants::math::PIHalf); - values[kdeltaphi_randomPhi_toward] = RecoDecay::constrainAngle(v1.phi() - randomPhi_toward, -o2::constants::math::PIHalf); - values[kdeltaphi_randomPhi_away] = RecoDecay::constrainAngle(v1.phi() - randomPhi_away, -o2::constants::math::PIHalf); - } - } -} - template void VarManager::FillEnergyCorrelatorTriple(T1 const& lepton1, T2 const& lepton2, T3 const& hadron, float* values, float Translow, float Transhigh, bool applyFitMass, float sidebandMass) { diff --git a/PWGDQ/Tasks/dqEfficiency_withAssoc_direct.cxx b/PWGDQ/Tasks/dqEfficiency_withAssoc_direct.cxx index 948493f9cf4..4585a894098 100644 --- a/PWGDQ/Tasks/dqEfficiency_withAssoc_direct.cxx +++ b/PWGDQ/Tasks/dqEfficiency_withAssoc_direct.cxx @@ -19,8 +19,6 @@ #include "PWGDQ/Core/HistogramsLibrary.h" #include "PWGDQ/Core/MCSignal.h" #include "PWGDQ/Core/MCSignalLibrary.h" -#include "PWGDQ/Core/MixingHandler.h" -#include "PWGDQ/Core/MixingLibrary.h" #include "PWGDQ/Core/VarManager.h" #include "PWGDQ/DataModel/ReducedInfoTables.h" @@ -77,7 +75,6 @@ namespace o2::aod { namespace dqanalysisflags { -DECLARE_SOA_COLUMN(MixingHash, mixingHash, int); //! Hash used in event mixing //need to understand DECLARE_SOA_BITMAP_COLUMN(IsEventSelected, isEventSelected, 32); //! Event decision DECLARE_SOA_BITMAP_COLUMN(IsBarrelSelected, isBarrelSelected, 32); //! Barrel track decisions DECLARE_SOA_COLUMN(BarrelAmbiguityInBunch, barrelAmbiguityInBunch, int8_t); //! Barrel track in-bunch ambiguity @@ -186,8 +183,7 @@ DECLARE_SOA_COLUMN(OniaVz, oniaVz, float); DECLARE_SOA_COLUMN(OniaVtxZ, oniaVtxZ, float); } // namespace dqanalysisflags -DECLARE_SOA_TABLE(EventCuts, "AOD", "DQANAEVCUTS", dqanalysisflags::IsEventSelected); //! joinable to ReducedEvents -DECLARE_SOA_TABLE(MixingHashes, "AOD", "DQANAMIXHASHA", dqanalysisflags::MixingHash); //! joinable to ReducedEvents +DECLARE_SOA_TABLE(EventCuts, "AOD", "DQANAEVCUTS", dqanalysisflags::IsEventSelected); //! joinable to ReducedEvents //! joinable to ReducedEvents DECLARE_SOA_TABLE(BarrelTrackCuts, "AOD", "DQANATRKCUTS", dqanalysisflags::IsBarrelSelected); //! joinable to ReducedTracksAssoc DECLARE_SOA_TABLE(BarrelAmbiguities, "AOD", "DQBARRELAMB", dqanalysisflags::BarrelAmbiguityInBunch, dqanalysisflags::BarrelAmbiguityOutOfBunch); //! joinable to ReducedBarrelTracks DECLARE_SOA_TABLE(Prefilter, "AOD", "DQPREFILTER", dqanalysisflags::IsBarrelSelectedPrefilter); //! joinable to ReducedTracksAssoc @@ -246,7 +242,6 @@ using MyMuonTracksWithCovWithAmbiguities = soa::Join; using MyEvents = soa::Join; using MyEventsSelected = soa::Join; -using MyEventsHashSelected = soa::Join; using MyBarrelTracksWithCov = soa::Join eventSel; - Produces hash; OutputObj fOutputList{"output"}; - Configurable fConfigMixingVariables{"cfgMixingVars", "", "Mixing configs separated by a comma, default no mixing"}; Configurable fConfigEventCuts{"cfgEventCuts", "eventStandard", "Event selection"}; Configurable fConfigEventCutsJSON{"cfgEventCutsJSON", "", "Additional event cuts specified in JSON format"}; Configurable fConfigQA{"cfgQA", false, "If true, fill QA histograms"}; @@ -309,7 +302,6 @@ struct AnalysisEventSelection { Configurable fConfigNoLaterThan{"ccdb-no-later-than", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object"}; HistogramManager* fHistMan = nullptr; - MixingHandler* fMixHandler = nullptr; AnalysisCompositeCut* fEventCut; @@ -361,16 +353,6 @@ struct AnalysisEventSelection { fOutputList.setObject(fHistMan->GetMainHistogramList()); } - TString mixVarsString = fConfigMixingVariables.value; - std::unique_ptr objArray(mixVarsString.Tokenize(",")); - if (objArray->GetEntries() > 0) { - fMixHandler = new MixingHandler("mixingHandler", "mixing handler"); - fMixHandler->Init(); - for (int iVar = 0; iVar < objArray->GetEntries(); ++iVar) { - dqmixing::SetUpMixing(fMixHandler, objArray->At(iVar)->GetName()); - } - } - fCurrentRun = -1; fCCDB->setURL(fConfigCcdbUrl.value); fCCDB->setCaching(true); @@ -442,10 +424,6 @@ struct AnalysisEventSelection { auto& evIndices = fBCCollMap[bc.globalBC()]; evIndices.push_back(event.globalIndex()); } - if (fMixHandler != nullptr) { - int hh = fMixHandler->FindEventCategory(VarManager::fgValues); - hash(hh); - } } for (auto& event : mcEvents) { @@ -2143,15 +2121,9 @@ struct AnalysisDileptonTrack { Configurable fConfigUseKFVertexing{"cfgUseKFVertexing", false, "Use KF Particle for secondary vertex reconstruction (DCAFitter is used by default)"}; Configurable fConfigDileptonLowpTCut{"cfgDileptonLowpTCut", 0.0, "Low pT cut for dileptons used in the triplet vertexing"}; Configurable fConfigDileptonHighpTCut{"cfgDileptonHighpTCut", 1E5, "High pT cut for dileptons used in the triplet vertexing"}; - Configurable fConfigDileptonRapCutAbs{"cfgDileptonRapCutAbs", 1.0, "Rap cut for dileptons used in the triplet vertexing"}; Configurable fConfigHistogramSubgroups{"cfgDileptonTrackHistogramsSubgroups", "invmass,vertexing", "Comma separated list of dilepton-track histogram subgroups"}; Configurable fConfigAddJSONHistograms{"cfgAddJSONHistograms", "", "Histograms in JSON format"}; - Configurable fConfigMixingDepth{"cfgMixingDepth", 5, "Event mixing pool depth"}; Configurable fConfigPublishTripletTable{"cfgPublishTripletTable", false, "Publish the triplet tables, BmesonCandidates"}; - Configurable fConfigApplyMassEC{"cfgApplyMassEC", false, "Apply fit mass for sideband for the energy correlator study"}; - Configurable> fConfigSavelessevents{"cfgSavelessevents", std::vector{1, 0}, "Save less events for the energy correlator study"}; - Configurable> fConfigTransRange{"cfgTransRange", std::vector{0.333333, 0.666667}, "Transverse region for the energy correlstor analysis"}; - Configurable fConfigEnergycorrelator{"cfgEnergycorrelator", false, "Add some hist for energy correlator study"}; } fConfigOptions; struct : ConfigurableGroup { @@ -2212,19 +2184,14 @@ struct AnalysisDileptonTrack { MCSignal* fDileptonLegSignal; MCSignal* fHadronSignal; - NoBinningPolicy fHashBin; - void init(o2::framework::InitContext& context) { cout << "AnalysisDileptonTrack::init() called" << endl; bool isBarrel = context.mOptions.get("processBarrel"); - bool isBarrelME = context.mOptions.get("processBarrelMixedEvent"); // bool isBarrelAsymmetric = context.mOptions.get("processDstarToD0Pi"); // bool isMuon = context.mOptions.get("processMuonSkimmed"); bool isMCGen = context.mOptions.get("processMCGen"); bool isDummy = context.mOptions.get("processDummy"); - bool isMCGen_energycorrelators = context.mOptions.get("processMCGenEnergyCorrelators") || context.mOptions.get("processMCGenEnergyCorrelatorsPion"); - bool isMCGen_energycorrelatorsME = context.mOptions.get("processMCGenEnergyCorrelatorsME") || context.mOptions.get("processMCGenEnergyCorrelatorsPionME"); if (isDummy) { if (isBarrel || isMCGen /*|| isBarrelAsymmetric*/ /*|| isMuon*/) { @@ -2469,11 +2436,8 @@ struct AnalysisDileptonTrack { fLegCutNames.push_back(pairLegCutName); // define dilepton histograms - if (!fConfigOptions.fConfigEnergycorrelator) { - DefineHistograms(fHistMan, Form("DileptonsSelected_%s", pairLegCutName.Data()), "barrel,vertexing"); - } else { - DefineHistograms(fHistMan, Form("DileptonsSelected_%s", pairLegCutName.Data()), ""); - } + DefineHistograms(fHistMan, Form("DileptonsSelected_%s", pairLegCutName.Data()), "barrel,vertexing"); + // loop over track cuts and create dilepton - track histogram directories for (int iCutTrack = 0; iCutTrack < fNCuts; iCutTrack++) { @@ -2485,9 +2449,6 @@ struct AnalysisDileptonTrack { DefineHistograms(fHistMan, Form("DileptonTrack_%s_%s", pairLegCutName.Data(), fTrackCutNames[iCutTrack].Data()), fConfigOptions.fConfigHistogramSubgroups.value.data()); for (auto& sig : fRecMCSignals) { DefineHistograms(fHistMan, Form("DileptonTrackMCMatched_%s_%s_%s", pairLegCutName.Data(), fTrackCutNames[iCutTrack].Data(), sig->GetName()), fConfigOptions.fConfigHistogramSubgroups.value.data()); - if (isBarrelME) { - DefineHistograms(fHistMan, Form("DileptonTrackMCMatchedME_%s_%s_%s", pairLegCutName.Data(), fTrackCutNames[iCutTrack].Data(), sig->GetName()), fConfigOptions.fConfigHistogramSubgroups.value.data()); - } } if (!cfgPairing_strCommonTrackCuts.IsNull()) { @@ -2537,18 +2498,6 @@ struct AnalysisDileptonTrack { } } - if (isMCGen_energycorrelators) { - for (auto& sig : fGenMCSignals) { - DefineHistograms(fHistMan, Form("MCTruthEenergyCorrelators_%s", sig->GetName()), ""); - } - } - - if (isMCGen_energycorrelatorsME) { - for (auto& sig : fGenMCSignals) { - DefineHistograms(fHistMan, Form("MCTruthEenergyCorrelatorsME_%s", sig->GetName()), ""); - } - } - TString addHistsStr = fConfigOptions.fConfigAddJSONHistograms.value; if (addHistsStr != "") { dqhistograms::AddHistogramsFromJSON(fHistMan, addHistsStr.Data()); @@ -2616,11 +2565,6 @@ struct AnalysisDileptonTrack { if (dilepton.sign() != 0) { continue; } - // dilepton rap cut - float rap = dilepton.rap(); - if (fConfigMCOptions.fConfigUseMCRapcut && abs(rap) > fConfigOptions.fConfigDileptonRapCutAbs) { - continue; - } VarManager::FillTrack(dilepton, fValuesDilepton); @@ -2679,11 +2623,6 @@ struct AnalysisDileptonTrack { continue; } auto trackMC = track.mcParticle(); - // for the energy correlator analysis - auto motherParticle = lepton1MC.template mothers_first_as(); - std::vector fTransRange = fConfigOptions.fConfigTransRange; - VarManager::FillEnergyCorrelator(dilepton, track, fValuesHadron, fTransRange[0], fTransRange[1], fConfigOptions.fConfigApplyMassEC); - VarManager::FillEnergyCorrelatorsMCUnfolding(dilepton, track, motherParticle, trackMC, fValuesHadron); mcDecision = 0; isig = 0; for (auto sig = fRecMCSignals.begin(); sig != fRecMCSignals.end(); sig++, isig++) { @@ -2885,10 +2824,6 @@ struct AnalysisDileptonTrack { if (!event.isEventSelected_bit(0)) { continue; } - std::vector fSavelessevents = fConfigOptions.fConfigSavelessevents; - if (fSavelessevents[0] > 1 && event.globalIndex() % fSavelessevents[0] == fSavelessevents[1]) { - continue; - } auto groupedBarrelAssocs = assocs.sliceBy(trackAssocsPerCollision, event.globalIndex()); // groupedBarrelAssocs.bindInternalIndicesTo(&assocs); auto groupedDielectrons = dileptons.sliceBy(dielectronsPerCollision, event.globalIndex()); @@ -2898,114 +2833,6 @@ struct AnalysisDileptonTrack { cout << "AnalysisDileptonTrack::processBarrel() completed" << endl; } - void processBarrelMixedEvent(soa::Filtered& events, - BCsWithTimestamps const& bcs, - soa::Join const& assocs, - MyBarrelTracksWithCov const& tracks, soa::Filtered const& dileptons, - McCollisions const& /*mcEvents*/, McParticles const& /*mcTracks*/) - { - if (events.size() == 0) { - return; - } - if (fCurrentRun != bcs.begin().runNumber()) { // start: runNumber - initParamsFromCCDB(bcs.begin().timestamp()); - fCurrentRun = bcs.begin().runNumber(); - } // end: runNumber - // loop over two event comibnations - for (auto& [event1, event2] : selfCombinations(fHashBin, fConfigOptions.fConfigMixingDepth.value, -1, events, events)) { - // fill event quantities - if (!event1.isEventSelected_bit(0) || !event2.isEventSelected_bit(0)) { - continue; - } - std::vector fSavelessevents = fConfigOptions.fConfigSavelessevents; - if (fSavelessevents[0] > 1 && event1.globalIndex() % fSavelessevents[0] == fSavelessevents[1]) { - continue; - } - // get the dilepton slice for event1 - auto evDileptons = dileptons.sliceBy(dielectronsPerCollision, event1.globalIndex()); - evDileptons.bindExternalIndices(&events); - - // get the track associations slice for event2 - auto evAssocs = assocs.sliceBy(trackAssocsPerCollision, event2.globalIndex()); - evAssocs.bindExternalIndices(&events); - - uint32_t mcDecision = static_cast(0); - size_t isig = 0; - - // loop over dileptons - for (auto dilepton : evDileptons) { - // get full track info of tracks based on the index - auto lepton1 = tracks.rawIteratorAt(dilepton.index0Id()); - auto lepton2 = tracks.rawIteratorAt(dilepton.index1Id()); - if (!lepton1.has_mcParticle() || !lepton2.has_mcParticle()) { - continue; - } - auto lepton1MC = lepton1.mcParticle(); - auto lepton2MC = lepton2.mcParticle(); - // Check that the dilepton has zero charge - if (dilepton.sign() != 0) { - continue; - } - // dilepton rap cut - float rap = dilepton.rap(); - if (fConfigMCOptions.fConfigUseMCRapcut && abs(rap) > fConfigOptions.fConfigDileptonRapCutAbs) { - continue; - } - - // loop over associations - for (auto& assoc : evAssocs) { - - // check that this track fulfills at least one of the specified cuts - uint32_t trackSelection = (assoc.isBarrelSelected_raw() & fTrackCutBitMap); - if (!trackSelection) { - continue; - } - - // get the track from this association - // auto track = assoc.template track_as(); - auto track = tracks.rawIteratorAt(assoc.trackId()); - // check that this track is not included in the current dilepton - if (track.globalIndex() == dilepton.index0Id() || track.globalIndex() == dilepton.index1Id()) { - continue; - } - - if (!track.has_mcParticle()) { - continue; - } - auto trackMC = track.mcParticle(); - // for the energy correlator analysis - auto motherParticle = lepton1MC.template mothers_first_as(); - std::vector fTransRange = fConfigOptions.fConfigTransRange; - VarManager::FillEnergyCorrelator(dilepton, track, VarManager::fgValues, fTransRange[0], fTransRange[1], fConfigOptions.fConfigApplyMassEC); - VarManager::FillEnergyCorrelatorsMCUnfolding(dilepton, track, motherParticle, trackMC, VarManager::fgValues); - mcDecision = 0; - isig = 0; - for (auto sig = fRecMCSignals.begin(); sig != fRecMCSignals.end(); sig++, isig++) { - if ((*sig)->CheckSignal(true, lepton1MC, lepton2MC, trackMC)) { - mcDecision |= (static_cast(1) << isig); - } - } - - // loop over dilepton leg cuts and track cuts and fill histograms separately for each combination - for (int icut = 0; icut < fNCuts; icut++) { - if (!dilepton.filterMap_bit(icut)) { - continue; - } - for (uint32_t iTrackCut = 0; iTrackCut < fTrackCutNames.size(); iTrackCut++) { - if (trackSelection & (static_cast(1) << iTrackCut)) { - for (uint32_t isig = 0; isig < fRecMCSignals.size(); isig++) { - if (mcDecision & (static_cast(1) << isig)) { - fHistMan->FillHistClass(Form("DileptonTrackMCMatchedME_%s_%s_%s", fLegCutNames[icut].Data(), fTrackCutNames[iTrackCut].Data(), fRecMCSignals[isig]->GetName()), VarManager::fgValues); - } - } - } - } - } - } // end for (assocs) - } // end for (dileptons) - } // end event loop - } - /* void processDstarToD0Pi(soa::Filtered const& events, BCsWithTimestamps const& bcs, soa::Filtered> const& assocs, MyBarrelTracksWithCov const& tracks, soa::Filtered const& ditracks, @@ -3144,183 +2971,15 @@ struct AnalysisDileptonTrack { cout << "AnalysisDileptonTrack::processMCGen() completed" << endl; } - template - void runEnergyCorrelators(TEvent const& event, McParticles const& mcTracks) - { - auto groupedMCTracks = mcTracks.sliceBy(perReducedMcEvent, event.mcCollisionId()); - groupedMCTracks.bindInternalIndicesTo(&mcTracks); - for (auto& t1 : groupedMCTracks) { - auto t1_raw = mcTracks.rawIteratorAt(t1.globalIndex()); - // apply kinematic cuts for signal - if ((t1_raw.pt() < fConfigOptions.fConfigDileptonLowpTCut || t1_raw.pt() > fConfigOptions.fConfigDileptonHighpTCut)) - continue; - if (abs(t1_raw.y()) > fConfigOptions.fConfigDileptonRapCutAbs) - continue; - // for the energy correlators - for (auto& t2 : groupedMCTracks) { - auto t2_raw = groupedMCTracks.rawIteratorAt(t2.globalIndex()); - if (!t2_raw.isPhysicalPrimary()) { - continue; - } - - if (t2_raw.has_mothers()) { - auto mother_raw = t2_raw.template mothers_first_as(); - if (mother_raw.globalIndex() == t1_raw.globalIndex()) { - continue; - } - } - - if (t2_raw.pt() < fConfigMCOptions.fConfigMCGenHadronPtMin.value || std::abs(t2_raw.eta()) > fConfigMCOptions.fConfigMCGenHadronEtaAbs.value) { - continue; - } - - std::vector fTransRange = fConfigOptions.fConfigTransRange; - VarManager::FillEnergyCorrelatorsMC(t1_raw, t2_raw, VarManager::fgValues, fTransRange[0], fTransRange[1]); - for (auto& sig : fGenMCSignals) { - if (sig->CheckSignal(true, t1_raw)) { - fHistMan->FillHistClass(Form("MCTruthEenergyCorrelators_%s", sig->GetName()), VarManager::fgValues); - } - } - } - } - } - - void processMCGenEnergyCorrelators(soa::Filtered const& events, - McCollisions const& /*mcEvents*/, McParticles const& mcTracks) - { - if (events.size() == 0) { - LOG(warning) << "No events in this TF, going to the next one ..."; - return; - } - for (auto& event : events) { - if (!event.isEventSelected_bit(0)) { - continue; - } - if (!event.has_mcCollision()) { - continue; - } - std::vector fSavelessevents = fConfigOptions.fConfigSavelessevents; - if (fSavelessevents[0] > 1 && event.globalIndex() % fSavelessevents[0] == fSavelessevents[1]) { - continue; - } - runEnergyCorrelators(event, mcTracks); - } - } - - void processMCGenEnergyCorrelatorsPion(soa::Filtered const& events, - McCollisions const& /*mcEvents*/, McParticles const& mcTracks) - { - if (events.size() == 0) { - LOG(warning) << "No events in this TF, going to the next one ..."; - return; - } - for (auto& event : events) { - if (!event.isEventSelected_bit(0)) { - continue; - } - if (!event.has_mcCollision()) { - continue; - } - runEnergyCorrelators(event, mcTracks); - } - } - - template - void runEnergyCorrelatorsMixedEvent(TEvent const& event1, TEvent const& event2, McParticles const& mcTracks) - { - auto groupedMCTracks1 = mcTracks.sliceBy(perReducedMcEvent, event1.mcCollisionId()); - auto groupedMCTracks2 = mcTracks.sliceBy(perReducedMcEvent, event2.mcCollisionId()); - groupedMCTracks1.bindInternalIndicesTo(&mcTracks); - groupedMCTracks2.bindInternalIndicesTo(&mcTracks); - for (auto& t1 : groupedMCTracks1) { - auto t1_raw = mcTracks.rawIteratorAt(t1.globalIndex()); - // apply kinematic cuts for signal - if ((t1_raw.pt() < fConfigOptions.fConfigDileptonLowpTCut || t1_raw.pt() > fConfigOptions.fConfigDileptonHighpTCut)) { - continue; - } - if (abs(t1_raw.y()) > fConfigOptions.fConfigDileptonRapCutAbs) { - continue; - } - // for the energy correlators - for (auto& t2 : groupedMCTracks2) { - auto t2_raw = groupedMCTracks2.rawIteratorAt(t2.globalIndex()); - if (!t2_raw.isPhysicalPrimary()) { - continue; - } - - if (t2_raw.has_mothers()) { - auto mother_raw = t2_raw.template mothers_first_as(); - if (mother_raw.globalIndex() == t1_raw.globalIndex()) { - continue; - } - } - - if (t2_raw.pt() < fConfigMCOptions.fConfigMCGenHadronPtMin.value || std::abs(t2_raw.eta()) > fConfigMCOptions.fConfigMCGenHadronEtaAbs.value) { - continue; - } - - for (auto& sig : fGenMCSignals) { - if (sig->CheckSignal(true, t1_raw)) { - VarManager::FillEnergyCorrelatorsMC(t1_raw, t2_raw, VarManager::fgValues); - fHistMan->FillHistClass(Form("MCTruthEenergyCorrelatorsME_%s", sig->GetName()), VarManager::fgValues); - } - } - } - } - } - - void processMCGenEnergyCorrelatorsME(soa::Filtered const& events, - McCollisions const& /*mcEvents*/, McParticles const& mcTracks) - { - if (events.size() == 0) { - LOG(warning) << "No events in this TF, going to the next one ..."; - return; - } - // loop over two event comibnations - for (auto& [event1, event2] : selfCombinations(fHashBin, fConfigOptions.fConfigMixingDepth.value, -1, events, events)) { - if (!event1.isEventSelected_bit(0) || !event2.isEventSelected_bit(0)) { - continue; - } - if (!event1.has_mcCollision() || !event2.has_mcCollision()) { - continue; - } - runEnergyCorrelatorsMixedEvent(event1, event2, mcTracks); - } - } - - void processMCGenEnergyCorrelatorsPionME(soa::Filtered const& events, - McCollisions const& /*mcEvents*/, McParticles const& mcTracks) - { - if (events.size() == 0) { - LOG(warning) << "No events in this TF, going to the next one ..."; - return; - } - // loop over two event comibnations - for (auto& [event1, event2] : selfCombinations(fHashBin, fConfigOptions.fConfigMixingDepth.value, -1, events, events)) { - if (!event1.isEventSelected_bit(0) || !event2.isEventSelected_bit(0)) { - continue; - } - if (!event1.has_mcCollision() || !event2.has_mcCollision()) { - continue; - } - runEnergyCorrelatorsMixedEvent(event1, event2, mcTracks); - } - } - void processDummy(MyEvents&) { // do nothing } PROCESS_SWITCH(AnalysisDileptonTrack, processBarrel, "Run barrel dilepton-track pairing, using skimmed data", false); - PROCESS_SWITCH(AnalysisDileptonTrack, processBarrelMixedEvent, "Run barrel dilepton-hadron mixed event pairing", false); // PROCESS_SWITCH(AnalysisDileptonTrack, processDstarToD0Pi, "Run barrel pairing of D0 daughters with pion candidate, using skimmed data", false); // PROCESS_SWITCH(AnalysisDileptonTrack, processMuonSkimmed, "Run muon dilepton-track pairing, using skimmed data", false); PROCESS_SWITCH(AnalysisDileptonTrack, processMCGen, "Loop over MC particle stack and fill generator level histograms", false); - PROCESS_SWITCH(AnalysisDileptonTrack, processMCGenEnergyCorrelators, "Loop over MC particle stack and fill generator level histograms(energy correlators)", false); - PROCESS_SWITCH(AnalysisDileptonTrack, processMCGenEnergyCorrelatorsPion, "Loop over MC particle stack and fill generator level histograms(energy correlators)", false); - PROCESS_SWITCH(AnalysisDileptonTrack, processMCGenEnergyCorrelatorsME, "Loop over MC particle stack and fill generator level histograms(energy correlators)", false); - PROCESS_SWITCH(AnalysisDileptonTrack, processMCGenEnergyCorrelatorsPionME, "Loop over MC particle stack and fill generator level histograms(energy correlators)", false); PROCESS_SWITCH(AnalysisDileptonTrack, processDummy, "Dummy function", true); }; @@ -3431,9 +3090,5 @@ void DefineHistograms(HistogramManager* histMan, TString histClasses, const char if (classStr.Contains("DileptonHadronCorrelation")) { dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "dilepton-hadron-correlation"); } - - if (classStr.Contains("MCTruthEenergyCorrelators")) { - dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "energy-correlator-gen"); - } } // end loop over histogram classes } diff --git a/PWGDQ/Tasks/tableReader_withAssoc.cxx b/PWGDQ/Tasks/tableReader_withAssoc.cxx index 2b112f3c15d..4d22ba5eac8 100644 --- a/PWGDQ/Tasks/tableReader_withAssoc.cxx +++ b/PWGDQ/Tasks/tableReader_withAssoc.cxx @@ -3602,7 +3602,7 @@ struct AnalysisDileptonTrack { } // dilepton rap cut float rap = dilepton.rap(); - if (fConfigUseRapcut && abs(rap) > fConfigDileptonRapCutAbs) + if (fConfigUseRapcut && std::abs(rap) > fConfigDileptonRapCutAbs) continue; VarManager::FillTrack(dilepton, fValuesDilepton); @@ -3660,7 +3660,7 @@ struct AnalysisDileptonTrack { // for the energy correlator analysis std::vector fTransRange = fConfigTransRange; - VarManager::FillEnergyCorrelator(dilepton, track, fValuesHadron, fTransRange[0], fTransRange[1], fConfigApplyMassEC, fMassBkg->GetRandom()); + VarManager::FillEnergyCorrelatorTriple(lepton1, lepton2, track, fValuesHadron, fTransRange[0], fTransRange[1], fConfigApplyMassEC, fMassBkg->GetRandom()); // table to be written out for ML analysis BmesonsTable(event.runNumber(), event.globalIndex(), event.timestamp(), fValuesHadron[VarManager::kPairMass], dilepton.mass(), fValuesHadron[VarManager::kDeltaMass], fValuesHadron[VarManager::kPairPt], fValuesHadron[VarManager::kPairEta], fValuesHadron[VarManager::kPairPhi], fValuesHadron[VarManager::kPairRap], @@ -3817,7 +3817,7 @@ struct AnalysisDileptonTrack { void processBarrelMixedEvent(soa::Filtered& events, soa::Filtered> const& assocs, - MyBarrelTracksWithCov const&, soa::Filtered const& dileptons) + MyBarrelTracksWithCov const& tracks, soa::Filtered const& dileptons) { if (events.size() == 0) { return; @@ -3853,10 +3853,16 @@ struct AnalysisDileptonTrack { // loop over dileptons for (auto dilepton : evDileptons) { - + // get full track info of tracks based on the index + auto lepton1 = tracks.rawIteratorAt(dilepton.index0Id()); + auto lepton2 = tracks.rawIteratorAt(dilepton.index1Id()); + // Check that the dilepton has zero charge + if (dilepton.sign() != 0) { + continue; + } // dilepton rap cut float rap = dilepton.rap(); - if (fConfigUseRapcut && abs(rap) > fConfigDileptonRapCutAbs) + if (fConfigUseRapcut && std::abs(rap) > fConfigDileptonRapCutAbs) continue; // compute dilepton - track quantities @@ -3864,7 +3870,7 @@ struct AnalysisDileptonTrack { // for the energy correlator analysis std::vector fTransRange = fConfigTransRange; - VarManager::FillEnergyCorrelator(dilepton, track, VarManager::fgValues, fTransRange[0], fTransRange[1], fConfigApplyMassEC, fMassBkg->GetRandom()); + VarManager::FillEnergyCorrelatorTriple(lepton1, lepton2, track, fValuesHadron, fTransRange[0], fTransRange[1], fConfigApplyMassEC, fMassBkg->GetRandom()); // loop over dilepton leg cuts and track cuts and fill histograms separately for each combination for (int icut = 0; icut < fNCuts; icut++) { From 82601d3ab0ec099e701c472205143b7910a6e954 Mon Sep 17 00:00:00 2001 From: Shirajum Monira <38348689+Eloviyo@users.noreply.github.com> Date: Tue, 10 Mar 2026 19:25:04 +0200 Subject: [PATCH 240/347] [PWGCF] FemtoUniverse V0 Task -- added has TOF check for combined signa PID (#15317) Co-authored-by: Shirajum Monira --- .../femtoUniversePairTaskTrackV0Extended.cxx | 42 +++++++++++++------ 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx index 91c5826fbec..f10e793f263 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx @@ -203,9 +203,9 @@ struct FemtoUniversePairTaskTrackV0Extended { std::unique_ptr pEffHistp2; Service ccdb; - bool isNSigmaCombined(float mom, float nsigmaTPCParticle, float nsigmaTOFParticle) + bool isNSigmaCombined(float mom, float nsigmaTPCParticle, float nsigmaTOFParticle, bool hasTOF) { - if (mom <= confmom) { + if (mom <= confmom || hasTOF == 0) { return (std::abs(nsigmaTPCParticle) < confNsigmaTPCParticle); } else { return (std::hypot(nsigmaTOFParticle, nsigmaTPCParticle) < confNsigmaCombinedParticle); @@ -236,7 +236,7 @@ struct FemtoUniversePairTaskTrackV0Extended { } } - bool isNSigmaTOF(float mom, float nsigmaTOFParticle, float hasTOF) + bool isNSigmaTOF(float mom, float nsigmaTOFParticle, bool hasTOF) { // Cut only on daughter tracks, that have TOF signal if (mom > confmom && hasTOF == 1) { @@ -256,7 +256,7 @@ struct FemtoUniversePairTaskTrackV0Extended { const float tpcNSigmas[3] = {aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePr()), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePi()), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStoreKa())}; const float tofNSigmas[3] = {aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePr()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePi()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStoreKa())}; - return isNSigmaCombined(part.p(), tpcNSigmas[id], tofNSigmas[id]); + return isNSigmaCombined(part.p(), tpcNSigmas[id], tofNSigmas[id], (part.pidCut() & 512u) != 0); } template @@ -470,7 +470,7 @@ struct FemtoUniversePairTaskTrackV0Extended { const float tpcNSigmas[3] = {aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePr()), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePi()), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStoreKa())}; const float tofNSigmas[3] = {aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePr()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePi()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStoreKa())}; - if (!isNSigmaCombined(part.p(), tpcNSigmas[ConfTrkSelection.confTrackChoicePartOne], tofNSigmas[ConfTrkSelection.confTrackChoicePartOne])) + if (!isNSigmaCombined(part.p(), tpcNSigmas[ConfTrkSelection.confTrackChoicePartOne], tofNSigmas[ConfTrkSelection.confTrackChoicePartOne], (part.pidCut() & 512u) != 0)) continue; if (part.sign() > 0) { qaRegistry.fill(HIST("Tracks_pos/nSigmaTPC"), part.p(), tpcNSigmas[ConfTrkSelection.confTrackChoicePartOne]); @@ -1604,21 +1604,29 @@ struct FemtoUniversePairTaskTrackV0Extended { registryMCreco.fill(HIST("plus/MCrecoAllPt"), mcpart.pt()); if (mcpart.pdgMCTruth() == kPiPlus) { if constexpr (std::experimental::is_detected::value) { - if (!isNSigmaCombined(part.p(), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePi()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePi()))) + if (!isNSigmaCombined(part.p(), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePi()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePi()), (part.pidCut() & 512u) != 0)) continue; } else { - if ((part.pidCut() & 128u) == 0) // 128 for pion combined + if ((part.pidCut() & 512u) != 0) { + if ((part.pidCut() & 128u) == 0) // 128 for pion combined + continue; + } else if ((part.pidCut() & 2u) == 0) { continue; + } } registryMCreco.fill(HIST("plus/MCrecoPi"), mcpart.pt(), mcpart.eta()); registryMCreco.fill(HIST("plus/MCrecoPiPt"), mcpart.pt()); } else if (mcpart.pdgMCTruth() == kProton) { if constexpr (std::experimental::is_detected::value) { - if (!isNSigmaCombined(part.p(), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePr()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePr()))) + if (!isNSigmaCombined(part.p(), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePr()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePr()), (part.pidCut() & 512u) != 0)) continue; } else { - if ((part.pidCut() & 64u) == 0) // 64 for proton combined + if ((part.pidCut() & 512u) != 0) { + if ((part.pidCut() & 64u) == 0) // 64 for proton combined + continue; + } else if ((part.pidCut() & 1u) == 0) { continue; + } } registryMCreco.fill(HIST("plus/MCrecoPr"), mcpart.pt(), mcpart.eta()); registryMCreco.fill(HIST("plus/MCrecoPrPt"), mcpart.pt()); @@ -1627,21 +1635,29 @@ struct FemtoUniversePairTaskTrackV0Extended { registryMCreco.fill(HIST("minus/MCrecoAllPt"), mcpart.pt()); if (mcpart.pdgMCTruth() == kPiMinus) { if constexpr (std::experimental::is_detected::value) { - if (!isNSigmaCombined(part.p(), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePi()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePi()))) + if (!isNSigmaCombined(part.p(), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePi()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePi()), (part.pidCut() & 512u) != 0)) continue; } else { - if ((part.pidCut() & 128u) == 0) // 128 for pion combined + if ((part.pidCut() & 512u) != 0) { + if ((part.pidCut() & 128u) == 0) // 128 for pion combined + continue; + } else if ((part.pidCut() & 2u) == 0) { continue; + } } registryMCreco.fill(HIST("minus/MCrecoPi"), mcpart.pt(), mcpart.eta()); registryMCreco.fill(HIST("minus/MCrecoPiPt"), mcpart.pt()); } else if (mcpart.pdgMCTruth() == kProtonBar) { if constexpr (std::experimental::is_detected::value) { - if (!isNSigmaCombined(part.p(), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePr()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePr()))) + if (!isNSigmaCombined(part.p(), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePr()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePr()), (part.pidCut() & 512u) != 0)) continue; } else { - if ((part.pidCut() & 64u) == 0) // 64 for proton combined + if ((part.pidCut() & 512u) != 0) { + if ((part.pidCut() & 64u) == 0) // 64 for proton combined + continue; + } else if ((part.pidCut() & 1u) == 0) { continue; + } } registryMCreco.fill(HIST("minus/MCrecoPr"), mcpart.pt(), mcpart.eta()); registryMCreco.fill(HIST("minus/MCrecoPrPt"), mcpart.pt()); From a79afd714fbefd27e91b4939d2b929d2bbf7822f Mon Sep 17 00:00:00 2001 From: ikantak <149821212+ikantak@users.noreply.github.com> Date: Tue, 10 Mar 2026 18:29:44 +0100 Subject: [PATCH 241/347] [PWGEM] Add new ML features and add optional alpha meson cut (#15323) Co-authored-by: Isabel Kantak --- PWGEM/PhotonMeson/Core/EmMlResponsePCM.h | 87 ++++++++++- PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h | 30 ++++ PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h | 30 ++++ PWGEM/PhotonMeson/Core/V0PhotonCandidate.h | 142 +++++++++++++++--- .../TableProducer/photonconversionbuilder.cxx | 12 +- 5 files changed, 275 insertions(+), 26 deletions(-) diff --git a/PWGEM/PhotonMeson/Core/EmMlResponsePCM.h b/PWGEM/PhotonMeson/Core/EmMlResponsePCM.h index baa9330ad95..b46e258353c 100644 --- a/PWGEM/PhotonMeson/Core/EmMlResponsePCM.h +++ b/PWGEM/PhotonMeson/Core/EmMlResponsePCM.h @@ -53,20 +53,47 @@ namespace o2::analysis { enum class InputFeaturesPCM : uint8_t { + v0PhotonCandidatefVx, + v0PhotonCandidatefVy, + v0PhotonCandidatefVz, v0PhotonCandidatefDCAxyToPV, v0PhotonCandidatefDCAzToPV, v0PhotonCandidatefPCA, v0PhotonCandidatefAlpha, v0PhotonCandidatefQtArm, v0PhotonCandidatefChiSquareNDF, + v0PhotonCandidatefCosPARZ, + v0PhotonCandidatefCosPAXY, v0PhotonCandidatefCosPA, + v0PhotonCandidatefPsiPair, + v0PhotonCandidatefPhiV, + posV0LegfDCAXY, + posV0LegfDCAZ, + posV0LegfEta, + posV0LegfTPCNClsShared, + posV0LegfTPCNClsFindable, + posV0LegfTPCNClsFindableMinusFound, + posV0LegfTPCNClsFindableMinusCrossedRows, + posV0LegfTPCChi2NCl, + posV0LegfTPCSignal, posV0LegfTPCNSigmaEl, posV0LegfTPCNSigmaPi, + posV0LegfITSClusterSizes, + negV0LegfDCAXY, + negV0LegfDCAZ, + negV0LegfEta, + negV0LegfTPCNClsShared, + negV0LegfTPCNClsFindable, + negV0LegfTPCNClsFindableMinusFound, + negV0LegfTPCNClsFindableMinusCrossedRows, + negV0LegfTPCChi2NCl, + negV0LegfTPCSignal, negV0LegfTPCNSigmaEl, - negV0LegfTPCNSigmaPi + negV0LegfTPCNSigmaPi, + negV0LegfITSClusterSizes }; -template +template class EmMlResponsePCM : public EmMlResponse { public: @@ -85,17 +112,44 @@ class EmMlResponsePCM : public EmMlResponse for (const auto& idx : MlResponse::mCachedIndices) { switch (idx) { + CHECK_AND_FILL_VEC_PCM_FULL(candidate, v0PhotonCandidatefVx, getConversionPointX); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, v0PhotonCandidatefVy, getConversionPointY); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, v0PhotonCandidatefVz, getConversionPointZ); CHECK_AND_FILL_VEC_PCM_FULL(candidate, v0PhotonCandidatefDCAxyToPV, getDcaXYToPV); CHECK_AND_FILL_VEC_PCM_FULL(candidate, v0PhotonCandidatefDCAzToPV, getDcaZToPV); CHECK_AND_FILL_VEC_PCM_FULL(candidate, v0PhotonCandidatefPCA, getPCA); CHECK_AND_FILL_VEC_PCM_FULL(candidate, v0PhotonCandidatefAlpha, getAlpha); CHECK_AND_FILL_VEC_PCM_FULL(candidate, v0PhotonCandidatefQtArm, getQt); CHECK_AND_FILL_VEC_PCM_FULL(candidate, v0PhotonCandidatefChiSquareNDF, getChi2NDF); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, v0PhotonCandidatefCosPARZ, getCosPARZ); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, v0PhotonCandidatefCosPAXY, getCosPAXY); CHECK_AND_FILL_VEC_PCM_FULL(candidate, v0PhotonCandidatefCosPA, getCosPA); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, v0PhotonCandidatefPsiPair, getPsiPair); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, v0PhotonCandidatefPhiV, getPhiV); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, posV0LegfDCAXY, getPosDcaXY); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, posV0LegfDCAZ, getPosDcaZ); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, posV0LegfEta, getPosEta); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, posV0LegfTPCNClsShared, getPosTPCNClsShared); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, posV0LegfTPCNClsFindable, getPosTPCNClsFindable); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, posV0LegfTPCNClsFindableMinusFound, getPosTPCNClsFindableMinusShared); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, posV0LegfTPCNClsFindableMinusCrossedRows, getPosTPCNClsFindableMinusCrossedRows); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, posV0LegfTPCChi2NCl, getPosTPCChi2NCl); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, posV0LegfTPCSignal, getPosTPCSignal); CHECK_AND_FILL_VEC_PCM_FULL(posLeg, posV0LegfTPCNSigmaEl, tpcNSigmaEl); CHECK_AND_FILL_VEC_PCM_FULL(posLeg, posV0LegfTPCNSigmaPi, tpcNSigmaPi); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, posV0LegfITSClusterSizes, getPosITSClusterSizes); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, negV0LegfDCAXY, getEleDcaXY); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, negV0LegfDCAZ, getEleDcaZ); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, negV0LegfEta, getEleEta); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, negV0LegfTPCNClsShared, getEleTPCNClsShared); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, negV0LegfTPCNClsFindable, getEleTPCNClsFindable); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, negV0LegfTPCNClsFindableMinusFound, getEleTPCNClsFindableMinusShared); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, negV0LegfTPCNClsFindableMinusCrossedRows, getEleTPCNClsFindableMinusCrossedRows); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, negV0LegfTPCChi2NCl, getEleTPCChi2NCl); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, negV0LegfTPCSignal, getEleTPCSignal); CHECK_AND_FILL_VEC_PCM_FULL(negLeg, negV0LegfTPCNSigmaEl, tpcNSigmaEl); CHECK_AND_FILL_VEC_PCM_FULL(negLeg, negV0LegfTPCNSigmaPi, tpcNSigmaPi); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, negV0LegfITSClusterSizes, getEleITSClusterSizes); } } return inputFeatures; @@ -106,17 +160,44 @@ class EmMlResponsePCM : public EmMlResponse void setAvailableInputFeatures() { MlResponse::mAvailableInputFeatures = { + FILL_MAP_PCM(v0PhotonCandidatefVx), + FILL_MAP_PCM(v0PhotonCandidatefVy), + FILL_MAP_PCM(v0PhotonCandidatefVz), FILL_MAP_PCM(v0PhotonCandidatefDCAxyToPV), FILL_MAP_PCM(v0PhotonCandidatefDCAzToPV), FILL_MAP_PCM(v0PhotonCandidatefPCA), FILL_MAP_PCM(v0PhotonCandidatefAlpha), FILL_MAP_PCM(v0PhotonCandidatefQtArm), FILL_MAP_PCM(v0PhotonCandidatefChiSquareNDF), + FILL_MAP_PCM(v0PhotonCandidatefCosPARZ), + FILL_MAP_PCM(v0PhotonCandidatefCosPAXY), FILL_MAP_PCM(v0PhotonCandidatefCosPA), + FILL_MAP_PCM(v0PhotonCandidatefPsiPair), + FILL_MAP_PCM(v0PhotonCandidatefPhiV), + FILL_MAP_PCM(posV0LegfDCAXY), + FILL_MAP_PCM(posV0LegfDCAZ), + FILL_MAP_PCM(posV0LegfEta), + FILL_MAP_PCM(posV0LegfTPCNClsShared), + FILL_MAP_PCM(posV0LegfTPCNClsFindable), + FILL_MAP_PCM(posV0LegfTPCNClsFindableMinusFound), + FILL_MAP_PCM(posV0LegfTPCNClsFindableMinusCrossedRows), + FILL_MAP_PCM(posV0LegfTPCChi2NCl), + FILL_MAP_PCM(posV0LegfTPCSignal), FILL_MAP_PCM(posV0LegfTPCNSigmaEl), FILL_MAP_PCM(posV0LegfTPCNSigmaPi), + FILL_MAP_PCM(posV0LegfITSClusterSizes), + FILL_MAP_PCM(negV0LegfDCAXY), + FILL_MAP_PCM(negV0LegfDCAZ), + FILL_MAP_PCM(negV0LegfEta), + FILL_MAP_PCM(negV0LegfTPCNClsShared), + FILL_MAP_PCM(negV0LegfTPCNClsFindable), + FILL_MAP_PCM(negV0LegfTPCNClsFindableMinusFound), + FILL_MAP_PCM(negV0LegfTPCNClsFindableMinusCrossedRows), + FILL_MAP_PCM(negV0LegfTPCChi2NCl), + FILL_MAP_PCM(negV0LegfTPCSignal), FILL_MAP_PCM(negV0LegfTPCNSigmaEl), - FILL_MAP_PCM(negV0LegfTPCNSigmaPi)}; + FILL_MAP_PCM(negV0LegfTPCNSigmaPi), + FILL_MAP_PCM(negV0LegfITSClusterSizes)}; } }; diff --git a/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h b/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h index 952fc5348ea..0ff535f45dc 100644 --- a/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h +++ b/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h @@ -70,6 +70,12 @@ #include #include +enum AlphaMesonCutOption { + Off = 0, + SpecificValue = 1, + PTDependent = 2 +}; + template struct Pi0EtaToGammaGamma { o2::framework::Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; @@ -92,6 +98,11 @@ struct Pi0EtaToGammaGamma { o2::framework::ConfigurableAxis ConfEPBins{"ConfEPBins", {o2::framework::VARIABLE_WIDTH, -o2::constants::math::PIHalf, -o2::constants::math::PIQuarter, 0.0f, +o2::constants::math::PIQuarter, +o2::constants::math::PIHalf}, "Mixing bins - event plane angle"}; o2::framework::ConfigurableAxis ConfOccupancyBins{"ConfOccupancyBins", {o2::framework::VARIABLE_WIDTH, -1, 1e+10}, "Mixing bins - occupancy"}; + o2::framework::Configurable cfgAlphaMesonCut{"cfgAlphaMesonCut", 0, "flag for photon energy asymmetry distribution cut: 0: no cut, 1: cut specific value, 2: cut depending on pT"}; + o2::framework::Configurable cfgAlphaMeson{"cfgAlphaMeson", 0.65, "photon energy asymmetry distribution parameter for specific value cut"}; + o2::framework::Configurable cfgAlphaMesonA{"cfgAlphaMesonA", 0.65, "photon energy asymmetry distribution parameter A for pT dependent cut (A * tanh(B*pT))"}; + o2::framework::Configurable cfgAlphaMesonB{"cfgAlphaMesonB", 1.2, "photon energy asymmetry distribution parameter B for pT dependent cut (A * tanh(B*pT))"}; + EMPhotonEventCut fEMEventCut; struct : o2::framework::ConfigurableGroup { std::string prefix = "eventcut_group"; @@ -880,6 +891,25 @@ struct Pi0EtaToGammaGamma { continue; } + float alphaMeson = std::fabs(g1.e() - g2.e()) / (g1.e() + g2.e()); + float alphaCut = 999.f; + switch (static_cast(cfgAlphaMesonCut.value)) { + case AlphaMesonCutOption::Off: + break; + case AlphaMesonCutOption::SpecificValue: + alphaCut = cfgAlphaMeson; + break; + case AlphaMesonCutOption::PTDependent: { + alphaCut = cfgAlphaMesonA * std::tanh(cfgAlphaMesonB * v12.pt()); + break; + } + default: + LOGF(error, "Invalid option for alpha meson cut. No alpha cut will be applied."); + } + if (alphaMeson > alphaCut) { + continue; + } + fRegistry.fill(HIST("Pair/same/hs"), v12.M(), v12.Pt(), weight); if (std::find(used_photonIds_per_col.begin(), used_photonIds_per_col.end(), g1.globalIndex()) == used_photonIds_per_col.end()) { diff --git a/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h b/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h index 9170a97ea73..a44ec614df0 100644 --- a/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h +++ b/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h @@ -65,6 +65,12 @@ #include #include +enum AlphaMesonCutOption { + Off = 0, + SpecificValue = 1, + PTDependent = 2 +}; + template struct Pi0EtaToGammaGammaMC { o2::framework::Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; @@ -81,6 +87,11 @@ struct Pi0EtaToGammaGammaMC { o2::framework::Configurable fd_k0s_to_pi0{"fd_k0s_pi0", "1.0", "feed down correction to pi0"}; o2::framework::Configurable cfgRequireTrueAssociation{"cfgRequireTrueAssociation", false, "flag to require true mc collision association"}; + o2::framework::Configurable cfgAlphaMesonCut{"cfgAlphaMesonCut", 0, "flag for photon energy asymmetry distribution cut: 0: no cut, 1: cut specific value, 2: cut depending on pT"}; + o2::framework::Configurable cfgAlphaMeson{"cfgAlphaMeson", 0.65, "photon energy asymmetry distribution parameter for specific value cut"}; + o2::framework::Configurable cfgAlphaMesonA{"cfgAlphaMesonA", 0.65, "photon energy asymmetry distribution parameter A for pT dependent cut (A * tanh(B*pT))"}; + o2::framework::Configurable cfgAlphaMesonB{"cfgAlphaMesonB", 1.2, "photon energy asymmetry distribution parameter B for pT dependent cut (A * tanh(B*pT))"}; + EMPhotonEventCut fEMEventCut; struct : o2::framework::ConfigurableGroup { std::string prefix = "eventcut_group"; @@ -672,6 +683,25 @@ struct Pi0EtaToGammaGammaMC { continue; } + float alphaMeson = std::fabs(g1.e() - g2.e()) / (g1.e() + g2.e()); + float alphaCut = 999.f; + switch (static_cast(cfgAlphaMesonCut.value)) { + case AlphaMesonCutOption::Off: + break; + case AlphaMesonCutOption::SpecificValue: + alphaCut = cfgAlphaMeson; + break; + case AlphaMesonCutOption::PTDependent: { + alphaCut = cfgAlphaMesonA * std::tanh(cfgAlphaMesonB * v12.pt()); + break; + } + default: + LOGF(error, "Invalid option for alpha meson cut. No alpha cut will be applied."); + } + if (alphaMeson > alphaCut) { + continue; + } + if (pairtype == o2::aod::pwgem::photonmeson::photonpair::PairType::kEMCEMC) { float openingAngle = std::acos(v1.Vect().Dot(v2.Vect()) / (v1.P() * v2.P())); if (openingAngle < emccuts.minOpenAngle) { diff --git a/PWGEM/PhotonMeson/Core/V0PhotonCandidate.h b/PWGEM/PhotonMeson/Core/V0PhotonCandidate.h index d81c803ca2c..c29925b4bfb 100644 --- a/PWGEM/PhotonMeson/Core/V0PhotonCandidate.h +++ b/PWGEM/PhotonMeson/Core/V0PhotonCandidate.h @@ -35,41 +35,71 @@ struct V0PhotonCandidate { // Empty Constructor V0PhotonCandidate() = default; // Set method for photonconversionbuilder - void setPhotonCandidate(const KFParticle& v0, const KFParticle& pos, const KFParticle& ele, const auto& collision, float cospa, float psipair, float phiv, CentType centType) + template + void setPhotonCandidate(const KFParticle& v0DecayVtx, const KFParticle& v0PV, const TTrack& pos, const KFParticle& posDecayVtx, const TTrack& ele, const KFParticle& eleDecayVtx, const auto& collision, float cospa, float cospaRZ, float cospaXY, float psipair, float phiv, CentType centType, auto posdcaXY, auto eledcaXY, auto posdcaZ, auto eledcaZ) { - px = v0.GetPx(); - py = v0.GetPy(); - pz = v0.GetPz(); + conversionPointx = v0DecayVtx.GetX(); + conversionPointy = v0DecayVtx.GetY(); + conversionPointz = v0DecayVtx.GetZ(); + px = v0PV.GetPx(); + py = v0PV.GetPy(); + pz = v0PV.GetPz(); pT = RecoDecay::sqrtSumOfSquares(px, py); - posPx = pos.GetPx(); - posPy = pos.GetPy(); - posPz = pos.GetPz(); - elePx = ele.GetPx(); - elePy = ele.GetPy(); - elePz = ele.GetPz(); + posPx = posDecayVtx.GetPx(); + posPy = posDecayVtx.GetPy(); + posPz = posDecayVtx.GetPz(); + elePx = eleDecayVtx.GetPx(); + elePy = eleDecayVtx.GetPy(); + elePz = eleDecayVtx.GetPz(); posPT = RecoDecay::sqrtSumOfSquares(posPx, posPy); elePT = RecoDecay::sqrtSumOfSquares(elePx, elePy); + posEta = RecoDecay::eta(std::array{posPx, posPy, posPz}); + eleEta = RecoDecay::eta(std::array{elePx, elePy, elePz}); - chi2ndf = v0.GetChi2() / v0.GetNDF(); - pca = pos.GetDistanceFromParticle(ele); + posTPCNClsShared = pos.tpcNClsShared(); + posTPCNClsFindable = pos.tpcNClsFindable(); + posTPCNClsFindableMinusShared = pos.tpcNClsFindableMinusFound(); + posTPCNClsFindableMinusCrossedRows = pos.tpcNClsFindableMinusCrossedRows(); + posTPCChi2NCl = pos.tpcChi2NCl(); + posTPCSignal = pos.tpcSignal(); + posITSClusterSizes = pos.itsClusterSizes(); + eleTPCNClsShared = ele.tpcNClsShared(); + eleTPCNClsFindable = ele.tpcNClsFindable(); + eleTPCNClsFindableMinusShared = ele.tpcNClsFindableMinusFound(); + eleTPCNClsFindableMinusCrossedRows = ele.tpcNClsFindableMinusCrossedRows(); + eleTPCChi2NCl = ele.tpcChi2NCl(); + eleTPCSignal = ele.tpcSignal(); + eleITSClusterSizes = ele.itsClusterSizes(); - float v0mom = RecoDecay::sqrtSumOfSquares(v0.GetPx(), v0.GetPy(), v0.GetPz()); - float length = RecoDecay::sqrtSumOfSquares(v0.GetX() - collision.posX(), v0.GetY() - collision.posY(), v0.GetZ() - collision.posZ()); - float dcaXV0ToPV = (v0.GetX() - v0.GetPx() * cospa * length / v0mom) - collision.posX(); - float dcaYV0ToPV = (v0.GetY() - v0.GetPy() * cospa * length / v0mom) - collision.posY(); + chi2ndf = v0DecayVtx.GetChi2() / v0DecayVtx.GetNDF(); + pca = posDecayVtx.GetDistanceFromParticle(eleDecayVtx); + eta = RecoDecay::eta(std::array{px, py, pz}); + posEta = RecoDecay::eta(std::array{posPx, posPy, posPz}); + eleEta = RecoDecay::eta(std::array{elePx, elePy, elePz}); + + float v0mom = RecoDecay::sqrtSumOfSquares(v0DecayVtx.GetPx(), v0DecayVtx.GetPy(), v0DecayVtx.GetPz()); + float length = RecoDecay::sqrtSumOfSquares(v0DecayVtx.GetX() - collision.posX(), v0DecayVtx.GetY() - collision.posY(), v0DecayVtx.GetZ() - collision.posZ()); + float dcaXV0ToPV = (v0DecayVtx.GetX() - v0DecayVtx.GetPx() * cospa * length / v0mom) - collision.posX(); + float dcaYV0ToPV = (v0DecayVtx.GetY() - v0DecayVtx.GetPy() * cospa * length / v0mom) - collision.posY(); float tmpSign = (dcaXV0ToPV * dcaYV0ToPV > 0.f) ? +1.f : -1.f; dcaXYV0ToPV = RecoDecay::sqrtSumOfSquares(dcaXV0ToPV, dcaYV0ToPV) * tmpSign; - dcaZV0ToPV = (v0.GetZ() - v0.GetPz() * cospa * length / v0mom) - collision.posZ(); + dcaZV0ToPV = (v0DecayVtx.GetZ() - v0DecayVtx.GetPz() * cospa * length / v0mom) - collision.posZ(); alpha = v0_alpha(posPx, posPy, posPz, elePx, elePy, elePz); qt = v0_qt(posPx, posPy, posPz, elePx, elePy, elePz); this->cospa = cospa; + this->cospaRZ = cospaRZ; + this->cospaXY = cospaXY; this->psipair = psipair; this->phiv = phiv; this->centType = centType; + this->posdcaXY = posdcaXY; + this->eledcaXY = eledcaXY; + this->posdcaZ = posdcaZ; + this->eledcaZ = eledcaZ; switch (centType) { case CentType::CentFT0A: @@ -87,6 +117,9 @@ struct V0PhotonCandidate { // Set-Method for V0PhotonCut void setPhoton(const auto& v0, const auto& pos, const auto& ele, float cent, CentType centType) { + conversionPointx = v0.vx(); + conversionPointy = v0.vy(); + conversionPointz = v0.vz(); px = v0.px(); py = v0.py(); pz = v0.pz(); @@ -100,14 +133,37 @@ struct V0PhotonCandidate { elePz = ele.pz(); posPT = pos.pt(); elePT = ele.pt(); + posEta = pos.eta(); + eleEta = ele.eta(); + posdcaXY = pos.dcaXY(); + posdcaZ = pos.dcaZ(); + eledcaXY = ele.dcaXY(); + eledcaZ = ele.dcaZ(); + posTPCNClsShared = pos.tpcNClsShared(); + posTPCNClsFindable = pos.tpcNClsFindable(); + posTPCNClsFindableMinusShared = pos.tpcNClsFindableMinusFound(); + posTPCNClsFindableMinusCrossedRows = pos.tpcNClsFindableMinusCrossedRows(); + posTPCChi2NCl = pos.tpcChi2NCl(); + posTPCSignal = pos.tpcSignal(); + posITSClusterSizes = pos.itsClusterSizes(); + eleTPCNClsShared = ele.tpcNClsShared(); + eleTPCNClsFindable = ele.tpcNClsFindable(); + eleTPCNClsFindableMinusShared = ele.tpcNClsFindableMinusFound(); + eleTPCNClsFindableMinusCrossedRows = ele.tpcNClsFindableMinusCrossedRows(); + eleTPCChi2NCl = ele.tpcChi2NCl(); + eleTPCSignal = ele.tpcSignal(); + eleITSClusterSizes = ele.itsClusterSizes(); chi2ndf = v0.chiSquareNDF(); pca = v0.pca(); + eta = v0.eta(); dcaXYV0ToPV = v0.dcaXYtopv(); dcaZV0ToPV = v0.dcaZtopv(); cospa = v0.cospa(); + cospaRZ = v0.cospaRZ(); + cospaXY = v0.cospaXY(); alpha = v0.alpha(); qt = v0.qtarm(); psipair = 999.f; // default if V0PhotonPhiVPsi table is not included @@ -131,6 +187,14 @@ struct V0PhotonCandidate { float getPhiV() const { return phiv; } float getPsiPair() const { return psipair; } float getCosPA() const { return cospa; } + float getCosPARZ() const { return cospaRZ; } + float getCosPAXY() const { return cospaXY; } + float getEta() const { return eta; } + float getPosEta() const { return posEta; } + float getEleEta() const { return eleEta; } + float getConversionPointX() const { return conversionPointx; } + float getConversionPointY() const { return conversionPointy; } + float getConversionPointZ() const { return conversionPointz; } float getPx() const { return px; } float getPy() const { return py; } float getPz() const { return pz; } @@ -141,11 +205,32 @@ struct V0PhotonCandidate { float getElePx() const { return elePx; } float getElePy() const { return elePy; } float getElePz() const { return elePz; } + float getPosDcaXY() const { return posdcaXY; } + float getPosDcaZ() const { return posdcaZ; } + float getEleDcaXY() const { return eledcaXY; } + float getEleDcaZ() const { return eledcaZ; } + float getPosTPCNClsShared() const { return posTPCNClsShared; } + float getPosTPCNClsFindable() const { return posTPCNClsFindable; } + float getPosTPCNClsFindableMinusShared() const { return posTPCNClsFindableMinusShared; } + float getPosTPCNClsFindableMinusCrossedRows() const { return posTPCNClsFindableMinusCrossedRows; } + float getPosTPCChi2NCl() const { return posTPCChi2NCl; } + float getPosTPCSignal() const { return posTPCSignal; } + float getPosITSClusterSizes() const { return posITSClusterSizes; } + float getEleTPCNClsShared() const { return eleTPCNClsShared; } + float getEleTPCNClsFindable() const { return eleTPCNClsFindable; } + float getEleTPCNClsFindableMinusShared() const { return eleTPCNClsFindableMinusShared; } + float getEleTPCNClsFindableMinusCrossedRows() const { return eleTPCNClsFindableMinusCrossedRows; } + float getEleTPCChi2NCl() const { return eleTPCChi2NCl; } + float getEleTPCSignal() const { return eleTPCSignal; } + float getEleITSClusterSizes() const { return eleITSClusterSizes; } float getCent() const { return cent; } float getPCA() const { return pca; } CentType getCentType() const { return centType; } private: + float conversionPointx; + float conversionPointy; + float conversionPointz; float px; float py; float pz; @@ -165,9 +250,32 @@ struct V0PhotonCandidate { float phiv; float psipair; float cospa; + float cospaRZ; + float cospaXY; float chi2ndf; float cent; float pca; + float eta; + float posEta; + float eleEta; + float posdcaXY; + float posdcaZ; + float eledcaXY; + float eledcaZ; + float posTPCNClsShared; + float posTPCNClsFindable; + float posTPCNClsFindableMinusShared; + float posTPCNClsFindableMinusCrossedRows; + float posTPCChi2NCl; + float posTPCSignal; + float posITSClusterSizes; + float eleTPCNClsShared; + float eleTPCNClsFindable; + float eleTPCNClsFindableMinusShared; + float eleTPCNClsFindableMinusCrossedRows; + float eleTPCChi2NCl; + float eleTPCSignal; + float eleITSClusterSizes; CentType centType; }; diff --git a/PWGEM/PhotonMeson/TableProducer/photonconversionbuilder.cxx b/PWGEM/PhotonMeson/TableProducer/photonconversionbuilder.cxx index 0591f841f2c..33dd3e0ae31 100644 --- a/PWGEM/PhotonMeson/TableProducer/photonconversionbuilder.cxx +++ b/PWGEM/PhotonMeson/TableProducer/photonconversionbuilder.cxx @@ -723,8 +723,10 @@ struct PhotonConversionBuilder { kfp_pos_DecayVtx.TransportToPoint(xyz); // Don't set Primary Vertex kfp_ele_DecayVtx.TransportToPoint(xyz); // Don't set Primary Vertex + float cospaXYKF = cospaXY_KF(gammaKF_DecayVtx, KFPV); + float cospaRZKF = cospaRZ_KF(gammaKF_DecayVtx, KFPV); CentType centType = static_cast(centTypePCMMl.value); - v0photoncandidate.setPhotonCandidate(gammaKF_DecayVtx, kfp_pos_DecayVtx, kfp_ele_DecayVtx, collision, cospa_kf, psipair, phiv, centType); + v0photoncandidate.setPhotonCandidate(gammaKF_DecayVtx, gammaKF_PV, pos, kfp_pos_DecayVtx, ele, kfp_ele_DecayVtx, collision, cospaXYKF, cospaRZKF, cospaXYKF, psipair, phiv, centType, posdcaXY, posdcaZ, eledcaXY, eledcaZ); if (!ele.hasITS() && !pos.hasITS()) { // V0s with TPConly-TPConly if (max_r_itsmft_ss < rxy && rxy < maxX + margin_r_tpc) { @@ -822,11 +824,9 @@ struct PhotonConversionBuilder { registry.fill(HIST("V0/hPCA_diffX"), v0photoncandidate.getPCA(), std::min(pTrack.getX(), nTrack.getX()) - rxy); // trackiu.x() - rxy should be positive registry.fill(HIST("V0/hPhiVPsiPair"), v0photoncandidate.getPsiPair(), v0photoncandidate.getPhiV()); - float cospaXY_kf = cospaXY_KF(gammaKF_DecayVtx, KFPV); - float cospaRZ_kf = cospaRZ_KF(gammaKF_DecayVtx, KFPV); // LOGF(info, "cospa_kf = %f, cospaXY_kf = %f, cospaRZ_kf = %f", cospa_kf, cospaXY_kf, cospaRZ_kf); - registry.fill(HIST("V0/hCosPAXY_Rxy"), rxy, cospaXY_kf); - registry.fill(HIST("V0/hCosPARZ_Rxy"), rxy, cospaRZ_kf); + registry.fill(HIST("V0/hCosPAXY_Rxy"), rxy, cospaXYKF); + registry.fill(HIST("V0/hCosPARZ_Rxy"), rxy, cospaRZKF); for (const auto& leg : {kfp_pos_DecayVtx, kfp_ele_DecayVtx}) { float legpt = RecoDecay::sqrtSumOfSquares(leg.GetPx(), leg.GetPy()); @@ -855,7 +855,7 @@ struct PhotonConversionBuilder { gammaKF_DecayVtx.GetX(), gammaKF_DecayVtx.GetY(), gammaKF_DecayVtx.GetZ(), gammaKF_PV.GetPx(), gammaKF_PV.GetPy(), gammaKF_PV.GetPz(), v0_sv.M(), v0photoncandidate.getDcaXYToPV(), v0photoncandidate.getDcaZToPV(), - cospa_kf, cospaXY_kf, cospaRZ_kf, + cospa_kf, cospaXYKF, cospaRZKF, v0photoncandidate.getPCA(), v0photoncandidate.getAlpha(), v0photoncandidate.getQt(), v0photoncandidate.getChi2NDF()); v0photonsphivpsi(v0photoncandidate.getPhiV(), v0photoncandidate.getPsiPair()); From 0e0303c0396e4730fa2b979ef9cbedaf5701b3ae Mon Sep 17 00:00:00 2001 From: omvazque Date: Tue, 10 Mar 2026 12:52:36 -0600 Subject: [PATCH 242/347] [PWGLF] Cheks for BC (#15332) --- PWGLF/Tasks/Nuspex/piKpRAA.cxx | 213 +++++++++++++++++++-------------- 1 file changed, 120 insertions(+), 93 deletions(-) diff --git a/PWGLF/Tasks/Nuspex/piKpRAA.cxx b/PWGLF/Tasks/Nuspex/piKpRAA.cxx index 52475e98a9e..e6981fe8b2c 100644 --- a/PWGLF/Tasks/Nuspex/piKpRAA.cxx +++ b/PWGLF/Tasks/Nuspex/piKpRAA.cxx @@ -210,6 +210,7 @@ struct PiKpRAA { Configurable isNoCollInTimeRangeNarrow{"isNoCollInTimeRangeNarrow", false, "use isNoCollInTimeRangeNarrow?"}; Configurable isOccupancyCut{"isOccupancyCut", true, "Occupancy cut?"}; Configurable isCentSel{"isCentSel", true, "Centrality selection?"}; + Configurable selHasBC{"selHasBC", true, "Has BC?"}; Configurable selHasFT0{"selHasFT0", true, "Has FT0?"}; Configurable isT0Ccent{"isT0Ccent", true, "Use T0C-based centrality?"}; @@ -275,6 +276,7 @@ struct PiKpRAA { enum EvCutLabel { All = 1, + HasBC, HasFT0, SelEigth, SelTriggerTVX, @@ -398,11 +400,12 @@ struct PiKpRAA { const char* latexEta[kNEtaHists] = {"-0.8<#eta<-0.6", "-0.6<#eta<-0.4", "-0.4<#eta<-0.2", "-0.2<#eta<0", "0<#eta<0.2", "0.2<#eta<0.4", "0.4<#eta<0.6", "0.6<#eta<0.8"}; registry.add("EventCounter", ";;Events", kTH1F, {axisEvent}); - registry.add("HasFT0AndTVX", "AllEvents=1 | HasFT0=2 | HasFT0&TVX=3;;", kTH1F, {{3, 0.5, 3.5}}); + registry.add("HasBCVsFT0VsTVXVsEvSel", "Alls=1 | BC=2 | FT0=3 | TVX=4 | EvSel=5;;", kTH1F, {{5, 0.5, 5.5}}); registry.add("zPos", "With Event Selection;;Entries;", kTH1F, {axisZpos}); registry.add("T0Ccent", ";;Entries", kTH1F, {axisCent}); registry.add("T0CcentVsFoundFT0", "Found(=1.5) NOT Found(=0.5);;Status;", kTH2F, {{{axisCent}, {2, 0, 2}}}); - registry.add("T0CcentVsFoundFT0AndTVX", "Found(=1.5) NOT Found(=0.5);;Status;", kTH2F, {{{axisCent}, {2, 0, 2}}}); + registry.add("T0CcentVsBCVsFT0VsTVXVsEvSel", "All=1 | BC=2 | FT0=3 | TVX=4 | EvSel=5;;Status;", kTH2F, {{axisCent}, {5, 0.5, 5.5}}); + // registry.add("T0CcentVsFoundFT0AndTVX", "Found(=1.5) NOT Found(=0.5);;Status;", kTH2F, {{{axisCent}, {2, 0, 2}}}); registry.add("NchVsCent", "Measured Nch v.s. Centrality (At least Once Rec. Coll. + Sel. criteria);;Nch", kTH2F, {{axisCent, {nBinsNch, minNch, maxNch}}}); registry.add("NclVsEtaPID", ";#eta;Ncl used for PID", kTH2F, {{{axisEta}, {161, -0.5, 160.5}}}); registry.add("NclVsEtaPIDp", ";#eta;#LTNcl#GT used for PID", kTProfile, {axisEta}); @@ -412,24 +415,25 @@ struct PiKpRAA { auto hstat = registry.get(HIST("EventCounter")); auto* x = hstat->GetXaxis(); x->SetBinLabel(1, "All"); - x->SetBinLabel(2, "Has FT0?"); - x->SetBinLabel(3, "SelEigth"); - x->SetBinLabel(4, "SelTriggerTVX"); - x->SetBinLabel(5, "SelNoITSROFrameBorder"); - x->SetBinLabel(6, "SelNoTimeFrameBorder"); - x->SetBinLabel(7, "VtxZ Sel."); - x->SetBinLabel(8, "GoodZvtxFT0vsPV"); - x->SetBinLabel(9, "NoSameBunchPileup"); - x->SetBinLabel(10, "NoCollInTimeRangeStrict"); - x->SetBinLabel(11, "NoCollInTimeRangeStandard"); - x->SetBinLabel(12, "NoCollInRofStrict"); - x->SetBinLabel(13, "NoCollInRofStandard"); - x->SetBinLabel(14, "NoHighMultCollInPrevRof"); - x->SetBinLabel(15, "NoCollInTimeRangeNarrow"); - x->SetBinLabel(16, "Occupancy Cut"); - x->SetBinLabel(17, "Cent. Sel."); - x->SetBinLabel(18, "Nch Sel."); - x->SetBinLabel(19, "INEL > 0"); + x->SetBinLabel(2, "Has BC?"); + x->SetBinLabel(3, "Has FT0?"); + x->SetBinLabel(4, "SelEigth"); + x->SetBinLabel(5, "SelTriggerTVX"); + x->SetBinLabel(6, "SelNoITSROFrameBorder"); + x->SetBinLabel(7, "SelNoTimeFrameBorder"); + x->SetBinLabel(8, "VtxZ Sel."); + x->SetBinLabel(9, "GoodZvtxFT0vsPV"); + x->SetBinLabel(10, "NoSameBunchPileup"); + x->SetBinLabel(11, "NoCollInTimeRangeStrict"); + x->SetBinLabel(12, "NoCollInTimeRangeStandard"); + x->SetBinLabel(13, "NoCollInRofStrict"); + x->SetBinLabel(14, "NoCollInRofStandard"); + x->SetBinLabel(15, "NoHighMultCollInPrevRof"); + x->SetBinLabel(16, "NoCollInTimeRangeNarrow"); + x->SetBinLabel(17, "Occupancy Cut"); + x->SetBinLabel(18, "Cent. Sel."); + x->SetBinLabel(19, "Nch Sel."); + x->SetBinLabel(20, "INEL > 0"); if (doprocessCalibrationAndV0s) { registry.add("T0CcentVsRCTSel", "Bad RCT(=0.5) Good RCT(=1.5) Good RCT & Good PID RCT(=2.5);;RCT Status;", kTH2F, {{{axisCent}, {3, 0, 3}}}); @@ -1232,12 +1236,65 @@ struct PiKpRAA { } } - const auto& nRecColls{collisions.size()}; - registry.fill(HIST("NumberOfRecoCollisions"), nRecColls); + //--------------------------- + // All Generated events irrespective of whether there is an associated reconstructed collision + // Consequently, the centrality being a reconstructed quantity, might not always be available + // Therefore it is expressed as a function of the generated pT and the generated Nch in ∣eta∣ < 0.8 + // This is used for the denominator of the signal loss correction + // Also for MC closure: True Pt vs Generated Nch + //--------------------------- + for (const auto& particle : mcParticles) { + if (particle.eta() < v0Selections.minEtaDaughter || particle.eta() > v0Selections.maxEtaDaughter) + continue; + + if (particle.pt() < v0Selections.minPt || particle.pt() > v0Selections.maxPt) + continue; + + auto charge{0.}; + // Get the MC particle + auto* pdgParticle = pdg->GetParticle(particle.pdgCode()); + if (pdgParticle != nullptr) { + charge = pdgParticle->Charge(); + } else { + continue; + } + + // Is it a charged particle? + if (std::abs(charge) < kMinCharge) + continue; + + // Is it a primary particle? + bool isPrimary{true}; + if (!particle.isPhysicalPrimary()) + isPrimary = false; + + if (isPrimary) { + if (particle.pdgCode() == PDG_t::kPiPlus || particle.pdgCode() == PDG_t::kPiMinus) { + registry.fill(HIST("PtPiVsNchMC_AllGen"), particle.pt(), nChMCEta08); + registry.fill(HIST("MCclosure_PtMCPiVsNchMC"), particle.pt(), nChMCEta08); + } else if (particle.pdgCode() == PDG_t::kKPlus || particle.pdgCode() == PDG_t::kKMinus) { + registry.fill(HIST("PtKaVsNchMC_AllGen"), particle.pt(), nChMCEta08); + registry.fill(HIST("MCclosure_PtMCKaVsNchMC"), particle.pt(), nChMCEta08); + } else if (particle.pdgCode() == PDG_t::kProton || particle.pdgCode() == PDG_t::kProtonBar) { + registry.fill(HIST("PtPrVsNchMC_AllGen"), particle.pt(), nChMCEta08); + registry.fill(HIST("MCclosure_PtMCPrVsNchMC"), particle.pt(), nChMCEta08); + } else { + continue; + } + } + } // Loop over Generated Particles + + //--------------------------- + // This is used for the denominator of the event loss correction + //--------------------------- + registry.fill(HIST("NchMC_AllGen"), nChMCEta08); //--------------------------- // Only Generated evets with at least one reconstrued collision //--------------------------- + const auto& nRecColls{collisions.size()}; + registry.fill(HIST("NumberOfRecoCollisions"), nRecColls); + if (nRecColls > kZeroInt) { // Finds the collisions with the largest number of contributors @@ -1256,6 +1313,9 @@ struct PiKpRAA { bestCollisionIndex = collision.globalIndex(); } + if (selHasBC && !collision.has_foundBC()) + continue; + if (selHasFT0 && !collision.has_foundFT0()) continue; @@ -1299,9 +1359,8 @@ struct PiKpRAA { //--------------------------- // Pick the collisions with the largest number of contributors //--------------------------- - if (bestCollisionIndex != collision.globalIndex()) { + if (bestCollisionIndex != collision.globalIndex()) continue; - } // Needed to load the Phi selection from the CCDB const auto& foundBC = collision.foundBC_as(); @@ -1327,13 +1386,29 @@ struct PiKpRAA { registry.fill(HIST("Centrality_WRecoEvt"), centrality); registry.fill(HIST("zPosMC"), mccollision.posZ()); + registry.fill(HIST("T0CcentVsBCVsFT0VsTVXVsEvSel"), centrality, 1.0); + registry.fill(HIST("HasBCVsFT0VsTVXVsEvSel"), 1.0); + + if (collision.has_foundBC()) { + registry.fill(HIST("T0CcentVsBCVsFT0VsTVXVsEvSel"), centrality, 2.0); + registry.fill(HIST("HasBCVsFT0VsTVXVsEvSel"), 2.0); + } + + if (collision.has_foundBC() && collision.has_foundFT0()) { + registry.fill(HIST("T0CcentVsBCVsFT0VsTVXVsEvSel"), centrality, 3.0); + registry.fill(HIST("HasBCVsFT0VsTVXVsEvSel"), 3.0); + } + + if (collision.has_foundBC() && collision.has_foundFT0() && collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + registry.fill(HIST("T0CcentVsBCVsFT0VsTVXVsEvSel"), centrality, 4.0); + registry.fill(HIST("HasBCVsFT0VsTVXVsEvSel"), 4.0); + } + //--------------------------- - // Event selection - // for reconstructed collisions + // Event Selection //--------------------------- - if (!isEventSelected(collision)) { - continue; - } + if (!isEventSelected(collision)) + return; registry.fill(HIST("Centrality_WRecoEvtWSelCri"), centrality); registry.fill(HIST("NchMCVsCent"), centrality, nChMCEta08); @@ -1344,18 +1419,16 @@ struct PiKpRAA { //--------------------------- // has_foundFT0() ? //--------------------------- - if (collision.has_foundFT0()) { - registry.fill(HIST("HasFT0AndTVX"), 2.0); + + if (collision.has_foundBC() && collision.has_foundFT0() && collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + registry.fill(HIST("T0CcentVsBCVsFT0VsTVXVsEvSel"), centrality, 5.0); + registry.fill(HIST("HasBCVsFT0VsTVXVsEvSel"), 5.0); + } + + if (collision.has_foundFT0()) registry.fill(HIST("T0CcentVsFoundFT0"), centrality, 1.5); - } else { + else registry.fill(HIST("T0CcentVsFoundFT0"), centrality, 0.5); - } - if (collision.has_foundFT0() && collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { - registry.fill(HIST("HasFT0AndTVX"), 3.0); - registry.fill(HIST("T0CcentVsFoundFT0AndTVX"), centrality, 1.5); - } else { - registry.fill(HIST("T0CcentVsFoundFT0AndTVX"), centrality, 0.5); - } //--------------------------- // All Generated events with at least one associated reconstructed collision @@ -1644,59 +1717,6 @@ struct PiKpRAA { registry.fill(HIST("NchVsCent"), centrality, nCh); } // Loop over Reco. Collisions: Only the collisions with the largest number of contributors } // If condition: Only simulated evets with at least one reconstrued collision - - //--------------------------- - // All Generated events irrespective of whether there is an associated reconstructed collision - // Consequently, the centrality being a reconstructed quantity, might not always be available - // Therefore it is expressed as a function of the generated pT and the generated Nch in ∣eta∣ < 0.8 - // This is used for the denominator of the signal loss correction - // Also for MC closure: True Pt vs Generated Nch - //--------------------------- - for (const auto& particle : mcParticles) { - if (particle.eta() < v0Selections.minEtaDaughter || particle.eta() > v0Selections.maxEtaDaughter) - continue; - - if (particle.pt() < v0Selections.minPt || particle.pt() > v0Selections.maxPt) - continue; - - auto charge{0.}; - // Get the MC particle - auto* pdgParticle = pdg->GetParticle(particle.pdgCode()); - if (pdgParticle != nullptr) { - charge = pdgParticle->Charge(); - } else { - continue; - } - - // Is it a charged particle? - if (std::abs(charge) < kMinCharge) - continue; - - // Is it a primary particle? - bool isPrimary{true}; - if (!particle.isPhysicalPrimary()) - isPrimary = false; - - if (isPrimary) { - if (particle.pdgCode() == PDG_t::kPiPlus || particle.pdgCode() == PDG_t::kPiMinus) { - registry.fill(HIST("PtPiVsNchMC_AllGen"), particle.pt(), nChMCEta08); - registry.fill(HIST("MCclosure_PtMCPiVsNchMC"), particle.pt(), nChMCEta08); - } else if (particle.pdgCode() == PDG_t::kKPlus || particle.pdgCode() == PDG_t::kKMinus) { - registry.fill(HIST("PtKaVsNchMC_AllGen"), particle.pt(), nChMCEta08); - registry.fill(HIST("MCclosure_PtMCKaVsNchMC"), particle.pt(), nChMCEta08); - } else if (particle.pdgCode() == PDG_t::kProton || particle.pdgCode() == PDG_t::kProtonBar) { - registry.fill(HIST("PtPrVsNchMC_AllGen"), particle.pt(), nChMCEta08); - registry.fill(HIST("MCclosure_PtMCPrVsNchMC"), particle.pt(), nChMCEta08); - } else { - continue; - } - } - } // Loop over Generated Particles - - //--------------------------- - // This is used for the denominator of the event loss correction - //--------------------------- - registry.fill(HIST("NchMC_AllGen"), nChMCEta08); } PROCESS_SWITCH(PiKpRAA, processSim, "Process Sim", false); @@ -2069,7 +2089,14 @@ struct PiKpRAA { bool isEventSelected(CheckCol const& col) { registry.fill(HIST("EventCounter"), EvCutLabel::All); - registry.fill(HIST("HasFT0AndTVX"), EvCutLabel::All); + + // Has BC? + if (selHasBC) { + if (!col.has_foundBC()) { + return false; + } + registry.fill(HIST("EventCounter"), EvCutLabel::HasBC); + } // Has FT0 information? if (selHasFT0) { From d543bb6cdc7dc4d8592be6021acecdf30950a93b Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Tue, 10 Mar 2026 20:17:55 +0100 Subject: [PATCH 243/347] [PWGEM/Dilepton] add createResolutionMapDerived.cxx (#15337) --- PWGEM/Dilepton/Tasks/CMakeLists.txt | 5 + .../Tasks/createResolutionMapDerived.cxx | 568 ++++++++++++++++++ 2 files changed, 573 insertions(+) create mode 100644 PWGEM/Dilepton/Tasks/createResolutionMapDerived.cxx diff --git a/PWGEM/Dilepton/Tasks/CMakeLists.txt b/PWGEM/Dilepton/Tasks/CMakeLists.txt index 3424bda2a24..ab6df58242a 100644 --- a/PWGEM/Dilepton/Tasks/CMakeLists.txt +++ b/PWGEM/Dilepton/Tasks/CMakeLists.txt @@ -40,6 +40,11 @@ o2physics_add_dpl_workflow(create-resolution-map PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::GlobalTracking COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(create-resolution-map-derived + SOURCES createResolutionMapDerived.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGEMDileptonCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(test-bremsstrahlung SOURCES testBremsstrahlung.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore diff --git a/PWGEM/Dilepton/Tasks/createResolutionMapDerived.cxx b/PWGEM/Dilepton/Tasks/createResolutionMapDerived.cxx new file mode 100644 index 00000000000..f0a35f7c814 --- /dev/null +++ b/PWGEM/Dilepton/Tasks/createResolutionMapDerived.cxx @@ -0,0 +1,568 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +// +// +// Analysis task to produce resolution map for electrons/muons over derived data. +// Please write to: daiki.sekihata@cern.ch + +#include "PWGEM/Dilepton/Core/DielectronCut.h" +#include "PWGEM/Dilepton/Core/DimuonCut.h" +#include "PWGEM/Dilepton/Core/EMEventCut.h" +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" +#include "PWGEM/Dilepton/Utils/MCUtilities.h" + +#include "Common/CCDB/RCTSelectionFlags.h" + +#include "Framework/ASoA.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/runDataProcessing.h" + +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::aod; +using namespace o2::soa; + +struct createResolutionMapDerived { + + Configurable cfgEventGeneratorType{"cfgEventGeneratorType", -1, "if positive, select event generator type. i.e. gap or signal"}; + Configurable cfg_require_true_mc_collision_association{"cfg_require_true_mc_collision_association", false, "flag to require true mc collision association"}; + + ConfigurableAxis ConfPtGenBins{"ConfPtGenBins", {VARIABLE_WIDTH, 0.00, 0.05, 0.06, 0.07, 0.08, 0.09, 0.10, 0.11, 0.12, 0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19, 0.20, 0.21, 0.22, 0.23, 0.24, 0.25, 0.26, 0.27, 0.28, 0.29, 0.30, 0.31, 0.32, 0.33, 0.34, 0.35, 0.36, 0.37, 0.38, 0.39, 0.40, 0.41, 0.42, 0.43, 0.44, 0.45, 0.46, 0.47, 0.48, 0.49, 0.50, 0.51, 0.52, 0.53, 0.54, 0.55, 0.56, 0.57, 0.58, 0.59, 0.60, 0.61, 0.62, 0.63, 0.64, 0.65, 0.66, 0.67, 0.68, 0.69, 0.70, 0.71, 0.72, 0.73, 0.74, 0.75, 0.76, 0.77, 0.78, 0.79, 0.80, 0.81, 0.82, 0.83, 0.84, 0.85, 0.86, 0.87, 0.88, 0.89, 0.90, 0.91, 0.92, 0.93, 0.94, 0.95, 0.96, 0.97, 0.98, 0.99, 1.00, 1.10, 1.20, 1.30, 1.40, 1.50, 1.60, 1.70, 1.80, 1.90, 2.00, 2.10, 2.20, 2.30, 2.40, 2.50, 2.60, 2.70, 2.80, 2.90, 3.00, 3.10, 3.20, 3.30, 3.40, 3.50, 3.60, 3.70, 3.80, 3.90, 4.00, 4.10, 4.20, 4.30, 4.40, 4.50, 4.60, 4.70, 4.80, 4.90, 5.00, 5.50, 6.00, 6.50, 7.00, 7.50, 8.00, 8.50, 9.00, 9.50, 10.00, 11.00, 12.00, 13.00, 14.00, 15.00, 16.00, 17.00, 18.00, 19.00, 20.00}, "gen. pT bins for output histograms"}; + ConfigurableAxis ConfCentBins{"ConfCentBins", {VARIABLE_WIDTH, 0, 10, 30, 50, 110}, "centrality (%) bins for output histograms"}; + + ConfigurableAxis ConfEtaCBGenBins{"ConfEtaCBGenBins", {30, -1.5, +1.5}, "gen. eta bins at midrapidity for output histograms"}; + ConfigurableAxis ConfEtaFWDGenBins{"ConfEtaFWDGenBins", {40, -5.5, -1.5}, "gen. eta bins at forward rapidity for output histograms"}; + ConfigurableAxis ConfPhiGenBins{"ConfPhiGenBins", {36, 0, 2.f * M_PI}, "gen. phi bins at forward rapidity for output histograms"}; + Configurable cfgRefR{"cfgRefR", 0.50, "ref. radius (m) for calculating phi position"}; // 0.50 +/- 0.06 can be syst. unc. + + ConfigurableAxis ConfRelDeltaPtCBBins{"ConfRelDeltaPtCBBins", {200, -1.f, +1.f}, "rel. dpt for output histograms at midrapidity"}; + ConfigurableAxis ConfRelDeltaPtFWDBins{"ConfRelDeltaPtFWDBins", {200, -1.f, +1.f}, "rel. dpt for output histograms at fwd rapidity"}; + + ConfigurableAxis ConfDeltaEtaCBBins{"ConfDeltaEtaCBBins", {200, -0.5f, +0.5f}, "deta bins for output histograms at midrapidity"}; + ConfigurableAxis ConfDeltaEtaFWDBins{"ConfDeltaEtaFWDBins", {200, -0.5f, +0.5f}, "deta bins for output histograms at fwd rapidity"}; + ConfigurableAxis ConfDeltaPhiBins{"ConfDeltaPhiBins", {200, -0.5f, +0.5f}, "dphi bins for output histograms"}; + + Configurable cfgFillTHnSparse{"cfgFillTHnSparse", true, "fill THnSparse for output"}; + Configurable cfgFillTH2{"cfgFillTH2", false, "fill TH2 for output"}; + + EMEventCut fEMEventCut; + struct : ConfigurableGroup { + std::string prefix = "eventcut_group"; + Configurable cfgZvtxMin{"cfgZvtxMin", -10.f, "min. Zvtx"}; + Configurable cfgZvtxMax{"cfgZvtxMax", +10.f, "max. Zvtx"}; + Configurable cfgRequireSel8{"cfgRequireSel8", false, "require sel8 in event cut"}; + Configurable cfgRequireFT0AND{"cfgRequireFT0AND", true, "require FT0AND in event cut"}; + Configurable cfgRequireNoTFB{"cfgRequireNoTFB", false, "require No time frame border in event cut"}; + Configurable cfgRequireNoITSROFB{"cfgRequireNoITSROFB", false, "require no ITS readout frame border in event cut"}; + Configurable cfgRequireNoSameBunchPileup{"cfgRequireNoSameBunchPileup", false, "require no same bunch pileup in event cut"}; + Configurable cfgRequireVertexITSTPC{"cfgRequireVertexITSTPC", false, "require Vertex ITSTPC in event cut"}; // ITS-TPC matched track contributes PV. + Configurable cfgRequireVertexTOFmatched{"cfgRequireVertexTOFmatched", false, "require Vertex TOFmatched in event cut"}; // ITS-TPC-TOF matched track contributes PV. + Configurable cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; + Configurable cfgTrackOccupancyMin{"cfgTrackOccupancyMin", -2, "min. occupancy"}; + Configurable cfgTrackOccupancyMax{"cfgTrackOccupancyMax", 1000000000, "max. occupancy"}; + Configurable cfgFT0COccupancyMin{"cfgFT0COccupancyMin", -2, "min. FT0C occupancy"}; + Configurable cfgFT0COccupancyMax{"cfgFT0COccupancyMax", 1000000000, "max. FT0C occupancy"}; + Configurable cfgRequireNoCollInTimeRangeStandard{"cfgRequireNoCollInTimeRangeStandard", false, "require no collision in time range standard"}; + Configurable cfgRequireNoCollInTimeRangeStrict{"cfgRequireNoCollInTimeRangeStrict", false, "require no collision in time range strict"}; + Configurable cfgRequireNoCollInITSROFStandard{"cfgRequireNoCollInITSROFStandard", false, "require no collision in time range standard"}; + Configurable cfgRequireNoCollInITSROFStrict{"cfgRequireNoCollInITSROFStrict", false, "require no collision in time range strict"}; + Configurable cfgRequireNoHighMultCollInPrevRof{"cfgRequireNoHighMultCollInPrevRof", false, "require no HM collision in previous ITS ROF"}; + Configurable cfgRequireGoodITSLayer3{"cfgRequireGoodITSLayer3", false, "number of inactive chips on ITS layer 3 are below threshold "}; + Configurable cfgRequireGoodITSLayer0123{"cfgRequireGoodITSLayer0123", false, "number of inactive chips on ITS layers 0-3 are below threshold "}; + Configurable cfgRequireGoodITSLayersAll{"cfgRequireGoodITSLayersAll", false, "number of inactive chips on all ITS layers are below threshold "}; + + // for RCT + Configurable cfgRequireGoodRCT{"cfgRequireGoodRCT", false, "require good detector flag in run condtion table"}; + Configurable cfgRCTLabel{"cfgRCTLabel", "CBT_hadronPID", "select 1 [CBT_hadronPID, CBT_muon_glo, CBT_muon]. see O2Physics/Common/CCDB/RCTSelectionFlags.h"}; + Configurable cfgCheckZDC{"cfgCheckZDC", false, "set ZDC flag for PbPb/OO"}; + Configurable cfgTreatLimitedAcceptanceAsBad{"cfgTreatLimitedAcceptanceAsBad", false, "reject all events where the detectors relevant for the specified Runlist are flagged as LimitedAcceptance"}; + + Configurable cfgEventGeneratorType{"cfgEventGeneratorType", -1, "if positive, select event generator type. i.e. gap or signal"}; + Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; + Configurable cfgCentMin{"cfgCentMin", -1, "min. centrality"}; + Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; + Configurable cfgNumContribMin{"cfgNumContribMin", 0, "min. numContrib"}; + Configurable cfgNumContribMax{"cfgNumContribMax", 65000, "max. numContrib"}; + } eventcuts; + + DielectronCut fDielectronCut; + struct : ConfigurableGroup { + std::string prefix = "electroncut_group"; + + Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.05, "min pT for single track"}; + Configurable cfg_max_pt_track{"cfg_max_pt_track", 1e+10, "max pT for single track"}; + Configurable cfg_min_eta_track{"cfg_min_eta_track", -2, "min eta for single track"}; + Configurable cfg_max_eta_track{"cfg_max_eta_track", +2, "max eta for single track"}; + Configurable cfg_min_phi_track{"cfg_min_phi_track", 0.f, "min phi for single track"}; + Configurable cfg_max_phi_track{"cfg_max_phi_track", 6.3, "max phi for single track"}; + Configurable cfg_mirror_phi_track{"cfg_mirror_phi_track", false, "mirror the phi cut around Pi, min and max Phi should be in 0-Pi"}; + Configurable cfg_reject_phi_track{"cfg_reject_phi_track", false, "reject the phi interval"}; + Configurable cfg_min_ncluster_tpc{"cfg_min_ncluster_tpc", 0, "min ncluster tpc"}; + Configurable cfg_min_ncluster_its{"cfg_min_ncluster_its", 5, "min ncluster its"}; + Configurable cfg_min_ncrossedrows{"cfg_min_ncrossedrows", 100, "min ncrossed rows"}; + Configurable cfg_max_frac_shared_clusters_tpc{"cfg_max_frac_shared_clusters_tpc", 999.f, "max fraction of shared clusters in TPC"}; + Configurable cfg_max_chi2tpc{"cfg_max_chi2tpc", 4.0, "max chi2/NclsTPC"}; + Configurable cfg_max_chi2its{"cfg_max_chi2its", 5.0, "max chi2/NclsITS"}; + Configurable cfg_max_chi2tof{"cfg_max_chi2tof", 1e+10, "max chi2 TOF"}; + Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1.0, "max dca XY for single track in cm"}; + Configurable cfg_max_dcaz{"cfg_max_dcaz", 1.0, "max dca Z for single track in cm"}; + Configurable cfg_require_itsib_any{"cfg_require_itsib_any", false, "flag to require ITS ib any hits"}; + Configurable cfg_require_itsib_1st{"cfg_require_itsib_1st", true, "flag to require ITS ib 1st hit"}; + Configurable cfg_min_its_cluster_size{"cfg_min_its_cluster_size", 0.f, "min ITS cluster size"}; + Configurable cfg_max_its_cluster_size{"cfg_max_its_cluster_size", 16.f, "max ITS cluster size"}; + Configurable cfgRefR{"cfgRefR", 0.50, "ref. radius (m) for calculating phi position"}; // 0.50 +/- 0.06 can be syst. unc. + Configurable cfg_min_phiposition_track{"cfg_min_phiposition_track", 0.f, "min phi position for single track at certain radius"}; + Configurable cfg_max_phiposition_track{"cfg_max_phiposition_track", 6.3, "max phi position for single track at certain radius"}; + Configurable acceptOnlyCorrectMatch{"acceptOnlyCorrectMatch", false, "flag to accept only correct match between ITS and TPC"}; // this is only for MC study, as we don't know correct match in data. + Configurable acceptOnlyWrongMatch{"acceptOnlyWrongMatch", false, "flag to accept only wrong match between ITS and TPC"}; // this is only for MC study, as we don't know correct match in data. + + Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DielectronCut::PIDSchemes::kTPChadrejORTOFreq), "pid scheme [kTOFreq : 0, kTPChadrej : 1, kTPChadrejORTOFreq : 2, kTPConly : 3, kTOFif = 4, kPIDML = 5]"}; + Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -2.0, "min. TPC n sigma for electron inclusion"}; + Configurable cfg_max_TPCNsigmaEl{"cfg_max_TPCNsigmaEl", +3.0, "max. TPC n sigma for electron inclusion"}; + // Configurable cfg_min_TPCNsigmaMu{"cfg_min_TPCNsigmaMu", -0.0, "min. TPC n sigma for muon exclusion"}; + // Configurable cfg_max_TPCNsigmaMu{"cfg_max_TPCNsigmaMu", +0.0, "max. TPC n sigma for muon exclusion"}; + Configurable cfg_min_TPCNsigmaPi{"cfg_min_TPCNsigmaPi", -1e+10, "min. TPC n sigma for pion exclusion"}; + Configurable cfg_max_TPCNsigmaPi{"cfg_max_TPCNsigmaPi", +3.0, "max. TPC n sigma for pion exclusion"}; + Configurable cfg_min_TPCNsigmaKa{"cfg_min_TPCNsigmaKa", -3.0, "min. TPC n sigma for kaon exclusion"}; + Configurable cfg_max_TPCNsigmaKa{"cfg_max_TPCNsigmaKa", +3.0, "max. TPC n sigma for kaon exclusion"}; + Configurable cfg_min_TPCNsigmaPr{"cfg_min_TPCNsigmaPr", -3.0, "min. TPC n sigma for proton exclusion"}; + Configurable cfg_max_TPCNsigmaPr{"cfg_max_TPCNsigmaPr", +3.0, "max. TPC n sigma for proton exclusion"}; + Configurable cfg_min_TOFNsigmaEl{"cfg_min_TOFNsigmaEl", -3.0, "min. TOF n sigma for electron inclusion"}; + Configurable cfg_max_TOFNsigmaEl{"cfg_max_TOFNsigmaEl", +3.0, "max. TOF n sigma for electron inclusion"}; + Configurable cfg_min_pin_pirejTPC{"cfg_min_pin_pirejTPC", 0.f, "min. pin for pion rejection in TPC"}; + Configurable cfg_max_pin_pirejTPC{"cfg_max_pin_pirejTPC", 1e+10, "max. pin for pion rejection in TPC"}; + Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; + + Configurable checkPIDForTracking{"checkPIDForTracking", false, "check PID for tracking"}; + Configurable PartIdentifier{"PartIdentifier", 2, "Particle identifier for selected particle; 0: electron, 1: muon, 2: pion, 3: kaon, 4: proton, 5: deuteron, 6: triton, 7: helium3, 8: alpha"}; + + // configuration for PID ML + Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; + Configurable> onnxPathsCCDB{"onnxPathsCCDB", std::vector{"path"}, "Paths of models on CCDB"}; + Configurable> binsMl{"binsMl", std::vector{-999999., 999999.}, "Bin limits for ML application"}; + Configurable> cutsMl{"cutsMl", std::vector{0.95}, "ML cuts per bin"}; + Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"feature"}, "Names of ML model input features"}; + Configurable nameBinningFeature{"nameBinningFeature", "pt", "Names of ML model binning feature"}; + Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB. Exceptions: > 0 for the specific timestamp, 0 gets the run dependent timestamp"}; + Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; + Configurable enableOptimizations{"enableOptimizations", false, "Enables the ONNX extended model-optimization: sessionOptions.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED)"}; + } electroncuts; + + DimuonCut fDimuonCut; + struct : ConfigurableGroup { + std::string prefix = "muoncut_group"; + + Configurable cfg_track_type{"cfg_track_type", 0, "muon track type [0: MFT-MCH-MID, 3: MCH-MID]"}; + Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.1, "min pT for single track"}; + Configurable cfg_max_pt_track{"cfg_max_pt_track", 1e+10, "max pT for single track"}; + Configurable cfg_min_eta_track{"cfg_min_eta_track", -10, "min eta for single track"}; + Configurable cfg_max_eta_track{"cfg_max_eta_track", 0, "max eta for single track"}; + Configurable cfg_min_phi_track{"cfg_min_phi_track", 0.f, "max phi for single track"}; + Configurable cfg_max_phi_track{"cfg_max_phi_track", 6.3, "max phi for single track"}; + Configurable cfg_min_ncluster_mft{"cfg_min_ncluster_mft", 5, "min ncluster MFT"}; + Configurable cfg_min_ncluster_mch{"cfg_min_ncluster_mch", 5, "min ncluster MCH"}; + Configurable cfg_max_chi2{"cfg_max_chi2", 1e+6, "max chi2/ndf"}; + Configurable cfg_max_chi2mft{"cfg_max_chi2mft", 1e+6, "max chi2/ndf"}; + // Configurable cfg_max_matching_chi2_mftmch{"cfg_max_matching_chi2_mftmch", 40, "max chi2 for MFT-MCH matching"}; + Configurable cfg_border_pt_for_chi2mchmft{"cfg_border_pt_for_chi2mchmft", 0, "border pt for different max chi2 for MFT-MCH matching"}; + Configurable cfg_max_matching_chi2_mftmch_lowPt{"cfg_max_matching_chi2_mftmch_lowPt", 8, "max chi2 for MFT-MCH matching for low pT"}; + Configurable cfg_max_matching_chi2_mftmch_highPt{"cfg_max_matching_chi2_mftmch_highPt", 40, "max chi2 for MFT-MCH matching for high pT"}; + Configurable cfg_max_matching_chi2_mchmid{"cfg_max_matching_chi2_mchmid", 1e+10, "max chi2 for MCH-MID matching"}; + Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1e+10, "max dca XY for single track in cm"}; + Configurable cfg_min_rabs{"cfg_min_rabs", 17.6, "min Radius at the absorber end"}; + Configurable cfg_max_rabs{"cfg_max_rabs", 89.5, "max Radius at the absorber end"}; + Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; + Configurable cfg_max_relDPt_wrt_matchedMCHMID{"cfg_max_relDPt_wrt_matchedMCHMID", 1e+10f, "max. relative dpt between MFT-MCH-MID and MCH-MID"}; + Configurable cfg_max_DEta_wrt_matchedMCHMID{"cfg_max_DEta_wrt_matchedMCHMID", 1e+10f, "max. deta between MFT-MCH-MID and MCH-MID"}; + Configurable cfg_max_DPhi_wrt_matchedMCHMID{"cfg_max_DPhi_wrt_matchedMCHMID", 1e+10f, "max. dphi between MFT-MCH-MID and MCH-MID"}; + Configurable requireMFTHitMap{"requireMFTHitMap", false, "flag to apply MFT hit map"}; + Configurable> requiredMFTDisks{"requiredMFTDisks", std::vector{0}, "hit map on MFT disks [0,1,2,3,4]. logical-OR of each double-sided disk"}; + Configurable acceptOnlyCorrectMatch{"acceptOnlyCorrectMatch", false, "flag to accept only correct match between MFT and MCH-MID"}; // this is only for MC study, as we don't know correct match in data. + Configurable acceptOnlyWrongMatch{"acceptOnlyWrongMatch", false, "flag to accept only wrong match between MFT and MCH-MID"}; // this is only for MC study, as we don't know correct match in data. + } muoncuts; + + HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject}; + o2::aod::rctsel::RCTFlagsChecker rctChecker; + + ~createResolutionMapDerived() {} + + void init(o2::framework::InitContext&) + { + rctChecker.init(eventcuts.cfgRCTLabel.value, eventcuts.cfgCheckZDC.value, eventcuts.cfgTreatLimitedAcceptanceAsBad.value); + + DefineEMEventCut(); + + if (doprocessElectron) { + DefineDielectronCut(); + } + if (doprocessMuon) { + DefineDimuonCut(); + } + addHistograms(); + } + + void addHistograms() + { + // registry.add("Event/Electron/hImpPar_Centrality", "true imapact parameter vs. estimated centrality;impact parameter (fm);centrality (%)", kTH2F, {{200, 0, 20}, {110, 0, 110}}, true); + // registry.add("Event/Electron/hImpPar_Centrality", "true imapact parameter vs. estimated centrality;impact parameter (fm);centrality (%)", kTH2F, {{200, 0, 20}, {110, 0, 110}}, true); + + if (doprocessGen) { + registry.add("Event/hGenID", "generator ID;generator ID;Number of mc collisions", kTH1F, {{7, -1.5, 5.5}}, true); + } + + const AxisSpec axis_cent{ConfCentBins, "centrality (%)"}; + const AxisSpec axis_pt_gen{ConfPtGenBins, "p_{T,l}^{gen} (GeV/c)"}; + const AxisSpec axis_eta_cb_gen{ConfEtaCBGenBins, "#eta_{l}^{gen}"}; + const AxisSpec axis_eta_fwd_gen{ConfEtaFWDGenBins, "#eta_{l}^{gen}"}; + const AxisSpec axis_phi_gen{ConfPhiGenBins, "#varphi_{l}^{gen} (rad.)"}; + const AxisSpec axis_dpt_cb{ConfRelDeltaPtCBBins, "(p_{T,l}^{gen} - p_{T,l}^{rec})/p_{T,l}^{gen}"}; + const AxisSpec axis_dpt_fwd{ConfRelDeltaPtFWDBins, "(p_{T,l}^{gen} - p_{T,l}^{rec})/p_{T,l}^{gen}"}; + const AxisSpec axis_deta_cb{ConfDeltaEtaCBBins, "#eta_{l}^{gen} - #eta_{l}^{rec}"}; + const AxisSpec axis_deta_fwd{ConfDeltaEtaFWDBins, "#eta_{l}^{gen} - #eta_{l}^{rec}"}; + const AxisSpec axis_dphi{ConfDeltaPhiBins, "#varphi_{l}^{gen} - #varphi_{l}^{rec} (rad.)"}; + const AxisSpec axis_charge_gen{3, -1.5, +1.5, "true sign"}; + + if (doprocessElectron) { + registry.add("Electron/hPIDForTracking", "PID for trackng", kTH1F, {{9, -0.5, 8.5}}, false); // see numbering in O2/DataFormats/Reconstruction/include/ReconstructionDataFormats/PID.h + if (cfgFillTH2) { + registry.add("Electron/hPt", "rec. p_{T,e};p_{T,e} (GeV/c)", kTH1F, {{1000, 0, 10}}, false); + registry.add("Electron/hEtaPhi", "rec. #eta vs. #varphi;#varphi_{e} (rad.);#eta_{e}", kTH2F, {{90, 0, 2 * M_PI}, {40, -2, +2}}, false); + registry.add("Electron/Ptgen_RelDeltaPt", "resolution", kTH2F, {{axis_pt_gen}, {axis_dpt_cb}}, true); + registry.add("Electron/Ptgen_DeltaEta", "resolution", kTH2F, {{axis_pt_gen}, {axis_deta_cb}}, true); + registry.add("Electron/Ptgen_DeltaPhi_Pos", "resolution", kTH2F, {{axis_pt_gen}, {axis_dphi}}, true); + registry.add("Electron/Ptgen_DeltaPhi_Neg", "resolution", kTH2F, {{axis_pt_gen}, {axis_dphi}}, true); + } + if (cfgFillTHnSparse) { + registry.add("Electron/hs_reso", "8D resolution", kTHnSparseF, {axis_cent, axis_pt_gen, axis_eta_cb_gen, axis_phi_gen, axis_charge_gen, axis_dpt_cb, axis_deta_cb, axis_dphi}, true); + } + } + + if (doprocessMuon) { + if (muoncuts.cfg_track_type == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack)) { + if (cfgFillTH2) { + registry.add("GlobalMuon/hPt", "rec. p_{T,#mu};p_{T,#mu} (GeV/c)", kTH1F, {{1000, 0, 10}}, false); + registry.add("GlobalMuon/hEtaPhi", "rec. #eta vs. #varphi;#varphi_{#mu} (rad.);#eta_{#mu}", kTH2F, {{90, 0, 2 * M_PI}, {60, -6, 0}}, false); + registry.add("GlobalMuon/Ptgen_RelDeltaPt", "resolution", kTH2F, {{axis_pt_gen}, {axis_dpt_fwd}}, true); + registry.add("GlobalMuon/Ptgen_DeltaEta", "resolution", kTH2F, {{axis_pt_gen}, {axis_deta_fwd}}, true); + registry.add("GlobalMuon/Ptgen_DeltaPhi_Pos", "resolution", kTH2F, {{axis_pt_gen}, {axis_dphi}}, true); + registry.add("GlobalMuon/Ptgen_DeltaPhi_Neg", "resolution", kTH2F, {{axis_pt_gen}, {axis_dphi}}, true); + } + if (cfgFillTHnSparse) { + registry.add("GlobalMuon/hs_reso", "8D resolution", kTHnSparseF, {axis_cent, axis_pt_gen, axis_eta_fwd_gen, axis_phi_gen, axis_charge_gen, axis_dpt_fwd, axis_deta_fwd, axis_dphi}, true); + } + } else if (muoncuts.cfg_track_type == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack)) { + if (cfgFillTH2) { + registry.add("StandaloneMuon/hPt", "rec. p_{T,#mu};p_{T,#mu} (GeV/c)", kTH1F, {{1000, 0, 10}}, false); + registry.add("StandaloneMuon/hEtaPhi", "rec. #eta vs. #varphi;#varphi_{#mu} (rad.);#eta_{#mu}", kTH2F, {{90, 0, 2 * M_PI}, {60, -6, 0}}, false); + registry.add("StandaloneMuon/Ptgen_RelDeltaPt", "resolution", kTH2F, {{axis_pt_gen}, {axis_dpt_fwd}}, true); + registry.add("StandaloneMuon/Ptgen_DeltaEta", "resolution", kTH2F, {{axis_pt_gen}, {axis_deta_fwd}}, true); + registry.add("StandaloneMuon/Ptgen_DeltaPhi_Pos", "resolution", kTH2F, {{axis_pt_gen}, {axis_dphi}}, true); + registry.add("StandaloneMuon/Ptgen_DeltaPhi_Neg", "resolution", kTH2F, {{axis_pt_gen}, {axis_dphi}}, true); + } + if (cfgFillTHnSparse) { + registry.add("StandaloneMuon/hs_reso", "8D resolution", kTHnSparseF, {axis_cent, axis_pt_gen, axis_eta_fwd_gen, axis_phi_gen, axis_charge_gen, axis_dpt_fwd, axis_deta_fwd, axis_dphi}, true); + } + } + } + } + + void DefineEMEventCut() + { + fEMEventCut = EMEventCut("fEMEventCut", "fEMEventCut"); + fEMEventCut.SetRequireSel8(eventcuts.cfgRequireSel8); + fEMEventCut.SetRequireFT0AND(eventcuts.cfgRequireFT0AND); + fEMEventCut.SetZvtxRange(eventcuts.cfgZvtxMin, eventcuts.cfgZvtxMax); + fEMEventCut.SetRequireNoTFB(eventcuts.cfgRequireNoTFB); + fEMEventCut.SetRequireNoITSROFB(eventcuts.cfgRequireNoITSROFB); + fEMEventCut.SetRequireNoSameBunchPileup(eventcuts.cfgRequireNoSameBunchPileup); + fEMEventCut.SetRequireVertexITSTPC(eventcuts.cfgRequireVertexITSTPC); + fEMEventCut.SetRequireVertexTOFmatched(eventcuts.cfgRequireVertexTOFmatched); + fEMEventCut.SetRequireGoodZvtxFT0vsPV(eventcuts.cfgRequireGoodZvtxFT0vsPV); + fEMEventCut.SetRequireNoCollInTimeRangeStandard(eventcuts.cfgRequireNoCollInTimeRangeStandard); + fEMEventCut.SetRequireNoCollInTimeRangeStrict(eventcuts.cfgRequireNoCollInTimeRangeStrict); + fEMEventCut.SetRequireNoCollInITSROFStandard(eventcuts.cfgRequireNoCollInITSROFStandard); + fEMEventCut.SetRequireNoCollInITSROFStrict(eventcuts.cfgRequireNoCollInITSROFStrict); + fEMEventCut.SetRequireNoHighMultCollInPrevRof(eventcuts.cfgRequireNoHighMultCollInPrevRof); + fEMEventCut.SetRequireGoodITSLayer3(eventcuts.cfgRequireGoodITSLayer3); + fEMEventCut.SetRequireGoodITSLayer0123(eventcuts.cfgRequireGoodITSLayer0123); + fEMEventCut.SetRequireGoodITSLayersAll(eventcuts.cfgRequireGoodITSLayersAll); + } + + void DefineDielectronCut() + { + fDielectronCut = DielectronCut("fDielectronCut", "fDielectronCut"); + + // for track + fDielectronCut.SetTrackPtRange(electroncuts.cfg_min_pt_track, electroncuts.cfg_max_pt_track); + fDielectronCut.SetTrackEtaRange(electroncuts.cfg_min_eta_track, +electroncuts.cfg_max_eta_track); + fDielectronCut.SetTrackPhiRange(electroncuts.cfg_min_phi_track, electroncuts.cfg_max_phi_track, electroncuts.cfg_mirror_phi_track, electroncuts.cfg_reject_phi_track); + fDielectronCut.SetMinNClustersTPC(electroncuts.cfg_min_ncluster_tpc); + fDielectronCut.SetMinNCrossedRowsTPC(electroncuts.cfg_min_ncrossedrows); + fDielectronCut.SetMinNCrossedRowsOverFindableClustersTPC(0.8); + fDielectronCut.SetMaxFracSharedClustersTPC(electroncuts.cfg_max_frac_shared_clusters_tpc); + fDielectronCut.SetChi2PerClusterTPC(0.0, electroncuts.cfg_max_chi2tpc); + fDielectronCut.SetChi2PerClusterITS(0.0, electroncuts.cfg_max_chi2its); + fDielectronCut.SetNClustersITS(electroncuts.cfg_min_ncluster_its, 7); + fDielectronCut.SetMeanClusterSizeITS(electroncuts.cfg_min_its_cluster_size, electroncuts.cfg_max_its_cluster_size); + fDielectronCut.SetTrackMaxDcaXY(electroncuts.cfg_max_dcaxy); + fDielectronCut.SetTrackMaxDcaZ(electroncuts.cfg_max_dcaz); + fDielectronCut.RequireITSibAny(electroncuts.cfg_require_itsib_any); + fDielectronCut.RequireITSib1st(electroncuts.cfg_require_itsib_1st); + fDielectronCut.SetChi2TOF(0.0, electroncuts.cfg_max_chi2tof); + // fDielectronCut.SetRelDiffPin(electroncuts.cfg_min_rel_diff_pin, electroncuts.cfg_max_rel_diff_pin); + fDielectronCut.EnableTTCA(electroncuts.enableTTCA); + + // for eID + fDielectronCut.SetPIDScheme(electroncuts.cfg_pid_scheme); + fDielectronCut.SetTPCNsigmaElRange(electroncuts.cfg_min_TPCNsigmaEl, electroncuts.cfg_max_TPCNsigmaEl); + // fDielectronCut.SetTPCNsigmaMuRange(electroncuts.cfg_min_TPCNsigmaMu, electroncuts.cfg_max_TPCNsigmaMu); + fDielectronCut.SetTPCNsigmaPiRange(electroncuts.cfg_min_TPCNsigmaPi, electroncuts.cfg_max_TPCNsigmaPi); + fDielectronCut.SetTPCNsigmaKaRange(electroncuts.cfg_min_TPCNsigmaKa, electroncuts.cfg_max_TPCNsigmaKa); + fDielectronCut.SetTPCNsigmaPrRange(electroncuts.cfg_min_TPCNsigmaPr, electroncuts.cfg_max_TPCNsigmaPr); + fDielectronCut.SetTOFNsigmaElRange(electroncuts.cfg_min_TOFNsigmaEl, electroncuts.cfg_max_TOFNsigmaEl); + fDielectronCut.SetPinRangeForPionRejectionTPC(electroncuts.cfg_min_pin_pirejTPC, electroncuts.cfg_max_pin_pirejTPC); + + if (electroncuts.cfg_pid_scheme == static_cast(DielectronCut::PIDSchemes::kPIDML)) { // please call this at the end of DefineDileptonCut + std::vector binsML{}; + binsML.reserve(electroncuts.binsMl.value.size()); + for (size_t i = 0; i < electroncuts.binsMl.value.size(); i++) { + binsML.emplace_back(electroncuts.binsMl.value[i]); + } + std::vector thresholdsML{}; + thresholdsML.reserve(electroncuts.cutsMl.value.size()); + for (size_t i = 0; i < electroncuts.cutsMl.value.size(); i++) { + thresholdsML.emplace_back(electroncuts.cutsMl.value[i]); + } + fDielectronCut.SetMLThresholds(binsML, thresholdsML); + + // static constexpr int nClassesMl = 2; + // const std::vector cutDirMl = {o2::cuts_ml::CutNot, o2::cuts_ml::CutSmaller}; + // const std::vector labelsClasses = {"Background", "Signal"}; + // const uint32_t nBinsMl = electroncuts.binsMl.value.size() - 1; + // const std::vector labelsBins(nBinsMl, "bin"); + // double cutsMlArr[nBinsMl][nClassesMl]; + // for (uint32_t i = 0; i < nBinsMl; i++) { + // cutsMlArr[i][0] = 0.; + // cutsMlArr[i][1] = electroncuts.cutsMl.value[i]; + // } + // o2::framework::LabeledArray cutsMl = {cutsMlArr[0], nBinsMl, nClassesMl, labelsBins, labelsClasses}; + + // mlResponseSingleTrack.configure(electroncuts.binsMl.value, cutsMl, cutDirMl, nClassesMl); + // if (electroncuts.loadModelsFromCCDB) { + // ccdbApi.init(ccdburl); + // mlResponseSingleTrack.setModelPathsCCDB(electroncuts.onnxFileNames.value, ccdbApi, electroncuts.onnxPathsCCDB.value, electroncuts.timestampCCDB.value); + // } else { + // mlResponseSingleTrack.setModelPathsLocal(electroncuts.onnxFileNames.value); + // } + // mlResponseSingleTrack.cacheInputFeaturesIndices(electroncuts.namesInputFeatures); + // mlResponseSingleTrack.cacheBinningIndex(electroncuts.nameBinningFeature); + // mlResponseSingleTrack.init(electroncuts.enableOptimizations.value); + + } // end of PID ML + } + + void DefineDimuonCut() + { + fDimuonCut = DimuonCut("fDimuonCut", "fDimuonCut"); + + // for track + fDimuonCut.SetTrackType(muoncuts.cfg_track_type); + fDimuonCut.SetTrackPtRange(muoncuts.cfg_min_pt_track, muoncuts.cfg_max_pt_track); + fDimuonCut.SetTrackEtaRange(muoncuts.cfg_min_eta_track, muoncuts.cfg_max_eta_track); + fDimuonCut.SetTrackPhiRange(muoncuts.cfg_min_phi_track, muoncuts.cfg_max_phi_track); + fDimuonCut.SetNClustersMFT(muoncuts.cfg_min_ncluster_mft, 10); + fDimuonCut.SetNClustersMCHMID(muoncuts.cfg_min_ncluster_mch, 20); + fDimuonCut.SetChi2(0.f, muoncuts.cfg_max_chi2); + fDimuonCut.SetChi2MFT(0.f, muoncuts.cfg_max_chi2mft); + // fDimuonCut.SetMatchingChi2MCHMFT(0.f, muoncuts.cfg_max_matching_chi2_mftmch); + fDimuonCut.SetMaxMatchingChi2MCHMFTPtDep([&](float pt) { return (pt < muoncuts.cfg_border_pt_for_chi2mchmft ? muoncuts.cfg_max_matching_chi2_mftmch_lowPt : muoncuts.cfg_max_matching_chi2_mftmch_highPt); }); + fDimuonCut.SetMatchingChi2MCHMID(0.f, muoncuts.cfg_max_matching_chi2_mchmid); + fDimuonCut.SetDCAxy(0.f, muoncuts.cfg_max_dcaxy); + fDimuonCut.SetRabs(muoncuts.cfg_min_rabs, muoncuts.cfg_max_rabs); + fDimuonCut.SetMaxPDCARabsDep([&](float rabs) { return (rabs < 26.5 ? 594.f : 324.f); }); + fDimuonCut.SetMaxdPtdEtadPhiwrtMCHMID(muoncuts.cfg_max_relDPt_wrt_matchedMCHMID, muoncuts.cfg_max_DEta_wrt_matchedMCHMID, muoncuts.cfg_max_DPhi_wrt_matchedMCHMID); // this is relevant for global muons + fDimuonCut.SetMFTHitMap(muoncuts.requireMFTHitMap, muoncuts.requiredMFTDisks); + fDimuonCut.EnableTTCA(muoncuts.enableTTCA); + } + + template + void create(TCollisions const& collisions, TTracks const& tracks, TPerCollision const& perCollision, TCut const& cut) + { + for (const auto& collision : collisions) { + if (!fEMEventCut.IsSelected(collision)) { + continue; + } + + float centrality = std::array{collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV()}[eventcuts.cfgCentEstimator]; + if (centrality < eventcuts.cfgCentMin || eventcuts.cfgCentMax < centrality) { + continue; + } + + if (eventcuts.cfgRequireGoodRCT && !rctChecker.checkTable(collision)) { + return; + } + + auto tracks_per_coll = tracks.sliceBy(perCollision, collision.globalIndex()); + for (const auto& track : tracks_per_coll) { + if (!cut.IsSelectedTrack(track)) { + continue; + } + + auto mcParticle = track.template emmcparticle_as(); + auto mcCollision = mcParticle.template emmcevent_as(); + if (cfgEventGeneratorType >= 0 && mcCollision.getSubGeneratorId() != cfgEventGeneratorType) { + continue; + } + + if (cfg_require_true_mc_collision_association && mcParticle.emmceventId() != collision.emmceventId()) { + return; + } + + if constexpr (std::is_same_v, MyMCElectrons>) { + if (std::abs(mcParticle.pdgCode()) != 11) { + continue; + } + + if (electroncuts.acceptOnlyCorrectMatch && o2::aod::pwgem::dilepton::utils::mcutil::hasFakeMatchITSTPC(track)) { + continue; + } + if (electroncuts.acceptOnlyWrongMatch && !o2::aod::pwgem::dilepton::utils::mcutil::hasFakeMatchITSTPC(track)) { + continue; + } + + registry.fill(HIST("Electron/hPIDForTracking"), track.pidForTracking()); + if (electroncuts.checkPIDForTracking && track.pidForTracking() != static_cast(electroncuts.PartIdentifier)) { + continue; + } + + if (cfgFillTHnSparse) { + registry.fill(HIST("Electron/hs_reso"), centrality, mcParticle.pt(), mcParticle.eta(), mcParticle.phi(), -mcParticle.pdgCode() / 11, (mcParticle.pt() - track.pt()) / mcParticle.pt(), mcParticle.eta() - track.eta(), mcParticle.phi() - track.phi()); + } + if (cfgFillTH2) { + registry.fill(HIST("Electron/hPt"), track.pt()); + registry.fill(HIST("Electron/hEtaPhi"), track.phi(), track.eta()); + registry.fill(HIST("Electron/Ptgen_RelDeltaPt"), mcParticle.pt(), (mcParticle.pt() - track.pt()) / mcParticle.pt()); + registry.fill(HIST("Electron/Ptgen_DeltaEta"), mcParticle.pt(), mcParticle.eta() - track.eta()); + if (mcParticle.pdgCode() == -11) { // positron + registry.fill(HIST("Electron/Ptgen_DeltaPhi_Pos"), mcParticle.pt(), mcParticle.phi() - track.phi()); + } else if (mcParticle.pdgCode() == 11) { // electron + registry.fill(HIST("Electron/Ptgen_DeltaPhi_Neg"), mcParticle.pt(), mcParticle.phi() - track.phi()); + } + } + } else if constexpr (std::is_same_v, MyMCMuons>) { + if (std::abs(mcParticle.pdgCode()) != 13) { + continue; + } + + if (track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack)) { + if (muoncuts.acceptOnlyCorrectMatch) { + if (track.emmcparticleId() != track.emmftmcparticleId()) { + continue; + } + } + if (muoncuts.acceptOnlyWrongMatch) { // reject correctly matched MFT-MCH-MID for bkg estimation + if (track.emmcparticleId() == track.emmftmcparticleId()) { + continue; + } + } + + if (cfgFillTHnSparse) { + registry.fill(HIST("GlobalMuon/hs_reso"), centrality, mcParticle.pt(), mcParticle.eta(), mcParticle.phi(), -mcParticle.pdgCode() / 13, (mcParticle.pt() - track.pt()) / mcParticle.pt(), mcParticle.eta() - track.eta(), mcParticle.phi() - track.phi()); + } + + if (cfgFillTH2) { + registry.fill(HIST("GlobalMuon/hPt"), track.pt()); + registry.fill(HIST("GlobalMuon/hEtaPhi"), track.phi(), track.eta()); + registry.fill(HIST("GlobalMuon/Ptgen_RelDeltaPt"), mcParticle.pt(), (mcParticle.pt() - track.pt()) / mcParticle.pt()); + registry.fill(HIST("GlobalMuon/Ptgen_DeltaEta"), mcParticle.pt(), mcParticle.eta() - track.eta()); + if (mcParticle.pdgCode() == -13) { // positive muon + registry.fill(HIST("GlobalMuon/Ptgen_DeltaPhi_Pos"), mcParticle.pt(), mcParticle.phi() - track.phi()); + } else if (mcParticle.pdgCode() == 13) { // negative muon + registry.fill(HIST("GlobalMuon/Ptgen_DeltaPhi_Neg"), mcParticle.pt(), mcParticle.phi() - track.phi()); + } + } + } else if (track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack)) { + if (cfgFillTHnSparse) { + registry.fill(HIST("StandaloneMuon/hs_reso"), centrality, mcParticle.pt(), mcParticle.eta(), mcParticle.phi(), -mcParticle.pdgCode() / 13, (mcParticle.pt() - track.pt()) / mcParticle.pt(), mcParticle.eta() - track.eta(), mcParticle.phi() - track.phi()); + } + if (cfgFillTH2) { + registry.fill(HIST("StandaloneMuon/hPt"), track.pt()); + registry.fill(HIST("StandaloneMuon/hEtaPhi"), track.phi(), track.eta()); + registry.fill(HIST("StandaloneMuon/Ptgen_RelDeltaPt"), mcParticle.pt(), (mcParticle.pt() - track.pt()) / mcParticle.pt()); + registry.fill(HIST("StandaloneMuon/Ptgen_DeltaEta"), mcParticle.pt(), mcParticle.eta() - track.eta()); + if (mcParticle.pdgCode() == -13) { // positive muon + registry.fill(HIST("StandaloneMuon/Ptgen_DeltaPhi_Pos"), mcParticle.pt(), mcParticle.phi() - track.phi()); + } else if (mcParticle.pdgCode() == 13) { // negative muon + registry.fill(HIST("StandaloneMuon/Ptgen_DeltaPhi_Neg"), mcParticle.pt(), mcParticle.phi() - track.phi()); + } + } + } + } + } // end of track loop per collision + } // end of collisions + } + + using MyCollisions = soa::Join; + using MyCollision = MyCollisions::iterator; + + using MyMCElectrons = soa::Join; + using MyMCElectron = MyMCElectrons::iterator; + + using MyMCMuons = soa::Join; + using MyMCMuon = MyMCMuons::iterator; + + SliceCache cache; + Preslice perCollision_mid = aod::emprimaryelectron::emeventId; + Preslice perCollision_fwd = aod::emprimarymuon::emeventId; + + Filter collisionFilter_centrality = (eventcuts.cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < eventcuts.cfgCentMax) || (eventcuts.cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < eventcuts.cfgCentMax) || (eventcuts.cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < eventcuts.cfgCentMax); + Filter collisionFilter_numContrib = eventcuts.cfgNumContribMin <= o2::aod::collision::numContrib && o2::aod::collision::numContrib < eventcuts.cfgNumContribMax; + Filter collisionFilter_occupancy_track = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; + Filter collisionFilter_occupancy_ft0c = eventcuts.cfgFT0COccupancyMin <= o2::aod::evsel::ft0cOccupancyInTimeRange && o2::aod::evsel::ft0cOccupancyInTimeRange < eventcuts.cfgFT0COccupancyMax; + using filteredMyCollisions = soa::Filtered; + + template + void processReso(filteredMyCollisions const& collisions, TTracks const& tracks, aod::EMMCEvents const&, aod::EMMCParticles const&) + { + if constexpr (std::is_same_v, MyMCElectrons>) { + create(collisions, tracks, perCollision_mid, fDielectronCut); + } else if constexpr (std::is_same_v, MyMCMuons>) { + create(collisions, tracks, perCollision_fwd, fDimuonCut); + } + } + + PROCESS_SWITCH_FULL(createResolutionMapDerived, processReso, processElectron, "create resolution map for electrons at mid rapidity", false); + PROCESS_SWITCH_FULL(createResolutionMapDerived, processReso, processMuon, "create resolution map for global muons at fwd rapidity", false); // gl or sa can be selected in subwagons. + + void processGen(aod::EMMCEvents const& mcCollisions) + { + for (const auto& mccollision : mcCollisions) { + registry.fill(HIST("Event/hGenID"), mccollision.getSubGeneratorId()); + } + } + PROCESS_SWITCH(createResolutionMapDerived, processGen, "process generated info", true); + + void processDummy(aod::EMMCEvents const&) {} + PROCESS_SWITCH(createResolutionMapDerived, processDummy, "process dummy", true); +}; +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc, TaskName{"create-resolution-map-derived"})}; +} From 799b573ff66e0b916f9b58fbffe3d67f0a3a17cb Mon Sep 17 00:00:00 2001 From: Evgeny Kryshen Date: Tue, 10 Mar 2026 23:09:48 +0300 Subject: [PATCH 244/347] [DPG] Added bc and time-dependent counters (#15333) --- DPG/Tasks/AOTEvent/lumiQa.cxx | 43 ++++++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/DPG/Tasks/AOTEvent/lumiQa.cxx b/DPG/Tasks/AOTEvent/lumiQa.cxx index 254e58f0b67..fa244f31861 100644 --- a/DPG/Tasks/AOTEvent/lumiQa.cxx +++ b/DPG/Tasks/AOTEvent/lumiQa.cxx @@ -9,24 +9,29 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "CCDB/BasicCCDBManager.h" -#include "Framework/HistogramRegistry.h" -#include "DataFormatsParameters/GRPLHCIFData.h" #include "DataFormatsFT0/Digit.h" -#include "TList.h" +#include "DataFormatsParameters/GRPLHCIFData.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/runDataProcessing.h" +#include + #include "TH1.h" +#include "TList.h" using namespace o2; using namespace o2::framework; using BCsRun3 = soa::Join; struct LumiQaTask { + Configurable confTimeBinWidthInSec{"TimeBinWidthInSec", 60., "Width of time bins in seconds"}; // o2-linter: disable=name/configurable (temporary fix) Service ccdb; HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; int lastRunNumber = -1; + double maxSec = 1; + double minSec = 0; TH1* hCalibT0C = nullptr; static const int nBCsPerOrbit = o2::constants::lhc::LHCMaxBunches; std::bitset bcPatternB; @@ -40,6 +45,7 @@ struct LumiQaTask { ccdb->setURL("http://alice-ccdb.cern.ch"); ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); + const AxisSpec axisMultZNA{2000, 0., 400., "ZNA multiplicity"}; const AxisSpec axisMultZNC{2000, 0., 400., "ZNC multiplicity"}; const AxisSpec axisMultT0M{1000, 0., 270000., "T0M multiplicity"}; @@ -116,9 +122,30 @@ struct LumiQaTask { LOGF(info, "hCalibZeqFT0C histogram is not available for run=%d at timestamp=%llu", runNumber, ts); return; } + + if (runNumber >= 500000) { + auto runInfo = o2::parameters::AggregatedRunInfo::buildAggregatedRunInfo(o2::ccdb::BasicCCDBManager::instance(), runNumber); + auto tsSOR = runInfo.sor; + auto tsEOR = runInfo.eor; + minSec = floor(tsSOR / 1000.); + maxSec = ceil(tsEOR / 1000.); + } + + int nTimeBins = static_cast((maxSec - minSec) / confTimeBinWidthInSec); + double timeInterval = nTimeBins * confTimeBinWidthInSec; + + const AxisSpec axisBCs{nBCsPerOrbit, 0., static_cast(nBCsPerOrbit), ""}; + const AxisSpec axisSeconds{nTimeBins, 0, timeInterval, "seconds"}; + histos.add("hSecondsBcsTCE", "", kTH2D, {axisSeconds, axisBCs}); + histos.add("hSecondsBcsZNA", "", kTH2D, {axisSeconds, axisBCs}); + histos.add("hSecondsBcsZNC", "", kTH2D, {axisSeconds, axisBCs}); + histos.add("hSecondsBcsZEM", "", kTH2D, {axisSeconds, axisBCs}); } for (const auto& bc : bcs) { + int64_t ts = bc.timestamp(); + double secFromSOR = ts / 1000. - minSec; + double bcInOrbit = bc.globalBC() % nBCsPerOrbit; if (bc.has_zdc()) { float timeZNA = bc.zdc().timeZNA(); float timeZNC = bc.zdc().timeZNC(); @@ -159,12 +186,15 @@ struct LumiQaTask { if (fabs(timeZNA - meanTimeZNA) < 2) { histos.get(HIST("hCounterZNA"))->Fill(srun, 1); + histos.fill(HIST("hSecondsBcsZNA"), secFromSOR, bcInOrbit); } if (fabs(timeZNC - meanTimeZNC) < 2) { histos.get(HIST("hCounterZNC"))->Fill(srun, 1); + histos.fill(HIST("hSecondsBcsZNC"), secFromSOR, bcInOrbit); } if (fabs(timeZNA - meanTimeZNA) < 2 || fabs(timeZNC - meanTimeZNC) < 2) { histos.get(HIST("hCounterZEM"))->Fill(srun, 1); + histos.fill(HIST("hSecondsBcsZEM"), secFromSOR, bcInOrbit); } } @@ -211,6 +241,7 @@ struct LumiQaTask { histos.fill(HIST("hCentT0CselTVXTCEB"), centT0C); histos.get(HIST("hCounterTCE"))->Fill(srun, 1); + histos.fill(HIST("hSecondsBcsTCE"), secFromSOR, bcInOrbit); } } }; From c76a89e446806a9e49c0e1768931cb6157e82aa2 Mon Sep 17 00:00:00 2001 From: JBae <110481228+joonsukbae@users.noreply.github.com> Date: Tue, 10 Mar 2026 21:44:30 +0100 Subject: [PATCH 245/347] =?UTF-8?q?[PWGJE]=20pTHat=20handling,=20remove=20?= =?UTF-8?q?HepMCXSections=20dependency,=20add=20R-d=E2=80=A6=20(#15284)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Claude Opus 4.6 --- PWGJE/Core/JetMatchingUtilities.h | 18 ++- .../Duplicates/jetMatchingDuplicates.h | 11 +- .../Substructure/jetSubstructureMatching.h | 11 +- .../Substructure/jetSubstructureMatchingSub.h | 11 +- PWGJE/TableProducer/Matching/jetMatchingMC.h | 11 +- .../TableProducer/Matching/jetMatchingMCSub.h | 11 +- PWGJE/TableProducer/Matching/jetMatchingSub.h | 11 +- PWGJE/Tasks/jetSpectraCharged.cxx | 61 +++++----- PWGJE/Tasks/trackEfficiency.cxx | 106 ++++++++---------- 9 files changed, 145 insertions(+), 106 deletions(-) diff --git a/PWGJE/Core/JetMatchingUtilities.h b/PWGJE/Core/JetMatchingUtilities.h index 8fb24f29b50..38c5bc29774 100644 --- a/PWGJE/Core/JetMatchingUtilities.h +++ b/PWGJE/Core/JetMatchingUtilities.h @@ -293,7 +293,7 @@ std::tuple, std::vector> MatchJetsGeometrically( } template -void MatchGeo(T const& jetsBasePerCollision, U const& jetsTagPerCollision, std::vector>& baseToTagMatchingGeo, std::vector>& tagToBaseMatchingGeo, float maxMatchingDistance) +void MatchGeo(T const& jetsBasePerCollision, U const& jetsTagPerCollision, std::vector>& baseToTagMatchingGeo, std::vector>& tagToBaseMatchingGeo, std::vector const& jetRadiiForMatchingDistance, std::vector const& maxMatchingDistancePerJetR) { std::vector jetsR; for (const auto& jetBase : jetsBasePerCollision) { @@ -307,6 +307,16 @@ void MatchGeo(T const& jetsBasePerCollision, U const& jetsTagPerCollision, std:: } } for (auto jetR : jetsR) { + float effectiveMatchingDistance = -1.0f; + for (std::size_t i = 0; i < jetRadiiForMatchingDistance.size(); i++) { + if (std::round(jetRadiiForMatchingDistance[i] * 100.0) == std::round(jetR)) { + effectiveMatchingDistance = maxMatchingDistancePerJetR[i]; + break; + } + } + if (effectiveMatchingDistance < 0.0f) { + LOGP(fatal, "No matching distance configured for jet R={:.2f}. Add it to jetRadiiForMatchingDistance and maxMatchingDistancePerJetR.", jetR / 100.0); + } std::vector jetsBasePhi; std::vector jetsBaseEta; std::vector jetsBaseGlobalIndex; @@ -332,7 +342,7 @@ void MatchGeo(T const& jetsBasePerCollision, U const& jetsTagPerCollision, std:: jetsTagEta.emplace_back(jetTag.eta()); jetsTagGlobalIndex.emplace_back(jetTag.globalIndex()); } - std::tie(baseToTagMatchingGeoIndex, tagToBaseMatchingGeoIndex) = MatchJetsGeometrically(jetsBasePhi, jetsBaseEta, jetsTagPhi, jetsTagEta, maxMatchingDistance); // change max distnace to a function call + std::tie(baseToTagMatchingGeoIndex, tagToBaseMatchingGeoIndex) = MatchJetsGeometrically(jetsBasePhi, jetsBaseEta, jetsTagPhi, jetsTagEta, effectiveMatchingDistance); int jetBaseIndex = 0; int jetTagIndex = 0; for (const auto& jetBase : jetsBasePerCollision) { @@ -564,11 +574,11 @@ void MatchPt(T const& jetsBasePerCollision, U const& jetsTagPerCollision, std::v // function that calls all the Match functions template -void doAllMatching(T const& jetsBasePerCollision, U const& jetsTagPerCollision, std::vector>& baseToTagMatchingGeo, std::vector>& baseToTagMatchingPt, std::vector>& baseToTagMatchingHF, std::vector>& tagToBaseMatchingGeo, std::vector>& tagToBaseMatchingPt, std::vector>& tagToBaseMatchingHF, V const& candidatesBase, M const& tracksBase, N const& clustersBase, O const& candidatesTag, P const& tracksTag, R const& clustersTag, bool doMatchingGeo, bool doMatchingHf, bool doMatchingPt, float maxMatchingDistance, float minPtFraction) +void doAllMatching(T const& jetsBasePerCollision, U const& jetsTagPerCollision, std::vector>& baseToTagMatchingGeo, std::vector>& baseToTagMatchingPt, std::vector>& baseToTagMatchingHF, std::vector>& tagToBaseMatchingGeo, std::vector>& tagToBaseMatchingPt, std::vector>& tagToBaseMatchingHF, V const& candidatesBase, M const& tracksBase, N const& clustersBase, O const& candidatesTag, P const& tracksTag, R const& clustersTag, bool doMatchingGeo, bool doMatchingHf, bool doMatchingPt, float minPtFraction, std::vector const& jetRadiiForMatchingDistance, std::vector const& maxMatchingDistancePerJetR) { // geometric matching if (doMatchingGeo) { - MatchGeo(jetsBasePerCollision, jetsTagPerCollision, baseToTagMatchingGeo, tagToBaseMatchingGeo, maxMatchingDistance); + MatchGeo(jetsBasePerCollision, jetsTagPerCollision, baseToTagMatchingGeo, tagToBaseMatchingGeo, jetRadiiForMatchingDistance, maxMatchingDistancePerJetR); } // pt matching if (doMatchingPt) { diff --git a/PWGJE/TableProducer/Matching/Duplicates/jetMatchingDuplicates.h b/PWGJE/TableProducer/Matching/Duplicates/jetMatchingDuplicates.h index 504219671fd..d1adaf02e28 100644 --- a/PWGJE/TableProducer/Matching/Duplicates/jetMatchingDuplicates.h +++ b/PWGJE/TableProducer/Matching/Duplicates/jetMatchingDuplicates.h @@ -34,7 +34,8 @@ struct JetMatchingDuplicates { o2::framework::Configurable doMatchingGeo{"doMatchingGeo", true, "Enable geometric matching"}; o2::framework::Configurable doMatchingPt{"doMatchingPt", true, "Enable pt matching"}; o2::framework::Configurable doMatchingHf{"doMatchingHf", false, "Enable HF matching"}; - o2::framework::Configurable maxMatchingDistance{"maxMatchingDistance", 0.24f, "Max matching distance"}; + o2::framework::Configurable> jetRadiiForMatchingDistance{"jetRadiiForMatchingDistance", {0.2, 0.3, 0.4, 0.5, 0.6}, "Jet R values for per-R matching distance"}; + o2::framework::Configurable> maxMatchingDistancePerJetR{"maxMatchingDistancePerJetR", {0.12, 0.18, 0.24, 0.30, 0.36}, "Max matching distance (0.6*R, see ALICE-AN-852) for each R in jetRadiiForMatchingDistance"}; o2::framework::Configurable minPtFraction{"minPtFraction", 0.5f, "Minimum pt fraction for pt matching"}; o2::framework::Produces jetsBasetoTagMatchingTable; @@ -49,6 +50,12 @@ struct JetMatchingDuplicates { void init(o2::framework::InitContext const&) { + if (jetRadiiForMatchingDistance->empty() || maxMatchingDistancePerJetR->empty()) { + LOGP(fatal, "jetRadiiForMatchingDistance and maxMatchingDistancePerJetR must not be empty"); + } + if (jetRadiiForMatchingDistance->size() != maxMatchingDistancePerJetR->size()) { + LOGP(fatal, "jetRadiiForMatchingDistance and maxMatchingDistancePerJetR must have the same number of entries"); + } } void processJets(o2::aod::JetCollisions const& collisions, @@ -72,7 +79,7 @@ struct JetMatchingDuplicates { const auto jetsBasePerColl = jetsBase.sliceBy(baseJetsPerCollision, collision.globalIndex()); const auto jetsTagPerColl = jetsTag.sliceBy(tagJetsPerCollision, collision.globalIndex()); // initialise template parameters as false since even if they are Mc we are not matching between detector and particle level - jetmatchingutilities::doAllMatching(jetsBasePerColl, jetsTagPerColl, jetsBasetoTagMatchingGeo, jetsBasetoTagMatchingPt, jetsBasetoTagMatchingHF, jetsTagtoBaseMatchingGeo, jetsTagtoBaseMatchingPt, jetsTagtoBaseMatchingHF, candidates, tracks, tracks, candidates, tracks, tracks, doMatchingGeo, doMatchingHf, doMatchingPt, maxMatchingDistance, minPtFraction); + jetmatchingutilities::doAllMatching(jetsBasePerColl, jetsTagPerColl, jetsBasetoTagMatchingGeo, jetsBasetoTagMatchingPt, jetsBasetoTagMatchingHF, jetsTagtoBaseMatchingGeo, jetsTagtoBaseMatchingPt, jetsTagtoBaseMatchingHF, candidates, tracks, tracks, candidates, tracks, tracks, doMatchingGeo, doMatchingHf, doMatchingPt, minPtFraction, jetRadiiForMatchingDistance, maxMatchingDistancePerJetR); } for (auto i = 0; i < jetsBase.size(); ++i) { diff --git a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatching.h b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatching.h index a971c1a7e8e..afc68acaa6b 100644 --- a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatching.h +++ b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatching.h @@ -41,7 +41,8 @@ struct JetSubstructureMatching { o2::framework::Configurable doMatchingGeo{"doMatchingGeo", true, "Enable geometric matching"}; o2::framework::Configurable doMatchingPt{"doMatchingPt", true, "Enable pt matching"}; o2::framework::Configurable doMatchingHf{"doMatchingHf", false, "Enable HF matching"}; - o2::framework::Configurable maxMatchingDistance{"maxMatchingDistance", 0.24f, "Max matching distance"}; + o2::framework::Configurable> jetRadiiForMatchingDistance{"jetRadiiForMatchingDistance", {0.2, 0.3, 0.4, 0.5, 0.6}, "Jet R values for per-R matching distance"}; + o2::framework::Configurable> maxMatchingDistancePerJetR{"maxMatchingDistancePerJetR", {0.12, 0.18, 0.24, 0.30, 0.36}, "Max matching distance (0.6*R, see ALICE-AN-852) for each R in jetRadiiForMatchingDistance"}; o2::framework::Configurable minPtFraction{"minPtFraction", 0.5f, "Minimum pt fraction for pt matching"}; o2::framework::Configurable requireGeoMatchedJets{"requireGeoMatchedJets", false, "require jets are geo matched as well"}; o2::framework::Configurable requirePtMatchedJets{"requirePtMatchedJets", false, "require jets are pT matched as well"}; @@ -52,6 +53,12 @@ struct JetSubstructureMatching { void init(o2::framework::InitContext const&) { + if (jetRadiiForMatchingDistance->empty() || maxMatchingDistancePerJetR->empty()) { + LOGP(fatal, "jetRadiiForMatchingDistance and maxMatchingDistancePerJetR must not be empty"); + } + if (jetRadiiForMatchingDistance->size() != maxMatchingDistancePerJetR->size()) { + LOGP(fatal, "jetRadiiForMatchingDistance and maxMatchingDistancePerJetR must have the same number of entries"); + } } o2::framework::PresliceOptional BaseSplittingsPerBaseJetInclusive = o2::aod::chargedmcdetectorlevelsplitting::jetId; @@ -218,7 +225,7 @@ struct JetSubstructureMatching { jetBaseSplittingsMap[jetBaseSplitting.globalIndex()] = baseSplittingIndex; baseSplittingIndex++; } - jetmatchingutilities::doAllMatching(jetBaseSplittings, jetTagSplittings, jetsBasetoTagSplittingsMatchingGeo, jetsBasetoTagSplittingsMatchingPt, jetsBasetoTagSplittingsMatchingHF, jetsTagtoBaseSplittingsMatchingGeo, jetsTagtoBaseSplittingsMatchingPt, jetsTagtoBaseSplittingsMatchingHF, candidatesBase, tracksBase, clustersBase, candidatesTag, tracksTag, tracksTag, doMatchingGeo, doMatchingHf, doMatchingPt, maxMatchingDistance, minPtFraction); + jetmatchingutilities::doAllMatching(jetBaseSplittings, jetTagSplittings, jetsBasetoTagSplittingsMatchingGeo, jetsBasetoTagSplittingsMatchingPt, jetsBasetoTagSplittingsMatchingHF, jetsTagtoBaseSplittingsMatchingGeo, jetsTagtoBaseSplittingsMatchingPt, jetsTagtoBaseSplittingsMatchingHF, candidatesBase, tracksBase, clustersBase, candidatesTag, tracksTag, tracksTag, doMatchingGeo, doMatchingHf, doMatchingPt, minPtFraction, jetRadiiForMatchingDistance, maxMatchingDistancePerJetR); // auto const& jetBasePairs = jetsBasePairs.sliceBy(BasePairsPerBaseJet, jetBase.globalIndex()); auto const& jetBasePairs = slicedPerJetForMatching(jetsBasePairs, jetBase, BasePairsPerBaseJetInclusive, BasePairsPerBaseJetD0, BasePairsPerBaseJetDplus, BasePairsPerBaseJetDs, BasePairsPerBaseJetDstar, BasePairsPerBaseJetLc, BasePairsPerBaseJetB0, BasePairsPerBaseJetBplus, BasePairsPerBaseJetXicToXiPiPi, BasePairsPerBaseJetDielectron); int basePairIndex = 0; diff --git a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSub.h b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSub.h index bcce8a6103f..6075d86cd55 100644 --- a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSub.h +++ b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSub.h @@ -42,7 +42,8 @@ struct JetSubstructureMatchingSub { o2::framework::Configurable doMatchingGeo{"doMatchingGeo", true, "Enable geometric matching"}; o2::framework::Configurable doMatchingPt{"doMatchingPt", true, "Enable pt matching"}; o2::framework::Configurable doMatchingHf{"doMatchingHf", false, "Enable HF matching"}; - o2::framework::Configurable maxMatchingDistance{"maxMatchingDistance", 0.24f, "Max matching distance"}; + o2::framework::Configurable> jetRadiiForMatchingDistance{"jetRadiiForMatchingDistance", {0.2, 0.3, 0.4, 0.5, 0.6}, "Jet R values for per-R matching distance"}; + o2::framework::Configurable> maxMatchingDistancePerJetR{"maxMatchingDistancePerJetR", {0.12, 0.18, 0.24, 0.30, 0.36}, "Max matching distance (0.6*R, see ALICE-AN-852) for each R in jetRadiiForMatchingDistance"}; o2::framework::Configurable minPtFraction{"minPtFraction", 0.5f, "Minimum pt fraction for pt matching"}; o2::framework::Configurable requireGeoMatchedJets{"requireGeoMatchedJets", false, "require jets are geo matched as well"}; o2::framework::Configurable requirePtMatchedJets{"requirePtMatchedJets", false, "require jets are pT matched as well"}; @@ -53,6 +54,12 @@ struct JetSubstructureMatchingSub { void init(o2::framework::InitContext const&) { + if (jetRadiiForMatchingDistance->empty() || maxMatchingDistancePerJetR->empty()) { + LOGP(fatal, "jetRadiiForMatchingDistance and maxMatchingDistancePerJetR must not be empty"); + } + if (jetRadiiForMatchingDistance->size() != maxMatchingDistancePerJetR->size()) { + LOGP(fatal, "jetRadiiForMatchingDistance and maxMatchingDistancePerJetR must have the same number of entries"); + } } o2::framework::PresliceOptional BaseSplittingsPerBaseJetInclusive = o2::aod::chargedsplitting::jetId; @@ -219,7 +226,7 @@ struct JetSubstructureMatchingSub { jetBaseSplittingsMap[jetBaseSplitting.globalIndex()] = baseSplittingIndex; baseSplittingIndex++; } - jetmatchingutilities::doAllMatching(jetBaseSplittings, jetTagSplittings, jetsBasetoTagSplittingsMatchingGeo, jetsBasetoTagSplittingsMatchingPt, jetsBasetoTagSplittingsMatchingHF, jetsTagtoBaseSplittingsMatchingGeo, jetsTagtoBaseSplittingsMatchingPt, jetsTagtoBaseSplittingsMatchingHF, candidates, tracksBase, clustersBase, candidates, tracksTag, tracksTag, doMatchingGeo, doMatchingHf, doMatchingPt, maxMatchingDistance, minPtFraction); + jetmatchingutilities::doAllMatching(jetBaseSplittings, jetTagSplittings, jetsBasetoTagSplittingsMatchingGeo, jetsBasetoTagSplittingsMatchingPt, jetsBasetoTagSplittingsMatchingHF, jetsTagtoBaseSplittingsMatchingGeo, jetsTagtoBaseSplittingsMatchingPt, jetsTagtoBaseSplittingsMatchingHF, candidates, tracksBase, clustersBase, candidates, tracksTag, tracksTag, doMatchingGeo, doMatchingHf, doMatchingPt, minPtFraction, jetRadiiForMatchingDistance, maxMatchingDistancePerJetR); // auto const& jetBasePairs = jetsBasePairs.sliceBy(BasePairsPerBaseJet, jetBase.globalIndex()); auto const& jetBasePairs = slicedPerJetForMatching(jetsBasePairs, jetBase, BasePairsPerBaseJetInclusive, BasePairsPerBaseJetD0, BasePairsPerBaseJetDplus, BasePairsPerBaseJetDs, BasePairsPerBaseJetDstar, BasePairsPerBaseJetLc, BasePairsPerBaseJetB0, BasePairsPerBaseJetBplus, BasePairsPerBaseJetXicToXiPiPi, BasePairsPerBaseJetDielectron); int basePairIndex = 0; diff --git a/PWGJE/TableProducer/Matching/jetMatchingMC.h b/PWGJE/TableProducer/Matching/jetMatchingMC.h index 10257b94ba7..a78c48a2800 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingMC.h +++ b/PWGJE/TableProducer/Matching/jetMatchingMC.h @@ -37,7 +37,8 @@ struct JetMatchingMc { o2::framework::Configurable doMatchingGeo{"doMatchingGeo", true, "Enable geometric matching"}; o2::framework::Configurable doMatchingPt{"doMatchingPt", true, "Enable pt matching"}; o2::framework::Configurable doMatchingHf{"doMatchingHf", false, "Enable HF matching"}; - o2::framework::Configurable maxMatchingDistance{"maxMatchingDistance", 0.24f, "Max matching distance"}; + o2::framework::Configurable> jetRadiiForMatchingDistance{"jetRadiiForMatchingDistance", {0.2, 0.3, 0.4, 0.5, 0.6}, "Jet R values for per-R matching distance"}; + o2::framework::Configurable> maxMatchingDistancePerJetR{"maxMatchingDistancePerJetR", {0.12, 0.18, 0.24, 0.30, 0.36}, "Max matching distance (0.6*R, see ALICE-AN-852) for each R in jetRadiiForMatchingDistance"}; o2::framework::Configurable minPtFraction{"minPtFraction", 0.5f, "Minimum pt fraction for pt matching"}; o2::framework::Produces jetsBasetoTagMatchingTable; @@ -54,6 +55,12 @@ struct JetMatchingMc { void init(o2::framework::InitContext const&) { + if (jetRadiiForMatchingDistance->empty() || maxMatchingDistancePerJetR->empty()) { + LOGP(fatal, "jetRadiiForMatchingDistance and maxMatchingDistancePerJetR must not be empty"); + } + if (jetRadiiForMatchingDistance->size() != maxMatchingDistancePerJetR->size()) { + LOGP(fatal, "jetRadiiForMatchingDistance and maxMatchingDistancePerJetR must have the same number of entries"); + } } void processJets(o2::aod::JetMcCollisions const& mcCollisions, o2::aod::JetCollisionsMCD const& collisions, @@ -84,7 +91,7 @@ struct JetMatchingMc { const auto jetsBasePerColl = jetsBase.sliceBy(baseJetsPerCollision, jetsBaseIsMc ? mcCollision.globalIndex() : collision.globalIndex()); const auto jetsTagPerColl = jetsTag.sliceBy(tagJetsPerCollision, jetsTagIsMc ? mcCollision.globalIndex() : collision.globalIndex()); - jetmatchingutilities::doAllMatching(jetsBasePerColl, jetsTagPerColl, jetsBasetoTagMatchingGeo, jetsBasetoTagMatchingPt, jetsBasetoTagMatchingHF, jetsTagtoBaseMatchingGeo, jetsTagtoBaseMatchingPt, jetsTagtoBaseMatchingHF, candidatesBase, tracks, clusters, candidatesTag, particles, particles, doMatchingGeo, doMatchingHf, doMatchingPt, maxMatchingDistance, minPtFraction); + jetmatchingutilities::doAllMatching(jetsBasePerColl, jetsTagPerColl, jetsBasetoTagMatchingGeo, jetsBasetoTagMatchingPt, jetsBasetoTagMatchingHF, jetsTagtoBaseMatchingGeo, jetsTagtoBaseMatchingPt, jetsTagtoBaseMatchingHF, candidatesBase, tracks, clusters, candidatesTag, particles, particles, doMatchingGeo, doMatchingHf, doMatchingPt, minPtFraction, jetRadiiForMatchingDistance, maxMatchingDistancePerJetR); } } for (auto i = 0; i < jetsBase.size(); ++i) { diff --git a/PWGJE/TableProducer/Matching/jetMatchingMCSub.h b/PWGJE/TableProducer/Matching/jetMatchingMCSub.h index 51a0b3d8424..395783865b4 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingMCSub.h +++ b/PWGJE/TableProducer/Matching/jetMatchingMCSub.h @@ -33,7 +33,8 @@ struct JetMatchingMcSub { o2::framework::Configurable doMatchingGeo{"doMatchingGeo", true, "Enable geometric matching"}; o2::framework::Configurable doMatchingPt{"doMatchingPt", true, "Enable pt matching"}; o2::framework::Configurable doMatchingHf{"doMatchingHf", false, "Enable HF matching"}; - o2::framework::Configurable maxMatchingDistance{"maxMatchingDistance", 0.24f, "Max matching distance"}; + o2::framework::Configurable> jetRadiiForMatchingDistance{"jetRadiiForMatchingDistance", {0.2, 0.3, 0.4, 0.5, 0.6}, "Jet R values for per-R matching distance"}; + o2::framework::Configurable> maxMatchingDistancePerJetR{"maxMatchingDistancePerJetR", {0.12, 0.18, 0.24, 0.30, 0.36}, "Max matching distance (0.6*R, see ALICE-AN-852) for each R in jetRadiiForMatchingDistance"}; o2::framework::Configurable minPtFraction{"minPtFraction", 0.5f, "Minimum pt fraction for pt matching"}; o2::framework::Produces jetsBasetoTagMatchingTable; @@ -48,6 +49,12 @@ struct JetMatchingMcSub { void init(o2::framework::InitContext const&) { + if (jetRadiiForMatchingDistance->empty() || maxMatchingDistancePerJetR->empty()) { + LOGP(fatal, "jetRadiiForMatchingDistance and maxMatchingDistancePerJetR must not be empty"); + } + if (jetRadiiForMatchingDistance->size() != maxMatchingDistancePerJetR->size()) { + LOGP(fatal, "jetRadiiForMatchingDistance and maxMatchingDistancePerJetR must have the same number of entries"); + } } void processJets(o2::aod::JetCollisions const& collisions, @@ -73,7 +80,7 @@ struct JetMatchingMcSub { const auto jetsBasePerColl = jetsBase.sliceBy(baseJetsPerCollision, collision.globalIndex()); const auto jetsTagPerColl = jetsTag.sliceBy(tagJetsPerCollision, collision.globalIndex()); - jetmatchingutilities::doAllMatching(jetsBasePerColl, jetsTagPerColl, jetsBasetoTagMatchingGeo, jetsBasetoTagMatchingPt, jetsBasetoTagMatchingHF, jetsTagtoBaseMatchingGeo, jetsTagtoBaseMatchingPt, jetsTagtoBaseMatchingHF, candidates, tracks, tracks, candidates, tracksSub, tracksSub, doMatchingGeo, doMatchingHf, doMatchingPt, maxMatchingDistance, minPtFraction); + jetmatchingutilities::doAllMatching(jetsBasePerColl, jetsTagPerColl, jetsBasetoTagMatchingGeo, jetsBasetoTagMatchingPt, jetsBasetoTagMatchingHF, jetsTagtoBaseMatchingGeo, jetsTagtoBaseMatchingPt, jetsTagtoBaseMatchingHF, candidates, tracks, tracks, candidates, tracksSub, tracksSub, doMatchingGeo, doMatchingHf, doMatchingPt, minPtFraction, jetRadiiForMatchingDistance, maxMatchingDistancePerJetR); } for (auto i = 0; i < jetsBase.size(); ++i) { diff --git a/PWGJE/TableProducer/Matching/jetMatchingSub.h b/PWGJE/TableProducer/Matching/jetMatchingSub.h index 0aa035794c3..b5d1db2491c 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingSub.h +++ b/PWGJE/TableProducer/Matching/jetMatchingSub.h @@ -34,7 +34,8 @@ struct JetMatchingSub { o2::framework::Configurable doMatchingGeo{"doMatchingGeo", true, "Enable geometric matching"}; o2::framework::Configurable doMatchingPt{"doMatchingPt", true, "Enable pt matching"}; o2::framework::Configurable doMatchingHf{"doMatchingHf", false, "Enable HF matching"}; - o2::framework::Configurable maxMatchingDistance{"maxMatchingDistance", 0.24f, "Max matching distance"}; + o2::framework::Configurable> jetRadiiForMatchingDistance{"jetRadiiForMatchingDistance", {0.2, 0.3, 0.4, 0.5, 0.6}, "Jet R values for per-R matching distance"}; + o2::framework::Configurable> maxMatchingDistancePerJetR{"maxMatchingDistancePerJetR", {0.12, 0.18, 0.24, 0.30, 0.36}, "Max matching distance (0.6*R, see ALICE-AN-852) for each R in jetRadiiForMatchingDistance"}; o2::framework::Configurable minPtFraction{"minPtFraction", 0.5f, "Minimum pt fraction for pt matching"}; o2::framework::Produces jetsBasetoTagMatchingTable; @@ -49,6 +50,12 @@ struct JetMatchingSub { void init(o2::framework::InitContext const&) { + if (jetRadiiForMatchingDistance->empty() || maxMatchingDistancePerJetR->empty()) { + LOGP(fatal, "jetRadiiForMatchingDistance and maxMatchingDistancePerJetR must not be empty"); + } + if (jetRadiiForMatchingDistance->size() != maxMatchingDistancePerJetR->size()) { + LOGP(fatal, "jetRadiiForMatchingDistance and maxMatchingDistancePerJetR must have the same number of entries"); + } } void processJets(o2::aod::JetCollisions const& collisions, @@ -72,7 +79,7 @@ struct JetMatchingSub { const auto jetsBasePerColl = jetsBase.sliceBy(baseJetsPerCollision, collision.globalIndex()); const auto jetsTagPerColl = jetsTag.sliceBy(tagJetsPerCollision, collision.globalIndex()); - jetmatchingutilities::doAllMatching(jetsBasePerColl, jetsTagPerColl, jetsBasetoTagMatchingGeo, jetsBasetoTagMatchingPt, jetsBasetoTagMatchingHF, jetsTagtoBaseMatchingGeo, jetsTagtoBaseMatchingPt, jetsTagtoBaseMatchingHF, candidates, tracks, tracks, candidates, tracksSub, tracksSub, doMatchingGeo, doMatchingHf, doMatchingPt, maxMatchingDistance, minPtFraction); + jetmatchingutilities::doAllMatching(jetsBasePerColl, jetsTagPerColl, jetsBasetoTagMatchingGeo, jetsBasetoTagMatchingPt, jetsBasetoTagMatchingHF, jetsTagtoBaseMatchingGeo, jetsTagtoBaseMatchingPt, jetsTagtoBaseMatchingHF, candidates, tracks, tracks, candidates, tracksSub, tracksSub, doMatchingGeo, doMatchingHf, doMatchingPt, minPtFraction, jetRadiiForMatchingDistance, maxMatchingDistancePerJetR); } for (auto i = 0; i < jetsBase.size(); ++i) { diff --git a/PWGJE/Tasks/jetSpectraCharged.cxx b/PWGJE/Tasks/jetSpectraCharged.cxx index 3812e1a08ff..09e02d67d4e 100644 --- a/PWGJE/Tasks/jetSpectraCharged.cxx +++ b/PWGJE/Tasks/jetSpectraCharged.cxx @@ -463,9 +463,8 @@ struct JetSpectraCharged { } template - void fillJetHistograms(TJets const& jet, float centrality, float weight = 1.0) + void fillJetHistograms(TJets const& jet, float centrality, float weight = 1.0, float pTHat = 999.0) { - float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); if (jet.pt() > pTHatMaxMCD * pTHat || pTHat < pTHatAbsoluteMin) { return; } @@ -487,9 +486,8 @@ struct JetSpectraCharged { } template - void fillJetAreaSubHistograms(TJets const& jet, float centrality, float rho, float weight = 1.0) + void fillJetAreaSubHistograms(TJets const& jet, float centrality, float rho, float weight = 1.0, float pTHat = 999.0) { - float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); if (jet.pt() > pTHatMaxMCD * pTHat || pTHat < pTHatAbsoluteMin) { return; } @@ -516,9 +514,8 @@ struct JetSpectraCharged { } template - void fillMCPHistograms(TJets const& jet, float weight = 1.0) + void fillMCPHistograms(TJets const& jet, float weight = 1.0, float pTHat = 999.0) { - float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); if (jet.pt() > pTHatMaxMCP * pTHat || pTHat < pTHatAbsoluteMin) { return; } @@ -538,9 +535,8 @@ struct JetSpectraCharged { } template - void fillMCPAreaSubHistograms(TJets const& jet, float rho = 0.0, float weight = 1.0) + void fillMCPAreaSubHistograms(TJets const& jet, float rho = 0.0, float weight = 1.0, float pTHat = 999.0) { - float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); if (jet.pt() > pTHatMaxMCP * pTHat || pTHat < pTHatAbsoluteMin) { return; } @@ -559,9 +555,8 @@ struct JetSpectraCharged { } template - void fillEventWiseConstituentSubtractedHistograms(TJets const& jet, float centrality, float weight = 1.0) + void fillEventWiseConstituentSubtractedHistograms(TJets const& jet, float centrality, float weight = 1.0, float pTHat = 999.0) { - float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); if (jet.pt() > pTHatMaxMCD * pTHat || pTHat < pTHatAbsoluteMin) { return; } @@ -572,9 +567,8 @@ struct JetSpectraCharged { } template - void fillMatchedHistograms(TBase const& jetMCD, float weight = 1.0) + void fillMatchedHistograms(TBase const& jetMCD, float weight = 1.0, float pTHat = 999.0) { - float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); if (jetMCD.pt() > pTHatMaxMCD * pTHat || pTHat < pTHatAbsoluteMin) { return; } @@ -665,15 +659,14 @@ struct JetSpectraCharged { } template - void fillGeoMatchedAreaSubHistograms(TBase const& jetMCD, float rho, float mcrho = 0.0, float weight = 1.0) + void fillGeoMatchedAreaSubHistograms(TBase const& jetMCD, float rho, float mcrho = 0.0, float weight = 1.0, float pTHat = 999.0) { - float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); if (jetMCD.pt() > pTHatMaxMCD * pTHat) { return; } if (jetMCD.has_matchedJetGeo()) { for (const auto& jetMCP : jetMCD.template matchedJetGeo_as>()) { - if (jetMCP.pt() > pTHatMaxMCD * pTHat) { + if (jetMCP.pt() > pTHatMaxMCP * pTHat) { continue; } if (jetMCD.r() == round(selectedJetsRadius * 100.0f)) { @@ -848,9 +841,10 @@ struct JetSpectraCharged { } PROCESS_SWITCH(JetSpectraCharged, processSpectraAreaSubMCD, "jet spectra with rho-area subtraction for MCD", false); - void processSpectraMCDWeighted(soa::Filtered::iterator const& collision, + void processSpectraMCDWeighted(soa::Filtered::iterator const& collision, soa::Join const& jets, - aod::JetTracks const&) + aod::JetTracks const&, + aod::JetMcCollisions const&) { bool fillHistograms = false; bool isWeighted = true; @@ -858,7 +852,7 @@ struct JetSpectraCharged { if (!applyCollisionCuts(collision, fillHistograms, isWeighted, eventWeight)) { return; } - + float pTHat = collision.has_mcCollision() && collision.mcCollision().ptHard() < 999.0f ? collision.mcCollision().ptHard() : 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); float centrality = -1.0; checkCentFT0M ? centrality = collision.centFT0M() : centrality = collision.centFT0C(); @@ -869,14 +863,15 @@ struct JetSpectraCharged { if (!isAcceptedJet(jet)) { continue; } - fillJetHistograms(jet, centrality, eventWeight); + fillJetHistograms(jet, centrality, eventWeight, pTHat); } } PROCESS_SWITCH(JetSpectraCharged, processSpectraMCDWeighted, "jet finder QA mcd with weighted events", false); - void processSpectraAreaSubMCDWeighted(soa::Filtered>::iterator const& collision, + void processSpectraAreaSubMCDWeighted(soa::Filtered>::iterator const& collision, soa::Join const& jets, - aod::JetTracks const&) + aod::JetTracks const&, + aod::JetMcCollisions const&) { bool fillHistograms = false; bool isWeighted = true; @@ -884,7 +879,7 @@ struct JetSpectraCharged { if (!applyCollisionCuts(collision, fillHistograms, isWeighted, eventWeight)) { return; } - + float pTHat = collision.has_mcCollision() && collision.mcCollision().ptHard() < 999.0f ? collision.mcCollision().ptHard() : 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); float centrality = -1.0; checkCentFT0M ? centrality = collision.centFT0M() : centrality = collision.centFT0C(); @@ -895,7 +890,7 @@ struct JetSpectraCharged { if (!isAcceptedJet(jet)) { continue; } - fillJetAreaSubHistograms(jet, centrality, collision.rho(), eventWeight); + fillJetAreaSubHistograms(jet, centrality, collision.rho(), eventWeight, pTHat); } } PROCESS_SWITCH(JetSpectraCharged, processSpectraAreaSubMCDWeighted, "jet spectra with rho-area subtraction for MCD", false); @@ -1127,7 +1122,7 @@ struct JetSpectraCharged { if (!applyMCCollisionCuts(mccollision, collisions, fillHistograms, isWeighted, eventWeight)) { return; } - + float pTHat = mccollision.ptHard() < 999.0f ? mccollision.ptHard() : 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); for (auto const& jet : jets) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { continue; @@ -1135,14 +1130,13 @@ struct JetSpectraCharged { if (!isAcceptedJet(jet, mcLevelIsParticleLevel)) { continue; } - double pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); int Nmax = 21; for (int N = 1; N < Nmax; N++) { if (jet.pt() < N * 0.25 * pTHat && jet.r() == round(selectedJetsRadius * 100.0f)) { registry.fill(HIST("h2_jet_ptcut_part"), jet.pt(), N * 0.25, eventWeight); } } - fillMCPHistograms(jet, eventWeight); + fillMCPHistograms(jet, eventWeight, pTHat); } } PROCESS_SWITCH(JetSpectraCharged, processSpectraMCPWeighted, "jet spectra for MC particle level weighted", false); @@ -1160,6 +1154,7 @@ struct JetSpectraCharged { if (!applyMCCollisionCuts(mccollision, collisions, fillHistograms, isWeighted, eventWeight)) { return; } + float pTHat = mccollision.ptHard() < 999.0f ? mccollision.ptHard() : 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); registry.fill(HIST("h_mccollisions_rho"), mccollision.rho(), eventWeight); for (auto const& jet : jets) { @@ -1169,7 +1164,7 @@ struct JetSpectraCharged { if (!isAcceptedJet(jet, mcLevelIsParticleLevel)) { continue; } - fillMCPAreaSubHistograms(jet, mccollision.rho(), eventWeight); + fillMCPAreaSubHistograms(jet, mccollision.rho(), eventWeight, pTHat); } } PROCESS_SWITCH(JetSpectraCharged, processSpectraAreaSubMCPWeighted, "jet spectra with area-based subtraction for MC particle level", false); @@ -1238,10 +1233,11 @@ struct JetSpectraCharged { } PROCESS_SWITCH(JetSpectraCharged, processJetsMatched, "matched mcp and mcd jets", false); - void processJetsMatchedWeighted(soa::Filtered::iterator const& collision, + void processJetsMatchedWeighted(soa::Filtered::iterator const& collision, ChargedMCDMatchedJets const& mcdjets, ChargedMCPMatchedJets const&, - aod::JetTracks const&, aod::JetParticles const&) + aod::JetTracks const&, aod::JetParticles const&, + aod::JetMcCollisions const&) { bool fillHistograms = false; bool isWeighted = true; @@ -1249,12 +1245,12 @@ struct JetSpectraCharged { if (!applyCollisionCuts(collision, fillHistograms, isWeighted, eventWeight)) { return; } - + float pTHat = collision.has_mcCollision() && collision.mcCollision().ptHard() < 999.0f ? collision.mcCollision().ptHard() : 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); for (const auto& mcdjet : mcdjets) { if (!isAcceptedJet(mcdjet)) { continue; } - fillMatchedHistograms(mcdjet, eventWeight); + fillMatchedHistograms(mcdjet, eventWeight, pTHat); } } PROCESS_SWITCH(JetSpectraCharged, processJetsMatchedWeighted, "matched mcp and mcd jets with weighted events", false); @@ -1292,6 +1288,7 @@ struct JetSpectraCharged { if (!applyCollisionCuts(collision, fillHistograms, isWeighted, eventWeight)) { return; } + float pTHat = collision.has_mcCollision() && collision.mcCollision().ptHard() < 999.0f ? collision.mcCollision().ptHard() : 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); double mcrho = collision.has_mcCollision() ? collision.mcCollision_as().rho() : -1; @@ -1299,7 +1296,7 @@ struct JetSpectraCharged { if (!isAcceptedJet(mcdjet)) { continue; } - fillGeoMatchedAreaSubHistograms(mcdjet, collision.rho(), mcrho, eventWeight); + fillGeoMatchedAreaSubHistograms(mcdjet, collision.rho(), mcrho, eventWeight, pTHat); } } PROCESS_SWITCH(JetSpectraCharged, processJetsMatchedAreaSubWeighted, "matched mcp and mcd jets after area-based pt subtraction with weighted events", false); diff --git a/PWGJE/Tasks/trackEfficiency.cxx b/PWGJE/Tasks/trackEfficiency.cxx index 9b908a8c951..d6886619555 100644 --- a/PWGJE/Tasks/trackEfficiency.cxx +++ b/PWGJE/Tasks/trackEfficiency.cxx @@ -52,6 +52,7 @@ struct TrackEfficiency { Configurable eventSelections{"eventSelections", "sel8", "choose event selection"}; Configurable trackSelections{"trackSelections", "globalTracks", "set track selections; other option: uniformTracks"}; Configurable skipMBGapEvents{"skipMBGapEvents", false, "flag to choose to reject min. bias gap events"}; + Configurable applyRCTSelections{"applyRCTSelections", true, "decide to apply RCT selections"}; // Tracking efficiency process function configurables: Configurable checkPrimaryPart{"checkPrimaryPart", true, "0: doesn't check mcparticle.isPhysicalPrimary() - 1: checks particle.isPhysicalPrimary()"}; @@ -85,7 +86,6 @@ struct TrackEfficiency { Configurable pTHatExponent{"pTHatExponent", 4.0, "exponent of the event weight for the calculation of pTHat"}; Configurable pTHatMaxFractionMCD{"pTHatMaxFractionMCD", 999.0, "maximum fraction of hard scattering for reconstructed track acceptance in MC"}; - Configurable getPtHatFromHepMCXSection{"getPtHatFromHepMCXSection", true, "test configurable, configurable should be removed once well tested"}; Configurable useTrueTrackWeight{"useTrueTrackWeight", true, "test configurable, should be set to 1 then config removed once well tested"}; // systematics variation - Run 2 guidelines: https://twiki.cern.ch/twiki/bin/view/ALICE/AliDPGtoolsTrackSystematicUncertainty @@ -398,8 +398,7 @@ struct TrackEfficiency { Filter particleCuts = (aod::jmcparticle::pt >= trackQAPtMin && aod::jmcparticle::pt < trackQAPtMax && aod::jmcparticle::eta > trackQAEtaMin && aod::jmcparticle::eta < trackQAEtaMax); Filter eventCuts = (nabs(aod::jcollision::posZ) < vertexZCut); - void processEFficiencyPurity(soa::Join::iterator const& mcCollision, - soa::Join const&, + void processEFficiencyPurity(aod::JetMcCollisions::iterator const& mcCollision, soa::SmallGroups const& collisions, // smallgroups gives only the collisions associated to the current mccollision, thanks to the mccollisionlabel pre-integrated in jetcollisionsmcd soa::Join const& jetTracks, soa::Join const&, @@ -432,7 +431,7 @@ struct TrackEfficiency { bool centralityCheck = false; bool occupancyCheck = false; if (acceptSplitCollisions == SplitOkCheckFirstAssocCollOnly || acceptSplitCollisions == NonSplitOnly) { // check only that the first reconstructed collision passes the check (for the NonSplitOnly case, there's only one associated collision) - if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents)) { // Skipping MC events that have their first associated collision not reconstructed + if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { // Skipping MC events that have their first associated collision not reconstructed hasSel8Coll = true; } if (!checkOccupancy || ((trackOccupancyInTimeRangeMin < collisions.begin().trackOccupancyInTimeRange()) && (collisions.begin().trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMax))) { // check occupancy only in GP Pb-Pb MC @@ -444,7 +443,7 @@ struct TrackEfficiency { } } else if (acceptSplitCollisions == SplitOkCheckAnyAssocColl) { // check that at least one of the reconstructed collisions passes the checks for (auto const& collision : collisions) { - if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split + if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split hasSel8Coll = true; } if (!checkOccupancy || ((trackOccupancyInTimeRangeMin < collision.trackOccupancyInTimeRange()) && (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMax))) { // check occupancy only in GP Pb-Pb MC @@ -470,7 +469,7 @@ struct TrackEfficiency { } registry.fill(HIST("hMcCollCutsCounts"), 5.5); // at least one of the reconstructed collisions associated with this mcCollision is selected with regard to centrality - float pTHat = getPtHatFromHepMCXSection ? mcCollision.mcCollision_as>().ptHard() : 10. / (std::pow(mcCollision.weight(), 1.0 / pTHatExponent)); + float pTHat = mcCollision.ptHard() < 999.0f ? mcCollision.ptHard() : 10. / (std::pow(mcCollision.weight(), 1.0 / pTHatExponent)); if (pTHat < ptHatMin || pTHat > ptHatMax) { // only allows mcCollisions with weight in between min and max return; } @@ -516,7 +515,7 @@ struct TrackEfficiency { return; } - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents) || !(std::abs(collision.posZ()) < vertexZCut)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections) || !(std::abs(collision.posZ()) < vertexZCut)) { continue; } @@ -586,8 +585,7 @@ struct TrackEfficiency { } PROCESS_SWITCH(TrackEfficiency, processEFficiencyPurity, "Histograms for efficiency and purity quantities", true); - void processEFficiencyPurityWeighted(soa::Join::iterator const& mcCollision, - soa::Join const&, + void processEFficiencyPurityWeighted(aod::JetMcCollisions::iterator const& mcCollision, soa::SmallGroups const& collisions, // smallgroups gives only the collisions associated to the current mccollision, thanks to the mccollisionlabel pre-integrated in jetcollisionsmcd soa::Join const& jetTracks, soa::Join const&, @@ -619,7 +617,7 @@ struct TrackEfficiency { bool hasSel8Coll = false; bool centralityCheck = false; if (acceptSplitCollisions == SplitOkCheckFirstAssocCollOnly || acceptSplitCollisions == NonSplitOnly) { // check only that the first reconstructed collision passes the check (for the NonSplitOnly case, there's only one associated collision) - if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents)) { // Skipping MC events that have their first associated collision not reconstructed + if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { // Skipping MC events that have their first associated collision not reconstructed hasSel8Coll = true; } centrality = checkCentFT0M ? collisions.begin().centFT0M() : collisions.begin().centFT0C(); @@ -628,7 +626,7 @@ struct TrackEfficiency { } } else if (acceptSplitCollisions == SplitOkCheckAnyAssocColl) { // check that at least one of the reconstructed collisions passes the checks for (auto const& collision : collisions) { - if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split + if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split hasSel8Coll = true; } centrality = checkCentFT0M ? collision.centFT0M() : collision.centFT0C(); @@ -691,7 +689,7 @@ struct TrackEfficiency { return; } - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents) || !(std::abs(collision.posZ()) < vertexZCut)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections) || !(std::abs(collision.posZ()) < vertexZCut)) { continue; } @@ -718,7 +716,7 @@ struct TrackEfficiency { registry.fill(HIST("hTrackCutsCounts"), 3.5, mcCollision.weight()); auto mcParticle = track.mcParticle_as(); - auto trueTrackMcCollision = mcParticle.mcCollision_as>(); + auto trueTrackMcCollision = mcParticle.mcCollision_as(); float trueTrackCollEventWeight = useTrueTrackWeight ? trueTrackMcCollision.weight() : mcCollEventWeight; auto jMcParticleFromTrack = track.mcParticle_as(); @@ -774,7 +772,7 @@ struct TrackEfficiency { soa::Filtered> const& jetTracks, soa::Join const&) { - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { return; } float centrality = checkCentFT0M ? collision.centFT0M() : collision.centFT0C(); @@ -790,15 +788,14 @@ struct TrackEfficiency { PROCESS_SWITCH(TrackEfficiency, processTracksFromData, "QA for charged tracks in data", false); void processTracksFromMc(soa::Filtered>::iterator const& collision, - soa::Join const&, - soa::Join const&, + aod::JetMcCollisions const&, soa::Filtered> const& jetTracks, soa::Join const&) { if (!collision.has_mcCollision()) { // the collision is fake and has no associated mc coll; skip as .mccollision() cannot be called return; } - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { return; } float centrality = checkCentFT0M ? collision.centFT0M() : collision.centFT0C(); @@ -809,7 +806,7 @@ struct TrackEfficiency { return; } - float pTHat = getPtHatFromHepMCXSection ? collision.mcCollision_as>().mcCollision_as>().ptHard() : 10. / (std::pow(collision.mcCollision().weight(), 1.0 / pTHatExponent)); + float pTHat = collision.mcCollision().ptHard() < 999.0f ? collision.mcCollision().ptHard() : 10. / (std::pow(collision.mcCollision().weight(), 1.0 / pTHatExponent)); if (pTHat < ptHatMin || pTHat > ptHatMax) { // only allows mcCollisions with weight in between min and max return; } @@ -819,16 +816,15 @@ struct TrackEfficiency { PROCESS_SWITCH(TrackEfficiency, processTracksFromMc, "QA for charged tracks in MC without weights", false); void processTracksFromMcWeighted(soa::Filtered>::iterator const& collision, - soa::Join const&, - soa::Join const&, + aod::JetMcCollisions const&, soa::Filtered> const& jetTracks, soa::Join const&) { if (!collision.has_mcCollision()) { // the collision is fake and has no associated mc coll; skip as .mccollision() cannot be called return; } - float eventWeight = collision.mcCollision_as>().weight(); - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { + float eventWeight = collision.mcCollision().weight(); + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { return; } float centrality = checkCentFT0M ? collision.centFT0M() : collision.centFT0C(); @@ -839,7 +835,7 @@ struct TrackEfficiency { return; } - float pTHat = getPtHatFromHepMCXSection ? collision.mcCollision_as>().mcCollision_as>().ptHard() : 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); + float pTHat = collision.mcCollision().ptHard() < 999.0f ? collision.mcCollision().ptHard() : 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); if (pTHat < ptHatMin || pTHat > ptHatMax) { // only allows mcCollisions with weight in between min and max return; } @@ -848,8 +844,7 @@ struct TrackEfficiency { } PROCESS_SWITCH(TrackEfficiency, processTracksFromMcWeighted, "QA for charged tracks in weighted MC", false); - void processParticles(soa::Join::iterator const& mcCollision, - soa::Join const&, + void processParticles(aod::JetMcCollisions::iterator const& mcCollision, soa::SmallGroups const& collisions, soa::Filtered const& mcparticles, soa::Filtered const& tracks) @@ -865,7 +860,7 @@ struct TrackEfficiency { return; } - float pTHat = getPtHatFromHepMCXSection ? mcCollision.mcCollision_as>().ptHard() : 10. / (std::pow(mcCollision.weight(), 1.0 / pTHatExponent)); + float pTHat = mcCollision.ptHard() < 999.0f ? mcCollision.ptHard() : 10. / (std::pow(mcCollision.weight(), 1.0 / pTHatExponent)); if (pTHat < ptHatMin || pTHat > ptHatMax) { // only allows mcCollisions with weight in between min and max return; } @@ -874,7 +869,7 @@ struct TrackEfficiency { bool hasSel8Coll = false; bool centralityCheck = false; if (acceptSplitCollisions == SplitOkCheckFirstAssocCollOnly || acceptSplitCollisions == NonSplitOnly) { // check only that the first reconstructed collision passes the check (for the NonSplitOnly case, there's only one associated collision) - if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents)) { // Skipping MC events that have their first associated collision not reconstructed + if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { // Skipping MC events that have their first associated collision not reconstructed hasSel8Coll = true; } centrality = checkCentFT0M ? collisions.begin().centFT0M() : collisions.begin().centFT0C(); @@ -883,7 +878,7 @@ struct TrackEfficiency { } } else if (acceptSplitCollisions == SplitOkCheckAnyAssocColl) { // check that at least one of the reconstructed collisions passes the checks for (auto const& collision : collisions) { - if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split + if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split hasSel8Coll = true; } centrality = checkCentFT0M ? collision.centFT0M() : collision.centFT0C(); @@ -907,8 +902,7 @@ struct TrackEfficiency { } PROCESS_SWITCH(TrackEfficiency, processParticles, "QA for charged particles", false); - void processParticlesWeighted(soa::Join::iterator const& mcCollision, - soa::Join const&, + void processParticlesWeighted(aod::JetMcCollisions::iterator const& mcCollision, soa::SmallGroups const& collisions, soa::Filtered const& mcparticles, soa::Filtered const& tracks) @@ -929,7 +923,7 @@ struct TrackEfficiency { return; } - float pTHat = getPtHatFromHepMCXSection ? mcCollision.mcCollision_as>().ptHard() : 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); + float pTHat = mcCollision.ptHard() < 999.0f ? mcCollision.ptHard() : 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); if (pTHat < ptHatMin || pTHat > ptHatMax) { // only allows mcCollisions with weight in between min and max return; } @@ -938,7 +932,7 @@ struct TrackEfficiency { bool hasSel8Coll = false; bool centralityCheck = false; if (acceptSplitCollisions == SplitOkCheckFirstAssocCollOnly || acceptSplitCollisions == NonSplitOnly) { // check only that the first reconstructed collision passes the check (for the NonSplitOnly case, there's only one associated collision) - if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents)) { // Skipping MC events that have their first associated collision not reconstructed + if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { // Skipping MC events that have their first associated collision not reconstructed hasSel8Coll = true; } centrality = checkCentFT0M ? collisions.begin().centFT0M() : collisions.begin().centFT0C(); @@ -947,7 +941,7 @@ struct TrackEfficiency { } } else if (acceptSplitCollisions == SplitOkCheckAnyAssocColl) { // check that at least one of the reconstructed collisions passes the checks for (auto const& collision : collisions) { - if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split + if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split hasSel8Coll = true; } centrality = checkCentFT0M ? collision.centFT0M() : collision.centFT0C(); @@ -978,7 +972,7 @@ struct TrackEfficiency { registry.fill(HIST("h_collisions"), 0.5); registry.fill(HIST("h2_centrality_collisions"), centrality, 0.5); - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { return; } registry.fill(HIST("h_collisions"), 1.5); @@ -997,8 +991,7 @@ struct TrackEfficiency { PROCESS_SWITCH(TrackEfficiency, processCollisionsFromData, "QA for reconstructed collisions in data", false); void processCollisionsFromMc(soa::Filtered>::iterator const& collision, - soa::Join const&, - soa::Join const&) + aod::JetMcCollisions const&) { float centrality = checkCentFT0M ? collision.centFT0M() : collision.centFT0C(); @@ -1008,7 +1001,7 @@ struct TrackEfficiency { } registry.fill(HIST("h_collisions"), 0.5); registry.fill(HIST("h2_centrality_collisions"), centrality, 0.5); - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { return; } registry.fill(HIST("h_collisions"), 1.5); @@ -1024,7 +1017,7 @@ struct TrackEfficiency { registry.fill(HIST("h_collisions"), 3.5); registry.fill(HIST("h2_centrality_collisions"), centrality, 3.5); - float pTHat = getPtHatFromHepMCXSection ? collision.mcCollision_as>().mcCollision_as>().ptHard() : 10. / (std::pow(collision.mcCollision().weight(), 1.0 / pTHatExponent)); + float pTHat = collision.mcCollision().ptHard() < 999.0f ? collision.mcCollision().ptHard() : 10. / (std::pow(collision.mcCollision().weight(), 1.0 / pTHatExponent)); if (pTHat < ptHatMin || pTHat > ptHatMax) { // only allows mcCollisions with weight in between min and max return; } @@ -1034,8 +1027,7 @@ struct TrackEfficiency { PROCESS_SWITCH(TrackEfficiency, processCollisionsFromMc, "QA for reconstructed collisions in MC without weights", false); void processCollisionsFromMcWeighted(soa::Filtered>::iterator const& collision, - soa::Join const&, - soa::Join const&) + aod::JetMcCollisions const&) { float centrality = checkCentFT0M ? collision.centFT0M() : collision.centFT0C(); @@ -1043,10 +1035,10 @@ struct TrackEfficiency { registry.fill(HIST("h_fakecollisions"), 0.5); return; } - float eventWeight = collision.mcCollision_as>().weight(); + float eventWeight = collision.mcCollision().weight(); registry.fill(HIST("h_collisions"), 0.5); registry.fill(HIST("h_collisions_weighted"), 0.5, eventWeight); - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { return; } registry.fill(HIST("h_collisions"), 1.5); @@ -1062,7 +1054,7 @@ struct TrackEfficiency { registry.fill(HIST("h_collisions"), 3.5); registry.fill(HIST("h_collisions_weighted"), 3.5, eventWeight); - float pTHat = getPtHatFromHepMCXSection ? collision.mcCollision_as>().mcCollision_as>().ptHard() : 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); + float pTHat = collision.mcCollision().ptHard() < 999.0f ? collision.mcCollision().ptHard() : 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); if (pTHat < ptHatMin || pTHat > ptHatMax) { // only allows mcCollisions with weight in between min and max return; } @@ -1071,22 +1063,21 @@ struct TrackEfficiency { } PROCESS_SWITCH(TrackEfficiency, processCollisionsFromMcWeighted, "QA for reconstructed collisions in weighted MC", false); - void processMcCollisions(soa::Join::iterator const& mcCollision, - soa::Join const&, + void processMcCollisions(aod::JetMcCollisions::iterator const& mcCollision, soa::SmallGroups const& collisions) { // float centrality = checkCentFT0M ? mcCollision.centFT0M() : mcCollision.centFT0C(); mcCollision.centFT0C() isn't filled at the moment; can be added back when it is float eventWeight = mcCollision.weight(); - float pTHat = getPtHatFromHepMCXSection ? mcCollision.mcCollision_as>().ptHard() : 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); - registry.fill(HIST("h2_mccollision_pthardfromweight_pthardfromhepmcxsection"), 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)), mcCollision.mcCollision_as>().ptHard()); + float pTHat = mcCollision.ptHard() < 999.0f ? mcCollision.ptHard() : 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); + registry.fill(HIST("h2_mccollision_pthardfromweight_pthardfromhepmcxsection"), 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)), mcCollision.ptHard()); float centrality = -1; bool hasSel8Coll = false; bool centralityCheck = false; if (collisions.size() > 1) { // remove and move the if block below under if (collisions.size() < 1) { when mccoll.centFt0C has been fixed if (acceptSplitCollisions == SplitOkCheckFirstAssocCollOnly || acceptSplitCollisions == NonSplitOnly) { // check only that the first reconstructed collision passes the check (for the NonSplitOnly case, there's only one associated collision) - if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents)) { // Skipping MC events that have their first associated collision not reconstructed + if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { // Skipping MC events that have their first associated collision not reconstructed hasSel8Coll = true; } centrality = checkCentFT0M ? collisions.begin().centFT0M() : collisions.begin().centFT0C(); @@ -1095,7 +1086,7 @@ struct TrackEfficiency { } } else if (acceptSplitCollisions == SplitOkCheckAnyAssocColl) { // check that at least one of the reconstructed collisions passes the checks for (auto const& collision : collisions) { - if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split + if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split hasSel8Coll = true; } centrality = checkCentFT0M ? collision.centFT0M() : collision.centFT0C(); @@ -1140,8 +1131,7 @@ struct TrackEfficiency { } PROCESS_SWITCH(TrackEfficiency, processMcCollisions, "QA for McCollisions in MC without weights", false); - void processMcCollisionsWeighted(soa::Join::iterator const& mcCollision, - soa::Join const&, + void processMcCollisionsWeighted(aod::JetMcCollisions::iterator const& mcCollision, soa::SmallGroups const& collisions) { if (skipMBGapEvents && mcCollision.getSubGeneratorId() == jetderiveddatautilities::JCollisionSubGeneratorId::mbGap) { @@ -1151,16 +1141,16 @@ struct TrackEfficiency { // float centrality = checkCentFT0M ? mcCollision.centFT0M() : mcCollision.centFT0C(); mcCollision.centFT0C() isn't filled at the moment; can be added back when it is float eventWeight = mcCollision.weight(); - float pTHat = getPtHatFromHepMCXSection ? mcCollision.mcCollision_as>().ptHard() : 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); - registry.fill(HIST("h2_mccollision_pthardfromweight_pthardfromhepmcxsection"), 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)), mcCollision.mcCollision_as>().ptHard()); - registry.fill(HIST("h2_mccollision_pthardfromweight_pthardfromhepmcxsection_weighted"), 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)), mcCollision.mcCollision_as>().ptHard(), eventWeight); + float pTHat = mcCollision.ptHard() < 999.0f ? mcCollision.ptHard() : 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); + registry.fill(HIST("h2_mccollision_pthardfromweight_pthardfromhepmcxsection"), 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)), mcCollision.ptHard()); + registry.fill(HIST("h2_mccollision_pthardfromweight_pthardfromhepmcxsection_weighted"), 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)), mcCollision.ptHard(), eventWeight); float centrality = -1; bool hasSel8Coll = false; bool centralityCheck = false; if (collisions.size() > 1) { // remove and move the if block below under if (collisions.size() < 1) { when mccoll.centFt0C has been fixed if (acceptSplitCollisions == SplitOkCheckFirstAssocCollOnly || acceptSplitCollisions == NonSplitOnly) { // check only that the first reconstructed collision passes the check (for the NonSplitOnly case, there's only one associated collision) - if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents)) { // Skipping MC events that have their first associated collision not reconstructed + if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { // Skipping MC events that have their first associated collision not reconstructed hasSel8Coll = true; } centrality = checkCentFT0M ? collisions.begin().centFT0M() : collisions.begin().centFT0C(); @@ -1169,7 +1159,7 @@ struct TrackEfficiency { } } else if (acceptSplitCollisions == SplitOkCheckAnyAssocColl) { // check that at least one of the reconstructed collisions passes the checks for (auto const& collision : collisions) { - if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split + if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split hasSel8Coll = true; } centrality = checkCentFT0M ? collision.centFT0M() : collision.centFT0C(); @@ -1221,7 +1211,7 @@ struct TrackEfficiency { void processTrackSelectionHistograms(soa::Filtered::iterator const& collision, soa::Join const& jetTracks, soa::Join const&) { - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { return; } float centrality = checkCentFT0M ? collision.centFT0M() : collision.centFT0C(); @@ -1275,7 +1265,7 @@ struct TrackEfficiency { registry.fill(HIST("h2_occupancy_ntracksall_presel"), occupancy, nTracksAll); registry.fill(HIST("h2_occupancy_ntrackssel_presel"), occupancy, nTracksAllAcceptanceAndSelected); registry.fill(HIST("h2_occupancy_ntracksselptetacuts_presel"), occupancy, nTracksInAcceptanceAndSelected); - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { return; } registry.fill(HIST("h2_occupancy_ntracksall_postsel"), occupancy, nTracksAll); From 6aebf51a14788c439fc5662548cca6dd9d1edccb Mon Sep 17 00:00:00 2001 From: EmilGorm <50658075+EmilGorm@users.noreply.github.com> Date: Wed, 11 Mar 2026 00:02:02 +0100 Subject: [PATCH 246/347] [PWGCF] additional track QA (#15340) --- .../Tasks/flowGenericFramework.cxx | 172 +++++++++++------- 1 file changed, 111 insertions(+), 61 deletions(-) diff --git a/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx b/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx index cf7d2168c53..44e1669f2cb 100644 --- a/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx +++ b/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx @@ -100,18 +100,21 @@ struct FlowGenericFramework { O2_DEFINE_CONFIGURABLE(cfgUseGapMethod, bool, false, "Use gap method in vn-pt calculations") O2_DEFINE_CONFIGURABLE(cfgEfficiency, std::string, "", "CCDB path to efficiency object") O2_DEFINE_CONFIGURABLE(cfgAcceptance, std::string, "", "CCDB path to acceptance object") - O2_DEFINE_CONFIGURABLE(cfgDCAxyNSigma, float, 7, "Cut on number of sigma deviations from expected DCA in the transverse direction"); - O2_DEFINE_CONFIGURABLE(cfgDCAz, float, 2, "Cut on DCA in the longitudinal direction (cm)"); - O2_DEFINE_CONFIGURABLE(cfgNTPCCls, float, 70, "Cut on number of TPC clusters found"); - O2_DEFINE_CONFIGURABLE(cfgNTPCXrows, float, 70, "Cut on number of TPC crossed rows"); - O2_DEFINE_CONFIGURABLE(cfgMinNITSCls, float, 5, "Cut on minimum number of ITS clusters found"); - O2_DEFINE_CONFIGURABLE(cfgChi2PrITSCls, float, 36, "Cut on chi^2 per ITS clusters found"); - O2_DEFINE_CONFIGURABLE(cfgChi2PrTPCCls, float, 2.5, "Cut on chi^2 per TPC clusters found"); O2_DEFINE_CONFIGURABLE(cfgPtmin, float, 0.2, "minimum pt (GeV/c)"); O2_DEFINE_CONFIGURABLE(cfgPtmax, float, 10, "maximum pt (GeV/c)"); O2_DEFINE_CONFIGURABLE(cfgEta, float, 0.8, "eta cut"); O2_DEFINE_CONFIGURABLE(cfgEtaPtPt, float, 0.4, "eta cut for pt-pt correlations"); O2_DEFINE_CONFIGURABLE(cfgVtxZ, float, 10, "vertex cut (cm)"); + struct : ConfigurableGroup { + O2_DEFINE_CONFIGURABLE(cfgDCAxyNSigma, float, 7, "Cut on number of sigma deviations from expected DCA in the transverse direction"); + O2_DEFINE_CONFIGURABLE(cfgDCAz, float, 2, "Cut on DCA in the longitudinal direction (cm)"); + O2_DEFINE_CONFIGURABLE(cfgNTPCCls, float, 70, "Cut on number of TPC clusters found"); + O2_DEFINE_CONFIGURABLE(cfgNTPCXrows, float, 70, "Cut on number of TPC crossed rows"); + O2_DEFINE_CONFIGURABLE(cfgMinNITSCls, float, 5, "Cut on minimum number of ITS clusters found"); + O2_DEFINE_CONFIGURABLE(cfgChi2PrITSCls, float, 36, "Cut on chi^2 per ITS clusters found"); + O2_DEFINE_CONFIGURABLE(cfgChi2PrTPCCls, float, 2.5, "Cut on chi^2 per TPC clusters found"); + O2_DEFINE_CONFIGURABLE(cfgTPCSectorCut, bool, false, "Cut on pt-phi distribution"); + } cfgTrackCuts; struct : ConfigurableGroup { O2_DEFINE_CONFIGURABLE(cfgNoSameBunchPileupCut, bool, true, "kNoSameBunchPileupCut"); O2_DEFINE_CONFIGURABLE(cfgIsGoodZvtxFT0vsPV, bool, true, "kIsGoodZvtxFT0vsPV"); @@ -189,6 +192,7 @@ struct FlowGenericFramework { hNUApi, hNUAka, hNUApr, + hPtPhiMult, kCount_TH3Names }; enum CentEstimators { @@ -275,6 +279,10 @@ struct FlowGenericFramework { TF1* fMultGlobalT0ACutLow = nullptr; TF1* fMultGlobalT0ACutHigh = nullptr; + // Track selection - pt-phi cuts + TF1* fPhiCutLow; + TF1* fPhiCutHigh; + void init(InitContext const&) { LOGF(info, "flowGenericFramework::init()"); @@ -313,6 +321,7 @@ struct FlowGenericFramework { o2::analysis::gfw::multGlobalT0ACutPars = cfgGlobalAsideCorrCuts.cfgMultGlobalT0ACutPars; AxisSpec phiAxis = {o2::analysis::gfw::phibins, o2::analysis::gfw::philow, o2::analysis::gfw::phiup, "#phi"}; + AxisSpec phiModAxis = {100, 0, constants::math::PI / 9, "fmod(#varphi,#pi/9)"}; AxisSpec etaAxis = {o2::analysis::gfw::etabins, -cfgEta, cfgEta, "#eta"}; AxisSpec vtxAxis = {o2::analysis::gfw::vtxZbins, -cfgVtxZ, cfgVtxZ, "Vtx_{z} (cm)"}; AxisSpec ptAxis = {o2::analysis::gfw::ptbinning, "#it{p}_{T} GeV/#it{c}"}; @@ -329,6 +338,7 @@ struct FlowGenericFramework { AxisSpec t0aAxis = {300, 0, 30000, "N_{ch} (T0A)"}; AxisSpec v0aAxis = {800, 0, 80000, "N_{ch} (V0A)"}; AxisSpec multpvAxis = {600, 0, 600, "N_{ch} (PV)"}; + AxisSpec occAxis = {600, 0, 3000, "occupancy"}; AxisSpec multAxis = (doprocessOnTheFly && !cfgUseNch) ? bAxis : (cfgUseNch) ? nchAxis : centAxis; AxisSpec dcaZAXis = {200, -2, 2, "DCA_{z} (cm)"}; @@ -353,6 +363,7 @@ struct FlowGenericFramework { if (doprocessMCReco || doprocessData || doprocessRun2) { registry.add("trackQA/before/phi_eta_vtxZ", "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); registry.add("trackQA/before/pt_dcaXY_dcaZ", "", {HistType::kTH3D, {ptAxis, dcaXYAXis, dcaZAXis}}); + registry.add("trackQA/before/pt_phi", "", {HistType::kTH2D, {ptAxis, phiModAxis}}); registry.add("trackQA/before/chi2prTPCcls", "#chi^{2}/cluster for the TPC track segment", {HistType::kTH1D, {{100, 0., 5.}}}); registry.add("trackQA/before/chi2prITScls", "#chi^{2}/cluster for the ITS track", {HistType::kTH1D, {{100, 0., 50.}}}); registry.add("trackQA/before/nTPCClusters", "Number of found TPC clusters", {HistType::kTH1D, {{100, 40, 180}}}); @@ -363,15 +374,16 @@ struct FlowGenericFramework { registry.add("trackQA/after/pt_ref", "", {HistType::kTH1D, {{100, o2::analysis::gfw::ptreflow, o2::analysis::gfw::ptrefup}}}); registry.add("trackQA/after/pt_poi", "", {HistType::kTH1D, {{100, o2::analysis::gfw::ptpoilow, o2::analysis::gfw::ptpoiup}}}); - registry.add("eventQA/before/centrality", "", {HistType::kTH1D, {centAxis}}); - registry.add("eventQA/before/multiplicity", "", {HistType::kTH1D, {nchAxis}}); - registry.add("eventQA/before/globalTracks_centT0C", "", {HistType::kTH2D, {centAxis, nchAxis}}); - registry.add("eventQA/before/PVTracks_centT0C", "", {HistType::kTH2D, {centAxis, multpvAxis}}); - registry.add("eventQA/before/globalTracks_PVTracks", "", {HistType::kTH2D, {multpvAxis, nchAxis}}); - registry.add("eventQA/before/globalTracks_multT0A", "", {HistType::kTH2D, {t0aAxis, nchAxis}}); - registry.add("eventQA/before/globalTracks_multV0A", "", {HistType::kTH2D, {t0aAxis, nchAxis}}); - registry.add("eventQA/before/multV0A_multT0A", "", {HistType::kTH2D, {t0aAxis, t0aAxis}}); - registry.add("eventQA/before/multT0C_centT0C", "", {HistType::kTH2D, {centAxis, t0cAxis}}); + registry.add("eventQA/before/centrality", "; centrality (%); Counts", {HistType::kTH1D, {centAxis}}); + registry.add("eventQA/before/multiplicity", "; N_{ch}; Counts", {HistType::kTH1D, {nchAxis}}); + registry.add("eventQA/before/globalTracks_centT0C", "; FT0C centrality (%); N_{global}", {HistType::kTH2D, {centAxis, nchAxis}}); + registry.add("eventQA/before/PVTracks_centT0C", "; FT0C centrality (%); N_{PV}", {HistType::kTH2D, {centAxis, multpvAxis}}); + registry.add("eventQA/before/globalTracks_PVTracks", "; N_{PV}; N_{global}", {HistType::kTH2D, {multpvAxis, nchAxis}}); + registry.add("eventQA/before/globalTracks_multT0A", "; multT0A; N_{global}", {HistType::kTH2D, {t0aAxis, nchAxis}}); + registry.add("eventQA/before/globalTracks_multV0A", "; multV0A; N_{global}", {HistType::kTH2D, {t0aAxis, nchAxis}}); + registry.add("eventQA/before/multV0A_multT0A", "; multV0A; multT0A", {HistType::kTH2D, {t0aAxis, t0aAxis}}); + registry.add("eventQA/before/multT0C_centT0C", "; multT0C; FT0C centrality (%)", {HistType::kTH2D, {centAxis, t0cAxis}}); + registry.add("eventQA/before/occ_mult_cent", "; occupancy; N_{ch}; centrality (%)", {HistType::kTH3D, {occAxis, nchAxis, centAxis}}); registry.addClone("eventQA/before/", "eventQA/after/"); registry.add("eventQA/eventSel", "Number of Events;; Counts", {HistType::kTH1D, {{11, 0, 11}}}); registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(1, "Filtered event"); @@ -482,6 +494,10 @@ struct FlowGenericFramework { LOGF(info, "fMultGlobalT0ACutHigh par %d = %g", i, fMultGlobalT0ACutHigh->GetParameter(i)); } + if (cfgTrackCuts.cfgTPCSectorCut) { + fPhiCutLow = new TF1("fPhiCutLow", "0.06/x+pi/18.0-0.06", 0, 100); + fPhiCutHigh = new TF1("fPhiCutHigh", "0.1/x+pi/18.0+0.06", 0, 100); + } // Density dependent corrections if (cfgUseDensityDependentCorrection) { std::vector pTEffBins = {0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.4, 1.8, 2.2, 2.6, 3.0}; @@ -591,31 +607,31 @@ struct FlowGenericFramework { return 1. / eff; } - /* template - int getNsigmaPID(TTrack track) - { - // Computing Nsigma arrays for pion, kaon, and protons - std::array nSigmaTPC = {track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr()}; - std::array nSigmaCombined = {std::hypot(track.tpcNSigmaPi(), track.tofNSigmaPi()), std::hypot(track.tpcNSigmaKa(), track.tofNSigmaKa()), std::hypot(track.tpcNSigmaPr(), track.tofNSigmaPr())}; - int pid = -1; - float nsigma = 3.0; - - // Choose which nSigma to use - std::array nSigmaToUse = (track.pt() > cfgTofPtCut && track.hasTOF()) ? nSigmaCombined : nSigmaTPC; - if (track.pt() >= cfgTofPtCut && !track.hasTOF()) - return -1; - - // Select particle with the lowest nsigma - const int nspecies = 3; - for (int i = 0; i < nspecies; ++i) { - if (std::abs(nSigmaToUse[i]) < nsigma) { - pid = i; - nsigma = std::abs(nSigmaToUse[i]); - } + template + int getNsigmaPID(TTrack track) + { + // Computing Nsigma arrays for pion, kaon, and protons + std::array nSigmaTPC = {track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr()}; + std::array nSigmaCombined = {std::hypot(track.tpcNSigmaPi(), track.tofNSigmaPi()), std::hypot(track.tpcNSigmaKa(), track.tofNSigmaKa()), std::hypot(track.tpcNSigmaPr(), track.tofNSigmaPr())}; + int pid = -1; + float nsigma = 3.0; + + // Choose which nSigma to use + std::array nSigmaToUse = (track.pt() > cfgTofPtCut && track.hasTOF()) ? nSigmaCombined : nSigmaTPC; + if (track.pt() >= cfgTofPtCut && !track.hasTOF()) + return -1; + + // Select particle with the lowest nsigma + const int nspecies = 3; + for (int i = 0; i < nspecies; ++i) { + if (std::abs(nSigmaToUse[i]) < nsigma) { + pid = i; + nsigma = std::abs(nSigmaToUse[i]); } - return pid + 1; // shift the pid by 1, 1 = pion, 2 = kaon, 3 = proton } - */ + return pid + 1; // shift the pid by 1, 1 = pion, 2 = kaon, 3 = proton + } + template bool eventSelected(TCollision collision, const int& multTrk, const float& centrality, const int& run) { @@ -699,11 +715,29 @@ struct FlowGenericFramework { } template - bool trackSelected(TTrack track) + bool trackSelected(TTrack track, const int& field) { - if (cfgDCAxyNSigma && (std::fabs(track.dcaXY()) > cfgDCAxyNSigma / 7. * (0.0105f + 0.0035f / track.pt()))) + if (cfgTrackCuts.cfgTPCSectorCut) { + double phimodn = track.phi(); + if (field < 0) // for negative polarity field + phimodn = o2::constants::math::TwoPI - phimodn; + if (track.sign() < 0) // for negative charge + phimodn = o2::constants::math::TwoPI - phimodn; + if (phimodn < 0) + LOGF(warning, "phi < 0: %g", phimodn); + + phimodn += o2::constants::math::PI / 18.0; // to center gap in the middle + phimodn = fmod(phimodn, o2::constants::math::PI / 9.0); + if (cfgFillQA) + registry.fill(HIST("trackQA/before/pt_phi"), track.pt(), phimodn); + if (phimodn < fPhiCutHigh->Eval(track.pt()) && phimodn > fPhiCutLow->Eval(track.pt())) + return false; // reject track + if (cfgFillQA) + registry.fill(HIST("trackQA/after/pt_phi"), track.pt(), phimodn); + } + if (cfgTrackCuts.cfgDCAxyNSigma && (std::fabs(track.dcaXY()) > cfgTrackCuts.cfgDCAxyNSigma / 7. * (0.0105f + 0.0035f / track.pt()))) return false; - return ((track.tpcNClsCrossedRows() >= cfgNTPCXrows) && (track.tpcNClsFound() >= cfgNTPCCls) && (track.itsNCls() >= cfgMinNITSCls)); + return ((track.tpcNClsCrossedRows() >= cfgTrackCuts.cfgNTPCXrows) && (track.tpcNClsFound() >= cfgTrackCuts.cfgNTPCCls) && (track.itsNCls() >= cfgTrackCuts.cfgMinNITSCls)); } template @@ -764,10 +798,12 @@ struct FlowGenericFramework { void createRunByRunHistograms(const int& run) { AxisSpec phiAxis = {o2::analysis::gfw::phibins, o2::analysis::gfw::philow, o2::analysis::gfw::phiup, "#phi"}; + AxisSpec phiModAxis = {100, 0, constants::math::PI / 9, "fmod(#varphi,#pi/9)"}; AxisSpec etaAxis = {o2::analysis::gfw::etabins, -cfgEta, cfgEta, "#eta"}; AxisSpec vtxAxis = {o2::analysis::gfw::vtxZbins, -cfgVtxZ, cfgVtxZ, "Vtx_{z} (cm)"}; AxisSpec nchAxis = {o2::analysis::gfw::nchbins, o2::analysis::gfw::nchlow, o2::analysis::gfw::nchup, "N_{ch}"}; AxisSpec centAxis = {o2::analysis::gfw::centbinning, "Centrality (%)"}; + AxisSpec ptAxis = {o2::analysis::gfw::ptbinning, "#it{p}_{T} GeV/#it{c}"}; std::vector> histos(kCount_TH1Names); histos[hPhi] = registry.add(Form("%d/phi", run), "", {HistType::kTH1D, {phiAxis}}); histos[hEta] = registry.add(Form("%d/eta", run), "", {HistType::kTH1D, {etaAxis}}); @@ -797,6 +833,7 @@ struct FlowGenericFramework { } else { histos3d[hNUAref] = registry.add(Form("%d/phi_eta_vtxz_ref", run), "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); } + histos3d[hPtPhiMult] = registry.add(Form("%d/pt_phi_mult", run), "", {HistType::kTH3D, {ptAxis, phiModAxis, (cfgUseNch) ? nchAxis : centAxis}}); th3sList.insert(std::make_pair(run, histos3d)); return; } @@ -846,7 +883,7 @@ struct FlowGenericFramework { } template - void processCollision(TCollision collision, TTracks tracks, const float& centrality, const int& run) + void processCollision(TCollision collision, TTracks tracks, const float& centrality, const int& field, const int& run) { if (tracks.size() < 1) return; @@ -905,7 +942,7 @@ struct FlowGenericFramework { AcceptedTracks acceptedTracks; for (const auto& track : tracks) { - processTrack(track, vtxz, run, densitycorrections, acceptedTracks); + processTrack(track, vtxz, field, run, densitycorrections, acceptedTracks); } registry.fill(HIST("trackQA/after/Nch_corrected"), acceptedTracks.corrected); @@ -937,7 +974,7 @@ struct FlowGenericFramework { }; template - inline void processTrack(TTrack const& track, const float& vtxz, const int& run, DensityCorr densitycorrections, AcceptedTracks& acceptedTracks) + inline void processTrack(TTrack const& track, const float& vtxz, const int& field, const int& run, DensityCorr densitycorrections, AcceptedTracks& acceptedTracks) { if constexpr (framework::has_type_v) { if (track.mcParticleId() < 0 || !(track.has_mcParticle())) @@ -959,7 +996,7 @@ struct FlowGenericFramework { acceptedTracks.corrected += getEfficiency(track); ++acceptedTracks.uncorrected; - if (!trackSelected(track)) + if (!trackSelected(track, field)) return; int pidIndex = 0; @@ -1023,15 +1060,13 @@ struct FlowGenericFramework { acceptedTracks.corrected += getEfficiency(track); ++acceptedTracks.uncorrected; - if (!trackSelected(track)) + if (!trackSelected(track, field)) return; int pidIndex = 0; - if (cfgUsePID) { - // pid_index = getBayesPIDIndex(track); - // pidIndex = getNsigmaPID(track); - pidIndex = 0; - } + if (cfgUsePID) + pidIndex = getNsigmaPID(track); + if (cfgFillWeights) { fillWeights(track, vtxz, pidIndex, run); } else { @@ -1185,10 +1220,10 @@ struct FlowGenericFramework { } o2::framework::expressions::Filter collisionFilter = nabs(aod::collision::posZ) < cfgVtxZ; - o2::framework::expressions::Filter trackFilter = nabs(aod::track::eta) < cfgEta && aod::track::pt > cfgPtmin&& aod::track::pt < cfgPtmax && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)) && (aod::track::itsChi2NCl < cfgChi2PrITSCls) && (aod::track::tpcChi2NCl < cfgChi2PrTPCCls) && nabs(aod::track::dcaZ) < cfgDCAz; + o2::framework::expressions::Filter trackFilter = nabs(aod::track::eta) < cfgEta && aod::track::pt > cfgPtmin&& aod::track::pt < cfgPtmax && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)) && (aod::track::itsChi2NCl < cfgTrackCuts.cfgChi2PrITSCls) && (aod::track::tpcChi2NCl < cfgTrackCuts.cfgChi2PrTPCCls) && nabs(aod::track::dcaZ) < cfgTrackCuts.cfgDCAz; - // using GFWTracks = soa::Filtered>; - using GFWTracks = soa::Filtered>; + using GFWTracks = soa::Filtered>; + // using GFWTracks = soa::Filtered>; void processData(soa::Filtered>::iterator const& collision, aod::BCsWithTimestamps const&, GFWTracks const& tracks) { @@ -1211,23 +1246,30 @@ struct FlowGenericFramework { } if (!cfgFillWeights && !cfgRunByRun) loadCorrections(bc); + registry.fill(HIST("eventQA/eventSel"), 0.5); if (cfgRunByRun) th1sList[run][hEventSel]->Fill(0.5); + if (!collision.sel8()) return; + registry.fill(HIST("eventQA/eventSel"), 1.5); if (cfgRunByRun) th1sList[run][hEventSel]->Fill(1.5); + + float centrality = getCentrality(collision); + if (cfgDoOccupancySel) { int occupancy = collision.trackOccupancyInTimeRange(); + registry.fill(HIST("eventQA/before/occ_mult_cent"), occupancy, tracks.size(), centrality); if (occupancy < 0 || occupancy > cfgOccupancySelection) return; + registry.fill(HIST("eventQA/after/occ_mult_cent"), occupancy, tracks.size(), centrality); } registry.fill(HIST("eventQA/eventSel"), 2.5); if (cfgRunByRun) th1sList[run][hEventSel]->Fill(2.5); - float centrality = getCentrality(collision); if (cfgFillQA) fillEventQA(collision, tracks); registry.fill(HIST("eventQA/before/centrality"), centrality); @@ -1238,7 +1280,11 @@ struct FlowGenericFramework { fillEventQA(collision, tracks); registry.fill(HIST("eventQA/after/centrality"), centrality); registry.fill(HIST("eventQA/after/multiplicity"), tracks.size()); - processCollision(collision, tracks, centrality, run); + + // Get magnetic field polarity + auto field = (cfgMagField == 99999) ? getMagneticField(bc.timestamp()) : cfgMagField; + + processCollision(collision, tracks, centrality, field, run); } PROCESS_SWITCH(FlowGenericFramework, processData, "Process analysis for non-derived data", true); @@ -1263,7 +1309,9 @@ struct FlowGenericFramework { if (!cfgFillWeights) loadCorrections(bc); - processCollision(collision, tracks, centrality, run); + + auto field = (cfgMagField == 99999) ? getMagneticField(bc.timestamp()) : cfgMagField; + processCollision(collision, tracks, centrality, field, run); } PROCESS_SWITCH(FlowGenericFramework, processMCReco, "Process analysis for MC reconstructed events", false); @@ -1277,7 +1325,7 @@ struct FlowGenericFramework { centrality = getCentrality(collision); } int run = 0; - processCollision(mcCollision, particles, centrality, run); + processCollision(mcCollision, particles, centrality, -999, run); } PROCESS_SWITCH(FlowGenericFramework, processMCGen, "Process analysis for MC generated events", false); @@ -1285,7 +1333,7 @@ struct FlowGenericFramework { { int run = 0; registry.fill(HIST("MCGen/impactParameter"), mcCollision.impactParameter(), mcParticles.size()); - processCollision(mcCollision, mcParticles, mcCollision.impactParameter(), run); + processCollision(mcCollision, mcParticles, mcCollision.impactParameter(), -999, run); } PROCESS_SWITCH(FlowGenericFramework, processOnTheFly, "Process analysis for MC on-the-fly generated events", false); @@ -1303,7 +1351,9 @@ struct FlowGenericFramework { const auto centrality = collision.centRun2V0M(); if (!cfgFillWeights) loadCorrections(bc); - processCollision(collision, tracks, centrality, run); + + auto field = (cfgMagField == 99999) ? getMagneticField(bc.timestamp()) : cfgMagField; + processCollision(collision, tracks, centrality, field, run); } PROCESS_SWITCH(FlowGenericFramework, processRun2, "Process analysis for Run 2 converted data", false); }; From 88eade21c02134214d0aa3c703a54b0f6c3b1da9 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Wed, 11 Mar 2026 01:15:32 +0100 Subject: [PATCH 247/347] [PWGEM/Dilepton] update mft ref bit (#15343) Co-authored-by: ALICE Action Bot --- .../TableProducer/skimmerPrimaryMFTTrack.cxx | 16 +++++++++++----- PWGEM/Dilepton/Utils/EMTrackUtilities.h | 18 ++++++++++-------- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/PWGEM/Dilepton/TableProducer/skimmerPrimaryMFTTrack.cxx b/PWGEM/Dilepton/TableProducer/skimmerPrimaryMFTTrack.cxx index 28055a15057..977061cee75 100644 --- a/PWGEM/Dilepton/TableProducer/skimmerPrimaryMFTTrack.cxx +++ b/PWGEM/Dilepton/TableProducer/skimmerPrimaryMFTTrack.cxx @@ -198,13 +198,16 @@ struct skimmerPrimaryMFTTrack { // As minimal cuts, following cuts are applied. The cut values are hardcoded on the purpose for consistent bit operation. // Ncls MFT >= 5 - // chi2/ndf MFT < 5 + // chi2/ndf MFT < 4 // |dcaXY| < 0.06 cm - if (mfttrack.nClusters() < 6 || mfttrack.chi2() / ndf > 5.f || std::fabs(dcaXY) > 0.05) { + if (mfttrack.nClusters() < 5 || mfttrack.chi2() / ndf > 4.f || std::fabs(dcaXY) > 0.06) { return; } + if (mfttrack.nClusters() >= 6) { + trackBit |= static_cast(RefMFTTrackBit::kNclsMFT6); + } if (mfttrack.nClusters() >= 7) { trackBit |= static_cast(RefMFTTrackBit::kNclsMFT7); } @@ -212,13 +215,16 @@ struct skimmerPrimaryMFTTrack { trackBit |= static_cast(RefMFTTrackBit::kNclsMFT8); } - if (mfttrack.chi2() / ndf < 4.f) { - trackBit |= static_cast(RefMFTTrackBit::kChi2MFT4); - } if (mfttrack.chi2() / ndf < 3.f) { trackBit |= static_cast(RefMFTTrackBit::kChi2MFT3); } + if (mfttrack.chi2() / ndf < 2.f) { + trackBit |= static_cast(RefMFTTrackBit::kChi2MFT2); + } + if (std::fabs(dcaXY) < 0.05) { + trackBit |= static_cast(RefMFTTrackBit::kDCAxy005cm); + } if (std::fabs(dcaXY) < 0.04) { trackBit |= static_cast(RefMFTTrackBit::kDCAxy004cm); } diff --git a/PWGEM/Dilepton/Utils/EMTrackUtilities.h b/PWGEM/Dilepton/Utils/EMTrackUtilities.h index 54bc28eb012..88daecccb62 100644 --- a/PWGEM/Dilepton/Utils/EMTrackUtilities.h +++ b/PWGEM/Dilepton/Utils/EMTrackUtilities.h @@ -47,14 +47,16 @@ enum class RefTrackBit : uint16_t { // This is not for leptons, but charged trac }; enum class RefMFTTrackBit : uint16_t { // This is not for leptons, but charged tracks for reference flow. - kNclsMFT7 = 1, // default is 6 - kNclsMFT8 = 2, - kChi2MFT4 = 4, // default is 5 - kChi2MFT3 = 8, - kDCAxy004cm = 16, // default is 0.05 cm - kDCAxy003cm = 32, - kDCAxy002cm = 64, - kDCAxy001cm = 128, + kNclsMFT6 = 1, // default is 5 + kNclsMFT7 = 2, + kNclsMFT8 = 4, + kChi2MFT3 = 8, // default is 4 + kChi2MFT2 = 16, + kDCAxy005cm = 32, // default is 0.06 cm + kDCAxy004cm = 64, + kDCAxy003cm = 128, + kDCAxy002cm = 256, + kDCAxy001cm = 512, }; //_______________________________________________________________________ From af75ce010231586925ad833170dd258a6b1b2f6c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 Mar 2026 12:08:01 +0100 Subject: [PATCH 248/347] [Infrastructure] Bump oxsecurity/megalinter from 9.3.0 to 9.4.0 (#15211) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/mega-linter.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/mega-linter.yml b/.github/workflows/mega-linter.yml index 009c658b22d..531bc39add4 100644 --- a/.github/workflows/mega-linter.yml +++ b/.github/workflows/mega-linter.yml @@ -38,7 +38,7 @@ jobs: id: ml # You can override MegaLinter flavor used to have faster performances # More info at https://megalinter.io/flavors/ - uses: oxsecurity/megalinter@v9.3.0 + uses: oxsecurity/megalinter@v9.4.0 env: # All available variables are described in documentation: # https://megalinter.io/configuration/ From 446864445e09637fc9951bae76d59633ce1a0add Mon Sep 17 00:00:00 2001 From: Marvin Hemmer <53471402+mhemmer-cern@users.noreply.github.com> Date: Wed, 11 Mar 2026 12:09:06 +0100 Subject: [PATCH 249/347] [Infrastructure] Add `photon` label to labeler config (#15138) --- .github/labeler.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/labeler.yml b/.github/labeler.yml index 0002f9b7327..23f9cda941a 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -87,3 +87,7 @@ trigger: tutorial: - changed-files: - any-glob-to-any-file: ["Tutorials/**"] + +photon: + - changed-files: + - any-glob-to-any-file: ["PWGEM/PhotonMeson/**", "*/PWGEM/PhotonMeson/**"] From facbdf7ec534240e4116115c51aac06377b872c3 Mon Sep 17 00:00:00 2001 From: pdhankhe <30958516+pdhankhe@users.noreply.github.com> Date: Wed, 11 Mar 2026 13:26:34 +0100 Subject: [PATCH 250/347] [PWGJE] Add new D0 substructure task (#15311) Co-authored-by: Preeti Dhankher Co-authored-by: ALICE Action Bot Co-authored-by: Preeti Dhankher --- PWGJE/Tasks/CMakeLists.txt | 4 + PWGJE/Tasks/jetD0AngSubstructure.cxx | 208 +++++++++++++++++++++++++++ 2 files changed, 212 insertions(+) create mode 100644 PWGJE/Tasks/jetD0AngSubstructure.cxx diff --git a/PWGJE/Tasks/CMakeLists.txt b/PWGJE/Tasks/CMakeLists.txt index 224b0278f73..55ec23b2c44 100644 --- a/PWGJE/Tasks/CMakeLists.txt +++ b/PWGJE/Tasks/CMakeLists.txt @@ -395,6 +395,10 @@ if(FastJet_FOUND) SOURCES jetDsSpectrumAndSubstructure.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(jet-d0-ang-substructure + SOURCES jetD0AngSubstructure.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore + COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(bjet-cent-mult SOURCES bjetCentMult.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore diff --git a/PWGJE/Tasks/jetD0AngSubstructure.cxx b/PWGJE/Tasks/jetD0AngSubstructure.cxx new file mode 100644 index 00000000000..05c1923dd96 --- /dev/null +++ b/PWGJE/Tasks/jetD0AngSubstructure.cxx @@ -0,0 +1,208 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +// +// \file JetD0AngSubstructure.cxx +// +// \brief Analysis task for the reconstruction and study of charged jets +// containing D_0 mesons in pp collisions. +// \inherited from D0 fragmentation and Ds +// \P. Dhankher + +#include "PWGHF/Core/DecayChannels.h" +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/HistogramRegistry.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#include "TVector3.h" + +#include +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +// Definition of a custom AOD table to store jet–D0 quantities +namespace o2::aod +{ +namespace jet_obj +{ +// Jet-related quantities +DECLARE_SOA_COLUMN(JetHfDist, jetHfDist, float); +DECLARE_SOA_COLUMN(JetPt, jetPt, float); +DECLARE_SOA_COLUMN(JetEta, jetEta, float); +DECLARE_SOA_COLUMN(JetPhi, jetPhi, float); +DECLARE_SOA_COLUMN(JetNConst, jetNConst, int); +DECLARE_SOA_COLUMN(JetAng, jetAng, float); +// D0 candidate quantities +DECLARE_SOA_COLUMN(HfPt, hfPt, float); +DECLARE_SOA_COLUMN(HfEta, hfEta, float); +DECLARE_SOA_COLUMN(HfPhi, hfPhi, float); +DECLARE_SOA_COLUMN(HfMass, hfMass, float); +DECLARE_SOA_COLUMN(HfY, hfY, float); +// ML scores +DECLARE_SOA_COLUMN(HfMlScore0, hfMlScore0, float); +DECLARE_SOA_COLUMN(HfMlScore1, hfMlScore1, float); +DECLARE_SOA_COLUMN(HfMlScore2, hfMlScore2, float); +} // namespace jet_obj +// AOD table definition +DECLARE_SOA_TABLE(JetObjTable, "AOD", "JETOBJTABLE", + jet_obj::JetHfDist, + jet_obj::JetPt, + jet_obj::JetEta, + jet_obj::JetPhi, + jet_obj::JetNConst, + jet_obj::JetAng, + jet_obj::HfPt, + jet_obj::HfEta, + jet_obj::HfPhi, + jet_obj::HfMass, + jet_obj::HfY, + jet_obj::HfMlScore0, + jet_obj::HfMlScore1, + jet_obj::HfMlScore2); +} // namespace o2::aod +struct JetD0AngSubstructure { + /** + * Histogram registry + * + * Contains: + * - Event and track histograms + * - Jet kinematic distributions + * - D0–jet substructure observables + */ + HistogramRegistry registry{"registry", + {{"h_collision_counter", "# of collisions;", {HistType::kTH1F, {{2, 0., 2.}}}}, + {"h_jet_counter", ";# of D^{0} jets;", {HistType::kTH1F, {{6, 0., 3.0}}}}, + {"h_d0_jet_projection", ";z^{D^{0},jet}_{||};dN/dz^{D^{0},jet}_{||}", {HistType::kTH1F, {{1000, 0., 10.}}}}, + {"h_d0_jet_distance_vs_projection", ";#DeltaR_{D^{0},jet};z^{D^{0},jet}_{||}", {HistType::kTH2F, {{1000, 0., 10.}, {1000, 0., 10.}}}}, + {"h_d0_jet_distance", ";#DeltaR_{D^{0},jet};dN/d(#DeltaR)", {HistType::kTH1F, {{1000, 0., 10.}}}}, + {"h_d0_jet_pt", ";p_{T,D^{0} jet};dN/dp_{T,D^{0} jet}", {HistType::kTH1F, {{200, 0., 10.}}}}, + {"h_d0_jet_eta", ";#eta_{T,D^{0} jet};dN/d#eta_{D^{0} jet}", {HistType::kTH1F, {{250, -5., 5.}}}}, + {"h_d0_jet_phi", ";#phi_{T,D^{0} jet};dN/d#phi_{D^{0} jet}", {HistType::kTH1F, {{250, -10., 10.}}}}, + {"h_d0_mass", ";m_{D^{0}});dN/dm_{D^{0}}", {HistType::kTH1F, {{1000, 0., 10.}}}}, + {"h_d0_eta", ";#eta_{D^{0}});dN/d#eta_{D_{}}", {HistType::kTH1F, {{250, -5., 5.}}}}, + {"h_d0_phi", ";#phi_{D^{0}});dN/d#phi_{D^{0}}", {HistType::kTH1F, {{250, -10., 10.}}}}, + {"h_d0_ang", ";#lambda_{#kappa}^{#alpha};counts", {HistType::kTH1F, {{100, 0., 1.}}}}}}; + + // Configurables + Configurable vertexZCut{"vertexZCut", 10.0f, "Accepted z-vertex range"}; + + Configurable jetPtMin{"jetPtMin", 5.0, "minimum jet pT cut"}; + Configurable jetR{"jetR", 0.4, "jet resolution parameter"}; + + Configurable eventSelections{"eventSelections", "sel8", "choose event selection"}; + Configurable trackSelections{"trackSelections", "globalTracks", "set track selections"}; + Configurable kappa{"kappa", 1.0, "angularity kappa"}; // to do: configurable from json + Configurable alpha{"alpha", 1.0, "angularity alpha"}; + + std::vector eventSelectionBits; + int trackSelection = -1; + + // Output table producer + Produces ObjJetTable; + + float angularity; + + void init(o2::framework::InitContext&) + { + eventSelectionBits = jetderiveddatautilities::initialiseEventSelectionBits(static_cast(eventSelections)); + trackSelection = jetderiveddatautilities::initialiseTrackSelection(static_cast(trackSelections)); + } + + template + void jetCalculateAngularity(T const& jet, U const& /*tracks*/) + { + angularity = 0.0; + for (auto& constituent : jet.template tracks_as()) { + angularity += std::pow(constituent.pt(), kappa) * std::pow(jetutilities::deltaR(jet, constituent) / (jet.r() / 100.f), alpha); + } + angularity /= std::pow(jet.pt(), kappa); + } + + void processDataChargedSubstructure(aod::JetCollision const& collision, + soa::Join const& jets, + aod::CandidatesD0Data const&, aod::JetTracks const& tracks) + { + // apply event selection and fill histograms for sanity check + registry.fill(HIST("h_collision_counter"), 0.5); + + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits) || !(std::abs(collision.posZ()) < vertexZCut)) { + return; + } + registry.fill(HIST("h_collision_counter"), 1.5); + + // Loop over jets containing D0 candidates + for (const auto& jet : jets) { + // number of charged jets with D0 + registry.fill(HIST("h_jet_counter"), 0.5); + // obtaining jet 3-vector + TVector3 jetVector(jet.px(), jet.py(), jet.pz()); + + // Loop over D0 candidates associated to the jet + for (const auto& d0Candidate : jet.candidates_as()) { + // obtaining jet 3-vector + TVector3 d0Vector(d0Candidate.px(), d0Candidate.py(), d0Candidate.pz()); + + // calculating fraction of the jet momentum carried by the D0 along the direction of the jet axis + double zParallel = (jetVector * d0Vector) / (jetVector * jetVector); + + // calculating angular distance in eta-phi plane + double axisDistance = jetutilities::deltaR(jet, d0Candidate); + + jetCalculateAngularity(jet, tracks); + + // filling histograms + registry.fill(HIST("h_d0_jet_projection"), zParallel); + registry.fill(HIST("h_d0_jet_distance_vs_projection"), axisDistance, zParallel); + registry.fill(HIST("h_d0_jet_distance"), axisDistance); + registry.fill(HIST("h_d0_jet_pt"), jet.pt()); + registry.fill(HIST("h_d0_jet_eta"), jet.eta()); + registry.fill(HIST("h_d0_jet_phi"), jet.phi()); + registry.fill(HIST("h_d0_mass"), d0Candidate.m()); + registry.fill(HIST("h_d0_eta"), d0Candidate.eta()); + registry.fill(HIST("h_d0_phi"), d0Candidate.phi()); + registry.fill(HIST("h_d0_ang"), angularity); // add more axis + + // filling table + ObjJetTable(axisDistance, + jet.pt(), jet.eta(), jet.phi(), jet.tracks_as().size(), angularity, + d0Candidate.pt(), d0Candidate.eta(), d0Candidate.phi(), d0Candidate.m(), d0Candidate.y(), d0Candidate.mlScores()[0], d0Candidate.mlScores()[1], d0Candidate.mlScores()[2]); + + break; // get out of candidates' loop after first HF particle is found in jet + } // end of D0 candidates loop + + } // end of jets loop + + } // end of process function + PROCESS_SWITCH(JetD0AngSubstructure, processDataChargedSubstructure, "charged HF jet substructure", false); +}; +// Workflow definition +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"jet-d0-ang-substructure"})}; } From 145c148f24480ffc24d4739f18c58284212def75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Tiek=C3=B6tter?= Date: Wed, 11 Mar 2026 14:23:00 +0100 Subject: [PATCH 251/347] [PWGDQ] Fix necessary use of ReducedEventsMultPV in rableReader_withAssoc (#15335) --- PWGDQ/Core/HistogramsLibrary.cxx | 8 ++++++++ PWGDQ/Core/VarManager.h | 3 +++ PWGDQ/Tasks/dqEfficiency_withAssoc.cxx | 1 - PWGDQ/Tasks/tableReader_withAssoc.cxx | 25 ++++++++++++++++--------- 4 files changed, 27 insertions(+), 10 deletions(-) diff --git a/PWGDQ/Core/HistogramsLibrary.cxx b/PWGDQ/Core/HistogramsLibrary.cxx index faedee1cb14..89c1002ac47 100644 --- a/PWGDQ/Core/HistogramsLibrary.cxx +++ b/PWGDQ/Core/HistogramsLibrary.cxx @@ -1170,6 +1170,14 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "Weight", "", false, 50, 0.0, 5.0, VarManager::kMCParticleWeight); hm->AddHistogram(histClass, "MCImpPar_CentFT0CMC", "MC impact param vs MC Cent. FT0C", false, 20, 0.0, 20.0, VarManager::kMCEventImpParam, 100, 0.0, 100.0, VarManager::kMCEventCentrFT0C); } + if (!groupStr.CompareTo("mctruth_mult")) { + hm->AddHistogram(histClass, "PtMC_MultEta05", "MC pT vs mult |#eta| < 0.5", false, 200, 0.0, 20.0, VarManager::kMCPt, 150, 0.0, 150.0, VarManager::kMultMCNParticlesEta05); + hm->AddHistogram(histClass, "PtMC_MultEta08", "MC pT vs mult |#eta| < 0.8", false, 200, 0.0, 20.0, VarManager::kMCPt, 150, 0.0, 150.0, VarManager::kMultMCNParticlesEta08); + hm->AddHistogram(histClass, "PtMC_MultEta10", "MC pT vs mult |#eta| < 1.0", false, 200, 0.0, 20.0, VarManager::kMCPt, 150, 0.0, 150.0, VarManager::kMultMCNParticlesEta10); + hm->AddHistogram(histClass, "EtaMC_MultEta05", "MC Eta vs mult |#eta| < 0.5", false, 40, -2.0, 2.0, VarManager::kMCEta, 150, 0.0, 150.0, VarManager::kMultMCNParticlesEta05); + hm->AddHistogram(histClass, "EtaMC_MultEta08", "MC Eta vs mult |#eta| < 0.8", false, 40, -2.0, 2.0, VarManager::kMCEta, 150, 0.0, 150.0, VarManager::kMultMCNParticlesEta08); + hm->AddHistogram(histClass, "EtaMC_MultEta10", "MC Eta vs mult |#eta| < 1.0", false, 40, -2.0, 2.0, VarManager::kMCEta, 150, 0.0, 150.0, VarManager::kMultMCNParticlesEta10); + } if (!groupStr.CompareTo("energy-correlator-gen")) { double coschiBins[26]; diff --git a/PWGDQ/Core/VarManager.h b/PWGDQ/Core/VarManager.h index 14488385846..6402590ef5a 100644 --- a/PWGDQ/Core/VarManager.h +++ b/PWGDQ/Core/VarManager.h @@ -2321,6 +2321,9 @@ void VarManager::FillEvent(T const& event, float* values) values[kMCEventWeight] = event.weight(); values[kMCEventImpParam] = event.impactParameter(); values[kMCEventCentrFT0C] = event.centFT0C(); + values[kMultMCNParticlesEta05] = event.multMCNParticlesEta05(); + values[kMultMCNParticlesEta08] = event.multMCNParticlesEta08(); + values[kMultMCNParticlesEta10] = event.multMCNParticlesEta10(); } if constexpr ((fillMap & EventFilter) > 0 || (fillMap & RapidityGapFilter) > 0) { diff --git a/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx b/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx index 96b4cf1ab4d..9fe021663bd 100644 --- a/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx +++ b/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx @@ -2176,7 +2176,6 @@ struct AnalysisSameEventPairing { template void runMCGen(MyEventsVtxCovSelected const& events, ReducedMCEvents const& mcEvents, ReducedMCTracks const& mcTracks) { - cout << "AnalysisSameEventPairing::runMCGen() called" << endl; uint32_t mcDecision = 0; int isig = 0; diff --git a/PWGDQ/Tasks/tableReader_withAssoc.cxx b/PWGDQ/Tasks/tableReader_withAssoc.cxx index 4d22ba5eac8..abaca5864de 100644 --- a/PWGDQ/Tasks/tableReader_withAssoc.cxx +++ b/PWGDQ/Tasks/tableReader_withAssoc.cxx @@ -195,6 +195,7 @@ DECLARE_SOA_TABLE(JPsieeCandidates, "AOD", "DQPSEUDOPROPER", dqanalysisflags::Ma // Declarations of various short names using MyEvents = soa::Join; +using MyEventsBasic = soa::Join; using MyEventsMultExtra = soa::Join; using MyEventsMultExtraQVector = soa::Join; using MyEventsZdc = soa::Join; @@ -307,7 +308,7 @@ struct AnalysisEventSelection { void init(o2::framework::InitContext& context) { - bool isAnyProcessEnabled = context.mOptions.get("processSkimmed") || context.mOptions.get("processSkimmedWithZdc") || context.mOptions.get("processSkimmedWithMultExtra") || context.mOptions.get("processSkimmedWithMultExtraZdc") || context.mOptions.get("processSkimmedWithMultExtraZdcFit") || context.mOptions.get("processSkimmedWithQvectorCentr"); + bool isAnyProcessEnabled = context.mOptions.get("processSkimmed") || context.mOptions.get("processSkimmedBasic") || context.mOptions.get("processSkimmedWithZdc") || context.mOptions.get("processSkimmedWithMultExtra") || context.mOptions.get("processSkimmedWithMultExtraZdc") || context.mOptions.get("processSkimmedWithMultExtraZdcFit") || context.mOptions.get("processSkimmedWithQvectorCentr"); bool isDummyEnabled = context.mOptions.get("processDummy"); if (isDummyEnabled) { @@ -528,6 +529,11 @@ struct AnalysisEventSelection { runEventSelection(events); publishSelections(events); } + void processSkimmedBasic(MyEventsBasic const& events) + { + runEventSelection(events); + publishSelections(events); + } void processSkimmedWithZdc(MyEventsZdc const& events) { runEventSelection(events); @@ -553,12 +559,13 @@ struct AnalysisEventSelection { runEventSelection(events); publishSelections(events); } - void processDummy(MyEvents&) + void processDummy(MyEventsBasic&) { // do nothing } PROCESS_SWITCH(AnalysisEventSelection, processSkimmed, "Run event selection on DQ skimmed events", false); + PROCESS_SWITCH(AnalysisEventSelection, processSkimmedBasic, "Run event selection on DQ skimmed events with basic tables", false); PROCESS_SWITCH(AnalysisEventSelection, processSkimmedWithZdc, "Run event selection on DQ skimmed events, with ZDC", false); PROCESS_SWITCH(AnalysisEventSelection, processSkimmedWithMultExtra, "Run event selection on DQ skimmed events, with mult extra", false); PROCESS_SWITCH(AnalysisEventSelection, processSkimmedWithMultExtraZdc, "Run event selection on DQ skimmed events, with mult extra and ZDC", false); @@ -814,7 +821,7 @@ struct AnalysisTrackSelection { { runTrackSelection(assocs, events, tracks); } - void processDummy(MyEvents&) + void processDummy(MyEventsBasic&) { // do nothing } @@ -1025,7 +1032,7 @@ struct AnalysisMuonSelection { { runMuonSelection(assocs, events, muons); } - void processDummy(MyEvents&) + void processDummy(MyEventsBasic&) { // do nothing } @@ -1207,7 +1214,7 @@ struct AnalysisPrefilterSelection { } } - void processDummy(MyEvents&) + void processDummy(MyEventsBasic&) { // do nothing } @@ -2500,7 +2507,7 @@ struct AnalysisSameEventPairing { runSameSideMixing(events, muonAssocs, muons, muonAssocsPerCollision); } - void processDummy(MyEvents&) + void processDummy(MyEventsBasic&) { // do nothing } @@ -3246,7 +3253,7 @@ struct AnalysisAsymmetricPairing { runThreeProng(events, trackAssocsPerCollision, barrelAssocs, barrelTracks, VarManager::kTripleCandidateToPKPi); } - void processDummy(MyEvents&) + void processDummy(MyEventsBasic&) { // do nothing } @@ -3936,7 +3943,7 @@ struct AnalysisDileptonTrack { } // end event loop } - void processDummy(MyEvents&) + void processDummy(MyEventsBasic&) { // do nothing } @@ -4191,7 +4198,7 @@ struct AnalysisDileptonTrackTrack { } } - void processDummy(MyEvents&) + void processDummy(MyEventsBasic&) { // do nothing } From d583954726f292a4be6058126190867f3f734693 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Wed, 11 Mar 2026 14:41:05 +0100 Subject: [PATCH 252/347] [DPG] Add ccosThetaStar in D0 derived data creator for calibration studies (#15346) --- DPG/Tasks/AOTTrack/D0CalibTables.h | 4 ++++ .../derivedDataCreatorD0Calibration.cxx | 24 +++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/DPG/Tasks/AOTTrack/D0CalibTables.h b/DPG/Tasks/AOTTrack/D0CalibTables.h index 33c9efdc2dd..973582d8ba2 100644 --- a/DPG/Tasks/AOTTrack/D0CalibTables.h +++ b/DPG/Tasks/AOTTrack/D0CalibTables.h @@ -444,6 +444,8 @@ DECLARE_SOA_COLUMN(Eta, eta, float); / DECLARE_SOA_COLUMN(Phi, phi, float); //! D0-candidate phi DECLARE_SOA_COLUMN(InvMassD0, invMassD0, float); //! invariant mass (D0 hypothesis) DECLARE_SOA_COLUMN(InvMassD0bar, invMassD0bar, float); //! invariant mass (D0bar hypothesis) +DECLARE_SOA_COLUMN(CosThetaStarD0, cosThetaStarD0, float); //! D0-candidate cost* (Helicity frame, D0 mass hypothesis) +DECLARE_SOA_COLUMN(CosThetaStarD0bar, cosThetaStarD0bar, float); //! D0-candidate cost* (Helicity frame, D0bar mass hypthesis) DECLARE_SOA_COLUMN(DecLength, decLength, uint8_t); //! compressed decay length DECLARE_SOA_COLUMN(DecLengthXY, decLengthXY, uint8_t); //! compressed decay length XY DECLARE_SOA_COLUMN(NormDecLength, normDecLength, uint8_t); //! compressed normalised decay length @@ -472,6 +474,8 @@ DECLARE_SOA_TABLE(D0CalibCands, "AOD", "D0CALIBCAND", hf_calib::Phi, hf_calib::InvMassD0, hf_calib::InvMassD0bar, + hf_calib::CosThetaStarD0, + hf_calib::CosThetaStarD0bar, hf_calib::DecLength, hf_calib::DecLengthXY, hf_calib::NormDecLength, diff --git a/DPG/Tasks/AOTTrack/derivedDataCreatorD0Calibration.cxx b/DPG/Tasks/AOTTrack/derivedDataCreatorD0Calibration.cxx index a8bd2c6d321..04db9d2fd1c 100644 --- a/DPG/Tasks/AOTTrack/derivedDataCreatorD0Calibration.cxx +++ b/DPG/Tasks/AOTTrack/derivedDataCreatorD0Calibration.cxx @@ -41,6 +41,11 @@ #include #include +#include +#include // IWYU pragma: keep (do not replace with Math/Vector3Dfwd.h) +#include +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include #include #include @@ -412,6 +417,7 @@ struct DerivedDataCreatorD0Calibration { } float invMassD0{0.f}, invMassD0bar{0.f}; + float cosThetaStarD0{0.f}, cosThetaStarD0bar{0.f}; std::vector bdtScoresD0{0.f, 1.f, 1.f}, bdtScoresD0bar{0.f, 1.f, 1.f}; // always selected a priori if (massHypo == D0MassHypo::D0 || massHypo == D0MassHypo::D0AndD0Bar) { invMassD0 = RecoDecay::m(std::array{pVecPos, pVecNeg}, std::array{o2::constants::physics::MassPiPlus, o2::constants::physics::MassKPlus}); @@ -424,6 +430,14 @@ struct DerivedDataCreatorD0Calibration { std::vector featuresCandD0 = {dcaPos.getY(), dcaNeg.getY(), chi2PCA, cosPaD0, cosPaXYD0, decLenXYD0, decLenD0, dcaPos.getY() * dcaNeg.getY(), aod::pid_tpc_tof_utils::combineNSigma(trackPos.tpcNSigmaPi(), trackPos.tofNSigmaPi()), aod::pid_tpc_tof_utils::combineNSigma(trackNeg.tpcNSigmaKa(), trackNeg.tofNSigmaKa()), trackPos.tpcNSigmaPi(), trackPos.tpcNSigmaKa(), aod::pid_tpc_tof_utils::combineNSigma(trackPos.tpcNSigmaKa(), trackPos.tofNSigmaKa()), trackNeg.tpcNSigmaPi(), trackNeg.tpcNSigmaKa(), aod::pid_tpc_tof_utils::combineNSigma(trackNeg.tpcNSigmaPi(), trackNeg.tofNSigmaPi())}; if (!mlResponse.isSelectedMl(featuresCandD0, ptD0, bdtScoresD0)) { massHypo -= D0MassHypo::D0; + } else { // selected, we compute cost* + ROOT::Math::PxPyPzMVector const fourVecPi = ROOT::Math::PxPyPzMVector(pVecPos[0], pVecPos[1], pVecPos[2], o2::constants::physics::MassPiPlus); + ROOT::Math::PxPyPzMVector const fourVecMother = ROOT::Math::PxPyPzMVector(pVecD0[0], pVecD0[1], pVecD0[2], invMassD0); + ROOT::Math::Boost const boost{fourVecMother.BoostToCM()}; + ROOT::Math::PxPyPzMVector const fourVecPiCM = boost(fourVecPi); + ROOT::Math::XYZVector const threeVecPiCM = fourVecPiCM.Vect(); + ROOT::Math::XYZVector const helicityVec = fourVecMother.Vect(); + cosThetaStarD0 = helicityVec.Dot(threeVecPiCM) / std::sqrt(threeVecPiCM.Mag2()) / std::sqrt(helicityVec.Mag2()); } } } @@ -439,6 +453,14 @@ struct DerivedDataCreatorD0Calibration { std::vector featuresCandD0bar = {dcaPos.getY(), dcaNeg.getY(), chi2PCA, cosPaD0, cosPaXYD0, decLenXYD0, decLenD0, dcaPos.getY() * dcaNeg.getY(), aod::pid_tpc_tof_utils::combineNSigma(trackNeg.tpcNSigmaPi(), trackNeg.tofNSigmaPi()), aod::pid_tpc_tof_utils::combineNSigma(trackPos.tpcNSigmaKa(), trackPos.tofNSigmaKa()), trackNeg.tpcNSigmaPi(), trackNeg.tpcNSigmaKa(), aod::pid_tpc_tof_utils::combineNSigma(trackNeg.tpcNSigmaKa(), trackNeg.tofNSigmaKa()), trackPos.tpcNSigmaPi(), trackPos.tpcNSigmaKa(), aod::pid_tpc_tof_utils::combineNSigma(trackPos.tpcNSigmaPi(), trackPos.tofNSigmaPi())}; if (!mlResponse.isSelectedMl(featuresCandD0bar, ptD0, bdtScoresD0bar)) { massHypo -= D0MassHypo::D0Bar; + } else { // selected, we compute cost* + ROOT::Math::PxPyPzMVector const fourVecPi = ROOT::Math::PxPyPzMVector(pVecNeg[0], pVecNeg[1], pVecNeg[2], o2::constants::physics::MassPiPlus); + ROOT::Math::PxPyPzMVector const fourVecMother = ROOT::Math::PxPyPzMVector(pVecD0[0], pVecD0[1], pVecD0[2], invMassD0bar); + ROOT::Math::Boost const boost{fourVecMother.BoostToCM()}; + ROOT::Math::PxPyPzMVector const fourVecPiCM = boost(fourVecPi); + ROOT::Math::XYZVector const threeVecPiCM = fourVecPiCM.Vect(); + ROOT::Math::XYZVector const helicityVec = fourVecMother.Vect(); + cosThetaStarD0bar = helicityVec.Dot(threeVecPiCM) / std::sqrt(threeVecPiCM.Mag2()) / std::sqrt(helicityVec.Mag2()); } } } @@ -813,6 +835,8 @@ struct DerivedDataCreatorD0Calibration { phiD0, invMassD0, invMassD0bar, + cosThetaStarD0, + cosThetaStarD0bar, getCompressedDecayLength(decLenD0), getCompressedDecayLength(decLenXYD0), getCompressedNormDecayLength(decLenD0 / errorDecayLengthD0), From 055f1164a54836730c3daf6620922bbc0de068e8 Mon Sep 17 00:00:00 2001 From: somabhatta <48771326+somabhatta@users.noreply.github.com> Date: Wed, 11 Mar 2026 17:57:42 +0100 Subject: [PATCH 253/347] [PWGCF] Update radial flow pid limits new (#15320) --- .../Tasks/radialFlowDecorr.cxx | 253 ++++++++---------- 1 file changed, 109 insertions(+), 144 deletions(-) diff --git a/PWGCF/EbyEFluctuations/Tasks/radialFlowDecorr.cxx b/PWGCF/EbyEFluctuations/Tasks/radialFlowDecorr.cxx index 4f710a0e788..b052893881e 100644 --- a/PWGCF/EbyEFluctuations/Tasks/radialFlowDecorr.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/radialFlowDecorr.cxx @@ -166,10 +166,6 @@ struct RadialFlowDecorr { Configurable cfgPtMin{"cfgPtMin", 0.2f, "min pT"}; Configurable cfgPtMax{"cfgPtMax", 5.0f, "max pT"}; Configurable cfgEtaCut{"cfgEtaCut", 0.8f, "|η| cut"}; - Configurable cfgTPCClsMin{"cfgTPCClsMin", 70.f, "min TPC clusters"}; - Configurable cfgChi2TPCMax{"cfgChi2TPCMax", 4.0f, "max TPC χ²"}; - Configurable cfgCutTpcChi2NCl{"cfgCutTpcChi2NCl", 2.5f, "Maximum TPCchi2NCl"}; - Configurable cfgCutItsChi2NCl{"cfgCutItsChi2NCl", 36.0f, "Maximum ITSchi2NCl"}; Configurable cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted z-vertex range"}; Configurable cfgCutTracKDcaMaxZ{"cfgCutTracKDcaMaxZ", 2.0f, "Maximum DcaZ"}; Configurable cfgCutTracKDcaMaxXY{"cfgCutTracKDcaMaxXY", 0.2f, "Maximum DcaZ"}; @@ -193,10 +189,6 @@ struct RadialFlowDecorr { Configurable cfgnSigmaCutTOF{"cfgnSigmaCutTOF", 2.0f, "PID nSigma cut for TOF"}; Configurable cfgnSigmaCutCombTPCTOF{"cfgnSigmaCutCombTPCTOF", 2.0f, "PID nSigma combined cut for TPC and TOF"}; - Configurable cfgTpcElRejCutMin{"cfgTpcElRejCutMin", -3.0f, "Electron Rejection Cut Minimum"}; - Configurable cfgTpcElRejCutMax{"cfgTpcElRejCutMax", 5.0f, "Electron Rejection Cut Maximum"}; - Configurable cfgTpcElRejCut{"cfgTpcElRejCut", 3.0f, "TPC Hadron Rejection Cut"}; - Configurable cfgCutPtLower{"cfgCutPtLower", 0.2f, "Lower pT cut"}; Configurable cfgCutPtUpper{"cfgCutPtUpper", 10.0f, "Higher pT cut for inclusive hadron analysis"}; Configurable cfgCutPtUpperPID{"cfgCutPtUpperPID", 6.0f, "Higher pT cut for identified particle analysis"}; @@ -297,24 +289,16 @@ struct RadialFlowDecorr { { float pt = track.pt(); auto sign = track.sign(); - histos.fill(HIST("h3DnsigmaTpcVsPtBefCut_Cent"), cent, pt, track.tpcNSigmaPi()); - histos.fill(HIST("h3DnsigmaTofVsPtBefCut_Cent"), cent, pt, track.tofNSigmaPi()); - histos.fill(HIST("h3DnsigmaTpcVsTofBefCut_Cent"), cent, track.tofNSigmaPi(), track.tpcNSigmaPi()); - - histos.fill(HIST("h3DnsigmaTpcVsPtBefCut_Cent"), cent, pt, track.tpcNSigmaKa()); - histos.fill(HIST("h3DnsigmaTofVsPtBefCut_Cent"), cent, pt, track.tofNSigmaKa()); - histos.fill(HIST("h3DnsigmaTpcVsTofBefCut_Cent"), cent, track.tofNSigmaKa(), track.tpcNSigmaKa()); - histos.fill(HIST("h3DnsigmaTpcVsPtBefCut_Cent"), cent, pt, track.tpcNSigmaPr()); - histos.fill(HIST("h3DnsigmaTofVsPtBefCut_Cent"), cent, pt, track.tofNSigmaPr()); - histos.fill(HIST("h3DnsigmaTpcVsTofBefCut_Cent"), cent, track.tofNSigmaPr(), track.tpcNSigmaPr()); if (sign > 0) { histos.fill(HIST("h3DnsigmaTpcVsPtBefCut_Cent_PiPlus"), cent, pt, track.tpcNSigmaPi()); histos.fill(HIST("h3DnsigmaTofVsPtBefCut_Cent_PiPlus"), cent, pt, track.tofNSigmaPi()); histos.fill(HIST("h3DnsigmaTpcVsTofBefCut_Cent_PiPlus"), cent, track.tofNSigmaPi(), track.tpcNSigmaPi()); + histos.fill(HIST("h3DnsigmaTpcVsPtBefCut_Cent_KaPlus"), cent, pt, track.tpcNSigmaKa()); histos.fill(HIST("h3DnsigmaTofVsPtBefCut_Cent_KaPlus"), cent, pt, track.tofNSigmaKa()); histos.fill(HIST("h3DnsigmaTpcVsTofBefCut_Cent_KaPlus"), cent, track.tofNSigmaKa(), track.tpcNSigmaKa()); + histos.fill(HIST("h3DnsigmaTpcVsPtBefCut_Cent_Pr"), cent, pt, track.tpcNSigmaPr()); histos.fill(HIST("h3DnsigmaTofVsPtBefCut_Cent_Pr"), cent, pt, track.tofNSigmaPr()); histos.fill(HIST("h3DnsigmaTpcVsTofBefCut_Cent_Pr"), cent, track.tofNSigmaPr(), track.tpcNSigmaPr()); @@ -322,9 +306,11 @@ struct RadialFlowDecorr { histos.fill(HIST("h3DnsigmaTpcVsPtBefCut_Cent_PiMinus"), cent, pt, track.tpcNSigmaPi()); histos.fill(HIST("h3DnsigmaTofVsPtBefCut_Cent_PiMinus"), cent, pt, track.tofNSigmaPi()); histos.fill(HIST("h3DnsigmaTpcVsTofBefCut_Cent_PiMinus"), cent, track.tofNSigmaPi(), track.tpcNSigmaPi()); + histos.fill(HIST("h3DnsigmaTpcVsPtBefCut_Cent_KaMinus"), cent, pt, track.tpcNSigmaKa()); histos.fill(HIST("h3DnsigmaTofVsPtBefCut_Cent_KaMinus"), cent, pt, track.tofNSigmaKa()); histos.fill(HIST("h3DnsigmaTpcVsTofBefCut_Cent_KaMinus"), cent, track.tofNSigmaKa(), track.tpcNSigmaKa()); + histos.fill(HIST("h3DnsigmaTpcVsPtBefCut_Cent_AntiPr"), cent, pt, track.tpcNSigmaPr()); histos.fill(HIST("h3DnsigmaTofVsPtBefCut_Cent_AntiPr"), cent, pt, track.tofNSigmaPr()); histos.fill(HIST("h3DnsigmaTpcVsTofBefCut_Cent_AntiPr"), cent, track.tofNSigmaPr(), track.tpcNSigmaPr()); @@ -346,61 +332,61 @@ struct RadialFlowDecorr { void fillNSigmaAftCut(const T& track, float cent, bool isSpecies[]) { float pt = track.pt(); + float tpcPi = track.tpcNSigmaPi(); + float tofPi = track.tofNSigmaPi(); - if (isSpecies[kInclusiveIdx]) { - histos.fill(HIST("h3DnsigmaTpcVsPtAftCut_Cent"), cent, pt, track.tpcNSigmaPi()); - histos.fill(HIST("h3DnsigmaTofVsPtAftCut_Cent"), cent, pt, track.tofNSigmaPi()); - histos.fill(HIST("h3DnsigmaTpcVsTofAftCut_Cent"), cent, track.tofNSigmaPi(), track.tpcNSigmaPi()); + float tpcKa = track.tpcNSigmaKa(); + float tofKa = track.tofNSigmaKa(); - histos.fill(HIST("h3DnsigmaTpcVsPtAftCut_Cent"), cent, pt, track.tpcNSigmaKa()); - histos.fill(HIST("h3DnsigmaTofVsPtAftCut_Cent"), cent, pt, track.tofNSigmaKa()); - histos.fill(HIST("h3DnsigmaTpcVsTofAftCut_Cent"), cent, track.tofNSigmaKa(), track.tpcNSigmaKa()); + float tpcPr = track.tpcNSigmaPr(); + float tofPr = track.tofNSigmaPr(); - histos.fill(HIST("h3DnsigmaTpcVsPtAftCut_Cent"), cent, pt, track.tpcNSigmaPr()); - histos.fill(HIST("h3DnsigmaTofVsPtAftCut_Cent"), cent, pt, track.tofNSigmaPr()); - histos.fill(HIST("h3DnsigmaTpcVsTofAftCut_Cent"), cent, track.tofNSigmaPr(), track.tpcNSigmaPr()); - } if (isSpecies[kPiPlusIdx]) { - histos.fill(HIST("h3DnsigmaTpcVsPtAftCut_Cent_PiPlus"), cent, pt, track.tpcNSigmaPi()); - histos.fill(HIST("h3DnsigmaTofVsPtAftCut_Cent_PiPlus"), cent, pt, track.tofNSigmaPi()); - histos.fill(HIST("h3DnsigmaTpcVsTofAftCut_Cent_PiPlus"), cent, track.tofNSigmaPi(), track.tpcNSigmaPi()); - } else if (isSpecies[kPiMinusIdx]) { - histos.fill(HIST("h3DnsigmaTpcVsPtAftCut_Cent_PiMinus"), cent, pt, track.tpcNSigmaPi()); - histos.fill(HIST("h3DnsigmaTofVsPtAftCut_Cent_PiMinus"), cent, pt, track.tofNSigmaPi()); - histos.fill(HIST("h3DnsigmaTpcVsTofAftCut_Cent_PiMinus"), cent, track.tofNSigmaPi(), track.tpcNSigmaPi()); + histos.fill(HIST("h3DnsigmaTpcVsPtAftCut_Cent_PiPlus"), cent, pt, tpcPi); + histos.fill(HIST("h3DnsigmaTofVsPtAftCut_Cent_PiPlus"), cent, pt, tofPi); + histos.fill(HIST("h3DnsigmaTpcVsTofAftCut_Cent_PiPlus"), cent, tofPi, tpcPi); + } + if (isSpecies[kPiMinusIdx]) { + histos.fill(HIST("h3DnsigmaTpcVsPtAftCut_Cent_PiMinus"), cent, pt, tpcPi); + histos.fill(HIST("h3DnsigmaTofVsPtAftCut_Cent_PiMinus"), cent, pt, tofPi); + histos.fill(HIST("h3DnsigmaTpcVsTofAftCut_Cent_PiMinus"), cent, tofPi, tpcPi); } if (isSpecies[kPiAllIdx]) { - histos.fill(HIST("h3DnsigmaTpcVsPtAftCut_Cent_PiAll"), cent, pt, track.tpcNSigmaPi()); - histos.fill(HIST("h3DnsigmaTofVsPtAftCut_Cent_PiAll"), cent, pt, track.tofNSigmaPi()); - histos.fill(HIST("h3DnsigmaTpcVsTofAftCut_Cent_PiAll"), cent, track.tofNSigmaPi(), track.tpcNSigmaPi()); + histos.fill(HIST("h3DnsigmaTpcVsPtAftCut_Cent_PiAll"), cent, pt, tpcPi); + histos.fill(HIST("h3DnsigmaTofVsPtAftCut_Cent_PiAll"), cent, pt, tofPi); + histos.fill(HIST("h3DnsigmaTpcVsTofAftCut_Cent_PiAll"), cent, tofPi, tpcPi); } if (isSpecies[kKaPlusIdx]) { - histos.fill(HIST("h3DnsigmaTpcVsPtAftCut_Cent_KaPlus"), cent, pt, track.tpcNSigmaKa()); - histos.fill(HIST("h3DnsigmaTofVsPtAftCut_Cent_KaPlus"), cent, pt, track.tofNSigmaKa()); - histos.fill(HIST("h3DnsigmaTpcVsTofAftCut_Cent_KaPlus"), cent, track.tofNSigmaKa(), track.tpcNSigmaKa()); - } else if (isSpecies[kKaMinusIdx]) { - histos.fill(HIST("h3DnsigmaTpcVsPtAftCut_Cent_KaMinus"), cent, pt, track.tpcNSigmaKa()); - histos.fill(HIST("h3DnsigmaTofVsPtAftCut_Cent_KaMinus"), cent, pt, track.tofNSigmaKa()); - histos.fill(HIST("h3DnsigmaTpcVsTofAftCut_Cent_KaMinus"), cent, track.tofNSigmaKa(), track.tpcNSigmaKa()); + histos.fill(HIST("h3DnsigmaTpcVsPtAftCut_Cent_KaPlus"), cent, pt, tpcKa); + histos.fill(HIST("h3DnsigmaTofVsPtAftCut_Cent_KaPlus"), cent, pt, tofKa); + histos.fill(HIST("h3DnsigmaTpcVsTofAftCut_Cent_KaPlus"), cent, tofKa, tpcKa); + } + if (isSpecies[kKaMinusIdx]) { + histos.fill(HIST("h3DnsigmaTpcVsPtAftCut_Cent_KaMinus"), cent, pt, tpcKa); + histos.fill(HIST("h3DnsigmaTofVsPtAftCut_Cent_KaMinus"), cent, pt, tofKa); + histos.fill(HIST("h3DnsigmaTpcVsTofAftCut_Cent_KaMinus"), cent, tofKa, tpcKa); } if (isSpecies[kKaAllIdx]) { - histos.fill(HIST("h3DnsigmaTpcVsPtAftCut_Cent_KaAll"), cent, pt, track.tpcNSigmaKa()); - histos.fill(HIST("h3DnsigmaTofVsPtAftCut_Cent_KaAll"), cent, pt, track.tofNSigmaKa()); - histos.fill(HIST("h3DnsigmaTpcVsTofAftCut_Cent_KaAll"), cent, track.tofNSigmaKa(), track.tpcNSigmaKa()); + histos.fill(HIST("h3DnsigmaTpcVsPtAftCut_Cent_KaAll"), cent, pt, tpcKa); + histos.fill(HIST("h3DnsigmaTofVsPtAftCut_Cent_KaAll"), cent, pt, tofKa); + histos.fill(HIST("h3DnsigmaTpcVsTofAftCut_Cent_KaAll"), cent, tofKa, tpcKa); } if (isSpecies[kPrIdx]) { - histos.fill(HIST("h3DnsigmaTpcVsPtAftCut_Cent_Pr"), cent, pt, track.tpcNSigmaPr()); - histos.fill(HIST("h3DnsigmaTofVsPtAftCut_Cent_Pr"), cent, pt, track.tofNSigmaPr()); - histos.fill(HIST("h3DnsigmaTpcVsTofAftCut_Cent_Pr"), cent, track.tofNSigmaPr(), track.tpcNSigmaPr()); - } else if (isSpecies[kAntiPrIdx]) { - histos.fill(HIST("h3DnsigmaTpcVsPtAftCut_Cent_AntiPr"), cent, pt, track.tpcNSigmaPr()); - histos.fill(HIST("h3DnsigmaTofVsPtAftCut_Cent_AntiPr"), cent, pt, track.tofNSigmaPr()); - histos.fill(HIST("h3DnsigmaTpcVsTofAftCut_Cent_AntiPr"), cent, track.tofNSigmaPr(), track.tpcNSigmaPr()); + histos.fill(HIST("h3DnsigmaTpcVsPtAftCut_Cent_Pr"), cent, pt, tpcPr); + histos.fill(HIST("h3DnsigmaTofVsPtAftCut_Cent_Pr"), cent, pt, tofPr); + histos.fill(HIST("h3DnsigmaTpcVsTofAftCut_Cent_Pr"), cent, tofPr, tpcPr); + } + if (isSpecies[kAntiPrIdx]) { + histos.fill(HIST("h3DnsigmaTpcVsPtAftCut_Cent_AntiPr"), cent, pt, tpcPr); + histos.fill(HIST("h3DnsigmaTofVsPtAftCut_Cent_AntiPr"), cent, pt, tofPr); + histos.fill(HIST("h3DnsigmaTpcVsTofAftCut_Cent_AntiPr"), cent, tofPr, tpcPr); } if (isSpecies[kPrAllIdx]) { - histos.fill(HIST("h3DnsigmaTpcVsPtAftCut_Cent_PrAll"), cent, pt, track.tpcNSigmaPr()); - histos.fill(HIST("h3DnsigmaTofVsPtAftCut_Cent_PrAll"), cent, pt, track.tofNSigmaPr()); - histos.fill(HIST("h3DnsigmaTpcVsTofAftCut_Cent_PrAll"), cent, track.tofNSigmaPr(), track.tpcNSigmaPr()); + histos.fill(HIST("h3DnsigmaTpcVsPtAftCut_Cent_PrAll"), cent, pt, tpcPr); + histos.fill(HIST("h3DnsigmaTofVsPtAftCut_Cent_PrAll"), cent, pt, tofPr); + histos.fill(HIST("h3DnsigmaTpcVsTofAftCut_Cent_PrAll"), cent, tofPr, tpcPr); + } else { + return; } } @@ -734,6 +720,10 @@ struct RadialFlowDecorr { return; } offsetFT0 = ccdb->getForTimeStamp>("FT0/Calib/Align", timestamp); + if (!offsetFT0) { + LOGF(fatal, "Failed to load valid FT0 alignment from CCDB!"); + return; + } mLastTimestamp = timestamp; LOGF(info, "Successfully loaded new alignment parameters for timestamp %llu", timestamp); LOGF(info, "Offset for FT0A: x = %.3f y = %.3f z = %.3f\n", (*offsetFT0)[0].getX(), (*offsetFT0)[0].getY(), (*offsetFT0)[0].getZ()); @@ -996,8 +986,8 @@ struct RadialFlowDecorr { histos.add("pmeanFT0Cmultpv", "N_{PV}; AmplitudeA", kTProfile, {nChAxis}); histos.add("pmeanFT0C_cent", "cent; AmplitudeA", kTProfile, {centAxis1Per}); - histos.add("pmean_cent_id_eta_FT0", ";cent;channel id; #eta;amplitude", kTProfile3D, {{centAxis1Per}, {100, -0.5, 99.5}, {100, -5.0, 5.0}}); - histos.add("h3_cent_id_eta_FT0", ";cent;channel id; #eta", kTH3F, {{centAxis1Per}, {100, -0.5, 99.5}, {100, -5.0, 5.0}}); + histos.add("pmean_cent_id_eta_FT0", ";cent;channel id; #eta;amplitude", kTProfile3D, {{centAxis1Per}, {200, -0.5, 199.5}, {100, -5.0, 5.0}}); + histos.add("h3_cent_id_eta_FT0", ";cent;channel id; #eta", kTH3F, {{centAxis1Per}, {200, -0.5, 199.5}, {100, -5.0, 5.0}}); histos.add("Prof_Cent_Nsp_Nchrec", ";cent;Species;#LT N_{PV}#GT", kTProfile2D, {{centAxis1Per}, {spBinAxis}}); histos.add("Prof_Mult_Nsp_Nchrec", ";N_{PV};Species;#LT N_{PV}#GT", kTProfile2D, {{nChAxis}, {spBinAxis}}); @@ -1235,7 +1225,9 @@ struct RadialFlowDecorr { if (hNumS && hNumF && hDenF) { state.hFake[pidType] = reinterpret_cast(hNumS->Clone(Form("hFake%s", suffix.c_str()))); state.hFake[pidType]->Add(hNumF); - state.hFake[pidType]->Add(hNumF2); + if (pidType != kInclusiveIdx && hNumF2) { + state.hFake[pidType]->Add(hNumF2); + } state.hFake[pidType]->SetDirectory(nullptr); state.hFake[pidType]->Divide(hDenF); } else { @@ -1468,15 +1460,10 @@ struct RadialFlowDecorr { histos.fill(HIST("Hist2D_globalTracks_PVTracks"), multPV, trackSlice.size()); histos.fill(HIST("Hist2D_cent_nch"), trackSlice.size(), cent); - - for (const auto& particle : partSlice) { - if (!isParticleSelected(particle) || !particle.isPhysicalPrimary()) + for (const auto& track : trackSlice) { + if (!isTrackSelected(track)) continue; - for (const auto& track : trackSlice) { - if (!isTrackSelected(track)) - continue; - fillNSigmaBefCut(track, cent); - } + fillNSigmaBefCut(track, cent); } } } @@ -1525,16 +1512,16 @@ struct RadialFlowDecorr { float pt = particle.pt(), eta = particle.eta(); bool isSpecies[KNsp] = { - (absPdg == KPiPlus || absPdg == KKPlus || absPdg == KProton), // kInclusiveIdx - pdg == -KPiPlus, // kPiMinusIdx - pdg == KPiPlus, // kPiPlusIdx - absPdg == KPiPlus, // kPiAllIdx - pdg == -KKPlus, // kKaMinusIdx - pdg == KKPlus, // kKaPlusIdx - absPdg == KKPlus, // kKaAllIdx - pdg == -KProton, // kAntiPrIdx - pdg == KProton, // kPrIdx - absPdg == KProton // kPrAllIdx + true, // kInclusiveIdx + pdg == -KPiPlus, // kPiMinusIdx + pdg == KPiPlus, // kPiPlusIdx + absPdg == KPiPlus, // kPiAllIdx + pdg == -KKPlus, // kKaMinusIdx + pdg == KKPlus, // kKaPlusIdx + absPdg == KKPlus, // kKaAllIdx + pdg == -KProton, // kAntiPrIdx + pdg == KProton, // kPrIdx + absPdg == KProton // kPrAllIdx }; histos.fill(HIST("h3_AllPrimary"), multPV, pt, eta); @@ -1572,37 +1559,29 @@ struct RadialFlowDecorr { bool isPi = (id == KPidPionOne); bool isKa = (id == KPidKaonTwo); bool isPr = (id == KPidProtonThree); - bool isAny = (isPi || isKa || isPr); // Only true if it passed PID! - bool isSpecies[KNsp] = { - isAny, + true, isPi && sign < 0, isPi && sign > 0, isPi, isKa && sign < 0, isKa && sign > 0, isKa, isPr && sign < 0, isPr && sign > 0, isPr}; + fillNSigmaAftCut(track, cent, isSpecies); + for (int isp = 0; isp < KNsp; ++isp) { if (!isSpecies[isp]) continue; - fillNSigmaAftCut(track, cent, isSpecies); - if (isp == kInclusiveIdx) { histos.fill(HIST("h3_AllReco"), multPV, pt, eta); if (track.has_mcParticle()) { auto mcP = track.mcParticle(); if (mcP.isPhysicalPrimary()) { - int mcPdg = std::abs(mcP.pdgCode()); - if (mcPdg == KPiPlus || mcPdg == KKPlus || mcPdg == KProton) { - histos.fill(HIST("ptResolution"), mcP.pt(), (pt - mcP.pt()) / mcP.pt()); - histos.fill(HIST("etaResolution"), mcP.eta(), eta - mcP.eta()); - histos.fill(HIST("etaTruthReco"), mcP.eta(), eta); - histos.fill(HIST("vzResolution"), mcP.vz(), (vz - mcP.vz()) / mcP.vz()); - histos.fill(HIST("TruthTracKVz"), mcP.vz(), vz); - histos.fill(HIST("h3_RecoMatchedToPrimary"), multPV, mcP.pt(), mcP.eta()); - } else { - // Misidentified! Reconstructed track, but true particle is not pi/K/P - histos.fill(HIST("h3_RecoMatchedToPrimary_MisID"), multPV, pt, eta); - } + histos.fill(HIST("ptResolution"), mcP.pt(), (pt - mcP.pt()) / mcP.pt()); + histos.fill(HIST("etaResolution"), mcP.eta(), eta - mcP.eta()); + histos.fill(HIST("etaTruthReco"), mcP.eta(), eta); + histos.fill(HIST("vzResolution"), mcP.vz(), (vz - mcP.vz()) / mcP.vz()); + histos.fill(HIST("TruthTracKVz"), mcP.vz(), vz); + histos.fill(HIST("h3_RecoMatchedToPrimary"), multPV, mcP.pt(), mcP.eta()); } else { histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary"), multPV, pt, eta); } @@ -1801,10 +1780,8 @@ struct RadialFlowDecorr { bool isPi = (id == KPidPionOne); bool isKa = (id == KPidKaonTwo); bool isPr = (id == KPidProtonThree); - bool isAny = (isPi || isKa || isPr); // Only true if it passed PID! - bool isSpecies[KNsp] = { - isAny, + true, isPi && sign < 0, isPi && sign > 0, isPi, isKa && sign < 0, isKa && sign > 0, isKa, isPr && sign < 0, isPr && sign > 0, isPr}; @@ -1920,16 +1897,16 @@ struct RadialFlowDecorr { int absPdg = std::abs(pdgCode); bool isSpecies[KNsp] = { - (absPdg == KPiPlus || absPdg == KKPlus || absPdg == KProton), // kInclusiveIdx - pdgCode == -KPiPlus, // kPiMinusIdx - pdgCode == KPiPlus, // kPiPlusIdx - absPdg == KPiPlus, // kPiAllIdx - pdgCode == -KKPlus, // kKaMinusIdx - pdgCode == KKPlus, // kKaPlusIdx - absPdg == KKPlus, // kKaAllIdx - pdgCode == -KProton, // kAntiPrIdx - pdgCode == KProton, // kPrIdx - absPdg == KProton // kPrAllIdx + true, // kInclusiveIdx + pdgCode == -KPiPlus, // kPiMinusIdx + pdgCode == KPiPlus, // kPiPlusIdx + absPdg == KPiPlus, // kPiAllIdx + pdgCode == -KKPlus, // kKaMinusIdx + pdgCode == KKPlus, // kKaPlusIdx + absPdg == KKPlus, // kKaAllIdx + pdgCode == -KProton, // kAntiPrIdx + pdgCode == KProton, // kPrIdx + absPdg == KProton // kPrAllIdx }; for (int ieta = 0; ieta < KNEta; ++ieta) { @@ -1965,9 +1942,8 @@ struct RadialFlowDecorr { bool isPi = (id == KPidPionOne); bool isKa = (id == KPidKaonTwo); bool isPr = (id == KPidProtonThree); - bool isAny = (isPi || isKa || isPr); // Only true if it passed PID! bool isSpecies[KNsp] = { - isAny, + true, isPi && sign < 0, isPi && sign > 0, isPi, isKa && sign < 0, isKa && sign > 0, isKa, isPr && sign < 0, isPr && sign > 0, isPr}; @@ -2008,7 +1984,6 @@ struct RadialFlowDecorr { histos.fill(HIST("Fake_eta"), eta, fake); histos.fill(HIST("wgt_eta"), eta, w); } - if (isp == kInclusiveIdx) { histos.fill(HIST("hEtaPhiReco"), vz, sign, pt, eta, phi); histos.fill(HIST("hEtaPhiRecoWtd"), vz, sign, pt, eta, phi, w); @@ -2295,16 +2270,16 @@ struct RadialFlowDecorr { int absPdg = std::abs(pdgCode); bool isSpecies[KNsp] = { - (absPdg == KPiPlus || absPdg == KKPlus || absPdg == KProton), // kInclusiveIdx - pdgCode == -KPiPlus, // kPiMinusIdx - pdgCode == KPiPlus, // kPiPlusIdx - absPdg == KPiPlus, // kPiAllIdx - pdgCode == -KKPlus, // kKaMinusIdx - pdgCode == KKPlus, // kKaPlusIdx - absPdg == KKPlus, // kKaAllIdx - pdgCode == -KProton, // kAntiPrIdx - pdgCode == KProton, // kPrIdx - absPdg == KProton // kPrAllIdx + true, // kInclusiveIdx + pdgCode == -KPiPlus, // kPiMinusIdx + pdgCode == KPiPlus, // kPiPlusIdx + absPdg == KPiPlus, // kPiAllIdx + pdgCode == -KKPlus, // kKaMinusIdx + pdgCode == KKPlus, // kKaPlusIdx + absPdg == KKPlus, // kKaAllIdx + pdgCode == -KProton, // kAntiPrIdx + pdgCode == KProton, // kPrIdx + absPdg == KProton // kPrAllIdx }; for (int ieta = 0; ieta < KNEta; ++ieta) { @@ -2338,10 +2313,8 @@ struct RadialFlowDecorr { bool isPi = (id == KPidPionOne); bool isKa = (id == KPidKaonTwo); bool isPr = (id == KPidProtonThree); - bool isAny = (isPi || isKa || isPr); // Only true if it passed PID! - bool isSpecies[KNsp] = { - isAny, + true, isPi && sign < 0, isPi && sign > 0, isPi, isKa && sign < 0, isKa && sign > 0, isKa, isPr && sign < 0, isPr && sign > 0, isPr}; @@ -3064,18 +3037,16 @@ struct RadialFlowDecorr { bool isPi = (id == KPidPionOne); bool isKa = (id == KPidKaonTwo); bool isPr = (id == KPidProtonThree); - bool isAny = (isPi || isKa || isPr); // Only true if it passed PID! - bool isSpecies[KNsp] = { - isAny, + true, isPi && sign < 0, isPi && sign > 0, isPi, isKa && sign < 0, isKa && sign > 0, isKa, isPr && sign < 0, isPr && sign > 0, isPr}; + fillNSigmaAftCut(track, cent, isSpecies); for (int isp = 0; isp < KNsp; ++isp) { if (!isSpecies[isp]) continue; - fillNSigmaAftCut(track, cent, isSpecies); float eff = getEfficiency(coll.multNTracksPV(), pt, eta, static_cast(isp), 0, cfgEff); if (eff <= KFloatEpsilon) continue; @@ -3192,10 +3163,8 @@ struct RadialFlowDecorr { bool isPi = (id == KPidPionOne); bool isKa = (id == KPidKaonTwo); bool isPr = (id == KPidProtonThree); - bool isAny = (isPi || isKa || isPr); // Only true if it passed PID! - bool isSpecies[KNsp] = { - isAny, + true, isPi && sign < 0, isPi && sign > 0, isPi, isKa && sign < 0, isKa && sign > 0, isKa, isPr && sign < 0, isPr && sign > 0, isPr}; @@ -3204,8 +3173,6 @@ struct RadialFlowDecorr { if (!isSpecies[isp]) continue; float eff = getEfficiency(coll.multNTracksPV(), pt, eta, static_cast(isp), 0, cfgEff); - - // Safety check BEFORE dividing if (eff <= KFloatEpsilon) continue; @@ -3268,16 +3235,20 @@ struct RadialFlowDecorr { } for (int isp = 0; isp < KNsp; ++isp) { + if (sumWi[isp][0] < 1.0f) + continue; histos.fill(HIST("Prof_Cent_Nsp_Nchrec"), cent, isp, sumWi[isp][0]); histos.fill(HIST("Prof_Mult_Nsp_Nchrec"), coll.multNTracksPV(), isp, sumWi[isp][0]); - if (sumWi[isp][0] > 1.0f) - histos.fill(HIST("Prof_Cent_Nsp_MeanpT"), cent, isp, sumWipti[isp][0] / sumWi[isp][0]); + histos.fill(HIST("Prof_Cent_Nsp_MeanpT"), cent, isp, sumWipti[isp][0] / sumWi[isp][0]); histos.fill(HIST("Prof_Mult_Nsp_MeanpT"), coll.multNTracksPV(), isp, sumWipti[isp][0] / sumWi[isp][0]); } for (int ietaA = 0; ietaA < KNEta; ++ietaA) { for (int ietaC = 0; ietaC < KNEta; ++ietaC) { for (int isp = 0; isp < KNsp; ++isp) { + if ((sumWi[isp][ietaA] < 1.0f) || (sumWi[isp][ietaC] < 1.0f)) + continue; + double wCorrAB = sumWi[isp][ietaA] + sumWi[isp][ietaC]; if (wCorrAB > 0) { float mptsub = (sumWipti[isp][ietaA] + sumWipti[isp][ietaC]) / wCorrAB; @@ -3314,7 +3285,6 @@ struct RadialFlowDecorr { } } } - double amplFT0A = 0, amplFT0C = 0; if (coll.has_foundFT0()) { const auto& ft0 = coll.foundFT0(); @@ -3402,10 +3372,8 @@ struct RadialFlowDecorr { bool isPi = (id == KPidPionOne); bool isKa = (id == KPidKaonTwo); bool isPr = (id == KPidProtonThree); - bool isAny = (isPi || isKa || isPr); // Only true if it passed PID! - bool isSpecies[KNsp] = { - isAny, + true, isPi && sign < 0, isPi && sign > 0, isPi, isKa && sign < 0, isKa && sign > 0, isKa, isPr && sign < 0, isPr && sign > 0, isPr}; @@ -3414,8 +3382,6 @@ struct RadialFlowDecorr { if (!isSpecies[isp]) continue; float eff = getEfficiency(coll.multNTracksPV(), pt, eta, static_cast(isp), 0, cfgEff); - - // Safety check BEFORE dividing if (eff <= KFloatEpsilon) continue; @@ -3535,7 +3501,6 @@ struct RadialFlowDecorr { float covFT0A = p1kBarFt0A * p1kBar[isp][ietaC]; float covFT0C = p1kBarFt0C * p1kBar[isp][ietaA]; - // Updated enum checks here if (isp == kInclusiveIdx) { if (std::isfinite(c2Sub)) { histos.fill(HIST("Prof_C2Sub2D_Cent_etaA_etaC"), cent, etaValA, etaValB, c2Sub); From afa05ac9203ee7b1be02785ef422ff47a59b2324 Mon Sep 17 00:00:00 2001 From: mapalhares <165794118+mapalhares@users.noreply.github.com> Date: Wed, 11 Mar 2026 21:12:41 +0100 Subject: [PATCH 254/347] [PWGLF/NuSpEx] Changed track selection: nTPCClus -> ntpcNClsCrossedRows and fix EvtSel (#15345) Co-authored-by: ALICE Action Bot --- PWGLF/TableProducer/Nuspex/lnnRecoTask.cxx | 131 +++++++++++---------- 1 file changed, 69 insertions(+), 62 deletions(-) diff --git a/PWGLF/TableProducer/Nuspex/lnnRecoTask.cxx b/PWGLF/TableProducer/Nuspex/lnnRecoTask.cxx index 5f7de80eff7..4e8d5fb205e 100644 --- a/PWGLF/TableProducer/Nuspex/lnnRecoTask.cxx +++ b/PWGLF/TableProducer/Nuspex/lnnRecoTask.cxx @@ -87,6 +87,8 @@ std::shared_ptr h2FT0CnClusTPCtoTrBfSel; std::shared_ptr h2FT0CnClusTPCtoPiBfSel; std::shared_ptr h2FT0Cchi2NClTPCtoTrBfSel; std::shared_ptr h2FT0Cchi2NClITStoTrBfSel; +std::shared_ptr h2FT0CnTPCNClsCrossedRows3HBfSel; +std::shared_ptr h2FT0CnTPCNClsCrossedRowsPiBfSel; // QA ITS-TPC and ITS-TPC-TOF track signals std::shared_ptr h2FT0CptTrBfSelItsTpc; std::shared_ptr h2FT0CptTrBfSelItsTpcTof; @@ -101,14 +103,9 @@ std::shared_ptr hPtTrkItsTpcTofTrStr; std::shared_ptr hPtItsTpcPiStr; std::shared_ptr hPtTrkItsTpcPiStr; // QA reco generated candidate and daugher particles from secondary vertex -std::shared_ptr h2FT0CPtGenColRecoGenCandMC; -std::shared_ptr h2FT0CPtGenColRecoGenTrStrMC; -std::shared_ptr h2FT0CPtGenColRecoGenPiStrMC; -std::shared_ptr h2FT0CPtRecColRecoGenCandMC; -std::shared_ptr h2FT0CPtRecColRecoGenTrStrMC; -std::shared_ptr h2FT0CPtRecColRecoGenPiStrMC; -std::shared_ptr h2FT0CPtRecColRecoTrStrMC; -std::shared_ptr h2FT0CPtRecColRecoPiStrMC; +std::shared_ptr h2FT0CPtGenColRecCandMC; +std::shared_ptr h2FT0CPtGenColRecTrStrMC; +std::shared_ptr h2FT0CPtGenColRecPiStrMC; // QA signal generated candidate and daugher particles from secondary vertex std::shared_ptr h2FT0CPtGenColGenCandMC; std::shared_ptr h2FT0CPtGenColGenTrStrMC; @@ -200,13 +197,16 @@ struct lnnRecoTask { Configurable tpcRigidityMin3H{"tpcRigidityMin3H", 0.2, "Minimum rigidity of the triton candidate"}; Configurable nSigmaCutMinTPC{"nSigmaCutMinTPC", -5, "triton dEdx cut (n sigma)"}; Configurable nSigmaCutMaxTPC{"nSigmaCutMaxTPC", 5, "triton dEdx cut (n sigma)"}; + Configurable nTPCNClsCrossedRows3H{"nTPCNClsCrossedRows3H", 80, "Number of crossed TPC Rows for triton"}; + Configurable nTPCNClsCrossedRowsPi{"nTPCNClsCrossedRowsPi", 80, "Number of crossed TPC Rows for pions"}; Configurable nTPCClusMin3H{"nTPCClusMin3H", 80, "triton NTPC clusters cut"}; Configurable nTPCClusMinPi{"nTPCClusMinPi", 60, "pion NTPC clusters cut"}; Configurable ptMinTOF{"ptMinTOF", 0.8, "minimum pt for TOF cut"}; Configurable trTOFMass2Cut{"trTOFMass2Cut", 5.5, "minimum Triton mass square to TOF"}; Configurable betaTrTOF{"betaTrTOF", 0.4, "minimum beta TOF cut"}; Configurable mcSignalOnly{"mcSignalOnly", true, "If true, save only signal in MC"}; - Configurable doTrackQA{"doTrackQA", true, "If true, compute the QA studies beased on detectors (ITS-TPC-TOF) signals"}; + Configurable doTrackQA{"doTrackQA", true, "if true, compute the QA studies beased on detectors (ITS-TPC-TOF) signals"}; + Configurable useNoSameBunchPileup{"useNoSameBunchPileup", false, "reject collisions in case of pileup with another collision in the same foundBC"}; // Define o2 fitter, 2-prong, active memory (no need to redefine per event) o2::vertexing::DCAFitterN<2> fitter; @@ -247,6 +247,7 @@ struct lnnRecoTask { ConfigurableAxis betaBins{"betaBins", {550, 0.f, 1.1f}, "Binning for Beta"}; ConfigurableAxis dcaXYBins{"dcaXYBins", {550, -5.f, 5.f}, "Binning for dcaXY triton"}; ConfigurableAxis tpcNClusBins{"tpcNClusBins", {260, 30, 165}, "Binning for nClusTPC"}; + ConfigurableAxis tpcNClsCrossedRowsBins{"TPCNClsCrossedRowsBins", {260, 30, 165}, "Binning for TPCNClsCrossedRows"}; ConfigurableAxis tpcChi2NClusBins{"tpcChi2NClusBins", {20, 0.5, 10}, "Binning for chi2NClusTPC"}; ConfigurableAxis itsChi2NClusBins{"itsChi2NClusBins", {72, 0, 36}, "Binning for chi2NClusTPC"}; ConfigurableAxis candPtBins{"candPtBins", {160, 0, 8}, "Binning for lnn cand pt"}; @@ -302,6 +303,7 @@ struct lnnRecoTask { const AxisSpec betaAxis{betaBins, "#beta_{TOF}"}; const AxisSpec dcaXYAxis(dcaXYBins, "DCA_{xy} ({}^{3}H (cm)"); const AxisSpec tpcNClusAxis(tpcNClusBins, "N_{clus}^{TPC}"); + const AxisSpec tpcNClsCrossedRowsAxis(tpcNClsCrossedRowsBins, "N_{TPC} crossed rows"); const AxisSpec tpcChi2NClusAxis(tpcChi2NClusBins, "{#Chi}^{2}/N_{clus}^{TPC}"); const AxisSpec itsChi2NClusAxis(itsChi2NClusBins, "{#Chi}^{2}/N_{clus}^{ITS}"); const AxisSpec candPtAxis(candPtBins, "#it{p}_{T} (Gev/#it{c})"); @@ -315,16 +317,18 @@ struct lnnRecoTask { hdEdxTot = qaRegistry.add("hdEdxTot", ";p_{TPC}/z (GeV/#it{c}); dE/dx", HistType::kTH2F, {rigidityAxis, dEdxAxis}); h3HMassPtTOF = qaRegistry.add("PID/hTrMassPtTOF", "; #it{p}_{T} ({}^{3}H) (GeV/#it{c}); #frac{m^{2}}{z^{2}} (GeV^{2}/#it{c}^{4})", HistType::kTH2F, {tPtAxis, mTOFAxis}); h3HSignalPtTOF = qaRegistry.add("PID/h3HSignalPtTOF", "; #it{p}_{T}({}^{3}H) (GeV/#it{c}); #beta_{TOF}", HistType::kTH2F, {tPtAxis, betaAxis}); - hEvents = qaRegistry.add("hEvents", ";Events; ", HistType::kTH1D, {{3, -0.5, 2.5}}); + hEvents = qaRegistry.add("hEvents", ";Events; ", HistType::kTH1D, {{4, -0.5, 3.5}}); hLnnCandLoss = qaRegistry.add("CandCounts/hLnnCandLoss", ";CandLoss; ", HistType::kTH1D, {{7, -0.5, 6.5}}); // QA its-tpc and its-tpc-tof tracks before selection h2FT0CnClusTPCtoTrBfSel = qaRegistry.add("QATracks/h2FT0CnClusTPCtoTrBfSel", ";FT0C (%);N_{clus}^{TPC}", HistType::kTH2F, {centAxis, tpcNClusAxis}); h2FT0CnClusTPCtoPiBfSel = qaRegistry.add("QATracks/h2FT0CnClusTPCtoPiBfSel", ";FT0C (%);N_{clus}^{TPC}", HistType::kTH2F, {centAxis, tpcNClusAxis}); h2FT0Cchi2NClTPCtoTrBfSel = qaRegistry.add("QATracks/h2FT0Cchi2NClTPCtoTrBfSel", ";FT0C (%);{#Chi}^{2}/N_{clus}^{TPC} ", HistType::kTH2F, {centAxis, tpcChi2NClusAxis}); h2FT0Cchi2NClITStoTrBfSel = qaRegistry.add("QATracks/h2FT0Cchi2NClITStoTrBfSel", ";FT0C (%);{#Chi}^{2}/N_{clus}^{ITS}", HistType::kTH2F, {centAxis, itsChi2NClusAxis}); - h2FT0CptTrBfSelItsTpc = qaRegistry.add("QATracks/h2FT0CptTrBfSelItsTpc", "; #it{p}_{T}({}^{3}H) (GeV/#it{c}); #beta_{TOF}", HistType::kTH2F, {centAxis, candPtBins}); - h2FT0CptTrBfSelItsTpcTof = qaRegistry.add("QATracks/h2FT0CptTrBfSelItsTpcTof", "; #it{p}_{T}({}^{3}H) (GeV/#it{c}); #beta_{TOF}", HistType::kTH2F, {centAxis, candPtBins}); - h2FT0CptPiBfSelItsTpc = qaRegistry.add("QATracks/h2FT0CptPiBfSelItsTpc", "; #it{p}_{T}({}^{3}H) (GeV/#it{c}); #beta_{TOF}", HistType::kTH2F, {centAxis, candPtBins}); + h2FT0CnTPCNClsCrossedRows3HBfSel = qaRegistry.add("QATracks/h2FT0CnTPCNClsCrossedRows3H", ";FT0C (%);N_{TPC} crossed rows", HistType::kTH2F, {centAxis, tpcNClsCrossedRowsAxis}); + h2FT0CnTPCNClsCrossedRowsPiBfSel = qaRegistry.add("QATracks/h2FT0CnTPCNClsCrossedRowsPi", ";FT0C (%);N_{TPC} crossed rows", HistType::kTH2F, {centAxis, tpcNClsCrossedRowsAxis}); + h2FT0CptTrBfSelItsTpc = qaRegistry.add("QATracks/h2FT0CptTrBfSelItsTpc", ";FT0C (%);#it{p}_{T}", HistType::kTH2F, {centAxis, candPtBins}); + h2FT0CptTrBfSelItsTpcTof = qaRegistry.add("QATracks/h2FT0CptTrBfSelItsTpcTof", ";FT0C (%);#it{p}_{T}", HistType::kTH2F, {centAxis, candPtBins}); + h2FT0CptPiBfSelItsTpc = qaRegistry.add("QATracks/h2FT0CptPiBfSelItsTpc", ";FT0C (%);#it{p}_{T}", HistType::kTH2F, {centAxis, candPtBins}); // QA its-tpc, its-tpc-tof, and generated MC hPtItsTpcTrStr = qaRegistry.add("MC/McTracks/hPtItsTpcTrStr", ";FT0C (%);#it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {{10, 0, 100}, {160, 0, 8}}); hPtTrkItsTpcTrStr = qaRegistry.add("MC/McTracks/hPtTrkItsTpcTrStr", ";FT0C (%);#it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {{10, 0, 100}, {160, 0, 8}}); @@ -338,6 +342,7 @@ struct lnnRecoTask { hEvents->GetXaxis()->SetBinLabel(1, "All"); hEvents->GetXaxis()->SetBinLabel(2, "sel8"); hEvents->GetXaxis()->SetBinLabel(3, "z_{vtx}"); + hEvents->GetXaxis()->SetBinLabel(4, "NoSameBunchPileUp"); hLnnCandLoss->GetYaxis()->SetTitle("#it{N}_{cand}"); hLnnCandLoss->GetXaxis()->SetTitle("Cuts"); hLnnCandLoss->GetXaxis()->SetBinLabel(1, "Initial"); @@ -349,19 +354,15 @@ struct lnnRecoTask { hLnnCandLoss->GetXaxis()->SetBinLabel(7, "cosPA"); if (doprocessMC) { hDecayChannel = qaRegistry.add("MC/hDecayChannel", ";Decay channel; ", HistType::kTH1D, {{2, -0.5, 1.5}}); - hDecayChannel->GetXaxis()->SetBinLabel(1, "2-body"); + hDecayChannel->GetXaxis()->SetBinLabel(1, "All"); + hDecayChannel->GetXaxis()->SetBinLabel(2, "2-body"); hIsMatterGen = qaRegistry.add("MC/hIsMatterGen", ";; ", HistType::kTH1D, {{2, -0.5, 1.5}}); hIsMatterGen->GetXaxis()->SetBinLabel(1, "Matter"); hIsMatterGen->GetXaxis()->SetBinLabel(2, "Antimatter"); // QA for generated mother candidate and daughter particles - h2FT0CPtGenColRecoGenCandMC = qaRegistry.add("MC/QARecoGenSV/h2FT0CPtGenColRecoGenCandMC", ";FT0C (%);#it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {centAxis, candPtAxis}); - h2FT0CPtGenColRecoGenTrStrMC = qaRegistry.add("MC/QARecoGenSV/h2FT0CPtGenColRecoGenTrStrMC", ";FT0C (%);#it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {centAxis, candPtAxis}); - h2FT0CPtGenColRecoGenPiStrMC = qaRegistry.add("MC/QARecoGenSV/h2FT0CPtGenColRecoGenPiStrMC", ";FT0C (%);#it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {centAxis, candPtAxis}); - h2FT0CPtRecColRecoGenCandMC = qaRegistry.add("MC/QARecoGenSV/h2FT0CPtRecColRecoGenCandMC", ";FT0C (%);#it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {centAxis, candPtAxis}); - h2FT0CPtRecColRecoGenTrStrMC = qaRegistry.add("MC/QARecoGenSV/h2FT0CPtRecColRecoGenTrStrMC", ";FT0C (%);#it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {centAxis, candPtAxis}); - h2FT0CPtRecColRecoGenPiStrMC = qaRegistry.add("MC/QARecoGenSV/h2FT0CPtRecColRecoGenPiStrMC", ";FT0C (%);#it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {centAxis, candPtAxis}); - h2FT0CPtRecColRecoTrStrMC = qaRegistry.add("MC/QARecoGenSV/h2FT0CPtRecColRecoTrStrMC", ";FT0C (%);#it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {centAxis, candPtAxis}); - h2FT0CPtRecColRecoPiStrMC = qaRegistry.add("MC/QARecoGenSV/h2FT0CPtRecColRecoPiStrMC", ";FT0C (%);#it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {centAxis, candPtAxis}); + h2FT0CPtGenColRecCandMC = qaRegistry.add("MC/RecMcCol/h2FT0CPtGenColRecCandMC", ";FT0C (%);#it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {centAxis, candPtAxis}); + h2FT0CPtGenColRecTrStrMC = qaRegistry.add("MC/RecMcCol/h2FT0CPtGenColRecTrStrMC", ";FT0C (%);#it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {centAxis, candPtAxis}); + h2FT0CPtGenColRecPiStrMC = qaRegistry.add("MC/RecMcCol/h2FT0CPtGenColRecPiStrMC", ";FT0C (%);#it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {centAxis, candPtAxis}); // QA signal generated candidate and daugher particles from secondary vertex h2FT0CPtGenColGenCandMC = qaRegistry.add("MC/QASignalGenSV/h2FT0CPtGenColGenCandMC", ";FT0C (%);#it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {centAxis, candPtAxis}); h2FT0CPtGenColGenTrStrMC = qaRegistry.add("MC/QASignalGenSV/h2FT0CPtGenColGenTrStrMC", ";FT0C (%);#it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {centAxis, candPtAxis}); @@ -484,6 +485,8 @@ struct lnnRecoTask { // fill QA track histogram studies to check track signal before selections h2FT0CnClusTPCtoTrBfSel->Fill(collision.centFT0C(), h3track.tpcNClsFound()); h2FT0CnClusTPCtoPiBfSel->Fill(collision.centFT0C(), pitrack.tpcNClsFound()); + h2FT0CnTPCNClsCrossedRows3HBfSel->Fill(collision.centFT0C(), h3track.tpcNClsCrossedRows()); + h2FT0CnTPCNClsCrossedRowsPiBfSel->Fill(collision.centFT0C(), pitrack.tpcNClsCrossedRows()); h2FT0Cchi2NClTPCtoTrBfSel->Fill(collision.centFT0C(), h3track.tpcChi2NCl()); h2FT0Cchi2NClITStoTrBfSel->Fill(collision.centFT0C(), h3track.itsChi2NCl()); @@ -503,11 +506,11 @@ struct lnnRecoTask { } if (h3Rigidity < tpcRigidityMin3H || - h3track.tpcNClsFound() < nTPCClusMin3H || + h3track.tpcNClsCrossedRows() < nTPCNClsCrossedRows3H || h3track.tpcChi2NCl() < chi2nClusTPCMin || h3track.tpcChi2NCl() > chi2nClusTPCMax || h3track.itsChi2NCl() > chi2nClusITS || - pitrack.tpcNClsFound() < nTPCClusMinPi) { + pitrack.tpcNClsCrossedRows() < nTPCNClsCrossedRowsPi) { continue; } @@ -697,32 +700,31 @@ struct lnnRecoTask { if (!mcPart.has_mothers()) return false; - bool motherIsAccepted = true; + if (mcPart.getProcess() != 4) + return false; + + bool motherIsAccepted = false; auto mothers = mcPart.mothers_as(); for (const auto& mother : mothers) { - if (mcPart.getProcess() == 4) { - motherIsAccepted = false; - // só aceita se a mãe for um Lnn - if (std::abs(mother.pdgCode()) == lnnPdg) { - motherIsAccepted = true; - } + if (std::abs(mother.pdgCode()) == lnnPdg) { + motherIsAccepted = true; + break; } } return motherIsAccepted; } template - void fillMcHistograms(TracksFullMC::iterator const& mcTrack, aod::McParticles::iterator const& mc, bool motherIsAccepted, Tcoll const& collision) + void fillMcHistograms(TracksFullMC::iterator const& mcTrack, aod::McParticles::iterator const& mc, Tcoll const& collision) { bool passedTrackITS = mcTrack.hasITS(); bool passedTrackTPC = mcTrack.hasTPC(); bool passedTrackTOF = mcTrack.hasTOF(); - if (!motherIsAccepted) - return; + int pdg = std::abs(mc.pdgCode()); - if (std::abs(mc.pdgCode()) == h3DauPdg) { + if (pdg == h3DauPdg) { hPtGeneratedTrStr->Fill(collision.centFT0C(), mc.pt()); if (passedTrackITS && passedTrackTPC) { @@ -735,7 +737,7 @@ struct lnnRecoTask { } } - if (std::abs(mc.pdgCode()) == piDauPdg) { + if (pdg == piDauPdg) { hPtGeneratedPiStr->Fill(collision.centFT0C(), mc.pt()); if (passedTrackITS && passedTrackTPC) { hPtItsTpcPiStr->Fill(collision.centFT0C(), mc.pt()); @@ -761,6 +763,10 @@ struct lnnRecoTask { continue; } hEvents->Fill(2.); + if (useNoSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + continue; + } + hEvents->Fill(3.); hZvtx->Fill(collision.posZ()); hCentFT0A->Fill(collision.centFT0A()); @@ -809,9 +815,11 @@ struct lnnRecoTask { continue; auto mc = trackMC.mcParticle(); - bool motherIsAccepted = isLnnDecay(mc); - fillMcHistograms(trackMC, mc, motherIsAccepted, collision); + if (!isLnnDecay(mc)) + continue; + + fillMcHistograms(trackMC, mc, collision); } lnnCandidates.clear(); @@ -822,6 +830,7 @@ struct lnnRecoTask { if (collision.has_mcCollision()) { recoCollisionIds[collision.mcCollisionId()] = collision.globalIndex(); } + if ((!collision.sel8())) { continue; } @@ -830,6 +839,10 @@ struct lnnRecoTask { continue; } hEvents->Fill(2.); + if (useNoSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + continue; + } + hEvents->Fill(3.); hZvtx->Fill(collision.posZ()); hCentFT0A->Fill(collision.centFT0A()); @@ -854,19 +867,10 @@ struct lnnRecoTask { continue; } int chargeFactor = -1 + 2 * (lnnCand.pdgCode > 0); - - // Fill 2D map for generated daughter particles which the mother candidate is reconstructed - h2FT0CPtGenColRecoGenCandMC->Fill(collision.centFT0C(), chargeFactor * lnnCand.genPt()); - h2FT0CPtGenColRecoGenTrStrMC->Fill(collision.centFT0C(), chargeFactor * lnnCand.genPt3H()); - h2FT0CPtGenColRecoGenPiStrMC->Fill(collision.centFT0C(), chargeFactor * lnnCand.genPtPi()); - if (lnnCand.recoMcColl) { - h2FT0CPtRecColRecoGenCandMC->Fill(collision.centFT0C(), chargeFactor * lnnCand.genPt()); - h2FT0CPtRecColRecoGenTrStrMC->Fill(collision.centFT0C(), chargeFactor * lnnCand.genPt3H()); - h2FT0CPtRecColRecoGenPiStrMC->Fill(collision.centFT0C(), chargeFactor * lnnCand.genPtPi()); - if (lnnCand.isReco && lnnCand.survEvSelection) { - h2FT0CPtRecColRecoTrStrMC->Fill(collision.centFT0C(), chargeFactor * lnnCand.recoPt3H()); - h2FT0CPtRecColRecoPiStrMC->Fill(collision.centFT0C(), chargeFactor * lnnCand.recoPtPi()); - } + if (lnnCand.recoMcColl && lnnCand.survEvSelection) { + h2FT0CPtGenColRecCandMC->Fill(collision.centFT0C(), chargeFactor * lnnCand.genPt()); + h2FT0CPtGenColRecTrStrMC->Fill(collision.centFT0C(), chargeFactor * lnnCand.genPt3H()); + h2FT0CPtGenColRecPiStrMC->Fill(collision.centFT0C(), chargeFactor * lnnCand.genPtPi()); } outputMCTable(collision.centFT0A(), collision.centFT0C(), collision.centFT0M(), collision.posX(), collision.posY(), collision.posZ(), @@ -890,6 +894,9 @@ struct lnnRecoTask { continue; } float cent = collisionFT0Ccent[mcPart.mcCollisionId()]; + + h2FT0CPtGenColGenCandMC->Fill(cent, mcPart.pt()); + constexpr std::size_t kVtxDim = 3; std::array secVtx; std::array primVtx = {mcPart.vx(), mcPart.vy(), mcPart.vz()}; @@ -902,14 +909,17 @@ struct lnnRecoTask { bool is3HFound = false; for (const auto& mcDaught : mcPart.daughters_as()) { - if (std::abs(mcDaught.pdgCode()) == h3DauPdg) { + int pdg = std::abs(mcDaught.pdgCode()); + + if (pdg == h3DauPdg) { secVtx = {mcDaught.vx(), mcDaught.vy(), mcDaught.vz()}; mom3H = mcDaught.pVector(); + h2FT0CPtGenColGenTrStrMC->Fill(cent, mcDaught.pt()); is3HFound = true; - break; } - if (std::abs(mcDaught.pdgCode()) == piDauPdg) { + if (pdg == piDauPdg) { momPi = mcDaught.pVector(); + h2FT0CPtGenColGenPiStrMC->Fill(cent, mcDaught.pt()); } } @@ -918,9 +928,9 @@ struct lnnRecoTask { } else { hIsMatterGen->Fill(1.); } + if (!is3HFound) { hDecayChannel->Fill(1.); - continue; } hDecayChannel->Fill(0.); if (std::find(filledMothers.begin(), filledMothers.end(), mcPart.globalIndex()) != std::end(filledMothers)) { @@ -941,18 +951,15 @@ struct lnnRecoTask { lnnCand.posTrackID = -1; lnnCand.negTrackID = -1; lnnCand.isSignal = true; - if (lnnCand.isSignal) { - h2FT0CPtGenColGenCandMC->Fill(cent, chargeFactor * lnnCand.genPt()); - h2FT0CPtGenColGenTrStrMC->Fill(cent, chargeFactor * lnnCand.genPt3H()); - h2FT0CPtGenColGenPiStrMC->Fill(cent, chargeFactor * lnnCand.genPtPi()); - } - float centFT0C = -1.; + float centFT0A = -1, centFT0C = -1, centFT0M = -1; if (lnnCand.recoMcColl) { auto recoCollision = collisions.rawIteratorAt(recoCollisionIds[mcPart.mcCollisionId()]); + centFT0A = recoCollision.centFT0A(); centFT0C = recoCollision.centFT0C(); + centFT0M = recoCollision.centFT0M(); } - outputMCTable(-1, centFT0C, -1, + outputMCTable(centFT0A, centFT0C, centFT0M, -1, -1, -1, 0, -1, -1, -1, From e5e358b1acafee0d97496ec7e1f1a2ebb98f0f4b Mon Sep 17 00:00:00 2001 From: "Cicero D. Muncinelli" <88810740+cmuncinelli@users.noreply.github.com> Date: Wed, 11 Mar 2026 17:33:46 -0300 Subject: [PATCH 255/347] [PWGLF] Fixing Unbound indices error (small fixes) (#15352) --- PWGLF/DataModel/lambdaJetPolarizationIons.h | 8 ++++---- .../Strangeness/lambdaJetPolarizationIons.cxx | 4 ++-- .../Strangeness/lambdaJetPolarizationIonsDerived.cxx | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/PWGLF/DataModel/lambdaJetPolarizationIons.h b/PWGLF/DataModel/lambdaJetPolarizationIons.h index fe1116ee525..faa06e78b22 100644 --- a/PWGLF/DataModel/lambdaJetPolarizationIons.h +++ b/PWGLF/DataModel/lambdaJetPolarizationIons.h @@ -88,7 +88,7 @@ DECLARE_SOA_DYNAMIC_COLUMN(LeadParticlePz, leadParticlePz, //! Leading particle [](float leadParticlePt, float leadParticleEta) -> float { return leadParticlePt * std::sinh(leadParticleEta); }); } // namespace lambdajetpol -DECLARE_SOA_TABLE(RingCollisions, "AOD", "RINGCOLLISIONS", +DECLARE_SOA_TABLE(RingCollisions, "AOD", "RINGCOLLISION", o2::soa::Index<>, // self-index: auto-assigned row number lambdajetpol::CentFT0M, lambdajetpol::CentFT0C, @@ -99,7 +99,7 @@ namespace lambdajetpol DECLARE_SOA_INDEX_COLUMN(RingCollision, ringCollision); // Declare index after table is available } // namespace lambdajetpol -DECLARE_SOA_TABLE(RingJets, "AOD", "RINGJETS", +DECLARE_SOA_TABLE(RingJets, "AOD", "RINGJET", lambdajetpol::RingCollisionId, // relational index -> RingCollisions lambdajetpol::JetPt, lambdajetpol::JetEta, @@ -110,7 +110,7 @@ DECLARE_SOA_TABLE(RingJets, "AOD", "RINGJETS", lambdajetpol::JetPy, lambdajetpol::JetPz); -DECLARE_SOA_TABLE(RingLeadP, "AOD", "RINGLEADP", +DECLARE_SOA_TABLE(RingLeadPs, "AOD", "RINGLEADP", lambdajetpol::RingCollisionId, lambdajetpol::LeadParticlePt, lambdajetpol::LeadParticleEta, @@ -120,7 +120,7 @@ DECLARE_SOA_TABLE(RingLeadP, "AOD", "RINGLEADP", lambdajetpol::LeadParticlePy, lambdajetpol::LeadParticlePz); -DECLARE_SOA_TABLE(RingLaV0s, "AOD", "RINGLAV0S", +DECLARE_SOA_TABLE(RingLaV0s, "AOD", "RINGLAV0", lambdajetpol::RingCollisionId, lambdajetpol::V0Pt, lambdajetpol::V0Eta, diff --git a/PWGLF/TableProducer/Strangeness/lambdaJetPolarizationIons.cxx b/PWGLF/TableProducer/Strangeness/lambdaJetPolarizationIons.cxx index 7359008febf..0ed6559e140 100644 --- a/PWGLF/TableProducer/Strangeness/lambdaJetPolarizationIons.cxx +++ b/PWGLF/TableProducer/Strangeness/lambdaJetPolarizationIons.cxx @@ -156,7 +156,7 @@ struct lambdajetpolarizationions { // } products; Produces tableV0s; Produces tableJets; - Produces tableLeadParticles; + Produces tableLeadParticles; Produces tableCollisions; // Define histogram registries: @@ -274,7 +274,7 @@ struct lambdajetpolarizationions { Configurable phiHighCut{"phiHighCut", "0.1/x+pi/18.0+0.06", "High azimuth cut parametrisation"}; // PID (TPC/TOF) - Configurable tpcPidNsigmaCut{"tpcPidNsigmaCut", 3, "tpcPidNsigmaCut"}; // Default is 5. Reduced to agree with strangenessInJetsIons + Configurable tpcPidNsigmaCut{"tpcPidNsigmaCut", 4, "tpcPidNsigmaCut"}; // Default is 5 Configurable tofPidNsigmaCutLaPr{"tofPidNsigmaCutLaPr", 1e+6, "tofPidNsigmaCutLaPr"}; Configurable tofPidNsigmaCutLaPi{"tofPidNsigmaCutLaPi", 1e+6, "tofPidNsigmaCutLaPi"}; diff --git a/PWGLF/Tasks/Strangeness/lambdaJetPolarizationIonsDerived.cxx b/PWGLF/Tasks/Strangeness/lambdaJetPolarizationIonsDerived.cxx index 1681867e98b..dcf28b07b7f 100644 --- a/PWGLF/Tasks/Strangeness/lambdaJetPolarizationIonsDerived.cxx +++ b/PWGLF/Tasks/Strangeness/lambdaJetPolarizationIonsDerived.cxx @@ -432,9 +432,9 @@ struct lambdajetpolarizationionsderived { // (TODO: test using custom grouping) Preslice perColJets = o2::aod::lambdajetpol::ringCollisionId; Preslice perColV0s = o2::aod::lambdajetpol::ringCollisionId; - Preslice perColLeadPs = o2::aod::lambdajetpol::ringCollisionId; + Preslice perColLeadPs = o2::aod::lambdajetpol::ringCollisionId; void processPolarizationData(o2::aod::RingCollisions const& collisions, o2::aod::RingJets const& jets, o2::aod::RingLaV0s const& v0s, - o2::aod::RingLeadP const& leadPs) + o2::aod::RingLeadPs const& leadPs) { for (auto const& collision : collisions) { const auto collId = collision.globalIndex(); // The self-index accessor From 679382d3af224e70c945e4ea985dcad499d8b10c Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Wed, 11 Mar 2026 22:26:46 +0100 Subject: [PATCH 256/347] [PWGEM/Dilepton] remove unnecessary headers (#15350) Co-authored-by: ALICE Action Bot --- PWGEM/Dilepton/Core/DielectronCut.h | 11 +++--- PWGEM/Dilepton/Core/Dilepton.h | 34 ++---------------- PWGEM/Dilepton/Core/DileptonHadronMPC.h | 33 ++--------------- PWGEM/Dilepton/Core/DileptonMC.h | 34 ++---------------- PWGEM/Dilepton/Core/DileptonProducer.h | 4 +-- PWGEM/Dilepton/Core/SingleTrackQC.h | 35 ++----------------- PWGEM/Dilepton/Core/SingleTrackQCMC.h | 34 ++---------------- .../TableProducer/associateMCinfoDilepton.cxx | 24 ------------- .../TableProducer/prefilterDimuon.cxx | 5 --- .../TableProducer/skimmerPrimaryMFTTrack.cxx | 5 ++- .../TableProducer/skimmerPrimaryTrack.cxx | 11 ------ PWGEM/Dilepton/Tasks/CMakeLists.txt | 16 ++++----- PWGEM/Dilepton/Tasks/checkMCPairTemplate.cxx | 29 --------------- PWGEM/Dilepton/Tasks/dileptonPolarization.cxx | 12 ------- PWGEM/Dilepton/Tasks/evaluateAcceptance.cxx | 14 -------- PWGEM/Dilepton/Tasks/prefilterDielectron.cxx | 33 ----------------- PWGEM/Dilepton/Tasks/testBremsstrahlung.cxx | 2 -- 17 files changed, 29 insertions(+), 307 deletions(-) diff --git a/PWGEM/Dilepton/Core/DielectronCut.h b/PWGEM/Dilepton/Core/DielectronCut.h index c7f57bce7ca..654c9557095 100644 --- a/PWGEM/Dilepton/Core/DielectronCut.h +++ b/PWGEM/Dilepton/Core/DielectronCut.h @@ -17,7 +17,6 @@ #define PWGEM_DILEPTON_CORE_DIELECTRONCUT_H_ #include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" -#include "PWGEM/Dilepton/Utils/MlResponseDielectronSingleTrack.h" #include "PWGEM/Dilepton/Utils/PairUtilities.h" #include "CommonConstants/PhysicsConstants.h" @@ -547,10 +546,10 @@ class DielectronCut : public TNamed void IncludeITSsa(bool flag, float maxpt); void EnableTTCA(bool flag); - void SetPIDMlResponse(o2::analysis::MlResponseDielectronSingleTrack* mlResponse) - { - mPIDMlResponse = mlResponse; - } + // void SetPIDMlResponse(o2::analysis::MlResponseDielectronSingleTrack* mlResponse) + // { + // mPIDMlResponse = mlResponse; + // } void SetMLThresholds(const std::vector bins, const std::vector cuts) { @@ -646,7 +645,7 @@ class DielectronCut : public TNamed // float mMinP_ITSNsigmaKa{0.0}, mMaxP_ITSNsigmaKa{0.0}; // float mMinP_ITSNsigmaPr{0.0}, mMaxP_ITSNsigmaPr{0.0}; - o2::analysis::MlResponseDielectronSingleTrack* mPIDMlResponse{nullptr}; + // o2::analysis::MlResponseDielectronSingleTrack* mPIDMlResponse{nullptr}; std::vector mMLBins{}; // binning for a feature variable. e.g. tpcInnerParam std::vector mMLCuts{}; // threshold for each bin. mMLCuts.size() must be mMLBins.size()-1. diff --git a/PWGEM/Dilepton/Core/Dilepton.h b/PWGEM/Dilepton/Core/Dilepton.h index f8182eea7af..b1f5b3b3b46 100644 --- a/PWGEM/Dilepton/Core/Dilepton.h +++ b/PWGEM/Dilepton/Core/Dilepton.h @@ -26,14 +26,11 @@ #include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" #include "PWGEM/Dilepton/Utils/EventHistograms.h" #include "PWGEM/Dilepton/Utils/EventMixingHandler.h" -#include "PWGEM/Dilepton/Utils/MlResponseDielectronSingleTrack.h" #include "PWGEM/Dilepton/Utils/PairUtilities.h" #include "Common/CCDB/RCTSelectionFlags.h" #include "Common/Core/RecoDecay.h" #include "Common/Core/Zorro.h" -#include "Common/Core/trackUtilities.h" -#include "Tools/ML/MlResponse.h" #include "CCDB/BasicCCDBManager.h" #include "CommonConstants/LHCConstants.h" @@ -58,6 +55,7 @@ #include #include #include +#include #include #include @@ -241,8 +239,8 @@ struct Dilepton { // configuration for PID ML Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; Configurable> onnxPathsCCDB{"onnxPathsCCDB", std::vector{"path"}, "Paths of models on CCDB"}; - Configurable> binsMl{"binsMl", std::vector{-999999., 999999.}, "Bin limits for ML application"}; - Configurable> cutsMl{"cutsMl", std::vector{0.95}, "ML cuts per bin"}; + Configurable> binsMl{"binsMl", std::vector{0.1, 0.15, 0.2, 0.25, 0.4, 0.8, 1.6, 2.0, 20.f}, "Bin limits for ML application"}; + Configurable> cutsMl{"cutsMl", std::vector{0.98, 0.98, 0.9, 0.9, 0.95, 0.95, 0.8, 0.8}, "ML cuts per bin"}; Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"feature"}, "Names of ML model input features"}; Configurable nameBinningFeature{"nameBinningFeature", "pt", "Names of ML model binning feature"}; Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB. Exceptions: > 0 for the specific timestamp, 0 gets the run dependent timestamp"}; @@ -700,7 +698,6 @@ struct Dilepton { fEMEventCut.SetRequireGoodITSLayersAll(eventcuts.cfgRequireGoodITSLayersAll); } - o2::analysis::MlResponseDielectronSingleTrack mlResponseSingleTrack; void DefineDielectronCut() { fDielectronCut = DielectronCut("fDielectronCut", "fDielectronCut"); @@ -758,31 +755,6 @@ struct Dilepton { thresholdsML.emplace_back(dielectroncuts.cutsMl.value[i]); } fDielectronCut.SetMLThresholds(binsML, thresholdsML); - - // static constexpr int nClassesMl = 2; - // const std::vector cutDirMl = {o2::cuts_ml::CutNot, o2::cuts_ml::CutSmaller}; - // const std::vector labelsClasses = {"Background", "Signal"}; - // const uint32_t nBinsMl = dielectroncuts.binsMl.value.size() - 1; - // const std::vector labelsBins(nBinsMl, "bin"); - // double cutsMlArr[nBinsMl][nClassesMl]; - // for (uint32_t i = 0; i < nBinsMl; i++) { - // cutsMlArr[i][0] = 0.; - // cutsMlArr[i][1] = dielectroncuts.cutsMl.value[i]; - // } - // o2::framework::LabeledArray cutsMl = {cutsMlArr[0], nBinsMl, nClassesMl, labelsBins, labelsClasses}; - - // mlResponseSingleTrack.configure(dielectroncuts.binsMl.value, cutsMl, cutDirMl, nClassesMl); - // if (dielectroncuts.loadModelsFromCCDB) { - // ccdbApi.init(ccdburl); - // mlResponseSingleTrack.setModelPathsCCDB(dielectroncuts.onnxFileNames.value, ccdbApi, dielectroncuts.onnxPathsCCDB.value, dielectroncuts.timestampCCDB.value); - // } else { - // mlResponseSingleTrack.setModelPathsLocal(dielectroncuts.onnxFileNames.value); - // } - // mlResponseSingleTrack.cacheInputFeaturesIndices(dielectroncuts.namesInputFeatures); - // mlResponseSingleTrack.cacheBinningIndex(dielectroncuts.nameBinningFeature); - // mlResponseSingleTrack.init(dielectroncuts.enableOptimizations.value); - - // fDielectronCut.SetPIDMlResponse(&mlResponseSingleTrack); } // end of PID ML } diff --git a/PWGEM/Dilepton/Core/DileptonHadronMPC.h b/PWGEM/Dilepton/Core/DileptonHadronMPC.h index 2a6664e20b3..9973ebf0dc1 100644 --- a/PWGEM/Dilepton/Core/DileptonHadronMPC.h +++ b/PWGEM/Dilepton/Core/DileptonHadronMPC.h @@ -27,14 +27,11 @@ #include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" #include "PWGEM/Dilepton/Utils/EventHistograms.h" #include "PWGEM/Dilepton/Utils/EventMixingHandler.h" -#include "PWGEM/Dilepton/Utils/MlResponseDielectronSingleTrack.h" #include "PWGEM/Dilepton/Utils/PairUtilities.h" #include "Common/CCDB/RCTSelectionFlags.h" #include "Common/Core/RecoDecay.h" #include "Common/Core/Zorro.h" -#include "Common/Core/trackUtilities.h" -#include "Tools/ML/MlResponse.h" #include "CCDB/BasicCCDBManager.h" #include "CommonConstants/LHCConstants.h" @@ -228,8 +225,8 @@ struct DileptonHadronMPC { // configuration for PID ML Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; Configurable> onnxPathsCCDB{"onnxPathsCCDB", std::vector{"path"}, "Paths of models on CCDB"}; - Configurable> binsMl{"binsMl", std::vector{-999999., 999999.}, "Bin limits for ML application"}; - Configurable> cutsMl{"cutsMl", std::vector{0.95}, "ML cuts per bin"}; + Configurable> binsMl{"binsMl", std::vector{0.1, 0.15, 0.2, 0.25, 0.4, 0.8, 1.6, 2.0, 20.f}, "Bin limits for ML application"}; + Configurable> cutsMl{"cutsMl", std::vector{0.98, 0.98, 0.9, 0.9, 0.95, 0.95, 0.8, 0.8}, "ML cuts per bin"}; Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"feature"}, "Names of ML model input features"}; Configurable nameBinningFeature{"nameBinningFeature", "pt", "Names of ML model binning feature"}; Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB. Exceptions: > 0 for the specific timestamp, 0 gets the run dependent timestamp"}; @@ -589,7 +586,6 @@ struct DileptonHadronMPC { fEMEventCut.SetRequireGoodITSLayersAll(eventcuts.cfgRequireGoodITSLayersAll); } - o2::analysis::MlResponseDielectronSingleTrack mlResponseSingleTrack; void DefineDielectronCut() { fDielectronCut = DielectronCut("fDielectronCut", "fDielectronCut"); @@ -646,31 +642,6 @@ struct DileptonHadronMPC { thresholdsML.emplace_back(dielectroncuts.cutsMl.value[i]); } fDielectronCut.SetMLThresholds(binsML, thresholdsML); - - // static constexpr int nClassesMl = 2; - // const std::vector cutDirMl = {o2::cuts_ml::CutNot, o2::cuts_ml::CutSmaller}; - // const std::vector labelsClasses = {"Background", "Signal"}; - // const uint32_t nBinsMl = dielectroncuts.binsMl.value.size() - 1; - // const std::vector labelsBins(nBinsMl, "bin"); - // double cutsMlArr[nBinsMl][nClassesMl]; - // for (uint32_t i = 0; i < nBinsMl; i++) { - // cutsMlArr[i][0] = 0.; - // cutsMlArr[i][1] = dielectroncuts.cutsMl.value[i]; - // } - // o2::framework::LabeledArray cutsMl = {cutsMlArr[0], nBinsMl, nClassesMl, labelsBins, labelsClasses}; - - // mlResponseSingleTrack.configure(dielectroncuts.binsMl.value, cutsMl, cutDirMl, nClassesMl); - // if (dielectroncuts.loadModelsFromCCDB) { - // ccdbApi.init(ccdburl); - // mlResponseSingleTrack.setModelPathsCCDB(dielectroncuts.onnxFileNames.value, ccdbApi, dielectroncuts.onnxPathsCCDB.value, dielectroncuts.timestampCCDB.value); - // } else { - // mlResponseSingleTrack.setModelPathsLocal(dielectroncuts.onnxFileNames.value); - // } - // mlResponseSingleTrack.cacheInputFeaturesIndices(dielectroncuts.namesInputFeatures); - // mlResponseSingleTrack.cacheBinningIndex(dielectroncuts.nameBinningFeature); - // mlResponseSingleTrack.init(dielectroncuts.enableOptimizations.value); - - // fDielectronCut.SetPIDMlResponse(&mlResponseSingleTrack); } // end of PID ML } diff --git a/PWGEM/Dilepton/Core/DileptonMC.h b/PWGEM/Dilepton/Core/DileptonMC.h index d21392444fa..0c00de8bec5 100644 --- a/PWGEM/Dilepton/Core/DileptonMC.h +++ b/PWGEM/Dilepton/Core/DileptonMC.h @@ -24,13 +24,10 @@ #include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" #include "PWGEM/Dilepton/Utils/EventHistograms.h" #include "PWGEM/Dilepton/Utils/MCUtilities.h" -#include "PWGEM/Dilepton/Utils/MlResponseDielectronSingleTrack.h" #include "PWGEM/Dilepton/Utils/PairUtilities.h" #include "Common/CCDB/RCTSelectionFlags.h" #include "Common/Core/RecoDecay.h" -#include "Common/Core/trackUtilities.h" -#include "Tools/ML/MlResponse.h" #include "CCDB/BasicCCDBManager.h" #include "CommonConstants/LHCConstants.h" @@ -52,6 +49,7 @@ #include #include #include +#include #include #include @@ -243,8 +241,8 @@ struct DileptonMC { // configuration for PID ML Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; Configurable> onnxPathsCCDB{"onnxPathsCCDB", std::vector{"path"}, "Paths of models on CCDB"}; - Configurable> binsMl{"binsMl", std::vector{-999999., 999999.}, "Bin limits for ML application"}; - Configurable> cutsMl{"cutsMl", std::vector{0.95}, "ML cuts per bin"}; + Configurable> binsMl{"binsMl", std::vector{0.1, 0.15, 0.2, 0.25, 0.4, 0.8, 1.6, 2.0, 20.f}, "Bin limits for ML application"}; + Configurable> cutsMl{"cutsMl", std::vector{0.98, 0.98, 0.9, 0.9, 0.95, 0.95, 0.8, 0.8}, "ML cuts per bin"}; Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"feature"}, "Names of ML model input features"}; Configurable nameBinningFeature{"nameBinningFeature", "pt", "Names of ML model binning feature"}; Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB. Exceptions: > 0 for the specific timestamp, 0 gets the run dependent timestamp"}; @@ -708,7 +706,6 @@ struct DileptonMC { fEMEventCut.SetRequireGoodITSLayersAll(eventcuts.cfgRequireGoodITSLayersAll); } - o2::analysis::MlResponseDielectronSingleTrack mlResponseSingleTrack; void DefineDielectronCut() { fDielectronCut = DielectronCut("fDielectronCut", "fDielectronCut"); @@ -766,31 +763,6 @@ struct DileptonMC { thresholdsML.emplace_back(dielectroncuts.cutsMl.value[i]); } fDielectronCut.SetMLThresholds(binsML, thresholdsML); - - // static constexpr int nClassesMl = 2; - // const std::vector cutDirMl = {o2::cuts_ml::CutNot, o2::cuts_ml::CutSmaller}; - // const std::vector labelsClasses = {"Background", "Signal"}; - // const uint32_t nBinsMl = dielectroncuts.binsMl.value.size() - 1; - // const std::vector labelsBins(nBinsMl, "bin"); - // double cutsMlArr[nBinsMl][nClassesMl]; - // for (uint32_t i = 0; i < nBinsMl; i++) { - // cutsMlArr[i][0] = 0.; - // cutsMlArr[i][1] = dielectroncuts.cutsMl.value[i]; - // } - // o2::framework::LabeledArray cutsMl = {cutsMlArr[0], nBinsMl, nClassesMl, labelsBins, labelsClasses}; - - // mlResponseSingleTrack.configure(dielectroncuts.binsMl.value, cutsMl, cutDirMl, nClassesMl); - // if (dielectroncuts.loadModelsFromCCDB) { - // ccdbApi.init(ccdburl); - // mlResponseSingleTrack.setModelPathsCCDB(dielectroncuts.onnxFileNames.value, ccdbApi, dielectroncuts.onnxPathsCCDB.value, dielectroncuts.timestampCCDB.value); - // } else { - // mlResponseSingleTrack.setModelPathsLocal(dielectroncuts.onnxFileNames.value); - // } - // mlResponseSingleTrack.cacheInputFeaturesIndices(dielectroncuts.namesInputFeatures); - // mlResponseSingleTrack.cacheBinningIndex(dielectroncuts.nameBinningFeature); - // mlResponseSingleTrack.init(dielectroncuts.enableOptimizations.value); - - // fDielectronCut.SetPIDMlResponse(&mlResponseSingleTrack); } // end of PID ML } diff --git a/PWGEM/Dilepton/Core/DileptonProducer.h b/PWGEM/Dilepton/Core/DileptonProducer.h index 63ca7bd1eaa..69327c1b068 100644 --- a/PWGEM/Dilepton/Core/DileptonProducer.h +++ b/PWGEM/Dilepton/Core/DileptonProducer.h @@ -217,8 +217,8 @@ struct DileptonProducer { // configuration for PID ML Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; Configurable> onnxPathsCCDB{"onnxPathsCCDB", std::vector{"path"}, "Paths of models on CCDB"}; - Configurable> binsMl{"binsMl", std::vector{-999999., 999999.}, "Bin limits for ML application"}; - Configurable> cutsMl{"cutsMl", std::vector{0.95}, "ML cuts per bin"}; + Configurable> binsMl{"binsMl", std::vector{0.1, 0.15, 0.2, 0.25, 0.4, 0.8, 1.6, 2.0, 20.f}, "Bin limits for ML application"}; + Configurable> cutsMl{"cutsMl", std::vector{0.98, 0.98, 0.9, 0.9, 0.95, 0.95, 0.8, 0.8}, "ML cuts per bin"}; Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"feature"}, "Names of ML model input features"}; Configurable nameBinningFeature{"nameBinningFeature", "pt", "Names of ML model binning feature"}; Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB. Exceptions: > 0 for the specific timestamp, 0 gets the run dependent timestamp"}; diff --git a/PWGEM/Dilepton/Core/SingleTrackQC.h b/PWGEM/Dilepton/Core/SingleTrackQC.h index 64eb1e2ec5b..3aeb5f44893 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQC.h @@ -21,14 +21,10 @@ #include "PWGEM/Dilepton/Core/DimuonCut.h" #include "PWGEM/Dilepton/Core/EMEventCut.h" #include "PWGEM/Dilepton/DataModel/dileptonTables.h" -#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" #include "PWGEM/Dilepton/Utils/EventHistograms.h" -#include "PWGEM/Dilepton/Utils/MlResponseDielectronSingleTrack.h" -#include "PWGEM/Dilepton/Utils/PairUtilities.h" #include "Common/CCDB/RCTSelectionFlags.h" #include "Common/Core/Zorro.h" -#include "Tools/ML/MlResponse.h" #include "CCDB/BasicCCDBManager.h" #include "DataFormatsParameters/GRPMagField.h" @@ -52,7 +48,6 @@ using namespace o2::aod; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::soa; -using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; @@ -175,8 +170,8 @@ struct SingleTrackQC { // configuration for PID ML Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; Configurable> onnxPathsCCDB{"onnxPathsCCDB", std::vector{"path"}, "Paths of models on CCDB"}; - Configurable> binsMl{"binsMl", std::vector{-999999., 999999.}, "Bin limits for ML application"}; - Configurable> cutsMl{"cutsMl", std::vector{0.95}, "ML cuts per bin"}; + Configurable> binsMl{"binsMl", std::vector{0.1, 0.15, 0.2, 0.25, 0.4, 0.8, 1.6, 2.0, 20.f}, "Bin limits for ML application"}; + Configurable> cutsMl{"cutsMl", std::vector{0.98, 0.98, 0.9, 0.9, 0.95, 0.95, 0.8, 0.8}, "ML cuts per bin"}; Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"feature"}, "Names of ML model input features"}; Configurable nameBinningFeature{"nameBinningFeature", "pt", "Names of ML model binning feature"}; Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB. Exceptions: > 0 for the specific timestamp, 0 gets the run dependent timestamp"}; @@ -450,7 +445,6 @@ struct SingleTrackQC { fEMEventCut.SetRequireGoodITSLayersAll(eventcuts.cfgRequireGoodITSLayersAll); } - o2::analysis::MlResponseDielectronSingleTrack mlResponseSingleTrack; void DefineDielectronCut() { fDielectronCut = DielectronCut("fDielectronCut", "fDielectronCut"); @@ -497,31 +491,6 @@ struct SingleTrackQC { thresholdsML.emplace_back(dielectroncuts.cutsMl.value[i]); } fDielectronCut.SetMLThresholds(binsML, thresholdsML); - - // static constexpr int nClassesMl = 2; - // const std::vector cutDirMl = {o2::cuts_ml::CutNot, o2::cuts_ml::CutSmaller}; - // const std::vector labelsClasses = {"Background", "Signal"}; - // const uint32_t nBinsMl = dielectroncuts.binsMl.value.size() - 1; - // const std::vector labelsBins(nBinsMl, "bin"); - // double cutsMlArr[nBinsMl][nClassesMl]; - // for (uint32_t i = 0; i < nBinsMl; i++) { - // cutsMlArr[i][0] = 0.; - // cutsMlArr[i][1] = dielectroncuts.cutsMl.value[i]; - // } - // o2::framework::LabeledArray cutsMl = {cutsMlArr[0], nBinsMl, nClassesMl, labelsBins, labelsClasses}; - - // mlResponseSingleTrack.configure(dielectroncuts.binsMl.value, cutsMl, cutDirMl, nClassesMl); - // if (dielectroncuts.loadModelsFromCCDB) { - // ccdbApi.init(ccdburl); - // mlResponseSingleTrack.setModelPathsCCDB(dielectroncuts.onnxFileNames.value, ccdbApi, dielectroncuts.onnxPathsCCDB.value, dielectroncuts.timestampCCDB.value); - // } else { - // mlResponseSingleTrack.setModelPathsLocal(dielectroncuts.onnxFileNames.value); - // } - // mlResponseSingleTrack.cacheInputFeaturesIndices(dielectroncuts.namesInputFeatures); - // mlResponseSingleTrack.cacheBinningIndex(dielectroncuts.nameBinningFeature); - // mlResponseSingleTrack.init(dielectroncuts.enableOptimizations.value); - - // fDielectronCut.SetPIDMlResponse(&mlResponseSingleTrack); } // end of PID ML } diff --git a/PWGEM/Dilepton/Core/SingleTrackQCMC.h b/PWGEM/Dilepton/Core/SingleTrackQCMC.h index bde2c91649d..b000ee4ba28 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQCMC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQCMC.h @@ -21,14 +21,10 @@ #include "PWGEM/Dilepton/Core/DimuonCut.h" #include "PWGEM/Dilepton/Core/EMEventCut.h" #include "PWGEM/Dilepton/DataModel/dileptonTables.h" -#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" #include "PWGEM/Dilepton/Utils/EventHistograms.h" #include "PWGEM/Dilepton/Utils/MCUtilities.h" -#include "PWGEM/Dilepton/Utils/MlResponseDielectronSingleTrack.h" -#include "PWGEM/Dilepton/Utils/PairUtilities.h" #include "Common/CCDB/RCTSelectionFlags.h" -#include "Tools/ML/MlResponse.h" #include "CCDB/BasicCCDBManager.h" #include "DataFormatsParameters/GRPMagField.h" @@ -186,8 +182,8 @@ struct SingleTrackQCMC { // configuration for PID ML Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; Configurable> onnxPathsCCDB{"onnxPathsCCDB", std::vector{"path"}, "Paths of models on CCDB"}; - Configurable> binsMl{"binsMl", std::vector{-999999., 999999.}, "Bin limits for ML application"}; - Configurable> cutsMl{"cutsMl", std::vector{0.95}, "ML cuts per bin"}; + Configurable> binsMl{"binsMl", std::vector{0.1, 0.15, 0.2, 0.25, 0.4, 0.8, 1.6, 2.0, 20.f}, "Bin limits for ML application"}; + Configurable> cutsMl{"cutsMl", std::vector{0.98, 0.98, 0.9, 0.9, 0.95, 0.95, 0.8, 0.8}, "ML cuts per bin"}; Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"feature"}, "Names of ML model input features"}; Configurable nameBinningFeature{"nameBinningFeature", "pt", "Names of ML model binning feature"}; Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB. Exceptions: > 0 for the specific timestamp, 0 gets the run dependent timestamp"}; @@ -497,7 +493,6 @@ struct SingleTrackQCMC { fEMEventCut.SetRequireGoodITSLayersAll(eventcuts.cfgRequireGoodITSLayersAll); } - o2::analysis::MlResponseDielectronSingleTrack mlResponseSingleTrack; void DefineDielectronCut() { fDielectronCut = DielectronCut("fDielectronCut", "fDielectronCut"); @@ -545,31 +540,6 @@ struct SingleTrackQCMC { thresholdsML.emplace_back(dielectroncuts.cutsMl.value[i]); } fDielectronCut.SetMLThresholds(binsML, thresholdsML); - - // static constexpr int nClassesMl = 2; - // const std::vector cutDirMl = {o2::cuts_ml::CutNot, o2::cuts_ml::CutSmaller}; - // const std::vector labelsClasses = {"Background", "Signal"}; - // const uint32_t nBinsMl = dielectroncuts.binsMl.value.size() - 1; - // const std::vector labelsBins(nBinsMl, "bin"); - // double cutsMlArr[nBinsMl][nClassesMl]; - // for (uint32_t i = 0; i < nBinsMl; i++) { - // cutsMlArr[i][0] = 0.; - // cutsMlArr[i][1] = dielectroncuts.cutsMl.value[i]; - // } - // o2::framework::LabeledArray cutsMl = {cutsMlArr[0], nBinsMl, nClassesMl, labelsBins, labelsClasses}; - - // mlResponseSingleTrack.configure(dielectroncuts.binsMl.value, cutsMl, cutDirMl, nClassesMl); - // if (dielectroncuts.loadModelsFromCCDB) { - // ccdbApi.init(ccdburl); - // mlResponseSingleTrack.setModelPathsCCDB(dielectroncuts.onnxFileNames.value, ccdbApi, dielectroncuts.onnxPathsCCDB.value, dielectroncuts.timestampCCDB.value); - // } else { - // mlResponseSingleTrack.setModelPathsLocal(dielectroncuts.onnxFileNames.value); - // } - // mlResponseSingleTrack.cacheInputFeaturesIndices(dielectroncuts.namesInputFeatures); - // mlResponseSingleTrack.cacheBinningIndex(dielectroncuts.nameBinningFeature); - // mlResponseSingleTrack.init(dielectroncuts.enableOptimizations.value); - - // fDielectronCut.SetPIDMlResponse(&mlResponseSingleTrack); } // end of PID ML } diff --git a/PWGEM/Dilepton/TableProducer/associateMCinfoDilepton.cxx b/PWGEM/Dilepton/TableProducer/associateMCinfoDilepton.cxx index a9147840f9e..86c8fff432a 100644 --- a/PWGEM/Dilepton/TableProducer/associateMCinfoDilepton.cxx +++ b/PWGEM/Dilepton/TableProducer/associateMCinfoDilepton.cxx @@ -15,7 +15,6 @@ // Please write to: daiki.sekihata@cern.ch #include "PWGEM/Dilepton/DataModel/dileptonTables.h" -// #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "Common/Core/TableHelper.h" @@ -39,7 +38,6 @@ struct AssociateMCInfoDilepton { enum SubSystem { kElectron = 0x1, kFwdMuon = 0x2, - // kPCM = 0x4, }; using MyCollisionsMC = soa::Join; @@ -51,7 +49,6 @@ struct AssociateMCInfoDilepton { Produces mceventlabels; Produces emmcparticles; Produces emmcgenvms; - // Produces v0legmclabels; Produces emprimaryelectronmclabels; Produces emprimarymuonmclabels; Produces emmftmclabels; @@ -130,7 +127,6 @@ struct AssociateMCInfoDilepton { SliceCache cache; Preslice perMcCollision = aod::mcparticle::mcCollisionId; - // Preslice perCollision_pcm = aod::v0photonkf::collisionId; Preslice perCollision_el = aod::emprimaryelectron::collisionId; Preslice perCollision_mu = aod::emprimarymuon::collisionId; @@ -683,23 +679,6 @@ struct AssociateMCInfoDilepton { skimmingMC(collisions, bcs, mccollisions, mcTracks, o2tracks, o2fwdtracks, o2mfttracks, nullptr, nullptr, emprimaryelectrons, emprimarymuons); } - // void processMC_Electron_FwdMuon_PCM(MyCollisionsMC const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, TracksMC const& o2tracks, FwdTracksMC const& o2fwdtracks, MFTTracksMC const& o2mfttracks, aod::V0PhotonsKF const& v0photons, aod::V0Legs const& v0legs, aod::EMPrimaryElectrons const& emprimaryelectrons, aod::EMPrimaryMuons const& emprimarymuons) - // { - // const uint8_t sysflag = kPCM | kElectron | kFwdMuon; - // skimmingMC(collisions, bcs, mccollisions, mcTracks, o2tracks, o2fwdtracks, o2mfttracks, v0photons, v0legs, emprimaryelectrons, emprimarymuons); - // } - - // void processMC_Electron_PCM(MyCollisionsMC const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, TracksMC const& o2tracks, aod::V0PhotonsKF const& v0photons, aod::V0Legs const& v0legs, aod::EMPrimaryElectrons const& emprimaryelectrons) - // { - // const uint8_t sysflag = kPCM | kElectron; - // skimmingMC(collisions, bcs, mccollisions, mcTracks, o2tracks, nullptr, nullptr, v0photons, v0legs, emprimaryelectrons, nullptr); - // } - - // void processMC_PCM(MyCollisionsMC const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, TracksMC const& o2tracks, aod::V0PhotonsKF const& v0photons, aod::V0Legs const& v0legs) - // { - // skimmingMC(collisions, bcs, mccollisions, mcTracks, o2tracks, nullptr, nullptr, v0photons, v0legs, nullptr, nullptr); - // } - void processGenDummy(MyCollisionsMC const&) { for (int i = 0; i < n_dummy_loop; i++) { @@ -718,9 +697,6 @@ struct AssociateMCInfoDilepton { PROCESS_SWITCH(AssociateMCInfoDilepton, processMC_Electron, "create em mc event table for Electron", false); PROCESS_SWITCH(AssociateMCInfoDilepton, processMC_FwdMuon, "create em mc event table for Forward Muon", false); PROCESS_SWITCH(AssociateMCInfoDilepton, processMC_Electron_FwdMuon, "create em mc event table for Electron, FwdMuon", false); - // PROCESS_SWITCH(AssociateMCInfoDilepton, processMC_Electron_FwdMuon_PCM, "create em mc event table for PCM, Electron, FwdMuon", false); - // PROCESS_SWITCH(AssociateMCInfoDilepton, processMC_Electron_PCM, "create em mc event table for PCM, Electron", false); - // PROCESS_SWITCH(AssociateMCInfoDilepton, processMC_PCM, "create em mc event table for PCM", false); PROCESS_SWITCH(AssociateMCInfoDilepton, processGenDummy, "produce dummy data", false); PROCESS_SWITCH(AssociateMCInfoDilepton, processDummy, "processDummy", true); }; diff --git a/PWGEM/Dilepton/TableProducer/prefilterDimuon.cxx b/PWGEM/Dilepton/TableProducer/prefilterDimuon.cxx index b2555503c2f..d965dde3061 100644 --- a/PWGEM/Dilepton/TableProducer/prefilterDimuon.cxx +++ b/PWGEM/Dilepton/TableProducer/prefilterDimuon.cxx @@ -17,9 +17,6 @@ #include "PWGEM/Dilepton/Core/DimuonCut.h" #include "PWGEM/Dilepton/Core/EMEventCut.h" #include "PWGEM/Dilepton/DataModel/dileptonTables.h" - -// #include "PWGEM/Dilepton/Utils/EMTrack.h" -// #include "PWGEM/Dilepton/Utils/EventHistograms.h" #include "PWGEM/Dilepton/Utils/PairUtilities.h" #include "Framework/ASoAHelpers.h" @@ -29,9 +26,7 @@ #include "Math/Vector4D.h" #include "TString.h" -// #include #include -// #include #include #include diff --git a/PWGEM/Dilepton/TableProducer/skimmerPrimaryMFTTrack.cxx b/PWGEM/Dilepton/TableProducer/skimmerPrimaryMFTTrack.cxx index 977061cee75..83835874d87 100644 --- a/PWGEM/Dilepton/TableProducer/skimmerPrimaryMFTTrack.cxx +++ b/PWGEM/Dilepton/TableProducer/skimmerPrimaryMFTTrack.cxx @@ -17,7 +17,6 @@ #include "Common/Core/TableHelper.h" #include "Common/Core/fwdtrackUtilities.h" -// #include "Common/DataModel/CollisionAssociationTables.h" #include "CCDB/BasicCCDBManager.h" #include "CommonConstants/PhysicsConstants.h" @@ -68,7 +67,7 @@ struct skimmerPrimaryMFTTrack { Configurable fillQAHistogram{"fillQAHistogram", true, "flag to fill QA histograms"}; - Configurable cfgPtMin{"cfgPtMin", 0.2, "min pt for MFTsa track"}; + Configurable cfgPtMin{"cfgPtMin", 0.1, "min pt for MFTsa track"}; Configurable cfgPtMax{"cfgPtMax", 1e+10, "max pt for MFTsa track"}; Configurable cfgEtaMin{"cfgEtaMin", -4, "min eta acceptance"}; Configurable cfgEtaMax{"cfgEtaMax", -2, "max eta acceptance"}; @@ -238,7 +237,7 @@ struct skimmerPrimaryMFTTrack { trackBit |= static_cast(RefMFTTrackBit::kDCAxy001cm); } - emprimarytracks(/*collision.globalIndex(),*/ /*mfttrack.globalIndex(),*/ mfttrack.sign() / pt, eta, phi, trackBit); + emprimarytracks(mfttrack.sign() / pt, eta, phi, trackBit); prmtrackeventidtmp(collision.globalIndex()); if (fillQAHistogram) { diff --git a/PWGEM/Dilepton/TableProducer/skimmerPrimaryTrack.cxx b/PWGEM/Dilepton/TableProducer/skimmerPrimaryTrack.cxx index b217cae9548..bc88fd7fef0 100644 --- a/PWGEM/Dilepton/TableProducer/skimmerPrimaryTrack.cxx +++ b/PWGEM/Dilepton/TableProducer/skimmerPrimaryTrack.cxx @@ -18,7 +18,6 @@ #include "Common/Core/TableHelper.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/CollisionAssociationTables.h" -// #include "Common/DataModel/PIDResponseITS.h" #include "CCDB/BasicCCDBManager.h" #include "CommonConstants/PhysicsConstants.h" @@ -212,10 +211,6 @@ struct skimmerPrimaryTrack { return false; } - if (track.tpcNClsFound() < 0) { - return false; - } - if (track.tpcNClsCrossedRows() < 50) { return false; } @@ -241,16 +236,10 @@ struct skimmerPrimaryTrack { if (std::fabs(dcaXY) > dca_xy_max || std::fabs(dcaZ) > dca_z_max) { return false; } - if (std::fabs(dcaZ) > 3.f) { - return false; - } if (std::fabs(trackParCov.getEta()) > maxeta || trackParCov.getPt() < minpt || maxpt < trackParCov.getPt()) { return false; } - if (trackParCov.getPt() > 5.f) { - return false; - } return true; } diff --git a/PWGEM/Dilepton/Tasks/CMakeLists.txt b/PWGEM/Dilepton/Tasks/CMakeLists.txt index ab6df58242a..a32c3768bd5 100644 --- a/PWGEM/Dilepton/Tasks/CMakeLists.txt +++ b/PWGEM/Dilepton/Tasks/CMakeLists.txt @@ -62,12 +62,12 @@ o2physics_add_dpl_workflow(event-qc o2physics_add_dpl_workflow(single-electron-qc SOURCES singleElectronQC.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::MLCore O2Physics::PWGEMDileptonCore O2Physics::EventFilteringUtils + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::PWGEMDileptonCore O2Physics::EventFilteringUtils COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(single-electron-qc-mc SOURCES singleElectronQCMC.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::MLCore O2Physics::PWGEMDileptonCore + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::PWGEMDileptonCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(single-muon-qc @@ -82,12 +82,12 @@ o2physics_add_dpl_workflow(single-muon-qc-mc o2physics_add_dpl_workflow(dielectron SOURCES dielectron.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::MLCore O2Physics::PWGEMDileptonCore O2Physics::EventFilteringUtils + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::PWGEMDileptonCore O2Physics::EventFilteringUtils COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(dielectron-mc SOURCES dielectronMC.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::MLCore O2Physics::PWGEMDileptonCore + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::PWGEMDileptonCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(dimuon @@ -102,7 +102,7 @@ o2physics_add_dpl_workflow(dimuon-mc o2physics_add_dpl_workflow(prefilter-dielectron SOURCES prefilterDielectron.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::MLCore O2Physics::PWGEMDileptonCore + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGEMDileptonCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(associate-mccollision-to-collision @@ -127,12 +127,12 @@ o2physics_add_dpl_workflow(tagging-hfe o2physics_add_dpl_workflow(dielectron-hadron-mpc SOURCES dielectronHadronMPC.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::MLCore O2Physics::PWGEMDileptonCore O2Physics::EventFilteringUtils + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::PWGEMDileptonCore O2Physics::EventFilteringUtils COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(dimuon-hadron-mpc SOURCES dimuonHadronMPC.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::MLCore O2Physics::PWGEMDileptonCore O2Physics::EventFilteringUtils + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::PWGEMDileptonCore O2Physics::EventFilteringUtils COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(mc-particle-predictions-otf @@ -162,5 +162,5 @@ o2physics_add_dpl_workflow(check-mc-template o2physics_add_dpl_workflow(check-mc-pair-template SOURCES checkMCPairTemplate.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::MLCore O2Physics::PWGEMDileptonCore + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::PWGEMDileptonCore COMPONENT_NAME Analysis) diff --git a/PWGEM/Dilepton/Tasks/checkMCPairTemplate.cxx b/PWGEM/Dilepton/Tasks/checkMCPairTemplate.cxx index 00e6ff121d0..83777d2dbc1 100644 --- a/PWGEM/Dilepton/Tasks/checkMCPairTemplate.cxx +++ b/PWGEM/Dilepton/Tasks/checkMCPairTemplate.cxx @@ -21,13 +21,10 @@ #include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" #include "PWGEM/Dilepton/Utils/EventHistograms.h" #include "PWGEM/Dilepton/Utils/MCUtilities.h" -#include "PWGEM/Dilepton/Utils/MlResponseDielectronSingleTrack.h" #include "PWGEM/Dilepton/Utils/PairUtilities.h" #include "Common/CCDB/RCTSelectionFlags.h" #include "Common/Core/RecoDecay.h" -#include "Common/Core/trackUtilities.h" -#include "Tools/ML/MlResponse.h" #include "CCDB/BasicCCDBManager.h" #include "CommonConstants/LHCConstants.h" @@ -813,7 +810,6 @@ struct checkMCPairTemplate { fEMEventCut.SetRequireGoodITSLayersAll(eventcuts.cfgRequireGoodITSLayersAll); } - o2::analysis::MlResponseDielectronSingleTrack mlResponseSingleTrack; void DefineDielectronCut() { fDielectronCut = DielectronCut("fDielectronCut", "fDielectronCut"); @@ -871,31 +867,6 @@ struct checkMCPairTemplate { thresholdsML.emplace_back(dielectroncuts.cutsMl.value[i]); } fDielectronCut.SetMLThresholds(binsML, thresholdsML); - - // static constexpr int nClassesMl = 2; - // const std::vector cutDirMl = {o2::cuts_ml::CutNot, o2::cuts_ml::CutSmaller}; - // const std::vector labelsClasses = {"Background", "Signal"}; - // const uint32_t nBinsMl = dielectroncuts.binsMl.value.size() - 1; - // const std::vector labelsBins(nBinsMl, "bin"); - // double cutsMlArr[nBinsMl][nClassesMl]; - // for (uint32_t i = 0; i < nBinsMl; i++) { - // cutsMlArr[i][0] = 0.; - // cutsMlArr[i][1] = dielectroncuts.cutsMl.value[i]; - // } - // o2::framework::LabeledArray cutsMl = {cutsMlArr[0], nBinsMl, nClassesMl, labelsBins, labelsClasses}; - - // mlResponseSingleTrack.configure(dielectroncuts.binsMl.value, cutsMl, cutDirMl, nClassesMl); - // if (dielectroncuts.loadModelsFromCCDB) { - // ccdbApi.init(ccdburl); - // mlResponseSingleTrack.setModelPathsCCDB(dielectroncuts.onnxFileNames.value, ccdbApi, dielectroncuts.onnxPathsCCDB.value, dielectroncuts.timestampCCDB.value); - // } else { - // mlResponseSingleTrack.setModelPathsLocal(dielectroncuts.onnxFileNames.value); - // } - // mlResponseSingleTrack.cacheInputFeaturesIndices(dielectroncuts.namesInputFeatures); - // mlResponseSingleTrack.cacheBinningIndex(dielectroncuts.nameBinningFeature); - // mlResponseSingleTrack.init(dielectroncuts.enableOptimizations.value); - - // fDielectronCut.SetPIDMlResponse(&mlResponseSingleTrack); } // end of PID ML } diff --git a/PWGEM/Dilepton/Tasks/dileptonPolarization.cxx b/PWGEM/Dilepton/Tasks/dileptonPolarization.cxx index 478b48982e1..3afec6f363a 100644 --- a/PWGEM/Dilepton/Tasks/dileptonPolarization.cxx +++ b/PWGEM/Dilepton/Tasks/dileptonPolarization.cxx @@ -15,10 +15,7 @@ // Please write to: daiki.sekihata@cern.ch #include "PWGEM/Dilepton/DataModel/dileptonTables.h" -// #include "PWGEM/Dilepton/Utils/EMFwdTrack.h" #include "PWGEM/Dilepton/Utils/EMTrack.h" -// #include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" -// #include "PWGEM/Dilepton/Utils/EventMixingHandler.h" #include "PWGEM/Dilepton/Utils/PairUtilities.h" #include "Common/Core/RecoDecay.h" @@ -27,10 +24,6 @@ #include "CommonConstants/LHCConstants.h" #include "DataFormatsParameters/GRPECSObject.h" #include "DataFormatsParameters/GRPLHCIFData.h" -// #include "DataFormatsParameters/GRPMagField.h" -// #include "DataFormatsParameters/GRPObject.h" -// #include "DetectorsBase/GeometryManager.h" -// #include "DetectorsBase/Propagator.h" #include "Framework/ASoAHelpers.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" @@ -56,16 +49,11 @@ using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::soa; using namespace o2::aod::pwgem::dilepton::utils; -// using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; using namespace o2::aod::pwgem::dilepton::utils::pairutil; struct DileptonPolarization { // Configurables Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; - // Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; - // Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; - // Configurable skipGRPOquery{"skipGRPOquery", true, "skip grpo query"}; - // Configurable d_bz_input{"d_bz_input", -999, "bz field in kG, -999 is automatic"}; Configurable cfgPairType{"cfgPairType", 0, "0:dielectron, 1:dimuon"}; Configurable cfgOccupancyEstimator{"cfgOccupancyEstimator", 0, "FT0C:0, Track:1"}; diff --git a/PWGEM/Dilepton/Tasks/evaluateAcceptance.cxx b/PWGEM/Dilepton/Tasks/evaluateAcceptance.cxx index 9a552f407ae..5ad4d765e25 100644 --- a/PWGEM/Dilepton/Tasks/evaluateAcceptance.cxx +++ b/PWGEM/Dilepton/Tasks/evaluateAcceptance.cxx @@ -19,24 +19,10 @@ #include "Common/Core/RecoDecay.h" #include "Common/Core/TableHelper.h" -// #include "Common/Core/trackUtilities.h" -// #include "Common/DataModel/Centrality.h" -// #include "Common/DataModel/CollisionAssociationTables.h" -// #include "Common/DataModel/EventSelection.h" -// #include "Common/DataModel/Multiplicity.h" -// #include "Common/DataModel/TrackSelectionTables.h" - #include "CCDB/BasicCCDBManager.h" #include "CommonConstants/LHCConstants.h" #include "CommonConstants/PhysicsConstants.h" #include "DataFormatsParameters/GRPLHCIFData.h" - -// #include "DataFormatsCalibration/MeanVertexObject.h" -// #include "DataFormatsParameters/GRPMagField.h" -// #include "DataFormatsParameters/GRPObject.h" -// #include "DetectorsBase/GeometryManager.h" -// #include "DetectorsBase/Propagator.h" - #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" diff --git a/PWGEM/Dilepton/Tasks/prefilterDielectron.cxx b/PWGEM/Dilepton/Tasks/prefilterDielectron.cxx index e2292c07b07..c2ac0b75d80 100644 --- a/PWGEM/Dilepton/Tasks/prefilterDielectron.cxx +++ b/PWGEM/Dilepton/Tasks/prefilterDielectron.cxx @@ -17,13 +17,8 @@ #include "PWGEM/Dilepton/Core/DielectronCut.h" #include "PWGEM/Dilepton/Core/EMEventCut.h" #include "PWGEM/Dilepton/DataModel/dileptonTables.h" -#include "PWGEM/Dilepton/Utils/EMTrack.h" -#include "PWGEM/Dilepton/Utils/EventHistograms.h" #include "PWGEM/Dilepton/Utils/PairUtilities.h" -#include "Common/Core/RecoDecay.h" -#include "Common/Core/trackUtilities.h" - #include "CCDB/BasicCCDBManager.h" #include "DataFormatsParameters/GRPMagField.h" #include "DataFormatsParameters/GRPObject.h" @@ -47,8 +42,6 @@ using namespace o2::aod; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::soa; -using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; -using namespace o2::aod::pwgem::dilepton::utils::pairutil; struct prefilterDielectron { using MyCollisions = soa::Join; @@ -256,7 +249,6 @@ struct prefilterDielectron { fEMEventCut.SetRequireGoodZvtxFT0vsPV(eventcuts.cfgRequireGoodZvtxFT0vsPV); } - o2::analysis::MlResponseDielectronSingleTrack mlResponseSingleTrack; void DefineDielectronCut() { fDielectronCut = DielectronCut("fDielectronCut", "fDielectronCut"); @@ -314,31 +306,6 @@ struct prefilterDielectron { thresholdsML.emplace_back(dielectroncuts.cutsMl.value[i]); } fDielectronCut.SetMLThresholds(binsML, thresholdsML); - - // static constexpr int nClassesMl = 2; - // const std::vector cutDirMl = {o2::cuts_ml::CutSmaller, o2::cuts_ml::CutNot}; - // const std::vector labelsClasses = {"Signal", "Background"}; - // const uint32_t nBinsMl = dielectroncuts.binsMl.value.size() - 1; - // const std::vector labelsBins(nBinsMl, "bin"); - // double cutsMlArr[nBinsMl][nClassesMl]; - // for (uint32_t i = 0; i < nBinsMl; i++) { - // cutsMlArr[i][0] = dielectroncuts.cutsMl.value[i]; - // cutsMlArr[i][1] = 0.; - // } - // o2::framework::LabeledArray cutsMl = {cutsMlArr[0], nBinsMl, nClassesMl, labelsBins, labelsClasses}; - - // mlResponseSingleTrack.configure(dielectroncuts.binsMl.value, cutsMl, cutDirMl, nClassesMl); - // if (dielectroncuts.loadModelsFromCCDB) { - // ccdbApi.init(ccdburl); - // mlResponseSingleTrack.setModelPathsCCDB(dielectroncuts.onnxFileNames.value, ccdbApi, dielectroncuts.onnxPathsCCDB.value, dielectroncuts.timestampCCDB.value); - // } else { - // mlResponseSingleTrack.setModelPathsLocal(dielectroncuts.onnxFileNames.value); - // } - // mlResponseSingleTrack.cacheInputFeaturesIndices(dielectroncuts.namesInputFeatures); - // mlResponseSingleTrack.cacheBinningIndex(dielectroncuts.nameBinningFeature); - // mlResponseSingleTrack.init(dielectroncuts.enableOptimizations.value); - - // fDielectronCut.SetPIDMlResponse(&mlResponseSingleTrack); } // end of PID ML } diff --git a/PWGEM/Dilepton/Tasks/testBremsstrahlung.cxx b/PWGEM/Dilepton/Tasks/testBremsstrahlung.cxx index 9897c101b5f..f5f01ae4cfe 100644 --- a/PWGEM/Dilepton/Tasks/testBremsstrahlung.cxx +++ b/PWGEM/Dilepton/Tasks/testBremsstrahlung.cxx @@ -37,8 +37,6 @@ #include "Framework/HistogramRegistry.h" #include "Framework/runDataProcessing.h" -// #include "TGeoGlobalMagField.h" - #include #include #include From efc75263165c9cf029e46591ad070d7d5e5362e2 Mon Sep 17 00:00:00 2001 From: skundu692 <86804743+skundu692@users.noreply.github.com> Date: Wed, 11 Mar 2026 23:41:55 +0100 Subject: [PATCH 257/347] [PWGLF] Change PID selection for f1p correlation (#15353) --- .../Tasks/Resonances/f1protoncorrelation.cxx | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/PWGLF/Tasks/Resonances/f1protoncorrelation.cxx b/PWGLF/Tasks/Resonances/f1protoncorrelation.cxx index 63568887fab..eb563fd9970 100644 --- a/PWGLF/Tasks/Resonances/f1protoncorrelation.cxx +++ b/PWGLF/Tasks/Resonances/f1protoncorrelation.cxx @@ -292,9 +292,9 @@ struct f1protoncorrelation { if (f1track.f1d1TOFHit() != 1) { return (std::abs(nsTPC) < cutNoTOF); } - - const float comb = std::sqrt(nsTPC * nsTPC + nsTOF * nsTOF); - return (comb < cutWithTOF); + return (std::abs(nsTPC) < cutNoTOF && std::abs(nsTOF) < cutWithTOF); + // const float comb = std::sqrt(nsTPC * nsTPC + nsTOF * nsTOF); + // return (comb < cutWithTOF); } inline bool passKaonPID(int pidMode, const aod::F1Tracks::iterator& f1track, @@ -340,10 +340,10 @@ struct f1protoncorrelation { } return true; } - + return (std::abs(nsTPC) < cutNoTOFBase && std::abs(nsTOF) < cutWithTOF); // --- TOF available: circular cut in (TPC,TOF) nσ plane - const float comb = std::sqrt(nsTPC * nsTPC + nsTOF * nsTOF); - return (comb < cutWithTOF); + // const float comb = std::sqrt(nsTPC * nsTPC + nsTOF * nsTOF); + // return (comb < cutWithTOF); } inline bool passProtonPID(int pidMode, const aod::ProtonTracks::iterator& ptrack, @@ -379,8 +379,9 @@ struct f1protoncorrelation { // circular cut in (TPC,TOF) const float nsTPC = ptrack.protonNsigmaTPC(); const float nsTOF = ptrack.protonNsigmaTOF(); - const float comb = std::sqrt(nsTPC * nsTPC + nsTOF * nsTOF); - return (comb < cutCircle); + return (std::abs(nsTPC) < cutTPC && std::abs(nsTOF) < cutCircle); + // const float comb = std::sqrt(nsTPC * nsTPC + nsTOF * nsTOF); + // return (comb < cutCircle); } // Initialize the ananlysis task @@ -610,7 +611,7 @@ struct f1protoncorrelation { histos.fill(HIST("hNsigmaProtonTPC"), protontrack.protonNsigmaTPC(), protontrack.protonNsigmaTOF(), Proton.Pt()); } histos.fill(HIST("h2SameEventPtCorrelation"), relative_momentum, F1.Pt(), Proton.Pt()); - + auto mT = getmT(F1, Proton); if (f1track.f1SignalStat() > 0) { // check charge float pairCharge = f1track.f1SignalStat() * protontrack.protonCharge(); @@ -625,7 +626,9 @@ struct f1protoncorrelation { histos.fill(HIST("hPhaseSpaceProtonKaonSame"), Proton.Eta() - Kaon.Eta(), PhiAtSpecificRadiiTPC(Proton, Kaon, protontrack.protonCharge(), kaonCharge, bz, bz), relative_momentum); // Phase Space Proton kaon if (pionCharge == protontrack.protonCharge()) histos.fill(HIST("hPhaseSpaceProtonPionSame"), Proton.Eta() - Pion.Eta(), PhiAtSpecificRadiiTPC(Proton, Pion, protontrack.protonCharge(), pionCharge, bz, bz), relative_momentum); // Phase Space Proton Pionsyst - histos.fill(HIST("h2SameEventInvariantMassUnlike_mass"), relative_momentum, F1.Pt(), F1.M(), pairCharge, collision.numContrib()); // F1 sign = 1 unlike, F1 sign = -1 like + + histos.fill(HIST("h2SameEventInvariantMassUnlike_mass"), relative_momentum, F1.Pt(), F1.M(), pairCharge, collision.numContrib()); // F1 sign = 1 unlike, F1 sign = -1 like + histos.fill(HIST("h2SameEventInvariantMassUnlike_mass_SYS"), 0, relative_momentum, mT, F1.M(), collision.numContrib()); if (fillSparse) { histos.fill(HIST("SEMassUnlike"), F1.M(), F1.Pt(), Proton.Pt(), relative_momentum, combinedTPC, pairCharge); } @@ -651,6 +654,7 @@ struct f1protoncorrelation { } } if (f1track.f1SignalStat() == -1) { + histos.fill(HIST("h2SameEventInvariantMassLike_mass_SYS"), 0, relative_momentum, mT, F1.M(), collision.numContrib()); histos.fill(HIST("h2SameEventInvariantMassLike_mass"), relative_momentum, F1.Pt(), F1.M(), protontrack.protonCharge(), collision.numContrib()); if (fillSparse) { histos.fill(HIST("SEMassLike"), F1.M(), F1.Pt(), Proton.Pt(), relative_momentum, combinedTPC, protontrack.protonCharge()); @@ -896,6 +900,7 @@ struct f1protoncorrelation { continue; } auto relative_momentum = getkstar(F1, Proton); + auto mT = getmT(F1, Proton); if (t1.f1SignalStat() > 0) { float pairCharge = t1.f1SignalStat() * t2.protonCharge(); int f1Charge = t1.f1SignalStat(); @@ -905,6 +910,7 @@ struct f1protoncorrelation { pionCharge = 1; kaonCharge = -1; } + histos.fill(HIST("h2MixEventInvariantMassUnlike_mass_SYS"), 0, relative_momentum, mT, F1.M(), collision1.numContrib()); histos.fill(HIST("h2MixEventInvariantMassUnlike_mass"), relative_momentum, F1.Pt(), F1.M(), pairCharge, collision1.numContrib()); // F1 sign = 1 unlike, F1 sign = -1 like histos.fill(HIST("hPhaseSpaceProtonKaonMix"), Proton.Eta() - Kaon.Eta(), PhiAtSpecificRadiiTPC(Proton, Kaon, t2.protonCharge(), kaonCharge, bz, bz2), relative_momentum); // Phase Space Proton kaon histos.fill(HIST("hPhaseSpaceProtonPionMix"), Proton.Eta() - Pion.Eta(), PhiAtSpecificRadiiTPC(Proton, Pion, t2.protonCharge(), pionCharge, bz, bz2), relative_momentum); // Phase Space Proton Pion @@ -936,6 +942,7 @@ struct f1protoncorrelation { } } if (t1.f1SignalStat() == -1) { + histos.fill(HIST("h2MixEventInvariantMassLike_mass_SYS"), 0, relative_momentum, mT, F1.M(), collision1.numContrib()); histos.fill(HIST("h2MixEventInvariantMassLike_mass"), relative_momentum, F1.Pt(), F1.M(), t2.protonCharge(), collision1.numContrib()); if (fillSparse) { histos.fill(HIST("MEMassLike"), F1.M(), F1.Pt(), Proton.Pt(), relative_momentum, combinedTPC, t2.protonCharge()); From d97050625d4efa39c270151ba80cd78370542333 Mon Sep 17 00:00:00 2001 From: Mingze Li Date: Wed, 11 Mar 2026 23:47:33 +0100 Subject: [PATCH 258/347] [PWGHF] taskCharmPolarisation: Add centrality axis to the output (#15354) Co-authored-by: ALICE Action Bot --- PWGHF/D2H/Tasks/taskCharmPolarisation.cxx | 170 +++++++++++++++------- 1 file changed, 119 insertions(+), 51 deletions(-) diff --git a/PWGHF/D2H/Tasks/taskCharmPolarisation.cxx b/PWGHF/D2H/Tasks/taskCharmPolarisation.cxx index 573a5ca3fcf..dcc88fbb5d9 100644 --- a/PWGHF/D2H/Tasks/taskCharmPolarisation.cxx +++ b/PWGHF/D2H/Tasks/taskCharmPolarisation.cxx @@ -602,6 +602,10 @@ struct HfTaskCharmPolarisation { hRecoPromptRandomAxes.insert(hRecoPromptRandomAxes.end(), {thnAxisDauToMuons}); std::vector hRecoNonPromptRandomAxes(hRandomaxes); hRecoNonPromptRandomAxes.insert(hRecoNonPromptRandomAxes.end(), {thnAxisDauToMuons, thnAxisPtB}); + if (doprocessDstarMcInPbPb || doprocessDstarMcWithMlInPbPb) { + hRecoPromptRandomAxes.push_back(thnAxisCentrality); + hRecoNonPromptRandomAxes.push_back(thnAxisCentrality); + } registry.add("hRecoPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis and BDT scores for reconstructed prompt D*+ candidates", HistType::kTHnSparseF, hRecoPromptRandomAxes); registry.add("hRecoNonPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis and BDT scores for reconstructed non-prompt D*+ candidates", HistType::kTHnSparseF, hRecoNonPromptRandomAxes); if (activatePartRecoDstar) { @@ -633,8 +637,12 @@ struct HfTaskCharmPolarisation { registry.add("hRandom", "THn for polarisation studies with cosThStar w.r.t. random axis and BDT scores", HistType::kTHnSparseF, hRandomaxes); } if (doprocessDstarMc || doprocessDstarMcWithMl || doprocessDstarMcInPbPb || doprocessDstarMcWithMlInPbPb || doprocessLcToPKPiMc || doprocessLcToPKPiMcWithMl || doprocessLcToPKPiBackgroundMcWithMl) { - std::vector const hgenPromptAxes = {thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisCosThetaStarRandom, thnAxisDausAcc, thnAxisResoChannelLc, thnAxisCharge}; - std::vector const hgenNonPromptAxes = {thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisCosThetaStarRandom, thnAxisPtB, thnAxisDausAcc, thnAxisResoChannelLc, thnAxisCharge}; + std::vector hgenPromptAxes = {thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisCosThetaStarRandom, thnAxisDausAcc, thnAxisResoChannelLc, thnAxisCharge}; + std::vector hgenNonPromptAxes = {thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisCosThetaStarRandom, thnAxisPtB, thnAxisDausAcc, thnAxisResoChannelLc, thnAxisCharge}; + if (doprocessDstarMcInPbPb || doprocessDstarMcWithMlInPbPb) { + hgenPromptAxes.push_back(thnAxisCentrality); + hgenNonPromptAxes.push_back(thnAxisCentrality); + } registry.add("hGenPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis and BDT scores for generated prompt D*+ candidates", HistType::kTHnSparseF, hgenPromptAxes); registry.add("hGenNonPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis and BDT scores for generated non-prompt D*+ candidates", HistType::kTHnSparseF, hgenNonPromptAxes); if (activatePartRecoDstar) { @@ -659,6 +667,7 @@ struct HfTaskCharmPolarisation { if (nBkgRotations > 0) { hEPaxes.push_back(thnAxisIsRotatedCandidate); } + hEPaxes.push_back(thnAxisCentrality); registry.add("hEP", "THn for polarisation studies with cosThStar w.r.t. event plane axis and BDT scores", HistType::kTHnSparseF, hEPaxes); } } @@ -738,7 +747,7 @@ struct HfTaskCharmPolarisation { /// \param nMuons is the number of muons from daughter decays /// \param isPartRecoDstar is a flag indicating if it is a partly reconstructed Dstar meson (MC only) template - void fillRecoHistos(float invMassCharmHad, float ptCharmHad, int numPvContributors, float rapCharmHad, float invMassD0, float invMassKPiLc, float cosThetaStar, float phiEuler, std::array outputMl, int isRotatedCandidate, int8_t origin, float ptBhadMother, int8_t resoChannelLc, float absEtaMin, int numItsClsMin, int numTpcClsMin, int8_t charge, int8_t nMuons, bool isPartRecoDstar) + void fillRecoHistos(float invMassCharmHad, float ptCharmHad, int numPvContributors, float rapCharmHad, float invMassD0, float invMassKPiLc, float cosThetaStar, float phiEuler, std::array outputMl, int isRotatedCandidate, int8_t origin, float ptBhadMother, int8_t resoChannelLc, float absEtaMin, int numItsClsMin, int numTpcClsMin, int8_t charge, int8_t nMuons, bool isPartRecoDstar, float centrality = -999.f) { if constexpr (CosThetaStarType == charm_polarisation::CosThetaStarType::Helicity) { // Helicity if constexpr (!DoMc) { // data @@ -1193,15 +1202,31 @@ struct HfTaskCharmPolarisation { if constexpr (Channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ if (activateTrackingSys) { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + if (doprocessDstarMcInPbPb || doprocessDstarMcWithMlInPbPb) { + registry.fill(HIST("hRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, centrality); + } else { + registry.fill(HIST("hRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + } } else { - registry.fill(HIST("hPartRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + if (doprocessDstarMcInPbPb || doprocessDstarMcWithMlInPbPb) { + registry.fill(HIST("hPartRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, centrality); + } else { + registry.fill(HIST("hPartRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + } } } else { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons); + if (doprocessDstarMcInPbPb || doprocessDstarMcWithMlInPbPb) { + registry.fill(HIST("hRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, centrality); + } else { + registry.fill(HIST("hRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons); + } } else { - registry.fill(HIST("hPartRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons); + if (doprocessDstarMcInPbPb || doprocessDstarMcWithMlInPbPb) { + registry.fill(HIST("hPartRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, centrality); + } else { + registry.fill(HIST("hPartRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons); + } } } } else if constexpr (Channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ @@ -1211,15 +1236,31 @@ struct HfTaskCharmPolarisation { if constexpr (Channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ if (activateTrackingSys) { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + if (doprocessDstarMcInPbPb || doprocessDstarMcWithMlInPbPb) { + registry.fill(HIST("hRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother, centrality); + } else { + registry.fill(HIST("hRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + } } else { - registry.fill(HIST("hPartRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + if (doprocessDstarMcInPbPb || doprocessDstarMcWithMlInPbPb) { + registry.fill(HIST("hPartRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother, centrality); + } else { + registry.fill(HIST("hPartRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + } } } else { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, ptBhadMother); + if (doprocessDstarMcInPbPb || doprocessDstarMcWithMlInPbPb) { + registry.fill(HIST("hRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, ptBhadMother, centrality); + } else { + registry.fill(HIST("hRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, ptBhadMother); + } } else { - registry.fill(HIST("hPartRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, ptBhadMother); + if (doprocessDstarMcInPbPb || doprocessDstarMcWithMlInPbPb) { + registry.fill(HIST("hPartRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, ptBhadMother, centrality); + } else { + registry.fill(HIST("hPartRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, ptBhadMother); + } } } } else if constexpr (Channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ @@ -1230,9 +1271,17 @@ struct HfTaskCharmPolarisation { if (origin == RecoDecay::OriginType::Prompt) { // prompt if constexpr (Channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ if (!isPartRecoDstar) { - registry.fill(HIST("hRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + if (doprocessDstarMcInPbPb || doprocessDstarMcWithMlInPbPb) { + registry.fill(HIST("hRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, centrality); + } else { + registry.fill(HIST("hRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + } } else { - registry.fill(HIST("hPartRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + if (doprocessDstarMcInPbPb || doprocessDstarMcWithMlInPbPb) { + registry.fill(HIST("hPartRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, centrality); + } else { + registry.fill(HIST("hPartRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + } } } else if constexpr (Channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ registry.fill(HIST("hRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassKPiLc, cosThetaStar, resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); @@ -1240,9 +1289,17 @@ struct HfTaskCharmPolarisation { } else { // non-prompt if constexpr (Channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ if (!isPartRecoDstar) { - registry.fill(HIST("hRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + if (doprocessDstarMcInPbPb || doprocessDstarMcWithMlInPbPb) { + registry.fill(HIST("hRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother, centrality); + } else { + registry.fill(HIST("hRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + } } else { - registry.fill(HIST("hPartRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + if (doprocessDstarMcInPbPb || doprocessDstarMcWithMlInPbPb) { + registry.fill(HIST("hPartRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother, centrality); + } else { + registry.fill(HIST("hPartRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + } } } else if constexpr (Channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ registry.fill(HIST("hRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassKPiLc, cosThetaStar, resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); @@ -1256,15 +1313,15 @@ struct HfTaskCharmPolarisation { if constexpr (Channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ if (activateTrackingSys) { if (nBkgRotations > 0) { - registry.fill(HIST("hEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, isRotatedCandidate); + registry.fill(HIST("hEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, isRotatedCandidate, centrality); } else { - registry.fill(HIST("hEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin); + registry.fill(HIST("hEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, centrality); } } else { if (nBkgRotations > 0) { - registry.fill(HIST("hEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], isRotatedCandidate); + registry.fill(HIST("hEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], isRotatedCandidate, centrality); } else { - registry.fill(HIST("hEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2]); + registry.fill(HIST("hEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], centrality); } } } @@ -1272,15 +1329,15 @@ struct HfTaskCharmPolarisation { if constexpr (Channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ if (activateTrackingSys) { if (nBkgRotations > 0) { - registry.fill(HIST("hEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, isRotatedCandidate); + registry.fill(HIST("hEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, isRotatedCandidate, centrality); } else { - registry.fill(HIST("hEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin); + registry.fill(HIST("hEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, centrality); } } else { if (nBkgRotations > 0) { - registry.fill(HIST("hEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, isRotatedCandidate); + registry.fill(HIST("hEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, isRotatedCandidate, centrality); } else { - registry.fill(HIST("hEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar); + registry.fill(HIST("hEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, centrality); } } } @@ -1335,7 +1392,7 @@ struct HfTaskCharmPolarisation { /// \param resoChannelLc indicates the Lc decay channel (direct, resonant) /// \param isPartRecoDstar is a flag indicating if it is a partly reconstructed Dstar->D0pi->Kpipipi0 meson (MC only) template - void fillGenHistos(float ptCharmHad, int numPvContributors, float rapCharmHad, float cosThetaStar, int8_t origin, float ptBhadMother, bool areDausInAcc, uint8_t resoChannelLc, int8_t charge, bool isPartRecoDstar) + void fillGenHistos(float ptCharmHad, int numPvContributors, float rapCharmHad, float cosThetaStar, int8_t origin, float ptBhadMother, bool areDausInAcc, uint8_t resoChannelLc, int8_t charge, bool isPartRecoDstar, float centrality = -999.f) { if constexpr (CosThetaStarType == charm_polarisation::CosThetaStarType::Helicity) { // Helicity if (origin == RecoDecay::OriginType::Prompt) { // prompt @@ -1380,31 +1437,33 @@ struct HfTaskCharmPolarisation { } } } else if constexpr (CosThetaStarType == charm_polarisation::CosThetaStarType::Random) { // Random - if (origin == RecoDecay::OriginType::Prompt) { // prompt - if (!isPartRecoDstar) { - registry.fill(HIST("hGenPromptRandom"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, areDausInAcc, resoChannelLc, charge); - } else { - registry.fill(HIST("hGenPartRecoPromptRandom"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, areDausInAcc, resoChannelLc, charge); - } - } else { // non-prompt + if (origin == RecoDecay::OriginType::Prompt) { if (!isPartRecoDstar) { - registry.fill(HIST("hGenNonPromptRandom"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); - } else { - registry.fill(HIST("hGenPartRecoNonPromptRandom"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); - } - } - } else if constexpr (CosThetaStarType == charm_polarisation::CosThetaStarType::EP) { // EP - if (origin == RecoDecay::OriginType::Prompt) { // prompt - if (!isPartRecoDstar) { - registry.fill(HIST("hGenPromptEP"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, areDausInAcc, resoChannelLc, charge); + if (doprocessDstarMcInPbPb || doprocessDstarMcWithMlInPbPb) { + registry.fill(HIST("hGenPromptRandom"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, areDausInAcc, resoChannelLc, charge, centrality); + } else { + registry.fill(HIST("hGenPromptRandom"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, areDausInAcc, resoChannelLc, charge); + } } else { - registry.fill(HIST("hGenPartRecoPromptEP"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, areDausInAcc, resoChannelLc, charge); + if (doprocessDstarMcInPbPb || doprocessDstarMcWithMlInPbPb) { + registry.fill(HIST("hGenPartRecoPromptRandom"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, areDausInAcc, resoChannelLc, charge, centrality); + } else { + registry.fill(HIST("hGenPartRecoPromptRandom"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, areDausInAcc, resoChannelLc, charge); + } } } else { // non-prompt if (!isPartRecoDstar) { - registry.fill(HIST("hGenNonPromptEP"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); + if (doprocessDstarMcInPbPb || doprocessDstarMcWithMlInPbPb) { + registry.fill(HIST("hGenNonPromptRandom"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge, centrality); + } else { + registry.fill(HIST("hGenNonPromptRandom"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); + } } else { - registry.fill(HIST("hGenPartRecoNonPromptEP"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); + if (doprocessDstarMcInPbPb || doprocessDstarMcWithMlInPbPb) { + registry.fill(HIST("hGenPartRecoNonPromptRandom"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge, centrality); + } else { + registry.fill(HIST("hGenPartRecoNonPromptRandom"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); + } } } } @@ -1518,10 +1577,11 @@ struct HfTaskCharmPolarisation { /// \param tracks are the reconstructed tracks /// \return true if candidate in signal region template - bool runPolarisationAnalysis(Cand const& candidate, int bkgRotationId, int numPvContributors, Part const& particles, Trk const& /*tracks*/, QVecs const* qVecs = nullptr) + bool runPolarisationAnalysis(Cand const& candidate, int bkgRotationId, int numPvContributors, Part const& particles, Trk const& /*tracks*/, float centrality = -999.f, QVecs const* qVecs = nullptr) { if constexpr (WithEp) { assert(qVecs && "EP analysis requested but qVecs == nullptr"); + assert(centrality && "EP analysis requested but centrality == nullptr"); } constexpr std::size_t NScores{3u}; @@ -1845,7 +1905,7 @@ struct HfTaskCharmPolarisation { if (activateTHnSparseCosThStarEP) { // EP float cosThetaStarEP = qVecNorm.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()) / std::sqrt(qVecNorm.Mag2()); - fillRecoHistos(invMassCharmHadForSparse, ptCharmHad, numPvContributors, rapidity, invMassD0, invMassKPiLc, cosThetaStarEP, phiEP, outputMl, isRotatedCandidate, origin, ptBhadMother, resoChannelLc, absEtaTrackMin, numItsClsMin, numTpcClsMin, charge, nMuons, partRecoDstar); + fillRecoHistos(invMassCharmHadForSparse, ptCharmHad, numPvContributors, rapidity, invMassD0, invMassKPiLc, cosThetaStarEP, phiEP, outputMl, isRotatedCandidate, origin, ptBhadMother, resoChannelLc, absEtaTrackMin, numItsClsMin, numTpcClsMin, charge, nMuons, partRecoDstar, centrality); } } @@ -1871,7 +1931,11 @@ struct HfTaskCharmPolarisation { // random ROOT::Math::XYZVector const randomVec = ROOT::Math::XYZVector(std::sin(thetaRandom) * std::cos(phiRandom), std::sin(thetaRandom) * std::sin(phiRandom), std::cos(thetaRandom)); cosThetaStarRandom = randomVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()); - fillRecoHistos(invMassCharmHadForSparse, ptCharmHad, numPvContributors, rapidity, invMassD0, invMassKPiLc, cosThetaStarRandom, -99.f, outputMl, isRotatedCandidate, origin, ptBhadMother, resoChannelLc, absEtaTrackMin, numItsClsMin, numTpcClsMin, charge, nMuons, partRecoDstar); + if (doprocessDstarMcInPbPb || doprocessDstarMcWithMlInPbPb) { + fillRecoHistos(invMassCharmHadForSparse, ptCharmHad, numPvContributors, rapidity, invMassD0, invMassKPiLc, cosThetaStarRandom, -99.f, outputMl, isRotatedCandidate, origin, ptBhadMother, resoChannelLc, absEtaTrackMin, numItsClsMin, numTpcClsMin, charge, nMuons, partRecoDstar, centrality); + } else { + fillRecoHistos(invMassCharmHadForSparse, ptCharmHad, numPvContributors, rapidity, invMassD0, invMassKPiLc, cosThetaStarRandom, -99.f, outputMl, isRotatedCandidate, origin, ptBhadMother, resoChannelLc, absEtaTrackMin, numItsClsMin, numTpcClsMin, charge, nMuons, partRecoDstar); + } } /// Table for Lc->pKpi background studies @@ -2184,7 +2248,11 @@ struct HfTaskCharmPolarisation { if (activateTHnSparseCosThStarRandom) { ROOT::Math::XYZVector const randomVec = ROOT::Math::XYZVector(std::sin(thetaRandom) * std::cos(phiRandom), std::sin(thetaRandom) * std::sin(phiRandom), std::cos(thetaRandom)); float const cosThetaStarRandom = randomVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()); - fillGenHistos(ptCharmHad, numPvContributors, rapidity, cosThetaStarRandom, origin, ptBhadMother, areDauInAcc, resoChannelLc, charge, partRecoDstar); + if constexpr (WithCent) { + fillGenHistos(ptCharmHad, numPvContributors, rapidity, cosThetaStarRandom, origin, ptBhadMother, areDauInAcc, resoChannelLc, charge, partRecoDstar, *centrality); + } else { + fillGenHistos(ptCharmHad, numPvContributors, rapidity, cosThetaStarRandom, origin, ptBhadMother, areDauInAcc, resoChannelLc, charge, partRecoDstar); + } } } @@ -2330,7 +2398,7 @@ struct HfTaskCharmPolarisation { for (const auto& dstarCandidate : groupedDstarCandidates) { nCands++; - if (runPolarisationAnalysis(dstarCandidate, 0, numPvContributors, -1 /*MC particles*/, tracks, &qVecs)) { + if (runPolarisationAnalysis(dstarCandidate, 0, numPvContributors, -1 /*MC particles*/, tracks, centrality, &qVecs)) { nCandsInSignalRegion++; } } @@ -2359,7 +2427,7 @@ struct HfTaskCharmPolarisation { for (const auto& dstarCandidate : groupedDstarCandidates) { nCands++; - if (runPolarisationAnalysis(dstarCandidate, 0, numPvContributors, -1 /*MC particles*/, tracks, &qVecs)) { + if (runPolarisationAnalysis(dstarCandidate, 0, numPvContributors, -1 /*MC particles*/, tracks, centrality, &qVecs)) { nCandsInSignalRegion++; } } @@ -2394,7 +2462,7 @@ struct HfTaskCharmPolarisation { for (const auto& dstarCandidate : groupedDstarCandidates) { nCands++; - if (runPolarisationAnalysis(dstarCandidate, 0, numPvContributors, -1 /*MC particles*/, tracks)) { + if (runPolarisationAnalysis(dstarCandidate, 0, numPvContributors, -1 /*MC particles*/, tracks, centrality)) { nCandsInSignalRegion++; } } @@ -2434,7 +2502,7 @@ struct HfTaskCharmPolarisation { for (const auto& dstarCandidate : groupedDstarCandidates) { nCands++; - if (runPolarisationAnalysis(dstarCandidate, 0, numPvContributors, -1 /*MC particles*/, tracks)) { + if (runPolarisationAnalysis(dstarCandidate, 0, numPvContributors, -1 /*MC particles*/, tracks, centrality)) { nCandsInSignalRegion++; } } From f061493d4fb74e3c68b623db24e42ab3c711cf62 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Thu, 12 Mar 2026 00:31:47 +0100 Subject: [PATCH 259/347] [PWGEM/Dilepton] update skimmerPrimaryElectronQC.cxx (#15351) --- .../TableProducer/skimmerPrimaryElectronQC.cxx | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectronQC.cxx b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectronQC.cxx index 335fb978425..b50a0df8bab 100644 --- a/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectronQC.cxx +++ b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectronQC.cxx @@ -75,13 +75,14 @@ struct skimmerPrimaryElectronQC { struct : ConfigurableGroup { std::string prefix = "trackcut"; Configurable min_ncluster_tpc{"min_ncluster_tpc", 0, "min ncluster tpc"}; - Configurable mincrossedrows{"mincrossedrows", 40, "min. crossed rows"}; + Configurable mincrossedrows{"mincrossedrows", 0, "min. crossed rows"}; Configurable min_ncluster_its{"min_ncluster_its", 2, "min ncluster its"}; Configurable min_ncluster_itsib{"min_ncluster_itsib", 0, "min ncluster itsib"}; - Configurable min_tpc_cr_findable_ratio{"min_tpc_cr_findable_ratio", 0.8, "min. TPC Ncr/Nf ratio"}; + Configurable min_tpc_cr_findable_ratio{"min_tpc_cr_findable_ratio", 0.0, "min. TPC Ncr/Nf ratio"}; Configurable max_frac_shared_clusters_tpc{"max_frac_shared_clusters_tpc", 999.f, "max fraction of shared clusters in TPC"}; - Configurable maxchi2tpc{"maxchi2tpc", 5.0, "max. chi2/NclsTPC"}; - Configurable maxchi2its{"maxchi2its", 36.0, "max. chi2/NclsITS"}; + Configurable maxchi2tpc{"maxchi2tpc", 1e+10, "max. chi2/NclsTPC"}; + Configurable minchi2tpc{"minchi2tpc", -1e+10, "min. chi2/NclsTPC"}; + Configurable maxchi2its{"maxchi2its", 1e+10, "max. chi2/NclsITS"}; // actual maximum is 36 in the reconstruction. Configurable minchi2its{"minchi2its", -1e+10, "min. chi2/NclsITS"}; Configurable minpt{"minpt", 0.05, "min pt for ITS-TPC track"}; Configurable maxeta{"maxeta", 0.9, "eta acceptance"}; @@ -94,9 +95,9 @@ struct skimmerPrimaryElectronQC { struct : ConfigurableGroup { std::string prefix = "tighttrackcut"; - Configurable min_ncluster_tpc_pid{"min_ncluster_tpc_pid", 60, "min ncluster tpc used for PID"}; + Configurable min_ncluster_tpc_pid{"min_ncluster_tpc_pid", 0, "min ncluster tpc used for PID"}; Configurable min_ncluster_tpc{"min_ncluster_tpc", 0, "min ncluster tpc"}; - Configurable mincrossedrows{"mincrossedrows", 100, "min. crossed rows"}; + Configurable mincrossedrows{"mincrossedrows", 120, "min. crossed rows"}; Configurable min_ncluster_its{"min_ncluster_its", 5, "min ncluster its"}; Configurable min_ncluster_itsib{"min_ncluster_itsib", 3, "min ncluster itsib"}; Configurable min_tpc_cr_findable_ratio{"min_tpc_cr_findable_ratio", 0.8, "min. TPC Ncr/Nf ratio"}; @@ -309,7 +310,7 @@ struct skimmerPrimaryElectronQC { } if (track.hasTPC()) { - if (track.tpcChi2NCl() < 0.f || trackcut.maxchi2tpc < track.tpcChi2NCl()) { + if (track.tpcChi2NCl() < trackcut.minchi2tpc || trackcut.maxchi2tpc < track.tpcChi2NCl()) { return false; } From fea5cd24fdd3a91701036b1d94a5f097452cac3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Eduardo=20Mu=C3=B1oz=20M=C3=A9ndez?= <56033627+jmunozme@users.noreply.github.com> Date: Wed, 11 Mar 2026 20:57:01 -0600 Subject: [PATCH 260/347] [PWGLF,PWGMM] UPDATE eff param and json name of configurables (#15356) --- PWGMM/UE/Tasks/uecharged.cxx | 53 ++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/PWGMM/UE/Tasks/uecharged.cxx b/PWGMM/UE/Tasks/uecharged.cxx index dc65eeda8eb..9af0eb3cc2a 100644 --- a/PWGMM/UE/Tasks/uecharged.cxx +++ b/PWGMM/UE/Tasks/uecharged.cxx @@ -52,31 +52,31 @@ struct ueCharged { // Configurable for event selection Configurable isRun3{"isRun3", true, "is Run3 dataset"}; - Configurable pileuprejection{"pileuprejection", true, "Pileup rejection"}; - Configurable goodzvertex{"goodzvertex", true, "removes collisions with large differences between z of PV by tracks and z of PV from FT0 A-C time difference"}; - Configurable sel8{"sel8", true, "Apply the sel8 event selection"}; - Configurable removeITSROFBorder{"removeITSROFBorder", false, "Remove ITS Read-Out Frame border and only apply kIsTriggerTVX & kNoTimeFrameBorder (recommended for MC)"}; - Configurable cfgINELCut{"cfgINELCut", 0, "INEL event selection: 0 no sel, 1 INEL>0, 2 INEL>1"}; + Configurable pileuprejection{"event_pileuprejection", true, "Pileup rejection"}; + Configurable goodzvertex{"event_goodzvertex", true, "removes collisions with large differences between z of PV by tracks and z of PV from FT0 A-C time difference"}; + Configurable sel8{"event_sel8", true, "Apply the sel8 event selection"}; + Configurable removeITSROFBorder{"event_removeITSROFBorder", false, "Remove ITS Read-Out Frame border and only apply kIsTriggerTVX & kNoTimeFrameBorder (recommended for MC)"}; + Configurable cfgINELCut{"event_cfgINELCut", 0, "INEL event selection: 0 no sel, 1 INEL>0, 2 INEL>1"}; Configurable analyzeEvandTracksel{"analyzeEvandTracksel", true, "Analyze the event and track selection"}; // Track selection configurables TrackSelection myTrkSel; Configurable cfgTrkLowPtCut{"cfgTrkLowPtCut", 0.15f, "Minimum constituent pT"}; - Configurable isCustomTracks{"isCustomTracks", true, "Use custom track cuts"}; - Configurable setITSreq{"setITSreq", 0, "0 = Run3ITSibAny, 1 = Run3ITSallAny, 2 = Run3ITSall7Layers, 3 = Run3ITSibTwo"}; - Configurable minPt{"minPt", 0.1f, "Set minimum pT of tracks"}; - Configurable maxPt{"maxPt", 1e10f, "Set maximum pT of tracks"}; - Configurable requireEta{"requireEta", 0.8f, "Set eta range of tracks"}; - Configurable requireITSRefit{"requireITSRefit", true, "Additional cut on the ITS requirement"}; - Configurable requireTPCRefit{"requireTPCRefit", true, "Additional cut on the TPC requirement"}; - Configurable requireGoldenChi2{"requireGoldenChi2", true, "Additional cut on the GoldenChi2"}; - Configurable maxChi2PerClusterTPC{"maxChi2PerClusterTPC", 4.f, "Additional cut on the maximum value of the chi2 per cluster in the TPC"}; - Configurable maxChi2PerClusterITS{"maxChi2PerClusterITS", 36.f, "Additional cut on the maximum value of the chi2 per cluster in the ITS"}; - // Configurable minITSnClusters{"minITSnClusters", 5, "minimum number of found ITS clusters"}; - Configurable minNCrossedRowsTPC{"minNCrossedRowsTPC", 70.f, "Additional cut on the minimum number of crossed rows in the TPC"}; - Configurable minNCrossedRowsOverFindableClustersTPC{"minNCrossedRowsOverFindableClustersTPC", 0.8f, "Additional cut on the minimum value of the ratio between crossed rows and findable clusters in the TPC"}; - Configurable maxDcaXYFactor{"maxDcaXYFactor", 1.f, "Multiplicative factor on the maximum value of the DCA xy"}; - Configurable maxDcaZ{"maxDcaZ", 0.1f, "Additional cut on the maximum value of the DCA z"}; + Configurable isCustomTracks{"trkcfg_isCustomTracks", true, "Use custom track cuts"}; + Configurable setITSreq{"trkcfg_setITSreq", 0, "0 = Run3ITSibAny, 1 = Run3ITSallAny, 2 = Run3ITSall7Layers, 3 = Run3ITSibTwo"}; + Configurable minPt{"trkcfg_minPt", 0.1f, "Set minimum pT of tracks"}; + Configurable maxPt{"trkcfg_maxPt", 1e10f, "Set maximum pT of tracks"}; + Configurable requireEta{"trkcfg_requireEta", 0.8f, "Set eta range of tracks"}; + Configurable requireITSRefit{"trkcfg_requireITSRefit", true, "Additional cut on the ITS requirement"}; + Configurable requireTPCRefit{"trkcfg_requireTPCRefit", true, "Additional cut on the TPC requirement"}; + Configurable requireGoldenChi2{"trkcfg_requireGoldenChi2", true, "Additional cut on the GoldenChi2"}; + Configurable maxChi2PerClusterTPC{"trkcfg_maxChi2PerClusterTPC", 4.f, "Additional cut on the maximum value of the chi2 per cluster in the TPC"}; + Configurable maxChi2PerClusterITS{"trkcfg_maxChi2PerClusterITS", 36.f, "Additional cut on the maximum value of the chi2 per cluster in the ITS"}; + // Configurable minITSnClusters{"trkcfg_minITSnClusters", 5, "minimum number of found ITS clusters"}; + Configurable minNCrossedRowsTPC{"trkcfg_minNCrossedRowsTPC", 70.f, "Additional cut on the minimum number of crossed rows in the TPC"}; + Configurable minNCrossedRowsOverFindableClustersTPC{"trkcfg_minNCrossedRowsOverFindableClustersTPC", 0.8f, "Additional cut on the minimum value of the ratio between crossed rows and findable clusters in the TPC"}; + Configurable maxDcaXYFactor{"trkcfg_maxDcaXYFactor", 1.f, "Multiplicative factor on the maximum value of the DCA xy"}; + Configurable maxDcaZ{"trkcfg_maxDcaZ", 0.1f, "Additional cut on the maximum value of the DCA z"}; Service pdg; @@ -165,12 +165,13 @@ struct ueCharged { AxisSpec ptAxis = {ptBinning, "#it{p}_{T}^{assoc} (GeV/#it{c})"}; fEff.setObject(new TF1("fpara", - "(x<0.3)*((0.402353)+x*(1.90824)+x*x*(-3.37295)) +" - "(x>=0.3&&x<1.8)*((0.603846)+(0.30189)*x+(-0.240649)*" - "x*x+(0.0635382)*x*x*x) +" - "(x>=1.8&&x<14.)*((0.75982)+(-0.0241023)*x+" - "(0.00560107)*x*x+(-0.00048451)*x*x*x+" - "(1.43868e-05)*x*x*x*x)+(x>=14)*((0.755339)+(-0.000986326)*x)", + "(x<0.33)*((0.384347)+x*(1.77554)+x*x*(-2.9172)) +" + "(x>=0.33&&x<1.2)*((0.58547)+(0.293843)*x+(-0.293957)*" + "x*x+(0.109855)*x*x*x) +" + "(x>=1.2&&x<5.6)*((0.581232)+(0.205847)*x+" + "(-0.12133)*x*x+(0.0347906)*x*x*x+" + "(-0.0048334)*x*x*x*x+(0.000261644)*x*x*x*x*x)+(x>=5.6)*((0.711869)+(0.00364573)*x" + "+(-0.00019009)*x*x+(3.09894e-06)*x*x*x+(-1.81785e-08)*x*x*x*x)", 0., 1e5)); if (doprocessMC || doprocessMCTrue) { From 11f4dcb6b6fef85134ab75657f400e77fbe78a50 Mon Sep 17 00:00:00 2001 From: nzardosh Date: Thu, 12 Mar 2026 13:24:06 +0100 Subject: [PATCH 261/347] [PWGJE] fixing bug in background eta (#15361) --- PWGJE/Core/JetBkgSubUtils.cxx | 3 ++- PWGJE/TableProducer/rhoEstimator.cxx | 14 +++++--------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/PWGJE/Core/JetBkgSubUtils.cxx b/PWGJE/Core/JetBkgSubUtils.cxx index 32a2a0ed3bc..45f79a9fe97 100644 --- a/PWGJE/Core/JetBkgSubUtils.cxx +++ b/PWGJE/Core/JetBkgSubUtils.cxx @@ -28,6 +28,7 @@ #include #include +#include #include #include @@ -51,7 +52,7 @@ void JetBkgSubUtils::initialise() // Note: recommended to use R=0.2 jetDefBkg = fastjet::JetDefinition(algorithmBkg, jetBkgR, recombSchemeBkg, fastjet::Best); areaDefBkg = fastjet::AreaDefinition(fastjet::active_area_explicit_ghosts, ghostAreaSpec); - selRho = fastjet::SelectorEtaRange(bkgEtaMin, bkgEtaMax) && fastjet::SelectorPhiRange(bkgPhiMin, bkgPhiMax) && !fastjet::SelectorNHardest(nHardReject); // here we have to put rap range, to be checked! + selRho = fastjet::SelectorEtaRange(bkgEtaMin + jetBkgR, bkgEtaMax - jetBkgR) && fastjet::SelectorPhiRange(bkgPhiMin, bkgPhiMax) && !fastjet::SelectorNHardest(nHardReject); // here we have to put rap range, to be checked! } std::tuple JetBkgSubUtils::estimateRhoAreaMedian(const std::vector& inputParticles, bool doSparseSub) diff --git a/PWGJE/TableProducer/rhoEstimator.cxx b/PWGJE/TableProducer/rhoEstimator.cxx index 6f94e1e8785..a7a05e5ebe7 100644 --- a/PWGJE/TableProducer/rhoEstimator.cxx +++ b/PWGJE/TableProducer/rhoEstimator.cxx @@ -79,10 +79,6 @@ struct RhoEstimatorTask { Configurable jetAlgorithm{"jetAlgorithm", 0, "jet clustering algorithm. 0 = kT, 1 = C/A, 2 = Anti-kT"}; Configurable jetRecombScheme{"jetRecombScheme", 0, "jet recombination scheme. 0 = E-scheme, 1 = pT-scheme, 2 = pT2-scheme"}; Configurable bkgjetR{"bkgjetR", 0.2, "jet resolution parameter for determining background density"}; - Configurable bkgEtaMin{"bkgEtaMin", -0.7, "minimim pseudorapidity for determining background density"}; - Configurable bkgEtaMax{"bkgEtaMax", 0.7, "maximum pseudorapidity for determining background density"}; - Configurable bkgPhiMin{"bkgPhiMin", -6.283, "minimim phi for determining background density"}; - Configurable bkgPhiMax{"bkgPhiMax", 6.283, "maximum phi for determining background density"}; Configurable doSparse{"doSparse", false, "perfom sparse estimation"}; Configurable ghostRapMax{"ghostRapMax", 0.9, "Ghost rapidity max"}; Configurable ghostRepeat{"ghostRepeat", 1, "Ghost tiling repeats"}; @@ -127,13 +123,13 @@ struct RhoEstimatorTask { bkgSub.setJetAlgorithmAndScheme(static_cast(static_cast(config.jetAlgorithm)), static_cast(static_cast(config.jetRecombScheme))); bkgSub.setJetBkgR(config.bkgjetR); - bkgSub.setEtaMinMax(config.bkgEtaMin, config.bkgEtaMax); - bkgPhiMax_ = config.bkgPhiMax; - bkgPhiMin_ = config.bkgPhiMin; - if (config.bkgPhiMax > 98.0) { + bkgSub.setEtaMinMax(config.trackEtaMin, config.trackEtaMax); + bkgPhiMax_ = config.trackPhiMax; + bkgPhiMin_ = config.trackPhiMin; + if (config.trackPhiMax > 98.0) { bkgPhiMax_ = 2.0 * M_PI; } - if (config.bkgPhiMin < -98.0) { + if (config.trackPhiMin < -98.0) { bkgPhiMin_ = -2.0 * M_PI; } bkgSub.setPhiMinMax(bkgPhiMin_, bkgPhiMax_); From bc69d804b234d723fe33f529ccaf0d0a79c9ed6a Mon Sep 17 00:00:00 2001 From: Youssef El Mard <143704238+yelmardb@users.noreply.github.com> Date: Thu, 12 Mar 2026 14:05:46 +0100 Subject: [PATCH 262/347] [PWGEM] Add optional PCM material-budget weights in PCMPCM (#15139) Co-authored-by: Youssef El Mard Bouziani --- .../PhotonMeson/Core/MaterialBudgetWeights.h | 115 ++++++++++++++++++ PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h | 13 +- PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h | 19 ++- PWGEM/PhotonMeson/DataModel/gammaTables.h | 8 ++ .../PhotonMeson/TableProducer/CMakeLists.txt | 5 + .../TableProducer/materialBudgetWeights.cxx | 27 ++++ .../Tasks/Pi0EtaToGammaGammaMCPCMPCM.cxx | 3 +- .../Tasks/Pi0EtaToGammaGammaPCMPCM.cxx | 3 +- 8 files changed, 184 insertions(+), 9 deletions(-) create mode 100644 PWGEM/PhotonMeson/Core/MaterialBudgetWeights.h create mode 100644 PWGEM/PhotonMeson/TableProducer/materialBudgetWeights.cxx diff --git a/PWGEM/PhotonMeson/Core/MaterialBudgetWeights.h b/PWGEM/PhotonMeson/Core/MaterialBudgetWeights.h new file mode 100644 index 00000000000..41f4169f3bb --- /dev/null +++ b/PWGEM/PhotonMeson/Core/MaterialBudgetWeights.h @@ -0,0 +1,115 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +/// +/// \file materialBudgetWeights.cxx +/// +/// \brief This code produces a table to retrieve material budget weights. The table is to be join with V0PhotonKF +/// +/// \author Youssef El Mard (youssef.el.mard.bouziani@cern.ch) +/// + +#ifndef PWGEM_PHOTONMESON_CORE_MATERIALBUDGETWEIGHTS_H_ +#define PWGEM_PHOTONMESON_CORE_MATERIALBUDGETWEIGHTS_H_ + +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" + +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/Logger.h" +#include +#include +#include + +#include +#include + +using namespace o2; +using namespace o2::soa; +using namespace o2::framework; + +using MyV0PhotonsMB = o2::soa::Join; +using MyV0PhotonMB = MyV0PhotonsMB::iterator; + +struct MaterialBudgetWeights { + Produces omegaMBWeight; + + Configurable ccdbUrl{"ccdbUrl", "http://ccdb-test.cern.ch:8080", "CCDB url"}; + Configurable mbWeightsPath{"mbWeightsPath", "Users/y/yelmard/MaterialBudget/OmegaMBWeights", "Path of the mb weights"}; + + o2::ccdb::CcdbApi ccdbApi; + TH1F* hOmegaMBFromCCDB = nullptr; + + void init(InitContext&) + { + // Load CCDB object only when the real process is enabled + if (!doprocessMC) { + LOG(info) << "MaterialBudgetWeights: dummy mode enabled -> no CCDB query, will write weight=1"; + return; + } + + ccdbApi.init(ccdbUrl.value); + std::map metadata; + LOG(info) << "MaterialBudgetWeights: loading Omega MB histogram from CCDB at path: " << mbWeightsPath.value; + + hOmegaMBFromCCDB = ccdbApi.retrieveFromTFileAny(mbWeightsPath, metadata, -1); + + if (!hOmegaMBFromCCDB) { + LOG(fatal) << "MaterialBudgetWeights: CCDB object is missing. Path=" << mbWeightsPath.value; + } + } + + float computeMBWeight(float v0Rxy) + { + if (!hOmegaMBFromCCDB) { + return 1.f; + } + + int binMBWeight = hOmegaMBFromCCDB->FindBin(v0Rxy); + if (binMBWeight < 1 || binMBWeight > hOmegaMBFromCCDB->GetNbinsX()) { + LOG(debug) << "MaterialBudgetWeights: v0Rxy out of histogram range, returning 1"; + return 1.f; + } + + return hOmegaMBFromCCDB->GetBinContent(binMBWeight); + } + + // real process (weights from CCDB) + void processMC(MyV0PhotonMB const& v0) + { + static bool once = false; + if (!once) { + LOG(info) << "MaterialBudgetWeights: standard process running"; + once = true; + } + if (!hOmegaMBFromCCDB) { // histogram not loaded => behave like dummy + omegaMBWeight(1.f); + return; + } + omegaMBWeight(computeMBWeight(v0.v0radius())); + } + + // dummy process (always weight = 1) + void processDummy(MyV0PhotonMB const&) + { + static bool once = false; + if (!once) { + LOG(info) << "MaterialBudgetWeights: processDummy running"; + once = true; + } + omegaMBWeight(1.f); + } + + PROCESS_SWITCH(MaterialBudgetWeights, processMC, "Fill MB weights from CCDB", false); + PROCESS_SWITCH(MaterialBudgetWeights, processDummy, "Fill dummy MB weights (=1)", true); +}; + +#endif // PWGEM_PHOTONMESON_CORE_MATERIALBUDGETWEIGHTS_H_ diff --git a/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h b/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h index 0ff535f45dc..1eb74391520 100644 --- a/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h +++ b/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h @@ -238,7 +238,7 @@ struct Pi0EtaToGammaGamma { //--------------------------------------------------------------------------- // Preslices and partitions o2::framework::SliceCache cache; - o2::framework::PresliceOptional>> perCollision_pcm = o2::aod::v0photonkf::pmeventId; + o2::framework::PresliceOptional>> perCollision_pcm = o2::aod::v0photonkf::pmeventId; o2::framework::PresliceOptional> perCollision_emc = o2::aod::emccluster::pmeventId; o2::framework::PresliceOptional> perCollision_phos = o2::aod::phoscluster::pmeventId; o2::framework::PresliceOptional>> perCollision_electron = o2::aod::emprimaryelectronda::pmeventId; @@ -910,7 +910,16 @@ struct Pi0EtaToGammaGamma { continue; } - fRegistry.fill(HIST("Pair/same/hs"), v12.M(), v12.Pt(), weight); + float wpair = weight; + + if constexpr (requires { g1.omegaMBWeight(); }) { + wpair *= g1.omegaMBWeight(); + } + if constexpr (requires { g2.omegaMBWeight(); }) { + wpair *= g2.omegaMBWeight(); + } + + fRegistry.fill(HIST("Pair/same/hs"), v12.M(), v12.Pt(), wpair); if (std::find(used_photonIds_per_col.begin(), used_photonIds_per_col.end(), g1.globalIndex()) == used_photonIds_per_col.end()) { emh1->AddTrackToEventPool(key_df_collision, o2::aod::pwgem::dilepton::utils::EMTrack(g1.pt(), g1.eta(), g1.phi(), 0)); diff --git a/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h b/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h index a44ec614df0..442cf9d13b6 100644 --- a/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h +++ b/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h @@ -435,7 +435,7 @@ struct Pi0EtaToGammaGammaMC { } o2::framework::SliceCache cache; - o2::framework::PresliceOptional>> perCollision_pcm = o2::aod::v0photonkf::pmeventId; + o2::framework::PresliceOptional>> perCollision_pcm = o2::aod::v0photonkf::pmeventId; o2::framework::PresliceOptional> perCollision_emc = o2::aod::emccluster::pmeventId; o2::framework::PresliceOptional> perCollision_phos = o2::aod::phoscluster::pmeventId; o2::framework::PresliceOptional>> perCollision_electron = o2::aod::emprimaryelectronda::pmeventId; @@ -702,6 +702,15 @@ struct Pi0EtaToGammaGammaMC { continue; } + float wpair = weight; + + if constexpr (requires { g1.omegaMBWeight(); }) { + wpair *= g1.omegaMBWeight(); + } + if constexpr (requires { g2.omegaMBWeight(); }) { + wpair *= g2.omegaMBWeight(); + } + if (pairtype == o2::aod::pwgem::photonmeson::photonpair::PairType::kEMCEMC) { float openingAngle = std::acos(v1.Vect().Dot(v2.Vect()) / (v1.P() * v2.P())); if (openingAngle < emccuts.minOpenAngle) { @@ -711,9 +720,9 @@ struct Pi0EtaToGammaGammaMC { if (g1mc.globalIndex() == g2mc.globalIndex()) { if (o2::aod::pwgem::dilepton::utils::mcutil::getMotherPDGCode(g1mc, mcparticles) == 111) - fRegistry.fill(HIST("Pair/Pi0/hs_FromSameGamma"), v12.M(), v12.Pt(), weight); + fRegistry.fill(HIST("Pair/Pi0/hs_FromSameGamma"), v12.M(), v12.Pt(), wpair); else if (o2::aod::pwgem::dilepton::utils::mcutil::getMotherPDGCode(g1mc, mcparticles) == 221) - fRegistry.fill(HIST("Pair/Eta/hs_FromSameGamma"), v12.M(), v12.Pt(), weight); + fRegistry.fill(HIST("Pair/Eta/hs_FromSameGamma"), v12.M(), v12.Pt(), wpair); continue; } @@ -722,13 +731,13 @@ struct Pi0EtaToGammaGammaMC { if (cfgRequireTrueAssociation && (pi0mc.emmceventId() != collision.emmceventId())) { continue; } - o2::aod::pwgem::photonmeson::utils::nmhistogram::fillTruePairInfo(&fRegistry, v12, pi0mc, mcparticles, mccollisions, f1fd_k0s_to_pi0, weight); + o2::aod::pwgem::photonmeson::utils::nmhistogram::fillTruePairInfo(&fRegistry, v12, pi0mc, mcparticles, mccollisions, f1fd_k0s_to_pi0, wpair); } else if (etaid > 0) { auto etamc = mcparticles.iteratorAt(etaid); if (cfgRequireTrueAssociation && (etamc.emmceventId() != collision.emmceventId())) { continue; } - o2::aod::pwgem::photonmeson::utils::nmhistogram::fillTruePairInfo(&fRegistry, v12, etamc, mcparticles, mccollisions, f1fd_k0s_to_pi0, weight); + o2::aod::pwgem::photonmeson::utils::nmhistogram::fillTruePairInfo(&fRegistry, v12, etamc, mcparticles, mccollisions, f1fd_k0s_to_pi0, wpair); } } // end of pairing loop } else if constexpr (pairtype == o2::aod::pwgem::photonmeson::photonpair::PairType::kPCMDalitzEE) { diff --git a/PWGEM/PhotonMeson/DataModel/gammaTables.h b/PWGEM/PhotonMeson/DataModel/gammaTables.h index ee3d89310fa..afb88c6694a 100644 --- a/PWGEM/PhotonMeson/DataModel/gammaTables.h +++ b/PWGEM/PhotonMeson/DataModel/gammaTables.h @@ -719,6 +719,14 @@ DECLARE_SOA_TABLE(NonLinV0s, "AOD", "NONLINV0", //! table of non lin corrected v DECLARE_SOA_TABLE(NonLinEmcClusters, "AOD", "NONLINEMCCLUSTER", //! table of non lin corrected values for EMCal Photons (so far only E and pT) nonlin::CorrE, nonlin::CorrPt); //! +namespace v0photonMBweights +{ +DECLARE_SOA_COLUMN(OmegaMBWeight, omegaMBWeight, float); +} + +DECLARE_SOA_TABLE(V0PhotonOmegaMBWeights, "AOD", "V0PHOTONMBW", v0photonMBweights::OmegaMBWeight); // store MB weights. To be joined with V0PhotonsKF table at analysis level. + +using V0PhotonOmegaMBWeight = V0PhotonOmegaMBWeights::iterator; } // namespace o2::aod #endif // PWGEM_PHOTONMESON_DATAMODEL_GAMMATABLES_H_ diff --git a/PWGEM/PhotonMeson/TableProducer/CMakeLists.txt b/PWGEM/PhotonMeson/TableProducer/CMakeLists.txt index 5c265e57d96..99bccdf5c49 100644 --- a/PWGEM/PhotonMeson/TableProducer/CMakeLists.txt +++ b/PWGEM/PhotonMeson/TableProducer/CMakeLists.txt @@ -75,3 +75,8 @@ o2physics_add_dpl_workflow(pm-qvector-dummy-otf SOURCES pmQvectorDummyOtf.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(material-budget-weights + SOURCES materialBudgetWeights.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::CCDB ROOT::Hist ROOT::Core + COMPONENT_NAME Analysis) diff --git a/PWGEM/PhotonMeson/TableProducer/materialBudgetWeights.cxx b/PWGEM/PhotonMeson/TableProducer/materialBudgetWeights.cxx new file mode 100644 index 00000000000..6d235b0db0c --- /dev/null +++ b/PWGEM/PhotonMeson/TableProducer/materialBudgetWeights.cxx @@ -0,0 +1,27 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +/// +/// \file MaterialBudgetWeights.h +/// +/// \brief This code produces a table to retrieve material budget weights. The table is to be join with V0PhotonKF +/// +/// \author Youssef El Mard (youssef.el.mard.bouziani@cern.ch) + +#include "PWGEM/PhotonMeson/Core/MaterialBudgetWeights.h" + +#include "Framework/runDataProcessing.h" + +using namespace o2::framework; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaMCPCMPCM.cxx b/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaMCPCMPCM.cxx index 62c57593fd0..9ec33da1389 100644 --- a/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaMCPCMPCM.cxx +++ b/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaMCPCMPCM.cxx @@ -13,6 +13,7 @@ /// \brief This code loops over photons and makes pairs for neutral mesons analyses in MC for PCM-PCM. /// \author D. Sekihata, daiki.sekihata@cern.ch +#include "PWGEM/PhotonMeson/Core/MaterialBudgetWeights.h" #include "PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/PairUtilities.h" @@ -26,7 +27,7 @@ using namespace o2::aod; using namespace o2::framework; using namespace o2::aod::pwgem::photonmeson::photonpair; -using MyV0Photons = o2::soa::Filtered>; +using MyV0Photons = o2::soa::Filtered>; using MyMCV0Legs = soa::Join; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaPCMPCM.cxx b/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaPCMPCM.cxx index 6272af75da6..a19c2ac5be0 100644 --- a/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaPCMPCM.cxx +++ b/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaPCMPCM.cxx @@ -13,6 +13,7 @@ /// \brief This code loops over photons and makes pairs for neutral mesons analyses for PCM-PCM. /// \author D. Sekihata, daiki.sekihata@cern.ch +#include "PWGEM/PhotonMeson/Core/MaterialBudgetWeights.h" #include "PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/PairUtilities.h" @@ -26,7 +27,7 @@ using namespace o2::aod; using namespace o2::framework; using namespace o2::aod::pwgem::photonmeson::photonpair; -using MyV0Photons = o2::soa::Filtered>; +using MyV0Photons = o2::soa::Filtered>; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { From d22d05b0f8a8f571c5f487d5d4bb3eb970b8dd72 Mon Sep 17 00:00:00 2001 From: aferrero2707 Date: Thu, 12 Mar 2026 14:31:48 +0100 Subject: [PATCH 263/347] [PWGDQ] fixed configurable matching methods parameters (#15302) --- PWGDQ/Tasks/qaMatching.cxx | 175 ++++++++++++++++++++++++------------- 1 file changed, 112 insertions(+), 63 deletions(-) diff --git a/PWGDQ/Tasks/qaMatching.cxx b/PWGDQ/Tasks/qaMatching.cxx index c4e88a46d2b..ea18c0aa9d7 100644 --- a/PWGDQ/Tasks/qaMatching.cxx +++ b/PWGDQ/Tasks/qaMatching.cxx @@ -162,58 +162,107 @@ struct qaMatching { std::map mMatchingFunctionMap; ///< MFT-MCH Matching function // Chi2 matching interface - static constexpr int sChi2FunctionsNum = 3; + static constexpr int sChi2FunctionsNum = 5; struct : ConfigurableGroup { - std::array, sChi2FunctionsNum> fFunctionLabel{{ - {"cfgChi2FunctionLabel_0", std::string{"ProdAll"}, "Text label identifying this chi2 matching method"}, - {"cfgChi2FunctionLabel_1", std::string{"MatchXYPhiTanlMom"}, "Text label identifying this chi2 matching method"}, - {"cfgChi2FunctionLabel_2", std::string{"MatchXYPhiTanl"}, "Text label identifying this chi2 matching method"}, - }}; - std::array, sChi2FunctionsNum> fFunctionName{{{"cfgChi2FunctionNames_0", std::string{"prod"}, "Name of the chi2 matching function"}, - {"cfgChi2FunctionNames_1", std::string{"matchALL"}, "Name of the chi2 matching function"}, - {"cfgChi2FunctionNames_2", std::string{"matchXYPhiTanl"}, "Name of the chi2 matching function"}}}; - std::array, sChi2FunctionsNum> fMatchingScoreCut{{ - {"cfgChi2FunctionMatchingScoreCut_0", 0.f, "Minimum score value for selecting good matches"}, - {"cfgChi2FunctionMatchingScoreCut_1", 0.5f, "Minimum score value for selecting good matches"}, - {"cfgChi2FunctionMatchingScoreCut_2", 0.5f, "Minimum score value for selecting good matches"}, - }}; - std::array, sChi2FunctionsNum> fMatchingPlaneZ{{ - {"cfgChi2FunctionMatchingPlaneZ_0", static_cast(o2::mft::constants::mft::LayerZCoordinate()[9]), "Z position of the matching plane"}, - {"cfgChi2FunctionMatchingPlaneZ_1", static_cast(o2::mft::constants::mft::LayerZCoordinate()[9]), "Z position of the matching plane"}, - {"cfgChi2FunctionMatchingPlaneZ_2", static_cast(o2::mft::constants::mft::LayerZCoordinate()[9]), "Z position of the matching plane"}, - }}; - std::array, sChi2FunctionsNum> fMatchingExtrapMethod{{ - {"cfgMatchingExtrapMethod_0", static_cast(0), "Method for MCH track extrapolation to maching plane"}, - {"cfgMatchingExtrapMethod_1", static_cast(0), "Method for MCH track extrapolation to maching plane"}, - {"cfgMatchingExtrapMethod_2", static_cast(0), "Method for MCH track extrapolation to maching plane"}, - }}; + Configurable fFunctionLabel_1{"cfgChi2FunctionLabel_1", std::string{"ProdAll"}, "Text label identifying this chi2 matching method"}; + Configurable fFunctionLabel_2{"cfgChi2FunctionLabel_2", std::string{"MatchXYPhiTanlMom"}, "Text label identifying this chi2 matching method"}; + Configurable fFunctionLabel_3{"cfgChi2FunctionLabel_3", std::string{"MatchXYPhiTanl"}, "Text label identifying this chi2 matching method"}; + Configurable fFunctionLabel_4{"cfgChi2FunctionLabel_4", std::string{""}, "Text label identifying this chi2 matching method"}; + Configurable fFunctionLabel_5{"cfgChi2FunctionLabel_5", std::string{""}, "Text label identifying this chi2 matching method"}; + std::array*, sChi2FunctionsNum> fFunctionLabel{ + &fFunctionLabel_1, &fFunctionLabel_2, &fFunctionLabel_3, &fFunctionLabel_4, &fFunctionLabel_5}; + + Configurable fFunctionNames_1{"cfgChi2FunctionNames_1", std::string{"prod"}, "Name of the chi2 matching function"}; + Configurable fFunctionNames_2{"cfgChi2FunctionNames_2", std::string{"matchALL"}, "Name of the chi2 matching function"}; + Configurable fFunctionNames_3{"cfgChi2FunctionNames_3", std::string{"matchXYPhiTanl"}, "Name of the chi2 matching function"}; + Configurable fFunctionNames_4{"cfgChi2FunctionNames_4", std::string{""}, "Name of the chi2 matching function"}; + Configurable fFunctionNames_5{"cfgChi2FunctionNames_5", std::string{""}, "Name of the chi2 matching function"}; + std::array*, sChi2FunctionsNum> fFunctionName{ + &fFunctionNames_1, &fFunctionNames_2, &fFunctionNames_3, &fFunctionNames_4, &fFunctionNames_5}; + + Configurable fMatchingScoreCut_1{"cfgChi2FunctionMatchingScoreCut_1", 0.f, "Minimum score value for selecting good matches"}; + Configurable fMatchingScoreCut_2{"cfgChi2FunctionMatchingScoreCut_2", 0.5f, "Minimum score value for selecting good matches"}; + Configurable fMatchingScoreCut_3{"cfgChi2FunctionMatchingScoreCut_3", 0.5f, "Minimum score value for selecting good matches"}; + Configurable fMatchingScoreCut_4{"cfgChi2FunctionMatchingScoreCut_4", 0.5f, "Minimum score value for selecting good matches"}; + Configurable fMatchingScoreCut_5{"cfgChi2FunctionMatchingScoreCut_5", 0.5f, "Minimum score value for selecting good matches"}; + std::array*, sChi2FunctionsNum> fMatchingScoreCut{ + &fMatchingScoreCut_1, &fMatchingScoreCut_2, &fMatchingScoreCut_3, &fMatchingScoreCut_4, &fMatchingScoreCut_5}; + + Configurable fMatchingPlaneZ_1{"cfgChi2FunctionMatchingPlaneZ_1", static_cast(o2::mft::constants::mft::LayerZCoordinate()[9]), "Z position of the matching plane"}; + Configurable fMatchingPlaneZ_2{"cfgChi2FunctionMatchingPlaneZ_2", static_cast(o2::mft::constants::mft::LayerZCoordinate()[9]), "Z position of the matching plane"}; + Configurable fMatchingPlaneZ_3{"cfgChi2FunctionMatchingPlaneZ_3", static_cast(o2::mft::constants::mft::LayerZCoordinate()[9]), "Z position of the matching plane"}; + Configurable fMatchingPlaneZ_4{"cfgChi2FunctionMatchingPlaneZ_4", static_cast(o2::mft::constants::mft::LayerZCoordinate()[9]), "Z position of the matching plane"}; + Configurable fMatchingPlaneZ_5{"cfgChi2FunctionMatchingPlaneZ_5", static_cast(o2::mft::constants::mft::LayerZCoordinate()[9]), "Z position of the matching plane"}; + std::array*, sChi2FunctionsNum> fMatchingPlaneZ{ + &fMatchingPlaneZ_1, &fMatchingPlaneZ_2, &fMatchingPlaneZ_3, &fMatchingPlaneZ_4, &fMatchingPlaneZ_5}; + + Configurable fMatchingExtrapMethod_1{"cfgChi2MatchingExtrapMethod_1", static_cast(0), "Method for MCH track extrapolation to maching plane"}; + Configurable fMatchingExtrapMethod_2{"cfgChi2MatchingExtrapMethod_2", static_cast(0), "Method for MCH track extrapolation to maching plane"}; + Configurable fMatchingExtrapMethod_3{"cfgChi2MatchingExtrapMethod_3", static_cast(0), "Method for MCH track extrapolation to maching plane"}; + Configurable fMatchingExtrapMethod_4{"cfgChi2MatchingExtrapMethod_4", static_cast(0), "Method for MCH track extrapolation to maching plane"}; + Configurable fMatchingExtrapMethod_5{"cfgChi2MatchingExtrapMethod_5", static_cast(0), "Method for MCH track extrapolation to maching plane"}; + std::array*, sChi2FunctionsNum> fMatchingExtrapMethod{ + &fMatchingExtrapMethod_1, &fMatchingExtrapMethod_2, &fMatchingExtrapMethod_3, &fMatchingExtrapMethod_4, &fMatchingExtrapMethod_5}; } fConfigChi2MatchingOptions; // ML interface - static constexpr int sMLModelsNum = 2; + static constexpr int sMLModelsNum = 5; struct : ConfigurableGroup { - std::array, sMLModelsNum> fModelLabel{{ - {"cfgMLModelLabel_0", std::string{""}, "Text label identifying this group of ML models"}, - {"cfgMLModelLabel_1", std::string{""}, "Text label identifying this group of ML models"}, - }}; - std::array>, sMLModelsNum> fModelPathsCCDB{{{"cfgMLModelPathsCCDB_0", std::vector{"Users/m/mcoquet/MLTest"}, "Paths of models on CCDB"}, - {"cfgMLModelPathsCCDB_1", std::vector{}, "Paths of models on CCDB"}}}; - std::array>, sMLModelsNum> fInputFeatures{{{"cfgMLInputFeatures_0", std::vector{"chi2MCHMFT"}, "Names of ML model input features"}, - {"cfgMLInputFeatures_1", std::vector{}, "Names of ML model input features"}}}; - std::array>, sMLModelsNum> fModelNames{{{"cfgMLModelNames_0", std::vector{"model.onnx"}, "ONNX file names for each pT bin (if not from CCDB full path)"}, - {"cfgMLModelNames_1", std::vector{}, "ONNX file names for each pT bin (if not from CCDB full path)"}}}; - std::array, sMLModelsNum> fMatchingScoreCut{{ - {"cfgMLModelMatchingScoreCut_0", 0.f, "Minimum score value for selecting good matches"}, - {"cfgMLModelMatchingScoreCut_1", 0.f, "Minimum score value for selecting good matches"}, - }}; - std::array, sMLModelsNum> fMatchingPlaneZ{{ - {"cfgMLModelMatchingPlaneZ_0", static_cast(o2::mft::constants::mft::LayerZCoordinate()[9]), "Z position of the matching plane"}, - {"cfgMLModelMatchingPlaneZ_1", 0.f, "Z position of the matching plane"}, - }}; - std::array, sMLModelsNum> fMatchingExtrapMethod{{ - {"cfgMatchingExtrapMethod_0", static_cast(0), "Method for MCH track extrapolation to maching plane"}, - {"cfgMatchingExtrapMethod_1", static_cast(0), "Method for MCH track extrapolation to maching plane"}, - }}; + Configurable fModelLabel_1{"cfgMLModelLabel_1", std::string{""}, "Text label identifying this group of ML models"}; + Configurable fModelLabel_2{"cfgMLModelLabel_2", std::string{""}, "Text label identifying this group of ML models"}; + Configurable fModelLabel_3{"cfgMLModelLabel_3", std::string{""}, "Text label identifying this group of ML models"}; + Configurable fModelLabel_4{"cfgMLModelLabel_4", std::string{""}, "Text label identifying this group of ML models"}; + Configurable fModelLabel_5{"cfgMLModelLabel_5", std::string{""}, "Text label identifying this group of ML models"}; + std::array*, sMLModelsNum> fModelLabel{ + &fModelLabel_1, &fModelLabel_2, &fModelLabel_3, &fModelLabel_4, &fModelLabel_5}; + + Configurable fModelPathCCDB_1{"cfgMLModelPathCCDB_1", "Users/m/mcoquet/MLTest", "Paths of models on CCDB"}; + Configurable fModelPathCCDB_2{"cfgMLModelPathsCCDB_2", std::string{""}, "Paths of models on CCDB"}; + Configurable fModelPathCCDB_3{"cfgMLModelPathsCCDB_3", std::string{""}, "Paths of models on CCDB"}; + Configurable fModelPathCCDB_4{"cfgMLModelPathsCCDB_4", std::string{""}, "Paths of models on CCDB"}; + Configurable fModelPathCCDB_5{"cfgMLModelPathsCCDB_5", std::string{""}, "Paths of models on CCDB"}; + std::array*, sMLModelsNum> fModelPathCCDB{ + &fModelPathCCDB_1, &fModelPathCCDB_2, &fModelPathCCDB_3, &fModelPathCCDB_4, &fModelPathCCDB_5}; + + Configurable fModelName_1{"cfgMLModelName_1", "model.onnx", "ONNX file names for each pT bin (if not from CCDB full path)"}; + Configurable fModelName_2{"cfgMLModelNames_2", std::string{""}, "ONNX file names for each pT bin (if not from CCDB full path)"}; + Configurable fModelName_3{"cfgMLModelNames_3", std::string{""}, "ONNX file names for each pT bin (if not from CCDB full path)"}; + Configurable fModelName_4{"cfgMLModelNames_4", std::string{""}, "ONNX file names for each pT bin (if not from CCDB full path)"}; + Configurable fModelName_5{"cfgMLModelNames_5", std::string{""}, "ONNX file names for each pT bin (if not from CCDB full path)"}; + std::array*, sMLModelsNum> fModelName{ + &fModelName_1, &fModelName_2, &fModelName_3, &fModelName_4, &fModelName_5}; + + Configurable fInputFeatures_1{"cfgMLInputFeatures_1", "chi2MCHMFT", "Names of ML model input features"}; + Configurable fInputFeatures_2{"cfgMLInputFeatures_2", std::string{""}, "Names of ML model input features"}; + Configurable fInputFeatures_3{"cfgMLInputFeatures_3", std::string{""}, "Names of ML model input features"}; + Configurable fInputFeatures_4{"cfgMLInputFeatures_4", std::string{""}, "Names of ML model input features"}; + Configurable fInputFeatures_5{"cfgMLInputFeatures_5", std::string{""}, "Names of ML model input features"}; + std::array*, sMLModelsNum> fInputFeatures{ + &fInputFeatures_1, &fInputFeatures_2, &fInputFeatures_3, &fInputFeatures_4, &fInputFeatures_5}; + + Configurable fMatchingScoreCut_1{"cfgMLModelMatchingScoreCut_1", 0.f, "Minimum score value for selecting good matches"}; + Configurable fMatchingScoreCut_2{"cfgMLModelMatchingScoreCut_2", 0.f, "Minimum score value for selecting good matches"}; + Configurable fMatchingScoreCut_3{"cfgMLModelMatchingScoreCut_3", 0.f, "Minimum score value for selecting good matches"}; + Configurable fMatchingScoreCut_4{"cfgMLModelMatchingScoreCut_4", 0.f, "Minimum score value for selecting good matches"}; + Configurable fMatchingScoreCut_5{"cfgMLModelMatchingScoreCut_5", 0.f, "Minimum score value for selecting good matches"}; + std::array*, sMLModelsNum> fMatchingScoreCut{ + &fMatchingScoreCut_1, &fMatchingScoreCut_2, &fMatchingScoreCut_3, &fMatchingScoreCut_4, &fMatchingScoreCut_5}; + + Configurable fMatchingPlaneZ_1{"cfgMLModelMatchingPlaneZ_1", static_cast(o2::mft::constants::mft::LayerZCoordinate()[9]), "Z position of the matching plane"}; + Configurable fMatchingPlaneZ_2{"cfgMLModelMatchingPlaneZ_2", 0.f, "Z position of the matching plane"}; + Configurable fMatchingPlaneZ_3{"cfgMLModelMatchingPlaneZ_3", 0.f, "Z position of the matching plane"}; + Configurable fMatchingPlaneZ_4{"cfgMLModelMatchingPlaneZ_4", 0.f, "Z position of the matching plane"}; + Configurable fMatchingPlaneZ_5{"cfgMLModelMatchingPlaneZ_5", 0.f, "Z position of the matching plane"}; + std::array*, sMLModelsNum> fMatchingPlaneZ{ + &fMatchingPlaneZ_1, &fMatchingPlaneZ_2, &fMatchingPlaneZ_3, &fMatchingPlaneZ_4, &fMatchingPlaneZ_5}; + + Configurable fMatchingExtrapMethod_1{"cfgMLMatchingExtrapMethod_1", static_cast(0), "Method for MCH track extrapolation to maching plane"}; + Configurable fMatchingExtrapMethod_2{"cfgMLMatchingExtrapMethod_2", static_cast(0), "Method for MCH track extrapolation to maching plane"}; + Configurable fMatchingExtrapMethod_3{"cfgMLMatchingExtrapMethod_3", static_cast(0), "Method for MCH track extrapolation to maching plane"}; + Configurable fMatchingExtrapMethod_4{"cfgMLMatchingExtrapMethod_4", static_cast(0), "Method for MCH track extrapolation to maching plane"}; + Configurable fMatchingExtrapMethod_5{"cfgMLMatchingExtrapMethod_5", static_cast(0), "Method for MCH track extrapolation to maching plane"}; + std::array*, sMLModelsNum> fMatchingExtrapMethod{ + &fMatchingExtrapMethod_1, &fMatchingExtrapMethod_2, &fMatchingExtrapMethod_3, &fMatchingExtrapMethod_4, &fMatchingExtrapMethod_5}; } fConfigMlOptions; std::vector binsPtMl; @@ -932,11 +981,11 @@ struct qaMatching { // Matching functions InitMatchingFunctions(); for (size_t funcId = 0; funcId < sChi2FunctionsNum; funcId++) { - auto label = fConfigChi2MatchingOptions.fFunctionLabel[funcId].value; - auto funcName = fConfigChi2MatchingOptions.fFunctionName[funcId].value; - auto scoreMin = fConfigChi2MatchingOptions.fMatchingScoreCut[funcId].value; - auto matchingPlaneZ = fConfigChi2MatchingOptions.fMatchingPlaneZ[funcId].value; - auto extrapMethod = fConfigChi2MatchingOptions.fMatchingExtrapMethod[funcId].value; + auto label = fConfigChi2MatchingOptions.fFunctionLabel[funcId]->value; + auto funcName = fConfigChi2MatchingOptions.fFunctionName[funcId]->value; + auto scoreMin = fConfigChi2MatchingOptions.fMatchingScoreCut[funcId]->value; + auto matchingPlaneZ = fConfigChi2MatchingOptions.fMatchingPlaneZ[funcId]->value; + auto extrapMethod = fConfigChi2MatchingOptions.fMatchingExtrapMethod[funcId]->value; if (label == "" || funcName == "") break; @@ -956,20 +1005,20 @@ struct qaMatching { o2::framework::LabeledArray mycutsMl(cutValues.data(), 1, 1, std::vector{"pT bin 0"}, std::vector{"score"}); for (size_t modelId = 0; modelId < sMLModelsNum; modelId++) { - auto label = fConfigMlOptions.fModelLabel[modelId].value; - auto modelPaths = fConfigMlOptions.fModelPathsCCDB[modelId].value; - auto inputFeatures = fConfigMlOptions.fInputFeatures[modelId].value; - auto modelNames = fConfigMlOptions.fModelNames[modelId].value; - auto scoreMin = fConfigMlOptions.fMatchingScoreCut[modelId].value; - auto matchingPlaneZ = fConfigMlOptions.fMatchingPlaneZ[modelId].value; - auto extrapMethod = fConfigMlOptions.fMatchingExtrapMethod[modelId].value; - - if (label == "" || modelPaths.empty() || inputFeatures.empty() || modelNames.empty()) + auto label = fConfigMlOptions.fModelLabel[modelId]->value; + auto modelPath = fConfigMlOptions.fModelPathCCDB[modelId]->value; + auto inputFeatures = fConfigMlOptions.fInputFeatures[modelId]->value; + auto modelName = fConfigMlOptions.fModelName[modelId]->value; + auto scoreMin = fConfigMlOptions.fMatchingScoreCut[modelId]->value; + auto matchingPlaneZ = fConfigMlOptions.fMatchingPlaneZ[modelId]->value; + auto extrapMethod = fConfigMlOptions.fMatchingExtrapMethod[modelId]->value; + + if (label == "" || modelPath == "" || inputFeatures == "" || modelName == "") break; matchingMlResponses[label].configure(binsPtMl, mycutsMl, cutDirMl, 1); - matchingMlResponses[label].setModelPathsCCDB(modelNames, fCCDBApi, modelPaths, fConfigCCDB.fConfigNoLaterThan.value); - matchingMlResponses[label].cacheInputFeaturesIndices(inputFeatures); + matchingMlResponses[label].setModelPathsCCDB(std::vector{modelName}, fCCDBApi, std::vector{modelPath}, fConfigCCDB.fConfigNoLaterThan.value); + matchingMlResponses[label].cacheInputFeaturesIndices(std::vector{inputFeatures}); matchingMlResponses[label].init(); matchingScoreCuts[label] = scoreMin; From 325754fcb744d9b7f7f05c735ef0024dadce8301 Mon Sep 17 00:00:00 2001 From: choich08365 <157435123+choich08365@users.noreply.github.com> Date: Thu, 12 Mar 2026 22:48:50 +0900 Subject: [PATCH 264/347] [PWGJE] GNN b-jet histograms revised (#15347) Co-authored-by: Changhwan Choi Co-authored-by: ALICE Action Bot --- PWGJE/Tasks/bjetTaggingGnn.cxx | 80 ++++++++++++++++++++++------------ 1 file changed, 53 insertions(+), 27 deletions(-) diff --git a/PWGJE/Tasks/bjetTaggingGnn.cxx b/PWGJE/Tasks/bjetTaggingGnn.cxx index a11288129f5..be7ec455b65 100644 --- a/PWGJE/Tasks/bjetTaggingGnn.cxx +++ b/PWGJE/Tasks/bjetTaggingGnn.cxx @@ -263,22 +263,24 @@ struct BjetTaggingGnn { registry.add("h_gnnfeat_trackPhi", "", {HistType::kTH1F, {{200, 0., 2. * M_PI, "#it{#phi}"}}}); registry.add("h_gnnfeat_trackEta", "", {HistType::kTH1F, {{200, -0.9, 0.9, "#it{#eta}"}}}); registry.add("h_gnnfeat_trackCharge", "", {HistType::kTH1F, {{3, -1., 2., "#it{q}"}}}); - registry.add("h_gnnfeat_trackDCAxy", "", {HistType::kTH1F, {{200, -5., 5., "DCA_#it{xy} (cm)"}}}); - registry.add("h_gnnfeat_trackSigmaDCAxy", "", {HistType::kTH1F, {{200, 0., 5., "#it{#sigma}_{{DCA_#it{xy}} (cm)"}}}); - registry.add("h_gnnfeat_trackDCAz", "", {HistType::kTH1F, {{200, -5., 5., "DCA_#it{z} (cm)"}}}); - registry.add("h_gnnfeat_trackSigmaDCAz", "", {HistType::kTH1F, {{200, 0., 5., "#it{#sigma}_{{DCA_#it{z}} (cm)"}}}); + registry.add("h_gnnfeat_trackDCAxy", "", {HistType::kTH1F, {{200, -5., 5., "DCA_{#it{xy}} (cm)"}}}); + registry.add("h_gnnfeat_trackSigmaDCAxy", "", {HistType::kTH1F, {{200, 0., 5., "#it{#sigma}_{{DCA_{#it{xy}}} (cm)"}}}); + registry.add("h_gnnfeat_trackDCAz", "", {HistType::kTH1F, {{200, -5., 5., "DCA_{#it{z}} (cm)"}}}); + registry.add("h_gnnfeat_trackSigmaDCAz", "", {HistType::kTH1F, {{200, 0., 5., "#it{#sigma}_{{DCA_{#it{z}}} (cm)"}}}); registry.add("h_gnnfeat_trackITSChi2NCl", "", {HistType::kTH1F, {{200, 0., 40., "ITS #it{#chi}^{2}/ndf"}}}); registry.add("h_gnnfeat_trackTPCChi2NCl", "", {HistType::kTH1F, {{200, 0., 5., "TPC #it{#chi}^{2}/ndf"}}}); registry.add("h_gnnfeat_trackITSNCls", "", {HistType::kTH1F, {{8, 0., 8., "ITS NCls"}}}); registry.add("h_gnnfeat_trackTPCNCls", "", {HistType::kTH1F, {{153, 0., 153., "TPC NCls"}}}); registry.add("h_gnnfeat_trackTPCNCrossedRows", "", {HistType::kTH1F, {{153, 0., 153., "TPC NCrossedRows"}}}); - registry.add("h_gnnfeat_tracksIPxy", "", {HistType::kTH1F, {{200, -5., 5., "{sIP}_#it{xy}"}}}); - registry.add("h_gnnfeat_tracksIPz", "", {HistType::kTH1F, {{200, -5., 5., "{sIP}_#it{z}"}}}); + registry.add("h_gnnfeat_tracksIPxy", "", {HistType::kTH1F, {{200, -5., 5., "{sIP}_{#it{xy}}"}}}); + registry.add("h_gnnfeat_tracksIPz", "", {HistType::kTH1F, {{200, -5., 5., "{sIP}_{#it{z}}"}}}); if (doprocessDataTracks || doprocessMCDTracks) { registry.add("h_trackpT", "", {HistType::kTH1F, {axisTrackpT}}, callSumw2); registry.add("h_tracketa", "", {HistType::kTH1F, {{100, trackEtaMin, trackEtaMax, "#it{#eta}"}}}, callSumw2); registry.add("h_trackphi", "", {HistType::kTH1F, {{100, 0.0, 2.0 * M_PI, "#it{#phi}"}}}, callSumw2); + registry.add("h_dcaXY", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{xy}}| (cm)"}}}, callSumw2); + registry.add("h_dcaZ", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{z}}| (cm)"}}}, callSumw2); } if (doprocessMCDTracks) { @@ -286,18 +288,23 @@ struct BjetTaggingGnn { registry.add("h_partpT_matched_fine", "", {HistType::kTH1F, {axisTrackpTFine}}, callSumw2); registry.add("h_partpT", "", {HistType::kTH1F, {axisTrackpT}}, callSumw2); registry.add("h_partpT_fine", "", {HistType::kTH1F, {axisTrackpTFine}}, callSumw2); - registry.add("h_dcaXY_coll_matched", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_#it{xy}| (cm)"}}}, callSumw2); - registry.add("h_dcaXY_coll_matched_b", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_#it{xy}| (cm)"}}}, callSumw2); - registry.add("h_dcaXY_coll_matched_c", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_#it{xy}| (cm)"}}}, callSumw2); - registry.add("h_dcaXY_coll_matched_lf", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_#it{xy}| (cm)"}}}, callSumw2); - registry.add("h_dcaXY_coll_mismatched", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_#it{xy}| (cm)"}}}, callSumw2); - registry.add("h_dcaXY_npp", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_#it{xy}| (cm)"}}}, callSumw2); - registry.add("h_dcaZ_coll_matched", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_#it{z}| (cm)"}}}, callSumw2); - registry.add("h_dcaZ_coll_matched_b", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_#it{z}| (cm)"}}}, callSumw2); - registry.add("h_dcaZ_coll_matched_c", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_#it{z}| (cm)"}}}, callSumw2); - registry.add("h_dcaZ_coll_matched_lf", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_#it{z}| (cm)"}}}, callSumw2); - registry.add("h_dcaZ_coll_mismatched", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_#it{z}| (cm)"}}}, callSumw2); - registry.add("h_dcaZ_npp", "", {HistType::kTH1F, {{200, 0., 5., "|DCA_#it{z}| (cm)"}}}, callSumw2); + // DCA cut study histograms (pT > pTMin) + registry.add("h_dcaXY_coll_fake", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{xy}}| (cm)"}}}, callSumw2); // tracks from fake collisions + registry.add("h_dcaXY_fake", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{xy}}| (cm)"}}}, callSumw2); // fake tracks (no matched particle) + registry.add("h_dcaXY_coll_matched", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{xy}}| (cm)"}}}, callSumw2); // tracks from matched collisions + registry.add("h_dcaXY_coll_matched_b", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{xy}}| (cm)"}}}, callSumw2); // tracks from matched collisions, b hadron decay + registry.add("h_dcaXY_coll_matched_c", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{xy}}| (cm)"}}}, callSumw2); // tracks from matched collisions, c hadron decay + registry.add("h_dcaXY_coll_matched_lf", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{xy}}| (cm)"}}}, callSumw2); // tracks from matched collisions, others + registry.add("h_dcaXY_coll_mismatched", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{xy}}| (cm)"}}}, callSumw2); // tracks from mismatched collisions + registry.add("h_dcaXY_npp", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{xy}}| (cm)"}}}, callSumw2); // non-physical primary tracks (GenStatusCode=-1) + registry.add("h_dcaZ_coll_fake", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{z}}| (cm)"}}}, callSumw2); + registry.add("h_dcaZ_fake", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{z}}| (cm)"}}}, callSumw2); + registry.add("h_dcaZ_coll_matched", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{z}}| (cm)"}}}, callSumw2); + registry.add("h_dcaZ_coll_matched_b", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{z}}| (cm)"}}}, callSumw2); + registry.add("h_dcaZ_coll_matched_c", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{z}}| (cm)"}}}, callSumw2); + registry.add("h_dcaZ_coll_matched_lf", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{z}}| (cm)"}}}, callSumw2); + registry.add("h_dcaZ_coll_mismatched", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{z}}| (cm)"}}}, callSumw2); + registry.add("h_dcaZ_npp", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{z}}| (cm)"}}}, callSumw2); } if (doprocessDataJetsSel || doprocessMCDJetsSel) { @@ -822,6 +829,10 @@ struct BjetTaggingGnn { registry.fill(HIST("h_trackpT"), track.pt()); registry.fill(HIST("h_tracketa"), track.eta()); registry.fill(HIST("h_trackphi"), track.phi()); + if (track.pt() >= trackPtMin) { + registry.fill(HIST("h_dcaXY"), std::fabs(track.dcaXY())); + registry.fill(HIST("h_dcaZ"), std::fabs(track.dcaZ())); + } } } PROCESS_SWITCH(BjetTaggingGnn, processDataTracks, "track information in Data", false); @@ -1095,17 +1106,34 @@ struct BjetTaggingGnn { registry.fill(HIST("h_trackpT"), track.pt(), weightEvt); registry.fill(HIST("h_tracketa"), track.eta(), weightEvt); registry.fill(HIST("h_trackphi"), track.phi(), weightEvt); + if (track.pt() >= trackPtMin) { + registry.fill(HIST("h_dcaXY"), std::fabs(track.dcaXY()), weightEvt); + registry.fill(HIST("h_dcaZ"), std::fabs(track.dcaZ()), weightEvt); + } - if (!matchedMcColl || !track.has_mcParticle()) { + if (!matchedMcColl) { + if (track.pt() >= trackPtMin) { + registry.fill(HIST("h_dcaXY_coll_fake"), std::fabs(track.dcaXY()), weightEvt); + registry.fill(HIST("h_dcaZ_coll_fake"), std::fabs(track.dcaZ()), weightEvt); + } + continue; + } + if (!track.has_mcParticle()) { + if (track.pt() >= trackPtMin) { + registry.fill(HIST("h_dcaXY_fake"), std::fabs(track.dcaXY()), weightEvt); + registry.fill(HIST("h_dcaZ_fake"), std::fabs(track.dcaZ()), weightEvt); + } continue; } auto particle = track.template mcParticle_as(); - if (particle.isPhysicalPrimary()) { - if (particle.eta() > trackEtaMin && particle.eta() < trackEtaMax) { + if (particle.eta() > trackEtaMin && particle.eta() < trackEtaMax) { + if (particle.isPhysicalPrimary()) { registry.fill(HIST("h2_trackpT_partpT"), track.pt(), particle.pt(), weightEvt); registry.fill(HIST("h_partpT_matched_fine"), particle.pt(), weightEvt); + } + if (track.pt() >= trackPtMin) { // Track association accuracy as a function of DCA - if (track.pt() >= trackPtMin) { + if (particle.isPhysicalPrimary()) { if (particle.mcCollisionId() == collision.mcCollisionId()) { registry.fill(HIST("h_dcaXY_coll_matched"), std::fabs(track.dcaXY()), weightEvt); // Matched to particle from the same MC collision registry.fill(HIST("h_dcaZ_coll_matched"), std::fabs(track.dcaZ()), weightEvt); @@ -1124,13 +1152,11 @@ struct BjetTaggingGnn { registry.fill(HIST("h_dcaXY_coll_mismatched"), std::fabs(track.dcaXY()), weightEvt); // Matched to particle from a different MC collision registry.fill(HIST("h_dcaZ_coll_mismatched"), std::fabs(track.dcaZ()), weightEvt); } + } else { + registry.fill(HIST("h_dcaXY_npp"), std::fabs(track.dcaXY()), weightEvt); + registry.fill(HIST("h_dcaZ_npp"), std::fabs(track.dcaZ()), weightEvt); } } - } else { - if (particle.eta() > trackEtaMin && particle.eta() < trackEtaMax && track.pt() >= trackPtMin) { - registry.fill(HIST("h_dcaXY_npp"), std::fabs(track.dcaXY()), weightEvt); - registry.fill(HIST("h_dcaZ_npp"), std::fabs(track.dcaZ()), weightEvt); - } } } From d379359829330d63cbdabc059f893b03401ec012 Mon Sep 17 00:00:00 2001 From: YazhenLin Date: Thu, 12 Mar 2026 23:36:13 +0800 Subject: [PATCH 265/347] [PWGDQ] Add some code in dqEnergyCorrelator_direct.cxx (#15360) --- PWGDQ/Tasks/dqEnergyCorrelator_direct.cxx | 30 ++++++++++++++++------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/PWGDQ/Tasks/dqEnergyCorrelator_direct.cxx b/PWGDQ/Tasks/dqEnergyCorrelator_direct.cxx index 9f54bbe1980..b70af0b51d4 100644 --- a/PWGDQ/Tasks/dqEnergyCorrelator_direct.cxx +++ b/PWGDQ/Tasks/dqEnergyCorrelator_direct.cxx @@ -131,6 +131,7 @@ struct AnalysisEnergyCorrelator { Configurable fConfigMCGenSignalsJSON{"cfgMCGenDileptonHadronSignalsJSON", "", "Comma separated list of MC signals (generated) via JSON"}; Configurable fConfigMCGenHadronEtaAbs{"cfgMCGenHadronEtaAbs", 0.9f, "eta abs range for the hadron"}; Configurable fConfigMCGenHadronPtMin{"cfgMCGenHadronPtMin", 0.1f, "minimum pt for the hadron"}; + Configurable fConfigContainlepton{"cfgContainlepton", false, "If true, require the hadron to contain the lepton in its decay tree for the energy correlator study"}; } fConfigDileptonHadronOptions; // Histogram configurables @@ -397,9 +398,11 @@ struct AnalysisEnergyCorrelator { if (isMCGen_energycorrelators) { DefineHistograms(fHistMan, Form("MCTruthGenSel_%s", sig->GetName()), ""); DefineHistograms(fHistMan, Form("MCTruthEenergyCorrelators_%s", sig->GetName()), ""); + DefineHistograms(fHistMan, Form("MCTruthEenergyCorrelators_Pion_%s", sig->GetName()), ""); } if (isMCGen_energycorrelatorsME) { DefineHistograms(fHistMan, Form("MCTruthEenergyCorrelatorsME_%s", sig->GetName()), ""); + DefineHistograms(fHistMan, Form("MCTruthEenergyCorrelatorsME_Pion_%s", sig->GetName()), ""); } } } @@ -786,7 +789,7 @@ struct AnalysisEnergyCorrelator { } PresliceUnsorted perReducedMcEvent = aod::mcparticle::mcCollisionId; - template + template void runEnergyCorrelators(TEvent const& event1, TEvent const& event2, McParticles const& mcTracks) { auto groupedMCTracks1 = mcTracks.sliceBy(perReducedMcEvent, event1.mcCollisionId()); @@ -801,7 +804,7 @@ struct AnalysisEnergyCorrelator { continue; } VarManager::FillTrackMC(groupedMCTracks1, t1_raw); - if (!MixedEvent) { + if (!MixedEvent && !PionMass) { fHistMan->FillHistClass(Form("MCTruthGenSel_%s", sig->GetName()), VarManager::fgValues); } } @@ -826,7 +829,10 @@ struct AnalysisEnergyCorrelator { continue; } } - if (std::abs(t2_raw.pdgCode()) != PDG_t::kPiPlus && std::abs(t2_raw.pdgCode()) != PDG_t::kKPlus && std::abs(t2_raw.pdgCode()) != PDG_t::kProton && std::abs(t2_raw.pdgCode()) != PDG_t::kElectron && std::abs(t2_raw.pdgCode()) != PDG_t::kMuonMinus) { + if (fConfigDileptonHadronOptions.fConfigContainlepton && std::abs(t2_raw.pdgCode()) != PDG_t::kPiPlus && std::abs(t2_raw.pdgCode()) != PDG_t::kKPlus && std::abs(t2_raw.pdgCode()) != PDG_t::kProton && std::abs(t2_raw.pdgCode()) != PDG_t::kElectron && std::abs(t2_raw.pdgCode()) != PDG_t::kMuonMinus) { + continue; + } + if (!fConfigDileptonHadronOptions.fConfigContainlepton && std::abs(t2_raw.pdgCode()) != PDG_t::kPiPlus && std::abs(t2_raw.pdgCode()) != PDG_t::kKPlus && std::abs(t2_raw.pdgCode()) != PDG_t::kProton) { continue; } if (t2_raw.pt() < fConfigDileptonHadronOptions.fConfigMCGenHadronPtMin.value || std::abs(t2_raw.eta()) > fConfigDileptonHadronOptions.fConfigMCGenHadronEtaAbs.value) { @@ -836,12 +842,18 @@ struct AnalysisEnergyCorrelator { VarManager::FillEnergyCorrelatorsMC(t1_raw, t2_raw, VarManager::fgValues, fTransRange[0], fTransRange[1]); for (auto& sig : fGenMCSignals) { if (sig->CheckSignal(true, t1_raw)) { - if (!MixedEvent) { + if (!MixedEvent && !PionMass) { fHistMan->FillHistClass(Form("MCTruthEenergyCorrelators_%s", sig->GetName()), VarManager::fgValues); } - if (MixedEvent) { + if (MixedEvent && !PionMass) { fHistMan->FillHistClass(Form("MCTruthEenergyCorrelatorsME_%s", sig->GetName()), VarManager::fgValues); } + if (!MixedEvent && PionMass) { + fHistMan->FillHistClass(Form("MCTruthEenergyCorrelators_Pion_%s", sig->GetName()), VarManager::fgValues); + } + if (MixedEvent && PionMass) { + fHistMan->FillHistClass(Form("MCTruthEenergyCorrelatorsME_Pion_%s", sig->GetName()), VarManager::fgValues); + } } } } @@ -870,7 +882,7 @@ struct AnalysisEnergyCorrelator { if (fSavelessevents[0] > 1 && event.globalIndex() % fSavelessevents[0] == fSavelessevents[1]) { continue; } - runEnergyCorrelators(event, event, mcTracks); + runEnergyCorrelators(event, event, mcTracks); } } @@ -900,7 +912,7 @@ struct AnalysisEnergyCorrelator { if (fSavelessevents[0] > 1 && event1.globalIndex() % fSavelessevents[0] == fSavelessevents[1]) { continue; } - runEnergyCorrelators(event1, event2, mcTracks); + runEnergyCorrelators(event1, event2, mcTracks); } } @@ -926,7 +938,7 @@ struct AnalysisEnergyCorrelator { if (fSavelessevents[0] > 1 && event.globalIndex() % fSavelessevents[0] == fSavelessevents[1]) { continue; } - runEnergyCorrelators(event, event, mcTracks); + runEnergyCorrelators(event, event, mcTracks); } } @@ -956,7 +968,7 @@ struct AnalysisEnergyCorrelator { if (fSavelessevents[0] > 1 && event1.globalIndex() % fSavelessevents[0] == fSavelessevents[1]) { continue; } - runEnergyCorrelators(event1, event2, mcTracks); + runEnergyCorrelators(event1, event2, mcTracks); } } From 9402f6dbd7f8bc6e42eb93a87dc38a90530b0f8e Mon Sep 17 00:00:00 2001 From: omvazque Date: Thu, 12 Mar 2026 09:42:58 -0600 Subject: [PATCH 266/347] [PWGLF] Implements RCT-based selections in Data and MC (#15355) --- PWGLF/Tasks/Nuspex/piKpRAA.cxx | 118 ++++++++++++++++++++++++++------- 1 file changed, 94 insertions(+), 24 deletions(-) diff --git a/PWGLF/Tasks/Nuspex/piKpRAA.cxx b/PWGLF/Tasks/Nuspex/piKpRAA.cxx index e6981fe8b2c..6dcabaea755 100644 --- a/PWGLF/Tasks/Nuspex/piKpRAA.cxx +++ b/PWGLF/Tasks/Nuspex/piKpRAA.cxx @@ -269,7 +269,7 @@ struct PiKpRAA { Configurable rctCheckZDC{"rctCheckZDC", false, "RCT flag to check whether the ZDC is present or not"}; Configurable rctTreatLimitedAcceptanceAsBad{"rctTreatLimitedAcceptanceAsBad", false, "RCT flag to reject events with limited acceptance for selected detectors"}; Configurable requireGoodRct{"requireGoodRct", true, "RCT flag to reject events with limited acceptance for selected detectors"}; - Configurable requireGoodPIDRct{"requireGoodPIDRct", true, "RCT flag to reject events with limited acceptance for selected detectors"}; + Configurable requireBCRct{"requireBCRct", true, "RCT flag to reject events with limited acceptance for selected detectors"}; // RCT Checker instance RCTFlagsChecker rctChecker; @@ -403,9 +403,10 @@ struct PiKpRAA { registry.add("HasBCVsFT0VsTVXVsEvSel", "Alls=1 | BC=2 | FT0=3 | TVX=4 | EvSel=5;;", kTH1F, {{5, 0.5, 5.5}}); registry.add("zPos", "With Event Selection;;Entries;", kTH1F, {axisZpos}); registry.add("T0Ccent", ";;Entries", kTH1F, {axisCent}); + registry.add("RCTSel", "Event accepted if flag=false: All=1 | RTC sel=2;;;", kTH1F, {{2, 0.5, 2.5}}); + registry.add("T0CcentVsRCTSel", "Event accepted if flag=false;;RCT Status;", kTH2F, {{{axisCent}, {9, 0.5, 9.5}}}); registry.add("T0CcentVsFoundFT0", "Found(=1.5) NOT Found(=0.5);;Status;", kTH2F, {{{axisCent}, {2, 0, 2}}}); registry.add("T0CcentVsBCVsFT0VsTVXVsEvSel", "All=1 | BC=2 | FT0=3 | TVX=4 | EvSel=5;;Status;", kTH2F, {{axisCent}, {5, 0.5, 5.5}}); - // registry.add("T0CcentVsFoundFT0AndTVX", "Found(=1.5) NOT Found(=0.5);;Status;", kTH2F, {{{axisCent}, {2, 0, 2}}}); registry.add("NchVsCent", "Measured Nch v.s. Centrality (At least Once Rec. Coll. + Sel. criteria);;Nch", kTH2F, {{axisCent, {nBinsNch, minNch, maxNch}}}); registry.add("NclVsEtaPID", ";#eta;Ncl used for PID", kTH2F, {{{axisEta}, {161, -0.5, 160.5}}}); registry.add("NclVsEtaPIDp", ";#eta;#LTNcl#GT used for PID", kTProfile, {axisEta}); @@ -435,8 +436,19 @@ struct PiKpRAA { x->SetBinLabel(19, "Nch Sel."); x->SetBinLabel(20, "INEL > 0"); + auto hrct = registry.get(HIST("T0CcentVsRCTSel")); + auto* y = hrct->GetYaxis(); + y->SetBinLabel(1, "All"); + y->SetBinLabel(2, "kFT0Bad"); + y->SetBinLabel(3, "kITSBad"); + y->SetBinLabel(4, "kITSLimAccMCRepr"); + y->SetBinLabel(5, "kTOFBad"); + y->SetBinLabel(6, "kTOFLimAccMCRepr"); + y->SetBinLabel(7, "kTPCBadTracking"); + y->SetBinLabel(8, "kTPCBadPID"); + y->SetBinLabel(9, "kTPCLimAccMCRepr"); + if (doprocessCalibrationAndV0s) { - registry.add("T0CcentVsRCTSel", "Bad RCT(=0.5) Good RCT(=1.5) Good RCT & Good PID RCT(=2.5);;RCT Status;", kTH2F, {{{axisCent}, {3, 0, 3}}}); registry.add("NchVsNPV", ";Nch; NPV;", kTH2F, {{{nBinsNPV, minNpv, maxNpv}, {nBinsNch, minNch, maxNch}}}); registry.add("ExcludedEvtVsNch", ";Nch;Entries;", kTH1F, {{nBinsNch, minNch, maxNch}}); registry.add("ExcludedEvtVsNPV", ";NPV;Entries;", kTH1F, {{nBinsNPV, minNpv, maxNpv}}); @@ -673,16 +685,52 @@ struct PiKpRAA { // Table's size: " << collisions.tableSize() << "\n"; // LOG(info) << "Run number: " << foundBC.runNumber() << "\n"; - if (!isEventSelected(collision)) { - return; - } - const auto& foundBC = collision.foundBC_as(); const uint64_t timeStamp{foundBC.timestamp()}; const int magField{getMagneticField(timeStamp)}; const double nPV{collision.multNTracksPVeta1() / 1.}; const float centrality{isT0Ccent ? collision.centFT0C() : collision.centFT0M()}; + // Apply RCT selection? + if (requireGoodRct) { + // Checks if collisions passes RCT selection + const bool isFT0Bad{requireBCRct ? foundBC.rct_bit(kFT0Bad) : collision.rct_bit(kFT0Bad)}; + const bool isITSBad{requireBCRct ? foundBC.rct_bit(kITSBad) : collision.rct_bit(kITSBad)}; + const bool isITSLimAcc{requireBCRct ? foundBC.rct_bit(kITSLimAccMCRepr) : collision.rct_bit(kITSLimAccMCRepr)}; + const bool isTOFBad{requireBCRct ? foundBC.rct_bit(kTOFBad) : collision.rct_bit(kTOFBad)}; + const bool isTOFLimAcc{requireBCRct ? foundBC.rct_bit(kTOFLimAccMCRepr) : collision.rct_bit(kTOFLimAccMCRepr)}; + const bool isTPCTrackingBad{requireBCRct ? foundBC.rct_bit(kTPCBadTracking) : collision.rct_bit(kTPCBadTracking)}; + const bool isTPCPIDBad{requireBCRct ? foundBC.rct_bit(kTPCBadPID) : collision.rct_bit(kTPCBadPID)}; + const bool isTPCLimAcc{requireBCRct ? foundBC.rct_bit(kTPCLimAccMCRepr) : collision.rct_bit(kTPCLimAccMCRepr)}; + + registry.fill(HIST("T0CcentVsRCTSel"), centrality, 1.0); + if (!isFT0Bad) + registry.fill(HIST("T0CcentVsRCTSel"), centrality, 2.0); + if (!isITSBad) + registry.fill(HIST("T0CcentVsRCTSel"), centrality, 3.0); + if (!isITSLimAcc) + registry.fill(HIST("T0CcentVsRCTSel"), centrality, 4.0); + if (!isTOFBad) + registry.fill(HIST("T0CcentVsRCTSel"), centrality, 5.0); + if (!isTOFLimAcc) + registry.fill(HIST("T0CcentVsRCTSel"), centrality, 6.0); + if (!isTPCTrackingBad) + registry.fill(HIST("T0CcentVsRCTSel"), centrality, 7.0); + if (!isTPCPIDBad) + registry.fill(HIST("T0CcentVsRCTSel"), centrality, 8.0); + if (!isTPCLimAcc) + registry.fill(HIST("T0CcentVsRCTSel"), centrality, 9.0); + + registry.fill(HIST("RCTSel"), 1.0); + if (!rctChecker(collision)) + return; + + registry.fill(HIST("RCTSel"), 2.0); + } + + if (!isEventSelected(collision)) + return; + //--------------------------- // Control histogram //--------------------------- @@ -691,23 +739,6 @@ struct PiKpRAA { } registry.fill(HIST("T0CcentVsFoundFT0"), centrality, 1.5); - // Apply RCT selection? - if (requireGoodRct) { - - // Checks if collisions passes RCT selection - if (!rctChecker(*collision)) { - registry.fill(HIST("T0CcentVsRCTSel"), centrality, 0.5); - return; - } - - registry.fill(HIST("T0CcentVsRCTSel"), centrality, 1.5); - // Checks if collisions passes good PID RCT status - if (requireGoodPIDRct && collision.rct_bit(kTPCBadPID)) { - return; - } - registry.fill(HIST("T0CcentVsRCTSel"), centrality, 2.5); - } - if (applyNchSel) { const int nextRunNumber{foundBC.runNumber()}; if (currentRunNumberNchSel != nextRunNumber) { @@ -1404,6 +1435,45 @@ struct PiKpRAA { registry.fill(HIST("HasBCVsFT0VsTVXVsEvSel"), 4.0); } + //--------------------------- + // RCT Selection + //--------------------------- + if (requireGoodRct) { + // Checks if collisions passes RCT selection + const bool isFT0Bad{requireBCRct ? foundBC.rct_bit(kFT0Bad) : collision.rct_bit(kFT0Bad)}; + const bool isITSBad{requireBCRct ? foundBC.rct_bit(kITSBad) : collision.rct_bit(kITSBad)}; + const bool isITSLimAcc{requireBCRct ? foundBC.rct_bit(kITSLimAccMCRepr) : collision.rct_bit(kITSLimAccMCRepr)}; + const bool isTOFBad{requireBCRct ? foundBC.rct_bit(kTOFBad) : collision.rct_bit(kTOFBad)}; + const bool isTOFLimAcc{requireBCRct ? foundBC.rct_bit(kTOFLimAccMCRepr) : collision.rct_bit(kTOFLimAccMCRepr)}; + const bool isTPCTrackingBad{requireBCRct ? foundBC.rct_bit(kTPCBadTracking) : collision.rct_bit(kTPCBadTracking)}; + const bool isTPCPIDBad{requireBCRct ? foundBC.rct_bit(kTPCBadPID) : collision.rct_bit(kTPCBadPID)}; + const bool isTPCLimAcc{requireBCRct ? foundBC.rct_bit(kTPCLimAccMCRepr) : collision.rct_bit(kTPCLimAccMCRepr)}; + + registry.fill(HIST("T0CcentVsRCTSel"), centrality, 1.0); + if (!isFT0Bad) + registry.fill(HIST("T0CcentVsRCTSel"), centrality, 2.0); + if (!isITSBad) + registry.fill(HIST("T0CcentVsRCTSel"), centrality, 3.0); + if (!isITSLimAcc) + registry.fill(HIST("T0CcentVsRCTSel"), centrality, 4.0); + if (!isTOFBad) + registry.fill(HIST("T0CcentVsRCTSel"), centrality, 5.0); + if (!isTOFLimAcc) + registry.fill(HIST("T0CcentVsRCTSel"), centrality, 6.0); + if (!isTPCTrackingBad) + registry.fill(HIST("T0CcentVsRCTSel"), centrality, 7.0); + if (!isTPCPIDBad) + registry.fill(HIST("T0CcentVsRCTSel"), centrality, 8.0); + if (!isTPCLimAcc) + registry.fill(HIST("T0CcentVsRCTSel"), centrality, 9.0); + + registry.fill(HIST("RCTSel"), 1.0); + if (!rctChecker(collision)) + return; + + registry.fill(HIST("RCTSel"), 2.0); + } + //--------------------------- // Event Selection //--------------------------- From 25078e21ab94ad5de1dc62f1e9aabd277f505cbc Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Thu, 12 Mar 2026 17:28:01 +0100 Subject: [PATCH 267/347] [PWGEM/Dilepton] update DileptonHadronMPC.h (#15364) Co-authored-by: ALICE Action Bot --- PWGEM/Dilepton/Core/DileptonHadronMPC.h | 48 +++++++-- PWGEM/Dilepton/Core/EMTrackCut.cxx | 78 +------------- PWGEM/Dilepton/Core/EMTrackCut.h | 130 +----------------------- 3 files changed, 45 insertions(+), 211 deletions(-) diff --git a/PWGEM/Dilepton/Core/DileptonHadronMPC.h b/PWGEM/Dilepton/Core/DileptonHadronMPC.h index 9973ebf0dc1..56b2c837cc8 100644 --- a/PWGEM/Dilepton/Core/DileptonHadronMPC.h +++ b/PWGEM/Dilepton/Core/DileptonHadronMPC.h @@ -68,7 +68,7 @@ using namespace o2::aod::pwgem::dilepton::utils; using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; using namespace o2::aod::pwgem::dilepton::utils::pairutil; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; using MyElectrons = soa::Join; @@ -96,6 +96,7 @@ struct DileptonHadronMPC { Configurable d_bz_input{"d_bz_input", -999, "bz field in kG, -999 is automatic"}; Configurable cfgAnalysisType{"cfgAnalysisType", static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonHadronAnalysisType::kAzimuthalCorrelation), "kAzimuthalCorrelation:0, kCumulant:1"}; + Configurable cfgEP2Estimator_for_Mix{"cfgEP2Estimator_for_Mix", 3, "FT0M:0, FT0A:1, FT0C:2, BTot:3, BPos:4, BNeg:5, FV0A:6"}; Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; Configurable cfgOccupancyEstimator{"cfgOccupancyEstimator", 0, "FT0C:0, Track:1"}; Configurable cfgDoMix{"cfgDoMix", true, "flag for event mixing"}; @@ -104,6 +105,7 @@ struct DileptonHadronMPC { Configurable ndiff_bc_mix{"ndiff_bc_mix", 594, "difference in global BC required in mixed events"}; ConfigurableAxis ConfVtxBins{"ConfVtxBins", {VARIABLE_WIDTH, -10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}, "Mixing bins - z-vertex"}; ConfigurableAxis ConfCentBins{"ConfCentBins", {VARIABLE_WIDTH, 0.0f, 5.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f, 100.f, 999.f}, "Mixing bins - centrality"}; + ConfigurableAxis ConfEPBins{"ConfEPBins", {16, -M_PI / 2, +M_PI / 2}, "Mixing bins - event plane angle"}; ConfigurableAxis ConfOccupancyBins{"ConfOccupancyBins", {VARIABLE_WIDTH, -1, 1e+10}, "Mixing bins - occupancy"}; Configurable cfg_swt_name{"cfg_swt_name", "fHighTrackMult", "desired software trigger name"}; // 1 trigger name per 1 task. fHighTrackMult, fHighFt0Mult // Configurable cfgNtracksPV08Min{"cfgNtracksPV08Min", -1, "min. multNTracksPV"}; @@ -115,9 +117,7 @@ struct DileptonHadronMPC { ConfigurableAxis ConfPtllBins{"ConfPtllBins", {VARIABLE_WIDTH, 0.00, 0.15, 0.50, 1.00, 1.50, 2.00, 2.50, 3.00, 3.50, 4.00, 4.50, 5.00, 6.00, 7.00, 8.00, 9.00, 10.00}, "pTll bins for output histograms"}; ConfigurableAxis ConfDCAllBins{"ConfDCAllBins", {VARIABLE_WIDTH, 0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0}, "DCAll bins for output histograms"}; - // ConfigurableAxis ConfMmumuBins{"ConfMmumuBins", {VARIABLE_WIDTH, 0.20, 0.21, 0.22, 0.23, 0.24, 0.25, 0.26, 0.27, 0.28, 0.29, 0.30, 0.31, 0.32, 0.33, 0.34, 0.35, 0.36, 0.37, 0.38, 0.39, 0.40, 0.41, 0.42, 0.43, 0.44, 0.45, 0.46, 0.47, 0.48, 0.49, 0.50, 0.51, 0.52, 0.53, 0.54, 0.55, 0.56, 0.57, 0.58, 0.59, 0.60, 0.61, 0.62, 0.63, 0.64, 0.65, 0.66, 0.67, 0.68, 0.69, 0.70, 0.71, 0.72, 0.73, 0.74, 0.75, 0.76, 0.77, 0.78, 0.79, 0.80, 0.81, 0.82, 0.83, 0.84, 0.85, 0.86, 0.87, 0.88, 0.89, 0.90, 0.91, 0.92, 0.93, 0.94, 0.95, 0.96, 0.97, 0.98, 0.99, 1.00, 1.01, 1.02, 1.03, 1.04, 1.05, 1.06, 1.07, 1.08, 1.09, 1.10, 1.11,1.12,1.13,1.14,1.15,1.16,1.17,1.18,1.19, 1.20, 1.30, 1.40, 1.50, 1.60, 1.70, 1.80, 1.90, 2.00, 2.10, 2.20, 2.30, 2.40, 2.50, 2.60, 2.70, 2.75, 2.80, 2.85, 2.90, 2.95, 3.00, 3.05, 3.10, 3.15, 3.20, 3.25, 3.30, 3.35, 3.40, 3.45, 3.50, 3.55, 3.60, 3.65, 3.70, 3.75, 3.80, 3.85, 3.90, 3.95, 4.00, 4.10, 4.20, 4.30, 4.40, 4.50, 4.60, 4.70, 4.80, 4.90, 5.00, 5.10, 5.20, 5.30, 5.40, 5.50, 5.60, 5.70, 5.80, 5.90, 6.00, 6.10, 6.20, 6.30, 6.40, 6.50, 6.60, 6.70, 6.80, 6.90, 7.00, 7.10, 7.20, 7.30, 7.40, 7.50, 7.60, 7.70, 7.80, 7.90, 8.00, 8.10, 8.20, 8.30, 8.40, 8.50, 8.60, 8.70, 8.80, 8.90, 9.00, 9.10, 9.20, 9.30, 9.40, 9.50, 9.60, 9.70, 9.80, 9.90, 10.00, 10.10, 10.20, 10.30, 10.40, 10.50, 10.60, 10.70, 10.80, 10.90, 11.00, 11.50, 12.00}, "mmumu bins for output histograms"}; // for dimuon. one can copy bins here to hyperloop page. - - ConfigurableAxis ConfPtHadronBins{"ConfPtHadronBins", {VARIABLE_WIDTH, 0.00, 0.15, 0.2, 0.3, 0.4, 0.50, 1.00, 2.00, 3.00, 4.00, 5.00}, "pT,h bins for output histograms"}; + ConfigurableAxis ConfPtHadronBins{"ConfPtHadronBins", {50, 0, 5}, "pT,h bins for output histograms"}; ConfigurableAxis ConfYllBins{"ConfYllBins", {1, -1.f, 1.f}, "yll bins for output histograms"}; // pair rapidity ConfigurableAxis ConfDEtaBins{"ConfDEtaBins", {120, -6, 6}, "deta bins for output histograms"}; Configurable cfgNbinsDPhi{"cfgNbinsDPhi", 36, "nbins in dphi for output histograms"}; @@ -314,10 +314,8 @@ struct DileptonHadronMPC { std::vector cent_bin_edges; std::vector zvtx_bin_edges; + std::vector ep_bin_edges; std::vector occ_bin_edges; - int nmod = -1; // this is for flow analysis - int subdet2 = -1; // this is for flow analysis - int subdet3 = -1; // this is for flow analysis float leptonM1 = 0.f; float leptonM2 = 0.f; @@ -366,6 +364,23 @@ struct DileptonHadronMPC { } } + if (ConfEPBins.value[0] == VARIABLE_WIDTH) { + ep_bin_edges = std::vector(ConfEPBins.value.begin(), ConfEPBins.value.end()); + ep_bin_edges.erase(ep_bin_edges.begin()); + for (const auto& edge : ep_bin_edges) { + LOGF(info, "VARIABLE_WIDTH: ep_bin_edges = %f", edge); + } + } else { + int nbins = static_cast(ConfEPBins.value[0]); + float xmin = static_cast(ConfEPBins.value[1]); + float xmax = static_cast(ConfEPBins.value[2]); + ep_bin_edges.resize(nbins + 1); + for (int i = 0; i < nbins + 1; i++) { + ep_bin_edges[i] = (xmax - xmin) / (nbins)*i + xmin; + LOGF(info, "FIXED_WIDTH: ep_bin_edges[%d] = %f", i, ep_bin_edges[i]); + } + } + LOGF(info, "cfgOccupancyEstimator = %d", cfgOccupancyEstimator.value); if (ConfOccupancyBins.value[0] == VARIABLE_WIDTH) { occ_bin_edges = std::vector(ConfOccupancyBins.value.begin(), ConfOccupancyBins.value.end()); @@ -478,6 +493,7 @@ struct DileptonHadronMPC { void addhistograms() { + static constexpr std::string_view qvec_det_names[7] = {"FT0M", "FT0A", "FT0C", "BTot", "BPos", "BNeg", "FV0A"}; // event info o2::aod::pwgem::dilepton::utils::eventhistogram::addEventHistograms<-1>(&fRegistry); @@ -522,7 +538,7 @@ struct DileptonHadronMPC { const AxisSpec axis_deta{ConfDEtaBins, deta_axis_title}; // hadron-hadron info - const AxisSpec axis_deta_hh{60, -3, +3, "#Delta#eta = #eta_{h}^{ref1} - #eta_{h}^{ref2}"}; + const AxisSpec axis_deta_hh{40, -2, +2, "#Delta#eta = #eta_{h}^{ref1} - #eta_{h}^{ref2}"}; const AxisSpec axis_pt_trg{ConfPtHadronBins, "p_{T,h} (GeV/c)"}; const AxisSpec axis_eta_trg{40, -2, +2, "#eta_{h}"}; @@ -562,6 +578,9 @@ struct DileptonHadronMPC { fRegistry.add("HadronHadron/same/hDEtaCosNDPhi", "hadron-hadron 2PC", kTH2D, {axis_cosndphi_hh, axis_deta_hh}, true); } fRegistry.add("Dilepton/mix/hDiffBC", "diff. global BC in mixed event;|BC_{current} - BC_{mixed}|", kTH1D, {{10001, -0.5, 10000.5}}, true); + + fRegistry.add("Event/before/hEP2_CentFT0C_forMix", Form("2nd harmonics event plane for mix;centrality FT0C (%%);#Psi_{2}^{%s} (rad.)", qvec_det_names[cfgEP2Estimator_for_Mix].data()), kTH2F, {{110, 0, 110}, {180, -M_PI_2, +M_PI_2}}, false); + fRegistry.add("Event/after/hEP2_CentFT0C_forMix", Form("2nd harmonics event plane for mix;centrality FT0C (%%);#Psi_{2}^{%s} (rad.)", qvec_det_names[cfgEP2Estimator_for_Mix].data()), kTH2F, {{110, 0, 110}, {180, -M_PI_2, +M_PI_2}}, false); } void DefineEMEventCut() @@ -1032,8 +1051,13 @@ struct DileptonHadronMPC { continue; } + const float eventplanes_2_for_mix[7] = {collision.ep2ft0m(), collision.ep2ft0a(), collision.ep2ft0c(), collision.ep2btot(), collision.ep2bpos(), collision.ep2bneg(), collision.ep2fv0a()}; + float ep2 = eventplanes_2_for_mix[cfgEP2Estimator_for_Mix]; + o2::aod::pwgem::dilepton::utils::eventhistogram::fillEventInfo<0, -1>(&fRegistry, collision); + fRegistry.fill(HIST("Event/before/hEP2_CentFT0C_forMix"), collision.centFT0C(), ep2); + if (!fEMEventCut.IsSelected(collision)) { continue; } @@ -1050,6 +1074,7 @@ struct DileptonHadronMPC { o2::aod::pwgem::dilepton::utils::eventhistogram::fillEventInfo<1, -1>(&fRegistry, collision); fRegistry.fill(HIST("Event/before/hCollisionCounter"), o2::aod::pwgem::dilepton::utils::eventhistogram::nbin_ev); // accepted fRegistry.fill(HIST("Event/after/hCollisionCounter"), o2::aod::pwgem::dilepton::utils::eventhistogram::nbin_ev); // accepted + fRegistry.fill(HIST("Event/after/hEP2_CentFT0C_forMix"), collision.centFT0C(), ep2); auto refTracks_per_coll = refTracks.sliceBy(perCollision_track, collision.globalIndex()); @@ -1127,7 +1152,12 @@ struct DileptonHadronMPC { centbin = static_cast(cent_bin_edges.size()) - 2; } - int epbin = 0; + int epbin = lower_bound(ep_bin_edges.begin(), ep_bin_edges.end(), ep2) - ep_bin_edges.begin() - 1; + if (epbin < 0) { + epbin = 0; + } else if (static_cast(ep_bin_edges.size()) - 2 < epbin) { + epbin = static_cast(ep_bin_edges.size()) - 2; + } int occbin = -1; if (cfgOccupancyEstimator == 0) { diff --git a/PWGEM/Dilepton/Core/EMTrackCut.cxx b/PWGEM/Dilepton/Core/EMTrackCut.cxx index 2ea7934a30b..ed9e345a0f9 100644 --- a/PWGEM/Dilepton/Core/EMTrackCut.cxx +++ b/PWGEM/Dilepton/Core/EMTrackCut.cxx @@ -17,14 +17,8 @@ #include "Framework/Logger.h" -#include -#include - ClassImp(EMTrackCut); -const std::pair> EMTrackCut::its_ib_any_Requirement = {1, {0, 1, 2}}; // hits on any ITS ib layers. -const std::pair> EMTrackCut::its_ib_1st_Requirement = {1, {0}}; // hit on 1st ITS ib layers. - void EMTrackCut::SetTrackPtRange(float minPt, float maxPt) { mMinTrackPt = minPt; @@ -43,74 +37,12 @@ void EMTrackCut::SetTrackPhiRange(float minPhi, float maxPhi) mMaxTrackPhi = maxPhi; LOG(info) << "EMTrack Cut, set track phi range (rad.): " << mMinTrackPhi << " - " << mMaxTrackPhi; } -void EMTrackCut::SetMinNClustersTPC(int minNClustersTPC) -{ - mMinNClustersTPC = minNClustersTPC; - LOG(info) << "EMTrack Cut, set min N clusters TPC: " << mMinNClustersTPC; -} -void EMTrackCut::SetMinNCrossedRowsTPC(int minNCrossedRowsTPC) -{ - mMinNCrossedRowsTPC = minNCrossedRowsTPC; - LOG(info) << "EMTrack Cut, set min N crossed rows TPC: " << mMinNCrossedRowsTPC; -} -void EMTrackCut::SetMinNCrossedRowsOverFindableClustersTPC(float minNCrossedRowsOverFindableClustersTPC) -{ - mMinNCrossedRowsOverFindableClustersTPC = minNCrossedRowsOverFindableClustersTPC; - LOG(info) << "EMTrack Cut, set min N crossed rows over findable clusters TPC: " << mMinNCrossedRowsOverFindableClustersTPC; -} -void EMTrackCut::SetMaxFracSharedClustersTPC(float max) -{ - mMaxFracSharedClustersTPC = max; - LOG(info) << "EMTrack Cut, set max fraction of shared clusters in TPC: " << mMaxFracSharedClustersTPC; -} -void EMTrackCut::SetChi2PerClusterTPC(float min, float max) -{ - mMinChi2PerClusterTPC = min; - mMaxChi2PerClusterTPC = max; - LOG(info) << "EMTrack Cut, set chi2 per cluster TPC range: " << mMinChi2PerClusterTPC << " - " << mMaxChi2PerClusterTPC; -} - -void EMTrackCut::SetNClustersITS(int min, int max) -{ - mMinNClustersITS = min; - mMaxNClustersITS = max; - LOG(info) << "EMTrack Cut, set N clusters ITS range: " << mMinNClustersITS << " - " << mMaxNClustersITS; -} -void EMTrackCut::SetChi2PerClusterITS(float min, float max) -{ - mMinChi2PerClusterITS = min; - mMaxChi2PerClusterITS = max; - LOG(info) << "EMTrack Cut, set chi2 per cluster ITS range: " << mMinChi2PerClusterITS << " - " << mMaxChi2PerClusterITS; -} - -void EMTrackCut::SetTrackMaxDcaXY(float maxDcaXY) -{ - mMaxDcaXY = maxDcaXY; - LOG(info) << "EMTrack Cut, set max DCA xy: " << mMaxDcaXY; -} -void EMTrackCut::SetTrackMaxDcaZ(float maxDcaZ) -{ - mMaxDcaZ = maxDcaZ; - LOG(info) << "EMTrack Cut, set max DCA z: " << mMaxDcaZ; -} -void EMTrackCut::SetTrackMaxDcaXYPtDep(std::function ptDepCut) -{ - mMaxDcaXYPtDep = ptDepCut; - LOG(info) << "EMTrack Cut, set max DCA xy pt dep: " << mMaxDcaXYPtDep(1.0); -} - -void EMTrackCut::RequireITSibAny(bool flag) -{ - mRequireITSibAny = flag; - LOG(info) << "EMTrack Cut, require ITS ib any: " << mRequireITSibAny; -} - -void EMTrackCut::RequireITSib1st(bool flag) -{ - mRequireITSib1st = flag; - LOG(info) << "EMTrack Cut, require ITS ib 1st: " << mRequireITSib1st; -} +// void EMTrackCut::SetTrackMaxDcaXYPtDep(std::function ptDepCut) +// { +// mMaxDcaXYPtDep = ptDepCut; +// LOG(info) << "EMTrack Cut, set max DCA xy pt dep: " << mMaxDcaXYPtDep(1.0); +// } void EMTrackCut::SetTrackBit(uint16_t bit) { diff --git a/PWGEM/Dilepton/Core/EMTrackCut.h b/PWGEM/Dilepton/Core/EMTrackCut.h index d70a009aaac..2194aabb7cf 100644 --- a/PWGEM/Dilepton/Core/EMTrackCut.h +++ b/PWGEM/Dilepton/Core/EMTrackCut.h @@ -16,23 +16,10 @@ #ifndef PWGEM_DILEPTON_CORE_EMTRACKCUT_H_ #define PWGEM_DILEPTON_CORE_EMTRACKCUT_H_ -#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/DataTypes.h" #include "Framework/Logger.h" -#include "Math/Vector4D.h" #include "TNamed.h" -#include -#include -#include -#include -#include - -using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; - class EMTrackCut : public TNamed { public: @@ -45,15 +32,6 @@ class EMTrackCut : public TNamed kTrackPtRange, kTrackEtaRange, kTrackPhiRange, - // kDCAxy, - // kDCAz, - // kTPCNCls, - // kTPCCrossedRows, - // kTPCCrossedRowsOverNCls, - // kTPCFracSharedClusters, - // kTPCChi2NDF, - // kITSNCls, - // kITSChi2NDF, kTrackBit, kNCuts }; @@ -61,10 +39,6 @@ class EMTrackCut : public TNamed template bool IsSelected(TTrack const& track) const { - // if (!track.hasITS() || !track.hasTPC()) { - // return false; - // } - if (!IsSelectedTrack(track, EMTrackCuts::kTrackPtRange)) { return false; } @@ -75,56 +49,10 @@ class EMTrackCut : public TNamed return false; } - // if (!IsSelectedTrack(track, EMTrackCuts::kDCAxy)) { - // return false; - // } - // if (!IsSelectedTrack(track, EMTrackCuts::kDCAz)) { - // return false; - // } - if (!IsSelectedTrack(track, EMTrackCuts::kTrackBit)) { return false; } - // // ITS cuts - // if (!IsSelectedTrack(track, EMTrackCuts::kITSNCls)) { - // return false; - // } - // if (!IsSelectedTrack(track, EMTrackCuts::kITSChi2NDF)) { - // return false; - // } - // - // if (mRequireITSibAny) { - // auto hits_ib = std::count_if(its_ib_any_Requirement.second.begin(), its_ib_any_Requirement.second.end(), [&](auto&& requiredLayer) { return track.itsClusterMap() & (1 << requiredLayer); }); - // if (hits_ib < its_ib_any_Requirement.first) { - // return false; - // } - // } - // - // if (mRequireITSib1st) { - // auto hits_ib = std::count_if(its_ib_1st_Requirement.second.begin(), its_ib_1st_Requirement.second.end(), [&](auto&& requiredLayer) { return track.itsClusterMap() & (1 << requiredLayer); }); - // if (hits_ib < its_ib_1st_Requirement.first) { - // return false; - // } - // } - // - // // TPC cuts - // if (!IsSelectedTrack(track, EMTrackCuts::kTPCNCls)) { - // return false; - // } - // if (!IsSelectedTrack(track, EMTrackCuts::kTPCCrossedRows)) { - // return false; - // } - // if (!IsSelectedTrack(track, EMTrackCuts::kTPCCrossedRowsOverNCls)) { - // return false; - // } - // if (!IsSelectedTrack(track, EMTrackCuts::kTPCFracSharedClusters)) { - // return false; - // } - // if (!IsSelectedTrack(track, EMTrackCuts::kTPCChi2NDF)) { - // return false; - // } - return true; } @@ -141,12 +69,6 @@ class EMTrackCut : public TNamed case EMTrackCuts::kTrackPhiRange: return track.phi() > mMinTrackPhi && track.phi() < mMaxTrackPhi; - // case EMTrackCuts::kDCAxy: - // return std::fabs(track.dcaXY()) < ((mMaxDcaXYPtDep) ? mMaxDcaXYPtDep(track.pt()) : mMaxDcaXY); - - // case EMTrackCuts::kDCAz: - // return std::fabs(track.dcaZ()) < mMaxDcaZ; - case EMTrackCuts::kTrackBit: { // for (int i = 0; i < 10; i++) { // if ((mTrackBit & (1 << i)) > 0 && !((track.trackBit() & (1 << i)) > 0)) { @@ -157,27 +79,6 @@ class EMTrackCut : public TNamed return (track.trackBit() & mTrackBit) >= mTrackBit; } - // case EMTrackCuts::kTPCNCls: - // return track.tpcNClsFound() >= mMinNClustersTPC; - - // case EMTrackCuts::kTPCCrossedRows: - // return track.tpcNClsCrossedRows() >= mMinNCrossedRowsTPC; - - // case EMTrackCuts::kTPCCrossedRowsOverNCls: - // return track.tpcCrossedRowsOverFindableCls() > mMinNCrossedRowsOverFindableClustersTPC; - - // case EMTrackCuts::kTPCFracSharedClusters: - // return track.tpcFractionSharedCls() < mMaxFracSharedClustersTPC; - - // case EMTrackCuts::kTPCChi2NDF: - // return mMinChi2PerClusterTPC < track.tpcChi2NCl() && track.tpcChi2NCl() < mMaxChi2PerClusterTPC; - - // case EMTrackCuts::kITSNCls: - // return mMinNClustersITS <= track.itsNCls() && track.itsNCls() <= mMaxNClustersITS; - - // case EMTrackCuts::kITSChi2NDF: - // return mMinChi2PerClusterITS < track.itsChi2NCl() && track.itsChi2NCl() < mMaxChi2PerClusterITS; - default: return false; } @@ -187,46 +88,17 @@ class EMTrackCut : public TNamed void SetTrackPtRange(float minPt = 0.f, float maxPt = 1e10f); void SetTrackEtaRange(float minEta = -1e10f, float maxEta = 1e10f); void SetTrackPhiRange(float minPhi = 0.f, float maxPhi = 6.3f); - void SetMinNClustersTPC(int minNClustersTPC); - void SetMinNCrossedRowsTPC(int minNCrossedRowsTPC); - void SetMinNCrossedRowsOverFindableClustersTPC(float minNCrossedRowsOverFindableClustersTPC); - void SetMaxFracSharedClustersTPC(float max); - void SetChi2PerClusterTPC(float min, float max); - void SetNClustersITS(int min, int max); - void SetChi2PerClusterITS(float min, float max); - - void SetTrackDca3DRange(float min, float max); // in sigma - void SetTrackMaxDcaXY(float maxDcaXY); // in cm - void SetTrackMaxDcaZ(float maxDcaZ); // in cm - void SetTrackMaxDcaXYPtDep(std::function ptDepCut); - void RequireITSibAny(bool flag); - void RequireITSib1st(bool flag); void SetTrackBit(uint16_t bits); private: - static const std::pair> its_ib_any_Requirement; - static const std::pair> its_ib_1st_Requirement; - // kinematic cuts float mMinTrackPt{0.f}, mMaxTrackPt{1e10f}; // range in pT float mMinTrackEta{-1e10f}, mMaxTrackEta{1e10f}; // range in eta float mMinTrackPhi{0.f}, mMaxTrackPhi{6.3}; // range in phi // track quality cuts - int mMinNClustersTPC{0}; // min number of TPC clusters - int mMinNCrossedRowsTPC{0}; // min number of crossed rows in TPC - float mMinChi2PerClusterTPC{0.f}, mMaxChi2PerClusterTPC{1e10f}; // max tpc fit chi2 per TPC cluster - float mMinNCrossedRowsOverFindableClustersTPC{0.f}; // min ratio crossed rows / findable clusters - float mMaxFracSharedClustersTPC{999.f}; // max ratio shared clusters / clusters in TPC - int mMinNClustersITS{0}, mMaxNClustersITS{7}; // range in number of ITS clusters - float mMinChi2PerClusterITS{0.f}, mMaxChi2PerClusterITS{1e10f}; // max its fit chi2 per ITS cluster - bool mRequireITSibAny{true}; - bool mRequireITSib1st{false}; uint16_t mTrackBit{0}; - - float mMaxDcaXY{1.0f}; // max dca in xy plane - float mMaxDcaZ{1.0f}; // max dca in z direction - std::function mMaxDcaXYPtDep{}; // max dca in xy plane as function of pT + // std::function mMaxDcaXYPtDep{}; // max dca in xy plane as function of pT ClassDef(EMTrackCut, 1); }; From 36d0a027e37aeba736345b54377cb149e84c8cfb Mon Sep 17 00:00:00 2001 From: MattOckleton <149105337+MattOckleton@users.noreply.github.com> Date: Thu, 12 Mar 2026 18:22:28 +0000 Subject: [PATCH 268/347] [PWGJE] Fixing jetCorrelationD0 table columns (#15365) --- PWGJE/Tasks/jetCorrelationD0.cxx | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/PWGJE/Tasks/jetCorrelationD0.cxx b/PWGJE/Tasks/jetCorrelationD0.cxx index 504928dd56b..22c08b9b272 100644 --- a/PWGJE/Tasks/jetCorrelationD0.cxx +++ b/PWGJE/Tasks/jetCorrelationD0.cxx @@ -27,10 +27,6 @@ #include "Framework/HistogramRegistry.h" #include "Framework/Logger.h" #include "Framework/runDataProcessing.h" -#include -#include - -#include #include #include @@ -57,8 +53,10 @@ DECLARE_SOA_TABLE(McCollisionTables, "AOD", "MCCOLLINFOTABLE", namespace collisionInfo { -DECLARE_SOA_INDEX_COLUMN(CollisionTable, collisionTable); -DECLARE_SOA_INDEX_COLUMN(McCollisionTable, mcCollisionTable); +// DECLARE_SOA_INDEX_COLUMN(CollisionTable, collisionTable); +DECLARE_SOA_INDEX_COLUMN_CUSTOM(CollisionTable, collisionTable, "COLLINFOTABLES"); +// DECLARE_SOA_INDEX_COLUMN(McCollisionTable, mcCollisionTable); +DECLARE_SOA_INDEX_COLUMN_CUSTOM(McCollisionTable, mcCollisionTable, "MCCOLLINFOTABLES"); } // namespace collisionInfo namespace d0Info { @@ -91,7 +89,7 @@ DECLARE_SOA_TABLE(D0DataTables, "AOD", "D0DATATABLE", d0Info::D0Phi, d0Info::D0Y); -DECLARE_SOA_TABLE(D0McPTables, "AOD", "D0MCPARTICLELEVELTABLE", +DECLARE_SOA_TABLE(D0McPTables, "AOD", "D0MCPTABLE", o2::soa::Index<>, collisionInfo::McCollisionTableId, d0Info::D0McOrigin, @@ -103,8 +101,8 @@ DECLARE_SOA_TABLE(D0McPTables, "AOD", "D0MCPARTICLELEVELTABLE", namespace jetInfo { // D0 tables -DECLARE_SOA_INDEX_COLUMN(D0DataTable, d0Data); -DECLARE_SOA_INDEX_COLUMN(D0McPTable, d0MCP); +DECLARE_SOA_INDEX_COLUMN(D0DataTable, d0DataTable); +DECLARE_SOA_INDEX_COLUMN(D0McPTable, d0McPTable); // Jet DECLARE_SOA_COLUMN(JetPt, jetPt, float); DECLARE_SOA_COLUMN(JetEta, jetEta, float); @@ -202,7 +200,7 @@ struct JetCorrelationD0 { { for (const auto& jetBase : jetsBase) { if (jetBase.has_matchedJetGeo()) { // geometric matching - for (auto& jetTag : jetBase.template matchedJetGeo_as>()) { + for (auto const& jetTag : jetBase.template matchedJetGeo_as>()) { registry.fill(HIST("hPtMatched"), jetBase.pt() - (rho * jetBase.area()), jetTag.pt(), weight); registry.fill(HIST("hPtMatched1d"), jetTag.pt(), weight); registry.fill(HIST("hPhiMatched"), jetBase.phi(), jetTag.phi(), weight); @@ -280,7 +278,7 @@ struct JetCorrelationD0 { continue; } float dphi = RecoDecay::constrainAngle(jet.phi() - d0Candidate.phi()); - if (abs(dphi - M_PI) > (M_PI / 2)) { // this is quite loose instead of pi/2 could do 0.6 + if (std::abs(dphi - o2::constants::math::PI) > (o2::constants::math::PI / 2)) { // this is quite loose instead of pi/2 could do 0.6 continue; } fillJetHistograms(jet, dphi); @@ -323,7 +321,7 @@ struct JetCorrelationD0 { continue; } float dphi = RecoDecay::constrainAngle(jet.phi() - d0Candidate.phi()); - if (abs(dphi - M_PI) > (M_PI / 2)) { // this is quite loose instead of pi/2 could do 0.6 + if (std::abs(dphi - o2::constants::math::PI) > (o2::constants::math::PI / 2)) { // this is quite loose instead of pi/2 could do 0.6 continue; } fillJetHistograms(jet, dphi); @@ -362,7 +360,7 @@ struct JetCorrelationD0 { continue; } float dphi = RecoDecay::constrainAngle(jet.phi() - d0MCPCandidate.phi()); - if (abs(dphi - M_PI) > (M_PI / 2)) { + if (std::abs(dphi - o2::constants::math::PI) > (o2::constants::math::PI / 2)) { continue; } fillJetHistograms(jet, dphi); From 15e5284e59c937c413a7a3771332d6f5b87a8f4d Mon Sep 17 00:00:00 2001 From: nkaratze Date: Thu, 12 Mar 2026 19:31:39 +0100 Subject: [PATCH 269/347] [PWGLF] Small fixes (#15368) --- PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx | 145 ++++++++++--------- 1 file changed, 73 insertions(+), 72 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx b/PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx index 79fc64c1883..32dc652f346 100644 --- a/PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx +++ b/PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx @@ -15,7 +15,7 @@ /// \author Roman Lietava (roman.lietava@cern.ch) /*Description -This task creates up to 30 histograms that are filled with the V0 invariant mass under the K0, Lambda and Antilambda mass assumption +This task creates up to 30 histograms that are filled with the V0 invariant mass under the K0, Lambda and AntiLambda mass assumption for different pt ranges (constituting bins). The values are inserted as configurable strings for convinience. Also feed-down matrices for the Lambda and Anti-Lambda are produced. This analysis includes three processes, one for Real Data and two for MC at the Generated and Reconstructed level*/ @@ -102,7 +102,7 @@ struct V0PtInvMassPlots { Configurable doitsMinHits{"doitsMinHits", true, "Enable ITS Minimum hits"}; // Configurables switches for K0sh selection - Configurable dotruthk0sh{"dotruthk0sh", true, "Enable K0sh MC Matching"}; + Configurable dotruthK0sh{"dotruthK0sh", true, "Enable K0sh MC Matching"}; Configurable doK0shTPCPID{"doK0shTPCPID", true, "Enable K0sh TPC PID"}; Configurable doK0shcomptmasscut{"doK0shcomptmasscut", true, "Enable K0sh Competitive V0 Mass Cut"}; Configurable doK0shMaxct{"doK0shMaxct", true, "Enable K0sh Max ct Cut"}; @@ -126,16 +126,16 @@ struct V0PtInvMassPlots { Configurable doLambdadcanegdautopv{"doLambdadcanegdautopv", true, "Enable Lambda DCA neg daughter to PV Topological Cut"}; // Configurables switches for Lambda selection - Configurable dotruthAntilambda{"dotruthAntilambda", true, "Enable Antilambda MC Matching"}; - Configurable doAntilambdaTPCPID{"doAntilambdaTPCPID", true, "Enable Antilambda TPC PID"}; - Configurable doAntilambdacomptmasscut{"doAntilambdacomptmasscut", true, "Enable Antilambda Competitive V0 Mass Cut"}; - Configurable doAntilambdaMaxct{"doAntilambdaMaxct", true, "Enable Antilambda Max ct Cut"}; - Configurable doAntilambdaArmenterosCut{"doAntilambdaArmenterosCut", true, "Enable Antilambda Armenteros Cut"}; - Configurable doAntilambdacosPACut{"doAntilambdacosPACut", true, "Enable Antilambda cosPA Topological Cut"}; - Configurable doAntilambdaDCAdauCut{"doAntilambdaDCAdauCut", true, "Enable Antilambda DCA daughters Topological Cut"}; - Configurable doAntilambdav0radiusCut{"doAntilambdav0radiusCut", true, "Enable Antilambda v0radius Topological Cut"}; - Configurable doAntilambdadcaposdautopv{"doAntilambdadcaposdautopv", true, "Enable Antilambda DCA pos daughter to PV Topological Cut"}; - Configurable doAntilambdadcanegdautopv{"doAntilambdadcanegdautopv", true, "Enable Antilambda DCA neg daughter to PV Topological Cut"}; + Configurable dotruthAntiLambda{"dotruthAntiLambda", true, "Enable AntiLambda MC Matching"}; + Configurable doAntilambdaTPCPID{"doAntilambdaTPCPID", true, "Enable AntiLambda TPC PID"}; + Configurable doAntilambdacomptmasscut{"doAntilambdacomptmasscut", true, "Enable AntiLambda Competitive V0 Mass Cut"}; + Configurable doAntilambdaMaxct{"doAntilambdaMaxct", true, "Enable AntiLambda Max ct Cut"}; + Configurable doAntilambdaArmenterosCut{"doAntilambdaArmenterosCut", true, "Enable AntiLambda Armenteros Cut"}; + Configurable doAntilambdacosPACut{"doAntilambdacosPACut", true, "Enable AntiLambda cosPA Topological Cut"}; + Configurable doAntilambdaDCAdauCut{"doAntilambdaDCAdauCut", true, "Enable AntiLambda DCA daughters Topological Cut"}; + Configurable doAntilambdav0radiusCut{"doAntilambdav0radiusCut", true, "Enable AntiLambda v0radius Topological Cut"}; + Configurable doAntilambdadcaposdautopv{"doAntilambdadcaposdautopv", true, "Enable AntiLambda DCA pos daughter to PV Topological Cut"}; + Configurable doAntilambdadcanegdautopv{"doAntilambdadcanegdautopv", true, "Enable AntiLambda DCA neg daughter to PV Topological Cut"}; // Configurable K0sh Cuts (best cuts determined by v0topologicalcuts task) Configurable k0shSettingdcav0dau{"k0shSettingdcav0dau", 0.3, "DCA V0 Daughters"}; @@ -155,24 +155,24 @@ struct V0PtInvMassPlots { Configurable lambdamaxct{"lambdamaxct", 30.00, "Lambda maximum ct value"}; Configurable lambdaparamArmenterosCut{"lambdaparamArmenterosCut", 0.2, "Lambda Armenteros Cut on parameter"}; - // Configurable Antilambda Cuts (best cuts determined by v0topologicalcuts task) + // Configurable AntiLambda Cuts (best cuts determined by v0topologicalcuts task) Configurable antilambdaSettingdcav0dau{"antilambdaSettingdcav0dau", 0.3, "DCA V0 Daughters"}; Configurable antilambdaSettingdcapostopv{"antilambdaSettingdcapostopv", 0.09, "DCA Pos To PV"}; Configurable antilambdaSettingdcanegtopv{"antilambdaSettingdcanegtopv", 0.05, "DCA Neg To PV"}; Configurable antilambdaSettingcosPA{"antilambdaSettingcosPA", 0.98, "V0 CosPA"}; // double -> N.B. dcos(x)/dx = 0 at x=0 Configurable antilambdaSettingradius{"antilambdaSettingradius", 0.50, "v0radius"}; - Configurable antilambdamaxct{"antilambdamaxct", 30.00, "Antilambda maximum ct value"}; - Configurable antilambdaparamArmenterosCut{"antilambdaparamArmenterosCut", 0.2, "Antilambda Armenteros Cut on parameter"}; + Configurable antilambdamaxct{"antilambdamaxct", 30.00, "AntiLambda maximum ct value"}; + Configurable antilambdaparamArmenterosCut{"antilambdaparamArmenterosCut", 0.2, "AntiLambda Armenteros Cut on parameter"}; // Configurables for Specific V0s analysis - Configurable kzeroAnalysis{"kzeroAnalysis", true, "Enable Kzerosh Pt Analysis"}; + Configurable kzeroAnalysis{"kzeroAnalysis", true, "Enable K0sh Pt Analysis"}; Configurable lambdaAnalysis{"lambdaAnalysis", true, "Enable Lambda Pt Analysis"}; - Configurable antiLambdaAnalysis{"antiLambdaAnalysis", true, "Enable Antilambda Pt Analysis"}; + Configurable antiLambdaAnalysis{"antiLambdaAnalysis", true, "Enable AntiLambda Pt Analysis"}; // Configurable string for Different Pt Bins - Configurable kzeroSettingPtBinsString{"kzeroSettingPtBinsString", {"0.0,0.15,0.3,0.45,0.6,0.75,0.9,1.05,1.2,1.35,1.5,1.65,1.8,1.95,2.1,2.25,2.4,2.55,2.7,2.85,3.0"}, "Kzero Pt Bin Values"}; + Configurable kzeroSettingPtBinsString{"kzeroSettingPtBinsString", {"0.0,0.15,0.3,0.45,0.6,0.75,0.9,1.05,1.2,1.35,1.5,1.65,1.8,1.95,2.1,2.25,2.4,2.55,2.7,2.85,3.0"}, "K0sh Pt Bin Values"}; Configurable lambdaSettingPtBinsString{"lambdaSettingPtBinsString", {"0.0,0.15,0.3,0.45,0.6,0.75,0.9,1.05,1.2,1.35,1.5,1.65,1.8,1.95,2.1,2.25,2.4,2.55,2.7,2.85,3.0"}, "Lambda Pt Bin Values"}; - Configurable antilambdaSettingPtBinsString{"antilambdaSettingPtBinsString", {"0.0,0.15,0.3,0.45,0.6,0.75,0.9,1.05,1.2,1.35,1.5,1.65,1.8,1.95,2.1,2.25,2.4,2.55,2.7,2.85,3.0"}, "Antilambda Pt Bin Values"}; + Configurable antilambdaSettingPtBinsString{"antilambdaSettingPtBinsString", {"0.0,0.15,0.3,0.45,0.6,0.75,0.9,1.05,1.2,1.35,1.5,1.65,1.8,1.95,2.1,2.25,2.4,2.55,2.7,2.85,3.0"}, "AntiLambda Pt Bin Values"}; void init(InitContext const&) { @@ -188,10 +188,10 @@ struct V0PtInvMassPlots { pthistos::kaonPt.resize(nKaonHistograms); // number of Kaon Pt histograms to expect pthistos::lambdaPt.resize(nLambdaHistograms); // number of Lambda histograms to expect - pthistos::antilambdaPt.resize(nAntilambdaHistograms); // number of Antilambda histograms to expect + pthistos::antilambdaPt.resize(nAntilambdaHistograms); // number of AntiLambda histograms to expect pthistos::kaonSplit.resize(nKaonHistograms); // number of Kaon Split Pt histograms to expect pthistos::lambdaSplit.resize(nLambdaHistograms); // number of Lambda Split Pt histograms to expect - pthistos::antilambdaSplit.resize(nAntilambdaHistograms); // number of Antilambda Split Pt histograms to expect + pthistos::antilambdaSplit.resize(nAntilambdaHistograms); // number of AntiLambda Split Pt histograms to expect // initialize and convert tokenized strings into vector of doubles for AxisSpec std::vector kaonptedgevalues(pthistos::kaonPtBins.size()); @@ -257,7 +257,7 @@ struct V0PtInvMassPlots { rPtAnalysis.add("hV0EtaDaughters", "hV0EtaDaughters", {HistType::kTH1F, {{nBins, -1.2f, 1.2f}}}); rPtAnalysis.add("V0Rapidity", "V0Rapidity", {HistType::kTH1F, {{nBins, -1.0f, 1.0f}}}); - // Adding Kzerosh Histograms to registry + // Adding K0sh Histograms to registry if (kzeroAnalysis == true) { rPtAnalysis.add("hMassK0ShortvsCuts", "hMassK0ShortvsCuts", {HistType::kTH2F, {{partCutsAxis}, {k0ShortMassAxis}}}); rPtAnalysis.add("hArmenterosPodolanskiPlotK0sh", "hArmenterosPodolanskiPlotK0sh", {HistType::kTH2F, {{armenterosasymAxis}, {armenterosQtAxis}}}); @@ -277,7 +277,7 @@ struct V0PtInvMassPlots { } // Adding Lambda Histograms if (lambdaAnalysis == true) { - // same method as in Kzerosh above + // same method as in K0sh above rPtAnalysis.add("hMassLambdavsCuts", "hMassLambdavsCuts", {HistType::kTH2F, {{partCutsAxis}, {k0ShortMassAxis}}}); rPtAnalysis.add("hArmenterosPodolanskiPlotLambda", "hArmenterosPodolanskiPlotLambda", {HistType::kTH2F, {{armenterosasymAxis}, {armenterosQtAxis}}}); rPtAnalysis.add("hNSigmaPosProtonFromLambdas", "hNSigmaPosProtonFromLambdas", {HistType::kTH2F, {{100, -5.f, 5.f}, {lambdaPtAxis}}}); @@ -298,9 +298,9 @@ struct V0PtInvMassPlots { rFeeddownMatrices.add("hLambdaXiZeroFeeddownMatrix", "hLambdaXiZeroFeeddownMatrix", {HistType::kTH3D, {lambdaPtAxis, lambdaPtAxis, centAxis}}); rFeeddownMatrices.add("hLambdaOmegaFeeddownMatrix", "hLambdaOmegaFeeddownMatrix", {HistType::kTH3D, {lambdaPtAxis, lambdaPtAxis, centAxis}}); } - // Adding Antilambda Histograms + // Adding AntiLambda Histograms if (antiLambdaAnalysis == true) { - // same method as in Lambda and Kzerosh above + // same method as in Lambda and K0sh above rPtAnalysis.add("hMassAntiLambdavsCuts", "hMassAntiLambdavsCuts", {HistType::kTH2F, {{partCutsAxis}, {k0ShortMassAxis}}}); rPtAnalysis.add("hArmenterosPodolanskiPlotAntiLambda", "hArmenterosPodolanskiPlotAntiLambda", {HistType::kTH2F, {{armenterosasymAxis}, {armenterosQtAxis}}}); rPtAnalysis.add("hNSigmaPosPionFromAntiLambdas", "hNSigmaPosPionFromAntiLambdas", {HistType::kTH2F, {{100, -5.f, 5.f}, {antilambdaPtAxis}}}); @@ -436,7 +436,7 @@ struct V0PtInvMassPlots { rPtAnalysis.fill(HIST("hNK0sh"), 2.5, collision.centFT0M()); rPtAnalysis.get(HIST("hNK0sh"))->GetXaxis()->SetBinLabel(3, "TPC_PID"); rPtAnalysis.fill(HIST("hMassK0ShortvsCuts"), 2.5, v0.mK0Short()); - if (doK0shcomptmasscut && ((std::abs(v0.mLambda() - o2::constants::physics::MassLambda0) < compv0masscut) || (std::abs(v0.mAntiLambda() - o2::constants::physics::MassLambda0) < compv0masscut))) { // Kzero competitive v0 mass cut (cut out Lambdas and Anti-Lambdas) + if (doK0shcomptmasscut && ((std::abs(v0.mLambda() - o2::constants::physics::MassLambda0) < compv0masscut) || (std::abs(v0.mAntiLambda() - o2::constants::physics::MassLambda0) < compv0masscut))) { // K0sh competitive v0 mass cut (cut out Lambdas and Anti-Lambdas) return false; } rPtAnalysis.fill(HIST("hNK0sh"), 3.5, collision.centFT0M()); @@ -580,7 +580,7 @@ struct V0PtInvMassPlots { return true; } - // Antilambda selection function + // AntiLambda selection function template bool acceptAntilambda(TV0 const& v0, Track const& posDaughterTrack, Track const& negDaughterTrack, TCollision const& collision) { @@ -600,64 +600,64 @@ struct V0PtInvMassPlots { rPtAnalysis.fill(HIST("hNAntiLambda"), 2.5, collision.centFT0M()); rPtAnalysis.get(HIST("hNAntiLambda"))->GetXaxis()->SetBinLabel(3, "TPC_PID"); rPtAnalysis.fill(HIST("hMassAntiLambdavsCuts"), 2.5, v0.mAntiLambda()); - if (doAntilambdacomptmasscut && ((std::abs(v0.mK0Short() - o2::constants::physics::MassK0Short) < compv0masscut) || (std::abs(v0.mLambda() - o2::constants::physics::MassLambda0) < compv0masscut))) { // Antilambda competitive v0 mass cut (cut out Kaons) + if (doAntilambdacomptmasscut && ((std::abs(v0.mK0Short() - o2::constants::physics::MassK0Short) < compv0masscut) || (std::abs(v0.mLambda() - o2::constants::physics::MassLambda0) < compv0masscut))) { // AntiLambda competitive v0 mass cut (cut out Kaons) return false; } rPtAnalysis.fill(HIST("hNAntiLambda"), 3.5, collision.centFT0M()); rPtAnalysis.get(HIST("hNAntiLambda"))->GetXaxis()->SetBinLabel(4, "Compt_Mass"); rPtAnalysis.fill(HIST("hMassAntiLambdavsCuts"), 3.5, v0.mAntiLambda()); - if (doAntilambdaMaxct && (v0.v0radius() > antilambdamaxct)) { // Antilambda max ct + if (doAntilambdaMaxct && (v0.v0radius() > antilambdamaxct)) { // AntiLambda max ct return false; } rPtAnalysis.fill(HIST("hNAntiLambda"), 4.5, collision.centFT0M()); rPtAnalysis.get(HIST("hNAntiLambda"))->GetXaxis()->SetBinLabel(5, "Max_ct"); rPtAnalysis.fill(HIST("hMassAntiLambdavsCuts"), 4.5, v0.mAntiLambda()); - if (doAntilambdaArmenterosCut && (v0.qtarm() < (antilambdaparamArmenterosCut * std::abs(v0.alpha())))) { // Antilambda Armenteros Cut + if (doAntilambdaArmenterosCut && (v0.qtarm() < (antilambdaparamArmenterosCut * std::abs(v0.alpha())))) { // AntiLambda Armenteros Cut return false; } rPtAnalysis.fill(HIST("hNAntiLambda"), 5.5, collision.centFT0M()); rPtAnalysis.get(HIST("hNAntiLambda"))->GetXaxis()->SetBinLabel(6, "Armenteros"); rPtAnalysis.fill(HIST("hMassAntiLambdavsCuts"), 5.5, v0.mAntiLambda()); - if (doAntilambdacosPACut && (v0.v0cosPA() < antilambdaSettingcosPA)) { // Antilambda cosPA Topological Cut + if (doAntilambdacosPACut && (v0.v0cosPA() < antilambdaSettingcosPA)) { // AntiLambda cosPA Topological Cut return false; } rPtAnalysis.fill(HIST("hNAntiLambda"), 6.5, collision.centFT0M()); rPtAnalysis.get(HIST("hNAntiLambda"))->GetXaxis()->SetBinLabel(7, "cosPA"); rPtAnalysis.fill(HIST("hMassAntiLambdavsCuts"), 6.5, v0.mAntiLambda()); - if (doAntilambdaDCAdauCut && (v0.dcaV0daughters() > antilambdaSettingdcav0dau)) { // Antilambda DCAdaughters Topological Cut + if (doAntilambdaDCAdauCut && (v0.dcaV0daughters() > antilambdaSettingdcav0dau)) { // AntiLambda DCAdaughters Topological Cut return false; } rPtAnalysis.fill(HIST("hNAntiLambda"), 7.5, collision.centFT0M()); rPtAnalysis.get(HIST("hNAntiLambda"))->GetXaxis()->SetBinLabel(8, "DCAdau"); rPtAnalysis.fill(HIST("hMassAntiLambdavsCuts"), 7.5, v0.mAntiLambda()); - if (doAntilambdav0radiusCut && (v0.v0radius() < antilambdaSettingradius)) { // Antilambda v0radius Topological Cut + if (doAntilambdav0radiusCut && (v0.v0radius() < antilambdaSettingradius)) { // AntiLambda v0radius Topological Cut return false; } rPtAnalysis.fill(HIST("hNAntiLambda"), 8.5, collision.centFT0M()); rPtAnalysis.get(HIST("hNAntiLambda"))->GetXaxis()->SetBinLabel(9, "v0radius"); rPtAnalysis.fill(HIST("hMassAntiLambdavsCuts"), 8.5, v0.mAntiLambda()); - if (doAntilambdadcaposdautopv && (std::abs(v0.dcapostopv()) < antilambdaSettingdcapostopv)) { // Antilambda DCAPosDaughterToPV Topological Cut + if (doAntilambdadcaposdautopv && (std::abs(v0.dcapostopv()) < antilambdaSettingdcapostopv)) { // AntiLambda DCAPosDaughterToPV Topological Cut return false; } - rPtAnalysis.fill(HIST("hNAntilambda"), 9.5, collision.centFT0M()); - rPtAnalysis.get(HIST("hNAntilambda"))->GetXaxis()->SetBinLabel(10, "DCAPosDautoPV"); - rPtAnalysis.fill(HIST("hMassAntilambdavsCuts"), 9.5, v0.mAntiLambda()); - if (doAntilambdadcanegdautopv && (std::abs(v0.dcanegtopv()) < antilambdaSettingdcanegtopv)) { // Antilambda DCANegDaughterToPV Topological Cut + rPtAnalysis.fill(HIST("hNAntiLambda"), 9.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNAntiLambda"))->GetXaxis()->SetBinLabel(10, "DCAPosDautoPV"); + rPtAnalysis.fill(HIST("hMassAntiLambdavsCuts"), 9.5, v0.mAntiLambda()); + if (doAntilambdadcanegdautopv && (std::abs(v0.dcanegtopv()) < antilambdaSettingdcanegtopv)) { // AntiLambda DCANegDaughterToPV Topological Cut return false; } - rPtAnalysis.fill(HIST("hNAntilambda"), 10.5, collision.centFT0M()); - rPtAnalysis.get(HIST("hNAntilambda"))->GetXaxis()->SetBinLabel(11, "DCANegDautoPV"); - rPtAnalysis.fill(HIST("hMassAntilambdavsCuts"), 10.5, v0.mAntiLambda()); + rPtAnalysis.fill(HIST("hNAntiLambda"), 10.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNAntiLambda"))->GetXaxis()->SetBinLabel(11, "DCANegDautoPV"); + rPtAnalysis.fill(HIST("hMassAntiLambdavsCuts"), 10.5, v0.mAntiLambda()); // Cut plots - rPtAnalysis.fill(HIST("hArmenterosPodolanskiPlotAntilambda"), v0.alpha(), v0.qtarm()); + rPtAnalysis.fill(HIST("hArmenterosPodolanskiPlotAntiLambda"), v0.alpha(), v0.qtarm()); // rPtAnalysis.fill(HIST("hNSigmaPosPionFromAntilambdas"), posDaughterTrack.tpcNSigmaPr(), posDaughterTrack.tpcInnerParam()); // rPtAnalysis.fill(HIST("hNSigmaNegProtonFromAntilambdas"), negDaughterTrack.tpcNSigmaPi(), negDaughterTrack.tpcInnerParam()); - rPtAnalysis.fill(HIST("hAntilambdacosPA"), v0.v0cosPA()); - rPtAnalysis.fill(HIST("hAntilambdaV0radius"), v0.v0radius()); - rPtAnalysis.fill(HIST("hAntilambdaDCAV0Daughters"), v0.dcaV0daughters()); - rPtAnalysis.fill(HIST("hAntilambdaDCAPosDaughter"), v0.dcapostopv()); - rPtAnalysis.fill(HIST("hAntilambdaDCANegDaughter"), v0.dcanegtopv()); + rPtAnalysis.fill(HIST("hAntiLambdacosPA"), v0.v0cosPA()); + rPtAnalysis.fill(HIST("hAntiLambdaV0radius"), v0.v0radius()); + rPtAnalysis.fill(HIST("hAntiLambdaDCAV0Daughters"), v0.dcaV0daughters()); + rPtAnalysis.fill(HIST("hAntiLambdaDCAPosDaughter"), v0.dcapostopv()); + rPtAnalysis.fill(HIST("hAntiLambdaDCANegDaughter"), v0.dcanegtopv()); rPtAnalysis.fill(HIST("V0Rapidity"), v0.rapidity(2)); return true; } @@ -715,15 +715,15 @@ struct V0PtInvMassPlots { if (std::abs(mcParticle.y()) < rapidityCut) { if (mcParticle.isPhysicalPrimary()) { rMCCorrections.fill(HIST("GenParticleRapidity"), mcParticle.y()); - if (mcParticle.pdgCode() == kK0Short) // kzero matched + if (mcParticle.pdgCode() == kK0Short) // K0sh matched { rMCCorrections.fill(HIST("hK0shGeneratedPtSpectrum"), mcParticle.pt(), mcCollision.centFT0M()); } - if (mcParticle.pdgCode() == kLambda0) // lambda matched + if (mcParticle.pdgCode() == kLambda0) // Lambda matched { rMCCorrections.fill(HIST("hLambdaGeneratedPtSpectrum"), mcParticle.pt(), mcCollision.centFT0M()); } - if (mcParticle.pdgCode() == kLambda0Bar) // antilambda matched + if (mcParticle.pdgCode() == kLambda0Bar) // AntiLambda matched { rMCCorrections.fill(HIST("hAntiLambdaGeneratedPtSpectrum"), mcParticle.pt(), mcCollision.centFT0M()); } @@ -789,7 +789,8 @@ struct V0PtInvMassPlots { // End of Signal Loss Numenator Loop } // This is the Process for the MC reconstructed Data - void recMCProcess(soa::Join::iterator const& collision, + // void recMCProcess(soa::Join::iterator const& collision, + void recMCProcess(soa::Join::iterator const& collision, soa::Join const& /*mcCollisions*/, soa::Join const& V0s, DaughterTracks const&, // no need to define a variable for tracks, if we don't access them directly @@ -846,7 +847,7 @@ struct V0PtInvMassPlots { // K0sh Signla Split Numerator End if (v0.has_mcParticle()) { auto v0mcParticle = v0.mcParticle(); - if (dotruthk0sh && (v0mcParticle.pdgCode() == kK0Short)) { // kzero matched + if (dotruthK0sh && (v0mcParticle.pdgCode() == kK0Short)) { // kzero matched if (v0mcParticle.isPhysicalPrimary()) { for (int i = 0; i < nKaonHistograms; i++) { if (kaonptedgevalues[i] <= v0.pt() && v0.pt() < kaonptedgevalues[i + 1]) { // finding v0s with pt within the range of our bin edges @@ -910,17 +911,17 @@ struct V0PtInvMassPlots { } // antilambda analysis if (antiLambdaAnalysis == true) { - if (acceptAntilambda(v0, posDaughterTrack, negDaughterTrack, mcCollision)) { // Antilambda Selections - // Antilambda Signal Split Numerator End + if (acceptAntilambda(v0, posDaughterTrack, negDaughterTrack, mcCollision)) { // AntiLambda Selections + // AntiLambda Signal Split Numerator End for (int i = 0; i < nAntilambdaHistograms; i++) { if (antilambdaptedgevalues[i] <= v0.pt() && v0.pt() < antilambdaptedgevalues[i + 1]) { pthistos::antilambdaSplit[i]->Fill(v0.mAntiLambda(), mcCollision.centFT0M()); } } - // Antilambda Signal Split Numerator End + // AntiLambda Signal Split Numerator End if (v0.has_mcParticle()) { auto v0mcParticle = v0.mcParticle(); - if (dotruthAntilambda && (v0mcParticle.pdgCode() == kLambda0Bar)) { // antilambda matched + if (dotruthAntiLambda && (v0mcParticle.pdgCode() == kLambda0Bar)) { // antilambda matched if (v0mcParticle.isPhysicalPrimary()) { for (int i = 0; i < nAntilambdaHistograms; i++) { if (antilambdaptedgevalues[i] <= v0.pt() && v0.pt() < antilambdaptedgevalues[i + 1]) { @@ -992,7 +993,7 @@ struct V0PtInvMassPlots { if (!acceptV0(v0, posDaughterTrack, negDaughterTrack, collision)) { // V0 Selection continue; } - // kzero analysis + // K0sh analysis if (kzeroAnalysis == true) { if (acceptK0sh(v0, posDaughterTrack, negDaughterTrack, collision)) { // K0sh Selection for (int i = 0; i < nKaonHistograms; i++) { @@ -1002,7 +1003,7 @@ struct V0PtInvMassPlots { } } } - // lambda analysis + // Lambda analysis if (lambdaAnalysis == true) { if (acceptLambda(v0, posDaughterTrack, negDaughterTrack, collision)) { // Lambda Selection for (int i = 0; i < nLambdaHistograms; i++) { @@ -1012,9 +1013,9 @@ struct V0PtInvMassPlots { } } } - // anti-lambda analysis + // Anti-Lambda analysis if (antiLambdaAnalysis == true) { - if (acceptAntilambda(v0, posDaughterTrack, negDaughterTrack, collision)) { // Antilambda Selection + if (acceptAntilambda(v0, posDaughterTrack, negDaughterTrack, collision)) { // AntiLambda Selection for (int i = 0; i < nAntilambdaHistograms; i++) { if (lambdaptedgevalues[i] <= v0.pt() && v0.pt() < lambdaptedgevalues[i + 1]) { pthistos::antilambdaPt[i]->Fill(v0.mAntiLambda(), collision.centFT0M()); @@ -1066,7 +1067,7 @@ struct V0PtInvMassPlots { if (!acceptV0Derived(v0, posDaughterTrack, negDaughterTrack, collision)) { // V0 Selection continue; } - // kzero analysis + // K0sh analysis if (kzeroAnalysis == true) { if (acceptK0sh(v0, posDaughterTrack, negDaughterTrack, collision)) { // K0sh Selection for (int i = 0; i < nKaonHistograms; i++) { @@ -1076,7 +1077,7 @@ struct V0PtInvMassPlots { } } } - // lambda analysis + // Lambda analysis if (lambdaAnalysis == true) { if (acceptLambda(v0, posDaughterTrack, negDaughterTrack, collision)) { // Lambda Selection for (int i = 0; i < nLambdaHistograms; i++) { @@ -1086,9 +1087,9 @@ struct V0PtInvMassPlots { } } } - // anti-lambda analysis + // Anti-Lambda analysis if (antiLambdaAnalysis == true) { - if (acceptAntilambda(v0, posDaughterTrack, negDaughterTrack, collision)) { // Antilambda Selection + if (acceptAntilambda(v0, posDaughterTrack, negDaughterTrack, collision)) { // AntiLambda Selection for (int i = 0; i < nAntilambdaHistograms; i++) { if (antilambdaptedgevalues[i] <= v0.pt() && v0.pt() < antilambdaptedgevalues[i + 1]) { pthistos::antilambdaPt[i]->Fill(v0.mAntiLambda(), collision.centFT0M()); @@ -1139,7 +1140,7 @@ struct V0PtInvMassPlots { if (!acceptV0Derived(v0, posDaughterTrack, negDaughterTrack, collision)) { // V0 Selections continue; } - // kzero analysis + // K0sh Analysis if (kzeroAnalysis == true) { if (acceptK0sh(v0, posDaughterTrack, negDaughterTrack, collision)) { // K0sh Selection // K0sh Signal Split Numerator Start @@ -1151,7 +1152,7 @@ struct V0PtInvMassPlots { // K0sh SignaL Split Numerator End if (v0.has_v0MCCore()) { auto v0mcParticle = v0.v0MCCore_as(); - if (dotruthk0sh && (v0mcParticle.pdgCode() == kK0Short)) { // kzero matched + if (dotruthK0sh && (v0mcParticle.pdgCode() == kK0Short)) { // kzero matched if (v0mcParticle.isPhysicalPrimary()) { for (int i = 0; i < nKaonHistograms; i++) { if (kaonptedgevalues[i] <= v0.ptMC() && v0.ptMC() < kaonptedgevalues[i + 1]) { // finding v0s with pt within the range of our bin edges @@ -1170,7 +1171,7 @@ struct V0PtInvMassPlots { } } } - // lambda analysis + // Lambda analysis if (lambdaAnalysis == true) { if (acceptLambda(v0, posDaughterTrack, negDaughterTrack, collision)) { // Lambda Selections // Lambda Signal Split Numerator Start @@ -1207,19 +1208,19 @@ struct V0PtInvMassPlots { } } } - // antilambda analysis + // AntiLambda analysis if (antiLambdaAnalysis == true) { - if (acceptAntilambda(v0, posDaughterTrack, negDaughterTrack, collision)) { // Antilambda Selections - // Antilambda Signal Split Numerator End + if (acceptAntilambda(v0, posDaughterTrack, negDaughterTrack, collision)) { // AntiLambda Selections + // AntiLambda Signal Split Numerator End for (int i = 0; i < nAntilambdaHistograms; i++) { if (antilambdaptedgevalues[i] <= v0.ptMC() && v0.ptMC() < antilambdaptedgevalues[i + 1]) { pthistos::antilambdaSplit[i]->Fill(v0.mAntiLambda(), collision.centFT0M()); } } - // Antilambda Signal Split Numerator End + // AntiLambda Signal Split Numerator End if (v0.has_v0MCCore()) { auto v0mcParticle = v0.v0MCCore_as(); - if (dotruthAntilambda && (v0mcParticle.pdgCode() == kLambda0Bar)) { // antilambda matched + if (dotruthAntiLambda && (v0mcParticle.pdgCode() == kLambda0Bar)) { // antilambda matched if (v0mcParticle.isPhysicalPrimary()) { for (int i = 0; i < nAntilambdaHistograms; i++) { if (antilambdaptedgevalues[i] <= v0.ptMC() && v0.ptMC() < antilambdaptedgevalues[i + 1]) { From 2e8b8e49ba5a667467a9680275d0ec117e50c76a Mon Sep 17 00:00:00 2001 From: EmilGorm <50658075+EmilGorm@users.noreply.github.com> Date: Thu, 12 Mar 2026 22:46:21 +0100 Subject: [PATCH 270/347] [PWGCF] Modify QA axes, remove pass-by-ref on int (#15362) --- .../Tasks/flowGenericFramework.cxx | 54 +++++++++++++------ 1 file changed, 38 insertions(+), 16 deletions(-) diff --git a/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx b/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx index 44e1669f2cb..7f27550ef6c 100644 --- a/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx +++ b/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx @@ -280,8 +280,8 @@ struct FlowGenericFramework { TF1* fMultGlobalT0ACutHigh = nullptr; // Track selection - pt-phi cuts - TF1* fPhiCutLow; - TF1* fPhiCutHigh; + TF1* fPhiCutLow = nullptr; + TF1* fPhiCutHigh = nullptr; void init(InitContext const&) { @@ -334,11 +334,11 @@ struct FlowGenericFramework { } AxisSpec nchAxis = {nchbinning, "N_{ch}"}; AxisSpec bAxis = {200, 0, 20, "#it{b}"}; - AxisSpec t0cAxis = {1000, 0, 10000, "N_{ch} (T0C)"}; - AxisSpec t0aAxis = {300, 0, 30000, "N_{ch} (T0A)"}; - AxisSpec v0aAxis = {800, 0, 80000, "N_{ch} (V0A)"}; - AxisSpec multpvAxis = {600, 0, 600, "N_{ch} (PV)"}; - AxisSpec occAxis = {600, 0, 3000, "occupancy"}; + AxisSpec t0cAxis = {1000, 0, 50000, "N_{ch} (T0C)"}; + AxisSpec t0aAxis = {1800, 0, 180000, "N_{ch} (T0A)"}; + AxisSpec v0aAxis = {1800, 0, 180000, "N_{ch} (V0A)"}; + AxisSpec multpvAxis = {3500, 0, 3500, "N_{ch} (PV)"}; + AxisSpec occAxis = {500, 0, 5000, "occupancy"}; AxisSpec multAxis = (doprocessOnTheFly && !cfgUseNch) ? bAxis : (cfgUseNch) ? nchAxis : centAxis; AxisSpec dcaZAXis = {200, -2, 2, "DCA_{z} (cm)"}; @@ -380,8 +380,8 @@ struct FlowGenericFramework { registry.add("eventQA/before/PVTracks_centT0C", "; FT0C centrality (%); N_{PV}", {HistType::kTH2D, {centAxis, multpvAxis}}); registry.add("eventQA/before/globalTracks_PVTracks", "; N_{PV}; N_{global}", {HistType::kTH2D, {multpvAxis, nchAxis}}); registry.add("eventQA/before/globalTracks_multT0A", "; multT0A; N_{global}", {HistType::kTH2D, {t0aAxis, nchAxis}}); - registry.add("eventQA/before/globalTracks_multV0A", "; multV0A; N_{global}", {HistType::kTH2D, {t0aAxis, nchAxis}}); - registry.add("eventQA/before/multV0A_multT0A", "; multV0A; multT0A", {HistType::kTH2D, {t0aAxis, t0aAxis}}); + registry.add("eventQA/before/globalTracks_multV0A", "; multV0A; N_{global}", {HistType::kTH2D, {v0aAxis, nchAxis}}); + registry.add("eventQA/before/multV0A_multT0A", "; multV0A; multT0A", {HistType::kTH2D, {t0aAxis, v0aAxis}}); registry.add("eventQA/before/multT0C_centT0C", "; multT0C; FT0C centrality (%)", {HistType::kTH2D, {centAxis, t0cAxis}}); registry.add("eventQA/before/occ_mult_cent", "; occupancy; N_{ch}; centrality (%)", {HistType::kTH3D, {occAxis, nchAxis, centAxis}}); registry.addClone("eventQA/before/", "eventQA/after/"); @@ -633,7 +633,7 @@ struct FlowGenericFramework { } template - bool eventSelected(TCollision collision, const int& multTrk, const float& centrality, const int& run) + bool eventSelected(TCollision collision, const int multTrk, const float& centrality, const int run) { // Cut on trigger alias if (cfgEventCutFlags.cfgTVXinTRD) { @@ -686,7 +686,7 @@ struct FlowGenericFramework { } template - bool selectMultiplicityCorrelation(TCollision collision, const int& multTrk, const float& centrality, const int& run) + bool selectMultiplicityCorrelation(TCollision collision, const int multTrk, const float& centrality, const int run) { auto multNTracksPV = collision.multNTracksPV(); if (multNTracksPV < fMultPVCutLow->Eval(centrality)) @@ -715,7 +715,7 @@ struct FlowGenericFramework { } template - bool trackSelected(TTrack track, const int& field) + bool trackSelected(TTrack track, const int field) { if (cfgTrackCuts.cfgTPCSectorCut) { double phimodn = track.phi(); @@ -754,7 +754,7 @@ struct FlowGenericFramework { }; template - void fillWeights(const TTrack track, const double vtxz, const int& pid_index, const int& run) + void fillWeights(const TTrack track, const double vtxz, const int pid_index, const int run) { if (cfgUsePID) { double ptpidmins[] = {o2::analysis::gfw::ptpoilow, o2::analysis::gfw::ptpoilow, 0.3, 0.5}; // min pt for ch, pi, ka, pr @@ -795,7 +795,7 @@ struct FlowGenericFramework { return; } - void createRunByRunHistograms(const int& run) + void createRunByRunHistograms(const int run) { AxisSpec phiAxis = {o2::analysis::gfw::phibins, o2::analysis::gfw::philow, o2::analysis::gfw::phiup, "#phi"}; AxisSpec phiModAxis = {100, 0, constants::math::PI / 9, "fmod(#varphi,#pi/9)"}; @@ -883,7 +883,7 @@ struct FlowGenericFramework { } template - void processCollision(TCollision collision, TTracks tracks, const float& centrality, const int& field, const int& run) + void processCollision(TCollision collision, TTracks tracks, const float& centrality, const int field, const int run) { if (tracks.size() < 1) return; @@ -974,7 +974,7 @@ struct FlowGenericFramework { }; template - inline void processTrack(TTrack const& track, const float& vtxz, const int& field, const int& run, DensityCorr densitycorrections, AcceptedTracks& acceptedTracks) + inline void processTrack(TTrack const& track, const float& vtxz, const int field, const int run, DensityCorr densitycorrections, AcceptedTracks& acceptedTracks) { if constexpr (framework::has_type_v) { if (track.mcParticleId() < 0 || !(track.has_mcParticle())) @@ -1297,9 +1297,31 @@ struct FlowGenericFramework { if (cfgRunByRun) createRunByRunHistograms(run); } + + registry.fill(HIST("eventQA/eventSel"), 0.5); + if (cfgRunByRun) + th1sList[run][hEventSel]->Fill(0.5); + if (!collision.sel8()) return; + + registry.fill(HIST("eventQA/eventSel"), 1.5); + if (cfgRunByRun) + th1sList[run][hEventSel]->Fill(1.5); + const auto centrality = getCentrality(collision); + + if (cfgDoOccupancySel) { + int occupancy = collision.trackOccupancyInTimeRange(); + registry.fill(HIST("eventQA/before/occ_mult_cent"), occupancy, tracks.size(), centrality); + if (occupancy < 0 || occupancy > cfgOccupancySelection) + return; + registry.fill(HIST("eventQA/after/occ_mult_cent"), occupancy, tracks.size(), centrality); + } + registry.fill(HIST("eventQA/eventSel"), 2.5); + if (cfgRunByRun) + th1sList[run][hEventSel]->Fill(2.5); + if (cfgFillQA) fillEventQA(collision, tracks); if (!eventSelected(collision, tracks.size(), centrality, run)) From fc79b76d7b4296fee8fdbfb824850639f5b42693 Mon Sep 17 00:00:00 2001 From: Shirajum Monira <38348689+Eloviyo@users.noreply.github.com> Date: Fri, 13 Mar 2026 08:40:55 +0200 Subject: [PATCH 271/347] [PWGCF] FemtoUniverse V0 Task -- has TOF check under same and mixed events (#15371) Co-authored-by: Shirajum Monira --- .../femtoUniversePairTaskTrackV0Extended.cxx | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx index f10e793f263..5b55784f63f 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx @@ -482,8 +482,12 @@ struct FemtoUniversePairTaskTrackV0Extended { trackHistoPartOneNeg.fillQA(part); } } else { - if ((part.pidCut() & (64u << ConfTrkSelection.confTrackChoicePartOne)) == 0) + if ((part.pidCut() & 512u) != 0) { + if ((part.pidCut() & (64u << ConfTrkSelection.confTrackChoicePartOne)) == 0) + continue; + } else if ((part.pidCut() & (1u << ConfTrkSelection.confTrackChoicePartOne)) == 0) { continue; + } if (ConfTrkSelection.confChargePart1 > 0) trackHistoPartOnePos.fillQA(part); if (ConfTrkSelection.confChargePart1 < 0) @@ -501,8 +505,12 @@ struct FemtoUniversePairTaskTrackV0Extended { if (!isParticleCombined(p1, ConfTrkSelection.confTrackChoicePartOne)) continue; } else { - if ((p1.pidCut() & (64u << ConfTrkSelection.confTrackChoicePartOne)) == 0) + if ((p1.pidCut() & 512u) != 0) { + if ((p1.pidCut() & (64u << ConfTrkSelection.confTrackChoicePartOne)) == 0) + continue; + } else if ((p1.pidCut() & (1u << ConfTrkSelection.confTrackChoicePartOne)) == 0) { continue; + } } // track cleaning if (!pairCleaner.isCleanPair(p1, p2, parts)) { @@ -958,8 +966,12 @@ struct FemtoUniversePairTaskTrackV0Extended { if (!isParticleCombined(p1, ConfTrkSelection.confTrackChoicePartOne)) continue; } else { - if ((p1.pidCut() & (64u << ConfTrkSelection.confTrackChoicePartOne)) == 0) + if ((p1.pidCut() & 512u) != 0) { + if ((p1.pidCut() & (64u << ConfTrkSelection.confTrackChoicePartOne)) == 0) + continue; + } else if ((p1.pidCut() & (1u << ConfTrkSelection.confTrackChoicePartOne)) == 0) { continue; + } } const auto& posChild = parts.iteratorAt(p2.globalIndex() - 2 - parts.begin().globalIndex()); From 53ad797ca874f6edf9109b718b19ff2f50847993 Mon Sep 17 00:00:00 2001 From: Fan Si <147278151+fsii@users.noreply.github.com> Date: Fri, 13 Mar 2026 08:19:32 +0100 Subject: [PATCH 272/347] [PWGCF] Update histogram definitions (#15369) --- PWGCF/EbyEFluctuations/Tasks/partNumFluc.cxx | 219 +++++++++---------- 1 file changed, 109 insertions(+), 110 deletions(-) diff --git a/PWGCF/EbyEFluctuations/Tasks/partNumFluc.cxx b/PWGCF/EbyEFluctuations/Tasks/partNumFluc.cxx index a92d235b395..d0c34878282 100644 --- a/PWGCF/EbyEFluctuations/Tasks/partNumFluc.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/partNumFluc.cxx @@ -1157,17 +1157,18 @@ struct PartNumFluc { if (groupAnalysis.cfgFlagQaEvent.value) { LOG(info) << "Enabling event QA."; - const AxisSpec asNGlobalTracks(200, -0.5, 199.5, "nGlobalTracks"); + const AxisSpec asNTracks(200, -0.5, 199.5); + const HistogramConfigSpec hcsQaEvent(HistType::kTHnSparseD, {asNTracks, asNTracks}); hrQaEvent.add("QaEvent/hVxVy", "", {HistType::kTHnSparseD, {{150, -0.15, 0.15, "#it{V}_{#it{x}} (cm)"}, {150, -0.15, 0.15, "#it{V}_{#it{y}} (cm)"}}}); hrQaEvent.add("QaEvent/hVz", "", {HistType::kTH1D, {{300, -15., 15., "#it{V}_{#it{z}} (cm)"}}}); - hrQaEvent.add("QaEvent/hNPvContributorsNGlobalTracks", "", {HistType::kTHnSparseF, {{200, -0.5, 199.5, "nPvContributors"}, asNGlobalTracks}}); - hrQaEvent.add("QaEvent/hNGlobalTracksMeanDcaXy", "", {HistType::kTHnSparseF, {asNGlobalTracks, {200, -0.5, 0.5, "#LTDCA_{#it{xy}}#GT_{event} (cm)"}}}); - hrQaEvent.add("QaEvent/hNGlobalTracksMeanDcaXy_nPvContributorsCut", "", {HistType::kTHnSparseF, {asNGlobalTracks, {200, -0.5, 0.5, "#LTDCA_{#it{z}}#GT_{event} (cm)"}}}); - hrQaEvent.add("QaEvent/hNGlobalTracksMeanDcaZ", "", {HistType::kTHnSparseF, {asNGlobalTracks, {200, -2., 2., "#LTDCA_{#it{z}}#GT_{event} (cm)"}}}); - hrQaEvent.add("QaEvent/hNGlobalTracksMeanDcaZ_nPvContributorsCut", "", {HistType::kTHnSparseF, {asNGlobalTracks, {200, -2., 2., "#LTDCA_{#it{z}}#GT_{event} (cm)"}}}); - hrQaEvent.add("QaEvent/hNTofBetaNGlobalTracks", "", {HistType::kTHnSparseF, {{200, -0.5, 199.5, "nTofBeta"}, asNGlobalTracks}}); - hrQaEvent.add("QaEvent/hNTofBetaNGlobalTracks_nPvContributorsCut", "", {HistType::kTHnSparseF, {{200, -0.5, 199.5, "nTofBeta"}, asNGlobalTracks}}); + hrQaEvent.add("QaEvent/hNPvContributorsNGlobalTracks", ";nPvContributors;nGlobalTracks;", hcsQaEvent); + hrQaEvent.add("QaEvent/hNGlobalTracksMeanDcaXy", ";nGlobalTracks;", {HistType::kTHnSparseD, {asNTracks, {250, -0.25, 0.25, "#LTDCA_{#it{xy}}#GT_{event} (cm)"}}}); + hrQaEvent.add("QaEvent/hNGlobalTracksMeanDcaXy_nPvContributorsCut", ";nGlobalTracks;", {HistType::kTHnSparseD, {asNTracks, {250, -0.25, 0.25, "#LTDCA_{#it{z}}#GT_{event} (cm)"}}}); + hrQaEvent.add("QaEvent/hNGlobalTracksMeanDcaZ", ";nGlobalTracks;", {HistType::kTHnSparseD, {asNTracks, {200, -2., 2., "#LTDCA_{#it{z}}#GT_{event} (cm)"}}}); + hrQaEvent.add("QaEvent/hNGlobalTracksMeanDcaZ_nPvContributorsCut", ";nGlobalTracks;", {HistType::kTHnSparseD, {asNTracks, {200, -2., 2., "#LTDCA_{#it{z}}#GT_{event} (cm)"}}}); + hrQaEvent.add("QaEvent/hNTofBetaNGlobalTracks", ";nTofBeta;nGlobalTracks;", hcsQaEvent); + hrQaEvent.add("QaEvent/hNTofBetaNGlobalTracks_nPvContributorsCut", ";nTofBeta;nGlobalTracks;", hcsQaEvent); } if (groupAnalysis.cfgFlagQaCentrality.value) { @@ -1199,14 +1200,13 @@ struct PartNumFluc { LOG(info) << "Enabling DCA QA."; const AxisSpec asPt(200, 0., 2., "#it{p}_{T} (GeV/#it{c})"); - const AxisSpec asDca(400, -1., 1.); - hrQaDca.add("QaDca/hPtDcaXy_p", ";;DCA_{#it{xy}} (cm)", {HistType::kTHnSparseD, {asPt, asDca}}); - hrQaDca.add("QaDca/hPtDcaXy_m", ";;DCA_{#it{xy}} (cm)", {HistType::kTHnSparseD, {asPt, asDca}}); + hrQaDca.add("QaDca/hPtDcaXy_p", "", {HistType::kTHnSparseD, {asPt, {500, -0.5, 0.5, "DCA_{#it{xy}} (cm)"}}}); + hrQaDca.add("QaDca/hPtDcaXy_m", "", {HistType::kTHnSparseD, {asPt, {500, -0.5, 0.5, "DCA_{#it{xy}} (cm)"}}}); hrQaDca.add("QaDca/pPtDcaXy_p", ";;#LTDCA_{#it{xy}}#GT (cm)", {HistType::kTProfile, {asPt}}); hrQaDca.add("QaDca/pPtDcaXy_m", ";;#LTDCA_{#it{xy}}#GT (cm)", {HistType::kTProfile, {asPt}}); - hrQaDca.add("QaDca/hPtDcaZ_p", ";;DCA_{#it{z}} (cm)", {HistType::kTHnSparseD, {asPt, asDca}}); - hrQaDca.add("QaDca/hPtDcaZ_m", ";;DCA_{#it{z}} (cm)", {HistType::kTHnSparseD, {asPt, asDca}}); + hrQaDca.add("QaDca/hPtDcaZ_p", "", {HistType::kTHnSparseD, {asPt, {500, -1., 1., "DCA_{#it{z}} (cm)"}}}); + hrQaDca.add("QaDca/hPtDcaZ_m", "", {HistType::kTHnSparseD, {asPt, {500, -1., 1., "DCA_{#it{z}} (cm)"}}}); hrQaDca.add("QaDca/pPtDcaZ_p", ";;#LTDCA_{#it{z}}#GT (cm)", {HistType::kTProfile, {asPt}}); hrQaDca.add("QaDca/pPtDcaZ_m", ";;#LTDCA_{#it{z}}#GT (cm)", {HistType::kTProfile, {asPt}}); } @@ -1363,26 +1363,25 @@ struct PartNumFluc { } if (groupAnalysis.cfgFlagQaPidPi.value || groupAnalysis.cfgFlagQaPidKa.value || groupAnalysis.cfgFlagQaPidPr.value) { - const AxisSpec asPt(40, 0., 2., "#it{p}_{T} (GeV/#it{c})"); - const AxisSpec asEta(32, -0.8, 0.8, "#it{#eta}"); + const HistogramConfigSpec hcsQaPid(HistType::kTHnSparseF, {asCentrality, {40, 0., 2., "#it{p}_{T} (GeV/#it{c})"}, {32, -0.8, 0.8, "#it{#eta}"}, {200, -10., 10.}}); if (groupAnalysis.cfgFlagQaPidPi.value) { LOG(info) << "Enabling pion PID QA."; if (doprocessMc.value) { - hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaPi_mcPiP", "", {HistType::kTHnSparseF, {asCentrality, asPt, asEta, {200, -10., 10., "TPC #it{n}#it{#sigma}_{#pi}"}}}); - hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaPi_mcPiM", "", {HistType::kTHnSparseF, {asCentrality, asPt, asEta, {200, -10., 10., "TPC #it{n}#it{#sigma}_{#pi}"}}}); - hrQaPid.add("QaPid/hCentralityPtEtaTofNSigmaPi_mcPiP", "", {HistType::kTHnSparseF, {asCentrality, asPt, asEta, {200, -10., 10., "TOF #it{n}#it{#sigma}_{#pi}"}}}); - hrQaPid.add("QaPid/hCentralityPtEtaTofNSigmaPi_mcPiM", "", {HistType::kTHnSparseF, {asCentrality, asPt, asEta, {200, -10., 10., "TOF #it{n}#it{#sigma}_{#pi}"}}}); + hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaPi_mcPiP", ";;;;TPC #it{n}#it{#sigma}_{#pi};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaPi_mcPiM", ";;;;TPC #it{n}#it{#sigma}_{#pi};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTofNSigmaPi_mcPiP", ";;;;TOF #it{n}#it{#sigma}_{#pi};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTofNSigmaPi_mcPiM", ";;;;TOF #it{n}#it{#sigma}_{#pi};", hcsQaPid); } else if (doprocessRaw.value) { - hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaPi_p", "", {HistType::kTHnSparseF, {asCentrality, asPt, asEta, {200, -10., 10., "TPC #it{n}#it{#sigma}_{#pi}"}}}); - hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaPi_m", "", {HistType::kTHnSparseF, {asCentrality, asPt, asEta, {200, -10., 10., "TPC #it{n}#it{#sigma}_{#pi}"}}}); - hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaPi_tofPiP", "", {HistType::kTHnSparseF, {asCentrality, asPt, asEta, {200, -10., 10., "TPC #it{n}#it{#sigma}_{#pi}"}}}); - hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaPi_tofPiM", "", {HistType::kTHnSparseF, {asCentrality, asPt, asEta, {200, -10., 10., "TPC #it{n}#it{#sigma}_{#pi}"}}}); - hrQaPid.add("QaPid/hCentralityPtEtaTofNSigmaPi_tpcPiP", "", {HistType::kTHnSparseF, {asCentrality, asPt, asEta, {200, -10., 10., "TOF #it{n}#it{#sigma}_{#pi}"}}}); - hrQaPid.add("QaPid/hCentralityPtEtaTofNSigmaPi_tpcPiM", "", {HistType::kTHnSparseF, {asCentrality, asPt, asEta, {200, -10., 10., "TOF #it{n}#it{#sigma}_{#pi}"}}}); - hrQaPid.add("QaPid/hCentralityPtEtaTpcTofNSigmaPi_p", "", {HistType::kTHnSparseF, {asCentrality, asPt, asEta, {200, -10., 10., "TPC-TOF #it{n}#it{#sigma}_{#pi}"}}}); - hrQaPid.add("QaPid/hCentralityPtEtaTpcTofNSigmaPi_m", "", {HistType::kTHnSparseF, {asCentrality, asPt, asEta, {200, -10., 10., "TPC-TOF #it{n}#it{#sigma}_{#pi}"}}}); + hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaPi_p", ";;;;TPC #it{n}#it{#sigma}_{#pi};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaPi_m", ";;;;TPC #it{n}#it{#sigma}_{#pi};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaPi_tofPiP", ";;;;TPC #it{n}#it{#sigma}_{#pi};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaPi_tofPiM", ";;;;TPC #it{n}#it{#sigma}_{#pi};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTofNSigmaPi_tpcPiP", ";;;;TOF #it{n}#it{#sigma}_{#pi};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTofNSigmaPi_tpcPiM", ";;;;TOF #it{n}#it{#sigma}_{#pi};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTpcTofNSigmaPi_p", ";;;;TPC-TOF #it{n}#it{#sigma}_{#pi};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTpcTofNSigmaPi_m", ";;;;TPC-TOF #it{n}#it{#sigma}_{#pi};", hcsQaPid); } } @@ -1390,19 +1389,19 @@ struct PartNumFluc { LOG(info) << "Enabling kaon PID QA."; if (doprocessMc.value) { - hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaKa_mcKaP", "", {HistType::kTHnSparseF, {asCentrality, asPt, asEta, {200, -10., 10., "TPC #it{n}#it{#sigma}_{K}"}}}); - hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaKa_mcKaM", "", {HistType::kTHnSparseF, {asCentrality, asPt, asEta, {200, -10., 10., "TPC #it{n}#it{#sigma}_{K}"}}}); - hrQaPid.add("QaPid/hCentralityPtEtaTofNSigmaKa_mcKaP", "", {HistType::kTHnSparseF, {asCentrality, asPt, asEta, {200, -10., 10., "TOF #it{n}#it{#sigma}_{K}"}}}); - hrQaPid.add("QaPid/hCentralityPtEtaTofNSigmaKa_mcKaM", "", {HistType::kTHnSparseF, {asCentrality, asPt, asEta, {200, -10., 10., "TOF #it{n}#it{#sigma}_{K}"}}}); + hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaKa_mcKaP", ";;;;TPC #it{n}#it{#sigma}_{K};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaKa_mcKaM", ";;;;TPC #it{n}#it{#sigma}_{K};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTofNSigmaKa_mcKaP", ";;;;TOF #it{n}#it{#sigma}_{K};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTofNSigmaKa_mcKaM", ";;;;TOF #it{n}#it{#sigma}_{K};", hcsQaPid); } else if (doprocessRaw.value) { - hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaKa_p", "", {HistType::kTHnSparseF, {asCentrality, asPt, asEta, {200, -10., 10., "TPC #it{n}#it{#sigma}_{K}"}}}); - hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaKa_m", "", {HistType::kTHnSparseF, {asCentrality, asPt, asEta, {200, -10., 10., "TPC #it{n}#it{#sigma}_{K}"}}}); - hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaKa_tofKaP", "", {HistType::kTHnSparseF, {asCentrality, asPt, asEta, {200, -10., 10., "TPC #it{n}#it{#sigma}_{K}"}}}); - hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaKa_tofKaM", "", {HistType::kTHnSparseF, {asCentrality, asPt, asEta, {200, -10., 10., "TPC #it{n}#it{#sigma}_{K}"}}}); - hrQaPid.add("QaPid/hCentralityPtEtaTofNSigmaKa_tpcKaP", "", {HistType::kTHnSparseF, {asCentrality, asPt, asEta, {200, -10., 10., "TOF #it{n}#it{#sigma}_{K}"}}}); - hrQaPid.add("QaPid/hCentralityPtEtaTofNSigmaKa_tpcKaM", "", {HistType::kTHnSparseF, {asCentrality, asPt, asEta, {200, -10., 10., "TOF #it{n}#it{#sigma}_{K}"}}}); - hrQaPid.add("QaPid/hCentralityPtEtaTpcTofNSigmaKa_p", "", {HistType::kTHnSparseF, {asCentrality, asPt, asEta, {200, -10., 10., "TPC-TOF #it{n}#it{#sigma}_{K}"}}}); - hrQaPid.add("QaPid/hCentralityPtEtaTpcTofNSigmaKa_m", "", {HistType::kTHnSparseF, {asCentrality, asPt, asEta, {200, -10., 10., "TPC-TOF #it{n}#it{#sigma}_{K}"}}}); + hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaKa_p", ";;;;TPC #it{n}#it{#sigma}_{K};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaKa_m", ";;;;TPC #it{n}#it{#sigma}_{K};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaKa_tofKaP", ";;;;TPC #it{n}#it{#sigma}_{K};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaKa_tofKaM", ";;;;TPC #it{n}#it{#sigma}_{K};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTofNSigmaKa_tpcKaP", ";;;;TOF #it{n}#it{#sigma}_{K};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTofNSigmaKa_tpcKaM", ";;;;TOF #it{n}#it{#sigma}_{K};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTpcTofNSigmaKa_p", ";;;;TPC-TOF #it{n}#it{#sigma}_{K};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTpcTofNSigmaKa_m", ";;;;TPC-TOF #it{n}#it{#sigma}_{K};", hcsQaPid); } } @@ -1410,19 +1409,19 @@ struct PartNumFluc { LOG(info) << "Enabling (anti)proton PID QA."; if (doprocessMc.value) { - hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaPr_mcPrP", "", {HistType::kTHnSparseF, {asCentrality, asPt, asEta, {200, -10., 10., "TPC #it{n}#it{#sigma}_{p}"}}}); - hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaPr_mcPrM", "", {HistType::kTHnSparseF, {asCentrality, asPt, asEta, {200, -10., 10., "TPC #it{n}#it{#sigma}_{p}"}}}); - hrQaPid.add("QaPid/hCentralityPtEtaTofNSigmaPr_mcPrP", "", {HistType::kTHnSparseF, {asCentrality, asPt, asEta, {200, -10., 10., "TOF #it{n}#it{#sigma}_{p}"}}}); - hrQaPid.add("QaPid/hCentralityPtEtaTofNSigmaPr_mcPrM", "", {HistType::kTHnSparseF, {asCentrality, asPt, asEta, {200, -10., 10., "TOF #it{n}#it{#sigma}_{p}"}}}); + hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaPr_mcPrP", ";;;;TPC #it{n}#it{#sigma}_{p};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaPr_mcPrM", ";;;;TPC #it{n}#it{#sigma}_{p};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTofNSigmaPr_mcPrP", ";;;;TOF #it{n}#it{#sigma}_{p};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTofNSigmaPr_mcPrM", ";;;;TOF #it{n}#it{#sigma}_{p};", hcsQaPid); } else if (doprocessRaw.value) { - hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaPr_p", "", {HistType::kTHnSparseF, {asCentrality, asPt, asEta, {200, -10., 10., "TPC #it{n}#it{#sigma}_{p}"}}}); - hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaPr_m", "", {HistType::kTHnSparseF, {asCentrality, asPt, asEta, {200, -10., 10., "TPC #it{n}#it{#sigma}_{p}"}}}); - hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaPr_tofPrP", "", {HistType::kTHnSparseF, {asCentrality, asPt, asEta, {200, -10., 10., "TPC #it{n}#it{#sigma}_{p}"}}}); - hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaPr_tofPrM", "", {HistType::kTHnSparseF, {asCentrality, asPt, asEta, {200, -10., 10., "TPC #it{n}#it{#sigma}_{p}"}}}); - hrQaPid.add("QaPid/hCentralityPtEtaTofNSigmaPr_tpcPrP", "", {HistType::kTHnSparseF, {asCentrality, asPt, asEta, {200, -10., 10., "TOF #it{n}#it{#sigma}_{p}"}}}); - hrQaPid.add("QaPid/hCentralityPtEtaTofNSigmaPr_tpcPrM", "", {HistType::kTHnSparseF, {asCentrality, asPt, asEta, {200, -10., 10., "TOF #it{n}#it{#sigma}_{p}"}}}); - hrQaPid.add("QaPid/hCentralityPtEtaTpcTofNSigmaPr_p", "", {HistType::kTHnSparseF, {asCentrality, asPt, asEta, {200, -10., 10., "TPC-TOF #it{n}#it{#sigma}_{p}"}}}); - hrQaPid.add("QaPid/hCentralityPtEtaTpcTofNSigmaPr_m", "", {HistType::kTHnSparseF, {asCentrality, asPt, asEta, {200, -10., 10., "TPC-TOF #it{n}#it{#sigma}_{p}"}}}); + hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaPr_p", ";;;;TPC #it{n}#it{#sigma}_{p};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaPr_m", ";;;;TPC #it{n}#it{#sigma}_{p};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaPr_tofPrP", ";;;;TPC #it{n}#it{#sigma}_{p};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaPr_tofPrM", ";;;;TPC #it{n}#it{#sigma}_{p};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTofNSigmaPr_tpcPrP", ";;;;TOF #it{n}#it{#sigma}_{p};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTofNSigmaPr_tpcPrM", ";;;;TOF #it{n}#it{#sigma}_{p};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTpcTofNSigmaPr_p", ";;;;TPC-TOF #it{n}#it{#sigma}_{p};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTpcTofNSigmaPr_m", ";;;;TPC-TOF #it{n}#it{#sigma}_{p};", hcsQaPid); } } } @@ -1583,6 +1582,60 @@ struct PartNumFluc { const HistogramConfigSpec hcsCalculationFluctuation(HistType::kTHnSparseD, {asCentrality, {50, -0.5, 49.5}, {50, -0.5, 49.5}}); const HistogramConfigSpec hcsFluctuationCalculator(HistType::kTH3D, {asCentrality, {groupEvent.cfgNSubgroups.value, -0.5, groupEvent.cfgNSubgroups.value - 0.5, "Subgroup Index"}, {fluctuation_calculator_base::NOrderVectors, -0.5, fluctuation_calculator_base::NOrderVectors - 0.5, "Order Vector Index"}}); + if (groupAnalysis.cfgFlagCalculationFluctuationCh.value) { + LOG(info) << "Enabling charge number fluctuation calculation."; + + fluctuationCalculatorTrackChP = std::make_unique(); + fluctuationCalculatorTrackChM = std::make_unique(); + fluctuationCalculatorTrackChT = std::make_unique(); + fluctuationCalculatorTrackChN = std::make_unique(); + + if (doprocessMc.value) { + hrCalculationFluctuation.add("CalculationFluctuation/hCentralityNChPNChM_mc", ";;#it{N}(h^{+});#it{N}(h^{#minus});", hcsCalculationFluctuation); + } + hrCalculationFluctuation.add("CalculationFluctuation/hCentralityNChPNChM", ";;#it{N}(h^{+});#it{N}(h^{#minus});", hcsCalculationFluctuation); + hrCalculationFluctuation.add("CalculationFluctuation/hFluctuationCalculatorChP", "", hcsFluctuationCalculator); + hrCalculationFluctuation.add("CalculationFluctuation/hFluctuationCalculatorChM", "", hcsFluctuationCalculator); + hrCalculationFluctuation.add("CalculationFluctuation/hFluctuationCalculatorChT", "", hcsFluctuationCalculator); + hrCalculationFluctuation.add("CalculationFluctuation/hFluctuationCalculatorChN", "", hcsFluctuationCalculator); + } + + if (groupAnalysis.cfgFlagCalculationFluctuationKa.value) { + LOG(info) << "Enabling kaon number fluctuation calculation."; + + fluctuationCalculatorTrackKaP = std::make_unique(); + fluctuationCalculatorTrackKaM = std::make_unique(); + fluctuationCalculatorTrackKaT = std::make_unique(); + fluctuationCalculatorTrackKaN = std::make_unique(); + + if (doprocessMc.value) { + hrCalculationFluctuation.add("CalculationFluctuation/hCentralityNKaPNKaM_mc", ";;#it{N}(K^{+});#it{N}(K^{#minus});", hcsCalculationFluctuation); + } + hrCalculationFluctuation.add("CalculationFluctuation/hCentralityNKaPNKaM", ";;#it{N}(K^{+});#it{N}(K^{#minus});", hcsCalculationFluctuation); + hrCalculationFluctuation.add("CalculationFluctuation/hFluctuationCalculatorKaP", "", hcsFluctuationCalculator); + hrCalculationFluctuation.add("CalculationFluctuation/hFluctuationCalculatorKaM", "", hcsFluctuationCalculator); + hrCalculationFluctuation.add("CalculationFluctuation/hFluctuationCalculatorKaT", "", hcsFluctuationCalculator); + hrCalculationFluctuation.add("CalculationFluctuation/hFluctuationCalculatorKaN", "", hcsFluctuationCalculator); + } + + if (groupAnalysis.cfgFlagCalculationFluctuationPr.value) { + LOG(info) << "Enabling (anti)proton number fluctuation calculation."; + + fluctuationCalculatorTrackPrP = std::make_unique(); + fluctuationCalculatorTrackPrM = std::make_unique(); + fluctuationCalculatorTrackPrT = std::make_unique(); + fluctuationCalculatorTrackPrN = std::make_unique(); + + if (doprocessMc.value) { + hrCalculationFluctuation.add("CalculationFluctuation/hCentralityNPrPNPrM_mc", ";;#it{N}(p);#it{N}(#bar{p});", hcsCalculationFluctuation); + } + hrCalculationFluctuation.add("CalculationFluctuation/hCentralityNPrPNPrM", ";;#it{N}(p);#it{N}(#bar{p});", hcsCalculationFluctuation); + hrCalculationFluctuation.add("CalculationFluctuation/hFluctuationCalculatorPrP", "", hcsFluctuationCalculator); + hrCalculationFluctuation.add("CalculationFluctuation/hFluctuationCalculatorPrM", "", hcsFluctuationCalculator); + hrCalculationFluctuation.add("CalculationFluctuation/hFluctuationCalculatorPrT", "", hcsFluctuationCalculator); + hrCalculationFluctuation.add("CalculationFluctuation/hFluctuationCalculatorPrN", "", hcsFluctuationCalculator); + } + if (groupAnalysis.cfgFlagCalculationFluctuationCh.value) { holderCcdb.hVzCentralityPtEtaEfficiencyTpcPiP.resize(nRunGroups); holderCcdb.hVzCentralityPtEtaEfficiencyTpcPiM.resize(nRunGroups); @@ -1681,60 +1734,6 @@ struct PartNumFluc { LOG(info) << "Reading from CCDB: " << holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofPrM[iRunGroup]->GetName(); } } - - if (groupAnalysis.cfgFlagCalculationFluctuationCh.value) { - LOG(info) << "Enabling charge number fluctuation calculation."; - - fluctuationCalculatorTrackChP = std::make_unique(); - fluctuationCalculatorTrackChM = std::make_unique(); - fluctuationCalculatorTrackChT = std::make_unique(); - fluctuationCalculatorTrackChN = std::make_unique(); - - if (doprocessMc.value) { - hrCalculationFluctuation.add("CalculationFluctuation/hCentralityNChPNChM_mc", ";;#it{N}(h^{+});#it{N}(h^{#minus})", hcsCalculationFluctuation); - } - hrCalculationFluctuation.add("CalculationFluctuation/hCentralityNChPNChM", ";;#it{N}(h^{+});#it{N}(h^{#minus})", hcsCalculationFluctuation); - hrCalculationFluctuation.add("CalculationFluctuation/hFluctuationCalculatorChP", "", hcsFluctuationCalculator); - hrCalculationFluctuation.add("CalculationFluctuation/hFluctuationCalculatorChM", "", hcsFluctuationCalculator); - hrCalculationFluctuation.add("CalculationFluctuation/hFluctuationCalculatorChT", "", hcsFluctuationCalculator); - hrCalculationFluctuation.add("CalculationFluctuation/hFluctuationCalculatorChN", "", hcsFluctuationCalculator); - } - - if (groupAnalysis.cfgFlagCalculationFluctuationKa.value) { - LOG(info) << "Enabling kaon number fluctuation calculation."; - - fluctuationCalculatorTrackKaP = std::make_unique(); - fluctuationCalculatorTrackKaM = std::make_unique(); - fluctuationCalculatorTrackKaT = std::make_unique(); - fluctuationCalculatorTrackKaN = std::make_unique(); - - if (doprocessMc.value) { - hrCalculationFluctuation.add("CalculationFluctuation/hCentralityNKaPNKaM_mc", ";;#it{N}(K^{+});#it{N}(K^{#minus})", hcsCalculationFluctuation); - } - hrCalculationFluctuation.add("CalculationFluctuation/hCentralityNKaPNKaM", ";;#it{N}(K^{+});#it{N}(K^{#minus})", hcsCalculationFluctuation); - hrCalculationFluctuation.add("CalculationFluctuation/hFluctuationCalculatorKaP", "", hcsFluctuationCalculator); - hrCalculationFluctuation.add("CalculationFluctuation/hFluctuationCalculatorKaM", "", hcsFluctuationCalculator); - hrCalculationFluctuation.add("CalculationFluctuation/hFluctuationCalculatorKaT", "", hcsFluctuationCalculator); - hrCalculationFluctuation.add("CalculationFluctuation/hFluctuationCalculatorKaN", "", hcsFluctuationCalculator); - } - - if (groupAnalysis.cfgFlagCalculationFluctuationPr.value) { - LOG(info) << "Enabling (anti)proton number fluctuation calculation."; - - fluctuationCalculatorTrackPrP = std::make_unique(); - fluctuationCalculatorTrackPrM = std::make_unique(); - fluctuationCalculatorTrackPrT = std::make_unique(); - fluctuationCalculatorTrackPrN = std::make_unique(); - - if (doprocessMc.value) { - hrCalculationFluctuation.add("CalculationFluctuation/hCentralityNPrPNPrM_mc", ";;#it{N}(p);#it{N}(#bar{p})", hcsCalculationFluctuation); - } - hrCalculationFluctuation.add("CalculationFluctuation/hCentralityNPrPNPrM", ";;#it{N}(p);#it{N}(#bar{p})", hcsCalculationFluctuation); - hrCalculationFluctuation.add("CalculationFluctuation/hFluctuationCalculatorPrP", "", hcsFluctuationCalculator); - hrCalculationFluctuation.add("CalculationFluctuation/hFluctuationCalculatorPrM", "", hcsFluctuationCalculator); - hrCalculationFluctuation.add("CalculationFluctuation/hFluctuationCalculatorPrT", "", hcsFluctuationCalculator); - hrCalculationFluctuation.add("CalculationFluctuation/hFluctuationCalculatorPrN", "", hcsFluctuationCalculator); - } } } @@ -1784,16 +1783,16 @@ struct PartNumFluc { } static const std::array*, 2>, 2>, static_cast(ParticleSpecies::kNSpecies)> pointersVectorHistogramShiftNSigmaPid = {{{{{&holderCcdb.hCentralityPtEtaShiftTpcNSigmaPiP, &holderCcdb.hCentralityPtEtaShiftTofNSigmaPiP}, {&holderCcdb.hCentralityPtEtaShiftTpcNSigmaPiM, &holderCcdb.hCentralityPtEtaShiftTofNSigmaPiM}}}, {{{&holderCcdb.hCentralityPtEtaShiftTpcNSigmaKaP, &holderCcdb.hCentralityPtEtaShiftTofNSigmaKaP}, {&holderCcdb.hCentralityPtEtaShiftTpcNSigmaKaM, &holderCcdb.hCentralityPtEtaShiftTofNSigmaKaM}}}, {{{&holderCcdb.hCentralityPtEtaShiftTpcNSigmaPrP, &holderCcdb.hCentralityPtEtaShiftTofNSigmaPrP}, {&holderCcdb.hCentralityPtEtaShiftTpcNSigmaPrM, &holderCcdb.hCentralityPtEtaShiftTofNSigmaPrM}}}}}; + static const auto clampInAxis = [](const double value, const TAxis* const axis) { + const std::int32_t first = std::clamp(axis->GetFirst(), 1, axis->GetNbins()); + const std::int32_t last = std::clamp(axis->GetLast(), 1, axis->GetNbins()); + return first == last ? axis->GetBinCenter(first) : std::clamp(value, std::nextafter(axis->GetBinCenter(first), std::numeric_limits::infinity()), std::nextafter(axis->GetBinCenter(last), -std::numeric_limits::infinity())); + }; if (holderTrack.sign == 0) { return 0.; } const TH3* const hCentralityPtEtaShiftNSigmaPid = pointersVectorHistogramShiftNSigmaPid[static_cast(particleSpecies)][holderTrack.sign > 0 ? 0 : 1][pidStrategy == PidStrategy::kTpc ? 0 : 1]->at(std::abs(holderEvent.runGroupIndex) - 1); - auto clampInAxis = [](const double value, const TAxis* const axis) { - const std::int32_t first = std::clamp(axis->GetFirst(), 1, axis->GetNbins()); - const std::int32_t last = std::clamp(axis->GetLast(), 1, axis->GetNbins()); - return first == last ? axis->GetBinCenter(first) : std::clamp(value, std::nextafter(axis->GetBinCenter(first), std::numeric_limits::infinity()), std::nextafter(axis->GetBinCenter(last), -std::numeric_limits::infinity())); - }; return hCentralityPtEtaShiftNSigmaPid ? hCentralityPtEtaShiftNSigmaPid->Interpolate(clampInAxis(holderEvent.centrality, hCentralityPtEtaShiftNSigmaPid->GetXaxis()), clampInAxis(holderTrack.pt, hCentralityPtEtaShiftNSigmaPid->GetYaxis()), clampInAxis(holderTrack.eta, hCentralityPtEtaShiftNSigmaPid->GetZaxis())) : 0.; } From 1d68c54c9e0c62793b0f418ecf80e9c5395714d5 Mon Sep 17 00:00:00 2001 From: ldellost <47105254+DelloStritto@users.noreply.github.com> Date: Fri, 13 Mar 2026 09:27:26 +0100 Subject: [PATCH 273/347] [PWGHF] Add V0 decay length to ML variables for LcK0sP (#15367) Co-authored-by: Luigi Dello Stritto --- PWGHF/Core/HfMlResponseLcToK0sP.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/PWGHF/Core/HfMlResponseLcToK0sP.h b/PWGHF/Core/HfMlResponseLcToK0sP.h index 4e6899bf3aa..1d90b015008 100644 --- a/PWGHF/Core/HfMlResponseLcToK0sP.h +++ b/PWGHF/Core/HfMlResponseLcToK0sP.h @@ -82,6 +82,7 @@ enum class InputFeaturesLcToK0sP : uint8_t { v0MK0Short, v0MGamma, ctV0, + decayLengthV0, dcaV0daughters, ptV0Pos, dcaPosToPV, @@ -136,6 +137,7 @@ class HfMlResponseLcToK0sP : public HfMlResponse CHECK_AND_FILL_VEC_LC_FULL(candidate, v0MGamma, mGamma); CHECK_AND_FILL_VEC_LC_HFHELPER(candidate, ctV0, ctV0K0s); // CHECK_AND_FILL_VEC_LC_HFHELPER(candidate, ctV0, ctV0Lambda); + CHECK_AND_FILL_VEC_LC(decayLengthV0); CHECK_AND_FILL_VEC_LC(dcaV0daughters); CHECK_AND_FILL_VEC_LC(ptV0Pos); CHECK_AND_FILL_VEC_LC_FULL(candidate, dcaPosToPV, dcapostopv); @@ -180,6 +182,7 @@ class HfMlResponseLcToK0sP : public HfMlResponse FILL_MAP_LC(v0MK0Short), FILL_MAP_LC(v0MGamma), FILL_MAP_LC(ctV0), + FILL_MAP_LC(decayLengthV0), FILL_MAP_LC(dcaV0daughters), FILL_MAP_LC(ptV0Pos), FILL_MAP_LC(dcaPosToPV), From 80dff7be7ad300db88a1ad7fe6d53f054d851c41 Mon Sep 17 00:00:00 2001 From: Junlee Kim Date: Fri, 13 Mar 2026 17:40:05 +0800 Subject: [PATCH 274/347] [PWGCF] adding q2 plots and switch for track selection (#15338) --- PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx b/PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx index 2853dd5d089..5a85b8eb58e 100644 --- a/PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx +++ b/PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx @@ -76,6 +76,7 @@ struct jEPFlowAnalysis { Configurable cfgEffCor{"cfgEffCor", false, "flag for efficiency correction"}; Configurable cfgEffCorDir{"cfgEffCorDir", "Users/n/nmallick/Run3OO/Eff/LHC25h3b_FT0C", "path for efficiency correction"}; + Configurable cfgTrkSelFlag{"cfgTrkSelFlag", true, "flag for track selection"}; Configurable cfgSystStudy{"cfgSystStudy", false, "flag for syst study"}; Configurable cfgITSNCls{"cfgITSNCls", 5, "minimum number of its clusters"}; Configurable cfgTPCNclsCR{"cfgTPCNclsCR", 70, "minimum number of tpc cluster crossed rows"}; @@ -278,7 +279,7 @@ struct jEPFlowAnalysis { epFlowHistograms.fill(HIST("EpResQvecRefARefBxy"), i + 2, cent, qx_shifted[2] * qy_shifted[1] - qx_shifted[1] * qy_shifted[2]); for (const auto& track : tracks) { - if (trackSel(track)) + if (cfgTrkSelFlag && trackSel(track)) continue; if (cfgEffCor) { From 4ebf60b341d9949ca7667efca566be9be8fdc87c Mon Sep 17 00:00:00 2001 From: somabhatta <48771326+somabhatta@users.noreply.github.com> Date: Fri, 13 Mar 2026 20:50:19 +0100 Subject: [PATCH 275/347] [PWGCF] Update evt and trk selection logic for rad decorr (#15395) --- .../Tasks/radialFlowDecorr.cxx | 1219 ++++++++--------- 1 file changed, 582 insertions(+), 637 deletions(-) diff --git a/PWGCF/EbyEFluctuations/Tasks/radialFlowDecorr.cxx b/PWGCF/EbyEFluctuations/Tasks/radialFlowDecorr.cxx index b052893881e..36fd6cd2254 100644 --- a/PWGCF/EbyEFluctuations/Tasks/radialFlowDecorr.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/radialFlowDecorr.cxx @@ -202,9 +202,10 @@ struct RadialFlowDecorr { Configurable cfgPupnSig{"cfgPupnSig", 3.0f, "Additional Pileup Cut"}; Configurable cfgApplySigPupCut{"cfgApplySigPupCut", 0, "nSig Pileup Cut"}; Configurable cfgApplyLinPupCut{"cfgApplyLinPupCut", 0, "Lin Pileup Cut"}; - - Configurable cfgLinPupParam0{"cfgLinPupParam0", 3.0f, "Linear Pileup Cut Const"}; - Configurable cfgLinPupParam1{"cfgLinPupParam1", 3.0f, "Linear Pileup Slope"}; + Configurable cfgLinPupParam0{"cfgLinPupParam0", 3.0f, "(Upper) Linear Pileup Cut Const"}; + Configurable cfgLinPupParam1{"cfgLinPupParam1", 3.0f, "(Upper) Linear Pileup Slope"}; + Configurable cfgLinPupParam2{"cfgLinPupParam2", 3.0f, "(Lower) Linear Pileup Cut Const"}; + Configurable cfgLinPupParam3{"cfgLinPupParam3", 3.0f, "(Lower) Linear Pileup Slope"}; Configurable cfgNchPbMax{"cfgNchPbMax", 10000, "Max Nch range for PbPb collisions"}; Configurable cfgNchOMax{"cfgNchOMax", 1000, "Max Nch range for OO collisions"}; @@ -549,9 +550,11 @@ struct RadialFlowDecorr { if (cfgApplyLinPupCut) { if (trksize > (cfgLinPupParam0 + cfgLinPupParam1 * multPV)) return false; + histos.fill(HIST("hEvtCount"), 7.5); + if (trksize < (cfgLinPupParam2 + cfgLinPupParam3 * multPV)) + return false; + histos.fill(HIST("hEvtCount"), 8.5); } - histos.fill(HIST("hEvtCount"), 7.5); - return true; } @@ -797,17 +800,7 @@ struct RadialFlowDecorr { aod::CentFT0Cs, aod::CentFT0Ms, aod::CentFDDMs, aod::CentFV0As, aod::CentNGlobals, aod::McCollisionLabels>; - using MyMCTracks = soa::Join< - aod::Tracks, aod::TrackSelection, aod::TracksExtra, aod::TracksDCA, - aod::McTrackLabels, - aod::pidTPCFullPi, aod::pidTPCFullKa, aod::pidTPCFullPr, aod::pidTPCFullEl, - aod::pidTOFFullPi, aod::pidTOFFullKa, aod::pidTOFFullPr, aod::pidTOFFullEl>; - - PresliceUnsorted partPerMcCollision = aod::mcparticle::mcCollisionId; PresliceUnsorted colPerMcCollision = aod::mccollisionlabel::mcCollisionId; - PresliceUnsorted trackPerMcParticle = aod::mctracklabel::mcParticleId; - Preslice perCollision = aod::track::collisionId; - Preslice trackPerCollision = aod::track::collisionId; void declareCommonQA() { @@ -816,6 +809,10 @@ struct RadialFlowDecorr { histos.add("hCentrality", ";centrality (%)", kTH1F, {{centAxis1Per}}); histos.add("Hist2D_globalTracks_PVTracks", ";N_{global};N_{PV}", kTH2F, {{nChAxis}, {nChAxis}}); histos.add("Hist2D_cent_nch", ";N_{PV};cent (%)", kTH2F, {{nChAxis}, {centAxis1Per}}); + + histos.add("Hist2D_globalTracks_cent", "cent (%);N_{global}", kTH2F, {{centAxis1Per}, {nChAxis}}); + histos.add("Hist2D_PVTracks_cent", "cent (%);N_{PV}", kTH2F, {{centAxis1Per}, {nChAxis}}); + histos.add("hP", ";p (GeV/c)", kTH1F, {{KNbinsPt, KPMin, KPMax}}); histos.add("hPt", ";p_{T} (GeV/c)", kTH1F, {{KNbinsPt, KPtMin, KPtMax}}); histos.add("hEta", ";#eta", kTH1F, {{KNbinsEtaFine, KEtaMin, KEtaMax}}); @@ -829,7 +826,8 @@ struct RadialFlowDecorr { histos.get(HIST("hEvtCount"))->GetXaxis()->SetBinLabel(5, "after kIsGoodZvtxFT0vsPV"); histos.get(HIST("hEvtCount"))->GetXaxis()->SetBinLabel(6, "after kIsGoodITSLayersAll"); histos.get(HIST("hEvtCount"))->GetXaxis()->SetBinLabel(7, "after PVTracksCent Pileup Cut"); - histos.get(HIST("hEvtCount"))->GetXaxis()->SetBinLabel(8, "after Linear Pileup Cut"); + histos.get(HIST("hEvtCount"))->GetXaxis()->SetBinLabel(8, "after Linear Pileup Cut (Up)"); + histos.get(HIST("hEvtCount"))->GetXaxis()->SetBinLabel(9, "after Linear Pileup Cut (Lw)"); histos.add("hTrkCount", "Number of Tracks;; Count", kTH1F, {{11, 0, 11}}); histos.get(HIST("hTrkCount"))->GetXaxis()->SetBinLabel(1, "all Tracks"); @@ -1436,303 +1434,279 @@ struct RadialFlowDecorr { LOGF(info, "CCDB initialization complete for RadialFlowDecorr."); } - void processMCGetMeanNsig(aod::McCollisions const& mcColl, MyRun3MCCollisions const& collisions, TCs const& tracks, FilteredTCs const& /*filteredTracks*/, aod::McParticles const& mcParticles) + void processMCGetMeanNsig(MyRun3MCCollisions::iterator const& mcCollision, FilteredTCs const& mcTracks) { - for (const auto& mcCollision : mcColl) { - auto colSlice = collisions.sliceBy(colPerMcCollision, mcCollision.globalIndex()); - if (colSlice.size() != 1) - continue; - for (const auto& col : colSlice) { - histos.fill(HIST("hVtxZ"), col.posZ()); - if (!col.has_mcCollision() || !isEventSelected(col)) - continue; - auto trackSlice = tracks.sliceBy(trackPerCollision, col.globalIndex()); - auto partSlice = mcParticles.sliceBy(partPerMcCollision, mcCollision.globalIndex()); - if (trackSlice.size() < 1 || partSlice.size() < 1) - continue; - float cent = getCentrality(col); - if (cent > KCentMax) - continue; - float multPV = col.multNTracksPV(); + histos.fill(HIST("hVtxZ"), mcCollision.posZ()); + if (!mcCollision.has_mcCollision() || !isEventSelected(mcCollision)) + return; + float cent = getCentrality(mcCollision); + if (cent > KCentMax) + return; + float multPV = mcCollision.multNTracksPV(); - histos.fill(HIST("hVtxZ_after_sel"), col.posZ()); - histos.fill(HIST("hCentrality"), cent); + histos.fill(HIST("hVtxZ_after_sel"), mcCollision.posZ()); + histos.fill(HIST("hCentrality"), cent); + histos.fill(HIST("Hist2D_globalTracks_PVTracks"), multPV, mcTracks.size()); + histos.fill(HIST("Hist2D_cent_nch"), mcTracks.size(), cent); + histos.fill(HIST("Hist2D_globalTracks_cent"), cent, mcTracks.size()); + histos.fill(HIST("Hist2D_PVTracks_cent"), cent, multPV); - histos.fill(HIST("Hist2D_globalTracks_PVTracks"), multPV, trackSlice.size()); - histos.fill(HIST("Hist2D_cent_nch"), trackSlice.size(), cent); - for (const auto& track : trackSlice) { - if (!isTrackSelected(track)) - continue; - fillNSigmaBefCut(track, cent); - } - } + for (const auto& track : mcTracks) { + if (!isTrackSelected(track)) + continue; + fillNSigmaBefCut(track, cent); } } PROCESS_SWITCH(RadialFlowDecorr, processMCGetMeanNsig, "process MC to calculate Mean values of nSig Plots", cfgRunMCGetNSig); - void processGetEffHists(aod::McCollisions const& mcColl, MyRun3MCCollisions const& collisions, TCs const& tracks, FilteredTCs const& /*filteredTracks*/, aod::McParticles const& mcParticles) + void processGetEffHists(MyRun3MCCollisions::iterator const& mcCollision, FilteredTCs const& mcTracks, aod::McParticles const& mcParticles) { - for (const auto& mcCollision : mcColl) { - auto colSlice = collisions.sliceBy(colPerMcCollision, mcCollision.globalIndex()); - if (colSlice.size() != 1) - continue; - - for (const auto& col : colSlice) { - histos.fill(HIST("hVtxZ"), col.posZ()); - if (!col.has_mcCollision() || !isEventSelected(col)) - continue; - - auto trackSlice = tracks.sliceBy(trackPerCollision, col.globalIndex()); - auto partSlice = mcParticles.sliceBy(partPerMcCollision, mcCollision.globalIndex()); - if (trackSlice.size() < 1 || partSlice.size() < 1) - continue; - - float cent = getCentrality(col); - - if (cent > KCentMax) - continue; - float multPV = col.multNTracksPV(); - float vz = col.posZ(); - - if (!isPassAddPileup(multPV, trackSlice.size(), cent)) - continue; - - histos.fill(HIST("hVtxZ_after_sel"), col.posZ()); - histos.fill(HIST("hCentrality"), cent); - - histos.fill(HIST("Hist2D_globalTracks_PVTracks"), multPV, trackSlice.size()); - histos.fill(HIST("Hist2D_cent_nch"), trackSlice.size(), cent); + histos.fill(HIST("hVtxZ"), mcCollision.posZ()); + if (!mcCollision.has_mcCollision() || !isEventSelected(mcCollision)) + return; + float cent = getCentrality(mcCollision); + if (cent > KCentMax) + return; + float multPV = mcCollision.multNTracksPV(); + float vz = mcCollision.posZ(); + if (!isPassAddPileup(multPV, mcTracks.size(), cent)) + return; + histos.fill(HIST("hVtxZ_after_sel"), mcCollision.posZ()); + histos.fill(HIST("hCentrality"), cent); - for (const auto& particle : partSlice) { - if (!isParticleSelected(particle) || !particle.isPhysicalPrimary()) - continue; + histos.fill(HIST("Hist2D_globalTracks_PVTracks"), multPV, mcTracks.size()); + histos.fill(HIST("Hist2D_cent_nch"), mcTracks.size(), cent); + histos.fill(HIST("Hist2D_globalTracks_cent"), cent, mcTracks.size()); + histos.fill(HIST("Hist2D_PVTracks_cent"), cent, multPV); - const int pdg = particle.pdgCode(); - const int absPdg = std::abs(pdg); - float pt = particle.pt(), eta = particle.eta(); + for (const auto& particle : mcParticles) { + if (!isParticleSelected(particle) || !particle.isPhysicalPrimary()) + continue; - bool isSpecies[KNsp] = { - true, // kInclusiveIdx - pdg == -KPiPlus, // kPiMinusIdx - pdg == KPiPlus, // kPiPlusIdx - absPdg == KPiPlus, // kPiAllIdx - pdg == -KKPlus, // kKaMinusIdx - pdg == KKPlus, // kKaPlusIdx - absPdg == KKPlus, // kKaAllIdx - pdg == -KProton, // kAntiPrIdx - pdg == KProton, // kPrIdx - absPdg == KProton // kPrAllIdx - }; + const int pdg = particle.pdgCode(); + const int absPdg = std::abs(pdg); + float pt = particle.pt(), eta = particle.eta(); - histos.fill(HIST("h3_AllPrimary"), multPV, pt, eta); - if (isSpecies[kPiMinusIdx]) - histos.fill(HIST("h3_AllPrimary_PiMinus"), multPV, pt, eta); - else if (isSpecies[kPiPlusIdx]) - histos.fill(HIST("h3_AllPrimary_PiPlus"), multPV, pt, eta); - if (isSpecies[kPiAllIdx]) - histos.fill(HIST("h3_AllPrimary_PiAll"), multPV, pt, eta); - - if (isSpecies[kKaMinusIdx]) - histos.fill(HIST("h3_AllPrimary_KaMinus"), multPV, pt, eta); - else if (isSpecies[kKaPlusIdx]) - histos.fill(HIST("h3_AllPrimary_KaPlus"), multPV, pt, eta); - if (isSpecies[kKaAllIdx]) - histos.fill(HIST("h3_AllPrimary_KaAll"), multPV, pt, eta); - - if (isSpecies[kAntiPrIdx]) - histos.fill(HIST("h3_AllPrimary_AntiPr"), multPV, pt, eta); - else if (isSpecies[kPrIdx]) - histos.fill(HIST("h3_AllPrimary_Pr"), multPV, pt, eta); - if (isSpecies[kPrAllIdx]) - histos.fill(HIST("h3_AllPrimary_PrAll"), multPV, pt, eta); - } + bool isSpecies[KNsp] = { + true, // kInclusiveIdx + pdg == -KPiPlus, // kPiMinusIdx + pdg == KPiPlus, // kPiPlusIdx + absPdg == KPiPlus, // kPiAllIdx + pdg == -KKPlus, // kKaMinusIdx + pdg == KKPlus, // kKaPlusIdx + absPdg == KKPlus, // kKaAllIdx + pdg == -KProton, // kAntiPrIdx + pdg == KProton, // kPrIdx + absPdg == KProton // kPrAllIdx + }; - for (const auto& track : trackSlice) { - if (!isTrackSelected(track)) - continue; + histos.fill(HIST("h3_AllPrimary"), multPV, pt, eta); + if (isSpecies[kPiMinusIdx]) + histos.fill(HIST("h3_AllPrimary_PiMinus"), multPV, pt, eta); + else if (isSpecies[kPiPlusIdx]) + histos.fill(HIST("h3_AllPrimary_PiPlus"), multPV, pt, eta); + if (isSpecies[kPiAllIdx]) + histos.fill(HIST("h3_AllPrimary_PiAll"), multPV, pt, eta); + + if (isSpecies[kKaMinusIdx]) + histos.fill(HIST("h3_AllPrimary_KaMinus"), multPV, pt, eta); + else if (isSpecies[kKaPlusIdx]) + histos.fill(HIST("h3_AllPrimary_KaPlus"), multPV, pt, eta); + if (isSpecies[kKaAllIdx]) + histos.fill(HIST("h3_AllPrimary_KaAll"), multPV, pt, eta); + + if (isSpecies[kAntiPrIdx]) + histos.fill(HIST("h3_AllPrimary_AntiPr"), multPV, pt, eta); + else if (isSpecies[kPrIdx]) + histos.fill(HIST("h3_AllPrimary_Pr"), multPV, pt, eta); + if (isSpecies[kPrAllIdx]) + histos.fill(HIST("h3_AllPrimary_PrAll"), multPV, pt, eta); + } + + for (const auto& track : mcTracks) { + if (!isTrackSelected(track)) + continue; - float pt = track.pt(), eta = track.eta(); - auto sign = track.sign(); - fillNSigmaBefCut(track, cent); + float pt = track.pt(), eta = track.eta(); + auto sign = track.sign(); + fillNSigmaBefCut(track, cent); - int id = identifyTrack(track, cent); - bool isPi = (id == KPidPionOne); - bool isKa = (id == KPidKaonTwo); - bool isPr = (id == KPidProtonThree); - bool isSpecies[KNsp] = { - true, - isPi && sign < 0, isPi && sign > 0, isPi, - isKa && sign < 0, isKa && sign > 0, isKa, - isPr && sign < 0, isPr && sign > 0, isPr}; + int id = identifyTrack(track, cent); + bool isPi = (id == KPidPionOne); + bool isKa = (id == KPidKaonTwo); + bool isPr = (id == KPidProtonThree); + bool isSpecies[KNsp] = { + true, + isPi && sign < 0, isPi && sign > 0, isPi, + isKa && sign < 0, isKa && sign > 0, isKa, + isPr && sign < 0, isPr && sign > 0, isPr}; - fillNSigmaAftCut(track, cent, isSpecies); + fillNSigmaAftCut(track, cent, isSpecies); - for (int isp = 0; isp < KNsp; ++isp) { - if (!isSpecies[isp]) - continue; + for (int isp = 0; isp < KNsp; ++isp) { + if (!isSpecies[isp]) + continue; - if (isp == kInclusiveIdx) { - histos.fill(HIST("h3_AllReco"), multPV, pt, eta); - if (track.has_mcParticle()) { - auto mcP = track.mcParticle(); - if (mcP.isPhysicalPrimary()) { - histos.fill(HIST("ptResolution"), mcP.pt(), (pt - mcP.pt()) / mcP.pt()); - histos.fill(HIST("etaResolution"), mcP.eta(), eta - mcP.eta()); - histos.fill(HIST("etaTruthReco"), mcP.eta(), eta); - histos.fill(HIST("vzResolution"), mcP.vz(), (vz - mcP.vz()) / mcP.vz()); - histos.fill(HIST("TruthTracKVz"), mcP.vz(), vz); - histos.fill(HIST("h3_RecoMatchedToPrimary"), multPV, mcP.pt(), mcP.eta()); - } else { - histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary"), multPV, pt, eta); - } - } else { - histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake"), multPV, pt, eta); - } - } else if (isp == kPiMinusIdx) { - histos.fill(HIST("h3_AllReco_PiMinus"), multPV, pt, eta); - if (track.has_mcParticle()) { - auto mcP = track.mcParticle(); - if (mcP.isPhysicalPrimary()) { - if (mcP.pdgCode() == -KPiPlus) { - histos.fill(HIST("h3_RecoMatchedToPrimary_PiMinus"), multPV, mcP.pt(), mcP.eta()); - } else { // Misidentified - histos.fill(HIST("h3_RecoMatchedToPrimary_MisID_PiMinus"), multPV, pt, eta); - } - } else { - histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_PiMinus"), multPV, pt, eta); - } - } else { // No MC - histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_PiMinus"), multPV, pt, eta); + if (isp == kInclusiveIdx) { + histos.fill(HIST("h3_AllReco"), multPV, pt, eta); + if (track.has_mcParticle()) { + auto mcP = track.mcParticle(); + if (mcP.isPhysicalPrimary()) { + histos.fill(HIST("ptResolution"), mcP.pt(), (pt - mcP.pt()) / mcP.pt()); + histos.fill(HIST("etaResolution"), mcP.eta(), eta - mcP.eta()); + histos.fill(HIST("etaTruthReco"), mcP.eta(), eta); + histos.fill(HIST("vzResolution"), mcP.vz(), (vz - mcP.vz()) / mcP.vz()); + histos.fill(HIST("TruthTracKVz"), mcP.vz(), vz); + histos.fill(HIST("h3_RecoMatchedToPrimary"), multPV, mcP.pt(), mcP.eta()); + } else { + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary"), multPV, pt, eta); + } + } else { + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake"), multPV, pt, eta); + } + } else if (isp == kPiMinusIdx) { + histos.fill(HIST("h3_AllReco_PiMinus"), multPV, pt, eta); + if (track.has_mcParticle()) { + auto mcP = track.mcParticle(); + if (mcP.isPhysicalPrimary()) { + if (mcP.pdgCode() == -KPiPlus) { + histos.fill(HIST("h3_RecoMatchedToPrimary_PiMinus"), multPV, mcP.pt(), mcP.eta()); + } else { // Misidentified + histos.fill(HIST("h3_RecoMatchedToPrimary_MisID_PiMinus"), multPV, pt, eta); } - } else if (isp == kPiPlusIdx) { - histos.fill(HIST("h3_AllReco_PiPlus"), multPV, pt, eta); - if (track.has_mcParticle()) { - auto mcP = track.mcParticle(); - if (mcP.isPhysicalPrimary()) { - if (mcP.pdgCode() == KPiPlus) { - histos.fill(HIST("h3_RecoMatchedToPrimary_PiPlus"), multPV, mcP.pt(), mcP.eta()); - } else { // Misidentified - histos.fill(HIST("h3_RecoMatchedToPrimary_MisID_PiPlus"), multPV, pt, eta); - } - } else { - histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_PiPlus"), multPV, pt, eta); - } - } else { - histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_PiPlus"), multPV, pt, eta); + } else { + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_PiMinus"), multPV, pt, eta); + } + } else { // No MC + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_PiMinus"), multPV, pt, eta); + } + } else if (isp == kPiPlusIdx) { + histos.fill(HIST("h3_AllReco_PiPlus"), multPV, pt, eta); + if (track.has_mcParticle()) { + auto mcP = track.mcParticle(); + if (mcP.isPhysicalPrimary()) { + if (mcP.pdgCode() == KPiPlus) { + histos.fill(HIST("h3_RecoMatchedToPrimary_PiPlus"), multPV, mcP.pt(), mcP.eta()); + } else { // Misidentified + histos.fill(HIST("h3_RecoMatchedToPrimary_MisID_PiPlus"), multPV, pt, eta); } - } else if (isp == kPiAllIdx) { - histos.fill(HIST("h3_AllReco_PiAll"), multPV, pt, eta); - if (track.has_mcParticle()) { - auto mcP = track.mcParticle(); - if (mcP.isPhysicalPrimary()) { - if (std::abs(mcP.pdgCode()) == KPiPlus) { - histos.fill(HIST("h3_RecoMatchedToPrimary_PiAll"), multPV, mcP.pt(), mcP.eta()); - } else { // Misidentified - histos.fill(HIST("h3_RecoMatchedToPrimary_MisID_PiAll"), multPV, pt, eta); - } - } else { - histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_PiAll"), multPV, pt, eta); - } - } else { - histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_PiAll"), multPV, pt, eta); + } else { + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_PiPlus"), multPV, pt, eta); + } + } else { + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_PiPlus"), multPV, pt, eta); + } + } else if (isp == kPiAllIdx) { + histos.fill(HIST("h3_AllReco_PiAll"), multPV, pt, eta); + if (track.has_mcParticle()) { + auto mcP = track.mcParticle(); + if (mcP.isPhysicalPrimary()) { + if (std::abs(mcP.pdgCode()) == KPiPlus) { + histos.fill(HIST("h3_RecoMatchedToPrimary_PiAll"), multPV, mcP.pt(), mcP.eta()); + } else { // Misidentified + histos.fill(HIST("h3_RecoMatchedToPrimary_MisID_PiAll"), multPV, pt, eta); } - } else if (isp == kKaMinusIdx) { - histos.fill(HIST("h3_AllReco_KaMinus"), multPV, pt, eta); - if (track.has_mcParticle()) { - auto mcP = track.mcParticle(); - if (mcP.isPhysicalPrimary()) { - if (mcP.pdgCode() == -KKPlus) { - histos.fill(HIST("h3_RecoMatchedToPrimary_KaMinus"), multPV, mcP.pt(), mcP.eta()); - } else { // Misidentified - histos.fill(HIST("h3_RecoMatchedToPrimary_MisID_KaMinus"), multPV, pt, eta); - } - } else { - histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_KaMinus"), multPV, pt, eta); - } - } else { - histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_KaMinus"), multPV, pt, eta); + } else { + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_PiAll"), multPV, pt, eta); + } + } else { + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_PiAll"), multPV, pt, eta); + } + } else if (isp == kKaMinusIdx) { + histos.fill(HIST("h3_AllReco_KaMinus"), multPV, pt, eta); + if (track.has_mcParticle()) { + auto mcP = track.mcParticle(); + if (mcP.isPhysicalPrimary()) { + if (mcP.pdgCode() == -KKPlus) { + histos.fill(HIST("h3_RecoMatchedToPrimary_KaMinus"), multPV, mcP.pt(), mcP.eta()); + } else { // Misidentified + histos.fill(HIST("h3_RecoMatchedToPrimary_MisID_KaMinus"), multPV, pt, eta); } - } else if (isp == kKaPlusIdx) { - histos.fill(HIST("h3_AllReco_KaPlus"), multPV, pt, eta); - if (track.has_mcParticle()) { - auto mcP = track.mcParticle(); - if (mcP.isPhysicalPrimary()) { - if (mcP.pdgCode() == KKPlus) { - histos.fill(HIST("h3_RecoMatchedToPrimary_KaPlus"), multPV, mcP.pt(), mcP.eta()); - } else { // Misidentified - histos.fill(HIST("h3_RecoMatchedToPrimary_MisID_KaPlus"), multPV, pt, eta); - } - } else { - histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_KaPlus"), multPV, pt, eta); - } - } else { - histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_KaPlus"), multPV, pt, eta); + } else { + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_KaMinus"), multPV, pt, eta); + } + } else { + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_KaMinus"), multPV, pt, eta); + } + } else if (isp == kKaPlusIdx) { + histos.fill(HIST("h3_AllReco_KaPlus"), multPV, pt, eta); + if (track.has_mcParticle()) { + auto mcP = track.mcParticle(); + if (mcP.isPhysicalPrimary()) { + if (mcP.pdgCode() == KKPlus) { + histos.fill(HIST("h3_RecoMatchedToPrimary_KaPlus"), multPV, mcP.pt(), mcP.eta()); + } else { // Misidentified + histos.fill(HIST("h3_RecoMatchedToPrimary_MisID_KaPlus"), multPV, pt, eta); } - } else if (isp == kKaAllIdx) { - histos.fill(HIST("h3_AllReco_KaAll"), multPV, pt, eta); - if (track.has_mcParticle()) { - auto mcP = track.mcParticle(); - if (mcP.isPhysicalPrimary()) { - if (std::abs(mcP.pdgCode()) == KKPlus) { - histos.fill(HIST("h3_RecoMatchedToPrimary_KaAll"), multPV, mcP.pt(), mcP.eta()); - } else { // Misidentified - histos.fill(HIST("h3_RecoMatchedToPrimary_MisID_KaAll"), multPV, pt, eta); - } - } else { - histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_KaAll"), multPV, pt, eta); - } - } else { - histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_KaAll"), multPV, pt, eta); + } else { + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_KaPlus"), multPV, pt, eta); + } + } else { + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_KaPlus"), multPV, pt, eta); + } + } else if (isp == kKaAllIdx) { + histos.fill(HIST("h3_AllReco_KaAll"), multPV, pt, eta); + if (track.has_mcParticle()) { + auto mcP = track.mcParticle(); + if (mcP.isPhysicalPrimary()) { + if (std::abs(mcP.pdgCode()) == KKPlus) { + histos.fill(HIST("h3_RecoMatchedToPrimary_KaAll"), multPV, mcP.pt(), mcP.eta()); + } else { // Misidentified + histos.fill(HIST("h3_RecoMatchedToPrimary_MisID_KaAll"), multPV, pt, eta); } - } else if (isp == kAntiPrIdx) { - histos.fill(HIST("h3_AllReco_AntiPr"), multPV, pt, eta); - if (track.has_mcParticle()) { - auto mcP = track.mcParticle(); - if (mcP.isPhysicalPrimary()) { - if (mcP.pdgCode() == -KProton) { - histos.fill(HIST("h3_RecoMatchedToPrimary_AntiPr"), multPV, mcP.pt(), mcP.eta()); - } else { // Misidentified - histos.fill(HIST("h3_RecoMatchedToPrimary_MisID_AntiPr"), multPV, pt, eta); - } - } else { - histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_AntiPr"), multPV, pt, eta); - } - } else { - histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_AntiPr"), multPV, pt, eta); + } else { + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_KaAll"), multPV, pt, eta); + } + } else { + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_KaAll"), multPV, pt, eta); + } + } else if (isp == kAntiPrIdx) { + histos.fill(HIST("h3_AllReco_AntiPr"), multPV, pt, eta); + if (track.has_mcParticle()) { + auto mcP = track.mcParticle(); + if (mcP.isPhysicalPrimary()) { + if (mcP.pdgCode() == -KProton) { + histos.fill(HIST("h3_RecoMatchedToPrimary_AntiPr"), multPV, mcP.pt(), mcP.eta()); + } else { // Misidentified + histos.fill(HIST("h3_RecoMatchedToPrimary_MisID_AntiPr"), multPV, pt, eta); } - } else if (isp == kPrIdx) { - histos.fill(HIST("h3_AllReco_Pr"), multPV, pt, eta); - if (track.has_mcParticle()) { - auto mcP = track.mcParticle(); - if (mcP.isPhysicalPrimary()) { - if (mcP.pdgCode() == KProton) { - histos.fill(HIST("h3_RecoMatchedToPrimary_Pr"), multPV, mcP.pt(), mcP.eta()); - } else { // Misidentified - histos.fill(HIST("h3_RecoMatchedToPrimary_MisID_Pr"), multPV, pt, eta); - } - } else { - histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_Pr"), multPV, pt, eta); - } - } else { - histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_Pr"), multPV, pt, eta); + } else { + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_AntiPr"), multPV, pt, eta); + } + } else { + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_AntiPr"), multPV, pt, eta); + } + } else if (isp == kPrIdx) { + histos.fill(HIST("h3_AllReco_Pr"), multPV, pt, eta); + if (track.has_mcParticle()) { + auto mcP = track.mcParticle(); + if (mcP.isPhysicalPrimary()) { + if (mcP.pdgCode() == KProton) { + histos.fill(HIST("h3_RecoMatchedToPrimary_Pr"), multPV, mcP.pt(), mcP.eta()); + } else { // Misidentified + histos.fill(HIST("h3_RecoMatchedToPrimary_MisID_Pr"), multPV, pt, eta); } - } else if (isp == kPrAllIdx) { - histos.fill(HIST("h3_AllReco_PrAll"), multPV, pt, eta); - if (track.has_mcParticle()) { - auto mcP = track.mcParticle(); - if (mcP.isPhysicalPrimary()) { - if (std::abs(mcP.pdgCode()) == KProton) { - histos.fill(HIST("h3_RecoMatchedToPrimary_PrAll"), multPV, mcP.pt(), mcP.eta()); - } else { // Misidentified - histos.fill(HIST("h3_RecoMatchedToPrimary_MisID_PrAll"), multPV, pt, eta); - } - } else { - histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_PrAll"), multPV, pt, eta); - } - } else { - histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_PrAll"), multPV, pt, eta); + } else { + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_Pr"), multPV, pt, eta); + } + } else { + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_Pr"), multPV, pt, eta); + } + } else if (isp == kPrAllIdx) { + histos.fill(HIST("h3_AllReco_PrAll"), multPV, pt, eta); + if (track.has_mcParticle()) { + auto mcP = track.mcParticle(); + if (mcP.isPhysicalPrimary()) { + if (std::abs(mcP.pdgCode()) == KProton) { + histos.fill(HIST("h3_RecoMatchedToPrimary_PrAll"), multPV, mcP.pt(), mcP.eta()); + } else { // Misidentified + histos.fill(HIST("h3_RecoMatchedToPrimary_MisID_PrAll"), multPV, pt, eta); } + } else { + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_PrAll"), multPV, pt, eta); } + } else { + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_PrAll"), multPV, pt, eta); } } } @@ -1740,103 +1714,93 @@ struct RadialFlowDecorr { } PROCESS_SWITCH(RadialFlowDecorr, processGetEffHists, "process MC to calculate EffWeights", cfgRunGetEff); - void processMCFlat(aod::McCollisions const& mcColl, MyRun3MCCollisions const& collisions, TCs const& tracks, FilteredTCs const& /*filteredTracks*/) + void processMCFlat(MyRun3MCCollisions::iterator const& mcCollision, FilteredTCs const& mcTracks) { - for (const auto& mcCollision : mcColl) { - auto colSlice = collisions.sliceBy(colPerMcCollision, mcCollision.globalIndex()); - if (colSlice.size() != 1) - continue; - - for (const auto& col : colSlice) { - histos.fill(HIST("hVtxZ"), col.posZ()); - if (!col.has_mcCollision() || !isEventSelected(col)) - continue; - - float cent = getCentrality(col); - if (cent > KCentMax) - continue; + histos.fill(HIST("hVtxZ"), mcCollision.posZ()); + if (!mcCollision.has_mcCollision() || !isEventSelected(mcCollision)) + return; - auto trackSlice = tracks.sliceBy(trackPerCollision, col.globalIndex()); - if (trackSlice.size() < 1) - continue; + float cent = getCentrality(mcCollision); + if (cent > KCentMax) + return; - float multPV = col.multNTracksPV(); - float vz = col.posZ(); + float multPV = mcCollision.multNTracksPV(); + float vz = mcCollision.posZ(); - if (!isPassAddPileup(multPV, trackSlice.size(), cent)) - continue; - histos.fill(HIST("hVtxZ_after_sel"), col.posZ()); - histos.fill(HIST("hCentrality"), cent); + if (!isPassAddPileup(multPV, mcTracks.size(), cent)) + return; + histos.fill(HIST("hVtxZ_after_sel"), mcCollision.posZ()); + histos.fill(HIST("hCentrality"), cent); - histos.fill(HIST("Hist2D_globalTracks_PVTracks"), col.multNTracksPV(), trackSlice.size()); - histos.fill(HIST("Hist2D_cent_nch"), trackSlice.size(), cent); - for (const auto& track : trackSlice) { - if (!isTrackSelected(track)) - continue; + histos.fill(HIST("Hist2D_globalTracks_PVTracks"), mcCollision.multNTracksPV(), mcTracks.size()); + histos.fill(HIST("Hist2D_cent_nch"), mcTracks.size(), cent); + histos.fill(HIST("Hist2D_globalTracks_cent"), cent, mcTracks.size()); + histos.fill(HIST("Hist2D_PVTracks_cent"), cent, multPV); + for (const auto& track : mcTracks) { + if (!isTrackSelected(track)) + continue; - float pt = track.pt(), eta = track.eta(), phi = track.phi(); - auto sign = track.sign(); - int id = identifyTrack(track, cent); - bool isPi = (id == KPidPionOne); - bool isKa = (id == KPidKaonTwo); - bool isPr = (id == KPidProtonThree); - bool isSpecies[KNsp] = { - true, - isPi && sign < 0, isPi && sign > 0, isPi, - isKa && sign < 0, isKa && sign > 0, isKa, - isPr && sign < 0, isPr && sign > 0, isPr}; + float pt = track.pt(), eta = track.eta(), phi = track.phi(); + auto sign = track.sign(); + int id = identifyTrack(track, cent); + bool isPi = (id == KPidPionOne); + bool isKa = (id == KPidKaonTwo); + bool isPr = (id == KPidProtonThree); + bool isSpecies[KNsp] = { + true, + isPi && sign < 0, isPi && sign > 0, isPi, + isKa && sign < 0, isKa && sign > 0, isKa, + isPr && sign < 0, isPr && sign > 0, isPr}; - for (int isp = 0; isp < KNsp; ++isp) { - if (!isSpecies[isp]) - continue; + for (int isp = 0; isp < KNsp; ++isp) { + if (!isSpecies[isp]) + continue; - float eff = getEfficiency(multPV, pt, eta, static_cast(isp), 0, cfgEff); - float fake = getEfficiency(multPV, pt, eta, static_cast(isp), 1, cfgEff); - float w = (eff > KFloatEpsilon) ? (1.0f - fake) / eff : 0.0f; + float eff = getEfficiency(multPV, pt, eta, static_cast(isp), 0, cfgEff); + float fake = getEfficiency(multPV, pt, eta, static_cast(isp), 1, cfgEff); + float w = (eff > KFloatEpsilon) ? (1.0f - fake) / eff : 0.0f; - if (std::isfinite(w) && w > 0.f) { - if (isp == kInclusiveIdx) { - histos.fill(HIST("MCReco/hEtaPhiRecoEffWtd"), vz, sign, pt, eta, phi, w); - histos.fill(HIST("MCReco/hEtaPhiReco"), vz, sign, pt, eta, phi, 1.0); - histos.fill(HIST("MCReco/hEtaPhiRecoWtd"), vz, sign, pt, eta, phi, w); - } else if (isp == kPiMinusIdx) { - histos.fill(HIST("MCReco/hEtaPhiRecoEffWtd_PiMinus"), vz, sign, pt, eta, phi, w); - histos.fill(HIST("MCReco/hEtaPhiReco_PiMinus"), vz, sign, pt, eta, phi, 1.0); - histos.fill(HIST("MCReco/hEtaPhiRecoWtd_PiMinus"), vz, sign, pt, eta, phi, w); - } else if (isp == kPiPlusIdx) { - histos.fill(HIST("MCReco/hEtaPhiRecoEffWtd_PiPlus"), vz, sign, pt, eta, phi, w); - histos.fill(HIST("MCReco/hEtaPhiReco_PiPlus"), vz, sign, pt, eta, phi, 1.0); - histos.fill(HIST("MCReco/hEtaPhiRecoWtd_PiPlus"), vz, sign, pt, eta, phi, w); - } else if (isp == kPiAllIdx) { - histos.fill(HIST("MCReco/hEtaPhiRecoEffWtd_PiAll"), vz, sign, pt, eta, phi, w); - histos.fill(HIST("MCReco/hEtaPhiReco_PiAll"), vz, sign, pt, eta, phi, 1.0); - histos.fill(HIST("MCReco/hEtaPhiRecoWtd_PiAll"), vz, sign, pt, eta, phi, w); - } else if (isp == kKaMinusIdx) { - histos.fill(HIST("MCReco/hEtaPhiRecoEffWtd_KaMinus"), vz, sign, pt, eta, phi, w); - histos.fill(HIST("MCReco/hEtaPhiReco_KaMinus"), vz, sign, pt, eta, phi, 1.0); - histos.fill(HIST("MCReco/hEtaPhiRecoWtd_KaMinus"), vz, sign, pt, eta, phi, w); - } else if (isp == kKaPlusIdx) { - histos.fill(HIST("MCReco/hEtaPhiRecoEffWtd_KaPlus"), vz, sign, pt, eta, phi, w); - histos.fill(HIST("MCReco/hEtaPhiReco_KaPlus"), vz, sign, pt, eta, phi, 1.0); - histos.fill(HIST("MCReco/hEtaPhiRecoWtd_KaPlus"), vz, sign, pt, eta, phi, w); - } else if (isp == kKaAllIdx) { - histos.fill(HIST("MCReco/hEtaPhiRecoEffWtd_KaAll"), vz, sign, pt, eta, phi, w); - histos.fill(HIST("MCReco/hEtaPhiReco_KaAll"), vz, sign, pt, eta, phi, 1.0); - histos.fill(HIST("MCReco/hEtaPhiRecoWtd_KaAll"), vz, sign, pt, eta, phi, w); - } else if (isp == kAntiPrIdx) { - histos.fill(HIST("MCReco/hEtaPhiRecoEffWtd_AntiPr"), vz, sign, pt, eta, phi, w); - histos.fill(HIST("MCReco/hEtaPhiReco_AntiPr"), vz, sign, pt, eta, phi, 1.0); - histos.fill(HIST("MCReco/hEtaPhiRecoWtd_AntiPr"), vz, sign, pt, eta, phi, w); - } else if (isp == kPrIdx) { - histos.fill(HIST("MCReco/hEtaPhiRecoEffWtd_Pr"), vz, sign, pt, eta, phi, w); - histos.fill(HIST("MCReco/hEtaPhiReco_Pr"), vz, sign, pt, eta, phi, 1.0); - histos.fill(HIST("MCReco/hEtaPhiRecoWtd_Pr"), vz, sign, pt, eta, phi, w); - } else if (isp == kPrAllIdx) { - histos.fill(HIST("MCReco/hEtaPhiRecoEffWtd_PrAll"), vz, sign, pt, eta, phi, w); - histos.fill(HIST("MCReco/hEtaPhiReco_PrAll"), vz, sign, pt, eta, phi, 1.0); - histos.fill(HIST("MCReco/hEtaPhiRecoWtd_PrAll"), vz, sign, pt, eta, phi, w); - } - } + if (std::isfinite(w) && w > 0.f) { + if (isp == kInclusiveIdx) { + histos.fill(HIST("MCReco/hEtaPhiRecoEffWtd"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("MCReco/hEtaPhiReco"), vz, sign, pt, eta, phi, 1.0); + histos.fill(HIST("MCReco/hEtaPhiRecoWtd"), vz, sign, pt, eta, phi, w); + } else if (isp == kPiMinusIdx) { + histos.fill(HIST("MCReco/hEtaPhiRecoEffWtd_PiMinus"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("MCReco/hEtaPhiReco_PiMinus"), vz, sign, pt, eta, phi, 1.0); + histos.fill(HIST("MCReco/hEtaPhiRecoWtd_PiMinus"), vz, sign, pt, eta, phi, w); + } else if (isp == kPiPlusIdx) { + histos.fill(HIST("MCReco/hEtaPhiRecoEffWtd_PiPlus"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("MCReco/hEtaPhiReco_PiPlus"), vz, sign, pt, eta, phi, 1.0); + histos.fill(HIST("MCReco/hEtaPhiRecoWtd_PiPlus"), vz, sign, pt, eta, phi, w); + } else if (isp == kPiAllIdx) { + histos.fill(HIST("MCReco/hEtaPhiRecoEffWtd_PiAll"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("MCReco/hEtaPhiReco_PiAll"), vz, sign, pt, eta, phi, 1.0); + histos.fill(HIST("MCReco/hEtaPhiRecoWtd_PiAll"), vz, sign, pt, eta, phi, w); + } else if (isp == kKaMinusIdx) { + histos.fill(HIST("MCReco/hEtaPhiRecoEffWtd_KaMinus"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("MCReco/hEtaPhiReco_KaMinus"), vz, sign, pt, eta, phi, 1.0); + histos.fill(HIST("MCReco/hEtaPhiRecoWtd_KaMinus"), vz, sign, pt, eta, phi, w); + } else if (isp == kKaPlusIdx) { + histos.fill(HIST("MCReco/hEtaPhiRecoEffWtd_KaPlus"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("MCReco/hEtaPhiReco_KaPlus"), vz, sign, pt, eta, phi, 1.0); + histos.fill(HIST("MCReco/hEtaPhiRecoWtd_KaPlus"), vz, sign, pt, eta, phi, w); + } else if (isp == kKaAllIdx) { + histos.fill(HIST("MCReco/hEtaPhiRecoEffWtd_KaAll"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("MCReco/hEtaPhiReco_KaAll"), vz, sign, pt, eta, phi, 1.0); + histos.fill(HIST("MCReco/hEtaPhiRecoWtd_KaAll"), vz, sign, pt, eta, phi, w); + } else if (isp == kAntiPrIdx) { + histos.fill(HIST("MCReco/hEtaPhiRecoEffWtd_AntiPr"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("MCReco/hEtaPhiReco_AntiPr"), vz, sign, pt, eta, phi, 1.0); + histos.fill(HIST("MCReco/hEtaPhiRecoWtd_AntiPr"), vz, sign, pt, eta, phi, w); + } else if (isp == kPrIdx) { + histos.fill(HIST("MCReco/hEtaPhiRecoEffWtd_Pr"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("MCReco/hEtaPhiReco_Pr"), vz, sign, pt, eta, phi, 1.0); + histos.fill(HIST("MCReco/hEtaPhiRecoWtd_Pr"), vz, sign, pt, eta, phi, w); + } else if (isp == kPrAllIdx) { + histos.fill(HIST("MCReco/hEtaPhiRecoEffWtd_PrAll"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("MCReco/hEtaPhiReco_PrAll"), vz, sign, pt, eta, phi, 1.0); + histos.fill(HIST("MCReco/hEtaPhiRecoWtd_PrAll"), vz, sign, pt, eta, phi, w); } } } @@ -1844,83 +1808,71 @@ struct RadialFlowDecorr { } PROCESS_SWITCH(RadialFlowDecorr, processMCFlat, "process MC to calculate FlatWeights", cfgRunGetMCFlat); - void processMCMean(aod::McCollisions const& mcColl, MyRun3MCCollisions const& collisions, TCs const& tracks, FilteredTCs const& /*filteredTracks*/, aod::FT0s const&, aod::McParticles const& mcParticles) + void processMCMean(MyRun3MCCollisions::iterator const& mcCollision, FilteredTCs const& mcTracks, aod::FT0s const&, aod::McParticles const& mcParticles) { double sumWiTruth[KNsp][KNEta]{}, sumWiptiTruth[KNsp][KNEta]{}; double sumWiReco[KNsp][KNEta]{}, sumWiptiReco[KNsp][KNEta]{}; double sumWiRecoEffCorr[KNsp][KNEta]{}, sumWiptiRecoEffCorr[KNsp][KNEta]{}; + histos.fill(HIST("hVtxZ"), mcCollision.posZ()); + if (!mcCollision.has_mcCollision() || !isEventSelected(mcCollision)) + return; + float cent = getCentrality(mcCollision); + if (cent > KCentMax) + return; + float multPV = mcCollision.multNTracksPV(); + float vz = mcCollision.posZ(); + if (!isPassAddPileup(multPV, mcTracks.size(), cent)) + return; - for (const auto& mcCollision : mcColl) { - auto colSlice = collisions.sliceBy(colPerMcCollision, mcCollision.globalIndex()); - if (colSlice.size() != 1) - continue; - - for (const auto& col : colSlice) { - histos.fill(HIST("hVtxZ"), col.posZ()); - if (!col.has_mcCollision() || !isEventSelected(col)) - continue; - - auto trackSlice = tracks.sliceBy(trackPerCollision, col.globalIndex()); - auto partSlice = mcParticles.sliceBy(partPerMcCollision, mcCollision.globalIndex()); - if (trackSlice.size() < 1 || partSlice.size() < 1) - continue; - - float cent = getCentrality(col); - if (cent > KCentMax) - continue; - float multPV = col.multNTracksPV(); - float vz = col.posZ(); - - if (!isPassAddPileup(multPV, trackSlice.size(), cent)) - continue; - - histos.fill(HIST("hVtxZ_after_sel"), col.posZ()); - histos.fill(HIST("hCentrality"), cent); + histos.fill(HIST("hVtxZ_after_sel"), mcCollision.posZ()); + histos.fill(HIST("hCentrality"), cent); - histos.fill(HIST("Hist2D_globalTracks_PVTracks"), col.multNTracksPV(), trackSlice.size()); - histos.fill(HIST("Hist2D_cent_nch"), trackSlice.size(), cent); + histos.fill(HIST("Hist2D_globalTracks_PVTracks"), mcCollision.multNTracksPV(), mcTracks.size()); + histos.fill(HIST("Hist2D_cent_nch"), mcTracks.size(), cent); + histos.fill(HIST("Hist2D_globalTracks_cent"), cent, mcTracks.size()); + histos.fill(HIST("Hist2D_PVTracks_cent"), cent, multPV); - memset(sumWiTruth, 0, sizeof(sumWiTruth)); - memset(sumWiptiTruth, 0, sizeof(sumWiptiTruth)); - memset(sumWiReco, 0, sizeof(sumWiReco)); - memset(sumWiptiReco, 0, sizeof(sumWiptiReco)); - memset(sumWiRecoEffCorr, 0, sizeof(sumWiRecoEffCorr)); - memset(sumWiptiRecoEffCorr, 0, sizeof(sumWiptiRecoEffCorr)); + memset(sumWiTruth, 0, sizeof(sumWiTruth)); + memset(sumWiptiTruth, 0, sizeof(sumWiptiTruth)); + memset(sumWiReco, 0, sizeof(sumWiReco)); + memset(sumWiptiReco, 0, sizeof(sumWiptiReco)); + memset(sumWiRecoEffCorr, 0, sizeof(sumWiRecoEffCorr)); + memset(sumWiptiRecoEffCorr, 0, sizeof(sumWiptiRecoEffCorr)); - for (const auto& particle : partSlice) { - if (!isParticleSelected(particle) || !particle.isPhysicalPrimary()) - continue; - float pt = particle.pt(), eta = particle.eta(); - if (pt <= cfgPtMin || pt > cfgPtMax) - continue; - int pdgCode = particle.pdgCode(); - int absPdg = std::abs(pdgCode); + for (const auto& particle : mcParticles) { + if (!isParticleSelected(particle) || !particle.isPhysicalPrimary()) + continue; + float pt = particle.pt(), eta = particle.eta(); + if (pt <= cfgPtMin || pt > cfgPtMax) + continue; + int pdgCode = particle.pdgCode(); + int absPdg = std::abs(pdgCode); - bool isSpecies[KNsp] = { - true, // kInclusiveIdx - pdgCode == -KPiPlus, // kPiMinusIdx - pdgCode == KPiPlus, // kPiPlusIdx - absPdg == KPiPlus, // kPiAllIdx - pdgCode == -KKPlus, // kKaMinusIdx - pdgCode == KKPlus, // kKaPlusIdx - absPdg == KKPlus, // kKaAllIdx - pdgCode == -KProton, // kAntiPrIdx - pdgCode == KProton, // kPrIdx - absPdg == KProton // kPrAllIdx - }; + bool isSpecies[KNsp] = { + true, // kInclusiveIdx + pdgCode == -KPiPlus, // kPiMinusIdx + pdgCode == KPiPlus, // kPiPlusIdx + absPdg == KPiPlus, // kPiAllIdx + pdgCode == -KKPlus, // kKaMinusIdx + pdgCode == KKPlus, // kKaPlusIdx + absPdg == KKPlus, // kKaAllIdx + pdgCode == -KProton, // kAntiPrIdx + pdgCode == KProton, // kPrIdx + absPdg == KProton // kPrAllIdx + }; - for (int ieta = 0; ieta < KNEta; ++ieta) { - if (eta <= etaLw[ieta] || eta > etaUp[ieta]) - continue; + for (int ieta = 0; ieta < KNEta; ++ieta) { + if (eta <= etaLw[ieta] || eta > etaUp[ieta]) + continue; - for (int isp = 0; isp < KNsp; ++isp) { - if (isSpecies[isp]) { - sumWiTruth[isp][ieta]++; - sumWiptiTruth[isp][ieta] += pt; - } - } + for (int isp = 0; isp < KNsp; ++isp) { + if (isSpecies[isp]) { + sumWiTruth[isp][ieta]++; + sumWiptiTruth[isp][ieta] += pt; } } + } + } for (int isp = 0; isp < KNsp; ++isp) { histos.fill(HIST("MCGen/Prof_Cent_Nsp_Nchrec"), cent, isp, sumWiTruth[isp][0]); @@ -1931,7 +1883,7 @@ struct RadialFlowDecorr { } } - for (const auto& track : trackSlice) { + for (const auto& track : mcTracks) { if (!isTrackSelected(track)) continue; float pt = track.pt(), eta = track.eta(), phi = track.phi(); @@ -2147,8 +2099,8 @@ struct RadialFlowDecorr { } // end ietaA double amplFT0A = 0, amplFT0C = 0; - if (col.has_foundFT0()) { - const auto& ft0 = col.foundFT0(); + if (mcCollision.has_foundFT0()) { + const auto& ft0 = mcCollision.foundFT0(); for (std::size_t iCh = 0; iCh < ft0.channelA().size(); iCh++) { auto chanelid = ft0.channelA()[iCh]; float ampl = ft0.amplitudeA()[iCh]; @@ -2172,12 +2124,10 @@ struct RadialFlowDecorr { histos.fill(HIST("pmeanFT0A_cent"), cent, amplFT0A); histos.fill(HIST("pmeanFT0Cmultpv"), multPV, amplFT0C); histos.fill(HIST("pmeanFT0C_cent"), cent, amplFT0C); - } - } } PROCESS_SWITCH(RadialFlowDecorr, processMCMean, "process MC to calculate mean pt and Eff Hists", cfgRunMCMean); - void processMCFluc(aod::McCollisions const& mcColl, MyRun3MCCollisions const& collisions, TCs const& tracks, FilteredTCs const& /*filteredTracks*/, aod::FT0s const&, aod::McParticles const& mcParticles) + void processMCFluc(MyRun3MCCollisions::iterator const& mcCollision, FilteredTCs const& mcTracks, aod::FT0s const&, aod::McParticles const& mcParticles) { if (!state.pmeanTruNchEtabinSpbinStep2 || !state.pmeanRecoNchEtabinSpbinStep2 || !state.pmeanRecoEffcorrNchEtabinSpbinStep2 || !state.pmeanMultTruNchEtabinSpbinStep2 || !state.pmeanMultRecoNchEtabinSpbinStep2 || !state.pmeanMultRecoEffcorrNchEtabinSpbinStep2) { @@ -2202,193 +2152,182 @@ struct RadialFlowDecorr { double p1kBarTru[KNsp][KNEta]{}, p1kBarReco[KNsp][KNEta]{}, p1kBarRecoEffCor[KNsp][KNEta]{}; double p1kBarTruMult[KNsp][KNEta]{}, p1kBarRecoMult[KNsp][KNEta]{}, p1kBarRecoEffCorMult[KNsp][KNEta]{}; - for (const auto& mcCollision : mcColl) { - auto partSlice = mcParticles.sliceBy(partPerMcCollision, mcCollision.globalIndex()); - auto colSlice = collisions.sliceBy(colPerMcCollision, mcCollision.globalIndex()); - if (colSlice.size() != 1) - continue; - - for (const auto& col : colSlice) { - if (!col.has_mcCollision() || !isEventSelected(col)) - continue; - - auto trackSlice = tracks.sliceBy(trackPerCollision, col.globalIndex()); - if (trackSlice.size() < 1) - continue; - - float cent = getCentrality(col); - if (cent > KCentMax) - continue; - float multPV = col.multNTracksPV(); - - if (!isPassAddPileup(multPV, trackSlice.size(), cent)) - continue; - - histos.fill(HIST("hVtxZ_after_sel"), col.posZ()); - histos.fill(HIST("hCentrality"), cent); - - histos.fill(HIST("Hist2D_globalTracks_PVTracks"), col.multNTracksPV(), trackSlice.size()); - histos.fill(HIST("Hist2D_cent_nch"), trackSlice.size(), cent); - - memset(sumPmwkTru, 0, sizeof(sumPmwkTru)); - memset(sumWkTru, 0, sizeof(sumWkTru)); - memset(sumPmwkReco, 0, sizeof(sumPmwkReco)); - memset(sumWkReco, 0, sizeof(sumWkReco)); - memset(sumPmwkRecoEffCor, 0, sizeof(sumPmwkRecoEffCor)); - memset(sumWkRecoEffCor, 0, sizeof(sumWkRecoEffCor)); - - memset(meanTru, 0, sizeof(meanTru)); - memset(c2Tru, 0, sizeof(c2Tru)); - memset(meanReco, 0, sizeof(meanReco)); - memset(c2Reco, 0, sizeof(c2Reco)); - memset(meanRecoEffCor, 0, sizeof(meanRecoEffCor)); - memset(c2RecoEffCor, 0, sizeof(c2RecoEffCor)); - - memset(meanTruMult, 0, sizeof(meanTruMult)); - memset(meanRecoMult, 0, sizeof(meanRecoMult)); - memset(meanRecoEffCorMult, 0, sizeof(meanRecoEffCorMult)); - - memset(p1kBarTru, 0, sizeof(p1kBarTru)); - memset(p1kBarReco, 0, sizeof(p1kBarReco)); - memset(p1kBarRecoEffCor, 0, sizeof(p1kBarRecoEffCor)); - - memset(p1kBarTruMult, 0, sizeof(p1kBarTruMult)); - memset(p1kBarRecoMult, 0, sizeof(p1kBarRecoMult)); - memset(p1kBarRecoEffCorMult, 0, sizeof(p1kBarRecoEffCorMult)); + if (!mcCollision.has_mcCollision() || !isEventSelected(mcCollision)) + return; + float cent = getCentrality(mcCollision); + if (cent > KCentMax) + return; + float multPV = mcCollision.multNTracksPV(); + float vz = mcCollision.posZ(); + if (!isPassAddPileup(multPV, mcTracks.size(), cent)) + return; - double p1kBarFt0A = 0.0, p1kBarFt0C = 0.0; + histos.fill(HIST("hVtxZ_after_sel"), mcCollision.posZ()); + histos.fill(HIST("hCentrality"), cent); - for (const auto& particle : partSlice) { - if (!isParticleSelected(particle) || !particle.isPhysicalPrimary()) - continue; + histos.fill(HIST("Hist2D_globalTracks_PVTracks"), multPV, mcTracks.size()); + histos.fill(HIST("Hist2D_cent_nch"), mcTracks.size(), cent); + histos.fill(HIST("Hist2D_globalTracks_cent"), cent, mcTracks.size()); + histos.fill(HIST("Hist2D_PVTracks_cent"), cent, multPV); + + memset(sumPmwkTru, 0, sizeof(sumPmwkTru)); + memset(sumWkTru, 0, sizeof(sumWkTru)); + memset(sumPmwkReco, 0, sizeof(sumPmwkReco)); + memset(sumWkReco, 0, sizeof(sumWkReco)); + memset(sumPmwkRecoEffCor, 0, sizeof(sumPmwkRecoEffCor)); + memset(sumWkRecoEffCor, 0, sizeof(sumWkRecoEffCor)); + + memset(meanTru, 0, sizeof(meanTru)); + memset(c2Tru, 0, sizeof(c2Tru)); + memset(meanReco, 0, sizeof(meanReco)); + memset(c2Reco, 0, sizeof(c2Reco)); + memset(meanRecoEffCor, 0, sizeof(meanRecoEffCor)); + memset(c2RecoEffCor, 0, sizeof(c2RecoEffCor)); + + memset(meanTruMult, 0, sizeof(meanTruMult)); + memset(meanRecoMult, 0, sizeof(meanRecoMult)); + memset(meanRecoEffCorMult, 0, sizeof(meanRecoEffCorMult)); + + memset(p1kBarTru, 0, sizeof(p1kBarTru)); + memset(p1kBarReco, 0, sizeof(p1kBarReco)); + memset(p1kBarRecoEffCor, 0, sizeof(p1kBarRecoEffCor)); + + memset(p1kBarTruMult, 0, sizeof(p1kBarTruMult)); + memset(p1kBarRecoMult, 0, sizeof(p1kBarRecoMult)); + memset(p1kBarRecoEffCorMult, 0, sizeof(p1kBarRecoEffCorMult)); + + double p1kBarFt0A = 0.0, p1kBarFt0C = 0.0; + + for (const auto& particle : mcParticles) { + if (!isParticleSelected(particle) || !particle.isPhysicalPrimary()) + continue; - float pt = particle.pt(); - if (pt <= cfgPtMin || pt > cfgPtMax) - continue; - float eta = particle.eta(); - int pdgCode = particle.pdgCode(); - int absPdg = std::abs(pdgCode); + float pt = particle.pt(); + if (pt <= cfgPtMin || pt > cfgPtMax) + continue; + float eta = particle.eta(); + int pdgCode = particle.pdgCode(); + int absPdg = std::abs(pdgCode); - bool isSpecies[KNsp] = { - true, // kInclusiveIdx - pdgCode == -KPiPlus, // kPiMinusIdx - pdgCode == KPiPlus, // kPiPlusIdx - absPdg == KPiPlus, // kPiAllIdx - pdgCode == -KKPlus, // kKaMinusIdx - pdgCode == KKPlus, // kKaPlusIdx - absPdg == KKPlus, // kKaAllIdx - pdgCode == -KProton, // kAntiPrIdx - pdgCode == KProton, // kPrIdx - absPdg == KProton // kPrAllIdx - }; + bool isSpecies[KNsp] = { + true, // kInclusiveIdx + pdgCode == -KPiPlus, // kPiMinusIdx + pdgCode == KPiPlus, // kPiPlusIdx + absPdg == KPiPlus, // kPiAllIdx + pdgCode == -KKPlus, // kKaMinusIdx + pdgCode == KKPlus, // kKaPlusIdx + absPdg == KKPlus, // kKaAllIdx + pdgCode == -KProton, // kAntiPrIdx + pdgCode == KProton, // kPrIdx + absPdg == KProton // kPrAllIdx + }; - for (int ieta = 0; ieta < KNEta; ++ieta) { - if (eta <= etaLw[ieta] || eta > etaUp[ieta]) - continue; - for (int isp = 0; isp < KNsp; ++isp) { - if (isSpecies[isp]) { - for (int k = 0; k < KIntK; ++k) { - for (int m = 0; m < KIntM; ++m) { - sumPmwkTru[isp][ieta][m][k] += std::pow(pt, m); - } - sumWkTru[isp][ieta][k]++; - } + for (int ieta = 0; ieta < KNEta; ++ieta) { + if (eta <= etaLw[ieta] || eta > etaUp[ieta]) + continue; + for (int isp = 0; isp < KNsp; ++isp) { + if (isSpecies[isp]) { + for (int k = 0; k < KIntK; ++k) { + for (int m = 0; m < KIntM; ++m) { + sumPmwkTru[isp][ieta][m][k] += std::pow(pt, m); } + sumWkTru[isp][ieta][k]++; } } - } // end truth loop - float vz = col.posZ(); - - for (const auto& track : trackSlice) { - if (!isTrackSelected(track)) - continue; + } + } + } // end truth loop - float pt = track.pt(); - if (pt <= cfgPtMin || pt > cfgPtMax) - continue; - float eta = track.eta(); - float phi = track.phi(); - auto sign = track.sign(); - int id = identifyTrack(track, cent); - bool isPi = (id == KPidPionOne); - bool isKa = (id == KPidKaonTwo); - bool isPr = (id == KPidProtonThree); - bool isSpecies[KNsp] = { - true, - isPi && sign < 0, isPi && sign > 0, isPi, - isKa && sign < 0, isKa && sign > 0, isKa, - isPr && sign < 0, isPr && sign > 0, isPr}; + for (const auto& track : mcTracks) { + if (!isTrackSelected(track)) + continue; - for (int isp = 0; isp < KNsp; ++isp) { - if (!isSpecies[isp]) - continue; - float eff = getEfficiency(col.multNTracksPV(), pt, eta, static_cast(isp), 0, cfgEff); - float fake = getEfficiency(col.multNTracksPV(), pt, eta, static_cast(isp), 1, cfgEff); - float flatW = getFlatteningWeight(vz, sign, pt, eta, phi, static_cast(isp), cfgFlat); - float w = flatW * (1.0 - fake) / eff; + float pt = track.pt(); + if (pt <= cfgPtMin || pt > cfgPtMax) + continue; + float eta = track.eta(); + float phi = track.phi(); + auto sign = track.sign(); + int id = identifyTrack(track, cent); + bool isPi = (id == KPidPionOne); + bool isKa = (id == KPidKaonTwo); + bool isPr = (id == KPidProtonThree); + bool isSpecies[KNsp] = { + true, + isPi && sign < 0, isPi && sign > 0, isPi, + isKa && sign < 0, isKa && sign > 0, isKa, + isPr && sign < 0, isPr && sign > 0, isPr}; - if (!std::isfinite(w) || w <= 0.f || eff <= KFloatEpsilon) - continue; + for (int isp = 0; isp < KNsp; ++isp) { + if (!isSpecies[isp]) + continue; + float eff = getEfficiency(multPV, pt, eta, static_cast(isp), 0, cfgEff); + float fake = getEfficiency(multPV, pt, eta, static_cast(isp), 1, cfgEff); + float flatW = getFlatteningWeight(vz, sign, pt, eta, phi, static_cast(isp), cfgFlat); + float w = flatW * (1.0 - fake) / eff; - for (int ieta = 0; ieta < KNEta; ++ieta) { - if (eta <= etaLw[ieta] || eta > etaUp[ieta]) - continue; - for (int k = 0; k < KIntK; ++k) { - for (int m = 0; m < KIntM; ++m) { - sumPmwkReco[isp][ieta][m][k] += std::pow(1.0, k) * std::pow(pt, m); - sumPmwkRecoEffCor[isp][ieta][m][k] += std::pow(w, k) * std::pow(pt, m); - } - sumWkReco[isp][ieta][k] += std::pow(1.0, k); - sumWkRecoEffCor[isp][ieta][k] += std::pow(w, k); - } - } + if (!std::isfinite(w) || w <= 0.f || eff <= KFloatEpsilon) + continue; - if (isp == kInclusiveIdx) { - histos.fill(HIST("hEtaPhiReco"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoWtd"), vz, sign, pt, eta, phi, w); - histos.fill(HIST("hEtaPhiRecoEffWtd"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - } else if (isp == kPiMinusIdx) { - histos.fill(HIST("hEtaPhiReco_PiMinus"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoWtd_PiMinus"), vz, sign, pt, eta, phi, w); - histos.fill(HIST("hEtaPhiRecoEffWtd_PiMinus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - } else if (isp == kPiPlusIdx) { - histos.fill(HIST("hEtaPhiReco_PiPlus"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoWtd_PiPlus"), vz, sign, pt, eta, phi, w); - histos.fill(HIST("hEtaPhiRecoEffWtd_PiPlus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - } else if (isp == kPiAllIdx) { - histos.fill(HIST("hEtaPhiReco_PiAll"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoWtd_PiAll"), vz, sign, pt, eta, phi, w); - histos.fill(HIST("hEtaPhiRecoEffWtd_PiAll"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - } else if (isp == kKaMinusIdx) { - histos.fill(HIST("hEtaPhiReco_KaMinus"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoWtd_KaMinus"), vz, sign, pt, eta, phi, w); - histos.fill(HIST("hEtaPhiRecoEffWtd_KaMinus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - } else if (isp == kKaPlusIdx) { - histos.fill(HIST("hEtaPhiReco_KaPlus"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoWtd_KaPlus"), vz, sign, pt, eta, phi, w); - histos.fill(HIST("hEtaPhiRecoEffWtd_KaPlus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - } else if (isp == kKaAllIdx) { - histos.fill(HIST("hEtaPhiReco_KaAll"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoWtd_KaAll"), vz, sign, pt, eta, phi, w); - histos.fill(HIST("hEtaPhiRecoEffWtd_KaAll"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - } else if (isp == kPrIdx) { - histos.fill(HIST("hEtaPhiReco_Pr"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoWtd_Pr"), vz, sign, pt, eta, phi, w); - histos.fill(HIST("hEtaPhiRecoEffWtd_Pr"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - } else if (isp == kAntiPrIdx) { - histos.fill(HIST("hEtaPhiReco_AntiPr"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoWtd_AntiPr"), vz, sign, pt, eta, phi, w); - histos.fill(HIST("hEtaPhiRecoEffWtd_AntiPr"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - } else if (isp == kPrAllIdx) { - histos.fill(HIST("hEtaPhiReco_PrAll"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoWtd_PrAll"), vz, sign, pt, eta, phi, w); - histos.fill(HIST("hEtaPhiRecoEffWtd_PrAll"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + for (int ieta = 0; ieta < KNEta; ++ieta) { + if (eta <= etaLw[ieta] || eta > etaUp[ieta]) + continue; + for (int k = 0; k < KIntK; ++k) { + for (int m = 0; m < KIntM; ++m) { + sumPmwkReco[isp][ieta][m][k] += std::pow(1.0, k) * std::pow(pt, m); + sumPmwkRecoEffCor[isp][ieta][m][k] += std::pow(w, k) * std::pow(pt, m); } + sumWkReco[isp][ieta][k] += std::pow(1.0, k); + sumWkRecoEffCor[isp][ieta][k] += std::pow(w, k); } - } // trkslice + } + + if (isp == kInclusiveIdx) { + histos.fill(HIST("hEtaPhiReco"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kPiMinusIdx) { + histos.fill(HIST("hEtaPhiReco_PiMinus"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_PiMinus"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_PiMinus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kPiPlusIdx) { + histos.fill(HIST("hEtaPhiReco_PiPlus"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_PiPlus"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_PiPlus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kPiAllIdx) { + histos.fill(HIST("hEtaPhiReco_PiAll"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_PiAll"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_PiAll"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kKaMinusIdx) { + histos.fill(HIST("hEtaPhiReco_KaMinus"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_KaMinus"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_KaMinus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kKaPlusIdx) { + histos.fill(HIST("hEtaPhiReco_KaPlus"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_KaPlus"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_KaPlus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kKaAllIdx) { + histos.fill(HIST("hEtaPhiReco_KaAll"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_KaAll"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_KaAll"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kPrIdx) { + histos.fill(HIST("hEtaPhiReco_Pr"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_Pr"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_Pr"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kAntiPrIdx) { + histos.fill(HIST("hEtaPhiReco_AntiPr"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_AntiPr"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_AntiPr"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kPrAllIdx) { + histos.fill(HIST("hEtaPhiReco_PrAll"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_PrAll"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_PrAll"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } + } + } // trkslice for (int ieta = 0; ieta < KNEta; ++ieta) { - const int ibx = state.pmeanTruNchEtabinSpbinStep2->GetXaxis()->FindBin(col.multNTracksPV()); + const int ibx = state.pmeanTruNchEtabinSpbinStep2->GetXaxis()->FindBin(mcCollision.multNTracksPV()); const int iby = ieta + 1; for (int isp = 0; isp < KNsp; ++isp) { @@ -2430,8 +2369,8 @@ struct RadialFlowDecorr { } double amplFT0A = 0, amplFT0C = 0; - if (col.has_foundFT0()) { - const auto& ft0 = col.foundFT0(); + if (mcCollision.has_foundFT0()) { + const auto& ft0 = mcCollision.foundFT0(); for (std::size_t iCh = 0; iCh < ft0.channelA().size(); iCh++) { float ampl = ft0.amplitudeA()[iCh]; amplFT0A += ampl; @@ -2472,33 +2411,33 @@ struct RadialFlowDecorr { for (int isp = 0; isp < KNsp; ++isp) { if (std::isfinite(meanTru[isp][ieta])) { histos.fill(HIST("MCGen/Prof_MeanpT_Cent_etabin_spbin"), cent, ieta, isp, meanTru[isp][ieta]); - histos.fill(HIST("MCGen/Prof_MeanpT_Mult_etabin_spbin"), col.multNTracksPV(), ieta, isp, meanTru[isp][ieta]); + histos.fill(HIST("MCGen/Prof_MeanpT_Mult_etabin_spbin"), multPV, ieta, isp, meanTru[isp][ieta]); } if (std::isfinite(c2Tru[isp][ieta])) { histos.fill(HIST("MCGen/Prof_C2_Cent_etabin_spbin"), cent, ieta, isp, c2Tru[isp][ieta]); - histos.fill(HIST("MCGen/Prof_C2_Mult_etabin_spbin"), col.multNTracksPV(), ieta, isp, c2Tru[isp][ieta]); + histos.fill(HIST("MCGen/Prof_C2_Mult_etabin_spbin"), multPV, ieta, isp, c2Tru[isp][ieta]); } if (std::isfinite(meanReco[isp][ieta])) { histos.fill(HIST("MCReco/Prof_MeanpT_Cent_etabin_spbin"), cent, ieta, isp, meanReco[isp][ieta]); - histos.fill(HIST("MCReco/Prof_MeanpT_Mult_etabin_spbin"), col.multNTracksPV(), ieta, isp, meanReco[isp][ieta]); + histos.fill(HIST("MCReco/Prof_MeanpT_Mult_etabin_spbin"), multPV, ieta, isp, meanReco[isp][ieta]); } if (std::isfinite(c2Reco[isp][ieta])) { histos.fill(HIST("MCReco/Prof_C2_Cent_etabin_spbin"), cent, ieta, isp, c2Reco[isp][ieta]); - histos.fill(HIST("MCReco/Prof_C2_Mult_etabin_spbin"), col.multNTracksPV(), ieta, isp, c2Reco[isp][ieta]); + histos.fill(HIST("MCReco/Prof_C2_Mult_etabin_spbin"), multPV, ieta, isp, c2Reco[isp][ieta]); } if (std::isfinite(meanRecoEffCor[isp][ieta])) { histos.fill(HIST("MCRecoEffCorr/Prof_MeanpT_Cent_etabin_spbin"), cent, ieta, isp, meanRecoEffCor[isp][ieta]); - histos.fill(HIST("MCRecoEffCorr/Prof_MeanpT_Mult_etabin_spbin"), col.multNTracksPV(), ieta, isp, meanRecoEffCor[isp][ieta]); + histos.fill(HIST("MCRecoEffCorr/Prof_MeanpT_Mult_etabin_spbin"), multPV, ieta, isp, meanRecoEffCor[isp][ieta]); } if (std::isfinite(c2RecoEffCor[isp][ieta])) { histos.fill(HIST("MCRecoEffCorr/Prof_C2_Cent_etabin_spbin"), cent, ieta, isp, c2RecoEffCor[isp][ieta]); - histos.fill(HIST("MCRecoEffCorr/Prof_C2_Mult_etabin_spbin"), col.multNTracksPV(), ieta, isp, c2RecoEffCor[isp][ieta]); + histos.fill(HIST("MCRecoEffCorr/Prof_C2_Mult_etabin_spbin"), multPV, ieta, isp, c2RecoEffCor[isp][ieta]); } } } - p1kBarFt0A = amplFT0A - state.pmeanFT0AmultpvStep2->GetBinContent(state.pmeanFT0AmultpvStep2->GetXaxis()->FindBin(col.multNTracksPV())); - p1kBarFt0C = amplFT0C - state.pmeanFT0CmultpvStep2->GetBinContent(state.pmeanFT0CmultpvStep2->GetXaxis()->FindBin(col.multNTracksPV())); + p1kBarFt0A = amplFT0A - state.pmeanFT0AmultpvStep2->GetBinContent(state.pmeanFT0AmultpvStep2->GetXaxis()->FindBin(multPV)); + p1kBarFt0C = amplFT0C - state.pmeanFT0CmultpvStep2->GetBinContent(state.pmeanFT0CmultpvStep2->GetXaxis()->FindBin(multPV)); for (int ietaA = 1; ietaA <= (KNEta - 1) / 2; ++ietaA) { int ietaC = KNEta - ietaA; @@ -2521,53 +2460,53 @@ struct RadialFlowDecorr { if (std::isfinite(c2SubTru)) { histos.fill(HIST("MCGen/Prof_C2Sub_Cent_etabin_spbin"), cent, ietaA, isp, c2SubTru); - histos.fill(HIST("MCGen/Prof_C2Sub_Mult_etabin_spbin"), col.multNTracksPV(), ietaA, isp, c2SubTru); + histos.fill(HIST("MCGen/Prof_C2Sub_Mult_etabin_spbin"), multPV, ietaA, isp, c2SubTru); } if (std::isfinite(c2SubReco)) { histos.fill(HIST("MCReco/Prof_C2Sub_Cent_etabin_spbin"), cent, ietaA, isp, c2SubReco); - histos.fill(HIST("MCReco/Prof_C2Sub_Mult_etabin_spbin"), col.multNTracksPV(), ietaA, isp, c2SubReco); + histos.fill(HIST("MCReco/Prof_C2Sub_Mult_etabin_spbin"), multPV, ietaA, isp, c2SubReco); } if (std::isfinite(c2SubRecoEffCor)) { histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub_Cent_etabin_spbin"), cent, ietaA, isp, c2SubRecoEffCor); - histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub_Mult_etabin_spbin"), col.multNTracksPV(), ietaA, isp, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub_Mult_etabin_spbin"), multPV, ietaA, isp, c2SubRecoEffCor); } if (std::isfinite(covTru)) { histos.fill(HIST("MCGen/Prof_Cov_Cent_etabin_spbin"), cent, ietaA, isp, covTru); - histos.fill(HIST("MCGen/Prof_Cov_Mult_etabin_spbin"), col.multNTracksPV(), ietaA, isp, covTru); + histos.fill(HIST("MCGen/Prof_Cov_Mult_etabin_spbin"), multPV, ietaA, isp, covTru); } if (std::isfinite(covReco)) { histos.fill(HIST("MCReco/Prof_Cov_Cent_etabin_spbin"), cent, ietaA, isp, covReco); - histos.fill(HIST("MCReco/Prof_Cov_Mult_etabin_spbin"), col.multNTracksPV(), ietaA, isp, covReco); + histos.fill(HIST("MCReco/Prof_Cov_Mult_etabin_spbin"), multPV, ietaA, isp, covReco); } if (std::isfinite(covRecoEffCor)) { histos.fill(HIST("MCRecoEffCorr/Prof_Cov_Cent_etabin_spbin"), cent, ietaA, isp, covRecoEffCor); - histos.fill(HIST("MCRecoEffCorr/Prof_Cov_Mult_etabin_spbin"), col.multNTracksPV(), ietaA, isp, covRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_Cov_Mult_etabin_spbin"), multPV, ietaA, isp, covRecoEffCor); } if (std::isfinite(covFT0ATru)) { histos.fill(HIST("MCGen/Prof_CovFT0A_Cent_etabin_spbin"), cent, ietaA, isp, covFT0ATru); - histos.fill(HIST("MCGen/Prof_CovFT0A_Mult_etabin_spbin"), col.multNTracksPV(), ietaA, isp, covFT0ATru); + histos.fill(HIST("MCGen/Prof_CovFT0A_Mult_etabin_spbin"), multPV, ietaA, isp, covFT0ATru); } if (std::isfinite(covFT0AReco)) { histos.fill(HIST("MCReco/Prof_CovFT0A_Cent_etabin_spbin"), cent, ietaA, isp, covFT0AReco); - histos.fill(HIST("MCReco/Prof_CovFT0A_Mult_etabin_spbin"), col.multNTracksPV(), ietaA, isp, covFT0AReco); + histos.fill(HIST("MCReco/Prof_CovFT0A_Mult_etabin_spbin"), multPV, ietaA, isp, covFT0AReco); } if (std::isfinite(covFT0ARecoEffCor)) { histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A_Cent_etabin_spbin"), cent, ietaA, isp, covFT0ARecoEffCor); - histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A_Mult_etabin_spbin"), col.multNTracksPV(), ietaA, isp, covFT0ARecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A_Mult_etabin_spbin"), multPV, ietaA, isp, covFT0ARecoEffCor); } if (std::isfinite(covFT0CTru)) { histos.fill(HIST("MCGen/Prof_CovFT0C_Cent_etabin_spbin"), cent, ietaA, isp, covFT0CTru); - histos.fill(HIST("MCGen/Prof_CovFT0C_Mult_etabin_spbin"), col.multNTracksPV(), ietaA, isp, covFT0CTru); + histos.fill(HIST("MCGen/Prof_CovFT0C_Mult_etabin_spbin"), multPV, ietaA, isp, covFT0CTru); } if (std::isfinite(covFT0CReco)) { histos.fill(HIST("MCReco/Prof_CovFT0C_Cent_etabin_spbin"), cent, ietaA, isp, covFT0CReco); - histos.fill(HIST("MCReco/Prof_CovFT0C_Mult_etabin_spbin"), col.multNTracksPV(), ietaA, isp, covFT0CReco); + histos.fill(HIST("MCReco/Prof_CovFT0C_Mult_etabin_spbin"), multPV, ietaA, isp, covFT0CReco); } if (std::isfinite(covFT0CRecoEffCor)) { histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C_Cent_etabin_spbin"), cent, ietaA, isp, covFT0CRecoEffCor); - histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C_Mult_etabin_spbin"), col.multNTracksPV(), ietaA, isp, covFT0CRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C_Mult_etabin_spbin"), multPV, ietaA, isp, covFT0CRecoEffCor); } } } @@ -2950,8 +2889,6 @@ struct RadialFlowDecorr { } } } - } // colSlice - } // mcColl LOGF(info, "FINISHED RUNNING processMCFluc"); } PROCESS_SWITCH(RadialFlowDecorr, processMCFluc, "process MC to calculate pt fluc", cfgRunMCFluc); @@ -2969,6 +2906,8 @@ struct RadialFlowDecorr { histos.fill(HIST("Hist2D_globalTracks_PVTracks"), coll.multNTracksPV(), tracks.size()); histos.fill(HIST("Hist2D_cent_nch"), tracks.size(), cent); + histos.fill(HIST("Hist2D_globalTracks_cent"), cent, tracks.size()); + histos.fill(HIST("Hist2D_PVTracks_cent"), cent, coll.multNTracksPV()); int ntrk = 0; for (const auto& track : tracks) { @@ -3016,6 +2955,8 @@ struct RadialFlowDecorr { histos.fill(HIST("Hist2D_globalTracks_PVTracks"), coll.multNTracksPV(), tracks.size()); histos.fill(HIST("Hist2D_cent_nch"), tracks.size(), cent); + histos.fill(HIST("Hist2D_globalTracks_cent"), cent, tracks.size()); + histos.fill(HIST("Hist2D_PVTracks_cent"), cent, coll.multNTracksPV()); int ntrk = 0; float vz = coll.posZ(); @@ -3136,6 +3077,8 @@ struct RadialFlowDecorr { histos.fill(HIST("Hist2D_globalTracks_PVTracks"), coll.multNTracksPV(), tracks.size()); histos.fill(HIST("Hist2D_cent_nch"), tracks.size(), cent); + histos.fill(HIST("Hist2D_globalTracks_cent"), cent, tracks.size()); + histos.fill(HIST("Hist2D_PVTracks_cent"), cent, coll.multNTracksPV()); float vz = coll.posZ(); @@ -3330,6 +3273,8 @@ struct RadialFlowDecorr { histos.fill(HIST("Hist2D_globalTracks_PVTracks"), coll.multNTracksPV(), tracks.size()); histos.fill(HIST("Hist2D_cent_nch"), tracks.size(), cent); + histos.fill(HIST("Hist2D_globalTracks_cent"), cent, tracks.size()); + histos.fill(HIST("Hist2D_PVTracks_cent"), cent, coll.multNTracksPV()); if (!state.pmeanNchEtabinSpbinStep2 || !state.pmeanMultNchEtabinSpbinStep2) { LOGF(warning, "Data fluc: Mean pT or Mult map missing"); From d4fd604fcbb8ceee301e8336f1b229c618e09e92 Mon Sep 17 00:00:00 2001 From: abilandz Date: Fri, 13 Mar 2026 23:44:16 +0100 Subject: [PATCH 276/347] [PWGCF] further clean-up and new corrections (#15374) --- .../Core/MuPa-Configurables.h | 11 +- .../Core/MuPa-DataMembers.h | 3 +- .../Core/MuPa-Enums.h | 12 +- .../Core/MuPa-MemberFunctions.h | 639 +++++++++++++++--- 4 files changed, 561 insertions(+), 104 deletions(-) diff --git a/PWGCF/MultiparticleCorrelations/Core/MuPa-Configurables.h b/PWGCF/MultiparticleCorrelations/Core/MuPa-Configurables.h index 1e5839de465..9f9304d4d1e 100644 --- a/PWGCF/MultiparticleCorrelations/Core/MuPa-Configurables.h +++ b/PWGCF/MultiparticleCorrelations/Core/MuPa-Configurables.h @@ -144,7 +144,7 @@ struct : ConfigurableGroup { Configurable cfFillParticleHistograms2D{"cfFillParticleHistograms2D", false, "if false, all 2D particle histograms are not filled. if kTRUE, the ones for which fBookParticleHistograms2D[...] is kTRUE, are filled"}; Configurable> cfBookParticleHistograms2D{"cfBookParticleHistograms2D", {"1-Phi_vs_Pt", "1-Phi_vs_Eta"}, "Book (1) or do not book (0) 2D particle histograms"}; Configurable> cfRebinSparse{"cfRebinSparse", {1., 1., 1., 1., 1., 1.}, "Ordering is the same as in eDiffPhiWeights. To make bins factor 2 finer use 0.5, to make bins factor 5 coarser use 5."}; - Configurable> cfBookParticleSparseHistograms{"cfBookParticleSparseHistograms", {"0-DWPhi", "0-DWPt", "0-DWEta"}, "Book (1) or do not book (0) particular category of sparse histograms"}; + Configurable> cfBookParticleSparseHistograms{"cfBookParticleSparseHistograms", {"0-DWPhi", "0-DWPt", "0-DWEta", "0-DWCharge"}, "Book (1) or do not book (0) particular category of sparse histograms"}; Configurable cfFillParticleSparseHistogramsBeforeCuts{"cfFillParticleSparseHistogramsBeforeCuts", false, "I need sparse histograms before cuts only when testing pt and eta weights, in internal validation"}; // TBI 20250223 add eventually configurable for FillParticleSparseHistogramsDimension } cf_ph; @@ -233,6 +233,7 @@ struct : ConfigurableGroup { Configurable> cfWhichDiffPhiWeights{"cfWhichDiffPhiWeights", {"1-wPhi", "1-wPt", "1-wEta", "1-wCharge", "1-wCentrality", "1-wVertexZ"}, "use (1) or do not use (0) differential phi weight for particular dimension. If only phi is set to 1, integrated phi weights are used. If phi is set to 0, ALL dimensions are switched off (yes!)"}; Configurable> cfWhichDiffPtWeights{"cfWhichDiffPtWeights", {"0-wPt", "0-wEta", "0-wCharge", "0-wCentrality"}, "use (1) or do not use (0) differential pt weight for particular dimension. If only pt is set to 1, integrated pt weights are used. If pt is set to 0, ALL dimensions are switched off (yes!)"}; Configurable> cfWhichDiffEtaWeights{"cfWhichDiffEtaWeights", {"0-wEta", "0-wPt", "0-wCharge", "0-wCentrality"}, "use (1) or do not use (0) differential eta weight for particular dimension. If only eta is set to 1, integrated eta weights are used. If eta is set to 0, ALL dimensions are switched off (yes!)"}; + Configurable> cfWhichDiffChargeWeights{"cfWhichDiffChargeWeights", {"0-wCharge", "0-wPt", "0-wEta", "0-wCentrality"}, "use (1) or do not use (0) differential charge weight for particular dimension. If only charge is set to 1, integrated charge weights are used. If charge is set to 0, ALL dimensions are switched off (yes!)"}; Configurable cfFileWithWeights{"cfFileWithWeights", "/home/abilandz/DatasetsO2/weights.root", "path to external ROOT file which holds all particle weights in O2 format"}; // for AliEn file prepend "/alice/cern.ch/", for CCDB prepend "/alice-ccdb.cern.ch" } cf_pw; @@ -252,9 +253,9 @@ struct : ConfigurableGroup { // *) Toy NUA: struct : ConfigurableGroup { - Configurable> cfApplyNUAPDF{"cfApplyNUAPDF", {0, 0, 0}, "Apply (1) or do not apply (0) NUA on variable, ordering is the same as in enum eNUAPDF (phi, pt, eta)"}; - Configurable> cfUseDefaultNUAPDF{"cfUseDefaultNUAPDF", {1, 1, 1}, "Use (1) or do not use (0) default NUA profile, ordering is the same as in enum eNUAPDF (phi, pt, eta)"}; - Configurable> cfCustomNUAPDFHistNames{"cfCustomNUAPDFHistNames", {"a", "bb", "ccc"}, "the names of histograms holding custom NUA in an external file."}; + Configurable> cfApplyNUAPDF{"cfApplyNUAPDF", {0, 0, 0, 0}, "Apply (1) or do not apply (0) NUA on variable, ordering is the same as in enum eNUAPDF (phi, pt, eta, charge)"}; + Configurable> cfUseDefaultNUAPDF{"cfUseDefaultNUAPDF", {1, 1, 1, 1}, "Use (1) or do not use (0) default NUA profile, ordering is the same as in enum eNUAPDF (phi, pt, eta, charge)"}; + Configurable> cfCustomNUAPDFHistNames{"cfCustomNUAPDFHistNames", {"a", "bb", "ccc", "dddd"}, "the names of histograms holding custom NUA in an external file."}; Configurable cfFileWithCustomNUA{"cfFileWithCustomNUA", "/home/abilandz/DatasetsO2/customNUA.root", "path to external ROOT file which holds all histograms with custom NUA"}; // for AliEn file prepend "/alice/cern.ch/", for CCDB prepend "/alice-ccdb.cern.ch" } cf_nua; @@ -263,7 +264,7 @@ struct : ConfigurableGroup { Configurable cfUseInternalValidation{"cfUseInternalValidation", false, "perform internal validation using flow analysis on-the-fly"}; Configurable cfInternalValidationForceBailout{"cfInternalValidationForceBailout", false, "force bailout (use only locally, since there is no graceful exit (yet))"}; Configurable cfnEventsInternalValidation{"cfnEventsInternalValidation", 0, "number of events simulated on-the-fly for internal validation"}; - Configurable cfHarmonicsOptionInternalValidation{"cfHarmonicsOptionInternalValidation", "constant", "for internal validation, supported options are \"constant\", \"correlated\", \"persistent\", \"ptDependent\", and \"ptEtaDependent\""}; + Configurable cfHarmonicsOptionInternalValidation{"cfHarmonicsOptionInternalValidation", "constant", "for internal validation, supported options are \"constant\", \"correlated\", \"persistent\", \"ptDependent\", \"ptEtaDependent\", and \"ptEtaChargeDependent\""}; Configurable cfRescaleWithTheoreticalInput{"cfRescaleWithTheoreticalInput", false, "if kTRUE, all correlators are rescaled with theoretical input, so that all results in profiles are 1"}; Configurable cfRandomizeReactionPlane{"cfRandomizeReactionPlane", true, "set to false only when validating against theoretical value the non-isotropic correlators"}; Configurable> cfInternalValidationAmplitudes{"cfInternalValidationAmplitudes", {0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09}, "{v1, v2, v3, v4, ...} + has an effect only in combination with cfHarmonicsOptionInternalValidation = \"constant\". Max number of vn's is gMaxHarmonic."}; diff --git a/PWGCF/MultiparticleCorrelations/Core/MuPa-DataMembers.h b/PWGCF/MultiparticleCorrelations/Core/MuPa-DataMembers.h index 45efee2c74b..32df4c726ee 100644 --- a/PWGCF/MultiparticleCorrelations/Core/MuPa-DataMembers.h +++ b/PWGCF/MultiparticleCorrelations/Core/MuPa-DataMembers.h @@ -343,6 +343,7 @@ struct ParticleWeights { bool fUseDiffPhiWeights[eDiffPhiWeights_N] = {false}; // use differential phi weights, see enum eDiffPhiWeights for supported dimensions bool fUseDiffPtWeights[eDiffPtWeights_N] = {false}; // use differential pt weights, see enum eDiffPtWeights for supported dimensions bool fUseDiffEtaWeights[eDiffEtaWeights_N] = {false}; // use differential eta weights, see enum eDiffEtaWeights for supported dimensions + bool fUseDiffChargeWeights[eDiffChargeWeights_N] = {false}; // use differential charge weights, see enum eDiffChargeWeights for supported dimensions // ... int fDWdimension[eDiffWeightCategory_N] = {0}; // dimension of differential weight for each category in current analysis TArrayD* fFindBinVector[eDiffWeightCategory_N] = {NULL}; // this is the vector I use to find bin when I obtain weights with sparse histograms @@ -399,7 +400,7 @@ struct InternalValidation { // Remember that for each real event, I do fnEventsInternalValidation events on-the-fly. // Can be used in combination with setting fSequentialBailout > 0. unsigned int fnEventsInternalValidation = 0; // how many on-the-fly events will be sampled for each real event, for internal validation - TString* fHarmonicsOptionInternalValidation = NULL; // "constant", "correlated", "persistent", "ptDependent", "ptEtaDependent", see .cxx for full documentation + TString* fHarmonicsOptionInternalValidation = NULL; // "constant", "correlated", "persistent", "ptDependent", "ptEtaDependent", "ptEtaChargeDependent", see .cxx for full documentation bool fRescaleWithTheoreticalInput = false; // if true, all measured correlators are rescaled with theoretical input, so that in profiles everything is at 1 bool fRandomizeReactionPlane = true; // if true, RP is randomized e-by-e. I need false basically only when validating against theoretical input non-isotropic correlators TArrayD* fInternalValidationVnPsin[2] = {NULL}; // 0 = { v1, v2, ... }, 1 = { Psi1, Psi2, ... } diff --git a/PWGCF/MultiparticleCorrelations/Core/MuPa-Enums.h b/PWGCF/MultiparticleCorrelations/Core/MuPa-Enums.h index a4becda5ffe..86fb4a7844e 100644 --- a/PWGCF/MultiparticleCorrelations/Core/MuPa-Enums.h +++ b/PWGCF/MultiparticleCorrelations/Core/MuPa-Enums.h @@ -107,6 +107,7 @@ enum eDiffWeightCategory { eDWPhi = 0, // corresponds to eDiffPhiWeights structure, here the fundamental 0-th axis never to be projected out is "phi" eDWPt, // corresponds to eDiffPtWeights structure, here the fundamental 0-th axis never to be projected out is "pt" eDWEta, // corresponds to eDiffEtaWeights structure, here the fundamental 0-th axis never to be projected out is "eta" + eDWCharge, // corresponds to eDiffChargeWeights structure, here the fundamental 0-th axis never to be projected out is "charge" // ... eDiffWeightCategory_N }; @@ -121,7 +122,7 @@ enum eDiffPhiWeights { eDiffPhiWeights_N }; -enum eDiffPtWeights { // if i add new entry here, or in eDiffPhiWeights and eDiffEtaWeights, I need to update also GetParticleWeights() +enum eDiffPtWeights { // if i add new entry here, or in eDiffPhiWeights and eDiffEtaWeights, I need to update also GetParticleWeights() + FillQvectorFromSparse() + WeightFromSparse() wPtPtAxis = 0, wPtEtaAxis, wPtChargeAxis, @@ -137,6 +138,14 @@ enum eDiffEtaWeights { eDiffEtaWeights_N }; +enum eDiffChargeWeights { + wChargeChargeAxis = 0, + wChargePtAxis, + wChargeEtaAxis, + wChargeCentralityAxis, + eDiffChargeWeights_N +}; + enum eVnPsin { eVn = 0, ePsin = 1 }; @@ -361,6 +370,7 @@ enum eNUAPDF { ePhiNUAPDF = 0, ePtNUAPDF, eEtaNUAPDF, + eChargeNUAPDF, eNUAPDF_N }; diff --git a/PWGCF/MultiparticleCorrelations/Core/MuPa-MemberFunctions.h b/PWGCF/MultiparticleCorrelations/Core/MuPa-MemberFunctions.h index 6b169302955..09b8968976a 100644 --- a/PWGCF/MultiparticleCorrelations/Core/MuPa-MemberFunctions.h +++ b/PWGCF/MultiparticleCorrelations/Core/MuPa-MemberFunctions.h @@ -699,6 +699,33 @@ void defaultConfiguration() } } + // **) Differential multidimensional charge weights: + auto lWhichDiffChargeWeights = cf_pw.cfWhichDiffChargeWeights.value; + if (lWhichDiffChargeWeights.size() != eDiffChargeWeights_N) { + LOGF(info, "\033[1;31m lWhichDiffChargeWeights.size() = %d\033[0m", lWhichDiffChargeWeights.size()); + LOGF(info, "\033[1;31m eDiffChargeWeights_N = %d\033[0m", static_cast(eDiffChargeWeights_N)); + LOGF(fatal, "\033[1;31m%s at line %d : Mismatch in the number of flags in configurable cfWhichDiffChargeWeights, and number of entries in enum eDiffChargeWeights_N \n \033[0m", __FUNCTION__, __LINE__); + } + for (int dpw = 0; dpw < eDiffChargeWeights_N; dpw++) { // "differential charge weight" + if (TString(lWhichDiffChargeWeights[dpw]).Contains("wCharge")) { + pw.fUseDiffChargeWeights[wChargeChargeAxis] = Alright(lWhichDiffChargeWeights[dpw]); // if I pass "1-Charge" => true, "0-Charge" => false + } else if (TString(lWhichDiffChargeWeights[dpw]).Contains("wPt")) { + pw.fUseDiffChargeWeights[wChargePtAxis] = Alright(lWhichDiffChargeWeights[dpw]) && pw.fUseDiffChargeWeights[wChargeChargeAxis]; + } else if (TString(lWhichDiffChargeWeights[dpw]).Contains("wEta")) { + pw.fUseDiffChargeWeights[wChargeEtaAxis] = Alright(lWhichDiffChargeWeights[dpw]) && pw.fUseDiffChargeWeights[wChargeChargeAxis]; + } else if (TString(lWhichDiffChargeWeights[dpw]).Contains("wCentrality")) { + pw.fUseDiffChargeWeights[wChargeCentralityAxis] = Alright(lWhichDiffChargeWeights[dpw]) && pw.fUseDiffChargeWeights[wChargeChargeAxis]; + } else { + LOGF(fatal, "\033[1;31m%s at line %d : The setting %s in configurable cfWhichDiffChargeWeights is not supported yet. See enum eDiffChargeWeights . \n \033[0m", __FUNCTION__, __LINE__, TString(lWhichDiffChargeWeights[dpw]).Data()); + } + } + + // **) Only for debugging purposes, print all enabled weights: + if (tc.fVerbose) { + LOGF(info, "\033[1;31m%s at line %d : printing current status of all weights flags\033[0m", __FUNCTION__, __LINE__); + PrintAllWeightsFlags(); + } // if (tc.fVerbose) { + // **) File holding all particle weights: pw.fFileWithWeights = cf_pw.cfFileWithWeights; @@ -726,9 +753,10 @@ void defaultConfiguration() nua.fApplyNUAPDF[ePhiNUAPDF] = static_cast(lApplyNUAPDF[ePhiNUAPDF]); nua.fApplyNUAPDF[ePtNUAPDF] = static_cast(lApplyNUAPDF[ePtNUAPDF]); nua.fApplyNUAPDF[eEtaNUAPDF] = static_cast(lApplyNUAPDF[eEtaNUAPDF]); + nua.fApplyNUAPDF[eChargeNUAPDF] = static_cast(lApplyNUAPDF[eChargeNUAPDF]); // **) Execute the lines below, only if toy NUA (either default or custom) is requested for at least one kine variable: - if (nua.fApplyNUAPDF[ePhiNUAPDF] || nua.fApplyNUAPDF[ePtNUAPDF] || nua.fApplyNUAPDF[eEtaNUAPDF]) { + if (nua.fApplyNUAPDF[ePhiNUAPDF] || nua.fApplyNUAPDF[ePtNUAPDF] || nua.fApplyNUAPDF[eEtaNUAPDF] || nua.fApplyNUAPDF[eChargeNUAPDF]) { auto lUseDefaultNUAPDF = (std::vector)cf_nua.cfUseDefaultNUAPDF; if (lUseDefaultNUAPDF.size() != eNUAPDF_N) { @@ -739,11 +767,13 @@ void defaultConfiguration() nua.fUseDefaultNUAPDF[ePhiNUAPDF] = static_cast(lUseDefaultNUAPDF[ePhiNUAPDF]); nua.fUseDefaultNUAPDF[ePtNUAPDF] = static_cast(lUseDefaultNUAPDF[ePtNUAPDF]); nua.fUseDefaultNUAPDF[eEtaNUAPDF] = static_cast(lUseDefaultNUAPDF[eEtaNUAPDF]); + nua.fUseDefaultNUAPDF[eChargeNUAPDF] = static_cast(lUseDefaultNUAPDF[eChargeNUAPDF]); // **) Execute the lines below, only if custom toy NUA is requested in at least one kine variable: if (!((nua.fApplyNUAPDF[ePhiNUAPDF] && nua.fUseDefaultNUAPDF[ePhiNUAPDF]) || (nua.fApplyNUAPDF[ePtNUAPDF] && nua.fUseDefaultNUAPDF[ePtNUAPDF]) || - (nua.fApplyNUAPDF[eEtaNUAPDF] && nua.fUseDefaultNUAPDF[eEtaNUAPDF]))) { + (nua.fApplyNUAPDF[eEtaNUAPDF] && nua.fUseDefaultNUAPDF[eEtaNUAPDF]) || + (nua.fApplyNUAPDF[eChargeNUAPDF] && nua.fUseDefaultNUAPDF[eChargeNUAPDF]))) { // If the above conditon is true, as least one NUA is requested and is not default, i.e. it's custom NUA obtained from external file, which was requested to be used. // TBI 20240501 Can I simplify the logic above, it's a bit cryptic... @@ -781,9 +811,16 @@ void defaultConfiguration() LOGF(fatal, "\033[1;31m%s at line %d\033[0m", __FUNCTION__, __LINE__); } } - } // if (!(nua.fUseDefaultNUAPDF[ePhiNUAPDF] || nua.fUseDefaultNUAPDF[ePtNUAPDF] || nua.fUseDefaultNUAPDF[eEtaNUAPDF])) { + if (!nua.fUseDefaultNUAPDF[eChargeNUAPDF]) { + nua.fCustomNUAPDFHistNames[eChargeNUAPDF] = new TString(lCustomNUAPDFHistNames[eChargeNUAPDF]); + this->GetHistogramWithCustomNUA(nua.fFileWithCustomNUA.Data(), eChargeNUAPDF); + if (!nua.fCustomNUAPDF[eChargeNUAPDF]) { + LOGF(fatal, "\033[1;31m%s at line %d\033[0m", __FUNCTION__, __LINE__); + } + } + } // if (!(nua.fUseDefaultNUAPDF[ePhiNUAPDF] || nua.fUseDefaultNUAPDF[ePtNUAPDF] || nua.fUseDefaultNUAPDF[eEtaNUAPDF] || nua.fUseDefaultNUAPDF[eChargeNUAPDF])) { - } // if ( nua.fApplyNUAPDF[ePhiNUAPDF] || nua.fApplyNUAPDF[ePtNUAPDF] || nua.fApplyNUAPDF[eEtaNUAPDF] ) { + } // if ( nua.fApplyNUAPDF[ePhiNUAPDF] || nua.fApplyNUAPDF[ePtNUAPDF] || nua.fApplyNUAPDF[eEtaNUAPDF] || nua.fApplyNUAPDF[eChargeNUAPDF]) { // *) Internal validation: iv.fUseInternalValidation = cf_iv.cfUseInternalValidation; @@ -1009,6 +1046,9 @@ void defaultConfiguration() ph.fParticleSparseHistogramsName[eDWEta] = "fParticleSparseHistograms_DWEta"; ph.fParticleSparseHistogramsTitle[eDWEta] = "sparse histogram for differential #eta weights,"; + ph.fParticleSparseHistogramsName[eDWCharge] = "fParticleSparseHistograms_DWCharge"; + ph.fParticleSparseHistogramsTitle[eDWCharge] = "sparse histogram for differential charge weights,"; + // ... // ** Eta separations: @@ -1136,6 +1176,31 @@ void defaultConfiguration() //============================================================ +void PrintAllWeightsFlags() +{ + // Simple utility function, to print current status of all weights flags. + + LOGF(info, "\033[1;33m Which multidimensional phi weights will be used (the ordering is the same as in enum eDiffPhiWeights):\033[0m"); + for (int dpw = 0; dpw < eDiffPhiWeights_N; dpw++) { + LOGF(info, "\033[1;33m %d \033[0m", pw.fUseDiffPhiWeights[dpw]); + } + LOGF(info, "\033[1;33m Which multidimensional pt weights will be used (the ordering is the same as in enum eDiffPtWeights):\033[0m"); + for (int dpw = 0; dpw < eDiffPtWeights_N; dpw++) { + LOGF(info, "\033[1;33m %d \033[0m", pw.fUseDiffPtWeights[dpw]); + } + LOGF(info, "\033[1;33m Which multidimensional eta weights will be used (the ordering is the same as in enum eDiffEtaWeights):\033[0m"); + for (int dpw = 0; dpw < eDiffEtaWeights_N; dpw++) { + LOGF(info, "\033[1;33m %d \033[0m", pw.fUseDiffEtaWeights[dpw]); + } + LOGF(info, "\033[1;33m Which multidimensional charge weights will be used (the ordering is the same as in enum eDiffChargeWeights):\033[0m"); + for (int dpw = 0; dpw < eDiffChargeWeights_N; dpw++) { + LOGF(info, "\033[1;33m %d \033[0m", pw.fUseDiffChargeWeights[dpw]); + } + +} // void PrintAllWeightsFlags() + +//============================================================ + bool Alright(TString s) { // Simple utility function, which for a string formatted "0-someName" returns false, and for "1-someName" returns true. @@ -1324,18 +1389,24 @@ void defaultBooking() ph.fRebinSparse[eDWPhi][wPhiVertexZAxis] = lRebinSparse[wPhiVertexZAxis]; // ... - ph.fRebinSparse[eDWPt][wPtPtAxis] = lRebinSparse[wPhiPtAxis]; // yes, wPhiPtAxis is on the RHS, becase I defined ordering of cfRebinSparse by using oredring in eDiffPhiWeights + ph.fRebinSparse[eDWPt][wPtPtAxis] = lRebinSparse[wPhiPtAxis]; // yes, wPhiPtAxis is on the RHS, becase I defined ordering of cfRebinSparse by using ordering in eDiffPhiWeights ph.fRebinSparse[eDWPt][wPtEtaAxis] = lRebinSparse[wPhiEtaAxis]; ph.fRebinSparse[eDWPt][wPtChargeAxis] = lRebinSparse[wPhiChargeAxis]; ph.fRebinSparse[eDWPt][wPtCentralityAxis] = lRebinSparse[wPhiCentralityAxis]; // ... - ph.fRebinSparse[eDWEta][wEtaEtaAxis] = lRebinSparse[wPhiEtaAxis]; // yes, wPhiEtaAxis is on the RHS, becase I defined ordering of cfRebinSparse by using oredring in eDiffPhiWeights + ph.fRebinSparse[eDWEta][wEtaEtaAxis] = lRebinSparse[wPhiEtaAxis]; // yes, wPhiEtaAxis is on the RHS, becase I defined ordering of cfRebinSparse by using ordering in eDiffPhiWeights ph.fRebinSparse[eDWEta][wEtaPtAxis] = lRebinSparse[wPhiPtAxis]; ph.fRebinSparse[eDWEta][wEtaChargeAxis] = lRebinSparse[wPhiChargeAxis]; ph.fRebinSparse[eDWEta][wEtaCentralityAxis] = lRebinSparse[wPhiCentralityAxis]; // ... + ph.fRebinSparse[eDWCharge][wChargeChargeAxis] = lRebinSparse[wPhiChargeAxis]; // yes, wPhiChargeAxis is on the RHS, becase I defined ordering of cfRebinSparse by using ordering in eDiffPhiWeights + ph.fRebinSparse[eDWCharge][wChargePtAxis] = lRebinSparse[wPhiPtAxis]; + ph.fRebinSparse[eDWCharge][wChargeEtaAxis] = lRebinSparse[wPhiEtaAxis]; + ph.fRebinSparse[eDWCharge][wChargeCentralityAxis] = lRebinSparse[wPhiCentralityAxis]; + // ... + // *) Categories of sparse histograms: auto lBookParticleSparseHistograms = cf_ph.cfBookParticleSparseHistograms.value; // fill or not particulat category of sparse histograms if (lBookParticleSparseHistograms.size() != eDiffWeightCategory_N) { @@ -1363,6 +1434,7 @@ void defaultBooking() ph.fBookParticleSparseHistograms[eDWPhi] = Alright(lBookParticleSparseHistograms[eDWPhi]); ph.fBookParticleSparseHistograms[eDWPt] = Alright(lBookParticleSparseHistograms[eDWPt]); ph.fBookParticleSparseHistograms[eDWEta] = Alright(lBookParticleSparseHistograms[eDWEta]); + ph.fBookParticleSparseHistograms[eDWCharge] = Alright(lBookParticleSparseHistograms[eDWCharge]); // f) QA: @@ -2889,7 +2961,7 @@ void insanityChecksBeforeBooking() } // **) Enforce that if the fixed number of randomly selected tracks is used that Toy NUA is disabled: - if (tc.fFixedNumberOfRandomlySelectedTracks > 0 && (nua.fApplyNUAPDF[ePhiNUAPDF] || nua.fApplyNUAPDF[ePtNUAPDF] || nua.fApplyNUAPDF[eEtaNUAPDF])) { + if (tc.fFixedNumberOfRandomlySelectedTracks > 0 && (nua.fApplyNUAPDF[ePhiNUAPDF] || nua.fApplyNUAPDF[ePtNUAPDF] || nua.fApplyNUAPDF[eEtaNUAPDF] || nua.fApplyNUAPDF[eChargeNUAPDF])) { LOGF(fatal, "\033[1;31m%s at line %d : Not supported at the moment: use FixedNumberOfRandomlySelectedTracks + Toy NUA enabled.\nI cannot in an easy way ensure that ParticleCuts behave exactly the same in the Main and Banishment loops, because e.g. I call consequtively for same partcile gRandom->Uniform(...) in ParticleCuts, and that can't work.\033[0m", __FUNCTION__, __LINE__); } @@ -2983,6 +3055,9 @@ void insanityChecksBeforeBooking() if (eDiffEtaWeights_N > gMaxNumberSparseDimensions) { LOGF(fatal, "\033[1;31m%s at line %d : set eDiffEtaWeights_N = %d is bigger than gMaxNumberSparseDimensions = %d\033[0m", __FUNCTION__, __LINE__, static_cast(eDiffEtaWeights_N), gMaxNumberSparseDimensions); } + if (eDiffChargeWeights_N > gMaxNumberSparseDimensions) { + LOGF(fatal, "\033[1;31m%s at line %d : set eDiffChargeWeights_N = %d is bigger than gMaxNumberSparseDimensions = %d\033[0m", __FUNCTION__, __LINE__, static_cast(eDiffChargeWeights_N), gMaxNumberSparseDimensions); + } // ** For simulated data when fDatabasePDG is NOT used, I have to disable cut on charge, since that info is not available: if ((tc.fProcess[eGenericRecSim] || tc.fProcess[eGenericSim]) && pc.fUseParticleCuts[eCharge] && !tc.fUseDatabasePDG) { @@ -3259,7 +3334,8 @@ void insanityChecksBeforeBooking() iv.fHarmonicsOptionInternalValidation->EqualTo("correlated", TString::kIgnoreCase) || iv.fHarmonicsOptionInternalValidation->EqualTo("persistent", TString::kIgnoreCase) || iv.fHarmonicsOptionInternalValidation->EqualTo("ptDependent", TString::kIgnoreCase) || - iv.fHarmonicsOptionInternalValidation->EqualTo("ptEtaDependent", TString::kIgnoreCase))) { + iv.fHarmonicsOptionInternalValidation->EqualTo("ptEtaDependent", TString::kIgnoreCase) || + iv.fHarmonicsOptionInternalValidation->EqualTo("ptEtaChargeDependent", TString::kIgnoreCase))) { LOGF(fatal, "\033[1;31m%s at line %d : fHarmonicsOptionInternalValidation = %s is not supported. \033[0m", __FUNCTION__, __LINE__, iv.fHarmonicsOptionInternalValidation->Data()); } @@ -3349,6 +3425,9 @@ void insanityChecksAfterBooking() if (iv.fRescaleWithTheoreticalInput && iv.fHarmonicsOptionInternalValidation->EqualTo("ptEtaDependent")) { LOGF(fatal, "\033[1;31m%s at line %d : rescaling with theoretical input doesn't make sanse for fHarmonicsOptionInternalValidation = \"ptEtaDependent\". \033[0m", __FUNCTION__, __LINE__); } + if (iv.fRescaleWithTheoreticalInput && iv.fHarmonicsOptionInternalValidation->EqualTo("ptEtaChargeDependent")) { + LOGF(fatal, "\033[1;31m%s at line %d : rescaling with theoretical input doesn't make sanse for fHarmonicsOptionInternalValidation = \"ptEtaChargeDependent\". \033[0m", __FUNCTION__, __LINE__); + } // **) Print a warning if this histogram is not booked: if (!eh.fEventHistograms[eNumberOfEvents][eSim][eAfter]) { @@ -5379,6 +5458,54 @@ void bookParticleHistograms() // ... + // **) eDiffWeightCategory = eDWCharge: + + // ***) charge-axis for diff charge weights - at the moment I support only fixed-length binning from control histograms, which optionally can be made finer or coarser with cfRebinSparse configurable: + ph.fParticleSparseHistogramsNBins[eDWCharge][wChargeChargeAxis] = static_cast(ph.fParticleHistogramsBins[eCharge][0] / ph.fRebinSparse[eDWCharge][wChargeChargeAxis]); + lAxis = new TAxis(ph.fParticleSparseHistogramsNBins[eDWCharge][wChargeChargeAxis], ph.fParticleHistogramsBins[eCharge][1], ph.fParticleHistogramsBins[eCharge][2]); + ph.fParticleSparseHistogramsBinEdges[eDWCharge][wChargeChargeAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWCharge][wChargeChargeAxis]); + for (int bin = 1; bin <= lAxis->GetNbins(); bin++) { + ph.fParticleSparseHistogramsBinEdges[eDWCharge][wChargeChargeAxis]->AddAt(lAxis->GetBinLowEdge(bin), bin - 1); + } + ph.fParticleSparseHistogramsBinEdges[eDWCharge][wChargeChargeAxis]->AddAt(lAxis->GetBinLowEdge(1 + lAxis->GetNbins()), lAxis->GetNbins()); // special treatment for last bin + delete lAxis; + ph.fParticleSparseHistogramsAxisTitle[eDWCharge][wChargeChargeAxis] = FancyFormatting("charge"); + + // ***) pt-axis for diff charge weights - at the moment I support only fixed-length binning from control histograms, which optionally can be made finer or coarser with cfRebinSparse configurable: + ph.fParticleSparseHistogramsNBins[eDWCharge][wChargePtAxis] = static_cast(ph.fParticleHistogramsBins[ePt][0] / ph.fRebinSparse[eDWCharge][wChargePtAxis]); + lAxis = new TAxis(ph.fParticleSparseHistogramsNBins[eDWCharge][wChargePtAxis], ph.fParticleHistogramsBins[ePt][1], ph.fParticleHistogramsBins[ePt][2]); + ph.fParticleSparseHistogramsBinEdges[eDWCharge][wChargePtAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWCharge][wChargePtAxis]); + for (int bin = 1; bin <= lAxis->GetNbins(); bin++) { + ph.fParticleSparseHistogramsBinEdges[eDWCharge][wChargePtAxis]->AddAt(lAxis->GetBinLowEdge(bin), bin - 1); + } + ph.fParticleSparseHistogramsBinEdges[eDWCharge][wChargePtAxis]->AddAt(lAxis->GetBinLowEdge(1 + lAxis->GetNbins()), lAxis->GetNbins()); // special treatment for last bin + delete lAxis; + ph.fParticleSparseHistogramsAxisTitle[eDWCharge][wChargePtAxis] = FancyFormatting("Pt"); + + // ***) eta-axis for diff charge weights - at the moment I support only fixed-length binning from control histograms, which optionally can be made finer or coarser with cfRebinSparse configurable: + ph.fParticleSparseHistogramsNBins[eDWCharge][wChargeEtaAxis] = static_cast(ph.fParticleHistogramsBins[eEta][0] / ph.fRebinSparse[eDWCharge][wChargeEtaAxis]); + lAxis = new TAxis(ph.fParticleSparseHistogramsNBins[eDWCharge][wChargeEtaAxis], ph.fParticleHistogramsBins[eEta][1], ph.fParticleHistogramsBins[eEta][2]); + ph.fParticleSparseHistogramsBinEdges[eDWCharge][wChargeEtaAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWCharge][wChargeEtaAxis]); + for (int bin = 1; bin <= lAxis->GetNbins(); bin++) { + ph.fParticleSparseHistogramsBinEdges[eDWCharge][wChargeEtaAxis]->AddAt(lAxis->GetBinLowEdge(bin), bin - 1); + } + ph.fParticleSparseHistogramsBinEdges[eDWCharge][wChargeEtaAxis]->AddAt(lAxis->GetBinLowEdge(1 + lAxis->GetNbins()), lAxis->GetNbins()); // special treatment for last bin + delete lAxis; + ph.fParticleSparseHistogramsAxisTitle[eDWCharge][wChargeEtaAxis] = FancyFormatting("Eta"); + + // ***) centrality-axis for diff charge weights - at the moment I support only fixed-length binning from control histograms, which optionally can be made finer or coarser with cfRebinSparse configurable: + ph.fParticleSparseHistogramsNBins[eDWCharge][wChargeCentralityAxis] = static_cast(eh.fEventHistogramsBins[eCentrality][0] / ph.fRebinSparse[eDWCharge][wChargeCentralityAxis]); + lAxis = new TAxis(ph.fParticleSparseHistogramsNBins[eDWCharge][wChargeCentralityAxis], eh.fEventHistogramsBins[eCentrality][1], eh.fEventHistogramsBins[eCentrality][2]); + ph.fParticleSparseHistogramsBinEdges[eDWCharge][wChargeCentralityAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWCharge][wChargeCentralityAxis]); + for (int bin = 1; bin <= lAxis->GetNbins(); bin++) { + ph.fParticleSparseHistogramsBinEdges[eDWCharge][wChargeCentralityAxis]->AddAt(lAxis->GetBinLowEdge(bin), bin - 1); + } + ph.fParticleSparseHistogramsBinEdges[eDWCharge][wChargeCentralityAxis]->AddAt(lAxis->GetBinLowEdge(1 + lAxis->GetNbins()), lAxis->GetNbins()); // special treatment for last bin + delete lAxis; + ph.fParticleSparseHistogramsAxisTitle[eDWCharge][wChargeCentralityAxis] = "Centrality"; // TBI 20250222 I cannot call here FancyFormatting for "Centrality", because ec.fsEventCuts[eCentralityEstimator] is still not fetched and set from configurable. Re-think how to proceed for this specific case. + + // ... + // e) Book specific particle sparse histograms (n-dimensions): if (ph.fBookParticleSparseHistograms[eDWPhi]) { BookParticleSparseHistograms(eDWPhi); @@ -5392,6 +5519,10 @@ void bookParticleHistograms() BookParticleSparseHistograms(eDWEta); } + if (ph.fBookParticleSparseHistograms[eDWCharge]) { + BookParticleSparseHistograms(eDWCharge); + } + if (tc.fVerbose) { ExitFunction(__FUNCTION__); } @@ -5423,6 +5554,10 @@ void BookParticleSparseHistograms(eDiffWeightCategory dwc) nDimensions = static_cast(eDiffEtaWeights_N); break; } + case eDWCharge: { + nDimensions = static_cast(eDiffChargeWeights_N); + break; + } default: { LOGF(fatal, "\033[1;31m%s at line %d : This differential weight category, dwc = %d, is not supported yet. \033[0m", __FUNCTION__, __LINE__, static_cast(dwc)); break; @@ -5977,7 +6112,7 @@ void bookWeightsHistograms() } // a) Book the profile holding flags: - pw.fWeightsFlagsPro = new TProfile("fWeightsFlagsPro", "flags for particle weights", 17, 0., 17.); + pw.fWeightsFlagsPro = new TProfile("fWeightsFlagsPro", "flags for particle weights", 23, 0., 23.); pw.fWeightsFlagsPro->SetStats(false); pw.fWeightsFlagsPro->SetLineColor(eColor); pw.fWeightsFlagsPro->SetFillColor(eFillColor); @@ -5991,7 +6126,7 @@ void bookWeightsHistograms() pw.fWeightsFlagsPro->GetXaxis()->SetBinLabel(4, "(w_{#varphi})_{| p_{T}}"); // TBI 20241019 not sure if this is the final notation, keep in sync with void SetDiffWeightsHist(...) pw.fWeightsFlagsPro->GetXaxis()->SetBinLabel(5, "(w_{#varphi})_{| #eta}"); // TBI 20241019 not sure if this is the final notation, keep in sync with void SetDiffWeightsHist(...) - // **) differential phi weights using sparse: + // **) differential phi weights using sparse (keep in sync with enum eDiffPhiWeights): pw.fWeightsFlagsPro->GetXaxis()->SetBinLabel(6, "(w_{#varphi})_{phi axis (sparse)}"); pw.fWeightsFlagsPro->GetXaxis()->SetBinLabel(7, "(w_{#varphi})_{p_{T} axis (sparse)}"); pw.fWeightsFlagsPro->GetXaxis()->SetBinLabel(8, "(w_{#varphi})_{#eta axis (sparse)}"); @@ -5999,11 +6134,23 @@ void bookWeightsHistograms() pw.fWeightsFlagsPro->GetXaxis()->SetBinLabel(10, "(w_{#varphi})_{centrality axis (sparse)}"); pw.fWeightsFlagsPro->GetXaxis()->SetBinLabel(11, "(w_{#varphi})_{VertexZ axis (sparse)}"); - // **) differential pt weights using sparse: + // **) differential pt weights using sparse (keep in sync with enum eDiffPtWeights): pw.fWeightsFlagsPro->GetXaxis()->SetBinLabel(12, "(w_{p_{T}})_{pt axis (sparse)}"); - - // **) differential eta weights using sparse: - pw.fWeightsFlagsPro->GetXaxis()->SetBinLabel(13, "(w_{#eta})_{eta axis (sparse)}"); + pw.fWeightsFlagsPro->GetXaxis()->SetBinLabel(13, "(w_{p_{T}})_{eta axis (sparse)}"); + pw.fWeightsFlagsPro->GetXaxis()->SetBinLabel(14, "(w_{p_{T}})_{charge axis (sparse)}"); + pw.fWeightsFlagsPro->GetXaxis()->SetBinLabel(15, "(w_{p_{T}})_{centrality axis (sparse)}"); + + // **) differential eta weights using sparse (keep in sync with enum eDiffEtaWeights): + pw.fWeightsFlagsPro->GetXaxis()->SetBinLabel(16, "(w_{#eta})_{eta axis (sparse)}"); + pw.fWeightsFlagsPro->GetXaxis()->SetBinLabel(17, "(w_{#eta})_{pt axis (sparse)}"); + pw.fWeightsFlagsPro->GetXaxis()->SetBinLabel(18, "(w_{#eta})_{charge axis (sparse)}"); + pw.fWeightsFlagsPro->GetXaxis()->SetBinLabel(19, "(w_{#eta})_{centrality axis (sparse)}"); + + // **) differential charge weights using sparse (keep in sync with enum eDiffChargeWeights): + pw.fWeightsFlagsPro->GetXaxis()->SetBinLabel(20, "(w_{charge})_{charge axis (sparse)}"); + pw.fWeightsFlagsPro->GetXaxis()->SetBinLabel(21, "(w_{charge})_{pt axis (sparse)}"); + pw.fWeightsFlagsPro->GetXaxis()->SetBinLabel(22, "(w_{charge})_{eta axis (sparse)}"); + pw.fWeightsFlagsPro->GetXaxis()->SetBinLabel(23, "(w_{charge})_{centrality axis (sparse)}"); } else { @@ -6016,7 +6163,7 @@ void bookWeightsHistograms() yAxisTitle += TString::Format("%d:(w_{#varphi})_{| p_{T}}; ", 4); yAxisTitle += TString::Format("%d:(w_{#varphi})_{| #eta}; ", 5); - // **) differential phi weights using sparse: + // **) differential phi weights using sparse (keep in sync with enum eDiffPhiWeights): yAxisTitle += TString::Format("%d:(w_{#varphi})_{phi axis (sparse)}; ", 6); yAxisTitle += TString::Format("%d:(w_{#varphi})_{p_{T} axis (sparse)}; ", 7); yAxisTitle += TString::Format("%d:(w_{#varphi})_{#eta axis (sparse)}; ", 8); @@ -6024,15 +6171,23 @@ void bookWeightsHistograms() yAxisTitle += TString::Format("%d:(w_{#varphi})_{centrality axis (sparse)}; ", 10); yAxisTitle += TString::Format("%d:(w_{#varphi})_{VertexZ axis (sparse)}; ", 11); - // **) differential pt weights using sparse: + // **) differential pt weights using sparse (keep in sync with enum eDiffPtWeights): yAxisTitle += TString::Format("%d:(w_{p_{T}})_{pt axis (sparse)}; ", 12); - yAxisTitle += TString::Format("%d:(w_{p_{T}})_{charge axis (sparse)}; ", 13); - yAxisTitle += TString::Format("%d:(w_{p_{T}})_{centrality axis (sparse)}; ", 14); - - // **) differential eta weights using sparse: - yAxisTitle += TString::Format("%d:(w_{#eta})_{eta axis (sparse)}; ", 15); - yAxisTitle += TString::Format("%d:(w_{#eta})_{charge axis (sparse)}; ", 16); - yAxisTitle += TString::Format("%d:(w_{#eta})_{centrality axis (sparse)}; ", 17); + yAxisTitle += TString::Format("%d:(w_{p_{T}})_{eta axis (sparse)}; ", 13); + yAxisTitle += TString::Format("%d:(w_{p_{T}})_{charge axis (sparse)}; ", 14); + yAxisTitle += TString::Format("%d:(w_{p_{T}})_{centrality axis (sparse)}; ", 15); + + // **) differential eta weights using sparse (keep in sync with enum eDiffEtaWeights): + yAxisTitle += TString::Format("%d:(w_{#eta})_{eta axis (sparse)}; ", 16); + yAxisTitle += TString::Format("%d:(w_{#eta})_{pt axis (sparse)}; ", 17); + yAxisTitle += TString::Format("%d:(w_{#eta})_{charge axis (sparse)}; ", 18); + yAxisTitle += TString::Format("%d:(w_{#eta})_{centrality axis (sparse)}; ", 19); + + // **) differential charge weights using sparse (keep in sync with enum eDiffChargeWeights): + yAxisTitle += TString::Format("%d:(w_{charge})_{charge axis (sparse)}; ", 20); + yAxisTitle += TString::Format("%d:(w_{charge})_{pt axis (sparse)}; ", 21); + yAxisTitle += TString::Format("%d:(w_{charge})_{eta axis (sparse)}; ", 22); + yAxisTitle += TString::Format("%d:(w_{charge})_{centrality axis (sparse)}; ", 23); // ... @@ -6089,23 +6244,43 @@ void bookWeightsHistograms() if (pw.fUseDiffPtWeights[wPtPtAxis]) { pw.fWeightsFlagsPro->Fill(11.5, 1.); } - if (pw.fUseDiffPhiWeights[wPtChargeAxis]) { + if (pw.fUseDiffPtWeights[wPtEtaAxis]) { pw.fWeightsFlagsPro->Fill(12.5, 1.); } - if (pw.fUseDiffPhiWeights[wPtCentralityAxis]) { + if (pw.fUseDiffPtWeights[wPtChargeAxis]) { pw.fWeightsFlagsPro->Fill(13.5, 1.); } + if (pw.fUseDiffPtWeights[wPtCentralityAxis]) { + pw.fWeightsFlagsPro->Fill(14.5, 1.); + } // **) differential eta weights using sparse: if (pw.fUseDiffEtaWeights[wEtaEtaAxis]) { - pw.fWeightsFlagsPro->Fill(14.5, 1.); - } - if (pw.fUseDiffPhiWeights[wEtaChargeAxis]) { pw.fWeightsFlagsPro->Fill(15.5, 1.); } - if (pw.fUseDiffPhiWeights[wEtaCentralityAxis]) { + if (pw.fUseDiffEtaWeights[wEtaPtAxis]) { pw.fWeightsFlagsPro->Fill(16.5, 1.); } + if (pw.fUseDiffEtaWeights[wEtaChargeAxis]) { + pw.fWeightsFlagsPro->Fill(17.5, 1.); + } + if (pw.fUseDiffEtaWeights[wEtaCentralityAxis]) { + pw.fWeightsFlagsPro->Fill(18.5, 1.); + } + + // **) differential charge weights using sparse: + if (pw.fUseDiffChargeWeights[wChargeChargeAxis]) { + pw.fWeightsFlagsPro->Fill(19.5, 1.); + } + if (pw.fUseDiffChargeWeights[wChargePtAxis]) { + pw.fWeightsFlagsPro->Fill(20.5, 1.); + } + if (pw.fUseDiffChargeWeights[wChargeEtaAxis]) { + pw.fWeightsFlagsPro->Fill(21.5, 1.); + } + if (pw.fUseDiffChargeWeights[wChargeCentralityAxis]) { + pw.fWeightsFlagsPro->Fill(22.5, 1.); + } pw.fWeightsList->Add(pw.fWeightsFlagsPro); @@ -6427,20 +6602,22 @@ void bookNUAHistograms() } // a) Book the profile holding flags: - nua.fNUAFlagsPro = new TProfile("fNUAFlagsPro", "flags for Toy NUA", 6, 0.5, 6.5); + nua.fNUAFlagsPro = new TProfile("fNUAFlagsPro", "flags for Toy NUA", 8, 0.5, 8.5); nua.fNUAFlagsPro->SetStats(false); nua.fNUAFlagsPro->SetLineColor(eColor); nua.fNUAFlagsPro->SetFillColor(eFillColor); nua.fNUAFlagsPro->GetXaxis()->SetLabelSize(0.03); - // TBI 20240429 the binning below is a bit fragile, but ok... + // TBI 20260312 the binning below is a bit fragile, but ok... if (tc.fUseSetBinLabel) { nua.fNUAFlagsPro->GetXaxis()->SetBinLabel(static_cast(1 + ePhiNUAPDF), "fApplyNUAPDF[phi]"); nua.fNUAFlagsPro->GetXaxis()->SetBinLabel(static_cast(1 + ePtNUAPDF), "fApplyNUAPDF[pt]"); nua.fNUAFlagsPro->GetXaxis()->SetBinLabel(static_cast(1 + eEtaNUAPDF), "fApplyNUAPDF[eta]"); - nua.fNUAFlagsPro->GetXaxis()->SetBinLabel(static_cast(4 + ePhiNUAPDF), "fUseDefaultNUAPDF[phi]"); - nua.fNUAFlagsPro->GetXaxis()->SetBinLabel(static_cast(4 + ePtNUAPDF), "fUseDefaultNUAPDF[pt]"); - nua.fNUAFlagsPro->GetXaxis()->SetBinLabel(static_cast(4 + eEtaNUAPDF), "fUseDefaultNUAPDF[eta]"); + nua.fNUAFlagsPro->GetXaxis()->SetBinLabel(static_cast(1 + eChargeNUAPDF), "fApplyNUAPDF[charge]"); + nua.fNUAFlagsPro->GetXaxis()->SetBinLabel(static_cast(5 + ePhiNUAPDF), "fUseDefaultNUAPDF[phi]"); + nua.fNUAFlagsPro->GetXaxis()->SetBinLabel(static_cast(5 + ePtNUAPDF), "fUseDefaultNUAPDF[pt]"); + nua.fNUAFlagsPro->GetXaxis()->SetBinLabel(static_cast(5 + eEtaNUAPDF), "fUseDefaultNUAPDF[eta]"); + nua.fNUAFlagsPro->GetXaxis()->SetBinLabel(static_cast(5 + eChargeNUAPDF), "fUseDefaultNUAPDF[charge]"); // ... @@ -6452,9 +6629,11 @@ void bookNUAHistograms() yAxisTitle += TString::Format("%d:fApplyNUAPDF[phi]; ", static_cast(1 + ePhiNUAPDF)); yAxisTitle += TString::Format("%d:fApplyNUAPDF[pt]; ", static_cast(1 + ePtNUAPDF)); yAxisTitle += TString::Format("%d:fApplyNUAPDF[eta]; ", static_cast(1 + eEtaNUAPDF)); - yAxisTitle += TString::Format("%d:fUseDefaultNUAPDF[phi]; ", static_cast(4 + ePhiNUAPDF)); - yAxisTitle += TString::Format("%d:fUseDefaultNUAPDF[pt]; ", static_cast(4 + ePtNUAPDF)); - yAxisTitle += TString::Format("%d:fUseDefaultNUAPDF[eta]; ", static_cast(4 + eEtaNUAPDF)); + yAxisTitle += TString::Format("%d:fApplyNUAPDF[charge]; ", static_cast(1 + eChargeNUAPDF)); + yAxisTitle += TString::Format("%d:fUseDefaultNUAPDF[phi]; ", static_cast(5 + ePhiNUAPDF)); + yAxisTitle += TString::Format("%d:fUseDefaultNUAPDF[pt]; ", static_cast(5 + ePtNUAPDF)); + yAxisTitle += TString::Format("%d:fUseDefaultNUAPDF[eta]; ", static_cast(5 + eEtaNUAPDF)); + yAxisTitle += TString::Format("%d:fUseDefaultNUAPDF[charge]; ", static_cast(5 + eChargeNUAPDF)); // ... @@ -6481,26 +6660,32 @@ void bookNUAHistograms() if (nua.fApplyNUAPDF[eEtaNUAPDF]) { nua.fNUAFlagsPro->Fill(static_cast(1 + eEtaNUAPDF), 1.); } + if (nua.fApplyNUAPDF[eChargeNUAPDF]) { + nua.fNUAFlagsPro->Fill(static_cast(1 + eChargeNUAPDF), 1.); + } if (nua.fUseDefaultNUAPDF[ePhiNUAPDF]) { - nua.fNUAFlagsPro->Fill(static_cast(4 + ePhiNUAPDF), 1.); + nua.fNUAFlagsPro->Fill(static_cast(5 + ePhiNUAPDF), 1.); } if (nua.fUseDefaultNUAPDF[ePtNUAPDF]) { - nua.fNUAFlagsPro->Fill(static_cast(4 + ePtNUAPDF), 1.); + nua.fNUAFlagsPro->Fill(static_cast(5 + ePtNUAPDF), 1.); } if (nua.fUseDefaultNUAPDF[eEtaNUAPDF]) { - nua.fNUAFlagsPro->Fill(static_cast(4 + eEtaNUAPDF), 1.); + nua.fNUAFlagsPro->Fill(static_cast(5 + eEtaNUAPDF), 1.); + } + if (nua.fUseDefaultNUAPDF[eChargeNUAPDF]) { + nua.fNUAFlagsPro->Fill(static_cast(5 + eChargeNUAPDF), 1.); } nua.fNUAList->Add(nua.fNUAFlagsPro); - if (!(nua.fApplyNUAPDF[ePhiNUAPDF] || nua.fApplyNUAPDF[ePtNUAPDF] || nua.fApplyNUAPDF[eEtaNUAPDF])) { + if (!(nua.fApplyNUAPDF[ePhiNUAPDF] || nua.fApplyNUAPDF[ePtNUAPDF] || nua.fApplyNUAPDF[eEtaNUAPDF] || nua.fApplyNUAPDF[eChargeNUAPDF])) { return; } // b) Common local labels: - TString sVariable[eNUAPDF_N] = {"#varphi", "p_{t}", "#eta"}; // has to be in sync with the ordering of enum eNUAPDF + TString sVariable[eNUAPDF_N] = {"#varphi", "p_{t}", "#eta", "charge"}; // has to be in sync with the ordering of enum eNUAPDF // c) Histograms: - for (int pdf = 0; pdf < eNUAPDF_N; pdf++) // use pdfs for NUA in (phi, pt, eta, ...) + for (int pdf = 0; pdf < eNUAPDF_N; pdf++) // use pdfs for NUA in (phi, pt, eta, charge, ...) { if (!nua.fCustomNUAPDF[pdf]) // yes, because these histos are cloned from the external ones, see void SetNUAPDF(TH1D* const hist, const char* variable); { @@ -6547,7 +6732,7 @@ void bookNUAHistograms() if (!nua.fApplyNUAPDF[eEtaNUAPDF]) { continue; } - // Define default detector acceptance in pseudorapidity: One sectors, with probability < 1. + // Define default detector acceptance in pseudorapidity: One sector, with probability < 1. double dSector[2] = {0.2, 0.6}; // sector is defined as 0.2 < eta < 0.6 double dProbability = 0.2; // probability, so after being set this way, only 20% of particles in that sector are reconstructed nua.fDefaultNUAPDF[eEtaNUAPDF] = new TF1(TString::Format("fDefaultNUAPDF[%d]", eEtaNUAPDF), "1.-(x>=[0])*(1.-[2]) + (x>=[1])*(1.-[2])", @@ -6556,6 +6741,21 @@ void bookNUAHistograms() nua.fDefaultNUAPDF[eEtaNUAPDF]->SetParameter(1, dSector[1]); nua.fDefaultNUAPDF[eEtaNUAPDF]->SetParameter(2, dProbability); nua.fNUAList->Add(nua.fDefaultNUAPDF[eEtaNUAPDF]); + } else if (sVariable[pdf].EqualTo("charge")) { + + // *) default NUA for charge pdf: + if (!nua.fApplyNUAPDF[eChargeNUAPDF]) { + continue; + } + // Define default detector acceptance in charge: Particles with negative charge, I take with probability 50% + double dSector[2] = {-1., 0.}; // nua sector is defined for charge in the range -1. < charge < 0. + double dProbability = 0.5; // probability, so after being set this way, only 50% of particles in that sector are reconstructed + nua.fDefaultNUAPDF[eChargeNUAPDF] = new TF1(TString::Format("fDefaultNUAPDF[%d]", eChargeNUAPDF), "1.-(x>=[0])*(1.-[2]) + (x>=[1])*(1.-[2])", + ph.fParticleHistogramsBins[eCharge][1], ph.fParticleHistogramsBins[eCharge][2]); + nua.fDefaultNUAPDF[eChargeNUAPDF]->SetParameter(0, dSector[0]); + nua.fDefaultNUAPDF[eChargeNUAPDF]->SetParameter(1, dSector[1]); + nua.fDefaultNUAPDF[eChargeNUAPDF]->SetParameter(2, dProbability); + nua.fNUAList->Add(nua.fDefaultNUAPDF[eChargeNUAPDF]); } else { LOGF(fatal, "\033[1;31m%s at line %d : pdf = %s is not supported (yet)\n \033[0m", __FUNCTION__, __LINE__, sVariable[pdf].Data()); } @@ -6579,7 +6779,7 @@ void bookNUAHistograms() nua.fMaxValuePDF[pdf] = nua.fDefaultNUAPDF[pdf]->GetMaximum(ph.fParticleHistogramsBins[pdf][1], ph.fParticleHistogramsBins[pdf][2]); } - } // for(int pdf=0;pdfSetParameter(1, 0.04); // v1 = 0.04 = const in this parameterization fPhiPDF->SetParameter(3, 0.06); // v3 = 0.06 = const in this parameterization // Amplitude v2(pt) and reaction plane are pbyp set ebye in the loop below - } else if (iv.fHarmonicsOptionInternalValidation->EqualTo("ptEtaDependent")) { - // For this option, one selected vn harmonic (v2) depends both on pT and eta. - // pt dependence is the same as defined in Eq. (32) in arXiv:1312.3572 - // eta dependence is defined as 0.4 - (1/4) eta^2, so that v2(eta) = 0.24 at eta = +-0.8, and v2(eta) = 0.4 at eta = 0 (keep in sync with details below, when I am sampling pt and eta) - // to increase significance, I multiply by factor of 2 the sampled v2(pt,eta) (see the formula below when sampling) - // I still use constant v1 = 0.04 and v3 = 0.06 in this example + one common reaction plane. + } else if (iv.fHarmonicsOptionInternalValidation->EqualTo("ptEtaDependent") || iv.fHarmonicsOptionInternalValidation->EqualTo("ptEtaChargeDependent")) { + // a) "ptEtaDependent": + // For this option, one selected vn harmonic (v2) depends both on pT and eta. + // pt dependence is the same as defined in Eq. (32) in arXiv:1312.3572 + // eta dependence is defined as 0.4 - (1/4) eta^2, so that v2(eta) = 0.24 at eta = +-0.8, and v2(eta) = 0.4 at eta = 0 (keep in sync with details below, when I am sampling pt and eta) + // to increase significance, I multiply by factor of 2 the sampled v2(pt,eta) (see the formula below when sampling) + // I still use constant v1 = 0.04 and v3 = 0.06 in this example + one common reaction plane. + + // b) "ptEtaChargeDependent": + // For this option, one selected vn harmonic (v2) depends on pT, eta and charge. + // pt and eta dependence, and all other settings are the same as in the option "ptEtaDependent" + // The only difference in this option that for particles with positive charge, I downscale their v2 by 25%, i.e. v2(positive) = 0.75 v2 (negative), everything else is the same. + // Therefore, I can use the same config here both for "ptEtaDependent" and "ptEtaChargeDependent", the charge dependence I introduce later in the loop below // Azimuthal angles are sampled from this pdf: fPhiPDF = new TF1("fPhiPDF", "1 + 2.*[1]*std::cos(x-[0]) + 2.*[2]*std::cos(2.*(x-[0])) + 2.*[3]*std::cos(3.*(x-[0]))", 0., o2::constants::math::TwoPI); @@ -6944,7 +7159,7 @@ void InternalValidation() // Set constant parameters here: fPhiPDF->SetParameter(1, 0.04); // v1 = 0.04 = const in this parameterization fPhiPDF->SetParameter(3, 0.06); // v3 = 0.06 = const in this parameterization - // Amplitude v2(pt,eta) and reaction plane are pbyp set ebye in the loop below + // Amplitude v2(pt,eta) for option "ptEtaDependent" and amplitude v2(pt,eta,charge) for option "ptEtaChargeDependent", and reaction plane are pbyp set ebye in the loop below } // b) Loop over on-the-fly events: @@ -6969,7 +7184,7 @@ void InternalValidation() fPhiPDF->SetParameter(3, fReactionPlane); } else if (iv.fHarmonicsOptionInternalValidation->EqualTo("ptDependent")) { fPhiPDF->SetParameter(0, fReactionPlane); - } else if (iv.fHarmonicsOptionInternalValidation->EqualTo("ptEtaDependent")) { + } else if (iv.fHarmonicsOptionInternalValidation->EqualTo("ptEtaDependent") || iv.fHarmonicsOptionInternalValidation->EqualTo("ptEtaChargeDependent")) { fPhiPDF->SetParameter(0, fReactionPlane); } // Remark: I do not need here anything for option "persistent", because RP is not used for that case. See below how 3 symmetry planes are introduced with persistent correlation @@ -7070,7 +7285,7 @@ void InternalValidation() float fV2vsPtMax = 0.3; // v2(pt): for pt < fV2vsPtCutOff v2 increases linearly, for pt >= fV2vsPtCutOff v2 = fV2vsPtMax, see Eq. (32) in arXiv:1312.3572 pbyp.fPt < fV2vsPtCutOff ? fPhiPDF->SetParameter(2, pbyp.fPt * fV2vsPtMax / fV2vsPtCutOff) : fPhiPDF->SetParameter(2, fV2vsPtMax); - } else if (iv.fHarmonicsOptionInternalValidation->EqualTo("ptEtaDependent")) { + } else if (iv.fHarmonicsOptionInternalValidation->EqualTo("ptEtaDependent") || iv.fHarmonicsOptionInternalValidation->EqualTo("ptEtaChargeDependent")) { float fV2vsPtCutOff = 2.0; // TBI 20250729 I could add configurables for these 2 variables at some point, otherwise, simply hardwire the constants in the expression below float fV2vsPtMax = 0.3; // TBI 20250729 I shall NOT use f to name these two variables, rename eventually // pt dependence: for pt < fV2vsPtCutOff v2 increases linearly, for pt >= fV2vsPtCutOff v2 = fV2vsPtMax, see Eq. (32) in arXiv:1312.3572 @@ -7081,7 +7296,14 @@ void InternalValidation() if (v2 < 0. || v2 > 0.5) { LOGF(fatal, "\033[1;31m%s at line %d : v2 = %f\033[0m", __FUNCTION__, __LINE__, v2); } - fPhiPDF->SetParameter(2, v2); // set v2(pt,eta) for this particle + if (iv.fHarmonicsOptionInternalValidation->EqualTo("ptEtaDependent")) { + fPhiPDF->SetParameter(2, v2); // set v2(pt,eta) for this particle + } else if (iv.fHarmonicsOptionInternalValidation->EqualTo("ptEtaChargeDependent")) { + if (pbyp.fCharge > 0.) { + v2 *= 0.75; // trim down by 25% only v2 of positive particles in this toy model + } + fPhiPDF->SetParameter(2, v2); // set v2(pt,eta,charge) for this particle + } } // Finally, sample particle angle: @@ -7119,6 +7341,14 @@ void InternalValidation() double vector[eDiffEtaWeights_N] = {pbyp.fEta, pbyp.fPt, pbyp.fCharge, ebye.fCentrality}; ph.fParticleSparseHistograms[eDWEta][eSim][eBefore]->Fill(vector); } + + // **) eDWCharge : here the fundamental 0-th axis never to be projected out is "charge" + if (ph.fBookParticleSparseHistograms[eDWCharge]) { + // Remark: It is mandatory that ordering in initialization here resembles the ordering in enum eDiffChargeWeights + double vector[eDiffChargeWeights_N] = {pbyp.fCharge, pbyp.fPt, pbyp.fEta, ebye.fCentrality}; + ph.fParticleSparseHistograms[eDWCharge][eSim][eBefore]->Fill(vector); + } + } // ph.fFillParticleSparseHistogramsBeforeCuts } // if (ph.fFillParticleHistograms || ph.fFillParticleHistograms2D) @@ -7156,6 +7386,9 @@ void InternalValidation() if (nua.fApplyNUAPDF[eEtaNUAPDF] && !Accept(pbyp.fEta, eEtaNUAPDF)) { continue; } + if (nua.fApplyNUAPDF[eChargeNUAPDF] && !Accept(pbyp.fCharge, eChargeNUAPDF)) { + continue; + } // *) Fill few selected particle histograms after cuts here directly here: // Remark: I do not call FillParticleHistograms(track, eAfter), as I do not want to bother to make here full 'track' object, etc., just to fill simple kine info: @@ -7187,6 +7420,12 @@ void InternalValidation() double vector[eDiffEtaWeights_N] = {pbyp.fEta, pbyp.fPt, pbyp.fCharge, ebye.fCentrality}; ph.fParticleSparseHistograms[eDWEta][eSim][eAfter]->Fill(vector); } + // **) eDWCharge : here the fundamental 0-th axis never to be projected out is "charge" + if (ph.fBookParticleSparseHistograms[eDWCharge]) { + // Remark: It is mandatory that ordering in initialization here resembles the ordering in enum eDiffChargeWeights + double vector[eDiffChargeWeights_N] = {pbyp.fCharge, pbyp.fPt, pbyp.fEta, ebye.fCentrality}; + ph.fParticleSparseHistograms[eDWCharge][eSim][eAfter]->Fill(vector); + } } // if (ph.fFillParticleHistograms || ph.fFillParticleHistograms2D) // Remark: Keep in sync all calls and flags below with the ones in MainLoopOverParticles(). @@ -7295,8 +7534,8 @@ bool Accept(const double& value, int var) // Given the acceptance profile for this observable, accept or not that observable for the analysis. // Use in Toy NUA studies. - // Remark: var corresponds to the field in enum eNUAPDF { ePhiNUAPDF, ePtNUAPDF, eEtaNUAPDF }; - // Therefore, always call this function as e.g. Accept(someAngle, ePhiNUAPDF) or Accept(somePt, ePtNUAPDF) + // Remark: var corresponds to the field in enum eNUAPDF { ePhiNUAPDF, ePtNUAPDF, eEtaNUAPDF, eChargeNUAPDF }; + // Therefore, always call this function as e.g. Accept(someAngle, ePhiNUAPDF) or Accept(somePt, ePtNUAPDF), etc. if (tc.fVerboseForEachParticle) { LOGF(info, "\033[1;32m%s\033[0m", __FUNCTION__); @@ -11082,7 +11321,7 @@ bool ParticleCuts(T const& track, eCutModus cutModus) // *) Toy NUA: // TBI 20250718 Check if can optimize here something by using new global pbyp.fPhi, pbyp.fPt, etc, variables. Most likely yes, since I would avoid calling again track.phi(), etc. // But I do not use Toy NUA in any case for real large-scale data analysis. - if (nua.fApplyNUAPDF[ePhiNUAPDF] || nua.fApplyNUAPDF[ePtNUAPDF] || nua.fApplyNUAPDF[eEtaNUAPDF]) { + if (nua.fApplyNUAPDF[ePhiNUAPDF] || nua.fApplyNUAPDF[ePtNUAPDF] || nua.fApplyNUAPDF[eEtaNUAPDF] || nua.fApplyNUAPDF[eChargeNUAPDF]) { // Remark: I do not for the time being add Toy NUA cuts to particle cut counters, since in this case I can inspect direcly from phi, pt and eta distributions. @@ -11090,12 +11329,14 @@ bool ParticleCuts(T const& track, eCutModus cutModus) double dPhi = 0.; double dPt = 0.; double dEta = 0.; + double dCharge = 0.; // *) Apply Toy NUA on info available in reconstructed (and the corresponding MC truth simulated track); if constexpr (rs == eRec || rs == eRecAndSim || rs == eRec_Run2 || rs == eRecAndSim_Run2 || rs == eRec_Run1 || rs == eRecAndSim_Run1) { dPhi = track.phi(); dPt = track.pt(); dEta = track.eta(); + dCharge = track.sign(); // Apply NUA on these kine variables: if (nua.fApplyNUAPDF[ePhiNUAPDF] && !Accept(dPhi, ePhiNUAPDF)) { @@ -11107,6 +11348,9 @@ bool ParticleCuts(T const& track, eCutModus cutModus) if (nua.fApplyNUAPDF[eEtaNUAPDF] && !Accept(dEta, eEtaNUAPDF)) { return false; } + if (nua.fApplyNUAPDF[eChargeNUAPDF] && !Accept(dCharge, eChargeNUAPDF)) { + return false; + } // ... and corresponding MC truth simulated ( see https://github.com/AliceO2Group/O2Physics/blob/master/Tutorials/src/mcHistograms.cxx ): if constexpr (rs == eRecAndSim || rs == eRecAndSim_Run2 || rs == eRecAndSim_Run1) { @@ -11118,6 +11362,12 @@ bool ParticleCuts(T const& track, eCutModus cutModus) dPhi = mcParticle.phi(); dPt = mcParticle.pt(); dEta = mcParticle.eta(); + // special treatment for charge, because there is no getter mcParticle.sign() + dCharge = -44.; // yes, never initialize charge to 0. + if (tc.fDatabasePDG && tc.fDatabasePDG->GetParticle(mcParticle.pdgCode())) { + // Yes, I have to check the 2nd condition, because e.g. for PDG code 1000010020 (deuteron), GetParticle(...) returns NULL + dCharge = tc.fDatabasePDG->GetParticle(mcParticle.pdgCode())->Charge() / 3.; // yes, divided by 3. Fundamental unit of charge is associated with quarks + } // Apply NUA on these kine variables: if (nua.fApplyNUAPDF[ePhiNUAPDF] && !Accept(dPhi, ePhiNUAPDF)) { @@ -11129,6 +11379,9 @@ bool ParticleCuts(T const& track, eCutModus cutModus) if (nua.fApplyNUAPDF[eEtaNUAPDF] && !Accept(dEta, eEtaNUAPDF)) { return false; } + if (nua.fApplyNUAPDF[eChargeNUAPDF] && !Accept(dCharge, eChargeNUAPDF)) { + return false; + } } // if constexpr (rs == eRecAndSim || rs == eRecAndSim_Run2 || rs == eRecAndSim_Run1) { } // if constexpr (rs == eRec || rs == eRecAndSim || rs == eRec_Run2 || rs == eRecAndSim_Run2 || rs == eRec_Run1 || rs == eRecAndSim_Run1) { @@ -11139,6 +11392,12 @@ bool ParticleCuts(T const& track, eCutModus cutModus) dPhi = track.phi(); dPt = track.pt(); dEta = track.eta(); + // special treatment for charge, because there is no getter mcParticle.sign() + dCharge = -44.; // yes, never initialize charge to 0. + if (tc.fDatabasePDG && tc.fDatabasePDG->GetParticle(track.pdgCode())) { + // Yes, I have to check the 2nd condition, because e.g. for PDG code 1000010020 (deuteron), GetParticle(...) returns NULL + dCharge = tc.fDatabasePDG->GetParticle(track.pdgCode())->Charge() / 3.; // yes, divided by 3. Fundamental unit of charge is associated with quarks + } // Apply NUA on these kine variables: if (nua.fApplyNUAPDF[ePhiNUAPDF] && !Accept(dPhi, ePhiNUAPDF)) { @@ -11150,9 +11409,12 @@ bool ParticleCuts(T const& track, eCutModus cutModus) if (nua.fApplyNUAPDF[eEtaNUAPDF] && !Accept(dEta, eEtaNUAPDF)) { return false; } + if (nua.fApplyNUAPDF[eChargeNUAPDF] && !Accept(dCharge, eChargeNUAPDF)) { + return false; + } } // if constexpr (rs == eSim || rs == eSim_Run2 || rs == eSim_Run1) { - } // if(nua.fApplyNUAPDF[ePhiNUAPDF] || nua.fApplyNUAPDF[ePtNUAPDF] || nua.fApplyNUAPDF[eEtaNUAPDF]) { + } // if(nua.fApplyNUAPDF[ePhiNUAPDF] || nua.fApplyNUAPDF[ePtNUAPDF] || nua.fApplyNUAPDF[eEtaNUAPDF] || nua.fApplyNUAPDF[eChargeNUAPDF]) { return true; @@ -11295,6 +11557,12 @@ void FillParticleHistograms(T const& track, eBeforeAfter ba, int weight = 1) double vector[eDiffEtaWeights_N] = {track.eta(), track.pt(), static_cast(track.sign()), ebye.fCentrality}; ph.fParticleSparseHistograms[eDWEta][eRec][ba]->Fill(vector, weight); } + // **) eDWCharge : here the fundamental 0-th axis never to be projected out is "charge" + if (ph.fBookParticleSparseHistograms[eDWCharge]) { + // Remark: It is mandatory that ordering in initialization here resembles the ordering in enum eDiffChargeWeights + double vector[eDiffChargeWeights_N] = {static_cast(track.sign()), track.pt(), track.eta(), ebye.fCentrality}; + ph.fParticleSparseHistograms[eDWCharge][eRec][ba]->Fill(vector, weight); + } } // if (ba == eAfter ... ) { // QA: @@ -11459,6 +11727,20 @@ void FillParticleHistograms(T const& track, eBeforeAfter ba, int weight = 1) double vector[eDiffEtaWeights_N] = {mcParticle.eta(), mcParticle.pt(), charge, ebye.fCentralitySim}; ph.fParticleSparseHistograms[eDWEta][eSim][ba]->Fill(vector, weight); } + // **) eDWCharge : here the fundamental 0-th axis never to be projected out is "charge" + if (ph.fBookParticleSparseHistograms[eDWCharge]) { + // Remark: It is mandatory that ordering in initialization here resembles the ordering in enum eDiffChargeWeights + + // special treatment for charge, because there is no getter mcParticle.sign() + double charge = -44.; // yes, never initialize charge to 0. + if (tc.fDatabasePDG && tc.fDatabasePDG->GetParticle(mcParticle.pdgCode())) { + // Yes, I have to check the 2nd condition, because e.g. for PDG code 1000010020 (deuteron), GetParticle(...) returns NULL + charge = tc.fDatabasePDG->GetParticle(mcParticle.pdgCode())->Charge() / 3.; // yes, divided by 3. Fundamental unit of charge is associated with quarks + } + double vector[eDiffChargeWeights_N] = {charge, mcParticle.pt(), mcParticle.eta(), ebye.fCentralitySim}; + ph.fParticleSparseHistograms[eDWCharge][eSim][ba]->Fill(vector, weight); + } + } // if (ba == eAfter ... ) { } // if constexpr (rs == eRecAndSim || rs == eRecAndSim_Run2 || rs == eRecAndSim_Run1) { @@ -13263,6 +13545,7 @@ void FillNestedLoopsContainers(const int& particleIndex) double wPhi = 1.; double wPt = 1.; double wEta = 1.; + double wCharge = 1.; if (pw.fUseDiffPhiWeights[wPhiPhiAxis]) { // yes, 0th axis serves as a common boolean for this category wPhi = WeightFromSparse(eDWPhi); @@ -13276,6 +13559,10 @@ void FillNestedLoopsContainers(const int& particleIndex) wEta = WeightFromSparse(eDWEta); } + if (pw.fUseDiffChargeWeights[wChargeChargeAxis]) { // yes, 0th axis serves as a common boolean for this category + wCharge = WeightFromSparse(eDWCharge); + } + if (pw.fUseWeights[wPHI]) { // TBI 20260216 obsolete, remove eventually wPhi = Weight(pbyp.fPhi, wPHI); } @@ -13288,7 +13575,7 @@ void FillNestedLoopsContainers(const int& particleIndex) wEta = Weight(pbyp.fEta, wETA); } - nl.ftaNestedLoops[1]->AddAt(wPhi * wPt * wEta, particleIndex); // remember that the 2nd argument here must start from 0 + nl.ftaNestedLoops[1]->AddAt(wPhi * wPt * wEta * wCharge, particleIndex); // remember that the 2nd argument here must start from 0 } if (tc.fVerbose) { @@ -14108,7 +14395,7 @@ void insanitizeDiffWeightsSparse(THnSparseF* const sparse) LOGF(fatal, "\033[1;31m%s at line %d : axis %d (#eta) of sparse %s has upper boundary %f, while upper cut on that variable is %f. This means that for some particles I won't be able to fetch weights from this sparse. \033[0m", __FUNCTION__, __LINE__, d, sparse->GetName(), sparse->GetAxis(d)->GetBinUpEdge(sparse->GetAxis(d)->GetNbins()), pc.fdParticleCuts[eEta][eMax]); } - } else if (!axisTitle.compare("Charge")) { + } else if (!axisTitle.compare("Charge") || !axisTitle.compare("charge")) { // check lower boundary: if ((pc.fdParticleCuts[eCharge][eMin] < sparse->GetAxis(d)->GetBinLowEdge(1)) && (std::abs(sparse->GetAxis(d)->GetBinLowEdge(1) - pc.fdParticleCuts[eCharge][eMin]) > tc.fFloatingPointPrecision)) { @@ -14551,7 +14838,7 @@ THnSparseF* GetSparseHistogramWithWeights(const char* filePath, const char* runN // b) Basic protection for arguments: // Remark: below I do one more specific check. - if (!(TString(whichCategory).EqualTo("phi") || TString(whichCategory).EqualTo("pt") || TString(whichCategory).EqualTo("eta"))) { + if (!(TString(whichCategory).EqualTo("phi") || TString(whichCategory).EqualTo("pt") || TString(whichCategory).EqualTo("eta") || TString(whichCategory).EqualTo("charge"))) { LOGF(fatal, "\033[1;31m%s at line %d\033[0m", __FUNCTION__, __LINE__); } if (TString(whichDimensions).EqualTo("")) { @@ -14712,6 +14999,8 @@ THnSparseF* GetSparseHistogramWithWeights(const char* filePath, const char* runN } if (!sparseHist) { + LOGF(info, "\033[1;33m%s at line %d : filePath = \"%s\"\033[0m", __FUNCTION__, __LINE__, filePath); + LOGF(info, "\033[1;33m%s at line %d : runNumber = \"%s\"\033[0m", __FUNCTION__, __LINE__, runNumber); listWithRuns->ls(); LOGF(fatal, "\033[1;31m%s at line %d : couldn't fetch sparse histogram with name = %s from this list\033[0m", __FUNCTION__, __LINE__, sparseHistName.Data()); } @@ -15763,7 +16052,10 @@ double WeightFromSparse(eDiffWeightCategory dwc) if (tc.fVerbose) { StartFunction(__FUNCTION__); - } + LOGF(info, "\033[1;31m dwc = %d\033[0m", static_cast(dwc)); + LOGF(info, "\033[1;31m%s at line %d : printing current status of all weights flags\033[0m", __FUNCTION__, __LINE__); + PrintAllWeightsFlags(); + } // if (tc.fVerbose) { // *) Reduce dimensionality if possible, i.e. look up only the dimensions in sparse histogram which were requested in this analysis: int dim = 1; // yes, because dimension 0 is always reserved for each category @@ -15792,6 +16084,9 @@ double WeightFromSparse(eDiffWeightCategory dwc) case eDWPt: { pw.fFindBinVector[dwc]->AddAt(pbyp.fPt, 0); // special treatment for pt in eDWPt category // Remember that ordering here has to resemble ordering in eDiffPtWeights + if (pw.fUseDiffPtWeights[wPtEtaAxis]) { + pw.fFindBinVector[dwc]->AddAt(pbyp.fEta, dim++); + } if (pw.fUseDiffPtWeights[wPtChargeAxis]) { pw.fFindBinVector[dwc]->AddAt(pbyp.fCharge, dim++); } @@ -15807,12 +16102,30 @@ double WeightFromSparse(eDiffWeightCategory dwc) if (pw.fUseDiffEtaWeights[wEtaChargeAxis]) { pw.fFindBinVector[dwc]->AddAt(pbyp.fCharge, dim++); } + if (pw.fUseDiffEtaWeights[wEtaPtAxis]) { + pw.fFindBinVector[dwc]->AddAt(pbyp.fPt, dim++); + } if (pw.fUseDiffEtaWeights[wEtaCentralityAxis]) { pw.fFindBinVector[dwc]->AddAt(ebye.fCentrality, dim++); } // ... break; } + case eDWCharge: { + pw.fFindBinVector[dwc]->AddAt(pbyp.fCharge, 0); // special treatment for charge in eDWCharge category + // Remember that ordering here has to resemble ordering in eDiffChargeWeights + if (pw.fUseDiffChargeWeights[wChargePtAxis]) { + pw.fFindBinVector[dwc]->AddAt(pbyp.fPt, dim++); + } + if (pw.fUseDiffChargeWeights[wChargeEtaAxis]) { + pw.fFindBinVector[dwc]->AddAt(pbyp.fEta, dim++); + } + if (pw.fUseDiffChargeWeights[wChargeCentralityAxis]) { + pw.fFindBinVector[dwc]->AddAt(ebye.fCentrality, dim++); + } + // ... + break; + } default: { LOGF(fatal, "\033[1;31m%s at line %d : This differential weight category, dwc = %d, is not supported yet. \033[0m", __FUNCTION__, __LINE__, static_cast(dwc)); break; @@ -15972,7 +16285,8 @@ void GetParticleWeights() // b) Differential weights; => TBI 20250225 this is now obsolete and superseeded with c), where I use more general approach with sparse histograms // c) Differential phi weights using sparse histograms; // d) Differential pt weights using sparse histograms; - // e) Differential eta weights using sparse histograms. + // e) Differential eta weights using sparse histograms; + // f) Differential charge weights using sparse histograms. if (tc.fVerbose) { StartFunction(__FUNCTION__); @@ -16170,6 +16484,39 @@ void GetParticleWeights() } // if (pw.fUseDiffEtaWeights[wEtaEtaAxis]) { + // f) Differential charge weights using sparse histograms: + if (pw.fUseDiffChargeWeights[wChargeChargeAxis]) { // yes, remember that flag for charge axis serves also as a common boolean to switch off all differential charge weights + + TString whichCategory = "charge"; // differential charge weights + + TString whichDimensions = ""; // differential charge weights as a function of particular dimension + // Remark: the naming convention hardwired here for axes dimensions have to be in sync with what I have in the macro to make these weights. + if (pw.fUseDiffChargeWeights[wChargePtAxis]) { + whichDimensions += "_pt"; + } + if (pw.fUseDiffChargeWeights[wChargeEtaAxis]) { + whichDimensions += "_eta"; + } + if (pw.fUseDiffChargeWeights[wChargeCentralityAxis]) { + whichDimensions += "_centrality"; + } + // ... + + THnSparseF* diffWeightsSparse = GetSparseHistogramWithWeights(pw.fFileWithWeights.Data(), tc.fRunNumber.Data(), whichCategory.Data(), whichDimensions.Data()); + if (!diffWeightsSparse) { + LOGF(fatal, "\033[1;31m%s at line %d : diffWeightsSparse for category \"charge\" is NULL. Check the external file %s with particle weights\033[0m", __FUNCTION__, __LINE__, pw.fFileWithWeights.Data()); + } + + // Check if particle weights are avaiable for the phase window I have selected for each dimension with cuts. + // Basically, I check whether range of each axis is compatible with the cuts i used for variable on that axis. + // Since GetParticleWeights() is called only once, this check is also performed only once. + insanitizeDiffWeightsSparse(diffWeightsSparse); + + // okay, just use this sparse histogram with weights: + SetDiffWeightsSparse(diffWeightsSparse, eDWCharge); + + } // if (pw.fUseDiffChargeWeights[wChargeChargeAxis]) { + if (tc.fVerbose) { ExitFunction(__FUNCTION__); } @@ -18146,13 +18493,14 @@ void FillQvectorFromSparse() double wPhi = 1.; // differential multidimensional phi weight, its dimensions are defined via enum eDiffPhiWeights double wPt = 1.; // differential multidimensional pt weight, its dimensions are defined via enum eDiffPtWeights double wEta = 1.; // differential multidimensional eta weight, its dimensions are defined via enum eDiffEtaWeights + double wCharge = 1.; // differential multidimensional charge weight, its dimensions are defined via enum eDiffChargeWeights double wToPowerP = 1.; // weight raised to power p // *) Multidimensional phi weights: if (pw.fUseDiffPhiWeights[wPhiPhiAxis]) { // yes, 0th axis serves as a common boolean for this category wPhi = WeightFromSparse(eDWPhi); if (!(wPhi > 0.)) { - LOGF(error, "\033[1;33m%s wPhi is not positive\033[0m", __FUNCTION__); + LOGF(error, "\033[1;33m%s at line %d : wPhi is not positive\033[0m", __FUNCTION__, __LINE__); LOGF(error, "pbyp.fPhi = %f", pbyp.fPhi); if (pw.fUseDiffPhiWeights[wPhiPtAxis]) { LOGF(fatal, "pbyp.fPt = %f", pbyp.fPt); @@ -18177,8 +18525,11 @@ void FillQvectorFromSparse() if (pw.fUseDiffPtWeights[wPtPtAxis]) { // yes, 0th axis serves as a common boolean for this category wPt = WeightFromSparse(eDWPt); if (!(wPt > 0.)) { - LOGF(error, "\033[1;33m%s wPt is not positive\033[0m", __FUNCTION__); + LOGF(error, "\033[1;33m%s at line %d : wPt is not positive\033[0m", __FUNCTION__, __LINE__); LOGF(error, "pbyp.fPt = %f", pbyp.fPt); + if (pw.fUseDiffPtWeights[wPtEtaAxis]) { + LOGF(fatal, "pbyp.fEta = %f", pbyp.fEta); + } if (pw.fUseDiffPtWeights[wPtChargeAxis]) { LOGF(fatal, "pbyp.fCharge = %f", pbyp.fCharge); } @@ -18193,8 +18544,11 @@ void FillQvectorFromSparse() if (pw.fUseDiffEtaWeights[wEtaEtaAxis]) { // yes, 0th axis serves as a common boolean for this category wEta = WeightFromSparse(eDWEta); if (!(wEta > 0.)) { - LOGF(error, "\033[1;33m%s wEta is not positive\033[0m", __FUNCTION__); + LOGF(error, "\033[1;33m%s at line %d : wEta is not positive\033[0m", __FUNCTION__, __LINE__); LOGF(error, "pbyp.fEta = %f", pbyp.fEta); + if (pw.fUseDiffEtaWeights[wEtaPtAxis]) { + LOGF(fatal, "pbyp.fPt = %f", pbyp.fPt); + } if (pw.fUseDiffEtaWeights[wEtaChargeAxis]) { LOGF(fatal, "pbyp.fCharge = %f", pbyp.fCharge); } @@ -18205,11 +18559,30 @@ void FillQvectorFromSparse() } } // if(pw.fUseDiffEtaWeights[wEtaEtaAxis]) + // *) Multidimensional charge weights: + if (pw.fUseDiffChargeWeights[wChargeChargeAxis]) { // yes, 0th axis serves as a common boolean for this category + wCharge = WeightFromSparse(eDWCharge); + if (!(wCharge > 0.)) { + LOGF(error, "\033[1;33m%s at line %d : wCharge is not positive\033[0m", __FUNCTION__, __LINE__); + LOGF(error, "pbyp.fCharge = %f", pbyp.fCharge); + if (pw.fUseDiffChargeWeights[wChargePtAxis]) { + LOGF(fatal, "pbyp.fPt = %f", pbyp.fPt); + } + if (pw.fUseDiffChargeWeights[wChargeEtaAxis]) { + LOGF(fatal, "pbyp.fEta = %f", pbyp.fEta); + } + if (pw.fUseDiffChargeWeights[wChargeCentralityAxis]) { + LOGF(fatal, "ebye.fCentrality = %f", ebye.fCentrality); + } + LOGF(fatal, "Multidimensional weight for enabled dimensions is wCharge = %f", wCharge); + } + } // if(pw.fUseDiffChargeWeights[wChargeChargeAxis]) + if (qv.fCalculateQvectors) { for (int h = 0; h < gMaxHarmonic * gMaxCorrelator + 1; h++) { for (int wp = 0; wp < gMaxCorrelator + 1; wp++) { // weight power - if (pw.fUseDiffPhiWeights[wPhiPhiAxis] || pw.fUseDiffPtWeights[wPtPtAxis] || pw.fUseDiffEtaWeights[wEtaEtaAxis]) { - wToPowerP = std::pow(wPhi * wPt * wEta, wp); + if (pw.fUseDiffPhiWeights[wPhiPhiAxis] || pw.fUseDiffPtWeights[wPtPtAxis] || pw.fUseDiffEtaWeights[wEtaEtaAxis] || pw.fUseDiffChargeWeights[wChargeChargeAxis]) { + wToPowerP = std::pow(wPhi * wPt * wEta * wCharge, wp); qv.fQvector[h][wp] += TComplex(wToPowerP * std::cos(h * pbyp.fPhi), wToPowerP * std::sin(h * pbyp.fPhi)); // Q-vector with weights, legacy code (TBI 20251027 remove this line) // qv.fQvector[h][wp] += std::complex(wToPowerP * std::cos(h * pbyp.fPhi), wToPowerP * std::sin(h * pbyp.fPhi)); // Q-vector with weights, new code // TBI 20251028 I have to keep it this way for the time being, otherwise I have to change all over the place, e.g. in TComplex Q(int n, int wp), etc. @@ -18227,12 +18600,12 @@ void FillQvectorFromSparse() if (pbyp.fEta < 0.) { for (int e = 0; e < gMaxNumberEtaSeparations; e++) { if (pbyp.fEta < -1. * es.fEtaSeparationsValues[e] / 2.) { // yes, if eta separation is 0.2, then separation interval runs from -0.1 to 0.1 - qv.fMab[0][e] += wPhi * wPt * wEta; + qv.fMab[0][e] += wPhi * wPt * wEta * wCharge; for (int h = 0; h < gMaxHarmonic; h++) { if (es.fEtaSeparationsSkipHarmonics[h]) { continue; } - qv.fQabVector[0][h][e] += TComplex(wPhi * wPt * wEta * std::cos((h + 1) * pbyp.fPhi), wPhi * wPt * wEta * std::sin((h + 1) * pbyp.fPhi)); + qv.fQabVector[0][h][e] += TComplex(wPhi * wPt * wEta * wCharge * std::cos((h + 1) * pbyp.fPhi), wPhi * wPt * wEta * wCharge * std::sin((h + 1) * pbyp.fPhi)); // Remark: I can hardwire linear weights like this only for 2-p correlations // TBI 20251028 Replace TComplex with std::complex (but it's a major modification, see the comment above within if (qv.fCalculateQvectors) ) } @@ -18241,13 +18614,13 @@ void FillQvectorFromSparse() } else if (pbyp.fEta > 0.) { for (int e = 0; e < gMaxNumberEtaSeparations; e++) { if (pbyp.fEta > es.fEtaSeparationsValues[e] / 2.) { // yes, if eta separation is 0.2, then separation interval runs from -0.1 to 0.1 - qv.fMab[1][e] += wPhi * wPt * wEta; + qv.fMab[1][e] += wPhi * wPt * wEta * wCharge; for (int h = 0; h < gMaxHarmonic; h++) { { if (es.fEtaSeparationsSkipHarmonics[h]) { continue; } - qv.fQabVector[1][h][e] += TComplex(wPhi * wPt * wEta * std::cos((h + 1) * pbyp.fPhi), wPhi * wPt * wEta * std::sin((h + 1) * pbyp.fPhi)); + qv.fQabVector[1][h][e] += TComplex(wPhi * wPt * wEta * wCharge * std::cos((h + 1) * pbyp.fPhi), wPhi * wPt * wEta * wCharge * std::sin((h + 1) * pbyp.fPhi)); // TBI 20251028 Replace TComplex with std::complex (but it's a major modification, see the comment above within if (qv.fCalculateQvectors) ) // Remark: I can hardwire linear weights like this only for 2-p correlations } @@ -18898,7 +19271,7 @@ void Fillqvectors() { // In this function, I fill all requested differential q-vectors, by calling for each requested case a helper function FillqvectorFromSparse(...). - // :44 + // :fqv if (tc.fVerboseForEachParticle) { StartFunction(__FUNCTION__); @@ -18909,10 +19282,11 @@ void Fillqvectors() } // *) Local variables: - int bin = -1; // global kine bin - double wPhi = 1.; // differential multidimensional phi weight, its dimensions are defined via enum eDiffPhiWeights - double wPt = 1.; // differential multidimensional pt weight, its dimensions are defined via enum eDiffPtWeights - double wEta = 1.; // differential multidimensional eta weight, its dimensions are defined via enum eDiffEtaWeights + int bin = -1; // global kine bin + double wPhi = 1.; // differential multidimensional phi weight, its dimensions are defined via enum eDiffPhiWeights + double wPt = 1.; // differential multidimensional pt weight, its dimensions are defined via enum eDiffPtWeights + double wEta = 1.; // differential multidimensional eta weight, its dimensions are defined via enum eDiffEtaWeights + double wCharge = 1.; // differential multidimensional eta weight, its dimensions are defined via enum eDiffChargeWeights /* // TBT // TBI 20250528 check if the test below is computationally heavy. If so, add the flag tc.fInsanityCheckForEachParticle here. @@ -18938,9 +19312,17 @@ void Fillqvectors() if (pw.fUseDiffPtWeights[wPtPtAxis]) { wPt = WeightFromSparse(eDWPt); } + // w_eta(pt): + if (pw.fUseDiffEtaWeights[wEtaPtAxis]) { + wEta = WeightFromSparse(eDWEta); + } + // w_charge(pt): + if (pw.fUseDiffChargeWeights[wChargePtAxis]) { + wCharge = WeightFromSparse(eDWCharge); + } // ****) finally, fill: - FillqvectorFromSparse(PTq, bin, wPhi * wPt * wEta); // weighted q(pT) filled for global bin to which this pT corresponds + FillqvectorFromSparse(PTq, bin, wPhi * wPt * wEta * wCharge); // weighted q(pT) filled for global bin to which this pT corresponds } // if(tc.fCalculateAsFunctionOf[AFO_PT]) @@ -18955,13 +19337,21 @@ void Fillqvectors() if (pw.fUseDiffPhiWeights[wPhiEtaAxis]) { wPhi = WeightFromSparse(eDWPhi); } + // w_pt(eta): + if (pw.fUseDiffPtWeights[wPtEtaAxis]) { + wPt = WeightFromSparse(eDWPt); + } // w_eta(eta): if (pw.fUseDiffEtaWeights[wEtaEtaAxis]) { wEta = WeightFromSparse(eDWEta); } + // w_charge(eta): + if (pw.fUseDiffChargeWeights[wChargeEtaAxis]) { + wCharge = WeightFromSparse(eDWCharge); + } // ****) finally, fill: - FillqvectorFromSparse(ETAq, bin, wPhi * wPt * wEta); // weighted q(eta) filled for global bin to which this eta corresponds + FillqvectorFromSparse(ETAq, bin, wPhi * wPt * wEta * wCharge); // weighted q(eta) filled for global bin to which this eta corresponds } // if (mupa.fCalculateCorrelationsAsFunctionOf[AFO_ETA] || t0.fCalculateTest0AsFunctionOf[AFO_ETA]) @@ -18978,15 +19368,19 @@ void Fillqvectors() } // w_pt(charge): if (pw.fUseDiffPtWeights[wPtChargeAxis]) { - wPt = WeightFromSparse(eDWPhi); + wPt = WeightFromSparse(eDWPt); } // w_eta(charge): if (pw.fUseDiffEtaWeights[wEtaChargeAxis]) { - wEta = WeightFromSparse(eDWPhi); + wEta = WeightFromSparse(eDWEta); + } + // w_charge(charge): + if (pw.fUseDiffChargeWeights[wChargeChargeAxis]) { + wCharge = WeightFromSparse(eDWCharge); } // ****) finally, fill: - FillqvectorFromSparse(CHARGEq, bin, wPhi * wPt * wEta); // weighted q(charge) filled for global bin to which this charge corresponds + FillqvectorFromSparse(CHARGEq, bin, wPhi * wPt * wEta * wCharge); // weighted q(charge) filled for global bin to which this charge corresponds } // if (mupa.fCalculateCorrelationsAsFunctionOf[AFO_CHARGE] || t0.fCalculateTest0AsFunctionOf[AFO_CHARGE]) @@ -19005,8 +19399,23 @@ void Fillqvectors() wPhi = WeightFromSparse(eDWPhi); } + // w_pt(pt,eta): + if (pw.fUseDiffPtWeights[wPtPtAxis] && pw.fUseDiffPtWeights[wPtEtaAxis]) { + wPt = WeightFromSparse(eDWPt); + } + + // w_eta(pt,eta): + if (pw.fUseDiffEtaWeights[wEtaPtAxis] && pw.fUseDiffEtaWeights[wEtaEtaAxis]) { + wEta = WeightFromSparse(eDWEta); + } + + // w_charge(pt,eta): + if (pw.fUseDiffChargeWeights[wChargePtAxis] && pw.fUseDiffChargeWeights[wChargeEtaAxis]) { + wCharge = WeightFromSparse(eDWCharge); + } + // ****) finally, fill: - FillqvectorFromSparse(PT_ETAq, bin, wPhi * wPt * wEta); // weighted q(pt,eta) filled for global bin to which this (pt,eta) corresponds + FillqvectorFromSparse(PT_ETAq, bin, wPhi * wPt * wEta * wCharge); // weighted q(pt,eta) filled for global bin to which this (pt,eta) corresponds } // if (t0.fCalculate2DTest0AsFunctionOf[AFO_PT_ETA] || t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_PT_ETA]) @@ -19021,9 +19430,21 @@ void Fillqvectors() if (pw.fUseDiffPhiWeights[wPhiPtAxis] && pw.fUseDiffPhiWeights[wPhiChargeAxis]) { wPhi = WeightFromSparse(eDWPhi); } + // w_pt(pt,charge): + if (pw.fUseDiffPtWeights[wPtPtAxis] && pw.fUseDiffPtWeights[wPtChargeAxis]) { + wPt = WeightFromSparse(eDWPt); + } + // w_eta(pt,charge): + if (pw.fUseDiffEtaWeights[wEtaPtAxis] && pw.fUseDiffEtaWeights[wEtaChargeAxis]) { + wEta = WeightFromSparse(eDWEta); + } + // w_charge(pt,charge): + if (pw.fUseDiffChargeWeights[wChargePtAxis] && pw.fUseDiffChargeWeights[wChargeChargeAxis]) { + wCharge = WeightFromSparse(eDWCharge); + } // ****) finally, fill: - FillqvectorFromSparse(PT_CHARGEq, bin, wPhi * wPt * wEta); // weighted q(pt,charge) filled for global bin to which this (pt,charge) corresponds + FillqvectorFromSparse(PT_CHARGEq, bin, wPhi * wPt * wEta * wCharge); // weighted q(pt,charge) filled for global bin to which this (pt,charge) corresponds } // if (t0.fCalculate2DTest0AsFunctionOf[AFO_PT_CHARGE] || t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_PT_CHARGE]) @@ -19035,12 +19456,24 @@ void Fillqvectors() // ****) determine all supported particle weights: // w_phi(eta,charge): - if (pw.fUseDiffPhiWeights[wEtaChargeAxis] && pw.fUseDiffPhiWeights[wPhiChargeAxis]) { + if (pw.fUseDiffPhiWeights[wPhiEtaAxis] && pw.fUseDiffPhiWeights[wPhiChargeAxis]) { wPhi = WeightFromSparse(eDWPhi); } + // w_pt(eta,charge): + if (pw.fUseDiffPtWeights[wPtEtaAxis] && pw.fUseDiffPtWeights[wPtChargeAxis]) { + wPt = WeightFromSparse(eDWPt); + } + // w_eta(eta,charge): + if (pw.fUseDiffEtaWeights[wEtaEtaAxis] && pw.fUseDiffEtaWeights[wEtaChargeAxis]) { + wEta = WeightFromSparse(eDWEta); + } + // w_charge(eta,charge): + if (pw.fUseDiffChargeWeights[wChargeEtaAxis] && pw.fUseDiffChargeWeights[wChargeChargeAxis]) { + wCharge = WeightFromSparse(eDWCharge); + } // ****) finally, fill: - FillqvectorFromSparse(ETA_CHARGEq, bin, wPhi * wPt * wEta); // weighted q(eta,charge) filled in global bin to which this (eta,charge) corresponds + FillqvectorFromSparse(ETA_CHARGEq, bin, wPhi * wPt * wEta * wCharge); // weighted q(eta,charge) filled in global bin to which this (eta,charge) corresponds } // if (t0.fCalculate2DTest0AsFunctionOf[AFO_ETA_CHARGE] || t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_ETA_CHARGE]) @@ -19059,9 +19492,21 @@ void Fillqvectors() if (pw.fUseDiffPhiWeights[wPhiPtAxis] && pw.fUseDiffPhiWeights[wPhiEtaAxis] && pw.fUseDiffPhiWeights[wPhiChargeAxis]) { wPhi = WeightFromSparse(eDWPhi); } + // w_pt(pt,eta,charge): + if (pw.fUseDiffPtWeights[wPtPtAxis] && pw.fUseDiffPtWeights[wPtEtaAxis] && pw.fUseDiffPtWeights[wPtChargeAxis]) { + wPt = WeightFromSparse(eDWPt); + } + // w_eta(pt,eta,charge): + if (pw.fUseDiffEtaWeights[wEtaPtAxis] && pw.fUseDiffEtaWeights[wEtaEtaAxis] && pw.fUseDiffEtaWeights[wEtaChargeAxis]) { + wEta = WeightFromSparse(eDWEta); + } + // w_charge(pt,eta,charge): + if (pw.fUseDiffChargeWeights[wChargePtAxis] && pw.fUseDiffChargeWeights[wChargeEtaAxis] && pw.fUseDiffChargeWeights[wChargeChargeAxis]) { + wCharge = WeightFromSparse(eDWCharge); + } // ****) finally, fill: - FillqvectorFromSparse(PT_ETA_CHARGEq, bin, wPhi * wPt * wEta); // weighted q(pt,eta,charge) filled in global bin to which this (pt,eta,charge) corresponds + FillqvectorFromSparse(PT_ETA_CHARGEq, bin, wPhi * wPt * wEta * wCharge); // weighted q(pt,eta,charge) filled in global bin to which this (pt,eta,charge) corresponds } if (tc.fVerboseForEachParticle) { @@ -19087,10 +19532,10 @@ void FillqvectorFromSparse(const eqvectorKine& kineVarChoice, const int& bin, co double wToPowerP = 1.; // weight raised to power p for (int h = 0; h < gMaxHarmonic * gMaxCorrelator + 1; h++) { - for (int wp = 0; wp < gMaxCorrelator + 1; wp++) { // weight power - if (pw.fUseDiffPhiWeights[wPhiPhiAxis] || pw.fUseDiffPtWeights[wPtPtAxis] || pw.fUseDiffEtaWeights[wEtaEtaAxis]) { // yes, because the first enum serves as a boolean for that category - wToPowerP = std::pow(dWeight, wp); // dWeight = wPhi * wPt * wEta - qv.fqvector[kineVarChoice][bin][h][wp] += std::complex(wToPowerP * std::cos(h * pbyp.fPhi), wToPowerP * std::sin(h * pbyp.fPhi)); // q-vector with weights + for (int wp = 0; wp < gMaxCorrelator + 1; wp++) { // weight power + if (pw.fUseDiffPhiWeights[wPhiPhiAxis] || pw.fUseDiffPtWeights[wPtPtAxis] || pw.fUseDiffEtaWeights[wEtaEtaAxis] || pw.fUseDiffChargeWeights[wChargeChargeAxis]) { // yes, because the first enum serves as a boolean for that category + wToPowerP = std::pow(dWeight, wp); // dWeight = wPhi * wPt * wEta * wcharge + qv.fqvector[kineVarChoice][bin][h][wp] += std::complex(wToPowerP * std::cos(h * pbyp.fPhi), wToPowerP * std::sin(h * pbyp.fPhi)); // q-vector with weights } else { qv.fqvector[kineVarChoice][bin][h][wp] += std::complex(std::cos(h * pbyp.fPhi), std::sin(h * pbyp.fPhi)); // bare q-vector without weights } @@ -19100,7 +19545,7 @@ void FillqvectorFromSparse(const eqvectorKine& kineVarChoice, const int& bin, co // *) Differential nested loops: if (nl.fCalculateKineCustomNestedLoops) { nl.ftaNestedLoopsKine[kineVarChoice][bin][0]->AddAt(pbyp.fPhi, qv.fqvectorEntries[kineVarChoice][bin]); - nl.ftaNestedLoopsKine[kineVarChoice][bin][1]->AddAt(dWeight, qv.fqvectorEntries[kineVarChoice][bin]); // dWeight = wPhi * wPt * wEta + nl.ftaNestedLoopsKine[kineVarChoice][bin][1]->AddAt(dWeight, qv.fqvectorEntries[kineVarChoice][bin]); // dWeight = wPhi * wPt * wEta * wCharge } // *) Multiplicity counter in this bin: @@ -19116,25 +19561,25 @@ void FillqvectorFromSparse(const eqvectorKine& kineVarChoice, const int& bin, co if (pbyp.fEta < 0.) { for (int e = 0; e < gMaxNumberEtaSeparations; e++) { if (pbyp.fEta < -1. * es.fEtaSeparationsValues[e] / 2.) { // yes, if eta separation is 0.2, then separation interval runs from -0.1 to 0.1 - qv.fmab[0][kineVarChoice][bin][e] += dWeight; // dWeight = wPhi * wPt * wEta => Remark: I can hardwire linear weight like this only for 2-p correlation + qv.fmab[0][kineVarChoice][bin][e] += dWeight; // dWeight = wPhi * wPt * wEta * wCharge => Remark: I can hardwire linear weight like this only for 2-p correlation for (int h = 0; h < gMaxHarmonic; h++) { if (es.fEtaSeparationsSkipHarmonics[h]) { continue; } - qv.fqabVector[0][kineVarChoice][bin][h][e] += std::complex(dWeight * std::cos((h + 1) * pbyp.fPhi), dWeight * std::sin((h + 1) * pbyp.fPhi)); // dWeight = wPhi * wPt * wEta => Remark: I can hardwire linear weight like this only for 2-p correlation + qv.fqabVector[0][kineVarChoice][bin][h][e] += std::complex(dWeight * std::cos((h + 1) * pbyp.fPhi), dWeight * std::sin((h + 1) * pbyp.fPhi)); // dWeight = wPhi * wPt * wEta * wCharge => Remark: I can hardwire linear weight like this only for 2-p correlation } } // for (int h = 0; h < gMaxHarmonic; h++) { } // for (int e = 0; e < gMaxNumberEtaSeparations; e++) { // eta separation } else if (pbyp.fEta > 0.) { for (int e = 0; e < gMaxNumberEtaSeparations; e++) { if (pbyp.fEta > es.fEtaSeparationsValues[e] / 2.) { // yes, if eta separation is 0.2, then separation interval runs from -0.1 to 0.1 - qv.fmab[1][kineVarChoice][bin][e] += dWeight; // dWeight = wPhi * wPt * wEta => Remark: I can hardwire linear weight like this only for 2-p correlation + qv.fmab[1][kineVarChoice][bin][e] += dWeight; // dWeight = wPhi * wPt * wEta * wCharge => Remark: I can hardwire linear weight like this only for 2-p correlation for (int h = 0; h < gMaxHarmonic; h++) { { if (es.fEtaSeparationsSkipHarmonics[h]) { continue; } - qv.fqabVector[1][kineVarChoice][bin][h][e] += std::complex(dWeight * std::cos((h + 1) * pbyp.fPhi), dWeight * std::sin((h + 1) * pbyp.fPhi)); // dWeight = wPhi * wPt * wEta => Remark: I can hardwire linear weight like this only for 2-p correlation + qv.fqabVector[1][kineVarChoice][bin][h][e] += std::complex(dWeight * std::cos((h + 1) * pbyp.fPhi), dWeight * std::sin((h + 1) * pbyp.fPhi)); // dWeight = wPhi * wPt * wEta * wCharge => Remark: I can hardwire linear weight like this only for 2-p correlation } } // for (int h = 0; h < gMaxHarmonic; h++) { } // for (int e = 0; e < gMaxNumberEtaSeparations; e++) { // eta separation From b885e18b641ec33ffda792f43923b14938152c82 Mon Sep 17 00:00:00 2001 From: skundu692 <86804743+skundu692@users.noreply.github.com> Date: Sat, 14 Mar 2026 05:39:07 +0100 Subject: [PATCH 277/347] [PWGLF] Add new process function for mixing (#15399) --- .../Strangeness/lambdaspincorrderived.cxx | 774 ++++++++++++++++-- 1 file changed, 724 insertions(+), 50 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx b/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx index 0ff87544f97..4e9bbcbfaa8 100644 --- a/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx +++ b/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx @@ -205,11 +205,12 @@ struct lambdaspincorrderived { Configurable ConfWeightPathALL2{"ConfWeightPathALL2", "Users/s/skundu/My/Object/spincorr/cent010LL", "Weight path 2"}; // Mixing ///////// + Configurable cfgV5MassBins{"cfgV5MassBins", 5, "Number of fixed mass bins for V5 mixing"}; Configurable cfgV5NeighborPt{"cfgV5NeighborPt", 0, "v5: neighbor bins in pT (use symmetric ±N, edge-safe)"}; Configurable cfgV5NeighborEta{"cfgV5NeighborEta", 0, "v5: neighbor bins in eta (use symmetric ±N, edge-safe)"}; Configurable cfgV5NeighborPhi{"cfgV5NeighborPhi", 0, "v5: neighbor bins in phi (use symmetric ±N, periodic wrap)"}; - + Configurable usePairKineMatch{"usePairKineMatch", true, "Require pair-level matching between (A,B) and (C,B)"}; Configurable cfgV5MaxMatches{"cfgV5MaxMatches", 50, "v5: max ME replacements per SE pair (after all cuts)"}; Configurable cfgMixSeed{"cfgMixSeed", 0xdecafbadULL, "RNG seed for downsampling matches (deterministic)"}; Configurable centMin{"centMin", 0, "Minimum Centrality"}; @@ -453,6 +454,88 @@ struct lambdaspincorrderived { return true; } + template + bool checkPairKinematics(TA const& A, TB const& B, TC const& C) + { + if (!usePairKineMatch) { + return true; + } + + const auto lA = ROOT::Math::PtEtaPhiMVector(A.lambdaPt(), A.lambdaEta(), A.lambdaPhi(), A.lambdaMass()); + const auto lB = ROOT::Math::PtEtaPhiMVector(B.lambdaPt(), B.lambdaEta(), B.lambdaPhi(), B.lambdaMass()); + const auto lC = ROOT::Math::PtEtaPhiMVector(C.lambdaPt(), C.lambdaEta(), C.lambdaPhi(), C.lambdaMass()); + + // relative pT inside the pair: |pT1 - pT2| + const float dPtAB = std::abs(A.lambdaPt() - B.lambdaPt()); + const float dPtCB = std::abs(C.lambdaPt() - B.lambdaPt()); + if (std::abs(dPtAB - dPtCB) > ptMix) { + return false; + } + + // relative longitudinal kinematics: |Δy| or |Δη| + if (userapidity) { + const float dYAB = std::abs(lA.Rapidity() - lB.Rapidity()); + const float dYCB = std::abs(lC.Rapidity() - lB.Rapidity()); + if (std::abs(dYAB - dYCB) > etaMix) { + return false; + } + } else { + const float dEtaAB = std::abs(A.lambdaEta() - B.lambdaEta()); + const float dEtaCB = std::abs(C.lambdaEta() - B.lambdaEta()); + if (std::abs(dEtaAB - dEtaCB) > etaMix) { + return false; + } + } + + // relative azimuth inside the pair: |Δφ| + const float dPhiAB = std::abs(deltaPhiMinusPiToPi((float)A.lambdaPhi(), (float)B.lambdaPhi())); + const float dPhiCB = std::abs(deltaPhiMinusPiToPi((float)C.lambdaPhi(), (float)B.lambdaPhi())); + if (std::abs(dPhiAB - dPhiCB) > phiMix) { + return false; + } + + return true; + } + template + bool checkPairKinematicsMC(TA const& A, TB const& B, TC const& C) + { + if (!usePairKineMatch) { + return true; + } + + const auto lA = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(A), mcacc::lamEta(A), mcacc::lamPhi(A), mcacc::lamMass(A)); + const auto lB = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(B), mcacc::lamEta(B), mcacc::lamPhi(B), mcacc::lamMass(B)); + const auto lC = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(C), mcacc::lamEta(C), mcacc::lamPhi(C), mcacc::lamMass(C)); + + const float dPtAB = std::abs(mcacc::lamPt(A) - mcacc::lamPt(B)); + const float dPtCB = std::abs(mcacc::lamPt(C) - mcacc::lamPt(B)); + if (std::abs(dPtAB - dPtCB) > ptMix) { + return false; + } + + if (userapidity) { + const float dYAB = std::abs(lA.Rapidity() - lB.Rapidity()); + const float dYCB = std::abs(lC.Rapidity() - lB.Rapidity()); + if (std::abs(dYAB - dYCB) > etaMix) { + return false; + } + } else { + const float dEtaAB = std::abs(mcacc::lamEta(A) - mcacc::lamEta(B)); + const float dEtaCB = std::abs(mcacc::lamEta(C) - mcacc::lamEta(B)); + if (std::abs(dEtaAB - dEtaCB) > etaMix) { + return false; + } + } + + const float dPhiAB = std::abs(deltaPhiMinusPiToPi((float)mcacc::lamPhi(A), (float)mcacc::lamPhi(B))); + const float dPhiCB = std::abs(deltaPhiMinusPiToPi((float)mcacc::lamPhi(C), (float)mcacc::lamPhi(B))); + if (std::abs(dPhiAB - dPhiCB) > phiMix) { + return false; + } + + return true; + } + void fillHistograms(int tag1, int tag2, const ROOT::Math::PtEtaPhiMVector& particle1, const ROOT::Math::PtEtaPhiMVector& particle2, const ROOT::Math::PtEtaPhiMVector& daughpart1, const ROOT::Math::PtEtaPhiMVector& daughpart2, @@ -1036,29 +1119,50 @@ struct lambdaspincorrderived { static constexpr int N_STATUS = 2; // v0Status ∈ {0,1} struct MixBinner { - // constructed from the task's configurables; φ is assumed already constrained into [0, 2π) + // constructed from the task's configurables; φ is assumed already constrained upstream float ptMin, ptMax, ptStep; float etaMin, etaMax, etaStep; float phiMin, phiMax, phiStep; - // Mass binning: [1.09, 1.14) with 50 bins (1e-3 GeV/c^2) - static constexpr float mMin = 1.09f; - static constexpr float mMax = 1.14f; - static constexpr int nM_ = 1; - static constexpr float mStep = (mMax - mMin) / nM_; + // configurable fixed mass-binning for mixing buffer + float mMin, mMax, mStep; + int nM_; int nPt_, nEta_, nPhi_; MixBinner(float ptMin_, float ptMax_, float ptStep_, float etaAbsMax, float etaStep_, - float phiStep_) - : ptMin(ptMin_), ptMax(ptMax_), ptStep(ptStep_), etaMin(-etaAbsMax), etaMax(+etaAbsMax), etaStep(etaStep_), phiMin(-static_cast(TMath::Pi())), phiMax(+static_cast(TMath::Pi())), phiStep(phiStep_) - // : ptMin(ptMin_), ptMax(ptMax_), ptStep(ptStep_), etaMin(-etaAbsMax), etaMax(+etaAbsMax), etaStep(etaStep_), phiMin(0.f), phiMax(static_cast(2.0 * TMath::Pi())), phiStep(phiStep_) + float phiStep_, + float mMin_, float mMax_, int nMassBins_) + : ptMin(ptMin_), + ptMax(ptMax_), + ptStep(ptStep_), + etaMin(-etaAbsMax), + etaMax(+etaAbsMax), + etaStep(etaStep_), + phiMin(-static_cast(TMath::Pi())), + phiMax(+static_cast(TMath::Pi())), + phiStep(phiStep_), + mMin(mMin_), + mMax(mMax_), + mStep(0.f), + nM_(std::max(1, nMassBins_)), + nPt_(0), + nEta_(0), + nPhi_(0) + // If you want phi in [0, 2pi), use: + // : ... phiMin(0.f), phiMax(static_cast(2.0 * TMath::Pi())), ... { ptStep = (ptStep > 0.f ? ptStep : 0.1f); etaStep = (etaStep > 0.f ? etaStep : 0.1f); phiStep = (phiStep > 0.f ? phiStep : 0.1f); + if (!(mMax > mMin)) { + mMin = 1.09f; + mMax = 1.14f; + } + mStep = (mMax - mMin) / static_cast(nM_); + nPt_ = std::max(1, static_cast(std::floor((ptMax - ptMin) / ptStep + 0.5f))); nEta_ = std::max(1, static_cast(std::floor((etaMax - etaMin) / etaStep + 0.5f))); nPhi_ = std::max(1, static_cast(std::ceil((phiMax - phiMin) / phiStep))); @@ -1071,14 +1175,17 @@ struct lambdaspincorrderived { inline int binFromValue(float v, float vmin, float step, int nBins) const { - if (!std::isfinite(v)) + if (!std::isfinite(v) || !std::isfinite(vmin) || !std::isfinite(step) || step <= 0.f || nBins <= 0) { return -1; + } const float x = (v - vmin) / step; int b = static_cast(std::floor(x + 1e-6f)); - if (b < 0) + if (b < 0) { return -1; - if (b >= nBins) + } + if (b >= nBins) { b = nBins - 1; // clamp exact-top edge + } return b; } @@ -1128,12 +1235,11 @@ struct lambdaspincorrderived { // ===================== Main mixing (with mass-bin + random unique sampling) ===================== void processMEV4(EventCandidates const& collisions, AllTrackCandidates const& V0s) { - // Build binner from your existing configurables MixBinner mb{ - ptMin.value, ptMax.value, ptMix.value, // pT range & step - v0etaMixBuffer.value, etaMix.value, // |eta| max & step - phiMix.value // φ step; φ range fixed to [0, 2π) - }; + ptMin.value, ptMax.value, ptMix.value, + v0etaMixBuffer.value, etaMix.value, + phiMix.value, + MassMin.value, MassMax.value, cfgV5MassBins.value}; const int nCol = colBinning.getAllBinsCount(); // event-class bins (vz, centrality) const int nStat = N_STATUS; // 2 @@ -1235,6 +1341,9 @@ struct lambdaspincorrderived { if (!checkKinematics(t1, tX)) { continue; } + if (!checkPairKinematics(t1, t2, tX)) { + continue; + } matches.push_back(MatchRef{bc.collisionIdx, bc.rowIndex}); } }; @@ -1565,11 +1674,11 @@ struct lambdaspincorrderived { // ----------------------------------------------------- void processMCMEV4(EventCandidatesMC const& collisions, AllTrackCandidatesMC const& V0sMC) { - // Same binner as in data MEV4 MixBinner mb{ ptMin.value, ptMax.value, ptMix.value, v0etaMixBuffer.value, etaMix.value, - phiMix.value}; + phiMix.value, + MassMin.value, MassMax.value, cfgV5MassBins.value}; const int nCol = colBinning.getAllBinsCount(); const int nStat = N_STATUS; @@ -1673,6 +1782,9 @@ struct lambdaspincorrderived { if (!checkKinematicsMC(t1, tX)) { continue; } + if (!checkPairKinematicsMC(t1, t2, tX)) { + continue; + } matches.push_back(MatchRef{bc.collisionIdx, bc.rowIndex}); } }; @@ -1827,12 +1939,11 @@ struct lambdaspincorrderived { void processMEV5(EventCandidates const& collisions, AllTrackCandidates const& V0s) { - // Buffer binning: use v0etaMixBuffer as the max range, etaMix as the bin step MixBinner mb{ - ptMin.value, ptMax.value, ptMix.value, // pT range & step - v0etaMixBuffer.value, etaMix.value, // |eta| (or |y|) max & step - phiMix.value // phi step - }; + ptMin.value, ptMax.value, ptMix.value, + v0etaMixBuffer.value, etaMix.value, + phiMix.value, + MassMin.value, MassMax.value, cfgV5MassBins.value}; const int nCol = colBinning.getAllBinsCount(); const int nStat = N_STATUS; @@ -2063,26 +2174,19 @@ struct lambdaspincorrderived { MixBinner mb{ ptMin.value, ptMax.value, ptMix.value, v0etaMixBuffer.value, etaMix.value, - phiMix.value}; + phiMix.value, + MassMin.value, MassMax.value, cfgV5MassBins.value}; const int nCol = colBinning.getAllBinsCount(); const int nStat = N_STATUS; const int nPt = mb.nPt(); - const int nEta = mb.nEta(); + const int nEta = mb.nEta(); // logical "nY" if userapidity=true const int nPhi = mb.nPhi(); + const int nM = mb.nM(); - const size_t nKeys = static_cast(nCol) * nStat * nPt * nEta * nPhi; + const size_t nKeys = static_cast(nCol) * nStat * nPt * nEta * nPhi * nM; std::vector> buffer(nKeys); - auto key5 = [&](int colBin, int status, int ptB, int etaB, int phiB) -> size_t { - size_t k = static_cast(colBin); - k = k * static_cast(nStat) + static_cast(status); - k = k * static_cast(nPt) + static_cast(ptB); - k = k * static_cast(nEta) + static_cast(etaB); - k = k * static_cast(nPhi) + static_cast(phiB); - return k; - }; - // -------- PASS 1: fill buffer -------- for (auto const& col : collisions) { const int colBin = colBinning.getBin(std::make_tuple(mcacc::posz(col), mcacc::cent(col))); @@ -2112,18 +2216,21 @@ struct lambdaspincorrderived { } const int phiB = mb.phiBin(RecoDecay::constrainAngle(mcacc::lamPhi(t), -TMath::Pi(), harmonic)); - if (ptB < 0 || etaB < 0 || phiB < 0) { + const int mB = mb.massBin(mcacc::lamMass(t)); + if (ptB < 0 || etaB < 0 || phiB < 0 || mB < 0) { continue; } - buffer[key5(colBin, status, ptB, etaB, phiB)].push_back(BufferCand{ - .collisionIdx = static_cast(col.index()), - .rowIndex = static_cast(t.globalIndex()), - .v0Status = static_cast(status), - .ptBin = static_cast(ptB), - .etaBin = static_cast(etaB), - .phiBin = static_cast(phiB), - .mBin = 0}); + buffer[linearKey(colBin, status, ptB, etaB, phiB, mB, + nStat, nPt, nEta, nPhi, nM)] + .push_back(BufferCand{ + .collisionIdx = static_cast(col.index()), + .rowIndex = static_cast(t.globalIndex()), + .v0Status = static_cast(status), + .ptBin = static_cast(ptB), + .etaBin = static_cast(etaB), + .phiBin = static_cast(phiB), + .mBin = static_cast(mB)}); } } @@ -2178,10 +2285,10 @@ struct lambdaspincorrderived { etaB = mb.etaBin(lv1.Rapidity()); } const int phiB = mb.phiBin(RecoDecay::constrainAngle(mcacc::lamPhi(t1), -TMath::Pi(), harmonic)); - if (ptB < 0 || etaB < 0 || phiB < 0) { + const int mB = mb.massBin(mcacc::lamMass(t1)); + if (ptB < 0 || etaB < 0 || phiB < 0 || mB < 0) { continue; } - collectNeighborBinsClamp(ptB, nPt, nN_pt, ptBins); collectNeighborBinsClamp(etaB, nEta, nN_eta, etaBins); collectNeighborBinsPhi(phiB, nPhi, nN_phi, phiBins); @@ -2191,8 +2298,8 @@ struct lambdaspincorrderived { for (int ptUse : ptBins) { for (int etaUse : etaBins) { for (int phiUse : phiBins) { - auto const& vec = buffer[key5(colBin, status, ptUse, etaUse, phiUse)]; - + auto const& vec = buffer[linearKey(colBin, status, ptUse, etaUse, phiUse, mB, + nStat, nPt, nEta, nPhi, nM)]; for (auto const& bc : vec) { if (bc.collisionIdx == curColIdx) { continue; @@ -2285,6 +2392,573 @@ struct lambdaspincorrderived { } } PROCESS_SWITCH(lambdaspincorrderived, processMCMEV5, "Process MC ME v5 (paper-style)", false); + + void processMEV6(EventCandidates const& collisions, AllTrackCandidates const& V0s) + { + MixBinner mb{ + ptMin.value, ptMax.value, ptMix.value, + v0etaMixBuffer.value, etaMix.value, + phiMix.value, + MassMin.value, MassMax.value, cfgV5MassBins.value}; + + const int nCol = colBinning.getAllBinsCount(); + const int nStat = N_STATUS; + const int nPt = mb.nPt(); + const int nEta = mb.nEta(); + const int nPhi = mb.nPhi(); + const int nM = mb.nM(); + + const size_t nKeys = static_cast(nCol) * nStat * nPt * nEta * nPhi * nM; + std::vector> buffer(nKeys); + + // -------- PASS 1: fill buffer -------- + for (auto const& col : collisions) { + const int colBin = colBinning.getBin(std::make_tuple(col.posz(), col.cent())); + if (colBin < 0) { + continue; + } + + auto slice = V0s.sliceBy(tracksPerCollisionV0, col.index()); + + for (auto const& t : slice) { + if (!selectionV0(t)) { + continue; + } + + const int status = static_cast(t.v0Status()); + if (status < 0 || status >= nStat) { + continue; + } + + const int ptB = mb.ptBin(t.lambdaPt()); + + int etaB = mb.etaBin(t.lambdaEta()); + if (userapidity) { + const auto lv = ROOT::Math::PtEtaPhiMVector(t.lambdaPt(), t.lambdaEta(), t.lambdaPhi(), t.lambdaMass()); + etaB = mb.etaBin(lv.Rapidity()); + } + + const int phiB = mb.phiBin(RecoDecay::constrainAngle(t.lambdaPhi(), -TMath::Pi(), harmonic)); + const int mB = mb.massBin(t.lambdaMass()); + + if (ptB < 0 || etaB < 0 || phiB < 0 || mB < 0) { + continue; + } + + const size_t key = linearKey(colBin, status, ptB, etaB, phiB, mB, + nStat, nPt, nEta, nPhi, nM); + + buffer[key].push_back(BufferCand{ + .collisionIdx = static_cast(col.index()), + .rowIndex = static_cast(t.globalIndex()), + .v0Status = static_cast(status), + .ptBin = static_cast(ptB), + .etaBin = static_cast(etaB), + .phiBin = static_cast(phiB), + .mBin = static_cast(mB)}); + } + } + + const int nN_pt = std::max(0, cfgV5NeighborPt.value); + const int nN_eta = std::max(0, cfgV5NeighborEta.value); + const int nN_phi = std::max(0, cfgV5NeighborPhi.value); + + std::vector ptBins, etaBins, phiBins; + std::vector matches1, matches2; + matches1.reserve(256); + matches2.reserve(256); + + auto collectMatchesForReplacedLeg = [&](auto const& tRep, auto const& tKeep, int colBin, int64_t curColIdx, std::vector& matches) { + matches.clear(); + + const int status = static_cast(tRep.v0Status()); + if (status < 0 || status >= nStat) { + return; + } + + const int ptB = mb.ptBin(tRep.lambdaPt()); + + int etaB = mb.etaBin(tRep.lambdaEta()); + if (userapidity) { + const auto lv = ROOT::Math::PtEtaPhiMVector(tRep.lambdaPt(), tRep.lambdaEta(), tRep.lambdaPhi(), tRep.lambdaMass()); + etaB = mb.etaBin(lv.Rapidity()); + } + + const int phiB = mb.phiBin(RecoDecay::constrainAngle(tRep.lambdaPhi(), -TMath::Pi(), harmonic)); + const int mB = mb.massBin(tRep.lambdaMass()); + + if (ptB < 0 || etaB < 0 || phiB < 0 || mB < 0) { + return; + } + + collectNeighborBinsClamp(ptB, nPt, nN_pt, ptBins); + collectNeighborBinsClamp(etaB, nEta, nN_eta, etaBins); + collectNeighborBinsPhi(phiB, nPhi, nN_phi, phiBins); + + for (int ptUse : ptBins) { + for (int etaUse : etaBins) { + for (int phiUse : phiBins) { + const auto& vec = buffer[linearKey(colBin, status, ptUse, etaUse, phiUse, mB, + nStat, nPt, nEta, nPhi, nM)]; + + for (auto const& bc : vec) { + if (bc.collisionIdx == curColIdx) { + continue; + } + + auto tX = V0s.iteratorAt(static_cast(bc.rowIndex)); + + if (!selectionV0(tX)) { + continue; + } + if (!checkKinematics(tRep, tX)) { + continue; + } + if (!checkPairKinematics(tRep, tKeep, tX)) { + continue; + } + + if (tX.globalIndex() == tRep.globalIndex()) { + continue; + } + if (tX.globalIndex() == tKeep.globalIndex()) { + continue; + } + + matches.push_back(MatchRef{bc.collisionIdx, bc.rowIndex}); + } + } + } + } + + std::sort(matches.begin(), matches.end(), + [](auto const& a, auto const& b) { + return std::tie(a.collisionIdx, a.rowIndex) < std::tie(b.collisionIdx, b.rowIndex); + }); + matches.erase(std::unique(matches.begin(), matches.end(), + [](auto const& a, auto const& b) { + return a.collisionIdx == b.collisionIdx && a.rowIndex == b.rowIndex; + }), + matches.end()); + }; + + auto downsampleMatches = [&](std::vector& matches, uint64_t seedBase) { + if (cfgV5MaxMatches.value > 0 && (int)matches.size() > cfgV5MaxMatches.value) { + uint64_t seed = cfgMixSeed.value ^ splitmix64(seedBase); + const int K = cfgV5MaxMatches.value; + for (int i = 0; i < K; ++i) { + seed = splitmix64(seed); + const int j = i + (int)(seed % (uint64_t)(matches.size() - i)); + std::swap(matches[i], matches[j]); + } + matches.resize(K); + } + }; + + // -------- PASS 2: two-leg mixing -------- + for (auto const& col1 : collisions) { + const int colBin = colBinning.getBin(std::make_tuple(col1.posz(), col1.cent())); + if (colBin < 0) { + continue; + } + + const int64_t curColIdx = static_cast(col1.index()); + auto poolA = V0s.sliceBy(tracksPerCollisionV0, col1.index()); + + for (auto const& [t1, t2] : + soa::combinations(o2::soa::CombinationsFullIndexPolicy(poolA, poolA))) { + + if (!selectionV0(t1) || !selectionV0(t2)) { + continue; + } + if (t2.index() <= t1.index()) { + continue; + } + + if (t1.protonIndex() == t2.protonIndex()) { + continue; + } + if (t1.pionIndex() == t2.pionIndex()) { + continue; + } + if (t1.protonIndex() == t2.pionIndex()) { + continue; + } + if (t1.pionIndex() == t2.protonIndex()) { + continue; + } + + // leg 1 replaced: (t1,t2) -> (tX,t2) + collectMatchesForReplacedLeg(t1, t2, colBin, curColIdx, matches1); + + // leg 2 replaced: (t1,t2) -> (t1,tY) + collectMatchesForReplacedLeg(t2, t1, colBin, curColIdx, matches2); + + downsampleMatches(matches1, + (uint64_t)t1.globalIndex() ^ (splitmix64((uint64_t)t2.globalIndex()) + 0x111ULL) ^ splitmix64((uint64_t)curColIdx)); + downsampleMatches(matches2, + (uint64_t)t2.globalIndex() ^ (splitmix64((uint64_t)t1.globalIndex()) + 0x222ULL) ^ splitmix64((uint64_t)curColIdx)); + + const int nReuse = static_cast(matches1.size() + matches2.size()); + if (nReuse <= 0) { + continue; + } + + const float wSE = 1.0f / static_cast(nReuse); + + // replace t1 -> tX, keep t2 + for (auto const& m : matches1) { + auto tX = V0s.iteratorAt(static_cast(m.rowIndex)); + + auto proton = ROOT::Math::PtEtaPhiMVector(tX.protonPt(), tX.protonEta(), tX.protonPhi(), + o2::constants::physics::MassProton); + auto lambda = ROOT::Math::PtEtaPhiMVector(tX.lambdaPt(), tX.lambdaEta(), tX.lambdaPhi(), + tX.lambdaMass()); + + auto proton2 = ROOT::Math::PtEtaPhiMVector(t2.protonPt(), t2.protonEta(), t2.protonPhi(), + o2::constants::physics::MassProton); + auto lambda2 = ROOT::Math::PtEtaPhiMVector(t2.lambdaPt(), t2.lambdaEta(), t2.lambdaPhi(), + t2.lambdaMass()); + + const int ptype = pairTypeCode(tX.v0Status(), t2.v0Status()); + double centPairWeight = 1.0; + if (hweightCentPair) { + const int bin = hweightCentPair->FindBin(col1.cent(), ptype); + centPairWeight = hweightCentPair->GetBinContent(bin); + if (centPairWeight <= 0.0) { + centPairWeight = 1.0; + } + } + + const float meWeight = wSE * centPairWeight; + const float dPhi = deltaPhiMinusPiToPi((float)lambda.Phi(), (float)lambda2.Phi()); + histos.fill(HIST("deltaPhiMix"), dPhi, wSE); + histos.fill(HIST("hCentPairTypeME"), col1.cent(), ptype, wSE); + + fillHistograms(tX.v0Status(), t2.v0Status(), + lambda, lambda2, proton, proton2, + 1, meWeight); + } + + // replace t2 -> tY, keep t1 + for (auto const& m : matches2) { + auto tY = V0s.iteratorAt(static_cast(m.rowIndex)); + + auto proton = ROOT::Math::PtEtaPhiMVector(t1.protonPt(), t1.protonEta(), t1.protonPhi(), + o2::constants::physics::MassProton); + auto lambda = ROOT::Math::PtEtaPhiMVector(t1.lambdaPt(), t1.lambdaEta(), t1.lambdaPhi(), + t1.lambdaMass()); + + auto proton2 = ROOT::Math::PtEtaPhiMVector(tY.protonPt(), tY.protonEta(), tY.protonPhi(), + o2::constants::physics::MassProton); + auto lambda2 = ROOT::Math::PtEtaPhiMVector(tY.lambdaPt(), tY.lambdaEta(), tY.lambdaPhi(), + tY.lambdaMass()); + + const int ptype = pairTypeCode(t1.v0Status(), tY.v0Status()); + double centPairWeight = 1.0; + if (hweightCentPair) { + const int bin = hweightCentPair->FindBin(col1.cent(), ptype); + centPairWeight = hweightCentPair->GetBinContent(bin); + if (centPairWeight <= 0.0) { + centPairWeight = 1.0; + } + } + + const float meWeight = wSE * centPairWeight; + const float dPhi = deltaPhiMinusPiToPi((float)lambda.Phi(), (float)lambda2.Phi()); + histos.fill(HIST("deltaPhiMix"), dPhi, wSE); + histos.fill(HIST("hCentPairTypeME"), col1.cent(), ptype, wSE); + + fillHistograms(t1.v0Status(), tY.v0Status(), + lambda, lambda2, proton, proton2, + 1, meWeight); + } + } + } + } + PROCESS_SWITCH(lambdaspincorrderived, processMEV6, "Process data ME v6 two-leg", false); + + void processMCMEV6(EventCandidatesMC const& collisions, AllTrackCandidatesMC const& V0sMC) + { + MixBinner mb{ + ptMin.value, ptMax.value, ptMix.value, + v0etaMixBuffer.value, etaMix.value, + phiMix.value, + MassMin.value, MassMax.value, cfgV5MassBins.value}; + + const int nCol = colBinning.getAllBinsCount(); + const int nStat = N_STATUS; + const int nPt = mb.nPt(); + const int nEta = mb.nEta(); + const int nPhi = mb.nPhi(); + const int nM = mb.nM(); + + const size_t nKeys = static_cast(nCol) * nStat * nPt * nEta * nPhi * nM; + std::vector> buffer(nKeys); + + // -------- PASS 1: fill buffer -------- + for (auto const& col : collisions) { + const int colBin = colBinning.getBin(std::make_tuple(mcacc::posz(col), mcacc::cent(col))); + if (colBin < 0) { + continue; + } + + auto slice = V0sMC.sliceBy(tracksPerCollisionV0mc, col.index()); + + for (auto const& t : slice) { + if (!selectionV0MC(t)) { + continue; + } + + const int status = mcacc::v0Status(t); + if (status < 0 || status >= nStat) { + continue; + } + + const int ptB = mb.ptBin(mcacc::lamPt(t)); + + int etaB = mb.etaBin(mcacc::lamEta(t)); + if (userapidity) { + const auto lv = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(t), mcacc::lamEta(t), mcacc::lamPhi(t), mcacc::lamMass(t)); + etaB = mb.etaBin(lv.Rapidity()); + } + + const int phiB = mb.phiBin(RecoDecay::constrainAngle(mcacc::lamPhi(t), -TMath::Pi(), harmonic)); + const int mB = mb.massBin(mcacc::lamMass(t)); + + if (ptB < 0 || etaB < 0 || phiB < 0 || mB < 0) { + continue; + } + + const size_t key = linearKey(colBin, status, ptB, etaB, phiB, mB, + nStat, nPt, nEta, nPhi, nM); + + buffer[key].push_back(BufferCand{ + .collisionIdx = static_cast(col.index()), + .rowIndex = static_cast(t.globalIndex()), + .v0Status = static_cast(status), + .ptBin = static_cast(ptB), + .etaBin = static_cast(etaB), + .phiBin = static_cast(phiB), + .mBin = static_cast(mB)}); + } + } + + const int nN_pt = std::max(0, cfgV5NeighborPt.value); + const int nN_eta = std::max(0, cfgV5NeighborEta.value); + const int nN_phi = std::max(0, cfgV5NeighborPhi.value); + + std::vector ptBins, etaBins, phiBins; + std::vector matches1, matches2; + matches1.reserve(256); + matches2.reserve(256); + + auto collectMatchesForReplacedLeg = [&](auto const& tRep, auto const& tKeep, int colBin, int64_t curColIdx, std::vector& matches) { + matches.clear(); + + const int status = mcacc::v0Status(tRep); + if (status < 0 || status >= nStat) { + return; + } + + const int ptB = mb.ptBin(mcacc::lamPt(tRep)); + + int etaB = mb.etaBin(mcacc::lamEta(tRep)); + if (userapidity) { + const auto lv = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(tRep), mcacc::lamEta(tRep), mcacc::lamPhi(tRep), mcacc::lamMass(tRep)); + etaB = mb.etaBin(lv.Rapidity()); + } + + const int phiB = mb.phiBin(RecoDecay::constrainAngle(mcacc::lamPhi(tRep), -TMath::Pi(), harmonic)); + const int mB = mb.massBin(mcacc::lamMass(tRep)); + + if (ptB < 0 || etaB < 0 || phiB < 0 || mB < 0) { + return; + } + + collectNeighborBinsClamp(ptB, nPt, nN_pt, ptBins); + collectNeighborBinsClamp(etaB, nEta, nN_eta, etaBins); + collectNeighborBinsPhi(phiB, nPhi, nN_phi, phiBins); + + for (int ptUse : ptBins) { + for (int etaUse : etaBins) { + for (int phiUse : phiBins) { + const auto& vec = buffer[linearKey(colBin, status, ptUse, etaUse, phiUse, mB, + nStat, nPt, nEta, nPhi, nM)]; + + for (auto const& bc : vec) { + if (bc.collisionIdx == curColIdx) { + continue; + } + + auto tX = V0sMC.iteratorAt(static_cast(bc.rowIndex)); + + if (!selectionV0MC(tX)) { + continue; + } + if (!checkKinematicsMC(tRep, tX)) { + continue; + } + if (!checkPairKinematicsMC(tRep, tKeep, tX)) { + continue; + } + + if (tX.globalIndex() == tRep.globalIndex()) { + continue; + } + if (tX.globalIndex() == tKeep.globalIndex()) { + continue; + } + + matches.push_back(MatchRef{bc.collisionIdx, bc.rowIndex}); + } + } + } + } + + std::sort(matches.begin(), matches.end(), + [](auto const& a, auto const& b) { + return std::tie(a.collisionIdx, a.rowIndex) < std::tie(b.collisionIdx, b.rowIndex); + }); + matches.erase(std::unique(matches.begin(), matches.end(), + [](auto const& a, auto const& b) { + return a.collisionIdx == b.collisionIdx && a.rowIndex == b.rowIndex; + }), + matches.end()); + }; + + auto downsampleMatches = [&](std::vector& matches, uint64_t seedBase) { + if (cfgV5MaxMatches.value > 0 && (int)matches.size() > cfgV5MaxMatches.value) { + uint64_t seed = cfgMixSeed.value ^ splitmix64(seedBase); + const int K = cfgV5MaxMatches.value; + for (int i = 0; i < K; ++i) { + seed = splitmix64(seed); + const int j = i + (int)(seed % (uint64_t)(matches.size() - i)); + std::swap(matches[i], matches[j]); + } + matches.resize(K); + } + }; + + // -------- PASS 2: two-leg mixing -------- + for (auto const& col1 : collisions) { + const int colBin = colBinning.getBin(std::make_tuple(mcacc::posz(col1), mcacc::cent(col1))); + if (colBin < 0) { + continue; + } + + const int64_t curColIdx = static_cast(col1.index()); + auto poolA = V0sMC.sliceBy(tracksPerCollisionV0mc, col1.index()); + + for (auto const& [t1, t2] : + soa::combinations(o2::soa::CombinationsFullIndexPolicy(poolA, poolA))) { + + if (!selectionV0MC(t1) || !selectionV0MC(t2)) { + continue; + } + if (t2.index() <= t1.index()) { + continue; + } + + if (mcacc::prIdx(t1) == mcacc::prIdx(t2)) { + continue; + } + if (mcacc::piIdx(t1) == mcacc::piIdx(t2)) { + continue; + } + if (mcacc::prIdx(t1) == mcacc::piIdx(t2)) { + continue; + } + if (mcacc::piIdx(t1) == mcacc::prIdx(t2)) { + continue; + } + + collectMatchesForReplacedLeg(t1, t2, colBin, curColIdx, matches1); + collectMatchesForReplacedLeg(t2, t1, colBin, curColIdx, matches2); + + downsampleMatches(matches1, + (uint64_t)t1.globalIndex() ^ (splitmix64((uint64_t)t2.globalIndex()) + 0x111ULL) ^ splitmix64((uint64_t)curColIdx)); + downsampleMatches(matches2, + (uint64_t)t2.globalIndex() ^ (splitmix64((uint64_t)t1.globalIndex()) + 0x222ULL) ^ splitmix64((uint64_t)curColIdx)); + + const int nReuse = static_cast(matches1.size() + matches2.size()); + if (nReuse <= 0) { + continue; + } + + const float wSE = 1.0f / static_cast(nReuse); + + // replace t1 -> tX, keep t2 + for (auto const& m : matches1) { + auto tX = V0sMC.iteratorAt(static_cast(m.rowIndex)); + + auto pX = ROOT::Math::PtEtaPhiMVector(mcacc::prPt(tX), mcacc::prEta(tX), mcacc::prPhi(tX), + o2::constants::physics::MassProton); + auto lX = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(tX), mcacc::lamEta(tX), mcacc::lamPhi(tX), + mcacc::lamMass(tX)); + + auto p2 = ROOT::Math::PtEtaPhiMVector(mcacc::prPt(t2), mcacc::prEta(t2), mcacc::prPhi(t2), + o2::constants::physics::MassProton); + auto l2 = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(t2), mcacc::lamEta(t2), mcacc::lamPhi(t2), + mcacc::lamMass(t2)); + + const int ptype = pairTypeCode(mcacc::v0Status(tX), mcacc::v0Status(t2)); + double centPairWeight = 1.0; + if (hweightCentPair) { + const int bin = hweightCentPair->FindBin(mcacc::cent(col1), ptype); + centPairWeight = hweightCentPair->GetBinContent(bin); + if (centPairWeight <= 0.0) { + centPairWeight = 1.0; + } + } + + const float meWeight = wSE * centPairWeight; + const float dPhi = deltaPhiMinusPiToPi((float)lX.Phi(), (float)l2.Phi()); + histos.fill(HIST("deltaPhiMix"), dPhi, wSE); + histos.fill(HIST("hCentPairTypeME"), mcacc::cent(col1), ptype, wSE); + + fillHistograms(mcacc::v0Status(tX), mcacc::v0Status(t2), + lX, l2, pX, p2, + 1, meWeight); + } + + // replace t2 -> tY, keep t1 + for (auto const& m : matches2) { + auto tY = V0sMC.iteratorAt(static_cast(m.rowIndex)); + + auto p1 = ROOT::Math::PtEtaPhiMVector(mcacc::prPt(t1), mcacc::prEta(t1), mcacc::prPhi(t1), + o2::constants::physics::MassProton); + auto l1 = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(t1), mcacc::lamEta(t1), mcacc::lamPhi(t1), + mcacc::lamMass(t1)); + + auto pY = ROOT::Math::PtEtaPhiMVector(mcacc::prPt(tY), mcacc::prEta(tY), mcacc::prPhi(tY), + o2::constants::physics::MassProton); + auto lY = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(tY), mcacc::lamEta(tY), mcacc::lamPhi(tY), + mcacc::lamMass(tY)); + + const int ptype = pairTypeCode(mcacc::v0Status(t1), mcacc::v0Status(tY)); + double centPairWeight = 1.0; + if (hweightCentPair) { + const int bin = hweightCentPair->FindBin(mcacc::cent(col1), ptype); + centPairWeight = hweightCentPair->GetBinContent(bin); + if (centPairWeight <= 0.0) { + centPairWeight = 1.0; + } + } + + const float meWeight = wSE * centPairWeight; + const float dPhi = deltaPhiMinusPiToPi((float)l1.Phi(), (float)lY.Phi()); + histos.fill(HIST("deltaPhiMix"), dPhi, wSE); + histos.fill(HIST("hCentPairTypeME"), mcacc::cent(col1), ptype, wSE); + + fillHistograms(mcacc::v0Status(t1), mcacc::v0Status(tY), + l1, lY, p1, pY, + 1, meWeight); + } + } + } + } + PROCESS_SWITCH(lambdaspincorrderived, processMCMEV6, "Process MC ME v6 two-leg", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { From 36411194e22582cf5c903711f7f3e992e9cf8971 Mon Sep 17 00:00:00 2001 From: Yash Patley <52608802+yashpatley@users.noreply.github.com> Date: Sat, 14 Mar 2026 14:48:32 +0530 Subject: [PATCH 278/347] [PWGCF] Update flowEventPlane.cxx (#15375) --- PWGCF/Flow/Tasks/flowEventPlane.cxx | 283 +++++++++++++++------------- 1 file changed, 156 insertions(+), 127 deletions(-) diff --git a/PWGCF/Flow/Tasks/flowEventPlane.cxx b/PWGCF/Flow/Tasks/flowEventPlane.cxx index ea895bc8232..510ba5c5b89 100644 --- a/PWGCF/Flow/Tasks/flowEventPlane.cxx +++ b/PWGCF/Flow/Tasks/flowEventPlane.cxx @@ -106,8 +106,14 @@ enum ParticleType { kNPart }; +enum ResoType { + kPhi0 = 0, + kKStar +}; + enum V0Type { - kLambda = 0, + kK0S = 0, + kLambda, kAntiLambda }; @@ -717,11 +723,17 @@ struct SpectatorPlaneTableProducer { struct FlowEventPlane { // Tracks - Configurable cNEtaBins{"cNEtaBins", 7, "# of eta bins"}; + Configurable cNEtaBins{"cNEtaBins", 5, "# of eta bins"}; + + // Pi,Ka,Pr + Configurable cMinPtPi{"cMinPtPi", 0.2, "Pion min pT"}; + Configurable cMinPtKa{"cMinPtKa", 0.3, "Kaon min pT"}; + Configurable cMinPtPr{"cMinPtPr", 0.5, "Proton min pT"}; // Resonance Configurable cNRapBins{"cNRapBins", 5, "# of y bins"}; - Configurable cNInvMassBins{"cNInvMassBins", 500, "# of m bins"}; + Configurable cPhiInvMassBins{"cPhiInvMassBins", 500, "# of Phi mass bins"}; + Configurable cKStarInvMassBins{"cKStarInvMassBins", 200, "# of Phi mass bins"}; Configurable cResRapCut{"cResRapCut", 0.5, "Resonance rapidity cut"}; // V0 @@ -732,19 +744,22 @@ struct FlowEventPlane { // V0s Configurable cV0TypeSelection{"cV0TypeSelection", 1, "V0 Type Selection"}; - Configurable cMinDcaProtonToPV{"cMinDcaProtonToPV", 0.02, "Minimum Proton DCAr to PV"}; - Configurable cMinDcaPionToPV{"cMinDcaPionToPV", 0.06, "Minimum Pion DCAr to PV"}; + Configurable cMinDcaProtonToPV{"cMinDcaProtonToPV", 0.01, "Minimum Proton DCAr to PV"}; + Configurable cMinDcaPionToPV{"cMinDcaPionToPV", 0.1, "Minimum Pion DCAr to PV"}; Configurable cDcaV0Dau{"cDcaV0Dau", 1., "DCA between V0 daughters"}; Configurable cDcaV0ToPv{"cDcaV0ToPv", 0.1, "DCA V0 to PV"}; Configurable cMinV0Radius{"cMinV0Radius", 0.5, "Minimum V0 radius from PV"}; - Configurable cMaxV0Radius{"cMaxV0Radius", 999.0, "Maximum V0 radius from PV"}; - Configurable cV0CTau{"cV0CTau", 30.0, "Decay length cut"}; - Configurable cV0CosPA{"cV0CosPA", 0.995, "V0 CosPA to PV"}; + Configurable cK0ShortCTau{"cK0ShortCTau", 20.0, "Decay length cut K0Short"}; + Configurable cLambdaCTau{"cLambdaCTau", 30.0, "Decay length cut Lambda"}; + Configurable cK0ShortCosPA{"cK0ShortCosPA", 0.998, "K0Short CosPA"}; + Configurable cLambdaCosPA{"cLambdaCosPA", 0.998, "Lambda CosPA"}; Configurable cK0SMassRej{"cK0SMassRej", 0.01, "Reject K0Short Candidates"}; - Configurable cLambdaMassWin{"cLambdaMassWin", 0.007, "Lambda Mass Window"}; - Configurable cMinV0Pt{"cMinV0Pt", 0.5, "Min v0 pT"}; - Configurable cMaxV0Pt{"cMaxV0Pt", 4.5, "Max v0 pT"}; - Configurable cV0RapCut{"cV0RapCut", 0.5, "V0 rap cut"}; + Configurable cArmPodSel{"cArmPodSel", 0.2, "Armentros-Podolanski Selection for K0S"}; + Configurable cV0RapCut{"cV0RapCut", 0.8, "V0 rap cut"}; + Configurable cK0SMinPt{"cK0SMinPt", 0.4, "K0S Min pT"}; + Configurable cK0SMaxPt{"cK0SMaxPt", 6.0, "K0S Max pT"}; + Configurable cLambdaMinPt{"cLambdaMinPt", 0.6, "Lambda Min pT"}; + Configurable cLambdaMaxPt{"cLambdaMaxPt", 6.0, "Lambda Max pT"}; // Histogram registry: an object to hold your histograms HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -752,6 +767,10 @@ struct FlowEventPlane { // Global objects float cent = 0.; std::array vSP = {0., 0., 0., 0.}; + std::map> mResoDauMass = {{kPhi0, {MassKaonCharged, MassKaonCharged}}, {kKStar, {MassPionCharged, MassKaonCharged}}}; + std::map mResoMass = {{kPhi0, MassPhi}, {kKStar, MassKaonCharged}}; + std::map mV0Ctau = {{kK0S, cK0ShortCTau}, {kLambda, cLambdaCTau}, {kAntiLambda, cLambdaCTau}}; + std::map mV0CosPA = {{kK0S, cK0ShortCosPA}, {kLambda, cLambdaCosPA}, {kAntiLambda, cLambdaCosPA}}; void init(InitContext const&) { @@ -769,7 +788,8 @@ struct FlowEventPlane { const AxisSpec axisTrackNSigma{161, -4.025, 4.025, {"n#sigma"}}; const AxisSpec axisTrackRap{cNRapBins, -0.5, 0.5, "y"}; - const AxisSpec axisInvMass{cNInvMassBins, 0.87, 1.12, "M_{KK} (GeV/#it{c}^{2}"}; + const AxisSpec axisPhiInvMass{cPhiInvMassBins, 0.99, 1.12, "M_{KK} (GeV/#it{c}^{2}"}; + const AxisSpec axisKStarInvMass{cKStarInvMassBins, 0.8, 1.2, "M_{#piK} (GeV/#it{c}^{2}"}; const AxisSpec axisMomPID(80, 0, 4, "p_{T} (GeV/#it{c})"); const AxisSpec axisNsigma(401, -10.025, 10.025, {"n#sigma"}); const AxisSpec axisdEdx(360, 20, 200, "#frac{dE}{dx}"); @@ -782,8 +802,8 @@ struct FlowEventPlane { const AxisSpec axisCTau(2000, 0, 200, "c#tau (cm)"); const AxisSpec axisAlpha(40, -1, 1, "#alpha"); const AxisSpec axisQtarm(40, 0, 0.4, "q_{T}"); - const AxisSpec axisLambdaPt(50, 0, 10, "p_{T} (GeV/#it{c})"); const AxisSpec axisLambdaInvMass(140, 1.08, 1.15, "M_{p#pi} (GeV/#it{c}^{2})"); + const AxisSpec axisK0ShortInvMass(200, 0.4, 0.6, "M_{#pi#pi} (GeV/#it{c}^{2})"); // Create histograms // Charged particles @@ -791,7 +811,6 @@ struct FlowEventPlane { histos.add("TrackQA/hPtDcaXY", "DCA_{XY} vs p_{T}", kTH2F, {axisTrackPt, axisTrackDcaXY}); histos.add("TrackQA/hPtDcaZ", "DCA_{Z} vs p_{T}", kTH2F, {axisTrackPt, axisTrackDcaZ}); histos.add("TrackQA/hTrackTPCdEdX", "hTrackTPCdEdX", kTH2F, {axisMomPID, axisdEdx}); - histos.add("DF/hQaQc", "X^{A}_{1}X^{C}_{1} + Y^{A}_{1}Y^{C}_{1}", kTProfile, {axisCent}); histos.add("DF/hAQu", "u_{x}X^{A}_{1} + u_{y}Y^{A}_{1}", kTProfile2D, {axisCent, axisTrackEta}); histos.add("DF/hCQu", "u_{x}X^{C}_{1} + u_{y}Y^{C}_{1}", kTProfile2D, {axisCent, axisTrackEta}); histos.add("DF/hAQuPos", "u_{x}X^{A}_{1} + u_{y}Y^{A}_{1}", kTProfile2D, {axisCent, axisTrackEta}); @@ -816,34 +835,44 @@ struct FlowEventPlane { // Resonance if (doprocessResoFlow) { - histos.add("Reso/Phi/hSigCentPtInvMass", "hUSCentPtInvMass", kTH3F, {axisCent, axisTrackPt, axisInvMass}); - histos.add("Reso/Phi/hBkgCentPtInvMass", "hLSCentPtInvMass", kTH3F, {axisCent, axisTrackPt, axisInvMass}); - histos.add("Reso/Phi/Sig/hPhiQuA", "hPhiQuA", kTProfile3D, {axisCent, axisTrackRap, axisInvMass}); - histos.add("Reso/Phi/Sig/hPhiQuC", "hPhiQuC", kTProfile3D, {axisCent, axisTrackRap, axisInvMass}); - histos.add("Reso/Phi/Bkg/hPhiQuA", "hPhiQuA", kTProfile3D, {axisCent, axisTrackRap, axisInvMass}); - histos.add("Reso/Phi/Bkg/hPhiQuC", "hPhiQuC", kTProfile3D, {axisCent, axisTrackRap, axisInvMass}); + histos.add("Reso/Phi/hSigCentEtaInvMass", "hUSCentEtaInvMass", kTH3F, {axisCent, axisTrackEta, axisPhiInvMass}); + histos.add("Reso/Phi/hBkgCentEtaInvMass", "hLSCentEtaInvMass", kTH3F, {axisCent, axisTrackEta, axisPhiInvMass}); + histos.add("Reso/Phi/Sig/hQuA", "hPhiQuA", kTProfile3D, {axisCent, axisTrackEta, axisPhiInvMass}); + histos.add("Reso/Phi/Sig/hQuC", "hPhiQuC", kTProfile3D, {axisCent, axisTrackEta, axisPhiInvMass}); + histos.add("Reso/Phi/Bkg/hQuA", "hPhiQuA", kTProfile3D, {axisCent, axisTrackEta, axisPhiInvMass}); + histos.add("Reso/Phi/Bkg/hQuC", "hPhiQuC", kTProfile3D, {axisCent, axisTrackEta, axisPhiInvMass}); + histos.add("Reso/KStar/hSigCentEtaInvMass", "hUSCentEtaInvMass", kTH3F, {axisCent, axisTrackEta, axisKStarInvMass}); + histos.add("Reso/KStar/hBkgCentEtaInvMass", "hLSCentEtaInvMass", kTH3F, {axisCent, axisTrackEta, axisKStarInvMass}); + histos.add("Reso/KStar/Sig/hQuA", "hKStarQuA", kTProfile3D, {axisCent, axisTrackEta, axisKStarInvMass}); + histos.add("Reso/KStar/Sig/hQuC", "hKStarQuC", kTProfile3D, {axisCent, axisTrackEta, axisKStarInvMass}); + histos.add("Reso/KStar/Bkg/hQuA", "hKStarQuA", kTProfile3D, {axisCent, axisTrackEta, axisKStarInvMass}); + histos.add("Reso/KStar/Bkg/hQuC", "hKStarQuC", kTProfile3D, {axisCent, axisTrackEta, axisKStarInvMass}); } // Lambda - if (doprocessLambdaFlow) { - histos.add("Lambda/QA/hQtVsAlpha", "Armentros-Podolanski Plot", kTH2F, {axisAlpha, axisQtarm}); - histos.add("Lambda/QA/hDcaV0Dau", "DCA between V0 daughters", kTH1F, {axisDcaDau}); - histos.add("Lambda/QA/hDcaPosToPv", "DCA positive prong to PV", kTH1F, {axisDcaProngPV}); - histos.add("Lambda/QA/hDcaNegToPv", "DCA negative prong to PV", kTH1F, {axisDcaProngPV}); - histos.add("Lambda/QA/hDcaV0ToPv", "DCA V0 to PV", kTH1F, {axisDcaV0PV}); - histos.add("Lambda/QA/hCosPa", "cos(#theta_{PA})", kTH1F, {axisCosPA}); - histos.add("Lambda/QA/hRxy", "V_{0} Decay Radius in XY plane", kTH1F, {axisRadius}); - histos.add("Lambda/QA/hCTau", "V_{0} c#tau", kTH1F, {axisCTau}); - histos.add("Lambda/QA/hPosdEdXVsP", "TPC Signal Pos-Prong", kTH2F, {axisMomPID, axisdEdx}); - histos.add("Lambda/QA/hNegdEdXVsP", "TPC Signal Neg-Prong", kTH2F, {axisMomPID, axisdEdx}); - histos.add("Lambda/QA/hPosNsigPrVsP", "TPC n#sigma Pos Prong", kTH2F, {axisMomPID, axisNsigma}); - histos.add("Lambda/QA/hNegNsigPrVsP", "TPC n#sigma Neg Prong", kTH2F, {axisMomPID, axisNsigma}); - histos.add("Lambda/QA/hPosNsigPiVsP", "TPC n#sigma Pos Prong", kTH2F, {axisMomPID, axisNsigma}); - histos.add("Lambda/QA/hNegNsigPiVsP", "TPC n#sigma Neg Prong", kTH2F, {axisMomPID, axisNsigma}); - histos.add("Lambda/hInvMassVsPt", "hInvMassVsPt", kTH3F, {axisCent, axisLambdaInvMass, axisLambdaPt}); - histos.add("Lambda/Flow/hQuA", "hPhiQuA", kTProfile3D, {axisCent, axisTrackRap, axisLambdaInvMass}); - histos.add("Lambda/Flow/hQuC", "hPhiQuC", kTProfile3D, {axisCent, axisTrackRap, axisLambdaInvMass}); - histos.addClone("Lambda/", "AntiLambda/"); + if (doprocessV0Flow) { + histos.add("V0/Lambda/QA/hQtVsAlpha", "Armentros-Podolanski Plot", kTH2F, {axisAlpha, axisQtarm}); + histos.add("V0/Lambda/QA/hDcaV0Dau", "DCA between V0 daughters", kTH1F, {axisDcaDau}); + histos.add("V0/Lambda/QA/hDcaPosToPv", "DCA positive prong to PV", kTH1F, {axisDcaProngPV}); + histos.add("V0/Lambda/QA/hDcaNegToPv", "DCA negative prong to PV", kTH1F, {axisDcaProngPV}); + histos.add("V0/Lambda/QA/hDcaV0ToPv", "DCA V0 to PV", kTH1F, {axisDcaV0PV}); + histos.add("V0/Lambda/QA/hCosPa", "cos(#theta_{PA})", kTH1F, {axisCosPA}); + histos.add("V0/Lambda/QA/hRxy", "V_{0} Decay Radius in XY plane", kTH1F, {axisRadius}); + histos.add("V0/Lambda/QA/hCTau", "V_{0} c#tau", kTH1F, {axisCTau}); + histos.add("V0/Lambda/QA/hPosdEdXVsP", "TPC Signal Pos-Prong", kTH2F, {axisMomPID, axisdEdx}); + histos.add("V0/Lambda/QA/hNegdEdXVsP", "TPC Signal Neg-Prong", kTH2F, {axisMomPID, axisdEdx}); + histos.add("V0/Lambda/QA/hPosNsigPrVsP", "TPC n#sigma Pos Prong", kTH2F, {axisMomPID, axisNsigma}); + histos.add("V0/Lambda/QA/hNegNsigPrVsP", "TPC n#sigma Neg Prong", kTH2F, {axisMomPID, axisNsigma}); + histos.add("V0/Lambda/QA/hPosNsigPiVsP", "TPC n#sigma Pos Prong", kTH2F, {axisMomPID, axisNsigma}); + histos.add("V0/Lambda/QA/hNegNsigPiVsP", "TPC n#sigma Neg Prong", kTH2F, {axisMomPID, axisNsigma}); + histos.addClone("V0/Lambda/", "V0/K0Short/"); + histos.add("V0/Lambda/hMassVsRap", "hMassVsRap", kTH3F, {axisCent, axisLambdaInvMass, axisTrackEta}); + histos.add("V0/Lambda/Flow/hQuA", "hQuA", kTProfile3D, {axisCent, axisTrackRap, axisLambdaInvMass}); + histos.add("V0/Lambda/Flow/hQuC", "hQuC", kTProfile3D, {axisCent, axisTrackRap, axisLambdaInvMass}); + histos.addClone("V0/Lambda/", "V0/AntiLambda/"); + histos.add("V0/K0Short/hMassVsRap", "hMassVsRap", kTH3F, {axisCent, axisK0ShortInvMass, axisTrackEta}); + histos.add("V0/K0Short/Flow/hQuA", "hQuA", kTProfile3D, {axisCent, axisTrackRap, axisK0ShortInvMass}); + histos.add("V0/K0Short/Flow/hQuC", "hQuC", kTProfile3D, {axisCent, axisTrackRap, axisK0ShortInvMass}); } } @@ -874,13 +903,13 @@ struct FlowEventPlane { float tpcNsigma = 0., tofNsigma = 0.; for (auto const& track : tracks) { static constexpr std::string_view SubDir[] = {"Pion/", "Kaon/", "Proton/"}; - if (part == kPi) { + if (part == kPi && track.pt() > cMinPtPi) { tpcNsigma = track.tpcNSigmaPi(); tofNsigma = track.tofNSigmaPi(); - } else if (part == kKa) { + } else if (part == kKa && track.pt() > cMinPtKa) { tpcNsigma = track.tpcNSigmaKa(); tofNsigma = track.tofNSigmaKa(); - } else if (part == kPr) { + } else if (part == kPr && track.pt() > cMinPtPr) { tpcNsigma = track.tpcNSigmaPr(); tofNsigma = track.tofNSigmaPr(); } else { @@ -893,6 +922,7 @@ struct FlowEventPlane { histos.fill(HIST("PartId/") + HIST(SubDir[part]) + HIST("hTOFNSigma"), track.pt(), tofNsigma); } + // Directed flow ux = std::cos(track.phi()); uy = std::sin(track.phi()); v1a = ux * vSP[kXa] + uy * vSP[kYa]; @@ -916,40 +946,47 @@ struct FlowEventPlane { return false; } - // Apply DCA Selection on Daughter Tracks Based on Lambda/AntiLambda daughters - float dcaProton = 0., dcaPion = 0.; - if (part == kLambda) { - dcaProton = std::abs(v0.dcapostopv()); - dcaPion = std::abs(v0.dcanegtopv()); + // Apply DCA Selection on Daughter Tracks Based on Lambda/AntiLambda/K0Short daughters + if (part == kK0S) { + if (std::abs(v0.dcapostopv()) <= cMinDcaPionToPV || std::abs(v0.dcanegtopv()) <= cMinDcaPionToPV) { + return false; + } + } else if (part == kLambda) { + if (std::abs(v0.dcapostopv()) <= cMinDcaProtonToPV || std::abs(v0.dcanegtopv()) <= cMinDcaPionToPV) { + return false; + } } else if (part == kAntiLambda) { - dcaPion = std::abs(v0.dcapostopv()); - dcaProton = std::abs(v0.dcanegtopv()); + if (std::abs(v0.dcapostopv()) <= cMinDcaPionToPV || std::abs(v0.dcanegtopv()) <= cMinDcaProtonToPV) { + return false; + } } else { return false; } - if (dcaProton <= cMinDcaProtonToPV || dcaPion <= cMinDcaPionToPV) { - return false; - } - - // Daughter track PID - float tpcNSigmaPr = 0., tpcNSigmaPi = 0.; + // Daughter track PID [Dau1 = PosTrack, Dau2 = NegTrack] + float tpcNSigmaDau1 = 0., tpcNSigmaDau2 = 0.; switch (part) { - // postrack = Proton, negtrack = Pion + // Dau1 = Proton, Dau2 = Pion case kLambda: - tpcNSigmaPr = postrack.tpcNSigmaPr(); - tpcNSigmaPi = negtrack.tpcNSigmaPi(); + tpcNSigmaDau1 = postrack.tpcNSigmaPr(); + tpcNSigmaDau2 = negtrack.tpcNSigmaPi(); break; - // negtrack = Proton, postrack = Pion + // Dau1 = Pion, Dau2 = Proton case kAntiLambda: - tpcNSigmaPr = negtrack.tpcNSigmaPr(); - tpcNSigmaPi = postrack.tpcNSigmaPi(); + tpcNSigmaDau1 = postrack.tpcNSigmaPi(); + tpcNSigmaDau2 = negtrack.tpcNSigmaPr(); + break; + + // Dau1 = Pion, Dau2 = Pion + case kK0S: + tpcNSigmaDau1 = postrack.tpcNSigmaPi(); + tpcNSigmaDau2 = negtrack.tpcNSigmaPi(); break; } - if (std::abs(tpcNSigmaPr) >= cTpcNsigmaCut || std::abs(tpcNSigmaPi) >= cTpcNsigmaCut) { + if (std::abs(tpcNSigmaDau1) >= cTpcNsigmaCut || std::abs(tpcNSigmaDau2) >= cTpcNsigmaCut) { return false; } @@ -959,14 +996,20 @@ struct FlowEventPlane { template void fillV0QAHist(C const& col, V const& v0, T const&) { - static constexpr std::string_view SubDir[] = {"Lambda/QA/", "AntiLambda/QA/"}; + static constexpr std::string_view SubDir[] = {"V0/K0Short/QA/", "V0/Lambda/QA/", "V0/AntiLambda/QA/"}; // daugthers auto postrack = v0.template posTrack_as(); auto negtrack = v0.template negTrack_as(); // ctau - float ctau = v0.distovertotmom(col.posX(), col.posY(), col.posZ()) * MassLambda0; + float mPDG = 0, ctau = 0; + if (part == kK0S) { + mPDG = MassKaonNeutral; + } else { + mPDG = MassLambda0; + } + ctau = v0.distovertotmom(col.posX(), col.posY(), col.posZ()) * mPDG; histos.fill(HIST(SubDir[part]) + HIST("hQtVsAlpha"), v0.alpha(), v0.qtarm()); histos.fill(HIST(SubDir[part]) + HIST("hDcaV0Dau"), v0.dcaV0daughters()); @@ -984,10 +1027,11 @@ struct FlowEventPlane { histos.fill(HIST(SubDir[part]) + HIST("hNegNsigPiVsP"), negtrack.tpcInnerParam(), negtrack.tpcNSigmaPi()); } - template + template void getResoFlow(T const& tracks1, T const& tracks2, std::array const& vSP) { float ux = 0., uy = 0., v1a = 0., v1c = 0.; + std::array vMassDau = mResoDauMass.at(rt); for (auto const& [track1, track2] : soa::combinations(soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { // Discard same track if (track1.index() == track2.index()) { @@ -999,15 +1043,15 @@ struct FlowEventPlane { continue; } - // Apply rapidity acceptance + // Apply pseudo-rapidity acceptance std::array v = {track1.px() + track2.px(), track1.py() + track2.py(), track1.pz() + track2.pz()}; - if (RecoDecay::y(v, MassPhi) >= cResRapCut) { + if (std::abs(RecoDecay::eta(v)) >= cResRapCut) { continue; } - // Reconstruct phi meson + // Reconstruct resonance float p = RecoDecay::p((track1.px() + track2.px()), (track1.py() + track2.py()), (track1.pz() + track2.pz())); - float e = RecoDecay::e(track1.px(), track1.py(), track1.pz(), MassKaonCharged) + RecoDecay::e(track2.px(), track2.py(), track2.pz(), MassKaonCharged); + float e = RecoDecay::e(track1.px(), track1.py(), track1.pz(), vMassDau[0]) + RecoDecay::e(track2.px(), track2.py(), track2.pz(), vMassDau[1]); float m = std::sqrt(RecoDecay::m2(p, e)); // Get directed flow @@ -1016,10 +1060,13 @@ struct FlowEventPlane { v1a = ux * vSP[kXa] + uy * vSP[kYa]; v1c = ux * vSP[kXc] + uy * vSP[kYc]; + // Histograms + static constexpr std::string_view SubDir[] = {"Reso/Phi/", "Reso/KStar/"}; + // Fill signal histogram - histos.fill(HIST("Reso/Phi/hSigCentPtInvMass"), cent, RecoDecay::pt(v), m); - histos.fill(HIST("Reso/Phi/Sig/hPhiQuA"), cent, RecoDecay::y(v, MassPhi), m, v1a); - histos.fill(HIST("Reso/Phi/Sig/hPhiQuC"), cent, RecoDecay::y(v, MassPhi), m, v1c); + histos.fill(HIST(SubDir[rt]) + HIST("hSigCentEtaInvMass"), cent, RecoDecay::eta(v), m); + histos.fill(HIST(SubDir[rt]) + HIST("Sig/hQuA"), cent, RecoDecay::eta(v), m, v1a); + histos.fill(HIST(SubDir[rt]) + HIST("Sig/hQuC"), cent, RecoDecay::eta(v), m, v1c); // Get background p = RecoDecay::p((track1.px() - track2.px()), (track1.py() - track2.py()), (track1.pz() - track2.pz())); @@ -1033,9 +1080,9 @@ struct FlowEventPlane { v1c = ux * vSP[kXc] + uy * vSP[kYc]; // Fill bkg histogram - histos.fill(HIST("Reso/Phi/hBkgCentPtInvMass"), cent, RecoDecay::pt(v), m); - histos.fill(HIST("Reso/Phi/Bkg/hPhiQuA"), cent, RecoDecay::y(v, MassPhi), m, v1a); - histos.fill(HIST("Reso/Phi/Bkg/hPhiQuC"), cent, RecoDecay::y(v, MassPhi), m, v1c); + histos.fill(HIST(SubDir[rt]) + HIST("hBkgCentEtaInvMass"), cent, RecoDecay::eta(v), m); + histos.fill(HIST(SubDir[rt]) + HIST("Bkg/hQuA"), cent, RecoDecay::eta(v), m, v1a); + histos.fill(HIST(SubDir[rt]) + HIST("Bkg/hQuC"), cent, RecoDecay::eta(v), m, v1c); } } @@ -1113,14 +1160,16 @@ struct FlowEventPlane { } // Track partitions + auto pionTracks = pionTrackPartition->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); auto kaonTracks = kaonTrackPartition->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); // Resonance flow - getResoFlow(kaonTracks, kaonTracks, vSP); + getResoFlow(kaonTracks, kaonTracks, vSP); + getResoFlow(pionTracks, kaonTracks, vSP); } PROCESS_SWITCH(FlowEventPlane, processResoFlow, "Resonance flow process", false); - void processLambdaFlow(CollisionsRun3::iterator const& collision, aod::V0Datas const& V0s, TracksV0s const& tracks) + void processV0Flow(CollisionsRun3::iterator const& collision, aod::V0Datas const& V0s, TracksV0s const& tracks) { if (!selCollision(collision, vSP)) { return; @@ -1128,69 +1177,49 @@ struct FlowEventPlane { // Loop over v0s for (auto const& v0 : V0s) { - // V0 kinematic selection - if (v0.pt() <= cMinV0Pt || v0.pt() >= cMaxV0Pt || std::abs(v0.yLambda()) >= cV0RapCut) { - continue; - } - - // Topological selections - float ctau = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * MassLambda0; - if (v0.dcaV0daughters() >= cDcaV0Dau || v0.dcav0topv() >= cDcaV0ToPv || - v0.v0radius() <= cMinV0Radius || v0.v0radius() >= cMaxV0Radius || - v0.v0cosPA() <= cV0CosPA || ctau >= cV0CTau || v0.v0Type() != cV0TypeSelection) { + // Topological and kinematic selections + if (std::abs(v0.eta()) >= cV0RapCut || v0.dcaV0daughters() >= cDcaV0Dau || v0.dcav0topv() >= cDcaV0ToPv || v0.v0radius() <= cMinV0Radius || v0.v0Type() != cV0TypeSelection) { continue; } - // Ks Mass Rejection - if (std::abs(v0.mK0Short() - MassK0Short) <= cK0SMassRej) { - continue; - } - - // Initialize daughter tracks - auto postrack = v0.template posTrack_as(); - auto negtrack = v0.template negTrack_as(); - - // Initialize selection flags - bool lambdaFlag = false, antiLambdaFlag = false; - - // Get v0 track as lambda - if ((std::abs(v0.mLambda() - MassLambda0) < cLambdaMassWin) && (selV0DauTracks(v0, postrack, negtrack))) { - lambdaFlag = true; - } - - // Get v0 track as anti-lambda - if ((std::abs(v0.mAntiLambda() - MassLambda0) < cLambdaMassWin) && (selV0DauTracks(v0, postrack, negtrack))) { - antiLambdaFlag = true; - } - - // Lambda/Anti-Lambda selection checks - if (!lambdaFlag && !antiLambdaFlag) { // neither Lambda nor Anti-Lambda - continue; - } else if (lambdaFlag && antiLambdaFlag) { // check if the track is identified as lambda and anti-lambda both (DISCARD THIS TRACK) - continue; - } - - // We have a Lambda/Anti-Lambda // Directed flow float ux = std::cos(v0.phi()); float uy = std::sin(v0.phi()); float v1a = ux * vSP[kXa] + uy * vSP[kYa]; float v1c = ux * vSP[kXc] + uy * vSP[kYc]; - if (lambdaFlag) { + // Initialize selection objects + auto postrack = v0.template posTrack_as(); + auto negtrack = v0.template negTrack_as(); + float ctauK0Short = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * MassKaonNeutral; + float ctauLambda = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * MassLambda0; + + // K0Short + if (selV0DauTracks(v0, postrack, negtrack) && v0.v0cosPA() > mV0CosPA.at(kK0S) && ctauK0Short < mV0Ctau.at(kK0S) && v0.qtarm() >= cArmPodSel * std::abs(v0.alpha()) && v0.pt() >= cK0SMinPt && v0.pt() < cK0SMaxPt) { + fillV0QAHist(collision, v0, tracks); + histos.fill(HIST("V0/K0Short/hMassVsRap"), cent, v0.mK0Short(), v0.eta()); + histos.fill(HIST("V0/K0Short/Flow/hQuA"), cent, v0.eta(), v0.mK0Short(), v1a); + histos.fill(HIST("V0/K0Short/Flow/hQuC"), cent, v0.eta(), v0.mK0Short(), v1c); + } + + // Lambda + if (selV0DauTracks(v0, postrack, negtrack) && v0.v0cosPA() > mV0CosPA.at(kLambda) && ctauLambda < mV0Ctau.at(kLambda) && std::abs(v0.mK0Short() - MassK0Short) >= cK0SMassRej && v0.pt() >= cLambdaMinPt && v0.pt() < cLambdaMaxPt) { fillV0QAHist(collision, v0, tracks); - histos.fill(HIST("Lambda/hInvMassVsPt"), cent, v0.mLambda(), v0.pt()); - histos.fill(HIST("Lambda/Flow/hQuA"), cent, v0.yLambda(), v0.mLambda(), v1a); - histos.fill(HIST("Lambda/Flow/hQuC"), cent, v0.yLambda(), v0.mLambda(), v1c); - } else if (antiLambdaFlag) { + histos.fill(HIST("V0/Lambda/hMassVsRap"), cent, v0.mLambda(), v0.eta()); + histos.fill(HIST("V0/Lambda/Flow/hQuA"), cent, v0.eta(), v0.mLambda(), v1a); + histos.fill(HIST("V0/Lambda/Flow/hQuC"), cent, v0.eta(), v0.mLambda(), v1c); + } + + // AntiLambda + if (selV0DauTracks(v0, postrack, negtrack) && v0.v0cosPA() > mV0CosPA.at(kAntiLambda) && ctauLambda < mV0Ctau.at(kAntiLambda) && std::abs(v0.mK0Short() - MassK0Short) >= cK0SMassRej && v0.pt() >= cLambdaMinPt && v0.pt() < cLambdaMaxPt) { fillV0QAHist(collision, v0, tracks); - histos.fill(HIST("AntiLambda/hInvMassVsPt"), cent, v0.mAntiLambda(), v0.pt()); - histos.fill(HIST("AntiLambda/Flow/hQuA"), cent, v0.yLambda(), v0.mAntiLambda(), v1a); - histos.fill(HIST("AntiLambda/Flow/hQuC"), cent, v0.yLambda(), v0.mAntiLambda(), v1c); + histos.fill(HIST("V0/AntiLambda/hMassVsRap"), cent, v0.mAntiLambda(), v0.eta()); + histos.fill(HIST("V0/AntiLambda/Flow/hQuA"), cent, v0.eta(), v0.mAntiLambda(), v1a); + histos.fill(HIST("V0/AntiLambda/Flow/hQuC"), cent, v0.eta(), v0.mAntiLambda(), v1c); } } } - PROCESS_SWITCH(FlowEventPlane, processLambdaFlow, "Lambda flow process", false); + PROCESS_SWITCH(FlowEventPlane, processV0Flow, "Lambda flow process", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) From 9c07055ca980f6388cb42791332f7b1af73ba0d3 Mon Sep 17 00:00:00 2001 From: Shirajum Monira <38348689+Eloviyo@users.noreply.github.com> Date: Sat, 14 Mar 2026 15:49:54 +0100 Subject: [PATCH 279/347] [PWGCF] FemtoUniverse Cascade Task -- hasTOF check for combined simga (#15370) Co-authored-by: Shirajum Monira Co-authored-by: Shirajum Monira --- ...toUniversePairTaskTrackCascadeExtended.cxx | 53 ++++++++++++++----- 1 file changed, 41 insertions(+), 12 deletions(-) diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackCascadeExtended.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackCascadeExtended.cxx index 4002a0a1cac..6417529d529 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackCascadeExtended.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackCascadeExtended.cxx @@ -198,9 +198,9 @@ struct femtoUniversePairTaskTrackCascadeExtended { } } - bool isNSigmaCombined(float mom, float nsigmaTPCParticle, float nsigmaTOFParticle) + bool isNSigmaCombined(float mom, float nsigmaTPCParticle, float nsigmaTOFParticle, bool hasTOF) { - if (mom <= confmom) { + if (mom <= confmom || hasTOF == 0) { return (std::abs(nsigmaTPCParticle) < confNsigmaTPCParticle); } else { return (TMath::Hypot(nsigmaTOFParticle, nsigmaTPCParticle) < confNsigmaCombinedParticle); @@ -231,7 +231,7 @@ struct femtoUniversePairTaskTrackCascadeExtended { const float tpcNSigmas[3] = {aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePr()), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePi()), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStoreKa())}; const float tofNSigmas[3] = {aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePr()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePi()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStoreKa())}; - return isNSigmaCombined(part.p(), tpcNSigmas[id], tofNSigmas[id]); + return isNSigmaCombined(part.p(), tpcNSigmas[id], tofNSigmas[id], (part.pidCut() & 512u) != 0); } void init(InitContext const&) @@ -462,13 +462,13 @@ struct femtoUniversePairTaskTrackCascadeExtended { rXiQA.fill(HIST("hInvMpTmult"), part.pt(), part.mLambda(), multCol); } - if constexpr (std::experimental::is_detected::value) { - for (const auto& part : groupPartsOne) { + for (const auto& part : groupPartsOne) { + if constexpr (std::experimental::is_detected::value) { /// PID plot for track particle const float tpcNSigmas[3] = {aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePr()), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePi()), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStoreKa())}; const float tofNSigmas[3] = {aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePr()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePi()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStoreKa())}; - if (!isNSigmaCombined(part.p(), tpcNSigmas[confTrackChoicePartOne], tofNSigmas[confTrackChoicePartOne])) + if (!isNSigmaCombined(part.p(), tpcNSigmas[confTrackChoicePartOne], tofNSigmas[confTrackChoicePartOne], (part.pidCut() & 512u) != 0)) continue; if (part.mAntiLambda() > 0) { @@ -480,8 +480,21 @@ struct femtoUniversePairTaskTrackCascadeExtended { qaRegistry.fill(HIST("Tracks_neg/nSigmaTOF"), part.p(), tofNSigmas[confTrackChoicePartOne]); trackHistoPartOneNeg.fillQA(part); } + } else { + if ((part.pidCut() & 512u) != 0) { + if ((part.pidCut() & (64u << confTrackChoicePartOne)) == 0) + continue; + } else if ((part.pidCut() & (1u << confTrackChoicePartOne)) == 0) { + continue; + } + if (part.mAntiLambda() > 0) { + trackHistoPartOnePos.fillQA(part); + } else if (part.mAntiLambda() < 0) { + trackHistoPartOneNeg.fillQA(part); + } } } + for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { // Cascade inv mass cut (mLambda stores Xi mass, mAntiLambda stores Omega mass) if (!invMCascade(p2.mLambda(), p2.mAntiLambda(), confCascType1)) @@ -491,8 +504,12 @@ struct femtoUniversePairTaskTrackCascadeExtended { if (!isParticleCombined(p1, confTrackChoicePartOne)) continue; } else { - if ((p1.pidCut() & (64u << confTrackChoicePartOne)) == 0) + if ((p1.pidCut() & 512u) != 0) { + if ((p1.pidCut() & (64u << confTrackChoicePartOne)) == 0) + continue; + } else if ((p1.pidCut() & (1u << confTrackChoicePartOne)) == 0) { continue; + } } // track cleaning if (!pairCleaner.isCleanPair(p1, p2, parts)) { @@ -734,8 +751,12 @@ struct femtoUniversePairTaskTrackCascadeExtended { if (!isParticleCombined(p1, confTrackChoicePartOne)) continue; } else { - if ((p1.pidCut() & (64u << confTrackChoicePartOne)) == 0) + if ((p1.pidCut() & 512u) != 0) { + if ((p1.pidCut() & (64u << confTrackChoicePartOne)) == 0) + continue; + } else if ((p1.pidCut() & (1u << confTrackChoicePartOne)) == 0) { continue; + } } const auto& posChild = parts.iteratorAt(p2.globalIndex() - 3 - parts.begin().globalIndex()); @@ -1144,11 +1165,15 @@ struct femtoUniversePairTaskTrackCascadeExtended { if (mcpart.pdgMCTruth() != kProton) continue; if constexpr (std::experimental::is_detected::value) { - if (!isNSigmaCombined(part.p(), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePr()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePr()))) + if (!isNSigmaCombined(part.p(), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePr()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePr()), (part.pidCut() & 512u) != 0)) continue; } else { - if ((part.pidCut() & 64u) == 0) + if ((part.pidCut() & 512u) != 0) { + if ((part.pidCut() & 64u) == 0) + continue; + } else if ((part.pidCut() & 1u) == 0) { continue; + } } registryMCreco.fill(HIST("plus/MCrecoPr"), mcpart.pt(), mcpart.eta()); registryMCreco.fill(HIST("plus/MCrecoPrPt"), mcpart.pt()); @@ -1157,11 +1182,15 @@ struct femtoUniversePairTaskTrackCascadeExtended { if (mcpart.pdgMCTruth() != kProtonBar) continue; if constexpr (std::experimental::is_detected::value) { - if (!isNSigmaCombined(part.p(), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePr()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePr()))) + if (!isNSigmaCombined(part.p(), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePr()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePr()), (part.pidCut() & 512u) != 0)) continue; } else { - if ((part.pidCut() & 64u) == 0) + if ((part.pidCut() & 512u) != 0) { + if ((part.pidCut() & 64u) == 0) + continue; + } else if ((part.pidCut() & 1u) == 0) { continue; + } } registryMCreco.fill(HIST("minus/MCrecoPr"), mcpart.pt(), mcpart.eta()); registryMCreco.fill(HIST("minus/MCrecoPrPt"), mcpart.pt()); From 06cf3a249222aa33189f6d593ce770216d3b7307 Mon Sep 17 00:00:00 2001 From: Roman Lietava Date: Sat, 14 Mar 2026 16:55:59 +0100 Subject: [PATCH 280/347] [PWGLF] Omegahm: downscaling HBs (pileup study) (#15372) --- PWGLF/Tasks/Strangeness/nonPromptCascade.cxx | 55 ++++++++++++-------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/nonPromptCascade.cxx b/PWGLF/Tasks/Strangeness/nonPromptCascade.cxx index 7bb2b93ea4a..4527b2342af 100644 --- a/PWGLF/Tasks/Strangeness/nonPromptCascade.cxx +++ b/PWGLF/Tasks/Strangeness/nonPromptCascade.cxx @@ -9,6 +9,9 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. +#include "PWGLF/DataModel/LFNonPromptCascadeTables.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" + #include "Common/Core/RecoDecay.h" #include "Common/Core/Zorro.h" #include "Common/Core/ZorroSummary.h" @@ -34,6 +37,8 @@ #include "Framework/O2DatabasePDGPlugin.h" #include "Framework/runDataProcessing.h" #include "MathUtils/BetheBlochAleph.h" +#include "ReconstructionDataFormats/DCA.h" +#include "ReconstructionDataFormats/Track.h" #include "ReconstructionDataFormats/Vertex.h" #include "Math/Vector4D.h" @@ -42,16 +47,12 @@ #include "TParticlePDG.h" #include "TTree.h" +#include #include +#include #include #include #include -// #include "PWGHF/Core/PDG.h" -#include "PWGLF/DataModel/LFNonPromptCascadeTables.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" - -#include "ReconstructionDataFormats/DCA.h" -#include "ReconstructionDataFormats/Track.h" using namespace o2; using namespace o2::framework; @@ -813,7 +814,7 @@ struct NonPromptCascadeTask { std::vector mcMult(mcCollisions.size(), 0); for (auto const& mcp : mcParticles) { int mcid = mcp.mcCollisionId(); - if (mcid < 0 || mcid >= (int)mcMult.size()) + if (mcid < 0 || static_cast(mcid) >= mcMult.size()) continue; // apply your primary/eta/charge definition here @@ -823,7 +824,7 @@ struct NonPromptCascadeTask { continue; int q = 0; if (auto pdg = pdgDB->GetParticle(mcp.pdgCode())) { - q = int(std::round(pdg->Charge() / 3.0)); + q = static_cast(std::round(pdg->Charge() / 3.0)); } if (q == 0) continue; @@ -838,14 +839,14 @@ struct NonPromptCascadeTask { // ------------------------------------------------------------ int maxCollRowId = -1; for (auto const& trk : tracks) { - maxCollRowId = std::max(maxCollRowId, (int)trk.collisionId()); + maxCollRowId = std::max(maxCollRowId, static_cast(trk.collisionId())); } std::vector collRowIdToDense(maxCollRowId + 1, -1); int dense = 0; for (auto const& col : colls) { const int collRowId = col.globalIndex(); // row id in aod::Collisions - if (collRowId >= 0 && collRowId < (int)collRowIdToDense.size()) { + if (collRowId >= 0 && static_cast(collRowId) < collRowIdToDense.size()) { collRowIdToDense[collRowId] = dense; } ++dense; @@ -860,7 +861,7 @@ struct NonPromptCascadeTask { continue; } const int collRowId = trk.collisionId(); - if (collRowId < 0 || collRowId >= (int)collRowIdToDense.size()) { + if (collRowId < 0 || static_cast(collRowId) >= collRowIdToDense.size()) { continue; } const int dIdx = collRowIdToDense[collRowId]; @@ -890,7 +891,7 @@ struct NonPromptCascadeTask { // Map track's collision row id -> dense colls index const int collRowId = trk.collisionId(); - if (collRowId < 0 || collRowId >= (int)collRowIdToDense.size()) { + if (collRowId < 0 || static_cast(collRowId) >= collRowIdToDense.size()) { continue; } const int dIdx = collRowIdToDense[collRowId]; @@ -903,14 +904,14 @@ struct NonPromptCascadeTask { // MC collision id (row index in aod::McCollisions) const int mcCollId = col.mcCollisionId(); - if (mcCollId < 0 || mcCollId >= (int)mcCollisions.size()) { + if (mcCollId < 0 || static_cast(mcCollId) >= mcCollisions.size()) { continue; } mcReconstructed[mcCollId] = 1; // MC particle id (row index in aod::McParticles) const int mcPid = trk.mcParticleId(); - if (mcPid < 0 || mcPid >= (int)mcParticles.size()) { + if (mcPid < 0 || static_cast(mcPid) >= mcParticles.size()) { continue; } @@ -934,7 +935,7 @@ struct NonPromptCascadeTask { int q = 0; if (auto pdgEntry = pdgDB->GetParticle(mcPar.pdgCode())) { - q = int(std::round(pdgEntry->Charge() / 3.0)); + q = static_cast(std::round(pdgEntry->Charge() / 3.0)); } if (q == 0) { continue; @@ -954,7 +955,7 @@ struct NonPromptCascadeTask { // ------------------------------------------------------------ // MC particles with no reco track (iterate by row index) // ------------------------------------------------------------ - for (int pid = 0; pid < (int)mcParticles.size(); ++pid) { + for (int pid = 0; pid < static_cast(mcParticles.size()); ++pid) { if (!isReco[pid]) { auto mcp = mcParticles.rawIteratorAt(pid); mRegistrydNdeta.fill(HIST("hdNdetaRM/hdNdetaRMNotInRecoTrk"), isRecoMult[pid], mcp.pt()); @@ -964,7 +965,7 @@ struct NonPromptCascadeTask { // ------------------------------------------------------------ // Unreconstructed MC collisions (iterate by row index) // ------------------------------------------------------------ - for (int mcid = 0; mcid < (int)mcCollisions.size(); ++mcid) { + for (int mcid = 0; mcid < static_cast(mcCollisions.size()); ++mcid) { if (!mcReconstructed[mcid]) { std::vector mcptvec; const int mult = mcMult[mcid]; @@ -981,19 +982,29 @@ struct NonPromptCascadeTask { { // std::cout << "Processing pile up" << std::endl; int ds = 1; + uint32_t orbitO = 0; + bool writeFlag = 0; for (const auto& coll : collisions) { - if (ds == cfgDownscaleMB) { - auto bc = coll.template bc_as(); + auto bc = coll.template bc_as(); + uint64_t globalBC = bc.globalBC(); + uint32_t orbit = globalBC / 3564; + if (orbitO != orbit) { + orbitO = orbit; + if ((ds % cfgDownscaleMB) == 0) { + writeFlag = 1; + } else { + writeFlag = 0; + } + ds++; + } + if (writeFlag) { if (mRunNumber != bc.runNumber()) { mRunNumber = bc.runNumber(); } float centFT0M = coll.centFT0M(); float multFT0M = coll.multFT0M(); - uint64_t globalBC = bc.globalBC(); NPPUTable(mRunNumber, globalBC, coll.numContrib(), coll.multNTracksGlobal(), centFT0M, multFT0M); - ds = 0; } - ds++; } }; PROCESS_SWITCH(NonPromptCascadeTask, processPileUp, "pile up studies", true); From 00835da238ca2ff478ac919c440d9bb68fb66d99 Mon Sep 17 00:00:00 2001 From: skundu692 <86804743+skundu692@users.noreply.github.com> Date: Sat, 14 Mar 2026 19:01:21 +0100 Subject: [PATCH 281/347] [PWGLF] Add decay radius in mixing buffer (#15403) --- .../Strangeness/lambdaspincorrderived.cxx | 1441 ++++++----------- 1 file changed, 459 insertions(+), 982 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx b/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx index 4e9bbcbfaa8..222fb030962 100644 --- a/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx +++ b/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx @@ -179,6 +179,10 @@ struct lambdaspincorrderived { Configurable nolaterthan{"ccdb-no-later-than", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "Latest acceptable timestamp of creation for the object"}; } cfgCcdbParam; + struct : ConfigurableGroup { + ConfigurableAxis cfgMixRadiusBins{"cfgMixRadiusBins", {VARIABLE_WIDTH, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 10.0, 12.0, 15.0, 20.0, 25.0, 30.0}, "Radius bins for V6 radius buffer"}; + } cfgMixRadiusParam; + // Enable access to the CCDB for the offset and correction constants and save them in dedicated variables. Service ccdb; o2::ccdb::CcdbApi ccdbApi; @@ -205,8 +209,8 @@ struct lambdaspincorrderived { Configurable ConfWeightPathALL2{"ConfWeightPathALL2", "Users/s/skundu/My/Object/spincorr/cent010LL", "Weight path 2"}; // Mixing ///////// + Configurable cfgMixLegMode{"cfgMixLegMode", 0, "0=replace leg-1 only, 1=replace leg-2 only, 2=do both one-leg replacements"}; Configurable cfgV5MassBins{"cfgV5MassBins", 5, "Number of fixed mass bins for V5 mixing"}; - Configurable cfgV5NeighborPt{"cfgV5NeighborPt", 0, "v5: neighbor bins in pT (use symmetric ±N, edge-safe)"}; Configurable cfgV5NeighborEta{"cfgV5NeighborEta", 0, "v5: neighbor bins in eta (use symmetric ±N, edge-safe)"}; Configurable cfgV5NeighborPhi{"cfgV5NeighborPhi", 0, "v5: neighbor bins in phi (use symmetric ±N, periodic wrap)"}; @@ -273,6 +277,7 @@ struct lambdaspincorrderived { void init(o2::framework::InitContext&) { + histos.add("hPtRadiusV0", "V0 QA;#it{p}_{T}^{V0} (GeV/#it{c});V0 decay radius (cm)", kTH2F, {{100, 0.0, 10.0}, {120, 0.0, 45.0}}); histos.add("hPtYSame", "hPtYSame", kTH2F, {{100, 0.0, 10.0}, {200, -1.0, 1.0}}); histos.add("hPtYMix", "hPtYMix", kTH2F, {{100, 0.0, 10.0}, {200, -1.0, 1.0}}); histos.add("hCentrality", "Centrality distribution", kTH1F, {{configThnAxisCentrality}}); @@ -813,6 +818,7 @@ struct lambdaspincorrderived { if (!selectionV0(v0)) { continue; } + histos.fill(HIST("hPtRadiusV0"), v0.lambdaPt(), v0.v0Radius()); histos.fill(HIST("ptCent"), v0.lambdaPt(), centrality); histos.fill(HIST("etaCent"), v0.lambdaEta(), centrality); proton = ROOT::Math::PtEtaPhiMVector(v0.protonPt(), v0.protonEta(), v0.protonPhi(), o2::constants::physics::MassProton); @@ -864,160 +870,6 @@ struct lambdaspincorrderived { using BinningType = ColumnBinningPolicy; BinningType colBinning{{CfgVtxBins, CfgMultBins}, true}; Preslice tracksPerCollisionV0 = aod::lambdapair::lambdaeventId; - void processME(EventCandidates const& collisions, AllTrackCandidates const& V0s) - { - auto collOldIndex = -999; - std::vector t1Used; - for (auto& [collision1, collision2] : selfCombinations(colBinning, nEvtMixing, -1, collisions, collisions)) { - // LOGF(info, "Mixed event collisions: (%d, %d)", collision1.index(), collision2.index()); - // auto centrality = collision1.cent(); - auto groupV01 = V0s.sliceBy(tracksPerCollisionV0, collision1.index()); - auto groupV02 = V0s.sliceBy(tracksPerCollisionV0, collision1.index()); - auto groupV03 = V0s.sliceBy(tracksPerCollisionV0, collision2.index()); - auto collNewIndex = collision1.index(); - // LOGF(info, "Mixed event collisions: (%d, %d)", collNewIndex, collOldIndex); - if (collOldIndex != collNewIndex) { - t1Used.resize(groupV01.size(), false); - // std::fill(t1Used.begin(), t1Used.end(), false); - // std::vector t1Used(groupV01.size(), false); // <-- reset here - collOldIndex = collNewIndex; - } - for (auto& [t1, t3] : soa::combinations(o2::soa::CombinationsFullIndexPolicy(groupV01, groupV03))) { - if (t1Used[t1.index()]) { - continue; - } - if (!checkKinematics(t1, t3)) { - continue; - } - if (!selectionV0(t1)) { - continue; - } - if (!selectionV0(t3)) { - continue; - } - t1Used[t1.index()] = true; - for (const auto& t2 : groupV02) { - if (t2.index() <= t1.index()) { - continue; - } - if (!selectionV0(t2)) { - continue; - } - if (t1.protonIndex() == t2.protonIndex()) { - continue; - } - if (t1.pionIndex() == t2.pionIndex()) { - continue; - } - proton = ROOT::Math::PtEtaPhiMVector(t3.protonPt(), t3.protonEta(), t3.protonPhi(), o2::constants::physics::MassProton); - lambda = ROOT::Math::PtEtaPhiMVector(t3.lambdaPt(), t3.lambdaEta(), t3.lambdaPhi(), t3.lambdaMass()); - proton2 = ROOT::Math::PtEtaPhiMVector(t2.protonPt(), t2.protonEta(), t2.protonPhi(), o2::constants::physics::MassProton); - lambda2 = ROOT::Math::PtEtaPhiMVector(t2.lambdaPt(), t2.lambdaEta(), t2.lambdaPhi(), t2.lambdaMass()); - histos.fill(HIST("deltaPhiMix"), RecoDecay::constrainAngle(t3.lambdaPhi() - t2.lambdaPhi(), -TMath::Pi(), harmonicDphi)); - if (t3.v0Status() == 0 && t2.v0Status() == 0) { - fillHistograms(0, 0, lambda, lambda2, proton, proton2, 1, 1.0); - } - if (t3.v0Status() == 0 && t2.v0Status() == 1) { - fillHistograms(0, 1, lambda, lambda2, proton, proton2, 1, 1.0); - } - if (t3.v0Status() == 1 && t2.v0Status() == 0) { - fillHistograms(1, 0, lambda, lambda2, proton, proton2, 1, 1.0); - } - if (t3.v0Status() == 1 && t2.v0Status() == 1) { - fillHistograms(1, 1, lambda, lambda2, proton, proton2, 1, 1.0); - } - } - } // replacement track pair - } // collision pair - } - PROCESS_SWITCH(lambdaspincorrderived, processME, "Process data ME", false); - - void processMEV2(EventCandidates const& collisions, AllTrackCandidates const& V0s) - { - auto nBins = colBinning.getAllBinsCount(); - std::vector>> eventPools(nBins); - - for (auto& collision1 : collisions) { - int bin = colBinning.getBin(std::make_tuple(collision1.posz(), collision1.cent())); - auto poolA = V0s.sliceBy(tracksPerCollisionV0, collision1.index()); - // float centrality = collision1.cent(); - - // <<< CHANGED: map old collision index → set of (t2.idx, t3.idx) we've already filled - std::unordered_map>> seenMap; - - for (auto& [t1, t2] : soa::combinations(o2::soa::CombinationsFullIndexPolicy(poolA, poolA))) { - if (!selectionV0(t1) || !selectionV0(t2)) - continue; - if (t2.index() <= t1.index()) - continue; - if (t1.protonIndex() == t2.protonIndex()) - continue; - if (t1.pionIndex() == t2.pionIndex()) - continue; - - int mixes = 0; - for (auto it = eventPools[bin].rbegin(); it != eventPools[bin].rend() && mixes < nEvtMixing; ++it, ++mixes) { - int collision2idx = it->first; - AllTrackCandidates& poolB = it->second; - - int nRepl = 0; - for (auto& t3 : poolB) { - if (selectionV0(t3) && checkKinematics(t1, t3)) { - ++nRepl; - } - } - if (nRepl == 0) - continue; - float invN = 1.0f / static_cast(nRepl); - - for (auto& t3 : poolB) { - if (!(selectionV0(t3) && checkKinematics(t1, t3))) { - continue; - } - if (collision1.index() == collision2idx) { - continue; - } - - // <<< CHANGED: dedupe (t2, t3) pairs per prior collision - auto key = std::make_pair(t2.index(), t3.index()); - auto& seen = seenMap[collision2idx]; - if (!seen.insert(key).second) { - continue; - } - - // reconstruct 4-vectors - proton = ROOT::Math::PtEtaPhiMVector(t3.protonPt(), t3.protonEta(), t3.protonPhi(), o2::constants::physics::MassProton); - lambda = ROOT::Math::PtEtaPhiMVector(t3.lambdaPt(), t3.lambdaEta(), t3.lambdaPhi(), t3.lambdaMass()); - proton2 = ROOT::Math::PtEtaPhiMVector(t2.protonPt(), t2.protonEta(), t2.protonPhi(), o2::constants::physics::MassProton); - lambda2 = ROOT::Math::PtEtaPhiMVector(t2.lambdaPt(), t2.lambdaEta(), t2.lambdaPhi(), t2.lambdaMass()); - - float dPhi = RecoDecay::constrainAngle(RecoDecay::constrainAngle(lambda.Phi(), 0.0F, harmonic) - RecoDecay::constrainAngle(lambda2.Phi(), 0.0, harmonic), -TMath::Pi(), harmonicDphi); - histos.fill(HIST("deltaPhiMix"), dPhi, invN); - - if (t3.v0Status() == 0 && t2.v0Status() == 0) { - fillHistograms(0, 0, lambda, lambda2, proton, proton2, 1, invN); - } - if (t3.v0Status() == 0 && t2.v0Status() == 1) { - fillHistograms(0, 1, lambda, lambda2, proton, proton2, 1, invN); - } - if (t3.v0Status() == 1 && t2.v0Status() == 0) { - fillHistograms(1, 0, lambda, lambda2, proton, proton2, 1, invN); - } - if (t3.v0Status() == 1 && t2.v0Status() == 1) { - fillHistograms(1, 1, lambda, lambda2, proton, proton2, 1, invN); - } - } - } // end mixing-event loop - } // end same-event pair loop - - auto sliced = V0s.sliceBy(tracksPerCollisionV0, collision1.index()); - eventPools[bin].emplace_back(collision1.index(), std::move(sliced)); - if (static_cast(eventPools[bin].size()) > nEvtMixing) { - eventPools[bin].pop_front(); - } - } // end primary-event loop - } - PROCESS_SWITCH(lambdaspincorrderived, processMEV2, "Process data ME", false); void processMEV3(EventCandidates const& collisions, AllTrackCandidates const& V0s) { @@ -1232,6 +1084,133 @@ struct lambdaspincorrderived { out.erase(std::unique(out.begin(), out.end()), out.end()); } + static inline std::vector makeRadiusEdges(const ConfigurableAxis& ax) + { + std::vector edges; + edges.reserve(ax.value.size()); + for (auto v : ax.value) { + edges.push_back(static_cast(v)); + } + return edges; + } + + struct MixBinnerR { + float ptMin, ptMax, ptStep; + float etaMin, etaMax, etaStep; + float phiMin, phiMax, phiStep; + + float mMin, mMax, mStep; + int nM_; + + std::vector rEdges; + int nR_; + + int nPt_, nEta_, nPhi_; + + MixBinnerR(float ptMin_, float ptMax_, float ptStep_, + float etaAbsMax, float etaStep_, + float phiStep_, + float mMin_, float mMax_, int nMassBins_, + std::vector rEdges_) + : ptMin(ptMin_), + ptMax(ptMax_), + ptStep(ptStep_), + etaMin(-etaAbsMax), + etaMax(+etaAbsMax), + etaStep(etaStep_), + phiMin(-static_cast(TMath::Pi())), + phiMax(+static_cast(TMath::Pi())), + phiStep(phiStep_), + mMin(mMin_), + mMax(mMax_), + mStep(0.f), + nM_(std::max(1, nMassBins_)), + rEdges(std::move(rEdges_)), + nR_(0), + nPt_(0), + nEta_(0), + nPhi_(0) + { + ptStep = (ptStep > 0.f ? ptStep : 0.1f); + etaStep = (etaStep > 0.f ? etaStep : 0.1f); + phiStep = (phiStep > 0.f ? phiStep : 0.1f); + + if (!(mMax > mMin)) { + mMin = 1.09f; + mMax = 1.14f; + } + mStep = (mMax - mMin) / static_cast(nM_); + if (!(mStep > 0.f)) { + nM_ = 5; + mMin = 1.09f; + mMax = 1.14f; + mStep = (mMax - mMin) / static_cast(nM_); + } + + if (rEdges.size() < 2) { + rEdges = {3.0, 5.0, 7.0, 10.0, 15.0, 20.0, 25.0, 30.0, 35.0}; + } + nR_ = static_cast(rEdges.size()) - 1; + + nPt_ = std::max(1, static_cast(std::floor((ptMax - ptMin) / ptStep + 0.5f))); + nEta_ = std::max(1, static_cast(std::floor((etaMax - etaMin) / etaStep + 0.5f))); + nPhi_ = std::max(1, static_cast(std::ceil((phiMax - phiMin) / phiStep))); + } + + inline int nPt() const { return nPt_; } + inline int nEta() const { return nEta_; } + inline int nPhi() const { return nPhi_; } + inline int nM() const { return nM_; } + inline int nR() const { return nR_; } + + inline int binFromValue(float v, float vmin, float step, int nBins) const + { + if (!std::isfinite(v) || !std::isfinite(vmin) || !std::isfinite(step) || step <= 0.f || nBins <= 0) { + return -1; + } + const float x = (v - vmin) / step; + int b = static_cast(std::floor(x + 1e-6f)); + if (b < 0) { + return -1; + } + if (b >= nBins) { + b = nBins - 1; + } + return b; + } + + inline int ptBin(float pt) const { return binFromValue(pt, ptMin, ptStep, nPt_); } + inline int etaBin(float eta) const { return binFromValue(eta, etaMin, etaStep, nEta_); } + inline int phiBin(float phi) const { return binFromValue(phi, phiMin, phiStep, nPhi_); } + inline int massBin(float m) const { return binFromValue(m, mMin, mStep, nM_); } + + inline int radiusBin(float r) const + { + if (!std::isfinite(r) || nR_ <= 0) { + return -1; + } + if (r < rEdges.front() || r >= rEdges.back()) { + return -1; + } + auto it = std::upper_bound(rEdges.begin(), rEdges.end(), static_cast(r)); + return static_cast(it - rEdges.begin()) - 1; + } + }; + + struct BufferCandR { + int64_t collisionIdx; + int64_t rowIndex; + uint8_t v0Status; + uint16_t ptBin, etaBin, phiBin, mBin, rBin; + }; + + static inline size_t linearKeyR(int colBin, int statBin, + int ptBin, int etaBin, int phiBin, int mBin, int rBin, + int nStatus, int nPt, int nEta, int nPhi, int nM, int nR) + { + return (((((((static_cast(colBin) * nStatus + statBin) * nPt + ptBin) * nEta + etaBin) * nPhi + phiBin) * nM + mBin) * nR + rBin)); + } + // ===================== Main mixing (with mass-bin + random unique sampling) ===================== void processMEV4(EventCandidates const& collisions, AllTrackCandidates const& V0s) { @@ -1502,7 +1481,7 @@ struct lambdaspincorrderived { if (!selectionV0MC(v0)) { continue; } - + histos.fill(HIST("hPtRadiusV0"), mcacc::lamPt(v0), mcacc::v0Radius(v0)); histos.fill(HIST("ptCent"), mcacc::lamPt(v0), centrality); histos.fill(HIST("etaCent"), mcacc::lamEta(v0), centrality); @@ -1553,623 +1532,102 @@ struct lambdaspincorrderived { } PROCESS_SWITCH(lambdaspincorrderived, processMC, "Process MC (SE)", false); - void processMCMEV3(EventCandidatesMC const& collisions, AllTrackCandidatesMC const& V0sMC) + static inline float phi0To2Pi(float phi) { - auto nBins = colBinning.getAllBinsCount(); - std::vector>> eventPools(nBins); + // harmonic=1, min=0 => [0, 2pi) + return RecoDecay::constrainAngle(phi, 0.0f, 1); + } - for (auto& collision1 : collisions) { - const int bin = colBinning.getBin(std::make_tuple(collision1.poszmc(), collision1.centmc())); + static inline float deltaPhiMinusPiToPi(float phiA, float phiB) + { + // returns in [-pi, pi) + const float d = phi0To2Pi(phiA) - phi0To2Pi(phiB); + return RecoDecay::constrainAngle(d, -TMath::Pi(), 1); + } - // if pool empty, push and continue - if (eventPools[bin].empty()) { - auto sliced = V0sMC.sliceBy(tracksPerCollisionV0mc, collision1.index()); - eventPools[bin].emplace_back(collision1.index(), std::move(sliced)); - if ((int)eventPools[bin].size() > nEvtMixing) { - eventPools[bin].pop_front(); - } + static inline float absDeltaPhi(float phiA, float phiB) + { + return std::abs(deltaPhiMinusPiToPi(phiA, phiB)); + } + + // symmetric neighbors for continuous mixing (pt/eta): include bin, ±1, ±2..., edge-safe + static inline void collectNeighborBins1D(int b, int nBins, int nNeighbor, std::vector& out) + { + out.clear(); + out.reserve(2 * nNeighbor + 1); + for (int d = -nNeighbor; d <= nNeighbor; ++d) { + const int bb = b + d; + if (bb < 0 || bb >= nBins) { continue; } + out.push_back(bb); + } + std::sort(out.begin(), out.end()); + out.erase(std::unique(out.begin(), out.end()), out.end()); + } - // current event slice - auto poolA = V0sMC.sliceBy(tracksPerCollisionV0mc, collision1.index()); + // symmetric neighbors for phi: periodic wrap + static inline void collectNeighborBinsPhi(int b, int nPhi, int nNeighbor, std::vector& out) + { + out.clear(); + out.reserve(2 * nNeighbor + 1); + for (int d = -nNeighbor; d <= nNeighbor; ++d) { + int bb = b + d; + bb %= nPhi; + if (bb < 0) { + bb += nPhi; + } + out.push_back(bb); + } + std::sort(out.begin(), out.end()); + out.erase(std::unique(out.begin(), out.end()), out.end()); + } - // loop over SE unordered pairs (t1,t2) - for (auto& [t1, t2] : soa::combinations(o2::soa::CombinationsFullIndexPolicy(poolA, poolA))) { + static inline void collectNeighborBinsClamp(int b, int nBins, int nNeighbor, std::vector& out) + { + out.clear(); + out.reserve(2 * nNeighbor + 1); + for (int d = -nNeighbor; d <= nNeighbor; ++d) { + const int bb = b + d; + if (bb >= 0 && bb < nBins) { + out.push_back(bb); + } + } + } - // ---- selections ---- - if (!selectionV0MC(t1) || !selectionV0MC(t2)) { - continue; - } - if (t2.index() <= t1.index()) { - continue; - } + static inline void collectPhiBinsWithEdgeWrap(int phiB, int nPhi, std::vector& out) + { + out.clear(); + out.reserve(2); + out.push_back(phiB); + if (nPhi <= 1) { + return; + } + if (phiB == 0) { + out.push_back(nPhi - 1); + } else if (phiB == nPhi - 1) { + out.push_back(0); + } + } - // no shared daughters (use global indices stored in your MC table) - if (t1.protonIndexmc() == t2.protonIndexmc()) - continue; - if (t1.pionIndexmc() == t2.pionIndexmc()) - continue; - if (t1.protonIndexmc() == t2.pionIndexmc()) - continue; - if (t1.pionIndexmc() == t2.protonIndexmc()) - continue; - - // scan prior events for replacements for t1 - struct PV { - AllTrackCandidatesMC* pool; - int nRepl; - }; - std::vector usable; - int totalRepl = 0; - - int mixes = 0; - for (auto it = eventPools[bin].rbegin(); - it != eventPools[bin].rend() && mixes < nEvtMixing; ++it, ++mixes) { - - const int collision2idx = it->first; - auto& poolB = it->second; - if (collision2idx == collision1.index()) { - continue; - } - - int nRepl = 0; - for (auto& tX : poolB) { - if (!selectionV0MC(tX)) - continue; - if (checkKinematicsMC(t1, tX)) - ++nRepl; - } - if (nRepl > 0) { - usable.push_back(PV{&poolB, nRepl}); - totalRepl += nRepl; - } - } - - if (totalRepl == 0) { - continue; - } - const float wBase = 1.0f / static_cast(totalRepl); - - // emit mixed pairs: tX replaces t1; t2 stays - for (auto& pv : usable) { - auto& poolB = *pv.pool; - for (auto& tX : poolB) { - if (!selectionV0MC(tX)) - continue; - if (!checkKinematicsMC(t1, tX)) - continue; - - // build 4-vectors - auto proton = ROOT::Math::PtEtaPhiMVector(tX.protonPtmc(), tX.protonEtamc(), tX.protonPhimc(), o2::constants::physics::MassProton); - auto lambda = ROOT::Math::PtEtaPhiMVector(tX.lambdaPtmc(), tX.lambdaEtamc(), tX.lambdaPhimc(), tX.lambdaMassmc()); - auto proton2 = ROOT::Math::PtEtaPhiMVector(t2.protonPtmc(), t2.protonEtamc(), t2.protonPhimc(), o2::constants::physics::MassProton); - auto lambda2 = ROOT::Math::PtEtaPhiMVector(t2.lambdaPtmc(), t2.lambdaEtamc(), t2.lambdaPhimc(), t2.lambdaMassmc()); - - const float dPhi = RecoDecay::constrainAngle( - RecoDecay::constrainAngle(lambda.Phi(), 0.0F, harmonic) - - RecoDecay::constrainAngle(lambda2.Phi(), 0.0F, harmonic), - -TMath::Pi(), harmonicDphi); - - histos.fill(HIST("deltaPhiMix"), dPhi, wBase); - fillHistograms(tX.v0Statusmc(), t2.v0Statusmc(), lambda, lambda2, proton, proton2, 1, wBase); - } - } - } // end SE pair loop - - // push current event into pool - auto sliced = V0sMC.sliceBy(tracksPerCollisionV0mc, collision1.index()); - eventPools[bin].emplace_back(collision1.index(), std::move(sliced)); - if ((int)eventPools[bin].size() > nEvtMixing) { - eventPools[bin].pop_front(); - } - } // end events - } - - // enable it - PROCESS_SWITCH(lambdaspincorrderived, processMCMEV3, "Process MC ME (MEV3)", false); - - // ----------------------------------------------------- - // 5) MC Event Mixing using your MEV4 6D-buffer approach - // ----------------------------------------------------- - void processMCMEV4(EventCandidatesMC const& collisions, AllTrackCandidatesMC const& V0sMC) - { - MixBinner mb{ - ptMin.value, ptMax.value, ptMix.value, - v0etaMixBuffer.value, etaMix.value, - phiMix.value, - MassMin.value, MassMax.value, cfgV5MassBins.value}; - - const int nCol = colBinning.getAllBinsCount(); - const int nStat = N_STATUS; - const int nPt = mb.nPt(); - const int nEta = mb.nEta(); - const int nPhi = mb.nPhi(); - const int nM = mb.nM(); - - const size_t nKeys = static_cast(nCol) * nStat * nPt * nEta * nPhi * nM; - std::vector> buffer(nKeys); - - // ---- PASS 1: fill 6D buffer from MC tables ---- - for (auto const& col : collisions) { - const int colBin = colBinning.getBin(std::make_tuple(mcacc::posz(col), mcacc::cent(col))); - auto slice = V0sMC.sliceBy(tracksPerCollisionV0mc, col.index()); - - for (auto const& t : slice) { - if (!selectionV0MC(t)) { - continue; - } - - const int status = mcacc::v0Status(t); - if (status < 0 || status >= nStat) { - continue; - } - - const int ptB = mb.ptBin(mcacc::lamPt(t)); - const int etaB = mb.etaBin(mcacc::lamEta(t)); - const int phiB = mb.phiBin(RecoDecay::constrainAngle(mcacc::lamPhi(t), -TMath::Pi(), harmonic)); - const int mB = mb.massBin(mcacc::lamMass(t)); - if (ptB < 0 || etaB < 0 || phiB < 0 || mB < 0) { - continue; - } - - const size_t key = linearKey(colBin, status, ptB, etaB, phiB, mB, - nStat, nPt, nEta, nPhi, nM); - - buffer[key].push_back(BufferCand{ - .collisionIdx = static_cast(col.index()), - .rowIndex = static_cast(t.globalIndex()), - .v0Status = static_cast(status), - .ptBin = static_cast(ptB), - .etaBin = static_cast(etaB), - .phiBin = static_cast(phiB), - .mBin = static_cast(mB)}); - } - } - - // ---- PASS 2: build mixed pairs for each same-event pair (t1,t2) ---- - for (auto const& collision1 : collisions) { - const int colBin = colBinning.getBin(std::make_tuple(mcacc::posz(collision1), mcacc::cent(collision1))); - auto poolA = V0sMC.sliceBy(tracksPerCollisionV0mc, collision1.index()); - - for (auto const& [t1, t2] : - soa::combinations(o2::soa::CombinationsFullIndexPolicy(poolA, poolA))) { - - if (!selectionV0MC(t1) || !selectionV0MC(t2)) { - continue; - } - if (t2.index() <= t1.index()) { - continue; - } - - // no shared daughters - if (mcacc::prIdx(t1) == mcacc::prIdx(t2)) - continue; - if (mcacc::piIdx(t1) == mcacc::piIdx(t2)) - continue; - if (mcacc::prIdx(t1) == mcacc::piIdx(t2)) - continue; - if (mcacc::piIdx(t1) == mcacc::prIdx(t2)) - continue; - - const int status = mcacc::v0Status(t1); - if (status < 0 || status >= nStat) { - continue; - } - - const int ptB = mb.ptBin(mcacc::lamPt(t1)); - const int etaB = mb.etaBin(mcacc::lamEta(t1)); - const int phiB = mb.phiBin(RecoDecay::constrainAngle(mcacc::lamPhi(t1), -TMath::Pi(), harmonic)); - const int mB = mb.massBin(mcacc::lamMass(t1)); - if (ptB < 0 || etaB < 0 || phiB < 0 || mB < 0) { - continue; - } - std::vector matches; - matches.reserve(128); - const int64_t curColIdx = static_cast(collision1.index()); - auto collectFrom = [&](int phiBinUse) { - const size_t keyUse = linearKey(colBin, status, ptB, etaB, phiBinUse, mB, - nStat, nPt, nEta, nPhi, nM); - auto const& vec = buffer[keyUse]; - for (const auto& bc : vec) { - if (bc.collisionIdx == curColIdx) { - continue; // different event - } - auto tX = V0sMC.iteratorAt(static_cast(bc.rowIndex)); - if (!selectionV0MC(tX)) { - continue; - } - if (!checkKinematicsMC(t1, tX)) { - continue; - } - if (!checkPairKinematicsMC(t1, t2, tX)) { - continue; - } - matches.push_back(MatchRef{bc.collisionIdx, bc.rowIndex}); - } - }; - - // nominal φ-bin + wrap neighbors only at edges - collectFrom(phiB); - if (phiB == 0) { - collectFrom(nPhi - 1); - } else if (phiB == nPhi - 1) { - collectFrom(0); - } - - if (matches.empty()) { - continue; - } - - // dedupe identical (collision,row) - std::sort(matches.begin(), matches.end(), - [](auto& a, auto& b) { return std::tie(a.collisionIdx, a.rowIndex) < std::tie(b.collisionIdx, b.rowIndex); }); - matches.erase(std::unique(matches.begin(), matches.end(), - [](auto& a, auto& b) { return a.collisionIdx == b.collisionIdx && a.rowIndex == b.rowIndex; }), - matches.end()); - if (matches.empty()) { - continue; - } - - const float wBase = 1.0f / static_cast(matches.size()); - - for (const auto& m : matches) { - auto tX = V0sMC.iteratorAt(static_cast(m.rowIndex)); - - auto pX = ROOT::Math::PtEtaPhiMVector(mcacc::prPt(tX), mcacc::prEta(tX), mcacc::prPhi(tX), - o2::constants::physics::MassProton); - auto lX = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(tX), mcacc::lamEta(tX), mcacc::lamPhi(tX), - mcacc::lamMass(tX)); - auto p2 = ROOT::Math::PtEtaPhiMVector(mcacc::prPt(t2), mcacc::prEta(t2), mcacc::prPhi(t2), - o2::constants::physics::MassProton); - auto l2 = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(t2), mcacc::lamEta(t2), mcacc::lamPhi(t2), - mcacc::lamMass(t2)); - - const float dPhi = RecoDecay::constrainAngle( - RecoDecay::constrainAngle(lX.Phi(), 0.0F, harmonic) - - RecoDecay::constrainAngle(l2.Phi(), 0.0F, harmonic), - -TMath::Pi(), harmonicDphi); - - histos.fill(HIST("deltaPhiMix"), dPhi, wBase); - - // datatype=1 (mixed event) - fillHistograms(mcacc::v0Status(tX), mcacc::v0Status(t2), - lX, l2, pX, p2, - /*datatype=*/1, /*mixpairweight=*/wBase); - } - } - } - } - PROCESS_SWITCH(lambdaspincorrderived, processMCMEV4, "Process MC ME (5d buffer)", false); - - static inline float phi0To2Pi(float phi) - { - // harmonic=1, min=0 => [0, 2pi) - return RecoDecay::constrainAngle(phi, 0.0f, 1); - } - - static inline float deltaPhiMinusPiToPi(float phiA, float phiB) - { - // returns in [-pi, pi) - const float d = phi0To2Pi(phiA) - phi0To2Pi(phiB); - return RecoDecay::constrainAngle(d, -TMath::Pi(), 1); - } - - static inline float absDeltaPhi(float phiA, float phiB) - { - return std::abs(deltaPhiMinusPiToPi(phiA, phiB)); - } - - // symmetric neighbors for continuous mixing (pt/eta): include bin, ±1, ±2..., edge-safe - static inline void collectNeighborBins1D(int b, int nBins, int nNeighbor, std::vector& out) - { - out.clear(); - out.reserve(2 * nNeighbor + 1); - for (int d = -nNeighbor; d <= nNeighbor; ++d) { - const int bb = b + d; - if (bb < 0 || bb >= nBins) { - continue; - } - out.push_back(bb); - } - std::sort(out.begin(), out.end()); - out.erase(std::unique(out.begin(), out.end()), out.end()); - } - - // symmetric neighbors for phi: periodic wrap - static inline void collectNeighborBinsPhi(int b, int nPhi, int nNeighbor, std::vector& out) - { - out.clear(); - out.reserve(2 * nNeighbor + 1); - for (int d = -nNeighbor; d <= nNeighbor; ++d) { - int bb = b + d; - bb %= nPhi; - if (bb < 0) { - bb += nPhi; - } - out.push_back(bb); - } - std::sort(out.begin(), out.end()); - out.erase(std::unique(out.begin(), out.end()), out.end()); - } - - static inline void collectNeighborBinsClamp(int b, int nBins, int nNeighbor, std::vector& out) - { - out.clear(); - out.reserve(2 * nNeighbor + 1); - for (int d = -nNeighbor; d <= nNeighbor; ++d) { - const int bb = b + d; - if (bb >= 0 && bb < nBins) { - out.push_back(bb); - } - } - } - - static inline void collectPhiBinsWithEdgeWrap(int phiB, int nPhi, std::vector& out) - { - out.clear(); - out.reserve(2); - out.push_back(phiB); - if (nPhi <= 1) { - return; - } - if (phiB == 0) { - out.push_back(nPhi - 1); - } else if (phiB == nPhi - 1) { - out.push_back(0); - } - } - - static inline uint64_t splitmix64(uint64_t x) - { - // simple deterministic hash for reproducible shuffling - x += 0x9e3779b97f4a7c15ULL; - x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9ULL; - x = (x ^ (x >> 27)) * 0x94d049bb133111ebULL; - return x ^ (x >> 31); - } - - static inline uint64_t splitmixmc64(uint64_t x) - { - x += 0x9e3779b97f4a7c15ULL; - x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9ULL; - x = (x ^ (x >> 27)) * 0x94d049bb133111ebULL; - return x ^ (x >> 31); - } - - void processMEV5(EventCandidates const& collisions, AllTrackCandidates const& V0s) - { - MixBinner mb{ - ptMin.value, ptMax.value, ptMix.value, - v0etaMixBuffer.value, etaMix.value, - phiMix.value, - MassMin.value, MassMax.value, cfgV5MassBins.value}; - - const int nCol = colBinning.getAllBinsCount(); - const int nStat = N_STATUS; - const int nPt = mb.nPt(); - const int nEta = mb.nEta(); // logical "nY" if userapidity=true - const int nPhi = mb.nPhi(); - const int nM = mb.nM(); - - const size_t nKeys = static_cast(nCol) * nStat * nPt * nEta * nPhi * nM; - std::vector> buffer(nKeys); - - // -------- PASS 1: fill buffer -------- - for (auto const& col : collisions) { - const int colBin = colBinning.getBin(std::make_tuple(col.posz(), col.cent())); - if (colBin < 0) { - continue; - } - - auto slice = V0s.sliceBy(tracksPerCollisionV0, col.index()); - - for (auto const& t : slice) { - if (!selectionV0(t)) { - continue; - } - - const int status = static_cast(t.v0Status()); - if (status < 0 || status >= nStat) { - continue; - } - - const int ptB = mb.ptBin(t.lambdaPt()); - - int etaB = mb.etaBin(t.lambdaEta()); - if (userapidity) { - const auto lv = ROOT::Math::PtEtaPhiMVector(t.lambdaPt(), t.lambdaEta(), t.lambdaPhi(), t.lambdaMass()); - etaB = mb.etaBin(lv.Rapidity()); // treat "eta axis" as rapidity axis - } - - const int phiB = mb.phiBin(RecoDecay::constrainAngle(t.lambdaPhi(), -TMath::Pi(), harmonic)); - const int mB = mb.massBin(t.lambdaMass()); - - if (ptB < 0 || etaB < 0 || phiB < 0 || mB < 0) { - continue; - } - - const size_t key = linearKey(colBin, status, ptB, etaB, phiB, mB, - nStat, nPt, nEta, nPhi, nM); - - buffer[key].push_back(BufferCand{ - .collisionIdx = static_cast(col.index()), - .rowIndex = static_cast(t.globalIndex()), - .v0Status = static_cast(status), - .ptBin = static_cast(ptB), - .etaBin = static_cast(etaB), - .phiBin = static_cast(phiB), - .mBin = static_cast(mB)}); - } - } - - // Neighbor policy from configurables - const int nN_pt = std::max(0, cfgV5NeighborPt.value); - const int nN_eta = std::max(0, cfgV5NeighborEta.value); - const int nN_phi = std::max(0, cfgV5NeighborPhi.value); - - std::vector ptBins, etaBins, phiBins; - std::vector matches; - matches.reserve(256); - - // -------- PASS 2: mix (replace t1 by tX, keep t2 from same event) -------- - for (auto const& col1 : collisions) { - const int colBin = colBinning.getBin(std::make_tuple(col1.posz(), col1.cent())); - if (colBin < 0) { - continue; - } - - const int64_t curColIdx = static_cast(col1.index()); - auto poolA = V0s.sliceBy(tracksPerCollisionV0, col1.index()); - - for (auto const& [t1, t2] : - soa::combinations(o2::soa::CombinationsFullIndexPolicy(poolA, poolA))) { - - if (!selectionV0(t1) || !selectionV0(t2)) { - continue; - } - if (t2.index() <= t1.index()) { - continue; // same-event ordering - } - - // no shared daughters (same-event) - if (t1.protonIndex() == t2.protonIndex()) - continue; - if (t1.pionIndex() == t2.pionIndex()) - continue; - if (t1.protonIndex() == t2.pionIndex()) - continue; - if (t1.pionIndex() == t2.protonIndex()) - continue; - - const int status = static_cast(t1.v0Status()); - if (status < 0 || status >= nStat) { - continue; - } - - const int ptB = mb.ptBin(t1.lambdaPt()); - - int etaB = mb.etaBin(t1.lambdaEta()); - if (userapidity) { - const auto lv1 = ROOT::Math::PtEtaPhiMVector(t1.lambdaPt(), t1.lambdaEta(), t1.lambdaPhi(), t1.lambdaMass()); - etaB = mb.etaBin(lv1.Rapidity()); - } - - const int phiB = mb.phiBin(RecoDecay::constrainAngle(t1.lambdaPhi(), -TMath::Pi(), harmonic)); - const int mB = mb.massBin(t1.lambdaMass()); - - if (ptB < 0 || etaB < 0 || phiB < 0 || mB < 0) { - continue; - } - - collectNeighborBinsClamp(ptB, nPt, nN_pt, ptBins); - collectNeighborBinsClamp(etaB, nEta, nN_eta, etaBins); - collectNeighborBinsPhi(phiB, nPhi, nN_phi, phiBins); - - matches.clear(); - - for (int ptUse : ptBins) { - for (int etaUse : etaBins) { - for (int phiUse : phiBins) { - const size_t keyUse = linearKey(colBin, status, ptUse, etaUse, phiUse, mB, - nStat, nPt, nEta, nPhi, nM); - auto const& vec = buffer[keyUse]; - - for (auto const& bc : vec) { - if (bc.collisionIdx == curColIdx) { - continue; // enforce different event - } - - auto tX = V0s.iteratorAt(static_cast(bc.rowIndex)); - if (!selectionV0(tX)) { - continue; - } - - if (!checkKinematics(t1, tX)) { - continue; - } - - if (tX.globalIndex() == t1.globalIndex()) - continue; - if (tX.globalIndex() == t2.globalIndex()) - continue; - - matches.push_back(MatchRef{bc.collisionIdx, bc.rowIndex}); - } - } - } - } - - if (matches.empty()) { - continue; - } - - std::sort(matches.begin(), matches.end(), - [](auto const& a, auto const& b) { - return std::tie(a.collisionIdx, a.rowIndex) < std::tie(b.collisionIdx, b.rowIndex); - }); - matches.erase(std::unique(matches.begin(), matches.end(), - [](auto const& a, auto const& b) { - return a.collisionIdx == b.collisionIdx && a.rowIndex == b.rowIndex; - }), - matches.end()); - if (matches.empty()) { - continue; - } - - if (cfgV5MaxMatches.value > 0 && (int)matches.size() > cfgV5MaxMatches.value) { - uint64_t seed = cfgMixSeed.value; - seed ^= splitmix64((uint64_t)t1.globalIndex()); - seed ^= splitmix64((uint64_t)t2.globalIndex() + 0x1234567ULL); - seed ^= splitmix64((uint64_t)curColIdx + 0x9abcULL); - - const int K = cfgV5MaxMatches.value; - for (int i = 0; i < K; ++i) { - seed = splitmix64(seed); - const int j = i + (int)(seed % (uint64_t)(matches.size() - i)); - std::swap(matches[i], matches[j]); - } - matches.resize(K); - } - - const float wBase = 1.0f / static_cast(matches.size()); - - for (auto const& m : matches) { - auto tX = V0s.iteratorAt(static_cast(m.rowIndex)); - - auto proton = ROOT::Math::PtEtaPhiMVector(tX.protonPt(), tX.protonEta(), tX.protonPhi(), - o2::constants::physics::MassProton); - auto lambda = ROOT::Math::PtEtaPhiMVector(tX.lambdaPt(), tX.lambdaEta(), tX.lambdaPhi(), - tX.lambdaMass()); - - auto proton2 = ROOT::Math::PtEtaPhiMVector(t2.protonPt(), t2.protonEta(), t2.protonPhi(), - o2::constants::physics::MassProton); - auto lambda2 = ROOT::Math::PtEtaPhiMVector(t2.lambdaPt(), t2.lambdaEta(), t2.lambdaPhi(), - t2.lambdaMass()); + static inline uint64_t splitmix64(uint64_t x) + { + // simple deterministic hash for reproducible shuffling + x += 0x9e3779b97f4a7c15ULL; + x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9ULL; + x = (x ^ (x >> 27)) * 0x94d049bb133111ebULL; + return x ^ (x >> 31); + } - const int ptype = pairTypeCode(tX.v0Status(), t2.v0Status()); - double centPairWeight = 1.0; - if (hweightCentPair) { - const int bin = hweightCentPair->FindBin(col1.cent(), ptype); - centPairWeight = hweightCentPair->GetBinContent(bin); - if (centPairWeight <= 0.0) { - centPairWeight = 1.0; - } - } - const float meWeight = wBase * centPairWeight; - const float dPhi = deltaPhiMinusPiToPi((float)lambda.Phi(), (float)lambda2.Phi()); - histos.fill(HIST("deltaPhiMix"), dPhi, wBase); - histos.fill(HIST("hCentPairTypeME"), col1.cent(), ptype, wBase); - fillHistograms(tX.v0Status(), t2.v0Status(), - lambda, lambda2, proton, proton2, - /*datatype=*/1, /*mixpairweight=*/meWeight); - } - } - } + static inline uint64_t splitmixmc64(uint64_t x) + { + x += 0x9e3779b97f4a7c15ULL; + x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9ULL; + x = (x ^ (x >> 27)) * 0x94d049bb133111ebULL; + return x ^ (x >> 31); } - PROCESS_SWITCH(lambdaspincorrderived, processMEV5, "Process data ME v5", false); - void processMCMEV5(EventCandidatesMC const& collisions, AllTrackCandidatesMC const& V0sMC) + void processMEV5(EventCandidates const& collisions, AllTrackCandidates const& V0s) { MixBinner mb{ ptMin.value, ptMax.value, ptMix.value, @@ -2189,51 +1647,53 @@ struct lambdaspincorrderived { // -------- PASS 1: fill buffer -------- for (auto const& col : collisions) { - const int colBin = colBinning.getBin(std::make_tuple(mcacc::posz(col), mcacc::cent(col))); + const int colBin = colBinning.getBin(std::make_tuple(col.posz(), col.cent())); if (colBin < 0) { continue; } - auto slice = V0sMC.sliceBy(tracksPerCollisionV0mc, col.index()); + auto slice = V0s.sliceBy(tracksPerCollisionV0, col.index()); for (auto const& t : slice) { - if (!selectionV0MC(t)) { + if (!selectionV0(t)) { continue; } - const int status = mcacc::v0Status(t); + const int status = static_cast(t.v0Status()); if (status < 0 || status >= nStat) { continue; } - const int ptB = mb.ptBin(mcacc::lamPt(t)); + const int ptB = mb.ptBin(t.lambdaPt()); - int etaB = mb.etaBin(mcacc::lamEta(t)); + int etaB = mb.etaBin(t.lambdaEta()); if (userapidity) { - const auto lv = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(t), mcacc::lamEta(t), - mcacc::lamPhi(t), mcacc::lamMass(t)); - etaB = mb.etaBin(lv.Rapidity()); + const auto lv = ROOT::Math::PtEtaPhiMVector(t.lambdaPt(), t.lambdaEta(), t.lambdaPhi(), t.lambdaMass()); + etaB = mb.etaBin(lv.Rapidity()); // treat "eta axis" as rapidity axis } - const int phiB = mb.phiBin(RecoDecay::constrainAngle(mcacc::lamPhi(t), -TMath::Pi(), harmonic)); - const int mB = mb.massBin(mcacc::lamMass(t)); + const int phiB = mb.phiBin(RecoDecay::constrainAngle(t.lambdaPhi(), -TMath::Pi(), harmonic)); + const int mB = mb.massBin(t.lambdaMass()); + if (ptB < 0 || etaB < 0 || phiB < 0 || mB < 0) { continue; } - buffer[linearKey(colBin, status, ptB, etaB, phiB, mB, - nStat, nPt, nEta, nPhi, nM)] - .push_back(BufferCand{ - .collisionIdx = static_cast(col.index()), - .rowIndex = static_cast(t.globalIndex()), - .v0Status = static_cast(status), - .ptBin = static_cast(ptB), - .etaBin = static_cast(etaB), - .phiBin = static_cast(phiB), - .mBin = static_cast(mB)}); + const size_t key = linearKey(colBin, status, ptB, etaB, phiB, mB, + nStat, nPt, nEta, nPhi, nM); + + buffer[key].push_back(BufferCand{ + .collisionIdx = static_cast(col.index()), + .rowIndex = static_cast(t.globalIndex()), + .v0Status = static_cast(status), + .ptBin = static_cast(ptB), + .etaBin = static_cast(etaB), + .phiBin = static_cast(phiB), + .mBin = static_cast(mB)}); } } + // Neighbor policy from configurables const int nN_pt = std::max(0, cfgV5NeighborPt.value); const int nN_eta = std::max(0, cfgV5NeighborEta.value); const int nN_phi = std::max(0, cfgV5NeighborPhi.value); @@ -2242,53 +1702,56 @@ struct lambdaspincorrderived { std::vector matches; matches.reserve(256); - // -------- PASS 2: build ME -------- + // -------- PASS 2: mix (replace t1 by tX, keep t2 from same event) -------- for (auto const& col1 : collisions) { - const int colBin = colBinning.getBin(std::make_tuple(mcacc::posz(col1), mcacc::cent(col1))); + const int colBin = colBinning.getBin(std::make_tuple(col1.posz(), col1.cent())); if (colBin < 0) { continue; } const int64_t curColIdx = static_cast(col1.index()); - auto poolA = V0sMC.sliceBy(tracksPerCollisionV0mc, col1.index()); + auto poolA = V0s.sliceBy(tracksPerCollisionV0, col1.index()); for (auto const& [t1, t2] : soa::combinations(o2::soa::CombinationsFullIndexPolicy(poolA, poolA))) { - if (!selectionV0MC(t1) || !selectionV0MC(t2)) { + if (!selectionV0(t1) || !selectionV0(t2)) { continue; } if (t2.index() <= t1.index()) { - continue; + continue; // same-event ordering } - if (mcacc::prIdx(t1) == mcacc::prIdx(t2)) + // no shared daughters (same-event) + if (t1.protonIndex() == t2.protonIndex()) continue; - if (mcacc::piIdx(t1) == mcacc::piIdx(t2)) + if (t1.pionIndex() == t2.pionIndex()) continue; - if (mcacc::prIdx(t1) == mcacc::piIdx(t2)) + if (t1.protonIndex() == t2.pionIndex()) continue; - if (mcacc::piIdx(t1) == mcacc::prIdx(t2)) + if (t1.pionIndex() == t2.protonIndex()) continue; - const int status = mcacc::v0Status(t1); + const int status = static_cast(t1.v0Status()); if (status < 0 || status >= nStat) { continue; } - const int ptB = mb.ptBin(mcacc::lamPt(t1)); + const int ptB = mb.ptBin(t1.lambdaPt()); - int etaB = mb.etaBin(mcacc::lamEta(t1)); + int etaB = mb.etaBin(t1.lambdaEta()); if (userapidity) { - const auto lv1 = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(t1), mcacc::lamEta(t1), - mcacc::lamPhi(t1), mcacc::lamMass(t1)); + const auto lv1 = ROOT::Math::PtEtaPhiMVector(t1.lambdaPt(), t1.lambdaEta(), t1.lambdaPhi(), t1.lambdaMass()); etaB = mb.etaBin(lv1.Rapidity()); } - const int phiB = mb.phiBin(RecoDecay::constrainAngle(mcacc::lamPhi(t1), -TMath::Pi(), harmonic)); - const int mB = mb.massBin(mcacc::lamMass(t1)); + + const int phiB = mb.phiBin(RecoDecay::constrainAngle(t1.lambdaPhi(), -TMath::Pi(), harmonic)); + const int mB = mb.massBin(t1.lambdaMass()); + if (ptB < 0 || etaB < 0 || phiB < 0 || mB < 0) { continue; } + collectNeighborBinsClamp(ptB, nPt, nN_pt, ptBins); collectNeighborBinsClamp(etaB, nEta, nN_eta, etaBins); collectNeighborBinsPhi(phiB, nPhi, nN_phi, phiBins); @@ -2298,18 +1761,21 @@ struct lambdaspincorrderived { for (int ptUse : ptBins) { for (int etaUse : etaBins) { for (int phiUse : phiBins) { - auto const& vec = buffer[linearKey(colBin, status, ptUse, etaUse, phiUse, mB, - nStat, nPt, nEta, nPhi, nM)]; + const size_t keyUse = linearKey(colBin, status, ptUse, etaUse, phiUse, mB, + nStat, nPt, nEta, nPhi, nM); + auto const& vec = buffer[keyUse]; + for (auto const& bc : vec) { if (bc.collisionIdx == curColIdx) { - continue; + continue; // enforce different event } - auto tX = V0sMC.iteratorAt(static_cast(bc.rowIndex)); - if (!selectionV0MC(tX)) { + auto tX = V0s.iteratorAt(static_cast(bc.rowIndex)); + if (!selectionV0(tX)) { continue; } - if (!checkKinematicsMC(t1, tX)) { + + if (!checkKinematics(t1, tX)) { continue; } @@ -2359,47 +1825,47 @@ struct lambdaspincorrderived { const float wBase = 1.0f / static_cast(matches.size()); for (auto const& m : matches) { - auto tX = V0sMC.iteratorAt(static_cast(m.rowIndex)); + auto tX = V0s.iteratorAt(static_cast(m.rowIndex)); - auto pX = ROOT::Math::PtEtaPhiMVector(mcacc::prPt(tX), mcacc::prEta(tX), mcacc::prPhi(tX), - o2::constants::physics::MassProton); - auto lX = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(tX), mcacc::lamEta(tX), mcacc::lamPhi(tX), - mcacc::lamMass(tX)); + auto proton = ROOT::Math::PtEtaPhiMVector(tX.protonPt(), tX.protonEta(), tX.protonPhi(), + o2::constants::physics::MassProton); + auto lambda = ROOT::Math::PtEtaPhiMVector(tX.lambdaPt(), tX.lambdaEta(), tX.lambdaPhi(), + tX.lambdaMass()); - auto p2 = ROOT::Math::PtEtaPhiMVector(mcacc::prPt(t2), mcacc::prEta(t2), mcacc::prPhi(t2), - o2::constants::physics::MassProton); - auto l2 = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(t2), mcacc::lamEta(t2), mcacc::lamPhi(t2), - mcacc::lamMass(t2)); + auto proton2 = ROOT::Math::PtEtaPhiMVector(t2.protonPt(), t2.protonEta(), t2.protonPhi(), + o2::constants::physics::MassProton); + auto lambda2 = ROOT::Math::PtEtaPhiMVector(t2.lambdaPt(), t2.lambdaEta(), t2.lambdaPhi(), + t2.lambdaMass()); - const int ptype = pairTypeCode(mcacc::v0Status(tX), mcacc::v0Status(t2)); + const int ptype = pairTypeCode(tX.v0Status(), t2.v0Status()); double centPairWeight = 1.0; if (hweightCentPair) { - const int bin = hweightCentPair->FindBin(mcacc::cent(col1), ptype); + const int bin = hweightCentPair->FindBin(col1.cent(), ptype); centPairWeight = hweightCentPair->GetBinContent(bin); if (centPairWeight <= 0.0) { centPairWeight = 1.0; } } const float meWeight = wBase * centPairWeight; - const float dPhi = deltaPhiMinusPiToPi((float)lX.Phi(), (float)l2.Phi()); + const float dPhi = deltaPhiMinusPiToPi((float)lambda.Phi(), (float)lambda2.Phi()); histos.fill(HIST("deltaPhiMix"), dPhi, wBase); - histos.fill(HIST("hCentPairTypeME"), mcacc::cent(col1), ptype, wBase); - fillHistograms(mcacc::v0Status(tX), mcacc::v0Status(t2), - lX, l2, pX, p2, + histos.fill(HIST("hCentPairTypeME"), col1.cent(), ptype, wBase); + fillHistograms(tX.v0Status(), t2.v0Status(), + lambda, lambda2, proton, proton2, /*datatype=*/1, /*mixpairweight=*/meWeight); } } } } - PROCESS_SWITCH(lambdaspincorrderived, processMCMEV5, "Process MC ME v5 (paper-style)", false); - + PROCESS_SWITCH(lambdaspincorrderived, processMEV5, "Process data ME v5", false); void processMEV6(EventCandidates const& collisions, AllTrackCandidates const& V0s) { - MixBinner mb{ + MixBinnerR mb{ ptMin.value, ptMax.value, ptMix.value, v0etaMixBuffer.value, etaMix.value, phiMix.value, - MassMin.value, MassMax.value, cfgV5MassBins.value}; + MassMin.value, MassMax.value, cfgV5MassBins.value, + cfgMixRadiusParam.cfgMixRadiusBins.value}; const int nCol = colBinning.getAllBinsCount(); const int nStat = N_STATUS; @@ -2407,9 +1873,10 @@ struct lambdaspincorrderived { const int nEta = mb.nEta(); const int nPhi = mb.nPhi(); const int nM = mb.nM(); + const int nR = mb.nR(); - const size_t nKeys = static_cast(nCol) * nStat * nPt * nEta * nPhi * nM; - std::vector> buffer(nKeys); + const size_t nKeys = static_cast(nCol) * nStat * nPt * nEta * nPhi * nM * nR; + std::vector> buffer(nKeys); // -------- PASS 1: fill buffer -------- for (auto const& col : collisions) { @@ -2440,22 +1907,24 @@ struct lambdaspincorrderived { const int phiB = mb.phiBin(RecoDecay::constrainAngle(t.lambdaPhi(), -TMath::Pi(), harmonic)); const int mB = mb.massBin(t.lambdaMass()); + const int rB = mb.radiusBin(t.v0Radius()); - if (ptB < 0 || etaB < 0 || phiB < 0 || mB < 0) { + if (ptB < 0 || etaB < 0 || phiB < 0 || mB < 0 || rB < 0) { continue; } - const size_t key = linearKey(colBin, status, ptB, etaB, phiB, mB, - nStat, nPt, nEta, nPhi, nM); + const size_t key = linearKeyR(colBin, status, ptB, etaB, phiB, mB, rB, + nStat, nPt, nEta, nPhi, nM, nR); - buffer[key].push_back(BufferCand{ + buffer[key].push_back(BufferCandR{ .collisionIdx = static_cast(col.index()), .rowIndex = static_cast(t.globalIndex()), .v0Status = static_cast(status), .ptBin = static_cast(ptB), .etaBin = static_cast(etaB), .phiBin = static_cast(phiB), - .mBin = static_cast(mB)}); + .mBin = static_cast(mB), + .rBin = static_cast(rB)}); } } @@ -2486,8 +1955,9 @@ struct lambdaspincorrderived { const int phiB = mb.phiBin(RecoDecay::constrainAngle(tRep.lambdaPhi(), -TMath::Pi(), harmonic)); const int mB = mb.massBin(tRep.lambdaMass()); + const int rB = mb.radiusBin(tRep.v0Radius()); - if (ptB < 0 || etaB < 0 || phiB < 0 || mB < 0) { + if (ptB < 0 || etaB < 0 || phiB < 0 || mB < 0 || rB < 0) { return; } @@ -2498,8 +1968,8 @@ struct lambdaspincorrderived { for (int ptUse : ptBins) { for (int etaUse : etaBins) { for (int phiUse : phiBins) { - const auto& vec = buffer[linearKey(colBin, status, ptUse, etaUse, phiUse, mB, - nStat, nPt, nEta, nPhi, nM)]; + const auto& vec = buffer[linearKeyR(colBin, status, ptUse, etaUse, phiUse, mB, rB, + nStat, nPt, nEta, nPhi, nM, nR)]; for (auto const& bc : vec) { if (bc.collisionIdx == curColIdx) { @@ -2555,7 +2025,7 @@ struct lambdaspincorrderived { } }; - // -------- PASS 2: two-leg mixing -------- + // -------- PASS 2: configurable one-leg / two-leg mixing -------- for (auto const& col1 : collisions) { const int colBin = colBinning.getBin(std::make_tuple(col1.posz(), col1.cent())); if (colBin < 0) { @@ -2565,9 +2035,7 @@ struct lambdaspincorrderived { const int64_t curColIdx = static_cast(col1.index()); auto poolA = V0s.sliceBy(tracksPerCollisionV0, col1.index()); - for (auto const& [t1, t2] : - soa::combinations(o2::soa::CombinationsFullIndexPolicy(poolA, poolA))) { - + for (auto const& [t1, t2] : soa::combinations(o2::soa::CombinationsFullIndexPolicy(poolA, poolA))) { if (!selectionV0(t1) || !selectionV0(t2)) { continue; } @@ -2588,16 +2056,24 @@ struct lambdaspincorrderived { continue; } - // leg 1 replaced: (t1,t2) -> (tX,t2) - collectMatchesForReplacedLeg(t1, t2, colBin, curColIdx, matches1); + const bool doMixLeg1 = (cfgMixLegMode.value == 0 || cfgMixLegMode.value == 2); + const bool doMixLeg2 = (cfgMixLegMode.value == 1 || cfgMixLegMode.value == 2); - // leg 2 replaced: (t1,t2) -> (t1,tY) - collectMatchesForReplacedLeg(t2, t1, colBin, curColIdx, matches2); + if (doMixLeg1) { + collectMatchesForReplacedLeg(t1, t2, colBin, curColIdx, matches1); + downsampleMatches(matches1, + (uint64_t)t1.globalIndex() ^ (splitmix64((uint64_t)t2.globalIndex()) + 0x111ULL) ^ splitmix64((uint64_t)curColIdx)); + } else { + matches1.clear(); + } - downsampleMatches(matches1, - (uint64_t)t1.globalIndex() ^ (splitmix64((uint64_t)t2.globalIndex()) + 0x111ULL) ^ splitmix64((uint64_t)curColIdx)); - downsampleMatches(matches2, - (uint64_t)t2.globalIndex() ^ (splitmix64((uint64_t)t1.globalIndex()) + 0x222ULL) ^ splitmix64((uint64_t)curColIdx)); + if (doMixLeg2) { + collectMatchesForReplacedLeg(t2, t1, colBin, curColIdx, matches2); + downsampleMatches(matches2, + (uint64_t)t2.globalIndex() ^ (splitmix64((uint64_t)t1.globalIndex()) + 0x222ULL) ^ splitmix64((uint64_t)curColIdx)); + } else { + matches2.clear(); + } const int nReuse = static_cast(matches1.size() + matches2.size()); if (nReuse <= 0) { @@ -2606,85 +2082,73 @@ struct lambdaspincorrderived { const float wSE = 1.0f / static_cast(nReuse); - // replace t1 -> tX, keep t2 - for (auto const& m : matches1) { - auto tX = V0s.iteratorAt(static_cast(m.rowIndex)); - - auto proton = ROOT::Math::PtEtaPhiMVector(tX.protonPt(), tX.protonEta(), tX.protonPhi(), - o2::constants::physics::MassProton); - auto lambda = ROOT::Math::PtEtaPhiMVector(tX.lambdaPt(), tX.lambdaEta(), tX.lambdaPhi(), - tX.lambdaMass()); + if (doMixLeg1) { + for (auto const& m : matches1) { + auto tX = V0s.iteratorAt(static_cast(m.rowIndex)); - auto proton2 = ROOT::Math::PtEtaPhiMVector(t2.protonPt(), t2.protonEta(), t2.protonPhi(), - o2::constants::physics::MassProton); - auto lambda2 = ROOT::Math::PtEtaPhiMVector(t2.lambdaPt(), t2.lambdaEta(), t2.lambdaPhi(), - t2.lambdaMass()); + auto proton = ROOT::Math::PtEtaPhiMVector(tX.protonPt(), tX.protonEta(), tX.protonPhi(), o2::constants::physics::MassProton); + auto lambda = ROOT::Math::PtEtaPhiMVector(tX.lambdaPt(), tX.lambdaEta(), tX.lambdaPhi(), tX.lambdaMass()); + auto proton2 = ROOT::Math::PtEtaPhiMVector(t2.protonPt(), t2.protonEta(), t2.protonPhi(), o2::constants::physics::MassProton); + auto lambda2 = ROOT::Math::PtEtaPhiMVector(t2.lambdaPt(), t2.lambdaEta(), t2.lambdaPhi(), t2.lambdaMass()); - const int ptype = pairTypeCode(tX.v0Status(), t2.v0Status()); - double centPairWeight = 1.0; - if (hweightCentPair) { - const int bin = hweightCentPair->FindBin(col1.cent(), ptype); - centPairWeight = hweightCentPair->GetBinContent(bin); - if (centPairWeight <= 0.0) { - centPairWeight = 1.0; + const int ptype = pairTypeCode(tX.v0Status(), t2.v0Status()); + double centPairWeight = 1.0; + if (hweightCentPair) { + const int bin = hweightCentPair->FindBin(col1.cent(), ptype); + centPairWeight = hweightCentPair->GetBinContent(bin); + if (centPairWeight <= 0.0) { + centPairWeight = 1.0; + } } - } - const float meWeight = wSE * centPairWeight; - const float dPhi = deltaPhiMinusPiToPi((float)lambda.Phi(), (float)lambda2.Phi()); - histos.fill(HIST("deltaPhiMix"), dPhi, wSE); - histos.fill(HIST("hCentPairTypeME"), col1.cent(), ptype, wSE); + const float meWeight = wSE * centPairWeight; + const float dPhi = deltaPhiMinusPiToPi((float)lambda.Phi(), (float)lambda2.Phi()); + histos.fill(HIST("deltaPhiMix"), dPhi, wSE); + histos.fill(HIST("hCentPairTypeME"), col1.cent(), ptype, wSE); - fillHistograms(tX.v0Status(), t2.v0Status(), - lambda, lambda2, proton, proton2, - 1, meWeight); + fillHistograms(tX.v0Status(), t2.v0Status(), lambda, lambda2, proton, proton2, 1, meWeight); + } } - // replace t2 -> tY, keep t1 - for (auto const& m : matches2) { - auto tY = V0s.iteratorAt(static_cast(m.rowIndex)); - - auto proton = ROOT::Math::PtEtaPhiMVector(t1.protonPt(), t1.protonEta(), t1.protonPhi(), - o2::constants::physics::MassProton); - auto lambda = ROOT::Math::PtEtaPhiMVector(t1.lambdaPt(), t1.lambdaEta(), t1.lambdaPhi(), - t1.lambdaMass()); + if (doMixLeg2) { + for (auto const& m : matches2) { + auto tY = V0s.iteratorAt(static_cast(m.rowIndex)); - auto proton2 = ROOT::Math::PtEtaPhiMVector(tY.protonPt(), tY.protonEta(), tY.protonPhi(), - o2::constants::physics::MassProton); - auto lambda2 = ROOT::Math::PtEtaPhiMVector(tY.lambdaPt(), tY.lambdaEta(), tY.lambdaPhi(), - tY.lambdaMass()); + auto proton = ROOT::Math::PtEtaPhiMVector(t1.protonPt(), t1.protonEta(), t1.protonPhi(), o2::constants::physics::MassProton); + auto lambda = ROOT::Math::PtEtaPhiMVector(t1.lambdaPt(), t1.lambdaEta(), t1.lambdaPhi(), t1.lambdaMass()); + auto proton2 = ROOT::Math::PtEtaPhiMVector(tY.protonPt(), tY.protonEta(), tY.protonPhi(), o2::constants::physics::MassProton); + auto lambda2 = ROOT::Math::PtEtaPhiMVector(tY.lambdaPt(), tY.lambdaEta(), tY.lambdaPhi(), tY.lambdaMass()); - const int ptype = pairTypeCode(t1.v0Status(), tY.v0Status()); - double centPairWeight = 1.0; - if (hweightCentPair) { - const int bin = hweightCentPair->FindBin(col1.cent(), ptype); - centPairWeight = hweightCentPair->GetBinContent(bin); - if (centPairWeight <= 0.0) { - centPairWeight = 1.0; + const int ptype = pairTypeCode(t1.v0Status(), tY.v0Status()); + double centPairWeight = 1.0; + if (hweightCentPair) { + const int bin = hweightCentPair->FindBin(col1.cent(), ptype); + centPairWeight = hweightCentPair->GetBinContent(bin); + if (centPairWeight <= 0.0) { + centPairWeight = 1.0; + } } - } - const float meWeight = wSE * centPairWeight; - const float dPhi = deltaPhiMinusPiToPi((float)lambda.Phi(), (float)lambda2.Phi()); - histos.fill(HIST("deltaPhiMix"), dPhi, wSE); - histos.fill(HIST("hCentPairTypeME"), col1.cent(), ptype, wSE); + const float meWeight = wSE * centPairWeight; + const float dPhi = deltaPhiMinusPiToPi((float)lambda.Phi(), (float)lambda2.Phi()); + histos.fill(HIST("deltaPhiMix"), dPhi, wSE); + histos.fill(HIST("hCentPairTypeME"), col1.cent(), ptype, wSE); - fillHistograms(t1.v0Status(), tY.v0Status(), - lambda, lambda2, proton, proton2, - 1, meWeight); + fillHistograms(t1.v0Status(), tY.v0Status(), lambda, lambda2, proton, proton2, 1, meWeight); + } } } } } - PROCESS_SWITCH(lambdaspincorrderived, processMEV6, "Process data ME v6 two-leg", false); - + PROCESS_SWITCH(lambdaspincorrderived, processMEV6, "Process data ME v6 with radius buffer", false); void processMCMEV6(EventCandidatesMC const& collisions, AllTrackCandidatesMC const& V0sMC) { - MixBinner mb{ + MixBinnerR mb{ ptMin.value, ptMax.value, ptMix.value, v0etaMixBuffer.value, etaMix.value, phiMix.value, - MassMin.value, MassMax.value, cfgV5MassBins.value}; + MassMin.value, MassMax.value, cfgV5MassBins.value, + cfgMixRadiusParam.cfgMixRadiusBins.value}; const int nCol = colBinning.getAllBinsCount(); const int nStat = N_STATUS; @@ -2692,9 +2156,10 @@ struct lambdaspincorrderived { const int nEta = mb.nEta(); const int nPhi = mb.nPhi(); const int nM = mb.nM(); + const int nR = mb.nR(); - const size_t nKeys = static_cast(nCol) * nStat * nPt * nEta * nPhi * nM; - std::vector> buffer(nKeys); + const size_t nKeys = static_cast(nCol) * nStat * nPt * nEta * nPhi * nM * nR; + std::vector> buffer(nKeys); // -------- PASS 1: fill buffer -------- for (auto const& col : collisions) { @@ -2725,22 +2190,24 @@ struct lambdaspincorrderived { const int phiB = mb.phiBin(RecoDecay::constrainAngle(mcacc::lamPhi(t), -TMath::Pi(), harmonic)); const int mB = mb.massBin(mcacc::lamMass(t)); + const int rB = mb.radiusBin(mcacc::v0Radius(t)); - if (ptB < 0 || etaB < 0 || phiB < 0 || mB < 0) { + if (ptB < 0 || etaB < 0 || phiB < 0 || mB < 0 || rB < 0) { continue; } - const size_t key = linearKey(colBin, status, ptB, etaB, phiB, mB, - nStat, nPt, nEta, nPhi, nM); + const size_t key = linearKeyR(colBin, status, ptB, etaB, phiB, mB, rB, + nStat, nPt, nEta, nPhi, nM, nR); - buffer[key].push_back(BufferCand{ + buffer[key].push_back(BufferCandR{ .collisionIdx = static_cast(col.index()), .rowIndex = static_cast(t.globalIndex()), .v0Status = static_cast(status), .ptBin = static_cast(ptB), .etaBin = static_cast(etaB), .phiBin = static_cast(phiB), - .mBin = static_cast(mB)}); + .mBin = static_cast(mB), + .rBin = static_cast(rB)}); } } @@ -2771,8 +2238,9 @@ struct lambdaspincorrderived { const int phiB = mb.phiBin(RecoDecay::constrainAngle(mcacc::lamPhi(tRep), -TMath::Pi(), harmonic)); const int mB = mb.massBin(mcacc::lamMass(tRep)); + const int rB = mb.radiusBin(mcacc::v0Radius(tRep)); - if (ptB < 0 || etaB < 0 || phiB < 0 || mB < 0) { + if (ptB < 0 || etaB < 0 || phiB < 0 || mB < 0 || rB < 0) { return; } @@ -2783,8 +2251,8 @@ struct lambdaspincorrderived { for (int ptUse : ptBins) { for (int etaUse : etaBins) { for (int phiUse : phiBins) { - const auto& vec = buffer[linearKey(colBin, status, ptUse, etaUse, phiUse, mB, - nStat, nPt, nEta, nPhi, nM)]; + const auto& vec = buffer[linearKeyR(colBin, status, ptUse, etaUse, phiUse, mB, rB, + nStat, nPt, nEta, nPhi, nM, nR)]; for (auto const& bc : vec) { if (bc.collisionIdx == curColIdx) { @@ -2840,7 +2308,7 @@ struct lambdaspincorrderived { } }; - // -------- PASS 2: two-leg mixing -------- + // -------- PASS 2: configurable one-leg / two-leg mixing -------- for (auto const& col1 : collisions) { const int colBin = colBinning.getBin(std::make_tuple(mcacc::posz(col1), mcacc::cent(col1))); if (colBin < 0) { @@ -2850,9 +2318,7 @@ struct lambdaspincorrderived { const int64_t curColIdx = static_cast(col1.index()); auto poolA = V0sMC.sliceBy(tracksPerCollisionV0mc, col1.index()); - for (auto const& [t1, t2] : - soa::combinations(o2::soa::CombinationsFullIndexPolicy(poolA, poolA))) { - + for (auto const& [t1, t2] : soa::combinations(o2::soa::CombinationsFullIndexPolicy(poolA, poolA))) { if (!selectionV0MC(t1) || !selectionV0MC(t2)) { continue; } @@ -2873,13 +2339,24 @@ struct lambdaspincorrderived { continue; } - collectMatchesForReplacedLeg(t1, t2, colBin, curColIdx, matches1); - collectMatchesForReplacedLeg(t2, t1, colBin, curColIdx, matches2); + const bool doMixLeg1 = (cfgMixLegMode.value == 0 || cfgMixLegMode.value == 2); + const bool doMixLeg2 = (cfgMixLegMode.value == 1 || cfgMixLegMode.value == 2); + + if (doMixLeg1) { + collectMatchesForReplacedLeg(t1, t2, colBin, curColIdx, matches1); + downsampleMatches(matches1, + (uint64_t)t1.globalIndex() ^ (splitmix64((uint64_t)t2.globalIndex()) + 0x111ULL) ^ splitmix64((uint64_t)curColIdx)); + } else { + matches1.clear(); + } - downsampleMatches(matches1, - (uint64_t)t1.globalIndex() ^ (splitmix64((uint64_t)t2.globalIndex()) + 0x111ULL) ^ splitmix64((uint64_t)curColIdx)); - downsampleMatches(matches2, - (uint64_t)t2.globalIndex() ^ (splitmix64((uint64_t)t1.globalIndex()) + 0x222ULL) ^ splitmix64((uint64_t)curColIdx)); + if (doMixLeg2) { + collectMatchesForReplacedLeg(t2, t1, colBin, curColIdx, matches2); + downsampleMatches(matches2, + (uint64_t)t2.globalIndex() ^ (splitmix64((uint64_t)t1.globalIndex()) + 0x222ULL) ^ splitmix64((uint64_t)curColIdx)); + } else { + matches2.clear(); + } const int nReuse = static_cast(matches1.size() + matches2.size()); if (nReuse <= 0) { @@ -2888,77 +2365,77 @@ struct lambdaspincorrderived { const float wSE = 1.0f / static_cast(nReuse); - // replace t1 -> tX, keep t2 - for (auto const& m : matches1) { - auto tX = V0sMC.iteratorAt(static_cast(m.rowIndex)); - - auto pX = ROOT::Math::PtEtaPhiMVector(mcacc::prPt(tX), mcacc::prEta(tX), mcacc::prPhi(tX), - o2::constants::physics::MassProton); - auto lX = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(tX), mcacc::lamEta(tX), mcacc::lamPhi(tX), - mcacc::lamMass(tX)); - - auto p2 = ROOT::Math::PtEtaPhiMVector(mcacc::prPt(t2), mcacc::prEta(t2), mcacc::prPhi(t2), - o2::constants::physics::MassProton); - auto l2 = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(t2), mcacc::lamEta(t2), mcacc::lamPhi(t2), - mcacc::lamMass(t2)); - - const int ptype = pairTypeCode(mcacc::v0Status(tX), mcacc::v0Status(t2)); - double centPairWeight = 1.0; - if (hweightCentPair) { - const int bin = hweightCentPair->FindBin(mcacc::cent(col1), ptype); - centPairWeight = hweightCentPair->GetBinContent(bin); - if (centPairWeight <= 0.0) { - centPairWeight = 1.0; + if (doMixLeg1) { + for (auto const& m : matches1) { + auto tX = V0sMC.iteratorAt(static_cast(m.rowIndex)); + + auto pX = ROOT::Math::PtEtaPhiMVector(mcacc::prPt(tX), mcacc::prEta(tX), mcacc::prPhi(tX), + o2::constants::physics::MassProton); + auto lX = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(tX), mcacc::lamEta(tX), mcacc::lamPhi(tX), + mcacc::lamMass(tX)); + auto p2 = ROOT::Math::PtEtaPhiMVector(mcacc::prPt(t2), mcacc::prEta(t2), mcacc::prPhi(t2), + o2::constants::physics::MassProton); + auto l2 = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(t2), mcacc::lamEta(t2), mcacc::lamPhi(t2), + mcacc::lamMass(t2)); + + const int ptype = pairTypeCode(mcacc::v0Status(tX), mcacc::v0Status(t2)); + double centPairWeight = 1.0; + if (hweightCentPair) { + const int bin = hweightCentPair->FindBin(mcacc::cent(col1), ptype); + centPairWeight = hweightCentPair->GetBinContent(bin); + if (centPairWeight <= 0.0) { + centPairWeight = 1.0; + } } - } - const float meWeight = wSE * centPairWeight; - const float dPhi = deltaPhiMinusPiToPi((float)lX.Phi(), (float)l2.Phi()); - histos.fill(HIST("deltaPhiMix"), dPhi, wSE); - histos.fill(HIST("hCentPairTypeME"), mcacc::cent(col1), ptype, wSE); + const float meWeight = wSE * centPairWeight; + const float dPhi = deltaPhiMinusPiToPi((float)lX.Phi(), (float)l2.Phi()); + histos.fill(HIST("deltaPhiMix"), dPhi, wSE); + histos.fill(HIST("hCentPairTypeME"), mcacc::cent(col1), ptype, wSE); - fillHistograms(mcacc::v0Status(tX), mcacc::v0Status(t2), - lX, l2, pX, p2, - 1, meWeight); + fillHistograms(mcacc::v0Status(tX), mcacc::v0Status(t2), + lX, l2, pX, p2, + 1, meWeight); + } } - // replace t2 -> tY, keep t1 - for (auto const& m : matches2) { - auto tY = V0sMC.iteratorAt(static_cast(m.rowIndex)); - - auto p1 = ROOT::Math::PtEtaPhiMVector(mcacc::prPt(t1), mcacc::prEta(t1), mcacc::prPhi(t1), - o2::constants::physics::MassProton); - auto l1 = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(t1), mcacc::lamEta(t1), mcacc::lamPhi(t1), - mcacc::lamMass(t1)); - - auto pY = ROOT::Math::PtEtaPhiMVector(mcacc::prPt(tY), mcacc::prEta(tY), mcacc::prPhi(tY), - o2::constants::physics::MassProton); - auto lY = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(tY), mcacc::lamEta(tY), mcacc::lamPhi(tY), - mcacc::lamMass(tY)); - - const int ptype = pairTypeCode(mcacc::v0Status(t1), mcacc::v0Status(tY)); - double centPairWeight = 1.0; - if (hweightCentPair) { - const int bin = hweightCentPair->FindBin(mcacc::cent(col1), ptype); - centPairWeight = hweightCentPair->GetBinContent(bin); - if (centPairWeight <= 0.0) { - centPairWeight = 1.0; + if (doMixLeg2) { + for (auto const& m : matches2) { + auto tY = V0sMC.iteratorAt(static_cast(m.rowIndex)); + + auto p1 = ROOT::Math::PtEtaPhiMVector(mcacc::prPt(t1), mcacc::prEta(t1), mcacc::prPhi(t1), + o2::constants::physics::MassProton); + auto l1 = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(t1), mcacc::lamEta(t1), mcacc::lamPhi(t1), + mcacc::lamMass(t1)); + auto pY = ROOT::Math::PtEtaPhiMVector(mcacc::prPt(tY), mcacc::prEta(tY), mcacc::prPhi(tY), + o2::constants::physics::MassProton); + auto lY = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(tY), mcacc::lamEta(tY), mcacc::lamPhi(tY), + mcacc::lamMass(tY)); + + const int ptype = pairTypeCode(mcacc::v0Status(t1), mcacc::v0Status(tY)); + double centPairWeight = 1.0; + if (hweightCentPair) { + const int bin = hweightCentPair->FindBin(mcacc::cent(col1), ptype); + centPairWeight = hweightCentPair->GetBinContent(bin); + if (centPairWeight <= 0.0) { + centPairWeight = 1.0; + } } - } - const float meWeight = wSE * centPairWeight; - const float dPhi = deltaPhiMinusPiToPi((float)l1.Phi(), (float)lY.Phi()); - histos.fill(HIST("deltaPhiMix"), dPhi, wSE); - histos.fill(HIST("hCentPairTypeME"), mcacc::cent(col1), ptype, wSE); + const float meWeight = wSE * centPairWeight; + const float dPhi = deltaPhiMinusPiToPi((float)l1.Phi(), (float)lY.Phi()); + histos.fill(HIST("deltaPhiMix"), dPhi, wSE); + histos.fill(HIST("hCentPairTypeME"), mcacc::cent(col1), ptype, wSE); - fillHistograms(mcacc::v0Status(t1), mcacc::v0Status(tY), - l1, lY, p1, pY, - 1, meWeight); + fillHistograms(mcacc::v0Status(t1), mcacc::v0Status(tY), + l1, lY, p1, pY, + 1, meWeight); + } } } } } - PROCESS_SWITCH(lambdaspincorrderived, processMCMEV6, "Process MC ME v6 two-leg", false); + PROCESS_SWITCH(lambdaspincorrderived, processMCMEV6, "Process MC ME v6 with radius buffer", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { From 7ce94edf6b9d23b9ea8db5e79a5513ab6d11a3a6 Mon Sep 17 00:00:00 2001 From: AlexianL <123153896+AlexianL@users.noreply.github.com> Date: Sat, 14 Mar 2026 19:46:55 +0100 Subject: [PATCH 282/347] [PWGLF,PWGMM] mftReassociationValidation.cxx : add features, solve issues (#15402) --- .../Mult/Tasks/mftReassociationValidation.cxx | 247 ++++++++++++++---- 1 file changed, 201 insertions(+), 46 deletions(-) diff --git a/PWGMM/Mult/Tasks/mftReassociationValidation.cxx b/PWGMM/Mult/Tasks/mftReassociationValidation.cxx index 7964859f289..2afc211b4b3 100644 --- a/PWGMM/Mult/Tasks/mftReassociationValidation.cxx +++ b/PWGMM/Mult/Tasks/mftReassociationValidation.cxx @@ -176,6 +176,13 @@ enum MftNot3dReassociatedAndMatchedToTrueCollisionStep { NMftNot3dReassociatedAndMatchedToTrueCollisionSteps }; +enum MftIsTrueCollisionAmongCompatibleCollisionsStep { + AllWronglyAssociatedTracks = 0, + IsTrueCollisionAmongCompatibleCollisions, + IsNotTrueCollisionAmongCompatibleCollisions, + NMftIsTrueCollisionAmongCompatibleCollisionsSteps +}; + enum MftTrackSelectionStep { NoSelection = 0, Eta, @@ -405,7 +412,7 @@ struct MftReassociationValidation { hZVtxDiffNot3dReassociatedTracks[MatchedToTrueCollisionStep::AllTracks] = registry.add("MC/hZVtxDiffNot3dReassociatedTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); hZVtxDiffNot3dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision] = registry.add("MC/hZVtxDiffNot3dReassociatedTracksNotMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); - hZVtxDiffNot3dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision] = registry.add("MC/hZVtxDhZVtxDiffNot3dReassociatedTracksMatchedToTrueCollisioniffAmbiguousTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + hZVtxDiffNot3dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision] = registry.add("MC/hZVtxDiffNot3dReassociatedTracksMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); registry.add("MC/hIsAmbiguousTrackMatchedToTrueCollision", "hIsAmbiguousTrackMatchedToTrueCollision", {HistType::kTH1D, {{MftAmbiguousAndMatchedToTrueCollisionStep::NMftAmbiguousAndMatchedToTrueCollisionSteps, -0.5, +MftAmbiguousAndMatchedToTrueCollisionStep::NMftAmbiguousAndMatchedToTrueCollisionSteps - 0.5}}}); std::string labelsMftAmbiguousAndMatchedToTrueCollisionStep[MftAmbiguousAndMatchedToTrueCollisionStep::NMftAmbiguousAndMatchedToTrueCollisionSteps]; @@ -472,6 +479,26 @@ struct MftReassociationValidation { for (int iBin = 0; iBin < MftNot3dReassociatedAndMatchedToTrueCollisionStep::NMftNot3dReassociatedAndMatchedToTrueCollisionSteps; iBin++) { registry.get(HIST("MC/IsNot3dReassociatedAndMatchedToTrueCollision"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMftNot3dReassociatedAndMatchedToTrueCollisionStep[iBin].data()); } + + registry.add("MC/hIsTrueCollisionAmongCompatibleCollisions", "IsTrueCollisionAmongCompatibleCollisions", {HistType::kTH1D, {{MftIsTrueCollisionAmongCompatibleCollisionsStep::NMftIsTrueCollisionAmongCompatibleCollisionsSteps, -0.5, +MftIsTrueCollisionAmongCompatibleCollisionsStep::NMftIsTrueCollisionAmongCompatibleCollisionsSteps - 0.5}}}); + registry.add("MC/hIsTrueCollisionAmongCompatibleCollisionsNonAmbi", "hIsTrueCollisionAmongCompatibleCollisionsNonAmbi", {HistType::kTH1D, {{MftIsTrueCollisionAmongCompatibleCollisionsStep::NMftIsTrueCollisionAmongCompatibleCollisionsSteps, -0.5, +MftIsTrueCollisionAmongCompatibleCollisionsStep::NMftIsTrueCollisionAmongCompatibleCollisionsSteps - 0.5}}}); + registry.add("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaReassociated", "hIsTrueCollisionAmongCompatibleCollisionsDcaReassociated", {HistType::kTH1D, {{MftIsTrueCollisionAmongCompatibleCollisionsStep::NMftIsTrueCollisionAmongCompatibleCollisionsSteps, -0.5, +MftIsTrueCollisionAmongCompatibleCollisionsStep::NMftIsTrueCollisionAmongCompatibleCollisionsSteps - 0.5}}}); + registry.add("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaNotReassociated", "hIsTrueCollisionAmongCompatibleCollisionsDcaNotReassociated", {HistType::kTH1D, {{MftIsTrueCollisionAmongCompatibleCollisionsStep::NMftIsTrueCollisionAmongCompatibleCollisionsSteps, -0.5, +MftIsTrueCollisionAmongCompatibleCollisionsStep::NMftIsTrueCollisionAmongCompatibleCollisionsSteps - 0.5}}}); + std::string labelsMftIsTrueCollisionAmongCompatibleCollisionsStep[MftIsTrueCollisionAmongCompatibleCollisionsStep::NMftIsTrueCollisionAmongCompatibleCollisionsSteps]; + labelsMftIsTrueCollisionAmongCompatibleCollisionsStep[MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks] = "number of wrongly associated tracks"; + labelsMftIsTrueCollisionAmongCompatibleCollisionsStep[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions] = "number of MFT tracks with True Coll. among Compatible"; + labelsMftIsTrueCollisionAmongCompatibleCollisionsStep[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions] = "number of MFT tracks WITHOUT True Coll. among Compatible"; + registry.get(HIST("MC/hIsTrueCollisionAmongCompatibleCollisions"))->SetMinimum(0); + registry.get(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsNonAmbi"))->SetMinimum(0); + registry.get(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaReassociated"))->SetMinimum(0); + registry.get(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaNotReassociated"))->SetMinimum(0); + + for (int iBin = 0; iBin < MftIsTrueCollisionAmongCompatibleCollisionsStep::NMftIsTrueCollisionAmongCompatibleCollisionsSteps; iBin++) { + registry.get(HIST("MC/hIsTrueCollisionAmongCompatibleCollisions"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMftIsTrueCollisionAmongCompatibleCollisionsStep[iBin].data()); + registry.get(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsNonAmbi"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMftIsTrueCollisionAmongCompatibleCollisionsStep[iBin].data()); + registry.get(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaReassociated"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMftIsTrueCollisionAmongCompatibleCollisionsStep[iBin].data()); + registry.get(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaNotReassociated"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMftIsTrueCollisionAmongCompatibleCollisionsStep[iBin].data()); + } } // ========================= @@ -607,6 +634,39 @@ struct MftReassociationValidation { return grpo->getNominalL3Field(); } + template + bool isTrueCollisionAmongCompatibleCollisions(TTrack track) + { + + auto const& compatibleIds = track.compatibleCollIds(); + + // For this track, check if *any* reco collision that corresponds to its TRUE MC collision + // is present among the compatible collisions. + bool recoOfTrueInCompatible = false; + if (track.ambDegree() != 0) { + const int mcTrueCollisionId = track.mcParticle().mcCollisionId(); + // Fast membership test using compatibleCollIds() if available. + // If compatibleIds is empty, it means the table is missing or no compatible collisions were stored. + if (!compatibleIds.empty()) { + for (auto const& id : compatibleIds) { + + auto iterator = recoMcCollisionId.find(id); + + if (iterator != recoMcCollisionId.end()) { + if (iterator->second == mcTrueCollisionId) { + + recoOfTrueInCompatible = true; + return recoOfTrueInCompatible; + } + } else { + return recoOfTrueInCompatible; + } + } + } + } + return recoOfTrueInCompatible; + } + // ========================= // Cuts with functions // ========================= @@ -790,6 +850,11 @@ struct MftReassociationValidation { void processCreateLookupTable(FilteredCollisionsWSelMultMcLabels const& collisions) { + recoVtxX.clear(); + recoVtxY.clear(); + recoVtxZ.clear(); + recoMcCollisionId.clear(); + recoVtxX.reserve(collisions.size()); recoVtxY.reserve(collisions.size()); recoVtxZ.reserve(collisions.size()); @@ -806,7 +871,7 @@ struct MftReassociationValidation { void processMcReassociated2d(FilteredCollisionsWSelMultMcLabels::iterator const& collision, FilteredMftTracksWCollsMcLabels const& /*mftTracks*/, - soa::SmallGroups> const& reassociated2dMftTracks, + soa::SmallGroups> const& reassociated2dMftTracks, aod::McCollisions const& /*mcCollisions*/, aod::McParticles const& /*particles*/) { @@ -852,47 +917,59 @@ struct MftReassociationValidation { float reassociatedDeltaY = -999.f; float reassociatedDeltaZ = -999.f; auto collision = templatedTrack.collision_as(); - // auto mcCollision = particle.mcCollision_as(); - // deltaZ = collision.posZ() - mcCollision.posZ(); auto xPosTrue = reassociated2dMftTrack.mcParticle().mcCollision().posX(); auto yPosTrue = reassociated2dMftTrack.mcParticle().mcCollision().posY(); auto zPosTrue = reassociated2dMftTrack.mcParticle().mcCollision().posZ(); - const int bestRecoCol = reassociated2dMftTrack.bestCollisionId(); - // if (bestRecoCol < 0) { - // // no associated reco collision -> skip or count separately - // continue; - // } + const int bestRecoColl = reassociated2dMftTrack.bestCollisionId(); + const int originalRecoColl = templatedTrack.collisionId(); + + auto iteratorOriginalCollVtxX = recoVtxX.find(originalRecoColl); + auto iteratorOriginalCollVtxY = recoVtxY.find(originalRecoColl); + auto iteratorOriginalCollVtxZ = recoVtxZ.find(originalRecoColl); + auto iteratorBestCollVtxX = recoVtxX.find(bestRecoColl); + auto iteratorBestCollVtxY = recoVtxY.find(bestRecoColl); + auto iteratorBestCollVtxZ = recoVtxZ.find(bestRecoColl); + auto iteratorRecoMcCollisionId = recoMcCollisionId.find(bestRecoColl); - auto iteratorRecoVtxX = recoVtxX.find(bestRecoCol); - auto iteratorRecoVtxY = recoVtxY.find(bestRecoCol); - auto iteratorRecoVtxZ = recoVtxZ.find(bestRecoCol); - auto iteratorRecoMcCollisionId = recoMcCollisionId.find(bestRecoCol); - if (iteratorRecoVtxX == recoVtxX.end()) { - // bestRecoCol not found in reco collisions map -> skip or count separately + if (iteratorOriginalCollVtxX == recoVtxX.end()) { + // bestRecoColl not found in reco collisions map -> skip or count separately continue; } - if (iteratorRecoVtxY == recoVtxY.end()) { - // bestRecoCol not found in reco collisions map -> skip or count separately + if (iteratorOriginalCollVtxY == recoVtxY.end()) { continue; } - if (iteratorRecoVtxZ == recoVtxZ.end()) { - // bestRecoCol not found in reco collisions map -> skip or count separately + if (iteratorOriginalCollVtxZ == recoVtxZ.end()) { + continue; + } + if (iteratorBestCollVtxX == recoVtxX.end()) { + continue; + } + if (iteratorBestCollVtxY == recoVtxY.end()) { + continue; + } + if (iteratorBestCollVtxZ == recoVtxZ.end()) { continue; } if (iteratorRecoMcCollisionId == recoMcCollisionId.end()) { - // bestRecoCol not found in reco collisions map -> skip or count separately continue; } - const float xReco = iteratorRecoVtxX->second; - const float yReco = iteratorRecoVtxY->second; - const float zReco = iteratorRecoVtxZ->second; + const float xPosOriginalColl = iteratorOriginalCollVtxX->second; + const float yPosOriginalColl = iteratorOriginalCollVtxY->second; + const float zPosOriginalColl = iteratorOriginalCollVtxZ->second; + const float xPosBestColl = iteratorBestCollVtxX->second; + const float yPosBestColl = iteratorBestCollVtxY->second; + const float zPosBestColl = iteratorBestCollVtxZ->second; const int mcCollisionIdReco = iteratorRecoMcCollisionId->second; - reassociatedDeltaX = xReco - xPosTrue; - reassociatedDeltaY = yReco - yPosTrue; - reassociatedDeltaZ = zReco - zPosTrue; + deltaX = xPosOriginalColl - xPosTrue; + deltaY = yPosOriginalColl - yPosTrue; + deltaZ = zPosOriginalColl - zPosTrue; + + reassociatedDeltaX = xPosBestColl - xPosTrue; + reassociatedDeltaY = yPosBestColl - yPosTrue; + reassociatedDeltaZ = zPosBestColl - zPosTrue; if (reassociated2dMftTrack.ambDegree() > 1) { // AMBIGUOUS TRACKS registry.fill(HIST("MC/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::NumberOfAmbiguousTracks); @@ -920,6 +997,16 @@ struct MftReassociationValidation { } else { registry.fill(HIST("MC/IsNot2dReassociatedAndMatchedToTrueCollision"), MftNot2dReassociatedAndMatchedToTrueCollisionStep::IsNot2dReassociatedAndNotMatchedToTrueCollision); hZVtxDiffNot2dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); + + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks); + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaNotReassociated"), MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks); + if (isTrueCollisionAmongCompatibleCollisions(reassociated2dMftTrack)) { + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions); + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaNotReassociated"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions); + } else { + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions); + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaNotReassociated"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions); + } } } else { // IS 2D REASSOCIATED @@ -935,6 +1022,16 @@ struct MftReassociationValidation { } else { registry.fill(HIST("MC/Is2dReassociatedAndMatchedToTrueCollision"), Mft2dReassociatedAndMatchedToTrueCollisionStep::Is2dReassociatedAndNotMatchedToTrueCollision); hZVtxDiff2dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); + + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks); + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaReassociated"), MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks); + if (isTrueCollisionAmongCompatibleCollisions(reassociated2dMftTrack)) { + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions); + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaReassociated"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions); + } else { + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions); + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaReassociated"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions); + } } } @@ -950,6 +1047,16 @@ struct MftReassociationValidation { } else { registry.fill(HIST("MC/hIsNonAmbiguousTrackMatchedToTrueCollision"), MftNonAmbiguousAndMatchedToTrueCollisionStep::IsNonAmbiguousAndNotMatchedToTrueCollision); hZVtxDiffNonAmbiguousTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); + + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks); + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsNonAmbi"), MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks); + if (isTrueCollisionAmongCompatibleCollisions(reassociated2dMftTrack)) { + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions); + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsNonAmbi"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions); + } else { + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions); + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsNonAmbi"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions); + } } } // end of if non ambi @@ -962,7 +1069,7 @@ struct MftReassociationValidation { void processMcReassociated3d(FilteredCollisionsWSelMultMcLabels::iterator const& collision, FilteredMftTracksWCollsMcLabels const& /*mftTracks*/, - soa::SmallGroups> const& reassociated3dMftTracks, + soa::SmallGroups> const& reassociated3dMftTracks, aod::McCollisions const& /*mcCollisions*/, aod::McParticles const& /*particles*/) { @@ -1014,41 +1121,59 @@ struct MftReassociationValidation { auto yPosTrue = reassociated3dMftTrack.mcParticle().mcCollision().posY(); auto zPosTrue = reassociated3dMftTrack.mcParticle().mcCollision().posZ(); - const int bestRecoCol = reassociated3dMftTrack.bestCollisionId(); - // if (bestRecoCol < 0) { + const int bestRecoColl = reassociated3dMftTrack.bestCollisionId(); + const int originalRecoColl = templatedTrack.collisionId(); + // if (bestRecoColl < 0) { // // no associated reco collision -> skip or count separately // continue; // } - auto iteratorRecoVtxX = recoVtxX.find(bestRecoCol); - auto iteratorRecoVtxY = recoVtxY.find(bestRecoCol); - auto iteratorRecoVtxZ = recoVtxZ.find(bestRecoCol); - auto iteratorRecoMcCollisionId = recoMcCollisionId.find(bestRecoCol); - if (iteratorRecoVtxX == recoVtxX.end()) { - // bestRecoCol not found in reco collisions map -> skip or count separately + auto iteratorOriginalCollVtxX = recoVtxX.find(originalRecoColl); + auto iteratorOriginalCollVtxY = recoVtxY.find(originalRecoColl); + auto iteratorOriginalCollVtxZ = recoVtxZ.find(originalRecoColl); + auto iteratorBestCollVtxX = recoVtxX.find(bestRecoColl); + auto iteratorBestCollVtxY = recoVtxY.find(bestRecoColl); + auto iteratorBestCollVtxZ = recoVtxZ.find(bestRecoColl); + auto iteratorRecoMcCollisionId = recoMcCollisionId.find(bestRecoColl); + + if (iteratorOriginalCollVtxX == recoVtxX.end()) { + // bestRecoColl not found in reco collisions map -> skip or count separately continue; } - if (iteratorRecoVtxY == recoVtxY.end()) { - // bestRecoCol not found in reco collisions map -> skip or count separately + if (iteratorOriginalCollVtxY == recoVtxY.end()) { continue; } - if (iteratorRecoVtxZ == recoVtxZ.end()) { - // bestRecoCol not found in reco collisions map -> skip or count separately + if (iteratorOriginalCollVtxZ == recoVtxZ.end()) { + continue; + } + if (iteratorBestCollVtxX == recoVtxX.end()) { + continue; + } + if (iteratorBestCollVtxY == recoVtxY.end()) { + continue; + } + if (iteratorBestCollVtxZ == recoVtxZ.end()) { continue; } if (iteratorRecoMcCollisionId == recoMcCollisionId.end()) { - // bestRecoCol not found in reco collisions map -> skip or count separately continue; } - const float xReco = iteratorRecoVtxX->second; - const float yReco = iteratorRecoVtxY->second; - const float zReco = iteratorRecoVtxZ->second; + const float xPosOriginalColl = iteratorOriginalCollVtxX->second; + const float yPosOriginalColl = iteratorOriginalCollVtxY->second; + const float zPosOriginalColl = iteratorOriginalCollVtxZ->second; + const float xPosBestColl = iteratorBestCollVtxX->second; + const float yPosBestColl = iteratorBestCollVtxY->second; + const float zPosBestColl = iteratorBestCollVtxZ->second; const int mcCollisionIdReco = iteratorRecoMcCollisionId->second; - reassociatedDeltaX = xReco - xPosTrue; - reassociatedDeltaY = yReco - yPosTrue; - reassociatedDeltaZ = zReco - zPosTrue; + deltaX = xPosOriginalColl - xPosTrue; + deltaY = yPosOriginalColl - yPosTrue; + deltaZ = zPosOriginalColl - zPosTrue; + + reassociatedDeltaX = xPosBestColl - xPosTrue; + reassociatedDeltaY = yPosBestColl - yPosTrue; + reassociatedDeltaZ = zPosBestColl - zPosTrue; if (reassociated3dMftTrack.ambDegree() > 1) { // AMBIGUOUS TRACKS registry.fill(HIST("MC/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::NumberOfAmbiguousTracks); @@ -1076,6 +1201,16 @@ struct MftReassociationValidation { } else { registry.fill(HIST("MC/IsNot3dReassociatedAndMatchedToTrueCollision"), MftNot3dReassociatedAndMatchedToTrueCollisionStep::IsNot3dReassociatedAndNotMatchedToTrueCollision); hZVtxDiffNot3dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); + + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks); + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaNotReassociated"), MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks); + if (isTrueCollisionAmongCompatibleCollisions(reassociated3dMftTrack)) { + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions); + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaNotReassociated"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions); + } else { + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions); + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaNotReassociated"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions); + } } } else { // IS 3D REASSOCIATED @@ -1091,6 +1226,16 @@ struct MftReassociationValidation { } else { registry.fill(HIST("MC/Is3dReassociatedAndMatchedToTrueCollision"), Mft3dReassociatedAndMatchedToTrueCollisionStep::Is3dReassociatedAndNotMatchedToTrueCollision); hZVtxDiff3dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); + + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks); + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaReassociated"), MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks); + if (isTrueCollisionAmongCompatibleCollisions(reassociated3dMftTrack)) { + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions); + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaReassociated"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions); + } else { + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions); + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaReassociated"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions); + } } } @@ -1106,6 +1251,16 @@ struct MftReassociationValidation { } else { registry.fill(HIST("MC/hIsNonAmbiguousTrackMatchedToTrueCollision"), MftNonAmbiguousAndMatchedToTrueCollisionStep::IsNonAmbiguousAndNotMatchedToTrueCollision); hZVtxDiffNonAmbiguousTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); + + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks); + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsNonAmbi"), MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks); + if (isTrueCollisionAmongCompatibleCollisions(reassociated3dMftTrack)) { + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions); + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsNonAmbi"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions); + } else { + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions); + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsNonAmbi"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions); + } } } // end of if non ambi From 6b71b6a46b2f3037ce0ee57b81fe52932421ebbf Mon Sep 17 00:00:00 2001 From: nzardosh Date: Sat, 14 Mar 2026 20:02:52 +0100 Subject: [PATCH 283/347] [PWGJE] fixing fastjet assertion problem (#15404) --- PWGJE/TableProducer/rhoEstimator.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWGJE/TableProducer/rhoEstimator.cxx b/PWGJE/TableProducer/rhoEstimator.cxx index a7a05e5ebe7..71c183e9e83 100644 --- a/PWGJE/TableProducer/rhoEstimator.cxx +++ b/PWGJE/TableProducer/rhoEstimator.cxx @@ -130,7 +130,7 @@ struct RhoEstimatorTask { bkgPhiMax_ = 2.0 * M_PI; } if (config.trackPhiMin < -98.0) { - bkgPhiMin_ = -2.0 * M_PI; + bkgPhiMin_ = -1.0 * M_PI; } bkgSub.setPhiMinMax(bkgPhiMin_, bkgPhiMax_); From 7aa026d684ae9ef018ed5053e505bd19195f4220 Mon Sep 17 00:00:00 2001 From: "Q.Y. Xia" <91366503+huinaibing@users.noreply.github.com> Date: Sun, 15 Mar 2026 05:55:25 +0800 Subject: [PATCH 284/347] [PWGCF] Add a new method to calculate correlation (#15376) --- PWGCF/Flow/Tasks/pidFlowPtCorr.cxx | 501 ++++++++++++++++++++++++----- 1 file changed, 423 insertions(+), 78 deletions(-) diff --git a/PWGCF/Flow/Tasks/pidFlowPtCorr.cxx b/PWGCF/Flow/Tasks/pidFlowPtCorr.cxx index cb0fe7b46d0..bc38ec4cb09 100644 --- a/PWGCF/Flow/Tasks/pidFlowPtCorr.cxx +++ b/PWGCF/Flow/Tasks/pidFlowPtCorr.cxx @@ -66,6 +66,7 @@ using namespace o2::framework::expressions; #define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable NAME{#NAME, DEFAULT, HELP}; struct PidFlowPtCorr { + // configurable O2_DEFINE_CONFIGURABLE(cfgCutVertex, float, 10.0f, "Accepted z-vertex range") O2_DEFINE_CONFIGURABLE(cfgCutChi2prTPCcls, float, 2.5, "Chi2 per TPC clusters") @@ -133,16 +134,17 @@ struct PidFlowPtCorr { O2_DEFINE_CONFIGURABLE(cfgFlowNbootstrap, int, 30, "Number of subsamples for bootstrap") // switch - O2_DEFINE_CONFIGURABLE(cfgDoLocDenCorr, bool, false, "do local density corr") - O2_DEFINE_CONFIGURABLE(cfgOutputNUAWeights, bool, false, "Fill and output NUA weights") - O2_DEFINE_CONFIGURABLE(cfgOutputrunbyrun, bool, false, "OPEN IF USE FUNCTION(fillcorrectiongraph) Fill and output NUA weights run by run") - O2_DEFINE_CONFIGURABLE(cfgOutPutMC, bool, false, "Fill MC graphs, note that if the processMCgen is open,this MUST be open") - O2_DEFINE_CONFIGURABLE(cfgOutputLocDenWeights, bool, false, "Fill and output local density weights") - O2_DEFINE_CONFIGURABLE(cfgOutputQA, bool, false, "OPEN IF USE FUNCTION(detectorPidQa) do QA") - - O2_DEFINE_CONFIGURABLE(cfgDebugMyCode, bool, false, "output some graph for code debug") - - O2_DEFINE_CONFIGURABLE(cfgOutPutPtSpectra, bool, false, "output pt spectra for data, MC and RECO") + struct : ConfigurableGroup { + std::string prefix = "switchsOpts"; + O2_DEFINE_CONFIGURABLE(cfgDoLocDenCorr, bool, false, "do local density corr"); + O2_DEFINE_CONFIGURABLE(cfgOutputrunbyrun, bool, false, "OPEN IF USE FUNCTION(fillcorrectiongraph) Fill and output NUA weights run by run"); + O2_DEFINE_CONFIGURABLE(cfgOutPutMC, bool, false, "Fill MC graphs, note that if the processMCgen is open,this MUST be open"); + O2_DEFINE_CONFIGURABLE(cfgOutputQA, bool, false, "OPEN IF USE FUNCTION(detectorPidQa) do QA"); + O2_DEFINE_CONFIGURABLE(cfgDebugMyCode, bool, false, "output some graph for code debug"); + O2_DEFINE_CONFIGURABLE(cfgOutPutPtSpectra, bool, false, "output pt spectra for data, MC and RECO"); + O2_DEFINE_CONFIGURABLE(cfgCheck2MethodDiff, bool, false, "check difference between v2' && v2''"); + O2_DEFINE_CONFIGURABLE(cfgUseITSOnly4MeanPt, bool, false, "use ITS only to calculate mean pt"); + } switchsOpts; /** * @brief cfg for PID pt range @@ -170,6 +172,15 @@ struct PidFlowPtCorr { // end separate k-p // end cfg for PID pt range + struct : ConfigurableGroup { + std::string prefix = "particleAbundanceOpts"; + ConfigurableAxis cfgaxisAbundancePi{"cfgaxisAbundancePi", {100, 0, 1100}, "axis for Abundance Pi"}; + ConfigurableAxis cfgaxisAbundanceKa{"cfgaxisAbundanceKa", {100, 0, 200}, "axis for Abundance ka"}; + ConfigurableAxis cfgaxisAbundancePr{"cfgaxisAbundancePr", {100, 0, 50}, "axis for Abundance Pr"}; + + O2_DEFINE_CONFIGURABLE(cfgOutPutAbundanceDis, bool, false, "out put hists for pid particle Abundance QA"); + } particleAbundanceOpts; + ConfigurableAxis cfgaxisVertex{"cfgaxisVertex", {20, -10, 10}, "vertex axis for histograms"}; ConfigurableAxis cfgaxisPhi{"cfgaxisPhi", {60, 0.0, constants::math::TwoPI}, "phi axis for histograms"}; ConfigurableAxis cfgaxisEta{"cfgaxisEta", {40, -1., 1.}, "eta axis for histograms"}; @@ -184,8 +195,16 @@ struct PidFlowPtCorr { Configurable> cfgTrackDensityV3P{"cfgTrackDensityV3P", std::vector{0.0174056, 0.000703329, -1.45044e-05, 1.91991e-07, -1.62137e-09}, "parameter of v2(cent) for track density efficiency correction"}; Configurable> cfgTrackDensityV4P{"cfgTrackDensityV4P", std::vector{0.008845, 0.000259668, -3.24435e-06, 4.54837e-08, -6.01825e-10}, "parameter of v2(cent) for track density efficiency correction"}; + struct : ConfigurableGroup { + std::string prefix = "meanptC22GraphOpts"; + ConfigurableAxis cfgaxisBootstrap{"cfgaxisBootstrap", {30, 0, 30}, "cfgaxisBootstrap"}; + } meanptC22GraphOpts; + AxisSpec axisMultiplicity{{0, 5, 10, 15, 20, 30, 40, 50, 60, 70, 80, 90}, "Centrality (%)"}; + // configurable + + // filter // filter and using // data Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; @@ -208,6 +227,10 @@ struct PidFlowPtCorr { using FilteredCollisionsWithMCLabel = soa::Filtered>; // end using and filter + // filter + + // others + Preslice perCollision = aod::track::collisionId; // Connect to ccdb @@ -218,7 +241,6 @@ struct PidFlowPtCorr { // Define output HistogramRegistry registry{"registry"}; - OutputObj fWeightsREF{GFWWeights("weightsREF")}; // val used for bootstrap TRandom3* fRndm = new TRandom3(0); @@ -246,6 +268,7 @@ struct PidFlowPtCorr { kProton, kNumberOfParticles }; + enum OutputTH1Names { // here are TProfiles for vn-pt correlations that are not implemented in GFW hPhi = 0, @@ -315,8 +338,11 @@ struct PidFlowPtCorr { std::vector qaHistVector; // end hists for QA runbyrun + // others + void init(InitContext const&) // Initialization { + // init and add lots of graphs according to switch ccdb->setURL(cfgurl.value); ccdb->setCaching(true); ccdb->setCreatedNotAfter(cfgnolaterthan.value); @@ -360,7 +386,7 @@ struct PidFlowPtCorr { registry.add("hNchUnCorrectedVSNchCorrected", "", {HistType::kTH2D, {cfgaxisNch, cfgaxisNch}}); runNumbers = cfgRunNumbers; // TPC vs TOF vs its, comparation graphs, check the PID performance in difference pt - if (cfgOutputQA) { + if (switchsOpts.cfgOutputQA.value) { registry.add("DetectorPidPerformace/TPCvsTOF/Pi", "", {HistType::kTH3D, {{600, -30, 30}, {600, -30, 30}, cfgaxisPt}}); registry.add("DetectorPidPerformace/TPCvsTOF/Pr", "", {HistType::kTH3D, {{600, -30, 30}, {600, -30, 30}, cfgaxisPt}}); registry.add("DetectorPidPerformace/TPCvsTOF/Ka", "", {HistType::kTH3D, {{600, -30, 30}, {600, -30, 30}, cfgaxisPt}}); @@ -397,7 +423,7 @@ struct PidFlowPtCorr { // end run by run QA hists } // cfgoutputqa - if (cfgOutPutMC) { + if (switchsOpts.cfgOutPutMC.value) { // hist for NUE correction registry.add("correction/hPtCentMcRec", "", {HistType::kTH2D, {cfgaxisPt, axisMultiplicity}}); registry.add("correction/hPtCentMcGen", "", {HistType::kTH2D, {cfgaxisPt, axisMultiplicity}}); @@ -416,7 +442,7 @@ struct PidFlowPtCorr { } // cfgoutputMC // debug hists - if (cfgDebugMyCode) { + if (switchsOpts.cfgDebugMyCode.value) { debugHist.hPtEffWeight = registry.add("debug/hPtEffWeight", "", {HistType::kTH1D, {cfgaxisPt}}); debugHist.hPtCentEffWeight = registry.add("debug/hPtCentEffWeight", "", {HistType::kTH2D, {cfgaxisPt, axisMultiplicity}}); debugHist.hRunNumberPhiEtaVertexWeight = registry.add("debug/hRunNumberPhiEtaVertexWeight", "", {HistType::kTHnSparseF, {cfgaxisRun, cfgaxisPhi, cfgaxisEta, cfgaxisVertex}}); @@ -425,27 +451,20 @@ struct PidFlowPtCorr { } } // cfgdebugmycode - if (cfgOutPutPtSpectra) { + if (switchsOpts.cfgOutPutPtSpectra.value) { registry.add("ptSpectra/hPtCentData", "", {HistType::kTH2D, {cfgaxisPt, axisMultiplicity}}); registry.add("ptSpectra/hCentEventCountData", "", {HistType::kTH1D, {axisMultiplicity}}); registry.add("ptSpectra/hCentEventCountMcGen", "", {HistType::kTH1D, {axisMultiplicity}}); registry.add("ptSpectra/hCentEventCountMcRec", "", {HistType::kTH1D, {axisMultiplicity}}); - // (PosEta)(PosCh) - registry.add("ptSpectra/hPtCentDataPosEtaPosCh", "", {HistType::kTH2D, {cfgaxisPt, axisMultiplicity}}); - - // (PosEta)(NegCh) - registry.add("ptSpectra/hPtCentDataPosEtaNegCh", "", {HistType::kTH2D, {cfgaxisPt, axisMultiplicity}}); - - // (NegEta(PosCh) - registry.add("ptSpectra/hPtCentDataNegEtaPosCh", "", {HistType::kTH2D, {cfgaxisPt, axisMultiplicity}}); - - // (NegEta)(NegCh) - registry.add("ptSpectra/hPtCentDataNegEtaNegCh", "", {HistType::kTH2D, {cfgaxisPt, axisMultiplicity}}); + registry.add("ptSpectra/hPtCentData4ITSOnly", "", {HistType::kTH2D, {cfgaxisPt, axisMultiplicity}}); + registry.add("c22PrimeVsc22/Pi", "", {HistType::kTH2D, {{100, 0., 0.01}, {100, 0., 0.01}}}); + registry.add("c22PrimeVsc22/Ka", "", {HistType::kTH2D, {{100, 0., 0.01}, {100, 0., 0.01}}}); + registry.add("c22PrimeVsc22/Pr", "", {HistType::kTH2D, {{100, 0., 0.01}, {100, 0., 0.01}}}); } // cfgoutputptspectra - if (cfgOutputrunbyrun) { + if (switchsOpts.cfgOutputrunbyrun.value) { // hist for NUA registry.add("correction/hRunNumberPhiEtaVertex", "", {HistType::kTHnSparseF, {cfgaxisRun, cfgaxisPhi, cfgaxisEta, cfgaxisVertex}}); // set "correction/hRunNumberPhiEtaVertex" axis0 label @@ -455,6 +474,12 @@ struct PidFlowPtCorr { // end set "correction/hRunNumberPhiEtaVertex" axis0 label } // cfgooutputrunbyrun + if (particleAbundanceOpts.cfgOutPutAbundanceDis) { + registry.add("abundance/hNumOfPiEventCount", "", {HistType::kTH1D, {particleAbundanceOpts.cfgaxisAbundancePi}}); + registry.add("abundance/hNumOfKaEventCount", "", {HistType::kTH1D, {particleAbundanceOpts.cfgaxisAbundanceKa}}); + registry.add("abundance/hNumOfPrEventCount", "", {HistType::kTH1D, {particleAbundanceOpts.cfgaxisAbundancePr}}); + } + // set bin label for hEventCount // processdata registry.add("hEventCount/processData", "", {HistType::kTH1D, {{14, 0, 14}}}); @@ -484,6 +509,7 @@ struct PidFlowPtCorr { registry.add("hInteractionRate", "", {HistType::kTH1D, {{1000, 0, 1000}}}); // end set bin label for eventcount + // flow container setup // cumulant of flow // fill TObjArray for charged TObjArray* oba4Ch = new TObjArray(); @@ -530,6 +556,28 @@ struct PidFlowPtCorr { registry.add("ka/c22dmeanpt", ";Centrality (%) ; C_{2}{2} ", {HistType::kTProfile2D, {axisMultiplicity, cfgaxisMeanPt}}); registry.add("pr/c22dmeanpt", ";Centrality (%) ; C_{2}{2} ", {HistType::kTProfile2D, {axisMultiplicity, cfgaxisMeanPt}}); + // init tprofile3d for <2'> - meanpt + // charged + registry.add("meanptCentNbs/hCharged", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); + registry.add("meanptCentNbs/hChargedMeanpt", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); + // end charged + + // pid + registry.add("meanptCentNbs/hChargedPionWithNpair", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); + registry.add("meanptCentNbs/hChargedPionFull", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); + registry.add("meanptCentNbs/hPion", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); + + registry.add("meanptCentNbs/hChargedKaonWithNpair", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); + registry.add("meanptCentNbs/hChargedKaonFull", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); + registry.add("meanptCentNbs/hKaon", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); + + registry.add("meanptCentNbs/hChargedProtonWithNpair", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); + registry.add("meanptCentNbs/hChargedProtonFull", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); + registry.add("meanptCentNbs/hProton", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); + // end pid + // end init tprofile3d for <2'> - meanpt + + // fgfw set up and correlation config setup // Data stored in fGFW double etaMax = trkQualityOpts.cfgCutEta.value; double etaGap = cfgEtaGap; @@ -590,7 +638,7 @@ struct PidFlowPtCorr { corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiKaN refN | olKaN {2 2} refP {-2 -2}", "Kaon0gap24a", kFALSE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiKaP refP | olKaP {2 2} refN {-2 -2}", "Kaon0gap24b", kFALSE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPrN refN | olPrN {2 2} refP {-2 -2}", "Prot0gap24a", kFALSE)); // 15 - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPrP refP | olPaP {2 2} refN {-2 -2}", "Prot0gap24b", kFALSE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPrP refP | olPrP {2 2} refN {-2 -2}", "Prot0gap24b", kFALSE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPiN08 {3} refP08 {-3}", "Pion08gap32a", kFALSE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPiP08 {3} refN08 {-3}", "Pion08gap32b", kFALSE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiKaN08 {3} refP08 {-3}", "Kaon08gap32a", kFALSE)); @@ -602,7 +650,7 @@ struct PidFlowPtCorr { corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiKaN refN | olKaN {3 3} refP {-3 -3}", "Kaon0gap34a", kFALSE)); // 25 corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiKaP refP | olKaP {3 3} refN {-3 -3}", "Kaon0gap34b", kFALSE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPrN refN | olPrN {3 3} refP {-3 -3}", "Prot0gap34a", kFALSE)); - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPrP refP | olPaP {3 3} refN {-3 -3}", "Prot0gap34b", kFALSE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPrP refP | olPrP {3 3} refN {-3 -3}", "Prot0gap34b", kFALSE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPiN08 {2} poiPiP08 {-2}", "PiPi08gap22", kFALSE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiKaN08 {2} poiKaP08 {-2}", "KaKa08gap22", kFALSE)); // 30 @@ -620,6 +668,7 @@ struct PidFlowPtCorr { fGFW->CreateRegions(); // finalize the initialization + // params // used for event selection fMultPVCutLow = new TF1("fMultPVCutLow", "[0]+[1]*x+[2]*x*x+[3]*x*x*x+[4]*x*x*x*x - 3.5*([5]+[6]*x+[7]*x*x+[8]*x*x*x+[9]*x*x*x*x)", 0, 100); fMultPVCutLow->SetParameters(cfgMultPVCutPara[0], cfgMultPVCutPara[1], cfgMultPVCutPara[2], cfgMultPVCutPara[3], cfgMultPVCutPara[4], cfgMultPVCutPara[5], cfgMultPVCutPara[6], cfgMultPVCutPara[7], cfgMultPVCutPara[8], cfgMultPVCutPara[9]); @@ -652,6 +701,8 @@ struct PidFlowPtCorr { funcV4->SetParameters(v4para[0], v4para[1], v4para[2], v4para[3], v4para[4]); } + // pid utils function + /** * @brief Identify whether the input track is a Pion * @@ -782,6 +833,26 @@ struct PidFlowPtCorr { return resultKaon; } + // pid util function + + // other utils + + double getPidC22InOneEvent(const GFW::CorrConfig& corrconfA, const GFW::CorrConfig& corrconfB) + { + double NpairA = fGFW->Calculate(corrconfA, 0, true).real(); + double NpairB = fGFW->Calculate(corrconfB, 0, true).real(); + + if (NpairA == 0 && NpairB == 0) + return 0; + + double ChC22A = NpairA ? fGFW->Calculate(corrconfA, 0, false).real() / NpairA : 0.; + double ChC22B = NpairB ? fGFW->Calculate(corrconfB, 0, false).real() / NpairB : 0.; + + double ChC22 = (ChC22A * NpairA + ChC22B * NpairB) / (NpairA + NpairB); + + return ChC22; + } + /** * @brief get stable particle * @note stable particle include @@ -813,14 +884,126 @@ struct PidFlowPtCorr { return false; } - void fillFC(MyParticleType type, const GFW::CorrConfig& corrconf, const double& cent, const double& rndm, const char* tarName) + // other utils + + // fgfw filling helpers + + /** + * @brief this function is used to fill fFCCh4PtC22 + * @details weight is nch * npair + * + * @param cent + * @param ptSum + * @param nch + * @param rndm + */ + void fillFC4PtC22(const double& cent, const double& ptSum, const double& nch, const double& rndm) + { + double dnx, val; + + dnx = fGFW->Calculate(corrconfigs.at(0), 0, kTRUE).real(); + if (dnx == 0) + return; + + // <2> + val = fGFW->Calculate(corrconfigs.at(0), 0, kFALSE).real() / dnx; + if (std::fabs(val) >= 1) + return; + + registry.fill(HIST("meanptCentNbs/hCharged"), ptSum / nch, cent, rndm * cfgFlowNbootstrap, val, nch * dnx); + registry.fill(HIST("meanptCentNbs/hChargedMeanpt"), ptSum / nch, cent, rndm * cfgFlowNbootstrap, ptSum / nch, nch * dnx); + } + + /** + * @brief note that the graph's x axis is pid meanpt, for <2'> weight is nPid * npairPID, for <2> weight is nch * npair + * + * @param cent + * @param nch + * @param rndm + * @param type + * @param pidPtSum + * @param nPid + */ + void fillFC4PtC22(const double& cent, const double& nch, const double& rndm, MyParticleType type, const double& pidPtSum, const double& nPid) + { + // <2> + double dnx, val; + + dnx = fGFW->Calculate(corrconfigs.at(0), 0, kTRUE).real(); + if (dnx == 0) + return; + + // <2> + val = fGFW->Calculate(corrconfigs.at(0), 0, kFALSE).real() / dnx; + if (std::fabs(val) >= 1) + return; + + double pidc22 = 0; + double npairPid = 0; + switch (type) { + case MyParticleType::kPion: + pidc22 = getPidC22InOneEvent(corrconfigs.at(5), corrconfigs.at(6)); + if (pidc22 == 0) + return; + + npairPid = fGFW->Calculate(corrconfigs.at(5), 0, kTRUE).real() + fGFW->Calculate(corrconfigs.at(6), 0, kTRUE).real(); + if (npairPid == 0) + return; + + registry.fill(HIST("meanptCentNbs/hPion"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, pidc22, nPid * npairPid); + registry.fill(HIST("meanptCentNbs/hChargedPionFull"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, val, dnx * nch); + registry.fill(HIST("meanptCentNbs/hChargedPionWithNpair"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, val, dnx); + + break; + // end pion + + case MyParticleType::kKaon: + pidc22 = getPidC22InOneEvent(corrconfigs.at(7), corrconfigs.at(8)); + if (pidc22 == 0) + return; + + npairPid = fGFW->Calculate(corrconfigs.at(7), 0, kTRUE).real() + fGFW->Calculate(corrconfigs.at(8), 0, kTRUE).real(); + if (npairPid == 0) + return; + + registry.fill(HIST("meanptCentNbs/hKaon"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, pidc22, nPid * npairPid); + registry.fill(HIST("meanptCentNbs/hChargedKaonFull"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, val, dnx * nch); + registry.fill(HIST("meanptCentNbs/hChargedKaonWithNpair"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, val, dnx); + + break; + // end kaon + + case MyParticleType::kProton: + pidc22 = getPidC22InOneEvent(corrconfigs.at(9), corrconfigs.at(10)); + if (pidc22 == 0) + return; + + npairPid = fGFW->Calculate(corrconfigs.at(9), 0, kTRUE).real() + fGFW->Calculate(corrconfigs.at(10), 0, kTRUE).real(); + if (npairPid == 0) + return; + + registry.fill(HIST("meanptCentNbs/hProton"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, pidc22, nPid * npairPid); + registry.fill(HIST("meanptCentNbs/hChargedProtonFull"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, val, dnx * nch); + registry.fill(HIST("meanptCentNbs/hChargedProtonWithNpair"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, val, dnx); + + break; + // end proton + + default: + return; + break; + } + // end switch particle type + } + + bool fillFC(MyParticleType type, const GFW::CorrConfig& corrconf, const double& cent, const double& rndm, const char* tarName) { double dnx, val; // calculate #sum exp{i * 0 (#phi_{i} - #phi_{j})} == N_{pairs} // note that weight is ignored in the formula but not in the calculation, for c24 is similar dnx = fGFW->Calculate(corrconf, 0, kTRUE).real(); if (dnx == 0) - return; + return false; if (!corrconf.pTDif) { // #sum exp{i * 2 * (#phi_{i} - #phi_{j})} / N_{pairs} == < 2 > val = fGFW->Calculate(corrconf, 0, kFALSE).real() / dnx; @@ -845,10 +1028,10 @@ struct PidFlowPtCorr { LOGF(warning, "particle not found"); break; } - return; + return true; } } - return; + return true; } /** @@ -952,6 +1135,10 @@ struct PidFlowPtCorr { return; } + // fill fgfw helper + + // correction apply functions + /** * @brief load NUE(1D) NUE(2D) NUA graphs * @note if u write more than one path in cfg, the graph would not load, that's the strange way to close NUE/NUA corr separatly @@ -1188,6 +1375,10 @@ struct PidFlowPtCorr { return true; } + // correction apply function + + // track cut functions + /** * @brief cut MC particles * @note include @@ -1305,6 +1496,10 @@ struct PidFlowPtCorr { return true; } + // track cut + + // event selection functions + /** * @brief fill eventCount for different function * @@ -1447,8 +1642,13 @@ struct PidFlowPtCorr { return true; } + // event selection + + // main functions + void processData(AodCollisions::iterator const& collision, aod::BCsWithTimestamps const&, AodTracks const& tracks) { + // sub region, init // init float rndm = fRndm->Rndm(); int nTot = tracks.size(); @@ -1473,9 +1673,9 @@ struct PidFlowPtCorr { // end collision cut // pt spectra - if (cfgOutPutPtSpectra) { + if (switchsOpts.cfgOutPutPtSpectra.value) { registry.fill(HIST("ptSpectra/hCentEventCountData"), cent); - } // cfgOutPutPtSpectra + } // switchsOpts.cfgOutPutPtSpectra.value // correction loadCorrections(bc.timestamp()); @@ -1489,7 +1689,7 @@ struct PidFlowPtCorr { double psi2Est = 0, psi3Est = 0, psi4Est = 0; float wEPeff = 1; double v2 = 0, v3 = 0, v4 = 0; - if (cfgDoLocDenCorr) { + if (switchsOpts.cfgDoLocDenCorr.value) { double q2x = 0, q2y = 0; double q3x = 0, q3y = 0; double q4x = 0, q4y = 0; @@ -1521,28 +1721,67 @@ struct PidFlowPtCorr { double nchCorrectedPassed = 0; double nchPassedSelection = 0; - if (cfgDebugMyCode) { + if (switchsOpts.cfgDebugMyCode.value) { LOGF(info, "===================================="); } + // val for pid particles + double pionPtSum = 0; + double kaonPtSum = 0; + double protonPtSum = 0; + + double nPionWeighted = 0; + double nKaonWeighted = 0; + double nProtonWeighted = 0; + + double pionPtSumw2 = 0; + double kaonPtSumw2 = 0; + double protonPtSumw2 = 0; + + double nPionSquare = 0; + double nKaonSquare = 0; + double nProtonSquare = 0; + + double pionPtSquareSum = 0; + double kaonPtSquareSum = 0; + double protonPtSquareSum = 0; + // end val for pid particles + /// @note calculate pt /// use ITS only for (const auto& track : tracks) { float weff = 1; // do nue - setParticleNUEWeight(weff, track, cent, false); + if (switchsOpts.cfgUseITSOnly4MeanPt.value) + setParticleNUEWeight(weff, track, cent, false); + else + setParticleNUEWeight(weff, track, cent, true); // end do nue // track cut ITS only if (!trackSelectedGlobal(track)) continue; - if (!trackSelected4ITS(track)) + if (!track.hasITS()) continue; - if (track.hasTPC()) + if (!trackSelected4ITS(track)) continue; + + if (switchsOpts.cfgUseITSOnly4MeanPt.value) { + if (track.hasTPC()) + continue; + } else { + if (!track.hasTPC()) + continue; + if (!trackSelected4TPC(track)) + continue; + } // end track cut its only + if (switchsOpts.cfgOutPutPtSpectra.value) { + registry.fill(HIST("ptSpectra/hPtCentData4ITSOnly"), track.pt(), cent); + } + // calculate ncharged(nch with weight) and pt if (std::fabs(track.eta()) < trkQualityOpts.cfgRangeEta.value) { nch += weff; @@ -1550,25 +1789,51 @@ struct PidFlowPtCorr { ptSum += weff * track.pt(); ptSumw2 += weff * weff * track.pt(); ptSquareSum += weff * weff * track.pt() * track.pt(); + + if (isPion(track)) { + nPionWeighted += weff; + nPionSquare += weff * weff; + pionPtSum += weff * track.pt(); + pionPtSumw2 += weff * weff * track.pt(); + pionPtSquareSum += weff * weff * track.pt() * track.pt(); + } + if (isKaon(track)) { + nKaonWeighted += weff; + nKaonSquare += weff * weff; + kaonPtSum += weff * track.pt(); + kaonPtSumw2 += weff * weff * track.pt(); + kaonPtSquareSum += weff * weff * track.pt() * track.pt(); + } + if (isProton(track)) { + nProtonWeighted += weff; + nProtonSquare += weff * weff; + protonPtSum += weff * track.pt(); + protonPtSumw2 += weff * weff * track.pt(); + protonPtSquareSum += weff * weff * track.pt() * track.pt(); + } } // end calculate nch and pt nchCorrectedPassed += weff; nchPassedSelection += 1; - if (weff == 1. && cfgDebugMyCode) { + if (weff == 1. && switchsOpts.cfgDebugMyCode.value) { LOGF(info, "weff is 1, if nue opt is open and this message appears a lot, check!"); } } // end pt calculation using ITS only - if (cfgDebugMyCode) { + if (switchsOpts.cfgDebugMyCode.value) { LOGF(info, Form("its only track num %f", nchPassedSelection)); } int totalGlobalTrack = 0; + // calculate number of pid particle + int numOfPi = 0; + int numOfKa = 0; + int numOfPr = 0; - // fill v2 flow + /// @note fill v2 flow // use global track for (const auto& track : tracks) { float weff = 1; @@ -1579,7 +1844,7 @@ struct PidFlowPtCorr { setParticleNUEWeight(weff, track, cent, true); // end do NUE && NUA - if (cfgDoLocDenCorr) { + if (switchsOpts.cfgDoLocDenCorr.value) { bool withinPtRef = (trkQualityOpts.cfgCutPtMin.value < track.pt()) && (track.pt() < trkQualityOpts.cfgCutPtMax.value); if (withinPtRef) { double fphi = v2 * std::cos(2 * (track.phi() - psi2Est)) + v3 * std::cos(3 * (track.phi() - psi3Est)) + v4 * std::cos(4 * (track.phi() - psi4Est)); @@ -1595,7 +1860,7 @@ struct PidFlowPtCorr { } } // cfgDoLocDenCorr - if (cfgDebugMyCode) { + if (switchsOpts.cfgDebugMyCode.value) { // pt eff weight graph { int ptBin = debugHist.hPtEffWeight->GetXaxis()->FindBin(track.pt()); @@ -1650,11 +1915,11 @@ struct PidFlowPtCorr { // end track cut totalGlobalTrack++; - if (cfgDebugMyCode && weff == 1.) { + if (switchsOpts.cfgDebugMyCode.value && weff == 1.) { LOGF(info, "weff for global track is 1, if NUE is open and this appears a lot, check!"); } - if (cfgDebugMyCode && wacc == 1.) { + if (switchsOpts.cfgDebugMyCode.value && wacc == 1.) { LOGF(info, "wacc for global track is 1, if NUA is open and this appears alot, check!"); } @@ -1667,24 +1932,8 @@ struct PidFlowPtCorr { // end fill QA hist // pt spectra - if (cfgOutPutPtSpectra) { + if (switchsOpts.cfgOutPutPtSpectra.value) { registry.fill(HIST("ptSpectra/hPtCentData"), track.pt(), cent); - - // region 1 +eta +ch - if (track.eta() > 0.05 && track.sign() > 0) - registry.fill(HIST("ptSpectra/hPtCentDataPosEtaPosCh"), track.pt(), cent); - - // region 2 +eta -ch - if (track.eta() > 0.05 && track.sign() < 0) - registry.fill(HIST("ptSpectra/hPtCentDataPosEtaNegCh"), track.pt(), cent); - - // region 3 -eta +ch - if (track.eta() < -0.05 && track.sign() > 0) - registry.fill(HIST("ptSpectra/hPtCentDataNegEtaPosCh"), track.pt(), cent); - - // region 4 -eta -ch - if (track.eta() < -0.05 && track.sign() < 0) - registry.fill(HIST("ptSpectra/hPtCentDataNegEtaNegCh"), track.pt(), cent); } // fill GFW @@ -1695,23 +1944,33 @@ struct PidFlowPtCorr { // bitmask 18: 0010010 fGFW->Fill(track.eta(), 0, track.phi(), wacc * weff, 18); // fill PIONS and overlap Pions + numOfPi++; } if (isKaon(track)) { // bitmask 36: 0100100 fGFW->Fill(track.eta(), 0, track.phi(), wacc * weff, 36); // fill KAONS and overlap Kaons + numOfKa++; } if (isProton(track)) { // bitmask 72: 1001000 fGFW->Fill(track.eta(), 0, track.phi(), wacc * weff, 72); // fill PROTONS and overlap Protons + numOfPr++; } // end fill GFW } // end track loop for v2 calculation - if (cfgDebugMyCode) { + // sub region, fill graphs after 2 loop on all tracks + if (particleAbundanceOpts.cfgOutPutAbundanceDis) { + registry.fill(HIST("abundance/hNumOfPiEventCount"), numOfPi); + registry.fill(HIST("abundance/hNumOfKaEventCount"), numOfKa); + registry.fill(HIST("abundance/hNumOfPrEventCount"), numOfPr); + } // outputabundacedis + + if (switchsOpts.cfgDebugMyCode.value) { LOGF(info, Form("global track num %d", totalGlobalTrack)); } @@ -1732,13 +1991,6 @@ struct PidFlowPtCorr { fillFC(MyParticleType::kProton, corrconfigs.at(39), cent, rndm, "c22Full"); fillFC(MyParticleType::kProton, corrconfigs.at(40), cent, rndm, "c22Full"); - fillFC(MyParticleType::kPion, corrconfigs.at(5), cent, rndm, "c22"); - fillFC(MyParticleType::kPion, corrconfigs.at(6), cent, rndm, "c22"); - fillFC(MyParticleType::kKaon, corrconfigs.at(7), cent, rndm, "c22"); - fillFC(MyParticleType::kKaon, corrconfigs.at(8), cent, rndm, "c22"); - fillFC(MyParticleType::kProton, corrconfigs.at(9), cent, rndm, "c22"); - fillFC(MyParticleType::kProton, corrconfigs.at(10), cent, rndm, "c22"); - fillFC(MyParticleType::kPion, corrconfigs.at(11), cent, rndm, "c24"); fillFC(MyParticleType::kPion, corrconfigs.at(12), cent, rndm, "c24"); fillFC(MyParticleType::kKaon, corrconfigs.at(13), cent, rndm, "c24"); @@ -1760,13 +2012,26 @@ struct PidFlowPtCorr { fillFC(MyParticleType::kProton, corrconfigs.at(27), cent, rndm, "c34"); fillFC(MyParticleType::kProton, corrconfigs.at(28), cent, rndm, "c34"); - fillFC(MyParticleType::kPion, corrconfigs.at(29), cent, rndm, "c22pure"); - fillFC(MyParticleType::kKaon, corrconfigs.at(30), cent, rndm, "c22pure"); - fillFC(MyParticleType::kProton, corrconfigs.at(31), cent, rndm, "c22pure"); + bool filledPi = fillFC(MyParticleType::kPion, corrconfigs.at(29), cent, rndm, "c22pure"); + bool filledKa = fillFC(MyParticleType::kKaon, corrconfigs.at(30), cent, rndm, "c22pure"); + bool filledPr = fillFC(MyParticleType::kProton, corrconfigs.at(31), cent, rndm, "c22pure"); + fillFC(MyParticleType::kPion, corrconfigs.at(32), cent, rndm, "c32pure"); fillFC(MyParticleType::kKaon, corrconfigs.at(33), cent, rndm, "c32pure"); fillFC(MyParticleType::kProton, corrconfigs.at(34), cent, rndm, "c32pure"); + if (filledPi || !switchsOpts.cfgCheck2MethodDiff.value) { + fillFC(MyParticleType::kPion, corrconfigs.at(5), cent, rndm, "c22"); + fillFC(MyParticleType::kPion, corrconfigs.at(6), cent, rndm, "c22"); + } + if (filledKa || !switchsOpts.cfgCheck2MethodDiff.value) { + fillFC(MyParticleType::kKaon, corrconfigs.at(7), cent, rndm, "c22"); + fillFC(MyParticleType::kKaon, corrconfigs.at(8), cent, rndm, "c22"); + } + if (filledPr || !switchsOpts.cfgCheck2MethodDiff.value) { + fillFC(MyParticleType::kProton, corrconfigs.at(9), cent, rndm, "c22"); + fillFC(MyParticleType::kProton, corrconfigs.at(10), cent, rndm, "c22"); + } fillFCvnpt(MyParticleType::kCharged, corrconfigs.at(0), cent, rndm, nch, nch, "c22TrackWeight"); fillFCvnpt(MyParticleType::kCharged, corrconfigs.at(1), cent, rndm, nch, nch, "c24TrackWeight"); fillFCvnpt(MyParticleType::kCharged, corrconfigs.at(2), cent, rndm, nch, nch, "c22FullTrackWeight"); @@ -1799,10 +2064,54 @@ struct PidFlowPtCorr { fillProfilePOIvnpt(corrconfigs.at(9), HIST("pr/c22dmeanpt"), cent, ptSum, nch); fillProfilePOIvnpt(corrconfigs.at(10), HIST("pr/c22dmeanpt"), cent, ptSum, nch); + fillFC4PtC22(cent, ptSum, nch, rndm); + if (nPionWeighted > 0) + fillFC4PtC22(cent, nch, rndm, MyParticleType::kPion, pionPtSum, nPionWeighted); + + if (nKaonWeighted > 0) + fillFC4PtC22(cent, nch, rndm, MyParticleType::kKaon, kaonPtSum, nKaonWeighted); + + if (nProtonWeighted > 0) + fillFC4PtC22(cent, nch, rndm, MyParticleType::kProton, protonPtSum, nProtonWeighted); + + if (switchsOpts.cfgOutPutPtSpectra.value) { + // charged calculation + double NpairCharged = fGFW->Calculate(corrconfigs.at(0), 0, true).real(); + double chargedC22 = NpairCharged > 0 ? fGFW->Calculate(corrconfigs.at(0), 0, false).real() / NpairCharged : 0; + // end charged calculation + + // pi + double pidChargedC22Pi = getPidC22InOneEvent(corrconfigs.at(5), corrconfigs.at(6)); + if (pidChargedC22Pi > 0 && chargedC22 > 0) + registry.fill(HIST("c22PrimeVsc22/Pi"), pidChargedC22Pi, chargedC22); + // end pi + + // Ka + double pidKaonC22 = getPidC22InOneEvent(corrconfigs.at(7), corrconfigs.at(8)); + if (pidKaonC22 > 0 && chargedC22 > 0) + registry.fill(HIST("c22PrimeVsc22/Ka"), pidKaonC22, chargedC22); + // end Ka + + // Pr + double pidProtonC22 = getPidC22InOneEvent(corrconfigs.at(9), corrconfigs.at(10)); + if (pidProtonC22 > 0 && chargedC22 > 0) + registry.fill(HIST("c22PrimeVsc22/Pr"), pidProtonC22, chargedC22); + // end Pr + } + fFCCh->FillProfile("hMeanPt", cent, (ptSum / nch), nch, rndm); + if (nPionWeighted > 0) + fFCPi->FillProfile("hMeanPt", cent, (pionPtSum / nPionWeighted), nPionWeighted, rndm); + + if (nKaonWeighted > 0) + fFCKa->FillProfile("hMeanPt", cent, (kaonPtSum / nKaonWeighted), nKaonWeighted, rndm); + + if (nProtonWeighted > 0) + fFCPr->FillProfile("hMeanPt", cent, (protonPtSum / nProtonWeighted), nProtonWeighted, rndm); + double nchDiff = nch * nch - nchSquare; - if (nchDiff) { + if (nchDiff > 1e-3) { fFCCh->FillProfile("ptSquareAve", cent, (ptSum * ptSum - ptSquareSum) / nchDiff, nchDiff, rndm); @@ -1811,6 +2120,40 @@ struct PidFlowPtCorr { (nch * ptSum - ptSumw2) / nchDiff, nchDiff, rndm); } + + double pionDiff = nPionWeighted * nPionWeighted - nPionSquare; + if (pionDiff > 1e-3) { + fFCPi->FillProfile("ptSquareAve", cent, + (pionPtSum * pionPtSum - pionPtSquareSum) / pionDiff, + pionDiff, rndm); + + fFCPi->FillProfile("ptAve", cent, + (nPionWeighted * pionPtSum - pionPtSumw2) / pionDiff, + pionDiff, rndm); + } + + double kaonDiff = nKaonWeighted * nKaonWeighted - nKaonSquare; + if (kaonDiff > 1e-3) { + fFCKa->FillProfile("ptSquareAve", cent, + (kaonPtSum * kaonPtSum - kaonPtSquareSum) / kaonDiff, + kaonDiff, rndm); + + fFCKa->FillProfile("ptAve", cent, + (nKaonWeighted * kaonPtSum - kaonPtSumw2) / kaonDiff, + kaonDiff, rndm); + } + + double protonDiff = nProtonWeighted * nProtonWeighted - nProtonSquare; + if (protonDiff > 1e-3) { + fFCPr->FillProfile("ptSquareAve", cent, + (protonPtSum * protonPtSum - protonPtSquareSum) / protonDiff, + protonDiff, rndm); + + fFCPr->FillProfile("ptAve", cent, + (nProtonWeighted * protonPtSum - protonPtSumw2) / protonDiff, + protonDiff, rndm); + } + } // end fill hist using fillProfile } PROCESS_SWITCH(PidFlowPtCorr, processData, "", true); @@ -2004,7 +2347,7 @@ struct PidFlowPtCorr { return; // end init && cut - if (cfgOutPutPtSpectra) { + if (switchsOpts.cfgOutPutPtSpectra.value) { registry.fill(HIST("ptSpectra/hCentEventCountMcRec"), cent); } // cfgoutputptspectra @@ -2092,7 +2435,7 @@ struct PidFlowPtCorr { continue; // end collision cut - if (cfgOutPutPtSpectra) { + if (switchsOpts.cfgOutPutPtSpectra.value) { registry.fill(HIST("ptSpectra/hCentEventCountMcGen"), cent); } // cfgoutputptspectra @@ -2123,6 +2466,8 @@ struct PidFlowPtCorr { // end cut && init } PROCESS_SWITCH(PidFlowPtCorr, processSim, "function used to do pt eff, NOTE (OutPutMc, processReco, processSim) should be open", true); + + // main function }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) From f14edd51e4ab93f9c4a13fe3530bdd1944d435fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <26327373+vkucera@users.noreply.github.com> Date: Mon, 16 Mar 2026 09:41:29 +0100 Subject: [PATCH 285/347] [Infrastructure] Sync clang-format version in pre-commit hooks with the CI (#15398) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6c154ffad42..5d7b8a3726a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -7,7 +7,7 @@ repos: - id: trailing-whitespace - id: end-of-file-fixer - repo: https://github.com/pre-commit/mirrors-clang-format - rev: v21.1.8 # clang-format version + rev: v18.1.3 # clang-format version hooks: - id: clang-format - repo: https://github.com/cpplint/cpplint From 9a9176aef2bb70e87e2d85cf3bd0657c10c5fb6d Mon Sep 17 00:00:00 2001 From: fuchuncui <162277233+fuchuncui@users.noreply.github.com> Date: Mon, 16 Mar 2026 17:35:42 +0800 Subject: [PATCH 286/347] [PWGCF] Add QA histos and fix a bug for v0 and casc PID (#15359) --- PWGCF/Flow/Tasks/flowGfwOmegaXi.cxx | 264 ++++++++++++++++++++++------ 1 file changed, 211 insertions(+), 53 deletions(-) diff --git a/PWGCF/Flow/Tasks/flowGfwOmegaXi.cxx b/PWGCF/Flow/Tasks/flowGfwOmegaXi.cxx index 4b41fbbb893..7f4bb419769 100644 --- a/PWGCF/Flow/Tasks/flowGfwOmegaXi.cxx +++ b/PWGCF/Flow/Tasks/flowGfwOmegaXi.cxx @@ -119,6 +119,8 @@ struct FlowGfwOmegaXi { O2_DEFINE_CONFIGURABLE(cfgcasc_v0cospa, float, 0.998f, "minimum cosine of pointing angle") O2_DEFINE_CONFIGURABLE(cfgcasc_dcav0topv, float, 0.01f, "minimum daughter DCA to PV") O2_DEFINE_CONFIGURABLE(cfgcasc_dcabachtopv, float, 0.01f, "minimum bachelor DCA to PV") + O2_DEFINE_CONFIGURABLE(cfgcasc_dcaLapitopv, float, 0.1f, "minimum pion from casc->Lambda->Pi DCA to PV") + O2_DEFINE_CONFIGURABLE(cfgcasc_dcaLaprtopv, float, 0.1f, "minimum proton from casc->Lambda->Pr DCA to PV") O2_DEFINE_CONFIGURABLE(cfgcasc_dcacascdau, float, 0.3f, "maximum DCA among cascade daughters") O2_DEFINE_CONFIGURABLE(cfgcasc_dcav0dau, float, 1.0f, "maximum DCA among V0 daughters") O2_DEFINE_CONFIGURABLE(cfgcasc_mlambdawindow, float, 0.04f, "Invariant mass window of lambda") @@ -423,18 +425,35 @@ struct FlowGfwOmegaXi { // QA if (cfgOutputQA) { // V0 QA - registry.add("QAhisto/V0/hqaV0radiusbefore", "", {HistType::kTH1D, {{200, 0, 200}}}); - registry.add("QAhisto/V0/hqaV0radiusafter", "", {HistType::kTH1D, {{200, 0, 200}}}); - registry.add("QAhisto/V0/hqaV0cosPAbefore", "", {HistType::kTH1D, {{1000, 0.95, 1}}}); - registry.add("QAhisto/V0/hqaV0cosPAafter", "", {HistType::kTH1D, {{1000, 0.95, 1}}}); - registry.add("QAhisto/V0/hqadcaV0daubefore", "", {HistType::kTH1D, {{100, 0, 1}}}); - registry.add("QAhisto/V0/hqadcaV0dauafter", "", {HistType::kTH1D, {{100, 0, 1}}}); - registry.add("QAhisto/V0/hqaarm_podobefore", "", {HistType::kTH2D, {{100, -1, 1}, {50, 0, 0.3}}}); - registry.add("QAhisto/V0/hqaarm_podoafter", "", {HistType::kTH2D, {{100, -1, 1}, {50, 0, 0.3}}}); - registry.add("QAhisto/V0/hqadcapostoPVbefore", "", {HistType::kTH1D, {{1000, -10, 10}}}); - registry.add("QAhisto/V0/hqadcapostoPVafter", "", {HistType::kTH1D, {{1000, -10, 10}}}); - registry.add("QAhisto/V0/hqadcanegtoPVbefore", "", {HistType::kTH1D, {{1000, -10, 10}}}); - registry.add("QAhisto/V0/hqadcanegtoPVafter", "", {HistType::kTH1D, {{1000, -10, 10}}}); + registry.add("QAhisto/K0s/hqaV0radiusbefore", "", {HistType::kTH1D, {{200, 0, 200}}}); + registry.add("QAhisto/K0s/hqaV0radiusafter", "", {HistType::kTH1D, {{200, 0, 200}}}); + registry.add("QAhisto/K0s/hqaV0cosPAbefore", "", {HistType::kTH1D, {{1000, 0.95, 1}}}); + registry.add("QAhisto/K0s/hqaV0cosPAafter", "", {HistType::kTH1D, {{1000, 0.95, 1}}}); + registry.add("QAhisto/K0s/hqadcaV0daubefore", "", {HistType::kTH1D, {{100, 0, 1}}}); + registry.add("QAhisto/K0s/hqadcaV0dauafter", "", {HistType::kTH1D, {{100, 0, 1}}}); + registry.add("QAhisto/K0s/hqaarm_podobefore", "", {HistType::kTH2D, {{100, -1, 1}, {50, 0, 0.3}}}); + registry.add("QAhisto/K0s/hqaarm_podoafter", "", {HistType::kTH2D, {{100, -1, 1}, {50, 0, 0.3}}}); + registry.add("QAhisto/K0s/hqadcapostoPVbefore", "", {HistType::kTH1D, {{1000, -10, 10}}}); + registry.add("QAhisto/K0s/hqadcapostoPVafter", "", {HistType::kTH1D, {{1000, -10, 10}}}); + registry.add("QAhisto/K0s/hqadcanegtoPVbefore", "", {HistType::kTH1D, {{1000, -10, 10}}}); + registry.add("QAhisto/K0s/hqadcanegtoPVafter", "", {HistType::kTH1D, {{1000, -10, 10}}}); + registry.add("QAhisto/K0s/hphiposPi", "", {HistType::kTH1D, {cfgaxisPhi}}); + registry.add("QAhisto/K0s/hphinegPi", "", {HistType::kTH1D, {cfgaxisPhi}}); + + registry.add("QAhisto/Lambda/hqaV0radiusbefore", "", {HistType::kTH1D, {{200, 0, 200}}}); + registry.add("QAhisto/Lambda/hqaV0radiusafter", "", {HistType::kTH1D, {{200, 0, 200}}}); + registry.add("QAhisto/Lambda/hqaV0cosPAbefore", "", {HistType::kTH1D, {{1000, 0.95, 1}}}); + registry.add("QAhisto/Lambda/hqaV0cosPAafter", "", {HistType::kTH1D, {{1000, 0.95, 1}}}); + registry.add("QAhisto/Lambda/hqadcaV0daubefore", "", {HistType::kTH1D, {{100, 0, 1}}}); + registry.add("QAhisto/Lambda/hqadcaV0dauafter", "", {HistType::kTH1D, {{100, 0, 1}}}); + registry.add("QAhisto/Lambda/hqadcaPrtoPVbefore", "", {HistType::kTH1D, {{1000, -10, 10}}}); + registry.add("QAhisto/Lambda/hqadcaPrtoPVafter", "", {HistType::kTH1D, {{1000, -10, 10}}}); + registry.add("QAhisto/Lambda/hqadcaPitoPVbefore", "", {HistType::kTH1D, {{1000, -10, 10}}}); + registry.add("QAhisto/Lambda/hqadcaPitoPVafter", "", {HistType::kTH1D, {{1000, -10, 10}}}); + registry.add("QAhisto/Lambda/hphiposPi", "", {HistType::kTH1D, {cfgaxisPhi}}); + registry.add("QAhisto/Lambda/hphiposPr", "", {HistType::kTH1D, {cfgaxisPhi}}); + registry.add("QAhisto/Lambda/hphinegPi", "", {HistType::kTH1D, {cfgaxisPhi}}); + registry.add("QAhisto/Lambda/hphinegPr", "", {HistType::kTH1D, {cfgaxisPhi}}); // Cascade QA registry.add("QAhisto/Xi/hqaCascRadiusbefore", "", {HistType::kTH1D, {{200, -10, 10}}}); registry.add("QAhisto/Xi/hqaCascRadiusafter", "", {HistType::kTH1D, {{200, -10, 10}}}); @@ -446,10 +465,19 @@ struct FlowGfwOmegaXi { registry.add("QAhisto/Xi/hqadcaCascV0toPVafter", "", {HistType::kTH1D, {{1000, -10, 10}}}); registry.add("QAhisto/Xi/hqadcaCascBachtoPVbefore", "", {HistType::kTH1D, {{1000, -10, 10}}}); registry.add("QAhisto/Xi/hqadcaCascBachtoPVafter", "", {HistType::kTH1D, {{1000, -10, 10}}}); + registry.add("QAhisto/Xi/hqadcaCascLaprtoPVbefore", "", {HistType::kTH1D, {{1000, -10, 10}}}); + registry.add("QAhisto/Xi/hqadcaCascLaprtoPVafter", "", {HistType::kTH1D, {{1000, -10, 10}}}); + registry.add("QAhisto/Xi/hqadcaCascLapitoPVbefore", "", {HistType::kTH1D, {{1000, -10, 10}}}); + registry.add("QAhisto/Xi/hqadcaCascLapitoPVafter", "", {HistType::kTH1D, {{1000, -10, 10}}}); registry.add("QAhisto/Xi/hqadcaCascdaubefore", "", {HistType::kTH1D, {{100, 0, 1}}}); registry.add("QAhisto/Xi/hqadcaCascdauafter", "", {HistType::kTH1D, {{100, 0, 1}}}); registry.add("QAhisto/Xi/hqadcaCascV0daubefore", "", {HistType::kTH1D, {{100, 0, 1}}}); registry.add("QAhisto/Xi/hqadcaCascV0dauafter", "", {HistType::kTH1D, {{100, 0, 1}}}); + registry.add("QAhisto/Xi/hTOFnsigmaposPi", "", {HistType::kTH1D, {{1000, -100, 100}}}); + registry.add("QAhisto/Xi/hTOFnsigmaposPr", "", {HistType::kTH1D, {{1000, -100, 100}}}); + registry.add("QAhisto/Xi/hBachTOFnsigmavsPt", "", {HistType::kTH2D, {{1000, -100, 100}, cfgaxisPt}}); + registry.add("QAhisto/Xi/hLaPrTOFnsigmavsPt", "", {HistType::kTH2D, {{1000, -100, 100}, cfgaxisPt}}); + registry.add("QAhisto/Xi/hLaPiTOFnsigmavsPt", "", {HistType::kTH2D, {{1000, -100, 100}, cfgaxisPt}}); registry.add("QAhisto/Omega/hqaCascRadiusbefore", "", {HistType::kTH1D, {{200, -10, 10}}}); registry.add("QAhisto/Omega/hqaCascRadiusafter", "", {HistType::kTH1D, {{200, -10, 10}}}); @@ -461,6 +489,10 @@ struct FlowGfwOmegaXi { registry.add("QAhisto/Omega/hqadcaCascV0toPVafter", "", {HistType::kTH1D, {{1000, -10, 10}}}); registry.add("QAhisto/Omega/hqadcaCascBachtoPVbefore", "", {HistType::kTH1D, {{1000, -10, 10}}}); registry.add("QAhisto/Omega/hqadcaCascBachtoPVafter", "", {HistType::kTH1D, {{1000, -10, 10}}}); + registry.add("QAhisto/Omega/hqadcaCascLaprtoPVbefore", "", {HistType::kTH1D, {{1000, -10, 10}}}); + registry.add("QAhisto/Omega/hqadcaCascLaprtoPVafter", "", {HistType::kTH1D, {{1000, -10, 10}}}); + registry.add("QAhisto/Omega/hqadcaCascLapitoPVbefore", "", {HistType::kTH1D, {{1000, -10, 10}}}); + registry.add("QAhisto/Omega/hqadcaCascLapitoPVafter", "", {HistType::kTH1D, {{1000, -10, 10}}}); registry.add("QAhisto/Omega/hqadcaCascdaubefore", "", {HistType::kTH1D, {{100, 0, 1}}}); registry.add("QAhisto/Omega/hqadcaCascdauafter", "", {HistType::kTH1D, {{100, 0, 1}}}); registry.add("QAhisto/Omega/hqadcaCascV0daubefore", "", {HistType::kTH1D, {{100, 0, 1}}}); @@ -552,8 +584,10 @@ struct FlowGfwOmegaXi { if (cfgOutputV0) { registry.add("InvMassK0s_all", "", {HistType::kTHnSparseF, {cfgaxisPtK0s, axisK0sMass, cfgaxisEta, axisMultiplicity}}); registry.add("InvMassLambda_all", "", {HistType::kTHnSparseF, {cfgaxisPtLambda, axisLambdaMass, cfgaxisEta, axisMultiplicity}}); + registry.add("InvMassALambda_all", "", {HistType::kTHnSparseF, {cfgaxisPtLambda, axisLambdaMass, cfgaxisEta, axisMultiplicity}}); registry.add("InvMassK0s", "", {HistType::kTHnSparseF, {cfgaxisPtK0s, axisK0sMass, cfgaxisEta, axisMultiplicity}}); registry.add("InvMassLambda", "", {HistType::kTHnSparseF, {cfgaxisPtLambda, axisLambdaMass, cfgaxisEta, axisMultiplicity}}); + registry.add("InvMassALambda", "", {HistType::kTHnSparseF, {cfgaxisPtLambda, axisLambdaMass, cfgaxisEta, axisMultiplicity}}); } // for local density correction if (cfgOutputLocDenWeights) { @@ -1008,7 +1042,7 @@ struct FlowGfwOmegaXi { return true; } - void processData(AodCollisions::iterator const& collision, aod::BCsWithTimestamps const&, AodTracks const& tracks, soa::Join const& Cascades, aod::V0Datas const& V0s, DaughterTracks const&) + void processData(AodCollisions::iterator const& collision, aod::BCsWithTimestamps const&, AodTracks const& tracks, soa::Join const& Cascades, soa::Join const& V0s, DaughterTracks const&) { o2::aod::ITSResponse itsResponse; int nTot = tracks.size(); @@ -1103,6 +1137,7 @@ struct FlowGfwOmegaXi { // check tpc bool isK0s = false; bool isLambda = false; + bool isALambda = false; if (v0posdau.pt() < trkQualityOpts.cfgCutPtDauMin.value || v0posdau.pt() > trkQualityOpts.cfgCutPtDauMax.value) continue; if (v0negdau.pt() < trkQualityOpts.cfgCutPtDauMin.value || v0negdau.pt() > trkQualityOpts.cfgCutPtDauMax.value) @@ -1110,7 +1145,7 @@ struct FlowGfwOmegaXi { // fill QA if (cfgOutputQA) { - registry.fill(HIST("QAhisto/V0/hqaarm_podobefore"), v0.alpha(), v0.qtarm()); + registry.fill(HIST("QAhisto/K0s/hqaarm_podobefore"), v0.alpha(), v0.qtarm()); } // check daughter ITS, TPC and TOF // K0short @@ -1118,12 +1153,12 @@ struct FlowGfwOmegaXi { if (v0.qtarm() / std::fabs(v0.alpha()) > v0BuilderOpts.cfgv0_ArmPodocut.value && std::fabs(v0.mK0Short() - o2::constants::physics::MassK0Short) < v0BuilderOpts.cfgv0_mk0swindow.value && (std::fabs(v0posdau.tpcNSigmaPi()) < cfgNSigma[0] && std::fabs(v0negdau.tpcNSigmaPi()) < cfgNSigma[0]) && - ((std::fabs(v0posdau.tofNSigmaPi()) < cfgNSigma[3] || v0posdau.pt() < lowpt) && (std::fabs(v0negdau.tofNSigmaPi()) < cfgNSigma[3] || v0negdau.pt() < lowpt)) && + ((std::fabs(v0.tofNSigmaK0PiPlus()) < cfgNSigma[3] || v0posdau.pt() < lowpt) && (std::fabs(v0.tofNSigmaK0PiMinus()) < cfgNSigma[3] || v0negdau.pt() < lowpt)) && ((std::fabs(itsResponse.nSigmaITS(v0posdau)) < cfgNSigma[6]) || v0posdau.pt() > lowpt) && ((std::fabs(itsResponse.nSigmaITS(v0negdau)) < cfgNSigma[6]) || v0negdau.pt() > lowpt)) { registry.fill(HIST("InvMassK0s_all"), v0.pt(), v0.mK0Short(), v0.eta(), cent); isK0s = true; if (cfgOutputQA) { - registry.fill(HIST("QAhisto/V0/hqaarm_podoafter"), v0.alpha(), v0.qtarm()); + registry.fill(HIST("QAhisto/K0s/hqaarm_podoafter"), v0.alpha(), v0.qtarm()); } } } @@ -1131,27 +1166,44 @@ struct FlowGfwOmegaXi { if (v0.pt() > trkQualityOpts.cfgCutPtLambdaMin.value && v0.pt() < trkQualityOpts.cfgCutPtLambdaMax.value) { if (std::fabs(v0.mLambda() - o2::constants::physics::MassLambda) < v0BuilderOpts.cfgv0_mlambdawindow.value && (std::fabs(v0posdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(v0negdau.tpcNSigmaPi()) < cfgNSigma[0]) && - ((std::fabs(v0posdau.tofNSigmaPr()) < cfgNSigma[4] || v0posdau.pt() < lowpt) && (std::fabs(v0negdau.tofNSigmaPi()) < cfgNSigma[3] || v0negdau.pt() < lowpt)) && + ((std::fabs(v0.tofNSigmaLaPr()) < cfgNSigma[4] || v0posdau.pt() < lowpt) && (std::fabs(v0.tofNSigmaLaPi()) < cfgNSigma[3] || v0negdau.pt() < lowpt)) && ((std::fabs(itsResponse.nSigmaITS(v0posdau)) < cfgNSigma[7]) || v0posdau.pt() > lowpt) && ((std::fabs(itsResponse.nSigmaITS(v0negdau)) < cfgNSigma[6]) || v0negdau.pt() > lowpt)) { registry.fill(HIST("InvMassLambda_all"), v0.pt(), v0.mLambda(), v0.eta(), cent); isLambda = true; - } else if (std::fabs(v0.mLambda() - o2::constants::physics::MassLambda) < v0BuilderOpts.cfgv0_mlambdawindow.value && - (std::fabs(v0negdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(v0posdau.tpcNSigmaPi()) < cfgNSigma[0]) && - ((std::fabs(v0negdau.tofNSigmaPr()) < cfgNSigma[4] || v0negdau.pt() < lowpt) && (std::fabs(v0posdau.tofNSigmaPi()) < cfgNSigma[3] || v0posdau.pt() < lowpt)) && - ((std::fabs(itsResponse.nSigmaITS(v0posdau)) < cfgNSigma[7]) || v0posdau.pt() > lowpt) && ((std::fabs(itsResponse.nSigmaITS(v0negdau)) < cfgNSigma[6]) || v0negdau.pt() > lowpt)) { - registry.fill(HIST("InvMassLambda_all"), v0.pt(), v0.mLambda(), v0.eta(), cent); - isLambda = true; + } + if (std::fabs(v0.mAntiLambda() - o2::constants::physics::MassLambda) < v0BuilderOpts.cfgv0_mlambdawindow.value && + (std::fabs(v0negdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(v0posdau.tpcNSigmaPi()) < cfgNSigma[0]) && + ((std::fabs(v0.tofNSigmaALaPr()) < cfgNSigma[4] || v0negdau.pt() < lowpt) && (std::fabs(v0.tofNSigmaALaPi()) < cfgNSigma[3] || v0posdau.pt() < lowpt)) && + ((std::fabs(itsResponse.nSigmaITS(v0negdau)) < cfgNSigma[7]) || v0posdau.pt() > lowpt) && ((std::fabs(itsResponse.nSigmaITS(v0posdau)) < cfgNSigma[6]) || v0negdau.pt() > lowpt)) { + registry.fill(HIST("InvMassALambda_all"), v0.pt(), v0.mAntiLambda(), v0.eta(), cent); + isALambda = true; } } // fill QA before cut if (cfgOutputQA) { - registry.fill(HIST("QAhisto/V0/hqaV0radiusbefore"), v0.v0radius()); - registry.fill(HIST("QAhisto/V0/hqaV0cosPAbefore"), v0.v0cosPA()); - registry.fill(HIST("QAhisto/V0/hqadcaV0daubefore"), v0.dcaV0daughters()); - registry.fill(HIST("QAhisto/V0/hqadcapostoPVbefore"), v0.dcapostopv()); - registry.fill(HIST("QAhisto/V0/hqadcanegtoPVbefore"), v0.dcanegtopv()); + if (isK0s) { + registry.fill(HIST("QAhisto/K0s/hqaV0radiusbefore"), v0.v0radius()); + registry.fill(HIST("QAhisto/K0s/hqaV0cosPAbefore"), v0.v0cosPA()); + registry.fill(HIST("QAhisto/K0s/hqadcaV0daubefore"), v0.dcaV0daughters()); + registry.fill(HIST("QAhisto/K0s/hqadcapostoPVbefore"), v0.dcapostopv()); + registry.fill(HIST("QAhisto/K0s/hqadcanegtoPVbefore"), v0.dcanegtopv()); + } + if (isLambda) { + registry.fill(HIST("QAhisto/Lambda/hqaV0radiusbefore"), v0.v0radius()); + registry.fill(HIST("QAhisto/Lambda/hqaV0cosPAbefore"), v0.v0cosPA()); + registry.fill(HIST("QAhisto/Lambda/hqadcaV0daubefore"), v0.dcaV0daughters()); + registry.fill(HIST("QAhisto/Lambda/hqadcaPrtoPVbefore"), v0.dcapostopv()); + registry.fill(HIST("QAhisto/Lambda/hqadcaPitoPVbefore"), v0.dcanegtopv()); + } + if (isALambda) { + registry.fill(HIST("QAhisto/Lambda/hqaV0radiusbefore"), v0.v0radius()); + registry.fill(HIST("QAhisto/Lambda/hqaV0cosPAbefore"), v0.v0cosPA()); + registry.fill(HIST("QAhisto/Lambda/hqadcaV0daubefore"), v0.dcaV0daughters()); + registry.fill(HIST("QAhisto/Lambda/hqadcaPrtoPVbefore"), v0.dcanegtopv()); + registry.fill(HIST("QAhisto/Lambda/hqadcaPitoPVbefore"), v0.dcapostopv()); + } } - if (!isK0s && !isLambda) + if (!isK0s && !isLambda && !isALambda) continue; // track quality check if (v0posdau.itsNCls() <= trkQualityOpts.cfgITSNCls.value) @@ -1187,14 +1239,38 @@ struct FlowGfwOmegaXi { isK0s = false; if (isLambda && std::fabs(v0.mK0Short() - o2::constants::physics::MassK0Short) < v0BuilderOpts.cfgv0_compmassrejK0s.value) isLambda = false; + if (isALambda && std::fabs(v0.mK0Short() - o2::constants::physics::MassK0Short) < v0BuilderOpts.cfgv0_compmassrejK0s.value) + isALambda = false; // fill QA after cut if (cfgOutputQA) { - registry.fill(HIST("QAhisto/V0/hqaV0radiusafter"), v0.v0radius()); - registry.fill(HIST("QAhisto/V0/hqaV0cosPAafter"), v0.v0cosPA()); - registry.fill(HIST("QAhisto/V0/hqadcaV0dauafter"), v0.dcaV0daughters()); - registry.fill(HIST("QAhisto/V0/hqadcapostoPVafter"), v0.dcapostopv()); - registry.fill(HIST("QAhisto/V0/hqadcanegtoPVafter"), v0.dcanegtopv()); + if (isK0s) { + registry.fill(HIST("QAhisto/K0s/hqaV0radiusafter"), v0.v0radius()); + registry.fill(HIST("QAhisto/K0s/hqaV0cosPAafter"), v0.v0cosPA()); + registry.fill(HIST("QAhisto/K0s/hqadcaV0dauafter"), v0.dcaV0daughters()); + registry.fill(HIST("QAhisto/K0s/hqadcapostoPVafter"), v0.dcapostopv()); + registry.fill(HIST("QAhisto/K0s/hqadcanegtoPVafter"), v0.dcanegtopv()); + registry.fill(HIST("QAhisto/K0s/hphiposPi"), v0posdau.phi()); + registry.fill(HIST("QAhisto/K0s/hphinegPi"), v0negdau.phi()); + } + if (isLambda) { + registry.fill(HIST("QAhisto/Lambda/hqaV0radiusafter"), v0.v0radius()); + registry.fill(HIST("QAhisto/Lambda/hqaV0cosPAafter"), v0.v0cosPA()); + registry.fill(HIST("QAhisto/Lambda/hqadcaV0dauafter"), v0.dcaV0daughters()); + registry.fill(HIST("QAhisto/Lambda/hqadcaPrtoPVafter"), v0.dcapostopv()); + registry.fill(HIST("QAhisto/Lambda/hqadcaPitoPVafter"), v0.dcanegtopv()); + registry.fill(HIST("QAhisto/Lambda/hphiposPr"), v0posdau.phi()); + registry.fill(HIST("QAhisto/Lambda/hphinegPi"), v0negdau.phi()); + } + if (isALambda) { + registry.fill(HIST("QAhisto/Lambda/hqaV0radiusafter"), v0.v0radius()); + registry.fill(HIST("QAhisto/Lambda/hqaV0cosPAafter"), v0.v0cosPA()); + registry.fill(HIST("QAhisto/Lambda/hqadcaV0dauafter"), v0.dcaV0daughters()); + registry.fill(HIST("QAhisto/Lambda/hqadcaPrtoPVafter"), v0.dcanegtopv()); + registry.fill(HIST("QAhisto/Lambda/hqadcaPitoPVafter"), v0.dcapostopv()); + registry.fill(HIST("QAhisto/Lambda/hphiposPi"), v0posdau.phi()); + registry.fill(HIST("QAhisto/Lambda/hphinegPr"), v0negdau.phi()); + } } if (isK0s) { if (cfgDoAccEffCorr) @@ -1225,7 +1301,7 @@ struct FlowGfwOmegaXi { registry.fill(HIST("correction/hRunNumberPhiEtaVertexK0s"), matchedPosition, v0.phi(), v0.eta(), vtxz); } } - if (isLambda) { + if (isLambda || isALambda) { if (cfgDoAccEffCorr) setCurrentParticleWeights(weff, wacc, v0, vtxz, 2); if (cfgDoLocDenCorr) { @@ -1238,10 +1314,16 @@ struct FlowGfwOmegaXi { registry.fill(HIST("MC/densityMCRecLambdaMultTPC"), v0.pt(), nMultTPC, density, v0.mLambda()); } } - registry.fill(HIST("InvMassLambda"), v0.pt(), v0.mLambda(), v0.eta(), cent); + if (isLambda) + registry.fill(HIST("InvMassLambda"), v0.pt(), v0.mLambda(), v0.eta(), cent); + if (isALambda) + registry.fill(HIST("InvMassALambda"), v0.pt(), v0.mAntiLambda(), v0.eta(), cent); registry.fill(HIST("hPhiLambda"), v0.phi()); registry.fill(HIST("hPhiLambdacorr"), v0.phi(), wacc); - fGFW->Fill(v0.eta(), fLambdaPtAxis->FindBin(v0.pt()) - 1 + ((fLambdaMass->FindBin(v0.mLambda()) - 1) * nLambdaPtBins), v0.phi(), wacc * weff * wloc, 16); + if (isLambda) + fGFW->Fill(v0.eta(), fLambdaPtAxis->FindBin(v0.pt()) - 1 + ((fLambdaMass->FindBin(v0.mLambda()) - 1) * nLambdaPtBins), v0.phi(), wacc * weff * wloc, 16); + if (isALambda) + fGFW->Fill(v0.eta(), fLambdaPtAxis->FindBin(v0.pt()) - 1 + ((fLambdaMass->FindBin(v0.mAntiLambda()) - 1) * nLambdaPtBins), v0.phi(), wacc * weff * wloc, 16); if (cfgOutputNUAWeights) fWeightsLambda->fill(v0.phi(), v0.eta(), vtxz, v0.pt(), cent, 0); if (cfgOutputrunbyrun) { @@ -1276,13 +1358,13 @@ struct FlowGfwOmegaXi { if (casc.pt() > trkQualityOpts.cfgCutPtOmegaMin.value && casc.pt() < trkQualityOpts.cfgCutPtOmegaMax.value) { if (casc.sign() < 0 && std::fabs(casc.yOmega()) < cfgCasc_rapidity && (std::fabs(bachelor.tpcNSigmaKa()) < cfgNSigma[2] && std::fabs(posdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(negdau.tpcNSigmaPi()) < cfgNSigma[0]) && - ((std::fabs(casc.tofNSigmaOmKa()) < cfgNSigma[5] || bachelor.pt() < bachPtcut) && (std::fabs(casc.tofNSigmaOmLaPr()) < cfgNSigma[4] || posdau.pt() < dauLaPrPtcut) && (std::fabs(casc.tofNSigmaOmLaPi()) < cfgNSigma[3] || negdau.pt() < dauLaPiPtcut)) && + ((std::fabs(casc.tofNSigmaOmKa()) < cfgNSigma[5] || bachelor.pt() < bachPtcut) && (std::fabs(casc.tofNSigmaOmLaPr()) < cfgNSigma[4] || posdau.pt() < dauLaPrPtcut)) && ((std::fabs(itsResponse.nSigmaITS(bachelor)) < cfgNSigma[8]) || bachelor.pt() > bachPtcut) && ((std::fabs(itsResponse.nSigmaITS(posdau)) < cfgNSigma[7]) || posdau.pt() > dauLaPrPtcut) && ((std::fabs(itsResponse.nSigmaITS(negdau)) < cfgNSigma[6]) || negdau.pt() > dauLaPiPtcut)) { registry.fill(HIST("InvMassOmega_all"), casc.pt(), casc.mOmega(), casc.eta(), cent); isOmega = true; } else if (casc.sign() > 0 && std::fabs(casc.yOmega()) < cfgCasc_rapidity && (std::fabs(bachelor.tpcNSigmaKa()) < cfgNSigma[2] && std::fabs(negdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(posdau.tpcNSigmaPi()) < cfgNSigma[0]) && - ((std::fabs(casc.tofNSigmaOmKa()) < cfgNSigma[5] || bachelor.pt() < bachPtcut) && (std::fabs(casc.tofNSigmaOmLaPr()) < cfgNSigma[4] || negdau.pt() < dauLaPrPtcut) && (std::fabs(casc.tofNSigmaOmLaPi()) < cfgNSigma[3] || posdau.pt() < dauLaPiPtcut)) && + ((std::fabs(casc.tofNSigmaOmKa()) < cfgNSigma[5] || bachelor.pt() < bachPtcut) && (std::fabs(casc.tofNSigmaOmLaPi()) < cfgNSigma[3] || posdau.pt() < dauLaPiPtcut)) && ((std::fabs(itsResponse.nSigmaITS(bachelor)) < cfgNSigma[8]) || bachelor.pt() > bachPtcut) && ((std::fabs(itsResponse.nSigmaITS(negdau)) < cfgNSigma[7]) || negdau.pt() > dauLaPrPtcut) && ((std::fabs(itsResponse.nSigmaITS(posdau)) < cfgNSigma[6]) || posdau.pt() > dauLaPiPtcut)) { registry.fill(HIST("InvMassOmega_all"), casc.pt(), casc.mOmega(), casc.eta(), cent); isOmega = true; @@ -1292,16 +1374,22 @@ struct FlowGfwOmegaXi { if (casc.pt() > trkQualityOpts.cfgCutPtXiMin.value && casc.pt() < trkQualityOpts.cfgCutPtXiMax.value) { if (casc.sign() < 0 && std::fabs(casc.yXi()) < cfgCasc_rapidity && (std::fabs(bachelor.tpcNSigmaPi()) < cfgNSigma[0] && std::fabs(posdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(negdau.tpcNSigmaPi()) < cfgNSigma[0]) && - ((std::fabs(casc.tofNSigmaXiPi()) < cfgNSigma[3] || bachelor.pt() < bachPtcut) && (std::fabs(casc.tofNSigmaXiLaPr()) < cfgNSigma[4] || posdau.pt() < dauLaPrPtcut) && (std::fabs(casc.tofNSigmaXiLaPi()) < cfgNSigma[3] || negdau.pt() < dauLaPiPtcut)) && + ((std::fabs(casc.tofNSigmaXiPi()) < cfgNSigma[3] || bachelor.pt() < bachPtcut) && (std::fabs(casc.tofNSigmaXiLaPr()) < cfgNSigma[4] || posdau.pt() < dauLaPrPtcut)) && ((std::fabs(itsResponse.nSigmaITS(bachelor)) < cfgNSigma[6]) || bachelor.pt() > bachPtcut) && ((std::fabs(itsResponse.nSigmaITS(posdau)) < cfgNSigma[7]) || posdau.pt() > dauLaPrPtcut) && ((std::fabs(itsResponse.nSigmaITS(negdau)) < cfgNSigma[6]) || negdau.pt() > dauLaPiPtcut)) { registry.fill(HIST("InvMassXi_all"), casc.pt(), casc.mXi(), casc.eta(), cent); isXi = true; + registry.fill(HIST("QAhisto/Xi/hTOFnsigmaposPr"), casc.tofNSigmaXiLaPr()); + registry.fill(HIST("QAhisto/Xi/hBachTOFnsigmavsPt"), casc.tofNSigmaXiPi(), bachelor.pt()); + registry.fill(HIST("QAhisto/Xi/hLaPrTOFnsigmavsPt"), casc.tofNSigmaXiLaPr(), posdau.pt()); } else if (casc.sign() > 0 && std::fabs(casc.yXi()) < cfgCasc_rapidity && (std::fabs(bachelor.tpcNSigmaPi()) < cfgNSigma[0] && std::fabs(negdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(posdau.tpcNSigmaPi()) < cfgNSigma[0]) && - ((std::fabs(casc.tofNSigmaXiPi()) < cfgNSigma[3] || bachelor.pt() < bachPtcut) && (std::fabs(casc.tofNSigmaXiLaPr()) < cfgNSigma[4] || negdau.pt() < dauLaPrPtcut) && (std::fabs(casc.tofNSigmaXiLaPi()) < cfgNSigma[3] || posdau.pt() < dauLaPiPtcut)) && + ((std::fabs(casc.tofNSigmaXiPi()) < cfgNSigma[3] || bachelor.pt() < bachPtcut) && (std::fabs(casc.tofNSigmaXiLaPi()) < cfgNSigma[3] || posdau.pt() < dauLaPiPtcut)) && ((std::fabs(itsResponse.nSigmaITS(bachelor)) < cfgNSigma[6]) || bachelor.pt() > bachPtcut) && ((std::fabs(itsResponse.nSigmaITS(negdau)) < cfgNSigma[7]) || negdau.pt() > dauLaPrPtcut) && ((std::fabs(itsResponse.nSigmaITS(posdau)) < cfgNSigma[6]) || posdau.pt() > dauLaPiPtcut)) { registry.fill(HIST("InvMassXi_all"), casc.pt(), casc.mXi(), casc.eta(), cent); isXi = true; + registry.fill(HIST("QAhisto/Xi/hTOFnsigmaposPi"), casc.tofNSigmaXiLaPi()); + registry.fill(HIST("QAhisto/Xi/hBachTOFnsigmavsPt"), casc.tofNSigmaXiPi(), bachelor.pt()); + registry.fill(HIST("QAhisto/Xi/hLaPiTOFnsigmavsPt"), casc.tofNSigmaXiLaPi(), posdau.pt()); } } // fill QA @@ -1314,6 +1402,13 @@ struct FlowGfwOmegaXi { registry.fill(HIST("QAhisto/Xi/hqadcaCascBachtoPVbefore"), casc.dcabachtopv()); registry.fill(HIST("QAhisto/Xi/hqadcaCascdaubefore"), casc.dcacascdaughters()); registry.fill(HIST("QAhisto/Xi/hqadcaCascV0daubefore"), casc.dcaV0daughters()); + if (casc.sign() > 0) { + registry.fill(HIST("QAhisto/Xi/hqadcaCascLaprtoPVbefore"), casc.dcapostopv()); + registry.fill(HIST("QAhisto/Xi/hqadcaCascLapitoPVbefore"), casc.dcanegtopv()); + } else { + registry.fill(HIST("QAhisto/Xi/hqadcaCascLaprtoPVbefore"), casc.dcanegtopv()); + registry.fill(HIST("QAhisto/Xi/hqadcaCascLapitoPVbefore"), casc.dcapostopv()); + } } if (isOmega) { registry.fill(HIST("QAhisto/Omega/hqaCascRadiusbefore"), casc.cascradius()); @@ -1323,6 +1418,13 @@ struct FlowGfwOmegaXi { registry.fill(HIST("QAhisto/Omega/hqadcaCascBachtoPVbefore"), casc.dcabachtopv()); registry.fill(HIST("QAhisto/Omega/hqadcaCascdaubefore"), casc.dcacascdaughters()); registry.fill(HIST("QAhisto/Omega/hqadcaCascV0daubefore"), casc.dcaV0daughters()); + if (casc.sign() > 0) { + registry.fill(HIST("QAhisto/Omega/hqadcaCascLaprtoPVbefore"), casc.dcapostopv()); + registry.fill(HIST("QAhisto/Omega/hqadcaCascLapitoPVbefore"), casc.dcanegtopv()); + } else { + registry.fill(HIST("QAhisto/Omega/hqadcaCascLaprtoPVbefore"), casc.dcanegtopv()); + registry.fill(HIST("QAhisto/Omega/hqadcaCascLapitoPVbefore"), casc.dcapostopv()); + } } } @@ -1339,6 +1441,17 @@ struct FlowGfwOmegaXi { continue; if (std::fabs(casc.dcabachtopv()) < cascBuilderOpts.cfgcasc_dcabachtopv.value) continue; + if (casc.sign() > 0) { + if (std::fabs(casc.dcapostopv()) < cascBuilderOpts.cfgcasc_dcaLaprtopv.value) + continue; + if (std::fabs(casc.dcanegtopv()) < cascBuilderOpts.cfgcasc_dcaLapitopv.value) + continue; + } else { + if (std::fabs(casc.dcanegtopv()) < cascBuilderOpts.cfgcasc_dcaLaprtopv.value) + continue; + if (std::fabs(casc.dcapostopv()) < cascBuilderOpts.cfgcasc_dcaLapitopv.value) + continue; + } if (casc.dcacascdaughters() > cascBuilderOpts.cfgcasc_dcacascdau.value) continue; if (casc.dcaV0daughters() > cascBuilderOpts.cfgcasc_dcav0dau.value) @@ -1388,6 +1501,13 @@ struct FlowGfwOmegaXi { registry.fill(HIST("QAhisto/Xi/hqadcaCascBachtoPVafter"), casc.dcabachtopv()); registry.fill(HIST("QAhisto/Xi/hqadcaCascdauafter"), casc.dcacascdaughters()); registry.fill(HIST("QAhisto/Xi/hqadcaCascV0dauafter"), casc.dcaV0daughters()); + if (casc.sign() > 0) { + registry.fill(HIST("QAhisto/Xi/hqadcaCascLaprtoPVafter"), casc.dcapostopv()); + registry.fill(HIST("QAhisto/Xi/hqadcaCascLapitoPVafter"), casc.dcanegtopv()); + } else { + registry.fill(HIST("QAhisto/Xi/hqadcaCascLaprtoPVafter"), casc.dcanegtopv()); + registry.fill(HIST("QAhisto/Xi/hqadcaCascLapitoPVafter"), casc.dcapostopv()); + } } if (isOmega) { registry.fill(HIST("QAhisto/Omega/hqaCascRadiusafter"), casc.cascradius()); @@ -1397,6 +1517,13 @@ struct FlowGfwOmegaXi { registry.fill(HIST("QAhisto/Omega/hqadcaCascBachtoPVafter"), casc.dcabachtopv()); registry.fill(HIST("QAhisto/Omega/hqadcaCascdauafter"), casc.dcacascdaughters()); registry.fill(HIST("QAhisto/Omega/hqadcaCascV0dauafter"), casc.dcaV0daughters()); + if (casc.sign() > 0) { + registry.fill(HIST("QAhisto/Omega/hqadcaCascLaprtoPVafter"), casc.dcapostopv()); + registry.fill(HIST("QAhisto/Omega/hqadcaCascLapitoPVafter"), casc.dcanegtopv()); + } else { + registry.fill(HIST("QAhisto/Omega/hqadcaCascLaprtoPVafter"), casc.dcanegtopv()); + registry.fill(HIST("QAhisto/Omega/hqadcaCascLapitoPVafter"), casc.dcapostopv()); + } } } @@ -1926,6 +2053,7 @@ struct FlowGfwOmegaXi { auto v0MC = v0.mcParticle_as(); auto v0negdau = v0.negTrack_as(); auto v0posdau = v0.posTrack_as(); + int pdgCode{v0MC.pdgCode()}; if (v0posdau.pt() < trkQualityOpts.cfgCutPtDauMin.value || v0posdau.pt() > trkQualityOpts.cfgCutPtDauMax.value) continue; @@ -1934,12 +2062,27 @@ struct FlowGfwOmegaXi { // fill QA before cut if (cfgOutputQA) { - registry.fill(HIST("QAhisto/V0/hqaV0radiusbefore"), v0.v0radius()); - registry.fill(HIST("QAhisto/V0/hqaV0cosPAbefore"), v0.v0cosPA()); - registry.fill(HIST("QAhisto/V0/hqadcaV0daubefore"), v0.dcaV0daughters()); - registry.fill(HIST("QAhisto/V0/hqadcapostoPVbefore"), v0.dcapostopv()); - registry.fill(HIST("QAhisto/V0/hqadcanegtoPVbefore"), v0.dcanegtopv()); - registry.fill(HIST("QAhisto/V0/hqaarm_podobefore"), v0.alpha(), v0.qtarm()); + if (pdgCode == kK0Short) { + registry.fill(HIST("QAhisto/K0s/hqaV0radiusbefore"), v0.v0radius()); + registry.fill(HIST("QAhisto/K0s/hqaV0cosPAbefore"), v0.v0cosPA()); + registry.fill(HIST("QAhisto/K0s/hqadcaV0daubefore"), v0.dcaV0daughters()); + registry.fill(HIST("QAhisto/K0s/hqadcapostoPVbefore"), v0.dcapostopv()); + registry.fill(HIST("QAhisto/K0s/hqadcanegtoPVbefore"), v0.dcanegtopv()); + } + if (pdgCode == kLambda0) { + registry.fill(HIST("QAhisto/Lambda/hqaV0radiusbefore"), v0.v0radius()); + registry.fill(HIST("QAhisto/Lambda/hqaV0cosPAbefore"), v0.v0cosPA()); + registry.fill(HIST("QAhisto/Lambda/hqadcaV0daubefore"), v0.dcaV0daughters()); + registry.fill(HIST("QAhisto/Lambda/hqadcaPrtoPVbefore"), v0.dcapostopv()); + registry.fill(HIST("QAhisto/Lambda/hqadcaPitoPVbefore"), v0.dcanegtopv()); + } + if (pdgCode == kLambda0Bar) { + registry.fill(HIST("QAhisto/Lambda/hqaV0radiusbefore"), v0.v0radius()); + registry.fill(HIST("QAhisto/Lambda/hqaV0cosPAbefore"), v0.v0cosPA()); + registry.fill(HIST("QAhisto/Lambda/hqadcaV0daubefore"), v0.dcaV0daughters()); + registry.fill(HIST("QAhisto/Lambda/hqadcaPrtoPVbefore"), v0.dcanegtopv()); + registry.fill(HIST("QAhisto/Lambda/hqadcaPitoPVbefore"), v0.dcapostopv()); + } } // // track quality check if (v0posdau.itsNCls() <= trkQualityOpts.cfgITSNCls.value) @@ -1973,14 +2116,29 @@ struct FlowGfwOmegaXi { continue; // fill QA after cut if (cfgOutputQA) { - registry.fill(HIST("QAhisto/V0/hqaV0radiusafter"), v0.v0radius()); - registry.fill(HIST("QAhisto/V0/hqaV0cosPAafter"), v0.v0cosPA()); - registry.fill(HIST("QAhisto/V0/hqadcaV0dauafter"), v0.dcaV0daughters()); - registry.fill(HIST("QAhisto/V0/hqadcapostoPVafter"), v0.dcapostopv()); - registry.fill(HIST("QAhisto/V0/hqadcanegtoPVafter"), v0.dcanegtopv()); + if (pdgCode == kK0Short) { + registry.fill(HIST("QAhisto/K0s/hqaV0radiusafter"), v0.v0radius()); + registry.fill(HIST("QAhisto/K0s/hqaV0cosPAafter"), v0.v0cosPA()); + registry.fill(HIST("QAhisto/K0s/hqadcaV0dauafter"), v0.dcaV0daughters()); + registry.fill(HIST("QAhisto/K0s/hqadcapostoPVafter"), v0.dcapostopv()); + registry.fill(HIST("QAhisto/K0s/hqadcanegtoPVafter"), v0.dcanegtopv()); + } + if (pdgCode == kLambda0) { + registry.fill(HIST("QAhisto/Lambda/hqaV0radiusafter"), v0.v0radius()); + registry.fill(HIST("QAhisto/Lambda/hqaV0cosPAafter"), v0.v0cosPA()); + registry.fill(HIST("QAhisto/Lambda/hqadcaV0dauafter"), v0.dcaV0daughters()); + registry.fill(HIST("QAhisto/Lambda/hqadcaPrtoPVafter"), v0.dcapostopv()); + registry.fill(HIST("QAhisto/Lambda/hqadcaPitoPVafter"), v0.dcanegtopv()); + } + if (pdgCode == kLambda0Bar) { + registry.fill(HIST("QAhisto/Lambda/hqaV0radiusafter"), v0.v0radius()); + registry.fill(HIST("QAhisto/Lambda/hqaV0cosPAafter"), v0.v0cosPA()); + registry.fill(HIST("QAhisto/Lambda/hqadcaV0dauafter"), v0.dcaV0daughters()); + registry.fill(HIST("QAhisto/Lambda/hqadcaPrtoPVafter"), v0.dcanegtopv()); + registry.fill(HIST("QAhisto/Lambda/hqadcaPitoPVafter"), v0.dcapostopv()); + } } - int pdgCode{v0MC.pdgCode()}; double v0Pt{v0MC.pt()}; double v0Phi{v0MC.phi()}; double v0Eta{v0MC.eta()}; From e247de2653d516fb0be89a6929ad2c42ffef6b98 Mon Sep 17 00:00:00 2001 From: Francesco Mazzaschi <43742195+fmazzasc@users.noreply.github.com> Date: Mon, 16 Mar 2026 11:48:05 +0100 Subject: [PATCH 287/347] [PWGLF] Adapt task to study sigma-pion correlations (#15363) Co-authored-by: Francesco Mazzaschi Co-authored-by: ALICE Action Bot --- ...SigmaProtonTables.h => LFSigmaHadTables.h} | 46 +- .../TableProducer/Strangeness/CMakeLists.txt | 4 +- .../Strangeness/sigmaHadCorr.cxx | 742 ++++++++++++++++++ .../Strangeness/sigmaProtonCorr.cxx | 547 ------------- 4 files changed, 767 insertions(+), 572 deletions(-) rename PWGLF/DataModel/{LFSigmaProtonTables.h => LFSigmaHadTables.h} (52%) create mode 100644 PWGLF/TableProducer/Strangeness/sigmaHadCorr.cxx delete mode 100644 PWGLF/TableProducer/Strangeness/sigmaProtonCorr.cxx diff --git a/PWGLF/DataModel/LFSigmaProtonTables.h b/PWGLF/DataModel/LFSigmaHadTables.h similarity index 52% rename from PWGLF/DataModel/LFSigmaProtonTables.h rename to PWGLF/DataModel/LFSigmaHadTables.h index d9eafbedda5..a70af6317fd 100644 --- a/PWGLF/DataModel/LFSigmaProtonTables.h +++ b/PWGLF/DataModel/LFSigmaHadTables.h @@ -10,8 +10,8 @@ // or submit itself to any jurisdiction. /// -/// \file LFKinkDecayTables.h -/// \brief Slim tables for kinks +/// \file LFSigmaHadTables.h +/// \brief Slim tables for Sigma-hadron pairs /// \author Francesco Mazzaschi /// @@ -22,31 +22,31 @@ #include "Framework/ASoAHelpers.h" #include "Framework/AnalysisDataModel.h" -#ifndef PWGLF_DATAMODEL_LFSIGMAPROTONTABLES_H_ -#define PWGLF_DATAMODEL_LFSIGMAPROTONTABLES_H_ +#ifndef PWGLF_DATAMODEL_LFSIGMAHADTABLES_H_ +#define PWGLF_DATAMODEL_LFSIGMAHADTABLES_H_ namespace o2::aod { namespace sigmaproton { -DECLARE_SOA_COLUMN(ChargeSigma, chargeSigma, int); //! Charge of the sigma candidate -DECLARE_SOA_COLUMN(SigmaDecRad, sigmaDecRad, float); //! Decay radius of the Sigma candidate -DECLARE_SOA_COLUMN(SigmaCosPA, sigmaCosPA, float); //! Cosine of pointing angle of the Sigma candidate -DECLARE_SOA_COLUMN(ChargePr, chargePr, int); //! Charge of the proton candidate -DECLARE_SOA_COLUMN(PxPr, pxPr, float); //! Px of the proton candidate -DECLARE_SOA_COLUMN(PyPr, pyPr, float); //! Py of the proton candidate -DECLARE_SOA_COLUMN(PzPr, pzPr, float); //! Pz of the proton candidate -DECLARE_SOA_COLUMN(NSigmaTPCPr, nSigmaTPCPr, float); //! Number of sigmas for the proton candidate from Sigma kink in TPC -DECLARE_SOA_COLUMN(NSigmaTOFPr, nSigmaTOFPr, float); //! Number of sigmas for the proton candidate from Sigma kink in TOF +DECLARE_SOA_COLUMN(ChargeSigma, chargeSigma, int); //! Charge of the sigma candidate +DECLARE_SOA_COLUMN(SigmaDecRad, sigmaDecRad, float); //! Decay radius of the Sigma candidate +DECLARE_SOA_COLUMN(SigmaCosPA, sigmaCosPA, float); //! Cosine of pointing angle of the Sigma candidate +DECLARE_SOA_COLUMN(ChargeHad, chargeHad, int); //! Charge of the hadron candidate +DECLARE_SOA_COLUMN(PxHad, pxHad, float); //! Px of the hadron candidate +DECLARE_SOA_COLUMN(PyHad, pyHad, float); //! Py of the hadron candidate +DECLARE_SOA_COLUMN(PzHad, pzHad, float); //! Pz of the hadron candidate +DECLARE_SOA_COLUMN(NSigmaTPCHad, nSigmaTPCHad, float); //! Number of sigmas for the hadron candidate from Sigma kink in TPC +DECLARE_SOA_COLUMN(NSigmaTOFHad, nSigmaTOFHad, float); //! Number of sigmas for the hadron candidate from Sigma kink in TOF // MC Columns DECLARE_SOA_COLUMN(SigmaPDG, sigmaPDG, int); //! PDG code of the Sigma daughter DECLARE_SOA_COLUMN(DaughterPDG, daughterPDG, int); //! PDG code of the kink daughter -DECLARE_SOA_COLUMN(PrPDG, prPDG, int); //! PDG code of the proton candidate +DECLARE_SOA_COLUMN(HadPDG, hadPDG, int); //! PDG code of the hadron candidate DECLARE_SOA_COLUMN(SigmaGenPt, sigmaGenPt, float); //! Generated pT of the Sigma candidate -DECLARE_SOA_COLUMN(PrGenPt, prGenPt, float); //! Generated pT of the proton candidate -DECLARE_SOA_COLUMN(GenKStar, genKStar, float); //! Generated k* of the Sigma-Proton pair +DECLARE_SOA_COLUMN(HadGenPt, hadGenPt, float); //! Generated pT of the hadron candidate +DECLARE_SOA_COLUMN(GenKStar, genKStar, float); //! Generated k* of the Sigma-hadron pair } // namespace sigmaproton @@ -54,18 +54,18 @@ DECLARE_SOA_TABLE(SigmaProtonCands, "AOD", "SIGMAPROTONCANDS", o2::soa::Index<>, sigmaproton::ChargeSigma, kinkcand::PxMoth, kinkcand::PyMoth, kinkcand::PzMoth, kinkcand::PxDaug, kinkcand::PyDaug, kinkcand::PzDaug, sigmaproton::SigmaDecRad, sigmaproton::SigmaCosPA, - sigmaproton::ChargePr, sigmaproton::PxPr, sigmaproton::PyPr, sigmaproton::PzPr, - sigmaproton::NSigmaTPCPr, sigmaproton::NSigmaTOFPr); + sigmaproton::ChargeHad, sigmaproton::PxHad, sigmaproton::PyHad, sigmaproton::PzHad, + sigmaproton::NSigmaTPCHad, sigmaproton::NSigmaTOFHad); DECLARE_SOA_TABLE(SigmaProtonMCCands, "AOD", "SIGMAPROTONMCCANDS", o2::soa::Index<>, sigmaproton::ChargeSigma, kinkcand::PxMoth, kinkcand::PyMoth, kinkcand::PzMoth, kinkcand::PxDaug, kinkcand::PyDaug, kinkcand::PzDaug, sigmaproton::SigmaDecRad, sigmaproton::SigmaCosPA, - sigmaproton::ChargePr, sigmaproton::PxPr, sigmaproton::PyPr, sigmaproton::PzPr, - sigmaproton::NSigmaTPCPr, sigmaproton::NSigmaTOFPr, - sigmaproton::SigmaPDG, sigmaproton::DaughterPDG, sigmaproton::PrPDG, - sigmaproton::SigmaGenPt, sigmaproton::PrGenPt, sigmaproton::GenKStar); + sigmaproton::ChargeHad, sigmaproton::PxHad, sigmaproton::PyHad, sigmaproton::PzHad, + sigmaproton::NSigmaTPCHad, sigmaproton::NSigmaTOFHad, + sigmaproton::SigmaPDG, sigmaproton::DaughterPDG, sigmaproton::HadPDG, + sigmaproton::SigmaGenPt, sigmaproton::HadGenPt, sigmaproton::GenKStar); } // namespace o2::aod -#endif // PWGLF_DATAMODEL_LFSIGMAPROTONTABLES_H_ +#endif // PWGLF_DATAMODEL_LFSIGMAHADTABLES_H_ diff --git a/PWGLF/TableProducer/Strangeness/CMakeLists.txt b/PWGLF/TableProducer/Strangeness/CMakeLists.txt index 9a6e18ac944..3f1d8565951 100644 --- a/PWGLF/TableProducer/Strangeness/CMakeLists.txt +++ b/PWGLF/TableProducer/Strangeness/CMakeLists.txt @@ -162,8 +162,8 @@ o2physics_add_dpl_workflow(lambdaspincorrelation PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(sigmaprotoncorr - SOURCES sigmaProtonCorr.cxx +o2physics_add_dpl_workflow(sigmahadcorr + SOURCES sigmaHadCorr.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) diff --git a/PWGLF/TableProducer/Strangeness/sigmaHadCorr.cxx b/PWGLF/TableProducer/Strangeness/sigmaHadCorr.cxx new file mode 100644 index 00000000000..0467ae6a660 --- /dev/null +++ b/PWGLF/TableProducer/Strangeness/sigmaHadCorr.cxx @@ -0,0 +1,742 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file sigmaHadCorr.cxx +/// \brief Analysis task for sigma-hadron correlations +/// \author Francesco Mazzaschi + +#include "PWGLF/DataModel/LFKinkDecayTables.h" +#include "PWGLF/DataModel/LFSigmaHadTables.h" + +#include "Common/Core/PID/PIDTOF.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" + +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/PID.h" + +#include +#include +#include +#include + +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +using TracksFull = soa::Join; +using TracksFullMC = soa::Join; +using CollisionsFull = soa::Join; +using CollisionsFullMC = soa::Join; + +struct sigmaHadCand { + + float ptHad() const + { + return std::hypot(pxHad, pyHad); + } + float sigmaPt() const + { + return std::hypot(sigmaPx, sigmaPy); + } + + int sigmaCharge = 0; // Charge of the sigma candidate + float sigmaMass = -1.f; // Mass of the Sigma candidate + float sigmaPx = -1; // Px of the Sigma candidate + float sigmaPy = -1; // Py of the Sigma candidate + float sigmaPz = -1; // Pz of the Sigma candidate + float sigmaDauPx = -1; // Px of the daughter track from Sigma decay + float sigmaDauPy = -1; // Py of the daughter track from Sigma decay + float sigmaDauPz = -1; // Pz of the daughter track from Sigma decay + float sigmaDecRadius = -1; // Decay radius of the Sigma candidate + float sigmaCosPA = -1; // Cosine of pointing angle of the Sigma candidate + + int chargeHad = 0; // Charge of the hadron candidate + float pxHad = -1; // Px of the hadron candidate + float pyHad = -1; // Py of the hadron candidate + float pzHad = -1; // Pz of the hadron candidate + + float nSigmaTPCHad = -1; // Number of sigmas for the hadron candidate + float nSigmaTOFHad = -1; // Number of sigmas for the hadron candidate using TOF + + int kinkDauID = -1; // ID of the pion from Sigma decay in MC + int sigmaID = -1; // ID of the Sigma candidate in MC + int hadID = -1; // ID of the hadron candidate in MC +}; + +struct sigmaHadCorrTask { + + std::vector sigmaHadCandidates; // Vector to store Sigma-hadron candidates + Produces outputDataTable; // Output table for Sigma-hadron candidates + Produces outputDataTableMC; // Output table for Sigma-hadron candidates in MC + // Histograms are defined with HistogramRegistry + HistogramRegistry rEventSelection{"eventSelection", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rSigmaHad{"sigmaHad", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + // Configurable for event selection + Configurable cutzvertex{"cutZVertex", 10.0f, "Accepted z-vertex range (cm)"}; + + Configurable minPtSigma{"minPtSigma", 1.f, "Minimum pT for Sigma candidates (GeV/c)"}; + Configurable cutEtaDaught{"cutEtaDaughter", 0.8f, "Eta cut for daughter tracks"}; + Configurable cutDCAtoPVSigma{"cutDCAtoPVSigma", 0.1f, "Max DCA to primary vertex for Sigma candidates (cm)"}; + Configurable doSigmaMinus{"doSigmaMinus", true, "If true, pair Sigma- candidates, else Sigma+"}; + Configurable cutSigmaRadius{"cutSigmaRadius", 20.f, "Minimum radius for Sigma candidates (cm)"}; + Configurable cutSigmaMass{"cutSigmaMass", 0.3, "Sigma mass window (GeV/c^2)"}; + Configurable alphaAPCut{"alphaAPCut", 0., "Alpha AP cut for Sigma candidates"}; + Configurable qtAPCutLow{"qtAPCutLow", 0.15, "Lower qT AP cut for Sigma candidates (GeV/c)"}; + Configurable qtAPCutHigh{"qtAPCutHigh", 0.2, "Upper qT AP cut for Sigma candidates (GeV/c)"}; + + Configurable cutNITSClusPr{"cutNITSClusPr", 5, "Minimum number of ITS clusters for hadron track"}; + Configurable cutNTPCClusPr{"cutNTPCClusPr", 90, "Minimum number of TPC clusters for hadron track"}; + Configurable cutNSigmaTPC{"cutNSigmaTPC", 3, "TPC nSigma cut for hadron track"}; + Configurable cutNSigmaTOF{"cutNSigmaTOF", 3, "TOF nSigma cut for hadron track"}; + Configurable applyTOFPIDKinkDaughter{"applyTOFPIDKinkDaughter", false, "If true, apply TOF PID cut to the kink daughter track"}; + Configurable matchSigmaToPions{"matchSigmaToPions", false, "If true, pair Sigma with pions instead of hadrons"}; + + Configurable cutMaxKStar{"cutMaxKStar", 1.5, "Maximum k* for Sigma-hadron pairs (GeV/c)"}; + Configurable useRecalculatedSigmaMomentum{"useRecalculatedSigmaMomentum", false, "If true, compute k* using Sigma momentum recalculated from daughter kinematics"}; + + Configurable fillOutputTree{"fillOutputTree", true, "If true, fill the output tree with Sigma-hadron candidates"}; + Configurable fillSparseInvMassKstar{"fillSparseInvMassKstar", false, "If true, fill THnSparse with invmass, k*, sigma charge, proton charge, sigma decay radius, cosPA, sigma pt"}; + + ConfigurableAxis CfgVtxBins{"CfgVtxBins", {10, -10, 10}, "Mixing bins - z-vertex"}; + ConfigurableAxis CfgMultBins{"CfgMultBins", {VARIABLE_WIDTH, 0.0, 40.0, 80.0, 500.0}, "Mixing bins - number of contributor"}; + Configurable nEvtMixingBkg{"nEvtMixingBkg", 5, "Number of events to mix for background reconstruction"}; + + Preslice kinkCandsPerCollisionPreslice = aod::kinkcand::collisionId; + Preslice tracksPerCollisionPreslice = aod::track::collisionId; + Preslice tracksMCPerCollisionPreslice = aod::track::collisionId; + + void init(InitContext const&) + { + // Axes + const AxisSpec ptAxis{100, -10, 10, "#it{p}_{T} (GeV/#it{c})"}; + const AxisSpec massResolutionAxis{100, -0.1, 0.1, "m_{rec} - m_{gen} (GeV/#it{c}^{2})"}; + const AxisSpec nSigmaHadAxis{100, -5, 5, "n#sigma_{had}"}; + const AxisSpec sigmaMassAxis{100, 1.1, 1.3, "m (GeV/#it{c}^{2})"}; + const AxisSpec kStarAxis{200, 0.0, 2., "k* (GeV/#it{c})"}; + const AxisSpec ptHadAxis{100, 0.0, 10.0, "#it{p}_{T,had} (GeV/#it{c})"}; + const AxisSpec sigmaPtAxis{100, 0.0, 10.0, "#it{p}_{T,#Sigma} (GeV/#it{c})"}; + const AxisSpec sigmaChargeAxis{2, -1.5, 1.5, "#Sigma charge"}; + const AxisSpec hadronChargeAxis{2, -1.5, 1.5, "Hadron charge"}; + const AxisSpec sigmaDecRadiusAxis{25, 14.5, 40.5, "#Sigma decay radius (cm)"}; + const AxisSpec cosPAAxis{50, 0.9, 1.0, "cos(PA)"}; + const AxisSpec alphaAPAxis{100, -1.0, 1.0, "#alpha_{AP}"}; + const AxisSpec qtAPAxis{100, 0.0, 0.5, "q_{T,AP} (GeV/#it{c})"}; + const AxisSpec vertexZAxis{100, -15., 15., "vrtx_{Z} [cm]"}; + + // qa histograms + rEventSelection.add("hVertexZRec", "hVertexZRec", {HistType::kTH1F, {vertexZAxis}}); + // Dedicated QA folder + rSigmaHad.add("QA/h2TPCNSigmaHadVsPtHad", "TPC n#sigma_{had} vs #it{p}_{T,had}", {HistType::kTH2F, {ptHadAxis, nSigmaHadAxis}}); + rSigmaHad.add("QA/h2TOFNSigmaHadVsPtHad", "TOF n#sigma_{had} vs #it{p}_{T,had}", {HistType::kTH2F, {ptHadAxis, nSigmaHadAxis}}); + rSigmaHad.add("QA/hSigmaPt", "#Sigma #it{p}_{T}", {HistType::kTH1F, {sigmaPtAxis}}); + rSigmaHad.add("QA/hSigmaPtRecal", "#Sigma #it{p}_{T} recalculated", {HistType::kTH1F, {sigmaPtAxis}}); + rSigmaHad.add("QA/h2InvMassVsPtSigma", "m_{#Sigma} vs #it{p}_{T,#Sigma}", {HistType::kTH2F, {sigmaPtAxis, sigmaMassAxis}}); + rSigmaHad.add("QA/h2QtAPvsAlphaAP", "q_{T,AP} vs #alpha_{AP}", {HistType::kTH2F, {alphaAPAxis, qtAPAxis}}); + + if (fillSparseInvMassKstar) { + rSigmaHad.add("hSparseSigmaHad", + "7D sparse: invmass, k*, sigma charge, hadron charge, sigma decay radius, cosPA, sigma pt", + {HistType::kTHnSparseF, {sigmaMassAxis, kStarAxis, sigmaChargeAxis, hadronChargeAxis, sigmaDecRadiusAxis, cosPAAxis, sigmaPtAxis}}); + rSigmaHad.add("hSparseSigmaHadMC", + "8D sparse (MC): invmass, k*, sigma charge, hadron charge, sigma decay radius, cosPA, sigma pt, k* gen", + {HistType::kTHnSparseF, {sigmaMassAxis, kStarAxis, sigmaChargeAxis, hadronChargeAxis, sigmaDecRadiusAxis, cosPAAxis, sigmaPtAxis, kStarAxis}}); + } + + LOG(info) << "Sigma-hadron correlation task initialized"; + LOG(info) << "Process SE enabled: " << doprocessSameEvent; + LOG(info) << "Process ME enabled: " << doprocessMixedEvent; + LOG(info) << "Process SE MC enabled: " << doprocessSameEventMC; + LOG(info) << "Process ME MC enabled: " << doprocessMixedEventMC; + LOG(info) << "Pairing mode: " << (matchSigmaToPions ? "Sigma-pion" : "Sigma-hadron"); + } + + float getAlphaAP(const std::array& momMother, const std::array& momKink) + { + std::array momMissing = {momMother[0] - momKink[0], momMother[1] - momKink[1], momMother[2] - momKink[2]}; + float lQlP = std::inner_product(momMother.begin(), momMother.end(), momKink.begin(), 0.f); + float lQlN = std::inner_product(momMother.begin(), momMother.end(), momMissing.begin(), 0.f); + return (lQlP - lQlN) / (lQlP + lQlN); + } + + float getQtAP(const std::array& momMother, const std::array& momKink) + { + float dp = std::inner_product(momMother.begin(), momMother.end(), momKink.begin(), 0.f); + float p2V0 = std::inner_product(momMother.begin(), momMother.end(), momMother.begin(), 0.f); + float p2A = std::inner_product(momKink.begin(), momKink.end(), momKink.begin(), 0.f); + return std::sqrt(p2A - dp * dp / p2V0); + } + + float getCosPA(const std::array& momMother, const std::array& decayVertex, const std::array& primaryVertex) + { + std::array decayVec = {decayVertex[0] - primaryVertex[0], decayVertex[1] - primaryVertex[1], decayVertex[2] - primaryVertex[2]}; + float dotProduct = std::inner_product(momMother.begin(), momMother.end(), decayVec.begin(), 0.f); + float momMotherMag = std::sqrt(std::inner_product(momMother.begin(), momMother.end(), momMother.begin(), 0.f)); + float decayVecMag = std::sqrt(std::inner_product(decayVec.begin(), decayVec.end(), decayVec.begin(), 0.f)); + return dotProduct / (momMotherMag * decayVecMag); + } + + float getRecalculatedSigmaMomentum(const sigmaHadCand& candidate) + { + constexpr float massPion = o2::constants::physics::MassPionCharged; + constexpr float massNeutron = o2::constants::physics::MassNeutron; + float massSigma = doSigmaMinus ? o2::constants::physics::MassSigmaMinus : o2::constants::physics::MassSigmaPlus; + + float pMother = std::sqrt(candidate.sigmaPx * candidate.sigmaPx + candidate.sigmaPy * candidate.sigmaPy + candidate.sigmaPz * candidate.sigmaPz); + if (pMother < 1e-6f) { + return -999.f; + } + float versorX = candidate.sigmaPx / pMother; + float versorY = candidate.sigmaPy / pMother; + float versorZ = candidate.sigmaPz / pMother; + float ePi = std::sqrt(massPion * massPion + candidate.sigmaDauPx * candidate.sigmaDauPx + candidate.sigmaDauPy * candidate.sigmaDauPy + candidate.sigmaDauPz * candidate.sigmaDauPz); + float a = versorX * candidate.sigmaDauPx + versorY * candidate.sigmaDauPy + versorZ * candidate.sigmaDauPz; + float K = massSigma * massSigma + massPion * massPion - massNeutron * massNeutron; + float A = 4.f * (ePi * ePi - a * a); + float B = -4.f * a * K; + float C = 4.f * ePi * ePi * massSigma * massSigma - K * K; + if (std::abs(A) < 1e-6f) { + return -999.f; + } + float D = B * B - 4.f * A * C; + if (D < 0.f) { + return -999.f; + } + float sqrtD = std::sqrt(D); + float P1 = (-B + sqrtD) / (2.f * A); + float P2 = (-B - sqrtD) / (2.f * A); + if (P2 < 0.f && P1 < 0.f) { + return -999.f; + } + if (P2 < 0.f) { + return P1; + } + float p1Diff = std::abs(P1 - pMother); + float p2Diff = std::abs(P2 - pMother); + return (p1Diff < p2Diff) ? P1 : P2; + } + + std::array getSigmaMomentumForKstar(const sigmaHadCand& candidate) + { + std::array sigmaMomentum = {candidate.sigmaPx, candidate.sigmaPy, candidate.sigmaPz}; + if (!useRecalculatedSigmaMomentum) { + return sigmaMomentum; + } + + float pNew = getRecalculatedSigmaMomentum(candidate); + if (pNew <= 0.f) { + return sigmaMomentum; + } + + float pOld = std::sqrt(candidate.sigmaPx * candidate.sigmaPx + candidate.sigmaPy * candidate.sigmaPy + candidate.sigmaPz * candidate.sigmaPz); + if (pOld <= 0.f) { + return sigmaMomentum; + } + + float scale = pNew / pOld; + sigmaMomentum[0] *= scale; + sigmaMomentum[1] *= scale; + sigmaMomentum[2] *= scale; + return sigmaMomentum; + } + + float getHadTrackMass() + { + return matchSigmaToPions ? o2::constants::physics::MassPionCharged : o2::constants::physics::MassProton; + } + + float getSigmaMassForKstar() + { + return doSigmaMinus ? o2::constants::physics::MassSigmaMinus : o2::constants::physics::MassSigmaPlus; + } + + template + float getTPCNSigmaHad(const Ttrack& track) + { + return matchSigmaToPions ? track.tpcNSigmaPi() : track.tpcNSigmaPr(); + } + + template + float getTOFNSigmaHad(const Ttrack& track) + { + return matchSigmaToPions ? track.tofNSigmaPi() : track.tofNSigmaPr(); + } + + TLorentzVector trackSum, PartOneCMS, PartTwoCMS, trackRelK; + float getKStar(const sigmaHadCand& candidate) + { + TLorentzVector part1; // Sigma + TLorentzVector part2; // Hadron track (proton/pion) + part1.SetXYZM(candidate.sigmaPx, candidate.sigmaPy, candidate.sigmaPz, getSigmaMassForKstar()); + part2.SetXYZM(candidate.pxHad, candidate.pyHad, candidate.pzHad, getHadTrackMass()); + trackSum = part1 + part2; + const float beta = trackSum.Beta(); + const float betax = beta * std::cos(trackSum.Phi()) * std::sin(trackSum.Theta()); + const float betay = beta * std::sin(trackSum.Phi()) * std::sin(trackSum.Theta()); + const float betaz = beta * std::cos(trackSum.Theta()); + PartOneCMS.SetXYZM(part1.Px(), part1.Py(), part1.Pz(), part1.M()); + PartTwoCMS.SetXYZM(part2.Px(), part2.Py(), part2.Pz(), part2.M()); + const ROOT::Math::Boost boostPRF = ROOT::Math::Boost(-betax, -betay, -betaz); + PartOneCMS = boostPRF(PartOneCMS); + PartTwoCMS = boostPRF(PartTwoCMS); + trackRelK = PartOneCMS - PartTwoCMS; + return 0.5 * trackRelK.P(); + } + + float getKStar(float sigmaPx, float sigmaPy, float sigmaPz, float pxHad, float pyHad, float pzHad) + { + TLorentzVector part1; // Sigma + TLorentzVector part2; // Hadron track (proton/pion) + part1.SetXYZM(sigmaPx, sigmaPy, sigmaPz, getSigmaMassForKstar()); + part2.SetXYZM(pxHad, pyHad, pzHad, getHadTrackMass()); + trackSum = part1 + part2; + const float beta = trackSum.Beta(); + const float betax = beta * std::cos(trackSum.Phi()) * std::sin(trackSum.Theta()); + const float betay = beta * std::sin(trackSum.Phi()) * std::sin(trackSum.Theta()); + const float betaz = beta * std::cos(trackSum.Theta()); + PartOneCMS.SetXYZM(part1.Px(), part1.Py(), part1.Pz(), part1.M()); + PartTwoCMS.SetXYZM(part2.Px(), part2.Py(), part2.Pz(), part2.M()); + const ROOT::Math::Boost boostPRF = ROOT::Math::Boost(-betax, -betay, -betaz); + PartOneCMS = boostPRF(PartOneCMS); + PartTwoCMS = boostPRF(PartTwoCMS); + trackRelK = PartOneCMS - PartTwoCMS; + return 0.5 * trackRelK.P(); + } + + template + bool selectHadTrack(const Ttrack& candidate) + { + if (std::abs(getTPCNSigmaHad(candidate)) > cutNSigmaTPC || candidate.tpcNClsFound() < cutNTPCClusPr || std::abs(candidate.eta()) > cutEtaDaught) { + return false; + } + + if (candidate.itsNCls() < cutNITSClusPr) { + return false; + } + + float ptMinTOF = 0.75f; // Minimum pT to use TOF for hadron-track PID + if (candidate.pt() < ptMinTOF) { + return true; // No TOF cut for low pT + } + + if (!candidate.hasTOF()) { + return false; + } + if (std::abs(getTOFNSigmaHad(candidate)) > cutNSigmaTOF) { + return false; + } + return true; // Track is selected + } + + template + bool selectSigma(aod::KinkCands::iterator const& sigmaCand, Ttrack const& kinkDauTrack) + { + float mass = doSigmaMinus ? sigmaCand.mSigmaMinus() : sigmaCand.mSigmaPlus(); + std::array momMoth = {sigmaCand.pxMoth(), sigmaCand.pyMoth(), sigmaCand.pzMoth()}; + std::array momDaug = {sigmaCand.pxDaug(), sigmaCand.pyDaug(), sigmaCand.pzDaug()}; + float alphaAP = getAlphaAP(momMoth, momDaug); + float qtAP = getQtAP(momMoth, momDaug); + + if (sigmaCand.ptMoth() < minPtSigma) { + return false; + } + + if (alphaAP > alphaAPCut || (qtAP < qtAPCutLow || qtAP > qtAPCutHigh)) { + return false; + } + float decRad = std::hypot(sigmaCand.xDecVtx(), sigmaCand.yDecVtx()); + if (decRad < cutSigmaRadius) { + return false; + } + + if (doSigmaMinus) { + if (mass < o2::constants::physics::MassSigmaMinus - cutSigmaMass || mass > o2::constants::physics::MassSigmaMinus + cutSigmaMass) { + return false; + } + if (std::abs(kinkDauTrack.tpcNSigmaPi()) > cutNSigmaTPC) { + return false; + } + } else { + if (mass < o2::constants::physics::MassSigmaPlus - cutSigmaMass || mass > o2::constants::physics::MassSigmaPlus + cutSigmaMass) { + return false; + } + if (std::abs(kinkDauTrack.tpcNSigmaPr()) > cutNSigmaTPC) { + return false; + } + } + + if (applyTOFPIDKinkDaughter) { + constexpr float ptMinTOF = 0.75f; + if (kinkDauTrack.pt() >= ptMinTOF) { + if (!kinkDauTrack.hasTOF()) { + return false; + } + float kinkDauTOFNSigma = doSigmaMinus ? kinkDauTrack.tofNSigmaPi() : kinkDauTrack.tofNSigmaPr(); + if (std::abs(kinkDauTOFNSigma) > cutNSigmaTOF) { + return false; + } + } + } + + if (std::abs(sigmaCand.dcaMothPv()) > cutDCAtoPVSigma) { + return false; + } + return true; + } + + template + void fillTreeAndHistograms(aod::KinkCands const& kinkCands, Ttrack const& tracksDauSigma, Ttrack const& tracks, Tcollision const& collision, bool isMC) + { + for (const auto& sigmaCand : kinkCands) { + auto kinkDauTrack = tracksDauSigma.rawIteratorAt(sigmaCand.trackDaugId()); + if (!selectSigma(sigmaCand, kinkDauTrack)) { + continue; + } + + std::array momMothAll = {sigmaCand.pxMoth(), sigmaCand.pyMoth(), sigmaCand.pzMoth()}; + std::array momDaugAll = {sigmaCand.pxDaug(), sigmaCand.pyDaug(), sigmaCand.pzDaug()}; + float alphaAP = getAlphaAP(momMothAll, momDaugAll); + float qtAP = getQtAP(momMothAll, momDaugAll); + rSigmaHad.fill(HIST("QA/h2QtAPvsAlphaAP"), alphaAP, qtAP); + + sigmaHadCand sigmaForPt; + sigmaForPt.sigmaPx = sigmaCand.pxMoth(); + sigmaForPt.sigmaPy = sigmaCand.pyMoth(); + sigmaForPt.sigmaPz = sigmaCand.pzMoth(); + sigmaForPt.sigmaDauPx = sigmaCand.pxDaug(); + sigmaForPt.sigmaDauPy = sigmaCand.pyDaug(); + sigmaForPt.sigmaDauPz = sigmaCand.pzDaug(); + auto sigmaMomForPt = getSigmaMomentumForKstar(sigmaForPt); + float sigmaPtRecal = std::hypot(sigmaMomForPt[0], sigmaMomForPt[1]); + float sigmaPtForSparse = useRecalculatedSigmaMomentum ? sigmaPtRecal : sigmaCand.ptMoth(); + float sigmaMassForQa = doSigmaMinus ? sigmaCand.mSigmaMinus() : sigmaCand.mSigmaPlus(); + + rSigmaHad.fill(HIST("QA/hSigmaPt"), sigmaCand.ptMoth()); + rSigmaHad.fill(HIST("QA/hSigmaPtRecal"), sigmaPtRecal); + rSigmaHad.fill(HIST("QA/h2InvMassVsPtSigma"), sigmaPtForSparse, sigmaMassForQa); + + for (const auto& hadTrack : tracks) { + if (hadTrack.globalIndex() == sigmaCand.trackDaugId()) { + continue; + } + + if (!selectHadTrack(hadTrack)) { + continue; + } + + sigmaHadCand candidate; + candidate.sigmaCharge = sigmaCand.mothSign(); + candidate.sigmaPx = sigmaCand.pxMoth(); + candidate.sigmaPy = sigmaCand.pyMoth(); + candidate.sigmaPz = sigmaCand.pzMoth(); + candidate.sigmaDauPx = sigmaCand.pxDaug(); + candidate.sigmaDauPy = sigmaCand.pyDaug(); + candidate.sigmaDauPz = sigmaCand.pzDaug(); + candidate.sigmaDecRadius = std::hypot(sigmaCand.xDecVtx(), sigmaCand.yDecVtx()); + + std::array momMoth = {sigmaCand.pxMoth(), sigmaCand.pyMoth(), sigmaCand.pzMoth()}; + std::array decayVtx = {sigmaCand.xDecVtx(), sigmaCand.yDecVtx(), sigmaCand.zDecVtx()}; + std::array primaryVtx = {collision.posX(), collision.posY(), collision.posZ()}; + candidate.sigmaCosPA = getCosPA(momMoth, decayVtx, primaryVtx); + + candidate.chargeHad = hadTrack.sign(); + candidate.pxHad = hadTrack.px(); + candidate.pyHad = hadTrack.py(); + candidate.pzHad = hadTrack.pz(); + candidate.nSigmaTPCHad = getTPCNSigmaHad(hadTrack); + candidate.nSigmaTOFHad = getTOFNSigmaHad(hadTrack); + candidate.sigmaMass = doSigmaMinus ? sigmaCand.mSigmaMinus() : sigmaCand.mSigmaPlus(); + + candidate.sigmaID = sigmaCand.trackMothId(); + candidate.kinkDauID = sigmaCand.trackDaugId(); + candidate.hadID = hadTrack.globalIndex(); + + auto sigmaMomForKstar = getSigmaMomentumForKstar(candidate); + float kStar = getKStar(sigmaMomForKstar[0], sigmaMomForKstar[1], sigmaMomForKstar[2], candidate.pxHad, candidate.pyHad, candidate.pzHad); + if (kStar > cutMaxKStar) { + continue; + } + + float sigmaPtUsed = std::hypot(sigmaMomForKstar[0], sigmaMomForKstar[1]); + + rSigmaHad.fill(HIST("h2PtHadNSigmaTPC"), candidate.ptHad(), candidate.nSigmaTPCHad); + rSigmaHad.fill(HIST("QA/h2TPCNSigmaHadVsPtHad"), candidate.ptHad(), candidate.nSigmaTPCHad); + if (hadTrack.hasTOF()) { + rSigmaHad.fill(HIST("h2PtHadNSigmaTOF"), candidate.ptHad(), candidate.nSigmaTOFHad); + rSigmaHad.fill(HIST("QA/h2TOFNSigmaHadVsPtHad"), candidate.ptHad(), candidate.nSigmaTOFHad); + } + if (fillSparseInvMassKstar && !isMC) { + rSigmaHad.fill(HIST("hSparseSigmaHad"), + candidate.sigmaMass, + kStar, + candidate.sigmaCharge, + candidate.chargeHad, + candidate.sigmaDecRadius, + candidate.sigmaCosPA, + sigmaPtUsed); + } + sigmaHadCandidates.push_back(candidate); + } + } + } + + void processSameEvent(CollisionsFull const& collisions, aod::KinkCands const& kinkCands, TracksFull const& tracks) + { + for (auto const& collision : collisions) { + + sigmaHadCandidates.clear(); + auto kinkCands_c = kinkCands.sliceBy(kinkCandsPerCollisionPreslice, collision.globalIndex()); + auto tracks_c = tracks.sliceBy(tracksPerCollisionPreslice, collision.globalIndex()); + if (std::abs(collision.posZ()) > cutzvertex || !collision.sel8()) { + continue; + } + rEventSelection.fill(HIST("hVertexZRec"), collision.posZ()); + fillTreeAndHistograms(kinkCands_c, tracks_c, tracks_c, collision, false); + if (fillOutputTree) { + // Fill output table + for (const auto& candidate : sigmaHadCandidates) { + outputDataTable(candidate.sigmaCharge, + candidate.sigmaPx, + candidate.sigmaPy, + candidate.sigmaPz, + candidate.sigmaDauPx, + candidate.sigmaDauPy, + candidate.sigmaDauPz, + candidate.sigmaDecRadius, + candidate.sigmaCosPA, + candidate.chargeHad, + candidate.pxHad, + candidate.pyHad, + candidate.pzHad, + candidate.nSigmaTPCHad, + candidate.nSigmaTOFHad); + } + } + } + } + PROCESS_SWITCH(sigmaHadCorrTask, processSameEvent, "Process Same event", true); + + // Processing Event Mixing + SliceCache cache; + using BinningType = ColumnBinningPolicy; + BinningType colBinning{{CfgVtxBins, CfgMultBins}, true}; + + void processMixedEvent(const CollisionsFull& collisions, const aod::KinkCands& kinkCands, const TracksFull& tracks) + { + for (auto const& [collision1, collision2] : + selfCombinations(colBinning, nEvtMixingBkg, -1, collisions, collisions)) { + if (collision1.index() == collision2.index()) + continue; + + sigmaHadCandidates.clear(); + if (std::abs(collision1.posZ()) > cutzvertex || !collision1.sel8()) { + continue; + } + if (std::abs(collision2.posZ()) > cutzvertex || !collision2.sel8()) { + continue; + } + auto kinkCands_c1 = kinkCands.sliceBy(kinkCandsPerCollisionPreslice, collision1.globalIndex()); + auto tracks_c1 = tracks.sliceBy(tracksPerCollisionPreslice, collision1.globalIndex()); + auto tracks_c2 = tracks.sliceBy(tracksPerCollisionPreslice, collision2.globalIndex()); + fillTreeAndHistograms(kinkCands_c1, tracks_c1, tracks_c2, collision1, false); + + if (fillOutputTree) { + // Fill output table + for (const auto& candidate : sigmaHadCandidates) { + outputDataTable(candidate.sigmaCharge, + candidate.sigmaPx, + candidate.sigmaPy, + candidate.sigmaPz, + candidate.sigmaDauPx, + candidate.sigmaDauPy, + candidate.sigmaDauPz, + candidate.sigmaDecRadius, + candidate.sigmaCosPA, + candidate.chargeHad, + candidate.pxHad, + candidate.pyHad, + candidate.pzHad, + candidate.nSigmaTPCHad, + candidate.nSigmaTOFHad); + } + } + } + LOG(debug) << "Processing mixed event"; + } + PROCESS_SWITCH(sigmaHadCorrTask, processMixedEvent, "Process Mixed event", false); + + void processSameEventMC(CollisionsFullMC const& collisions, aod::KinkCands const& kinkCands, TracksFullMC const& tracks, aod::McParticles const&) + { + for (auto const& collision : collisions) { + + sigmaHadCandidates.clear(); + auto kinkCands_c = kinkCands.sliceBy(kinkCandsPerCollisionPreslice, collision.globalIndex()); + auto tracks_c = tracks.sliceBy(tracksMCPerCollisionPreslice, collision.globalIndex()); + + if (std::abs(collision.posZ()) > cutzvertex || !collision.sel8()) { + continue; + } + rEventSelection.fill(HIST("hVertexZRec"), collision.posZ()); + fillTreeAndHistograms(kinkCands_c, tracks_c, tracks_c, collision, true); + for (const auto& candidate : sigmaHadCandidates) { + auto mcLabelSigma = tracks.rawIteratorAt(candidate.sigmaID); + auto mcLabelSigmaDau = tracks.rawIteratorAt(candidate.kinkDauID); + auto mcLabelHad = tracks.rawIteratorAt(candidate.hadID); + + if (!mcLabelSigma.has_mcParticle() || !mcLabelSigmaDau.has_mcParticle() || !mcLabelHad.has_mcParticle()) { + continue; // Skip candidates where MC truth is not available + } + + auto mcPartSigma = mcLabelSigma.mcParticle_as(); + auto mcPartSigmaDau = mcLabelSigmaDau.mcParticle_as(); + auto mcPartHad = mcLabelHad.mcParticle_as(); + auto pdgSigma = mcPartSigma.pdgCode(); + auto pdgSigmaDau = mcLabelSigmaDau.has_mcParticle() ? mcPartSigmaDau.pdgCode() : -999; + auto pdgHad = mcLabelHad.has_mcParticle() ? mcPartHad.pdgCode() : -999; + + float sigmaPtGen = std::hypot(mcPartSigma.px(), mcPartSigma.py()); + float hadPtGen = std::hypot(mcPartHad.px(), mcPartHad.py()); + float kStarGen = getKStar(mcPartSigma.px(), mcPartSigma.py(), mcPartSigma.pz(), mcPartHad.px(), mcPartHad.py(), mcPartHad.pz()); + + if (fillSparseInvMassKstar) { + auto sigmaMomForKstar = getSigmaMomentumForKstar(candidate); + float kStarRec = getKStar(sigmaMomForKstar[0], sigmaMomForKstar[1], sigmaMomForKstar[2], candidate.pxHad, candidate.pyHad, candidate.pzHad); + float sigmaPtUsed = std::hypot(sigmaMomForKstar[0], sigmaMomForKstar[1]); + rSigmaHad.fill(HIST("hSparseSigmaHadMC"), + candidate.sigmaMass, + kStarRec, + candidate.sigmaCharge, + candidate.chargeHad, + candidate.sigmaDecRadius, + candidate.sigmaCosPA, + sigmaPtUsed, + kStarGen); + } + + if (fillOutputTree) { + outputDataTableMC(candidate.sigmaCharge, + candidate.sigmaPx, + candidate.sigmaPy, + candidate.sigmaPz, + candidate.sigmaDauPx, + candidate.sigmaDauPy, + candidate.sigmaDauPz, + candidate.sigmaDecRadius, + candidate.sigmaCosPA, + candidate.chargeHad, + candidate.pxHad, + candidate.pyHad, + candidate.pzHad, + candidate.nSigmaTPCHad, + candidate.nSigmaTOFHad, + pdgSigma, + pdgSigmaDau, + pdgHad, + sigmaPtGen, + hadPtGen, + kStarGen); + } + } + } + } + PROCESS_SWITCH(sigmaHadCorrTask, processSameEventMC, "Process Same event MC", false); + + void processMixedEventMC(const CollisionsFullMC& collisions, const aod::KinkCands& kinkCands, const TracksFullMC& tracks, const aod::McParticles&) + { + for (auto const& [collision1, collision2] : + selfCombinations(colBinning, nEvtMixingBkg, -1, collisions, collisions)) { + if (collision1.index() == collision2.index()) + continue; + + sigmaHadCandidates.clear(); + if (std::abs(collision1.posZ()) > cutzvertex || !collision1.sel8()) { + continue; + } + if (std::abs(collision2.posZ()) > cutzvertex || !collision2.sel8()) { + continue; + } + auto kinkCands_c1 = kinkCands.sliceBy(kinkCandsPerCollisionPreslice, collision1.globalIndex()); + auto tracks_c1 = tracks.sliceBy(tracksPerCollisionPreslice, collision1.globalIndex()); + auto tracks_c2 = tracks.sliceBy(tracksPerCollisionPreslice, collision2.globalIndex()); + fillTreeAndHistograms(kinkCands_c1, tracks_c1, tracks_c2, collision1, true); + + for (const auto& candidate : sigmaHadCandidates) { + auto mcLabelSigma = tracks.rawIteratorAt(candidate.sigmaID); + auto mcLabelSigmaDau = tracks.rawIteratorAt(candidate.kinkDauID); + auto mcLabelHad = tracks.rawIteratorAt(candidate.hadID); + + if (!mcLabelSigma.has_mcParticle() || !mcLabelSigmaDau.has_mcParticle() || !mcLabelHad.has_mcParticle()) { + continue; // Skip candidates where MC truth is not available + } + + auto mcPartSigma = mcLabelSigma.mcParticle_as(); + auto mcPartSigmaDau = mcLabelSigmaDau.mcParticle_as(); + auto mcPartHad = mcLabelHad.mcParticle_as(); + auto pdgSigma = mcPartSigma.pdgCode(); + auto pdgSigmaDau = mcLabelSigmaDau.has_mcParticle() ? mcPartSigmaDau.pdgCode() : -999; + auto pdgHad = mcLabelHad.has_mcParticle() ? mcPartHad.pdgCode() : -999; + float sigmaPtGen = std::hypot(mcPartSigma.px(), mcPartSigma.py()); + float hadPtGen = std::hypot(mcPartHad.px(), mcPartHad.py()); + float kStarGen = getKStar(mcPartSigma.px(), mcPartSigma.py(), mcPartSigma.pz(), mcPartHad.px(), mcPartHad.py(), mcPartHad.pz()); + + if (fillSparseInvMassKstar) { + auto sigmaMomForKstar = getSigmaMomentumForKstar(candidate); + float kStarRec = getKStar(sigmaMomForKstar[0], sigmaMomForKstar[1], sigmaMomForKstar[2], candidate.pxHad, candidate.pyHad, candidate.pzHad); + float sigmaPtUsed = std::hypot(sigmaMomForKstar[0], sigmaMomForKstar[1]); + rSigmaHad.fill(HIST("hSparseSigmaHadMC"), + candidate.sigmaMass, + kStarRec, + candidate.sigmaCharge, + candidate.chargeHad, + candidate.sigmaDecRadius, + candidate.sigmaCosPA, + sigmaPtUsed, + kStarGen); + } + + if (fillOutputTree) { + outputDataTableMC(candidate.sigmaCharge, + candidate.sigmaPx, + candidate.sigmaPy, + candidate.sigmaPz, + candidate.sigmaDauPx, + candidate.sigmaDauPy, + candidate.sigmaDauPz, + candidate.sigmaDecRadius, + candidate.sigmaCosPA, + candidate.chargeHad, + candidate.pxHad, + candidate.pyHad, + candidate.pzHad, + candidate.nSigmaTPCHad, + candidate.nSigmaTOFHad, + pdgSigma, + pdgSigmaDau, + pdgHad, + sigmaPtGen, + hadPtGen, + kStarGen); + } + } + } + LOG(debug) << "Processing mixed event MC"; + } + PROCESS_SWITCH(sigmaHadCorrTask, processMixedEventMC, "Process Mixed event MC", false); +}; +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/TableProducer/Strangeness/sigmaProtonCorr.cxx b/PWGLF/TableProducer/Strangeness/sigmaProtonCorr.cxx deleted file mode 100644 index 26c4eee67d7..00000000000 --- a/PWGLF/TableProducer/Strangeness/sigmaProtonCorr.cxx +++ /dev/null @@ -1,547 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -/// \file sigmaProtonCorr.cxx -/// \brief Analysis task for sigma-proton correlations -/// \author Francesco Mazzaschi - -#include "PWGLF/DataModel/LFKinkDecayTables.h" -#include "PWGLF/DataModel/LFSigmaProtonTables.h" - -#include "Common/Core/PID/PIDTOF.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/PIDResponseTOF.h" -#include "Common/DataModel/PIDResponseTPC.h" - -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/PID.h" - -#include -#include -#include -#include - -using namespace o2; -using namespace o2::framework; -using namespace o2::framework::expressions; - -using TracksFull = soa::Join; -using TracksFullMC = soa::Join; -using CollisionsFull = soa::Join; -using CollisionsFullMC = soa::Join; - -struct sigmaProtonCand { - - float ptPr() const - { - return std::hypot(pxPr, pyPr); - } - float sigmaPt() const - { - return std::hypot(sigmaPx, sigmaPy); - } - - int sigmaCharge = 0; // Charge of the sigma candidate - int sigmaMass = -1; // Mass of the Sigma candidate - float sigmaPx = -1; // Px of the Sigma candidate - float sigmaPy = -1; // Py of the Sigma candidate - float sigmaPz = -1; // Pz of the Sigma candidate - float sigmaDauPx = -1; // Px of the daughter track from Sigma decay - float sigmaDauPy = -1; // Py of the daughter track from Sigma decay - float sigmaDauPz = -1; // Pz of the daughter track from Sigma decay - float sigmaDecRadius = -1; // Decay radius of the Sigma candidate - float sigmaCosPA = -1; // Cosine of pointing angle of the Sigma candidate - - int chargePr = 0; // Charge of the proton candidate - float pxPr = -1; // Px of the proton candidate - float pyPr = -1; // Py of the proton candidate - float pzPr = -1; // Pz of the proton candidate - - float nSigmaTPCPr = -1; // Number of sigmas for the proton candidate - float nSigmaTOFPr = -1; // Number of sigmas for the proton candidate using TOF - - int kinkDauID = -1; // ID of the pion from Sigma decay in MC - int sigmaID = -1; // ID of the Sigma candidate in MC - int prID = -1; // ID of the proton candidate in MC -}; - -struct sigmaProtonCorrTask { - - std::vector sigmaProtonCandidates; // Vector to store Sigma-Proton candidates - Produces outputDataTable; // Output table for Sigma-Proton candidates - Produces outputDataTableMC; // Output table for Sigma-Proton candidates in MC - // Histograms are defined with HistogramRegistry - HistogramRegistry rEventSelection{"eventSelection", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - HistogramRegistry rSigmaProton{"sigmaProton", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - // Configurable for event selection - Configurable cutzvertex{"cutZVertex", 10.0f, "Accepted z-vertex range (cm)"}; - - Configurable minPtSigma{"minPtSigma", 1.f, "Minimum pT for Sigma candidates (GeV/c)"}; - Configurable cutEtaDaught{"cutEtaDaughter", 0.8f, "Eta cut for daughter tracks"}; - Configurable cutDCAtoPVSigma{"cutDCAtoPVSigma", 0.1f, "Max DCA to primary vertex for Sigma candidates (cm)"}; - Configurable doSigmaMinus{"doSigmaMinus", true, "If true, pair Sigma- candidates, else Sigma+"}; - Configurable cutSigmaRadius{"cutSigmaRadius", 20.f, "Minimum radius for Sigma candidates (cm)"}; - Configurable cutSigmaMass{"cutSigmaMass", 0.3, "Sigma mass window (GeV/c^2)"}; - Configurable alphaAPCut{"alphaAPCut", 0., "Alpha AP cut for Sigma candidates"}; - Configurable qtAPCutLow{"qtAPCutLow", 0.15, "Lower qT AP cut for Sigma candidates (GeV/c)"}; - Configurable qtAPCutHigh{"qtAPCutHigh", 0.2, "Upper qT AP cut for Sigma candidates (GeV/c)"}; - - Configurable cutNITSClusPr{"cutNITSClusPr", 5, "Minimum number of ITS clusters for proton candidate"}; - Configurable cutNTPCClusPr{"cutNTPCClusPr", 90, "Minimum number of TPC clusters for proton candidate"}; - Configurable cutNSigmaTPC{"cutNSigmaTPC", 3, "NSigmaTPCPr"}; - Configurable cutNSigmaTOF{"cutNSigmaTOF", 3, "NSigmaTOFPr"}; - - Configurable cutMaxKStar{"cutMaxKStar", 1.5, "Maximum k* for Sigma-Proton pairs (GeV/c)"}; - - Configurable fillOutputTree{"fillOutputTree", true, "If true, fill the output tree with Sigma-Proton candidates"}; - - ConfigurableAxis CfgVtxBins{"CfgVtxBins", {10, -10, 10}, "Mixing bins - z-vertex"}; - ConfigurableAxis CfgMultBins{"CfgMultBins", {VARIABLE_WIDTH, 0.0, 40.0, 80.0, 500.0}, "Mixing bins - number of contributor"}; - Configurable nEvtMixingBkg{"nEvtMixingBkg", 5, "Number of events to mix for background reconstruction"}; - - Preslice kinkCandsPerCollisionPreslice = aod::kinkcand::collisionId; - Preslice tracksPerCollisionPreslice = aod::track::collisionId; - Preslice tracksMCPerCollisionPreslice = aod::track::collisionId; - - void init(InitContext const&) - { - // Axes - const AxisSpec ptAxis{100, -10, 10, "#it{p}_{T} (GeV/#it{c})"}; - const AxisSpec massResolutionAxis{100, -0.1, 0.1, "m_{rec} - m_{gen} (GeV/#it{c}^{2})"}; - const AxisSpec nSigmaPrAxis{100, -5, 5, "n#sigma_{#pr}"}; - const AxisSpec sigmaMassAxis{100, 1.1, 1.4, "m (GeV/#it{c}^{2})"}; - const AxisSpec vertexZAxis{100, -15., 15., "vrtx_{Z} [cm]"}; - - // qa histograms - rEventSelection.add("hVertexZRec", "hVertexZRec", {HistType::kTH1F, {vertexZAxis}}); - rSigmaProton.add("h2PtMassSigma", "h2PtMassSigma", {HistType::kTH2F, {ptAxis, sigmaMassAxis}}); - rSigmaProton.add("h2PtPrNSigma", "h2PtPrNSigma", {HistType::kTH2F, {ptAxis, nSigmaPrAxis}}); - rSigmaProton.add("h2PtPrNSigmaTOF", "h2PtPrNSigmaTOF", {HistType::kTH2F, {ptAxis, nSigmaPrAxis}}); - - LOG(info) << "Sigma-Proton correlation task initialized"; - LOG(info) << "Process SE enabled: " << doprocessSameEvent; - LOG(info) << "Process ME enabled: " << doprocessMixedEvent; - LOG(info) << "Process SE MC enabled: " << doprocessSameEventMC; - LOG(info) << "Process ME MC enabled: " << doprocessMixedEventMC; - } - - float getAlphaAP(const std::array& momMother, const std::array& momKink) - { - std::array momMissing = {momMother[0] - momKink[0], momMother[1] - momKink[1], momMother[2] - momKink[2]}; - float lQlP = std::inner_product(momMother.begin(), momMother.end(), momKink.begin(), 0.f); - float lQlN = std::inner_product(momMother.begin(), momMother.end(), momMissing.begin(), 0.f); - return (lQlP - lQlN) / (lQlP + lQlN); - } - - float getQtAP(const std::array& momMother, const std::array& momKink) - { - float dp = std::inner_product(momMother.begin(), momMother.end(), momKink.begin(), 0.f); - float p2V0 = std::inner_product(momMother.begin(), momMother.end(), momMother.begin(), 0.f); - float p2A = std::inner_product(momKink.begin(), momKink.end(), momKink.begin(), 0.f); - return std::sqrt(p2A - dp * dp / p2V0); - } - - float getCosPA(const std::array& momMother, const std::array& decayVertex, const std::array& primaryVertex) - { - std::array decayVec = {decayVertex[0] - primaryVertex[0], decayVertex[1] - primaryVertex[1], decayVertex[2] - primaryVertex[2]}; - float dotProduct = std::inner_product(momMother.begin(), momMother.end(), decayVec.begin(), 0.f); - float momMotherMag = std::sqrt(std::inner_product(momMother.begin(), momMother.end(), momMother.begin(), 0.f)); - float decayVecMag = std::sqrt(std::inner_product(decayVec.begin(), decayVec.end(), decayVec.begin(), 0.f)); - return dotProduct / (momMotherMag * decayVecMag); - } - - TLorentzVector trackSum, PartOneCMS, PartTwoCMS, trackRelK; - float getKStar(const sigmaProtonCand& candidate) - { - TLorentzVector part1; // Sigma - TLorentzVector part2; // Proton - part1.SetXYZM(candidate.sigmaPx, candidate.sigmaPy, candidate.sigmaPz, o2::constants::physics::MassSigmaMinus); - part2.SetXYZM(candidate.pxPr, candidate.pyPr, candidate.pzPr, o2::constants::physics::MassProton); - trackSum = part1 + part2; - const float beta = trackSum.Beta(); - const float betax = beta * std::cos(trackSum.Phi()) * std::sin(trackSum.Theta()); - const float betay = beta * std::sin(trackSum.Phi()) * std::sin(trackSum.Theta()); - const float betaz = beta * std::cos(trackSum.Theta()); - PartOneCMS.SetXYZM(part1.Px(), part1.Py(), part1.Pz(), part1.M()); - PartTwoCMS.SetXYZM(part2.Px(), part2.Py(), part2.Pz(), part2.M()); - const ROOT::Math::Boost boostPRF = ROOT::Math::Boost(-betax, -betay, -betaz); - PartOneCMS = boostPRF(PartOneCMS); - PartTwoCMS = boostPRF(PartTwoCMS); - trackRelK = PartOneCMS - PartTwoCMS; - return 0.5 * trackRelK.P(); - } - - float getKStar(float sigmaPx, float sigmaPy, float sigmaPz, float pxPr, float pyPr, float pzPr) - { - TLorentzVector part1; // Sigma - TLorentzVector part2; // Proton - part1.SetXYZM(sigmaPx, sigmaPy, sigmaPz, o2::constants::physics::MassSigmaMinus); - part2.SetXYZM(pxPr, pyPr, pzPr, o2::constants::physics::MassProton); - trackSum = part1 + part2; - const float beta = trackSum.Beta(); - const float betax = beta * std::cos(trackSum.Phi()) * std::sin(trackSum.Theta()); - const float betay = beta * std::sin(trackSum.Phi()) * std::sin(trackSum.Theta()); - const float betaz = beta * std::cos(trackSum.Theta()); - PartOneCMS.SetXYZM(part1.Px(), part1.Py(), part1.Pz(), part1.M()); - PartTwoCMS.SetXYZM(part2.Px(), part2.Py(), part2.Pz(), part2.M()); - const ROOT::Math::Boost boostPRF = ROOT::Math::Boost(-betax, -betay, -betaz); - PartOneCMS = boostPRF(PartOneCMS); - PartTwoCMS = boostPRF(PartTwoCMS); - trackRelK = PartOneCMS - PartTwoCMS; - return 0.5 * trackRelK.P(); - } - - template - bool selectPrTrack(const Ttrack& candidate) - { - if (std::abs(candidate.tpcNSigmaPr()) > cutNSigmaTPC || candidate.tpcNClsFound() < cutNTPCClusPr || std::abs(candidate.eta()) > cutEtaDaught) { - return false; - } - - if (candidate.itsNCls() < cutNITSClusPr) { - return false; - } - - float ptMinTOF = 0.75f; // Minimum pT to use TOF for proton PID - if (candidate.pt() < ptMinTOF) { - return true; // No TOF cut for low pT - } - - if (!candidate.hasTOF()) { - return false; - } - if (std::abs(candidate.tofNSigmaPr()) > cutNSigmaTOF) { - return false; - } - return true; // Track is selected - } - - template - bool selectSigma(aod::KinkCands::iterator const& sigmaCand, Ttrack const&) - { - - auto kinkDauTrack = sigmaCand.trackDaug_as(); - float mass = doSigmaMinus ? sigmaCand.mSigmaMinus() : sigmaCand.mSigmaPlus(); - std::array momMoth = {sigmaCand.pxMoth(), sigmaCand.pyMoth(), sigmaCand.pzMoth()}; - std::array momDaug = {sigmaCand.pxDaug(), sigmaCand.pyDaug(), sigmaCand.pzDaug()}; - float alphaAP = getAlphaAP(momMoth, momDaug); - float qtAP = getQtAP(momMoth, momDaug); - - if (sigmaCand.ptMoth() < minPtSigma) { - return false; - } - - if (alphaAP > alphaAPCut || (qtAP < qtAPCutLow || qtAP > qtAPCutHigh)) { - return false; - } - float decRad = std::hypot(sigmaCand.xDecVtx(), sigmaCand.yDecVtx()); - if (decRad < cutSigmaRadius) { - return false; - } - - if (doSigmaMinus) { - if (mass < o2::constants::physics::MassSigmaMinus - cutSigmaMass || mass > o2::constants::physics::MassSigmaMinus + cutSigmaMass) { - return false; - } - if (std::abs(kinkDauTrack.tpcNSigmaPi()) > cutNSigmaTPC) { - return false; - } - } else { - if (mass < o2::constants::physics::MassSigmaPlus - cutSigmaMass || mass > o2::constants::physics::MassSigmaPlus + cutSigmaMass) { - return false; - } - if (std::abs(kinkDauTrack.tpcNSigmaPr()) > cutNSigmaTPC) { - return false; - } - } - if (std::abs(sigmaCand.dcaMothPv()) > cutDCAtoPVSigma) { - return false; - } - return true; - } - - template - void fillTreeAndHistograms(aod::KinkCands const& kinkCands, Ttrack const& tracksDauSigma, Ttrack const& tracks, Tcollision const& collision) - { - for (const auto& sigmaCand : kinkCands) { - if (selectSigma(sigmaCand, tracksDauSigma)) { - if (doSigmaMinus) { - rSigmaProton.fill(HIST("h2PtMassSigma"), sigmaCand.mothSign() * sigmaCand.ptMoth(), sigmaCand.mSigmaMinus()); - } else { - rSigmaProton.fill(HIST("h2PtMassSigma"), sigmaCand.mothSign() * sigmaCand.ptMoth(), sigmaCand.mSigmaPlus()); - } - - for (const auto& prTrack : tracks) { - if (!selectPrTrack(prTrack)) { - continue; - } - - sigmaProtonCand candidate; - candidate.sigmaCharge = sigmaCand.mothSign(); - candidate.sigmaPx = sigmaCand.pxMoth(); - candidate.sigmaPy = sigmaCand.pyMoth(); - candidate.sigmaPz = sigmaCand.pzMoth(); - candidate.sigmaDauPx = sigmaCand.pxDaug(); - candidate.sigmaDauPy = sigmaCand.pyDaug(); - candidate.sigmaDauPz = sigmaCand.pzDaug(); - candidate.sigmaDecRadius = std::hypot(sigmaCand.xDecVtx(), sigmaCand.yDecVtx()); - - std::array momMoth = {sigmaCand.pxMoth(), sigmaCand.pyMoth(), sigmaCand.pzMoth()}; - std::array decayVtx = {sigmaCand.xDecVtx(), sigmaCand.yDecVtx(), sigmaCand.zDecVtx()}; - std::array primaryVtx = {collision.posX(), collision.posY(), collision.posZ()}; - candidate.sigmaCosPA = getCosPA(momMoth, decayVtx, primaryVtx); - - candidate.chargePr = prTrack.sign(); - candidate.pxPr = prTrack.px(); - candidate.pyPr = prTrack.py(); - candidate.pzPr = prTrack.pz(); - candidate.nSigmaTPCPr = prTrack.tpcNSigmaPr(); - candidate.nSigmaTOFPr = prTrack.tofNSigmaPr(); - candidate.sigmaMass = doSigmaMinus ? sigmaCand.mSigmaMinus() : sigmaCand.mSigmaPlus(); - - candidate.sigmaID = sigmaCand.trackMothId(); - candidate.kinkDauID = sigmaCand.trackDaugId(); - candidate.prID = prTrack.globalIndex(); - - if (getKStar(candidate) > cutMaxKStar) { - continue; - } - - rSigmaProton.fill(HIST("h2PtPrNSigma"), candidate.ptPr(), candidate.nSigmaTPCPr); - if (prTrack.hasTOF()) { - rSigmaProton.fill(HIST("h2PtPrNSigmaTOF"), candidate.ptPr(), candidate.nSigmaTOFPr); - } - sigmaProtonCandidates.push_back(candidate); - } - } - } - } - - void processSameEvent(CollisionsFull const& collisions, aod::KinkCands const& kinkCands, TracksFull const& tracks) - { - for (auto const& collision : collisions) { - - sigmaProtonCandidates.clear(); - auto kinkCands_c = kinkCands.sliceBy(kinkCandsPerCollisionPreslice, collision.globalIndex()); - auto tracks_c = tracks.sliceBy(tracksPerCollisionPreslice, collision.globalIndex()); - if (std::abs(collision.posZ()) > cutzvertex || !collision.sel8()) { - continue; - } - rEventSelection.fill(HIST("hVertexZRec"), collision.posZ()); - fillTreeAndHistograms(kinkCands_c, tracks_c, tracks_c, collision); - if (fillOutputTree) { - // Fill output table - for (const auto& candidate : sigmaProtonCandidates) { - outputDataTable(candidate.sigmaCharge, - candidate.sigmaPx, - candidate.sigmaPy, - candidate.sigmaPz, - candidate.sigmaDauPx, - candidate.sigmaDauPy, - candidate.sigmaDauPz, - candidate.sigmaDecRadius, - candidate.sigmaCosPA, - candidate.chargePr, - candidate.pxPr, - candidate.pyPr, - candidate.pzPr, - candidate.nSigmaTPCPr, - candidate.nSigmaTOFPr); - } - } - } - } - PROCESS_SWITCH(sigmaProtonCorrTask, processSameEvent, "Process Same event", true); - - // Processing Event Mixing - SliceCache cache; - using BinningType = ColumnBinningPolicy; - BinningType colBinning{{CfgVtxBins, CfgMultBins}, true}; - - void processMixedEvent(const CollisionsFull& collisions, const aod::KinkCands& kinkCands, const TracksFull& tracks) - { - for (auto const& [collision1, collision2] : - selfCombinations(colBinning, nEvtMixingBkg, -1, collisions, collisions)) { - if (collision1.index() == collision2.index()) - continue; - - sigmaProtonCandidates.clear(); - if (std::abs(collision1.posZ()) > cutzvertex || !collision1.sel8()) { - continue; - } - if (std::abs(collision2.posZ()) > cutzvertex || !collision2.sel8()) { - continue; - } - auto kinkCands_c1 = kinkCands.sliceBy(kinkCandsPerCollisionPreslice, collision1.globalIndex()); - auto tracks_c1 = tracks.sliceBy(tracksPerCollisionPreslice, collision1.globalIndex()); - auto tracks_c2 = tracks.sliceBy(tracksPerCollisionPreslice, collision2.globalIndex()); - fillTreeAndHistograms(kinkCands_c1, tracks_c1, tracks_c2, collision1); - - if (fillOutputTree) { - // Fill output table - for (const auto& candidate : sigmaProtonCandidates) { - outputDataTable(candidate.sigmaCharge, - candidate.sigmaPx, - candidate.sigmaPy, - candidate.sigmaPz, - candidate.sigmaDauPx, - candidate.sigmaDauPy, - candidate.sigmaDauPz, - candidate.sigmaDecRadius, - candidate.sigmaCosPA, - candidate.chargePr, - candidate.pxPr, - candidate.pyPr, - candidate.pzPr, - candidate.nSigmaTPCPr, - candidate.nSigmaTOFPr); - } - } - } - LOG(debug) << "Processing mixed event"; - } - PROCESS_SWITCH(sigmaProtonCorrTask, processMixedEvent, "Process Mixed event", false); - - void processSameEventMC(CollisionsFullMC const& collisions, aod::KinkCands const& kinkCands, TracksFullMC const& tracks, aod::McParticles const&) - { - for (auto const& collision : collisions) { - - sigmaProtonCandidates.clear(); - auto kinkCands_c = kinkCands.sliceBy(kinkCandsPerCollisionPreslice, collision.globalIndex()); - auto tracks_c = tracks.sliceBy(tracksMCPerCollisionPreslice, collision.globalIndex()); - - if (std::abs(collision.posZ()) > cutzvertex || !collision.sel8()) { - continue; - } - rEventSelection.fill(HIST("hVertexZRec"), collision.posZ()); - fillTreeAndHistograms(kinkCands_c, tracks_c, tracks_c, collision); - if (fillOutputTree) { - // Fill output table - for (const auto& candidate : sigmaProtonCandidates) { - auto mcLabelSigma = tracks.rawIteratorAt(candidate.sigmaID); - auto mcLabelSigmaDau = tracks.rawIteratorAt(candidate.kinkDauID); - auto mcLabelPr = tracks.rawIteratorAt(candidate.prID); - - if (!mcLabelSigma.has_mcParticle() || !mcLabelSigmaDau.has_mcParticle() || !mcLabelPr.has_mcParticle()) { - continue; // Skip candidates where MC truth is not available - } - - auto mcPartSigma = mcLabelSigma.mcParticle_as(); - auto mcPartSigmaDau = mcLabelSigmaDau.mcParticle_as(); - auto mcPartPr = mcLabelPr.mcParticle_as(); - auto pdgSigma = mcPartSigma.pdgCode(); - auto pdgSigmaDau = mcLabelSigmaDau.has_mcParticle() ? mcPartSigmaDau.pdgCode() : -999; - auto pdgPr = mcLabelPr.has_mcParticle() ? mcPartPr.pdgCode() : -999; - - float sigmaPtGen = std::hypot(mcPartSigma.px(), mcPartSigma.py()); - float prPtGen = std::hypot(mcPartPr.px(), mcPartPr.py()); - float kStarGen = getKStar(mcPartSigma.px(), mcPartSigma.py(), mcPartSigma.pz(), mcPartPr.px(), mcPartPr.py(), mcPartPr.pz()); - - outputDataTableMC(candidate.sigmaCharge, - candidate.sigmaPx, - candidate.sigmaPy, - candidate.sigmaPz, - candidate.sigmaDauPx, - candidate.sigmaDauPy, - candidate.sigmaDauPz, - candidate.sigmaDecRadius, - candidate.sigmaCosPA, - candidate.chargePr, - candidate.pxPr, - candidate.pyPr, - candidate.pzPr, - candidate.nSigmaTPCPr, - candidate.nSigmaTOFPr, - pdgSigma, - pdgSigmaDau, - pdgPr, - sigmaPtGen, - prPtGen, - kStarGen); - } - } - } - } - PROCESS_SWITCH(sigmaProtonCorrTask, processSameEventMC, "Process Same event MC", false); - - void processMixedEventMC(const CollisionsFullMC& collisions, const aod::KinkCands& kinkCands, const TracksFullMC& tracks, const aod::McParticles&) - { - for (auto const& [collision1, collision2] : - selfCombinations(colBinning, nEvtMixingBkg, -1, collisions, collisions)) { - if (collision1.index() == collision2.index()) - continue; - - sigmaProtonCandidates.clear(); - if (std::abs(collision1.posZ()) > cutzvertex || !collision1.sel8()) { - continue; - } - if (std::abs(collision2.posZ()) > cutzvertex || !collision2.sel8()) { - continue; - } - auto kinkCands_c1 = kinkCands.sliceBy(kinkCandsPerCollisionPreslice, collision1.globalIndex()); - auto tracks_c1 = tracks.sliceBy(tracksPerCollisionPreslice, collision1.globalIndex()); - auto tracks_c2 = tracks.sliceBy(tracksPerCollisionPreslice, collision2.globalIndex()); - fillTreeAndHistograms(kinkCands_c1, tracks_c1, tracks_c2, collision1); - - if (fillOutputTree) { - // Fill output table - for (const auto& candidate : sigmaProtonCandidates) { - auto mcLabelSigma = tracks.rawIteratorAt(candidate.sigmaID); - auto mcLabelSigmaDau = tracks.rawIteratorAt(candidate.kinkDauID); - auto mcLabelPr = tracks.rawIteratorAt(candidate.prID); - - if (!mcLabelSigma.has_mcParticle() || !mcLabelSigmaDau.has_mcParticle() || !mcLabelPr.has_mcParticle()) { - continue; // Skip candidates where MC truth is not available - } - - auto mcPartSigma = mcLabelSigma.mcParticle_as(); - auto mcPartSigmaDau = mcLabelSigmaDau.mcParticle_as(); - auto mcPartPr = mcLabelPr.mcParticle_as(); - auto pdgSigma = mcPartSigma.pdgCode(); - auto pdgSigmaDau = mcLabelSigmaDau.has_mcParticle() ? mcPartSigmaDau.pdgCode() : -999; - auto pdgPr = mcLabelPr.has_mcParticle() ? mcPartPr.pdgCode() : -999; - float sigmaPtGen = std::hypot(mcPartSigma.px(), mcPartSigma.py()); - float prPtGen = std::hypot(mcPartPr.px(), mcPartPr.py()); - float kStarGen = getKStar(mcPartSigma.px(), mcPartSigma.py(), mcPartSigma.pz(), mcPartPr.px(), mcPartPr.py(), mcPartPr.pz()); - outputDataTableMC(candidate.sigmaCharge, - candidate.sigmaPx, - candidate.sigmaPy, - candidate.sigmaPz, - candidate.sigmaDauPx, - candidate.sigmaDauPy, - candidate.sigmaDauPz, - candidate.sigmaDecRadius, - candidate.sigmaCosPA, - candidate.chargePr, - candidate.pxPr, - candidate.pyPr, - candidate.pzPr, - candidate.nSigmaTPCPr, - candidate.nSigmaTOFPr, - pdgSigma, - pdgSigmaDau, - pdgPr, - sigmaPtGen, - prPtGen, - kStarGen); - } - } - } - LOG(debug) << "Processing mixed event MC"; - } - PROCESS_SWITCH(sigmaProtonCorrTask, processMixedEventMC, "Process Mixed event MC", false); -}; -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) -{ - return WorkflowSpec{ - adaptAnalysisTask(cfgc)}; -} From f03dc93b7485ab1a58aa60435f92777abdf35764 Mon Sep 17 00:00:00 2001 From: Barbara Gawlik <132619264+allesgrau@users.noreply.github.com> Date: Mon, 16 Mar 2026 13:13:31 +0100 Subject: [PATCH 288/347] [PWGCF] Extend femtoPairV0V0 task for Lambda-AntiLambda analyses (#15397) Co-authored-by: ALICE Action Bot --- PWGCF/FemtoWorld/Tasks/CMakeLists.txt | 5 + .../Tasks/femtoPairLambdaAntilambda.cxx | 279 ++++++++++++++++++ 2 files changed, 284 insertions(+) create mode 100644 PWGCF/FemtoWorld/Tasks/femtoPairLambdaAntilambda.cxx diff --git a/PWGCF/FemtoWorld/Tasks/CMakeLists.txt b/PWGCF/FemtoWorld/Tasks/CMakeLists.txt index 4b4e045220a..90503ad0acd 100644 --- a/PWGCF/FemtoWorld/Tasks/CMakeLists.txt +++ b/PWGCF/FemtoWorld/Tasks/CMakeLists.txt @@ -53,3 +53,8 @@ o2physics_add_dpl_workflow(femto-world-efficiency-task-de SOURCES femtoWorldEfficiencyTaskDe.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(femto-pair-lambda-antilambda + SOURCES femtoPairLambdaAntilambda.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) diff --git a/PWGCF/FemtoWorld/Tasks/femtoPairLambdaAntilambda.cxx b/PWGCF/FemtoWorld/Tasks/femtoPairLambdaAntilambda.cxx new file mode 100644 index 00000000000..11c590b7002 --- /dev/null +++ b/PWGCF/FemtoWorld/Tasks/femtoPairLambdaAntilambda.cxx @@ -0,0 +1,279 @@ +// Copyright 2019-2025 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file FemtoPairLambdaAntilambda.cxx +/// \brief Tasks that computes correlation between two v0s +/// \author Anton Riedel, TU München, anton.riedel@cern.ch +/// \author Barbara Gawlik, WUT Warsaw, barbara.maria.gawlik@cern.ch + +#include "PWGCF/Femto/Core/closePairRejection.h" +#include "PWGCF/Femto/Core/collisionBuilder.h" +#include "PWGCF/Femto/Core/collisionHistManager.h" +#include "PWGCF/Femto/Core/modes.h" +#include "PWGCF/Femto/Core/pairBuilder.h" +#include "PWGCF/Femto/Core/pairHistManager.h" +#include "PWGCF/Femto/Core/particleCleaner.h" +#include "PWGCF/Femto/Core/partitions.h" +#include "PWGCF/Femto/Core/trackHistManager.h" +#include "PWGCF/Femto/Core/v0Builder.h" +#include "PWGCF/Femto/Core/v0HistManager.h" +#include "PWGCF/Femto/DataModel/FemtoTables.h" + +#include "Framework/ASoA.h" +#include "Framework/AnalysisHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/BinningPolicy.h" +#include "Framework/Configurable.h" +#include "Framework/Expressions.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/InitContext.h" +#include "Framework/OutputObjHeader.h" +#include "Framework/runDataProcessing.h" + +#include +#include + +using namespace o2::analysis::femto; + +struct FemtoPairLambdaAntilambda { + + // setup tables + using FemtoCollisions = o2::soa::Join; + using FilteredFemtoCollisions = o2::soa::Filtered; + using FilteredFemtoCollision = FilteredFemtoCollisions::iterator; + + using FemtoCollisionsWithLabel = o2::soa::Join; + using FilteredFemtoCollisionsWithLabel = o2::soa::Filtered; + using FilteredFemtoCollisionWithLabel = FilteredFemtoCollisionsWithLabel::iterator; + + using FemtoTracks = o2::soa::Join; + using FemtoLambdas = o2::soa::Join; + using FemtoK0shorts = o2::soa::Join; + + using FemtoTracksWithLabel = o2::soa::Join; + using FemtoLambdasWithLabel = o2::soa::Join; + using FemtoK0shortsWithLabel = o2::soa::Join; + + o2::framework::SliceCache cache; + + // setup collisions + collisionbuilder::ConfCollisionSelection collisionSelection; + o2::framework::expressions::Filter collisionFilter = MAKE_COLLISION_FILTER(collisionSelection); + colhistmanager::ConfCollisionBinning confCollisionBinning; + + // setup for daughters + trackhistmanager::ConfV0PosDauBinning confPosDauBinning; + trackhistmanager::ConfV0NegDauBinning confNegDauBinning; + + // setup lambdas + v0builder::ConfLambdaSelection1 confLambdaSelection; + v0builder::ConfLambdaSelection2 confLambdaSelection2; + particlecleaner::ConfLambdaCleaner1 confLambdaCleaner; + v0histmanager::ConfLambdaBinning1 confLambdaBinning; + + o2::framework::Partition lambdaPartition = MAKE_LAMBDA_PARTITION(confLambdaSelection); + o2::framework::Partition lambdaPartition2 = MAKE_LAMBDA_PARTITION(confLambdaSelection2); + o2::framework::Preslice perColLambdas = o2::aod::femtobase::stored::fColId; + + o2::framework::Partition lambdaWithLabelPartition = MAKE_LAMBDA_PARTITION(confLambdaSelection); + o2::framework::Partition lambdaWithLabelPartition2 = MAKE_LAMBDA_PARTITION(confLambdaSelection2); + o2::framework::Preslice perCollambdasWithLabel = o2::aod::femtobase::stored::fColId; + + // setup k0shorts + v0builder::ConfK0shortSelection1 confK0shortSelection; + particlecleaner::ConfK0shortCleaner1 confK0shortCleaner; + v0histmanager::ConfK0shortBinning1 confK0shortBinning; + + o2::framework::Partition k0shortPartition = MAKE_K0SHORT_PARTITION(confK0shortSelection); + o2::framework::Preslice perColk0shorts = o2::aod::femtobase::stored::fColId; + + o2::framework::Partition k0shortWithLabelPartition = MAKE_K0SHORT_PARTITION(confK0shortSelection); + o2::framework::Preslice perColk0shortsWithLabel = o2::aod::femtobase::stored::fColId; + + // setup pairs + pairhistmanager::ConfPairBinning confPairBinning; + pairhistmanager::ConfPairCuts confPairCuts; + + pairbuilder::PairV0V0Builder< + v0histmanager::PrefixLambda1, + trackhistmanager::PrefixV01PosDaughter, + trackhistmanager::PrefixV01NegDaughter, + v0histmanager::PrefixLambda2, + trackhistmanager::PrefixV02PosDaughter, + trackhistmanager::PrefixV02NegDaughter, + pairhistmanager::PrefixV0V0Se, + pairhistmanager::PrefixV0V0Me, + closepairrejection::PrefixV0V0PosSe, + closepairrejection::PrefixV0V0NegSe, + closepairrejection::PrefixV0V0PosMe, + closepairrejection::PrefixV0V0NegMe, + modes::V0::kLambda, + modes::V0::kLambda> + pairLambdaLambdaBuilder; + + pairbuilder::PairV0V0Builder< + v0histmanager::PrefixK0short1, + trackhistmanager::PrefixV01PosDaughter, + trackhistmanager::PrefixV01NegDaughter, + v0histmanager::PrefixK0short2, + trackhistmanager::PrefixV02PosDaughter, + trackhistmanager::PrefixV02NegDaughter, + pairhistmanager::PrefixV0V0Se, + pairhistmanager::PrefixV0V0Me, + closepairrejection::PrefixV0V0PosSe, + closepairrejection::PrefixV0V0NegSe, + closepairrejection::PrefixV0V0PosMe, + closepairrejection::PrefixV0V0NegMe, + modes::V0::kK0short, + modes::V0::kK0short> + pairK0shortK0shortBuilder; + + // setup mixing + std::vector defaultVtxBins{10, -10, 10}; + std::vector defaultMultBins{50, 0, 200}; + std::vector defaultCentBins{10, 0, 100}; + o2::framework::ColumnBinningPolicy mixBinsVtxMult{{defaultVtxBins, defaultMultBins}, true}; + o2::framework::ColumnBinningPolicy mixBinsVtxCent{{defaultVtxBins, defaultCentBins}, true}; + o2::framework::ColumnBinningPolicy mixBinsVtxMultCent{{defaultVtxBins, defaultMultBins, defaultCentBins}, true}; + pairhistmanager::ConfMixing confMixing; + + o2::framework::HistogramRegistry hRegistry{"FemtoV0V0", {}, o2::framework::OutputObjHandlingPolicy::AnalysisObject}; + + // setup cpr + closepairrejection::ConfCprV0DaugherV0DaughterPos confCprPos; + closepairrejection::ConfCprV0DaugherV0DaughterNeg confCprNeg; + + void init(o2::framework::InitContext&) + { + + // TODO: implement lambda-k0short + bool processData = doprocessLambdaLambdaSameEvent || doprocessLambdaLambdaSameEvent || doprocessK0shortK0shortSameEvent || doprocessK0shortK0shortSameEvent; + bool processMc = doprocessLambdaLambdaSameEventMc || doprocessLambdaLambdaSameEventMc || doprocessK0shortK0shortSameEventMc || doprocessK0shortK0shortSameEventMc; + + if (processData && processMc) { + LOG(fatal) << "Both data and mc processing is enabled. Breaking..."; + } + + bool processLambdaLambda = doprocessLambdaLambdaSameEvent || doprocessLambdaLambdaMixedEvent || doprocessLambdaLambdaSameEventMc || doprocessLambdaLambdaMixedEventMc; + bool processK0shortK0short = doprocessK0shortK0shortSameEvent || doprocessK0shortK0shortMixedEvent || doprocessK0shortK0shortSameEventMc || doprocessK0shortK0shortMixedEventMc; + + if (processLambdaLambda && processK0shortK0short) { + LOG(fatal) << "Both lambda-lambda and k0short-k0short processing is enabled. Breaking..."; + } + + // setup columnpolicy for binning + // default values are used during instantiation, so we need to explicity update them here + mixBinsVtxMult = {{confMixing.vtxBins, confMixing.multBins.value}, true}; + mixBinsVtxCent = {{confMixing.vtxBins.value, confMixing.centBins.value}, true}; + mixBinsVtxMultCent = {{confMixing.vtxBins.value, confMixing.multBins.value, confMixing.centBins.value}, true}; + + // setup histograms + std::map> colHistSpec; + std::map> trackHistSpec; + std::map> posDauSpec; + std::map> negDauSpec; + std::map> lambdaHistSpec; + std::map> k0shortHistSpec; + std::map> pairV0V0HistSpec; + std::map> cprHistSpecPos = closepairrejection::makeCprHistSpecMap(confCprPos); + std::map> cprHistSpecNeg = closepairrejection::makeCprHistSpecMap(confCprNeg); + + if (processData) { + colHistSpec = colhistmanager::makeColHistSpecMap(confCollisionBinning); + posDauSpec = trackhistmanager::makeTrackHistSpecMap(confPosDauBinning); + negDauSpec = trackhistmanager::makeTrackHistSpecMap(confNegDauBinning); + if (processLambdaLambda) { + lambdaHistSpec = v0histmanager::makeV0HistSpecMap(confLambdaBinning); + pairV0V0HistSpec = pairhistmanager::makePairHistSpecMap(confPairBinning); + pairLambdaLambdaBuilder.init(&hRegistry, confCollisionBinning, confLambdaSelection, confLambdaSelection2, confLambdaCleaner, confLambdaCleaner, confCprPos, confCprNeg, confMixing, confPairBinning, confPairCuts, colHistSpec, lambdaHistSpec, lambdaHistSpec, posDauSpec, negDauSpec, pairV0V0HistSpec, cprHistSpecPos, cprHistSpecNeg); + } + + // setup for k0short + if (doprocessK0shortK0shortSameEvent || doprocessK0shortK0shortMixedEvent) { + k0shortHistSpec = v0histmanager::makeV0HistSpecMap(confK0shortBinning); + pairV0V0HistSpec = pairhistmanager::makePairHistSpecMap(confPairBinning); + pairK0shortK0shortBuilder.init(&hRegistry, confCollisionBinning, confK0shortSelection, confK0shortSelection, confK0shortCleaner, confK0shortCleaner, confCprPos, confCprNeg, confMixing, confPairBinning, confPairCuts, colHistSpec, k0shortHistSpec, k0shortHistSpec, posDauSpec, negDauSpec, pairV0V0HistSpec, cprHistSpecPos, cprHistSpecNeg); + } + } else { + colHistSpec = colhistmanager::makeColMcHistSpecMap(confCollisionBinning); + posDauSpec = trackhistmanager::makeTrackMcHistSpecMap(confPosDauBinning); + negDauSpec = trackhistmanager::makeTrackMcHistSpecMap(confNegDauBinning); + if (processLambdaLambda) { + lambdaHistSpec = v0histmanager::makeV0McHistSpecMap(confLambdaBinning); + pairV0V0HistSpec = pairhistmanager::makePairMcHistSpecMap(confPairBinning); + pairLambdaLambdaBuilder.init(&hRegistry, confCollisionBinning, confLambdaSelection, confLambdaSelection2, confLambdaCleaner, confLambdaCleaner, confCprPos, confCprNeg, confMixing, confPairBinning, confPairCuts, colHistSpec, lambdaHistSpec, lambdaHistSpec, posDauSpec, negDauSpec, pairV0V0HistSpec, cprHistSpecPos, cprHistSpecNeg); + } + + // setup for k0short + if (doprocessK0shortK0shortSameEvent || doprocessK0shortK0shortMixedEvent) { + k0shortHistSpec = v0histmanager::makeV0McHistSpecMap(confK0shortBinning); + pairV0V0HistSpec = pairhistmanager::makePairMcHistSpecMap(confPairBinning); + pairK0shortK0shortBuilder.init(&hRegistry, confCollisionBinning, confK0shortSelection, confK0shortSelection, confK0shortCleaner, confK0shortCleaner, confCprPos, confCprNeg, confMixing, confPairBinning, confPairCuts, colHistSpec, k0shortHistSpec, k0shortHistSpec, posDauSpec, negDauSpec, pairV0V0HistSpec, cprHistSpecPos, cprHistSpecNeg); + } + } + }; + + void processLambdaLambdaSameEvent(FilteredFemtoCollision const& col, FemtoTracks const& tracks, FemtoLambdas const& lambdas) + { + pairLambdaLambdaBuilder.processSameEvent(col, tracks, lambdas, lambdaPartition, lambdaPartition2, cache); + } + PROCESS_SWITCH(FemtoPairLambdaAntilambda, processLambdaLambdaSameEvent, "Enable processing same event processing for lambda-lambda", true); + + void processLambdaLambdaSameEventMc(FilteredFemtoCollisionWithLabel const& col, o2::aod::FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FemtoLambdasWithLabel const& lambdas, o2::aod::FMcParticles const& mcParticles, o2::aod::FMcMothers const& mcMothers, o2::aod::FMcPartMoths const& mcPartonicMothers) + { + pairLambdaLambdaBuilder.processSameEvent(col, mcCols, tracks, lambdas, lambdaWithLabelPartition, lambdaWithLabelPartition2, mcParticles, mcMothers, mcPartonicMothers, cache); + } + PROCESS_SWITCH(FemtoPairLambdaAntilambda, processLambdaLambdaSameEventMc, "Enable processing same event processing for lambda-lambda with mc information", false); + + void processLambdaLambdaMixedEvent(FilteredFemtoCollisions const& cols, FemtoTracks const& tracks, FemtoLambdas const& lambdas) + { + pairLambdaLambdaBuilder.processMixedEvent(cols, tracks, lambdas, lambdaPartition, lambdaPartition2, cache, mixBinsVtxMult, mixBinsVtxCent, mixBinsVtxMultCent); + } + PROCESS_SWITCH(FemtoPairLambdaAntilambda, processLambdaLambdaMixedEvent, "Enable processing mixed event processing for lambda-lambda", true); + + void processLambdaLambdaMixedEventMc(FilteredFemtoCollisionsWithLabel const& cols, o2::aod::FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FemtoLambdasWithLabel const& /*lambdas*/, o2::aod::FMcParticles const& mcParticles, o2::aod::FMcMothers const& mcMothers, o2::aod::FMcPartMoths const& mcPartonicMothers) + { + pairLambdaLambdaBuilder.processMixedEvent(cols, mcCols, tracks, lambdaWithLabelPartition, lambdaWithLabelPartition2, mcParticles, mcMothers, mcPartonicMothers, cache, mixBinsVtxMult, mixBinsVtxCent, mixBinsVtxMultCent); + } + PROCESS_SWITCH(FemtoPairLambdaAntilambda, processLambdaLambdaMixedEventMc, "Enable processing mixed event processing for lambda-lambda with mc information", false); + + void processK0shortK0shortSameEvent(FilteredFemtoCollision const& col, FemtoTracks const& tracks, FemtoK0shorts const& k0shorts) + { + pairK0shortK0shortBuilder.processSameEvent(col, tracks, k0shorts, k0shortPartition, k0shortPartition, cache); + } + PROCESS_SWITCH(FemtoPairLambdaAntilambda, processK0shortK0shortSameEvent, "Enable processing same event processing for k0short-k0short", false); + + void processK0shortK0shortSameEventMc(FilteredFemtoCollisionWithLabel const& col, o2::aod::FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FemtoK0shortsWithLabel const& k0shorts, o2::aod::FMcParticles const& mcParticles, o2::aod::FMcMothers const& mcMothers, o2::aod::FMcPartMoths const& mcPartonicMothers) + { + pairK0shortK0shortBuilder.processSameEvent(col, mcCols, tracks, k0shorts, k0shortWithLabelPartition, k0shortWithLabelPartition, mcParticles, mcMothers, mcPartonicMothers, cache); + } + PROCESS_SWITCH(FemtoPairLambdaAntilambda, processK0shortK0shortSameEventMc, "Enable processing same event processing for k0short-k0short with mc information", false); + + void processK0shortK0shortMixedEvent(FilteredFemtoCollisions const& cols, FemtoTracks const& tracks, FemtoK0shorts const& k0shorts) + { + pairK0shortK0shortBuilder.processMixedEvent(cols, tracks, k0shorts, k0shortPartition, k0shortPartition, cache, mixBinsVtxMult, mixBinsVtxCent, mixBinsVtxMultCent); + } + PROCESS_SWITCH(FemtoPairLambdaAntilambda, processK0shortK0shortMixedEvent, "Enable processing mixed event processing for k0short-k0short", false); + + void processK0shortK0shortMixedEventMc(FilteredFemtoCollisionsWithLabel const& cols, o2::aod::FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FemtoK0shortsWithLabel const& /*k0shorts*/, o2::aod::FMcParticles const& mcParticles, o2::aod::FMcMothers const& mcMothers, o2::aod::FMcPartMoths const& mcPartonicMothers) + { + pairK0shortK0shortBuilder.processMixedEvent(cols, mcCols, tracks, k0shortWithLabelPartition, k0shortWithLabelPartition, mcParticles, mcMothers, mcPartonicMothers, cache, mixBinsVtxMult, mixBinsVtxCent, mixBinsVtxMultCent); + } + PROCESS_SWITCH(FemtoPairLambdaAntilambda, processK0shortK0shortMixedEventMc, "Enable processing mixed event processing for k0short-k0short with mc information", false); +}; + +o2::framework::WorkflowSpec defineDataProcessing(o2::framework::ConfigContext const& cfgc) +{ + o2::framework::WorkflowSpec workflow{ + adaptAnalysisTask(cfgc), + }; + return workflow; +} From e66614013a40e06defd1e5877ce125ab34125352 Mon Sep 17 00:00:00 2001 From: sashingo Date: Mon, 16 Mar 2026 21:17:41 +0900 Subject: [PATCH 289/347] [PWGHF] added UE study for Z->ee and multiplicity analysis in pp (#15358) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Vít Kučera --- PWGHF/HFL/Tasks/taskElectronWeakBoson.cxx | 118 ++++++++++++++++++++-- 1 file changed, 110 insertions(+), 8 deletions(-) diff --git a/PWGHF/HFL/Tasks/taskElectronWeakBoson.cxx b/PWGHF/HFL/Tasks/taskElectronWeakBoson.cxx index 2bac954d50d..a8f03743e4c 100644 --- a/PWGHF/HFL/Tasks/taskElectronWeakBoson.cxx +++ b/PWGHF/HFL/Tasks/taskElectronWeakBoson.cxx @@ -25,6 +25,7 @@ #include "Common/Core/ZorroSummary.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" #include "Tools/KFparticle/KFUtilities.h" @@ -46,6 +47,7 @@ #include #include +#include #include #include @@ -130,6 +132,8 @@ struct HfTaskElectronWeakBoson { // Centrality estimator configuration Configurable centralityEstimator{"centralityEstimator", CentralityEstimator::FT0M, "Centrality estimator. See CentralityEstimator for valid values."}; Configurable enableCentralityAnalysis{"enableCentralityAnalysis", true, "Enable centrality-dependent analysis"}; + Configurable enableMultiplicityPVAnalysis{"enableMultiplicityPVAnalysis", true, "Enable centrality-dependent analysis"}; + Configurable enableMultiplicityFT0MAnalysis{"enableMultiplicityFT0MAnalysis", true, "Enable centrality-dependent analysis"}; Configurable centralityMin{"centralityMin", -1, "minimum cut on centrality selection"}; Configurable centralityMax{"centralityMax", 101, "maximum cut on centrality selection"}; Configurable> centralityBins{"centralityBins", {0, 20, 60, 100}, "centrality bins"}; @@ -139,6 +143,11 @@ struct HfTaskElectronWeakBoson { Configurable massZMinQA{"massZMinQA", 0.1, "minimum mass cut for Zee Reco QA"}; // CCDB service object Service ccdb{}; + // UE + Configurable nRandomCones{"nRandomCones", 100, "number of random cones"}; + Configurable rcHardE{"rcHardE", 5.0, "hard cluster veto energy"}; + Configurable rcVetoR{"rcVetoR", 0.4, "veto radius"}; + Configurable useUEsub{"useUEsub", true, "apply UE subtraction in isolation"}; struct HfElectronCandidate { float pt, eta, phi, dcaxyTrk, dcazTrk, eop, energyIso, momIso; @@ -157,7 +166,7 @@ struct HfTaskElectronWeakBoson { : pt(ptr), eta(e), phi(ph), mass(m), ptchild0(ptzee0), ptchild1(ptzee1), charge(ch) {} }; std::vector reconstructedZ; - using CollisionsWithCent = soa::Join; + using CollisionsWithCent = soa::Join; using SelectedClusters = o2::aod::EMCALClusters; // PbPb // using TrackEle = o2::soa::Join; @@ -200,6 +209,8 @@ struct HfTaskElectronWeakBoson { ConfigurableAxis confaxisInvMassZgamma{"confaxisInvMassZgamma", {150, 0, 150}, "M_{ee} (GeV/c^{2})"}; ConfigurableAxis confaxisInvMassZ{"confaxisInvMassZ", {130, 20, 150}, "M_{ee} (GeV/c^{2})"}; ConfigurableAxis confaxisZfrag{"confaxisZfrag", {200, 0, 2.0}, "p_{T,h}/p_{T,Z}"}; + ConfigurableAxis confaxisMultPV{"confaxisMultPV", {200, 0, 200.0}, "multiplicity"}; + ConfigurableAxis confaxisMultFT0{"confaxisMultFT0", {1000, 0, 1000.0}, "multiplicity"}; // Histogram registry: an object to hold your registrygrams HistogramRegistry registry{"registry"}; @@ -208,6 +219,9 @@ struct HfTaskElectronWeakBoson { Zorro zorro; OutputObj zorroSummary{"zorroSummary"}; + // defined rnd + TRandom3* rnd = nullptr; + void init(InitContext const&) { // Configure CCDB @@ -229,6 +243,9 @@ struct HfTaskElectronWeakBoson { // add configurable for CCDB path zorro.setBaseCCDBPath(cfgCCDBPath.value); + // init random + rnd = new TRandom3(0); + // define axes you want to use const AxisSpec axisZvtx{40, -20, 20, "Zvtx"}; const AxisSpec axisCounter{1, 0, 1, "events"}; @@ -281,12 +298,18 @@ struct HfTaskElectronWeakBoson { const AxisSpec axisInvMassZgamma{confaxisInvMassZgamma, "M_{ee} (GeV/c^{2})"}; const AxisSpec axisInvMassZ{confaxisInvMassZ, "M_{ee} (GeV/c^{2})"}; const AxisSpec axisZfrag{confaxisZfrag, "p_{T,h}/p_{T,Z}"}; + const AxisSpec axisMultPV{confaxisMultPV, "multiplicity"}; + const AxisSpec axisMultFT0{confaxisMultFT0, "multiplicity"}; // create registrygrams registry.add("hZvtx", "Z vertex", kTH1D, {axisZvtx}); registry.add("hEventCounterInit", "hEventCounterInit", kTH1D, {axisCounter}); registry.add("hEventCounter", "hEventCounter", kTH1D, {axisCounter}); registry.add("hCentrality", "Centrality distribution", kTH1D, {axisCentrality}); + registry.add("hCentMultCorr", "Centrality distribution", kTH2D, {{axisCentrality}, {axisMultFT0}}); + registry.add("hMultPV", "multiplicity distribution for PV", kTH1D, {axisMultPV}); + registry.add("hMultFT0", "multiplicity distribution for FT0", kTH1D, {axisMultFT0}); + registry.add("hMultFT0PV", "multiplicity distribution", kTH2D, {{axisMultFT0}, {axisMultPV}}); registry.add("hITSchi2", "ITS #chi^{2}", kTH1F, {axisChi2}); registry.add("hTPCchi2", "TPC #chi^{2}", kTH1F, {axisChi2}); registry.add("hTPCnCls", "TPC NCls", kTH1F, {axisCluster}); @@ -320,12 +343,19 @@ struct HfTaskElectronWeakBoson { // hisotgram for EMCal trigger registry.add("hEMCalTrigger", "EMCal trigger", kTH1D, {axisTrigger}); + + // histogram for UE + registry.add("hRho", "rho UE density", kTH1F, {axisE}); + registry.add("hSumERC", "RC sumE", kTH1F, {axisE}); + registry.add("hEnergyUE", "UE vs. centrality", kTH2F, {{axisCentrality}, {axisE}}); } double getIsolatedCluster(const o2::aod::EMCALCluster& cluster, - const SelectedClusters& clusters) + const SelectedClusters& clusters, + float energyUE) { double energySum = 0.0; + double energySum_excl = 0.0; double isoEnergy = 10.0; double const etaAssCluster = cluster.eta(); double const phiAssCluster = cluster.phi(); @@ -346,11 +376,12 @@ struct HfTaskElectronWeakBoson { energySum += associateCluster.energy(); } } - + energySum_excl = energySum - cluster.energy(); if (energySum > 0) { - isoEnergy = energySum / cluster.energy() - 1.0; + isoEnergy = (energySum_excl - energyUE) / cluster.energy(); } + // LOG(info) <<"clustE = " << cluster.energy() << " ; energySum = " << energySum << " ; nclust in Cone = " << nclustSum - 1 << " ; UE = " << energyUE << " ; isoEnergy = " << isoEnergy; registry.fill(HIST("hIsolationEnergy"), cluster.energy(), isoEnergy); return (isoEnergy); @@ -387,6 +418,51 @@ struct HfTaskElectronWeakBoson { // LOG(info) << "isop = " << isoMomentum; return std::make_pair(trackCount - 1, isoMomentum); } + float estimateRhoRC(const SelectedClusters& clusters) + { + const float randomConeR = rIsolation; + const float randomConeArea = o2::constants::math::PI * randomConeR * randomConeR; + + std::vector sumErc; + sumErc.reserve(nRandomCones); + + for (int i = 0; i < nRandomCones; i++) { + + float etarc = rnd->Uniform(-etaEmcMax, etaEmcMax); // in EMCal acceptance + float phirc = rnd->Uniform(phiEmcMin, phiEmcMax); // in EMCal acceptance + + float energySumRC = 0; + + for (const auto& c : clusters) { + if (c.energy() > rcHardE) { + continue; + } + double dEtarc = etarc - c.eta(); + double dPhirc = phirc - c.phi(); + dPhirc = RecoDecay::constrainAngle(dPhirc, -o2::constants::math::PI); + double const deltaRrc = std::sqrt(dEtarc * dEtarc + dPhirc * dPhirc); + if (deltaRrc < randomConeR) { + energySumRC += c.energy(); + } + } + + registry.fill(HIST("hSumERC"), energySumRC); + sumErc.push_back(energySumRC); + } + + if (sumErc.empty()) { + return 0; + } + std::nth_element(sumErc.begin(), + sumErc.begin() + sumErc.size() / 2, + sumErc.end()); + + float median = sumErc[sumErc.size() / 2]; + // LOG(info) << "median = " << median; + registry.fill(HIST("hRho"), median / randomConeArea); + + return median / randomConeArea; + } void recoMassZee(const KFParticle& kfpIsoEle, int charge, @@ -527,13 +603,39 @@ struct HfTaskElectronWeakBoson { float centrality = 1.0; if (enableCentralityAnalysis) { centrality = o2::hf_centrality::getCentralityColl(collision, centralityEstimator); - // LOG(info) << centrality; + // LOG(info) << "centrality = " << o2::hf_centrality::getCentralityColl(collision, centralityEstimator) << " ; FTC = " << collision.multFT0C(); if (centrality < centralityMin || centrality > centralityMax) { return; } - registry.fill(HIST("hCentrality"), centrality); + registry.fill(HIST("hCentMultCorr"), centrality, collision.multFT0M()); + } + + if (enableMultiplicityFT0MAnalysis || enableMultiplicityPVAnalysis) { + if (enableMultiplicityFT0MAnalysis) + centrality = collision.multFT0M(); + if (enableMultiplicityPVAnalysis) + centrality = collision.multNTracksPV(); + // LOG(info) << "raw mult PV = " << collision.multNTracksPV(); + // LOG(info) << "raw mult FT0M = " << collision.multFT0M(); + registry.fill(HIST("hMultPV"), collision.multNTracksPV()); + registry.fill(HIST("hMultFT0"), collision.multFT0M()); + registry.fill(HIST("hMultFT0PV"), collision.multFT0M(), collision.multNTracksPV()); + } + + registry.fill(HIST("hCentrality"), centrality); + + // UE estimate + float rho = 0.f; + float energyUE = 0.f; + + if (useUEsub) { + rho = estimateRhoRC(emcClusters); + energyUE = rho * static_cast(o2::constants::math::PI * rIsolation * rIsolation); + registry.fill(HIST("hEnergyUE"), centrality, energyUE); + // LOG(info) << "UE = " << energyUE; } + // track loop for (const auto& track : tracks) { if (std::abs(track.eta()) > etaTrMax) { @@ -568,7 +670,7 @@ struct HfTaskElectronWeakBoson { registry.fill(HIST("hTPCNsigma"), track.p(), track.tpcNSigmaEl()); float eop = -0.01; - float isoEnergy = 1.0; + float isoEnergy = 99.0; // track isolation auto [trackCount, isoMomentum] = getIsolatedTrack(track.eta(), track.phi(), track.p(), tracks); // LOG(info) << "isoMomentum = " << isoMomentum; @@ -657,7 +759,7 @@ struct HfTaskElectronWeakBoson { eop = energyEmc / match.track_as().p(); // LOG(info) << "eop = " << eop; - isoEnergy = getIsolatedCluster(cluster, emcClusters); + isoEnergy = getIsolatedCluster(cluster, emcClusters, energyUE); if (match.track_as().pt() > ptTHnThresh && isTHnElectron) { registry.fill(HIST("hTHnElectrons"), match.track_as().pt(), match.track_as().tpcNSigmaEl(), m02Emc, eop, isoEnergy, isoMomentum, trackCount, track.eta(), track.tpcSignal()); From 172c165f58e627a164d5a9a95fa32dc97cca622d Mon Sep 17 00:00:00 2001 From: SuJeong Ji <120470463+SuJeong-Ji@users.noreply.github.com> Date: Mon, 16 Mar 2026 23:47:54 +0900 Subject: [PATCH 290/347] [PWGLF] Update code structure of k1analysis.cxx (#15410) Co-authored-by: ALICE Action Bot --- PWGLF/Tasks/Resonances/k1analysis.cxx | 1530 +++++++++++++++---------- 1 file changed, 950 insertions(+), 580 deletions(-) diff --git a/PWGLF/Tasks/Resonances/k1analysis.cxx b/PWGLF/Tasks/Resonances/k1analysis.cxx index a743c349c51..02ac98be89b 100644 --- a/PWGLF/Tasks/Resonances/k1analysis.cxx +++ b/PWGLF/Tasks/Resonances/k1analysis.cxx @@ -13,23 +13,67 @@ /// \brief Reconstruction of track-track decay resonance candidates /// /// -/// \author Bong-Hwi Lim - -#include "PWGLF/DataModel/LFResonanceTables.h" - +/// \author Su-Jeong Ji , Bong-Hwi Lim + +#include +#include +#include +#include +#include +#include +#include +#include +// #include // FIXME +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGLF/DataModel/mcCentrality.h" +#include "PWGLF/Utils/collisionCuts.h" +#include "PWGLF/Utils/inelGt.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/trackUtilities.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" - +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "CCDB/BasicCCDBManager.h" +#include "CCDB/CcdbApi.h" +#include "CommonConstants/MathConstants.h" #include "CommonConstants/PhysicsConstants.h" +#include "DCAFitter/DCAFitterN.h" +#include "DataFormatsParameters/GRPMagField.h" #include "DataFormatsParameters/GRPObject.h" #include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/StaticFor.h" +#include "Framework/StepTHn.h" #include "Framework/runDataProcessing.h" - -#include // FIXME -#include +#include "ReconstructionDataFormats/Track.h" + +#include "Math/GenVector/Boost.h" +#include "Math/RotationZ.h" +#include "Math/Vector3D.h" +#include "Math/Vector4D.h" +#include "TF1.h" +#include "TParticlePDG.h" +#include "TRandom3.h" +#include "TVector2.h" +#include #include // FIXME +#include +#include +#include +#include +#include +#include +#include #include using namespace o2; @@ -37,693 +81,1019 @@ using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::soa; using namespace o2::constants::physics; +using namespace o2::constants::math; +using namespace o2::aod::rctsel; -struct k1analysis { - enum binAnti : unsigned int { - kNormal = 0, - kAnti, - kNAEnd - }; - enum binType : unsigned int { +struct K1analysis { + enum BinType : unsigned int { kK1P = 0, - kK1N, - kK1P_Mix, - kK1N_Mix, - kK1P_GenINEL10, - kK1N_GenINEL10, - kK1P_GenINELgt10, - kK1N_GenINELgt10, - kK1P_GenTrig10, - kK1N_GenTrig10, - kK1P_GenEvtSel, - kK1N_GenEvtSel, - kK1P_Rec, - kK1N_Rec, + kK1A, + kK1P_Like, + kK1A_Like, + kK1P_Rot, + kK1A_Rot, kTYEnd }; + + enum EvtStep { + kAll = 0, + kZvtx, + kINELgt0, + kAssocReco, + kNSteps + }; + + enum class K1MassRegion : uint8_t { + Outside = 0, + Signal, + SBLeft, + SBRight + }; + + const int nSteps = static_cast(EvtStep::kNSteps); + SliceCache cache; - Preslice perRCol = aod::resodaughter::resoCollisionId; Preslice perCollision = aod::track::collisionId; + // Preslice perCollisionV0 = aod::v0data::collisionId; + Preslice perCollisionV0 = aod::v0data::collisionId; + Preslice perMCCollision = o2::aod::mcparticle::mcCollisionId; + + using EventCandidates = soa::Join; + using TrackCandidates = soa::Join; + using V0Candidates = aod::V0Datas; + + // for MC reco + using MCEventCandidates = soa::Join; + using MCTrackCandidates = soa::Join; //, aod::McParticles>; + using MCV0Candidates = soa::Join; + + // for MC truth + using MCTrueEventCandidates = aod::McCollisions; + using MCTrueTrackCandidates = aod::McParticles; + + using LorentzVectorSetXYZM = ROOT::Math::LorentzVector>; + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; - using ResoMCCols = soa::Join; - - ///// Configurables - Configurable cNbinsDiv{"cNbinsDiv", 1, "Integer to divide the number of bins"}; - /// Event Mixing - Configurable nEvtMixing{"nEvtMixing", 5, "Number of events to mix"}; - ConfigurableAxis CfgVtxBins{"CfgVtxBins", {VARIABLE_WIDTH, -10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}, "Mixing bins - z-vertex"}; - ConfigurableAxis CfgMultBins{"CfgMultBins", {VARIABLE_WIDTH, 0.0f, 20.0f, 40.0f, 60.0f, 80.0f, 100.0f, 200.0f, 99999.f}, "Mixing bins - multiplicity"}; - /// Pre-selection cuts - Configurable cMinPtcut{"cMinPtcut", 0.15, "Track minium pt cut"}; - - /// DCA Selections - // DCAr to PV - Configurable cMaxDCArToPVcut{"cMaxDCArToPVcut", 0.1, "Track DCAr cut to PV Maximum"}; - // DCAz to PV - Configurable cMaxDCAzToPVcut{"cMaxDCAzToPVcut", 0.1, "Track DCAz cut to PV Maximum"}; - Configurable cMinDCAzToPVcut{"cMinDCAzToPVcut", 0.0, "Track DCAz cut to PV Minimum"}; - - /// PID Selections - Configurable cMaxTPCnSigmaPion{"cMaxTPCnSigmaPion", 3.0, "TPC nSigma cut for Pion"}; // TPC - Configurable cMaxTOFnSigmaPion{"cMaxTOFnSigmaPion", 3.0, "TOF nSigma cut for Pion"}; // TOF - Configurable nsigmaCutCombinedPion{"nsigmaCutCombinedPion", -999, "Combined nSigma cut for Pion"}; // Combined - Configurable cTOFVeto{"cTOFVeto", true, "TOF Veto, if false, TOF is nessessary for PID selection"}; // TOF Veto - Configurable cUseOnlyTOFTrackPi{"cUseOnlyTOFTrackPi", false, "Use only TOF track for PID selection"}; // Use only TOF track for Pion PID selection - // Kaon - Configurable cMaxTPCnSigmaKaon{"cMaxTPCnSigmaKaon", 3.0, "TPC nSigma cut for Kaon"}; // TPC - Configurable cMaxTOFnSigmaKaon{"cMaxTOFnSigmaKaon", 3.0, "TOF nSigma cut for Kaon"}; // TOF - Configurable nsigmaCutCombinedKaon{"nsigmaCutCombinedKaon", -999, "Combined nSigma cut for Kaon"}; // Combined - Configurable cUseOnlyTOFTrackKa{"cUseOnlyTOFTrackKa", false, "Use only TOF track for PID selection"}; // Use only TOF track for Kaon PID selection + + Service ccdb; + Service pdg; + o2::ccdb::CcdbApi ccdbApi; + + struct : ConfigurableGroup { + Configurable cfgURL{"cfgURL", "http://alice-ccdb.cern.ch", "Address of the CCDB to browse"}; + } CCDBConfig; + // Configurable nolaterthan{"ccdb-no-later-than", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "Latest acceptable timestamp of creation for the object"}; + + // Configurables + struct : ConfigurableGroup { + ConfigurableAxis cfgBinsPt{"cfgBinsPt", {VARIABLE_WIDTH, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, 2.9, 3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 4.0, 4.1, 4.2, 4.3, 4.4, 4.5, 4.6, 4.7, 4.8, 4.9, 5.0, 5.1, 5.2, 5.3, 5.4, 5.5, 5.6, 5.7, 5.8, 5.9, 6.0, 6.1, 6.2, 6.3, 6.4, 6.5, 6.6, 6.7, 6.8, 6.9, 7.0, 7.1, 7.2, 7.3, 7.4, 7.5, 7.6, 7.7, 7.8, 7.9, 8.0, 8.1, 8.2, 8.3, 8.4, 8.5, 8.6, 8.7, 8.8, 8.9, 9.0, 9.1, 9.2, 9.3, 9.4, 9.5, 9.6, 9.7, 9.8, 9.9, 10.0}, "Binning of the pT axis"}; + ConfigurableAxis cfgBinsPtQA{"cfgBinsPtQA", {VARIABLE_WIDTH, 0.0, 0.3, 0.6, 1.2, 1.8, 2.4, 3.0, 3.6, 4.2, 4.8, 5.4, 6.0, 7.0, 10.0}, "Binning of the pT axis"}; + ConfigurableAxis cfgBinsCent{"cfgBinsCent", {VARIABLE_WIDTH, 0.0, 1.0, 5.0, 10.0, 15.0, 20.0, 30.0, 40.0, 50.0, 70.0, 100.0, 110.0}, "Binning of the centrality axis"}; + ConfigurableAxis cfgBinsVtxZ{"cfgBinsVtxZ", {VARIABLE_WIDTH, -10.0, -9.0, -8.0, -7.0, -6.0, -5.0, -4.0, -3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0}, "Binning of the z-vertex axis"}; + Configurable cNbinsDiv{"cNbinsDiv", 1, "Integer to divide the number of bins"}; + Configurable cNbinsDivQA{"cNbinsDivQA", 1, "Integer to divide the number of bins for QA"}; + } AxisConfig; + + /// Event cuts + o2::analysis::CollisonCuts colCuts; + struct : ConfigurableGroup { + Configurable cfgEvtZvtx{"cfgEvtZvtx", 10.f, "Evt sel: Max. z-Vertex (cm)"}; + Configurable cfgEvtOccupancyInTimeRangeMax{"cfgEvtOccupancyInTimeRangeMax", -1, "Evt sel: maximum track occupancy"}; + Configurable cfgEvtOccupancyInTimeRangeMin{"cfgEvtOccupancyInTimeRangeMin", -1, "Evt sel: minimum track occupancy"}; + Configurable cfgEvtTriggerCheck{"cfgEvtTriggerCheck", false, "Evt sel: check for trigger"}; + Configurable cfgEvtOfflineCheck{"cfgEvtOfflineCheck", false, "Evt sel: check for offline selection"}; + Configurable cfgEvtTriggerTVXSel{"cfgEvtTriggerTVXSel", true, "Evt sel: triggerTVX selection (MB)"}; + Configurable cfgEvtTFBorderCut{"cfgEvtTFBorderCut", true, "Evt sel: apply TF border cut"}; + Configurable cfgEvtUseITSTPCvertex{"cfgEvtUseITSTPCvertex", false, "Evt sel: use at lease on ITS-TPC track for vertexing"}; + Configurable cfgEvtZvertexTimedifference{"cfgEvtZvertexTimedifference", false, "Evt sel: apply Z-vertex time difference"}; + Configurable cfgEvtPileupRejection{"cfgEvtPileupRejection", false, "Evt sel: apply pileup rejection"}; + Configurable cfgEvtNoITSROBorderCut{"cfgEvtNoITSROBorderCut", true, "Evt sel: apply NoITSRO border cut"}; + Configurable cfgincludeCentralityMC{"cfgincludeCentralityMC", false, "Include centrality in MC"}; + Configurable cfgEvtCollInTimeRangeStandard{"cfgEvtCollInTimeRangeStandard", false, "Evt sel: apply NoCollInTimeRangeStandard"}; + Configurable cfgEventCentralityMin{"cfgEventCentralityMin", 0.0f, "Event sel: minimum centrality"}; + Configurable cfgEventCentralityMax{"cfgEventCentralityMax", 100.0f, "Event sel: maximum centrality"}; + Configurable cfgEvtUseRCTFlagChecker{"cfgEvtUseRCTFlagChecker", false, "Evt sel: use RCT flag checker"}; + Configurable cfgEvtRCTFlagCheckerLabel{"cfgEvtRCTFlagCheckerLabel", "CBT_hadronPID", "Evt sel: RCT flag checker label"}; + Configurable cfgEvtRCTFlagCheckerZDCCheck{"cfgEvtRCTFlagCheckerZDCCheck", false, "Evt sel: RCT flag checker ZDC check"}; + Configurable cfgEvtRCTFlagCheckerLimitAcceptAsBad{"cfgEvtRCTFlagCheckerLimitAcceptAsBad", false, "Evt sel: RCT flag checker treat Limited Acceptance As Bad"}; + } EventCuts; + RCTFlagsChecker rctChecker; + + Configurable cfgFillQAPlots{"cfgFillQAPlots", true, "Fill QA plots"}; + Configurable cfgCentEst{"cfgCentEst", 2, "Centrality estimator, 1: FT0C, 2: FT0M"}; + + /// PID Selections, pion + struct : ConfigurableGroup { + Configurable cfgTPConly{"cfgTPConly", true, "Use only TPC for PID"}; // bool + Configurable cfgMaxTPCnSigmaPion{"cfgMaxTPCnSigmaPion", 5.0, "TPC nSigma cut for Pion"}; // TPC + Configurable cfgMaxTOFnSigmaPion{"cfgMaxTOFnSigmaPion", 5.0, "TOF nSigma cut for Pion"}; // TOF + Configurable cfgNsigmaCutCombinedPion{"cfgNsigmaCutCombinedPion", -999, "Combined nSigma cut for Pion"}; // Combined + Configurable cfgTOFVeto{"cfgTOFVeto", false, "TOF Veto, if false, TOF is nessessary for PID selection"}; // TOF Veto + Configurable cfgTOFMinPt{"cfgTOFMinPt", 0.6, "Minimum TOF pT cut for Pion"}; // TOF pT cut + } PIDCuts; + // Track selections - Configurable cfgPrimaryTrack{"cfgPrimaryTrack", true, "Primary track selection"}; // kGoldenChi2 | kDCAxy | kDCAz - Configurable cfgGlobalWoDCATrack{"cfgGlobalWoDCATrack", true, "Global track selection without DCA"}; // kQualityTracks (kTrackType | kTPCNCls | kTPCCrossedRows | kTPCCrossedRowsOverNCls | kTPCChi2NDF | kTPCRefit | kITSNCls | kITSChi2NDF | kITSRefit | kITSHits) | kInAcceptanceTracks (kPtRange | kEtaRange) - Configurable cfgGlobalTrack{"cfgGlobalTrack", false, "Global track selection"}; // kGoldenChi2 | kDCAxy | kDCAz - Configurable cfgPVContributor{"cfgPVContributor", false, "PV contributor track selection"}; // PV Contriuibutor - Configurable additionalQAplots{"additionalQAplots", true, "Additional QA plots"}; - Configurable tof_at_high_pt{"tof_at_high_pt", false, "Use TOF at high pT"}; - Configurable additionalEvsel{"additionalEvsel", true, "Additional event selcection"}; - Configurable cfgTPCcluster{"cfgTPCcluster", 0, "Number of TPC cluster"}; - Configurable cfgUseTPCRefit{"cfgUseTPCRefit", false, "Require TPC Refit"}; - Configurable cfgUseITSRefit{"cfgUseITSRefit", false, "Require ITS Refit"}; - Configurable cfgHasTOF{"cfgHasTOF", false, "Require TOF"}; - - // Secondary selection - Configurable cfgModeK892orRho{"cfgModeK892orRho", true, "Secondary scenario for K892 (true) or Rho (false)"}; - Configurable cSecondaryMasswindow{"cSecondaryMasswindow", 0.1, "Secondary inv mass selection window"}; - Configurable cMinAnotherSecondaryMassCut{"cMinAnotherSecondaryMassCut", 0, "Min inv. mass selection of another secondary scenario"}; - Configurable cMaxAnotherSecondaryMassCut{"cMaxAnotherSecondaryMassCut", 999, "MAx inv. mass selection of another secondary scenario"}; - Configurable cMinPiKaMassCut{"cMinPiKaMassCut", 0, "bPion-Kaon pair inv mass selection minimum"}; - Configurable cMaxPiKaMassCut{"cMaxPiKaMassCut", 999, "bPion-Kaon pair inv mass selection maximum"}; - Configurable cMinAngle{"cMinAngle", 0, "Minimum angle between K(892)0 and bachelor pion"}; - Configurable cMaxAngle{"cMaxAngle", 4, "Maximum angle between K(892)0 and bachelor pion"}; - Configurable cMinPairAsym{"cMinPairAsym", -1, "Minimum pair asymmetry"}; - Configurable cMaxPairAsym{"cMaxPairAsym", 1, "Maximum pair asymmetry"}; + struct : ConfigurableGroup { + Configurable cfgMinPtcut{"cfgMinPtcut", 0.15, "Track minium pt cut"}; + Configurable cfgMaxEtacut{"cfgMaxEtacut", 0.8, "Track maximum eta cut"}; + Configurable cfgPrimaryTrack{"cfgPrimaryTrack", true, "Primary track selection"}; // kGoldenChi2 | kDCAxy | kDCAz + Configurable cfgGlobalWoDCATrack{"cfgGlobalWoDCATrack", true, "Global track selection without DCA"}; // kQualityTracks (kTrackType | kTPCNCls | kTPCCrossedRows | kTPCCrossedRowsOverNCls | kTPCChi2NDF | kTPCRefit | kITSNCls | kITSChi2NDF | kITSRefit | kITSHits) | kInAcceptanceTracks (kPtRange | kEtaRange) + Configurable cfgGlobalTrack{"cfgGlobalTrack", false, "Global track selection"}; // kGoldenChi2 | kDCAxy | kDCAz + Configurable cfgPVContributor{"cfgPVContributor", false, "PV contributor track selection"}; // PV Contriuibutor + + Configurable cfgpTdepDCAxyCut{"cfgpTdepDCAxyCut", true, "pT-dependent DCAxy cut"}; + Configurable cfgpTdepDCAzCut{"cfgpTdepDCAzCut", true, "pT-dependent DCAz cut"}; + Configurable cfgITScluster{"cfgITScluster", 0, "Number of ITS cluster"}; + Configurable cfgTPCcluster{"cfgTPCcluster", 0, "Number of TPC cluster"}; + Configurable cfgRatioTPCRowsOverFindableCls{"cfgRatioTPCRowsOverFindableCls", 0.0f, "TPC Crossed Rows to Findable Clusters"}; + Configurable cfgITSChi2NCl{"cfgITSChi2NCl", 999.0, "ITS Chi2/NCl"}; + Configurable cfgTPCChi2NCl{"cfgTPCChi2NCl", 999.0, "TPC Chi2/NCl"}; + Configurable cfgUseTPCRefit{"cfgUseTPCRefit", false, "Require TPC Refit"}; + Configurable cfgUseITSRefit{"cfgUseITSRefit", false, "Require ITS Refit"}; + Configurable cfgHasITS{"cfgHasITS", false, "Require ITS"}; + Configurable cfgHasTPC{"cfgHasTPC", false, "Require TPC"}; + Configurable cfgHasTOF{"cfgHasTOF", false, "Require TOF"}; + // DCAr to PV + Configurable cfgMaxbDCArToPVcut{"cfgMaxbDCArToPVcut", 0.1, "Track DCAr cut to PV Maximum"}; + // DCAz to PV + Configurable cfgMaxbDCAzToPVcut{"cfgMaxbDCAzToPVcut", 0.1, "Track DCAz cut to PV Maximum"}; + } TrackCuts; + + // Secondary Selection + struct : ConfigurableGroup { + Configurable cfgReturnFlag{"cfgReturnFlag", false, "Return Flag for debugging"}; + Configurable cfgSecondaryRequire{"cfgSecondaryRequire", true, "Secondary cuts on/off"}; + Configurable cfgSecondaryArmenterosCut{"cfgSecondaryArmenterosCut", true, "cut on Armenteros-Podolanski graph"}; + Configurable cfgSecondaryCrossMassHypothesisCut{"cfgSecondaryCrossMassHypothesisCut", false, "Apply cut based on the lambda mass hypothesis"}; + + Configurable cfgByPassDauPIDSelection{"cfgByPassDauPIDSelection", true, "Bypass Daughters PID selection"}; + Configurable cfgSecondaryDauDCAMax{"cfgSecondaryDauDCAMax", 1., "Maximum DCA Secondary daughters to PV"}; + Configurable cfgSecondaryDauPosDCAtoPVMin{"cfgSecondaryDauPosDCAtoPVMin", 0.1, "Minimum DCA Secondary positive daughters to PV"}; + Configurable cfgSecondaryDauNegDCAtoPVMin{"cfgSecondaryDauNegDCAtoPVMin", 0.1, "Minimum DCA Secondary negative daughters to PV"}; + + Configurable cfgSecondaryPtMin{"cfgSecondaryPtMin", 0.f, "Minimum transverse momentum of Secondary"}; + Configurable cfgSecondaryRapidityMax{"cfgSecondaryRapidityMax", 0.8, "Maximum rapidity of Secondary"}; + Configurable cfgSecondaryRadiusMin{"cfgSecondaryRadiusMin", 0, "Minimum transverse radius of Secondary"}; + Configurable cfgSecondaryRadiusMax{"cfgSecondaryRadiusMax", 999.9, "Maximum transverse radius of Secondary"}; + Configurable cfgSecondaryCosPAMin{"cfgSecondaryCosPAMin", 0.995, "Mininum cosine pointing angle of Secondary"}; + Configurable cfgSecondaryDCAtoPVMax{"cfgSecondaryDCAtoPVMax", 0.4, "Maximum DCA Secondary to PV"}; + Configurable cfgSecondaryProperLifetimeMax{"cfgSecondaryProperLifetimeMax", 20, "Maximum Secondary Lifetime"}; + Configurable cfgSecondaryparamArmenterosCut{"cfgSecondaryparamArmenterosCut", 0.2, "parameter for Armenteros Cut"}; + Configurable cfgSecondaryMassWindow{"cfgSecondaryMassWindow", 0.03, "Secondary inv mass selciton window"}; + Configurable cfgSecondaryCrossMassCutWindow{"cfgSecondaryCrossMassCutWindow", 0.05, "Secondary inv mass selection window with (anti)lambda hypothesis"}; + } SecondaryCuts; + + // K* selection + struct : ConfigurableGroup { + Configurable cfgKstarMinPt{"cfgKstarMinPt", 0.0, "Kstar minimum pT"}; + Configurable cfgKstarMaxRap{"cfgKstarMaxRap", 0.5, "Kstar maximum rapidity"}; + Configurable cfgKstarMinRap{"cfgKstarMinRap", -0.5, "Kstar minimum rapidity"}; + Configurable cfgKstarMassWindow{"cfgKstarMassWindow", 0.05, "Kstar inv mass selection window"}; + } KstarCuts; // K1 selection - Configurable cK1MaxRap{"cK1MaxRap", 0.5, "K1 maximum rapidity"}; - Configurable cK1MinRap{"cK1MinRap", -0.5, "K1 minimum rapidity"}; + struct : ConfigurableGroup { + Configurable cfgK1MinPt{"cfgK1MinPt", 0.0, "K1 minimum pT"}; + Configurable cfgK1MaxRap{"cfgK1MaxRap", 0.5, "K1 maximum rapidity"}; + Configurable cfgK1MinRap{"cfgK1MinRap", -0.5, "K1 minimum rapidity"}; + } K1Cuts; + + // Bkg estimation + struct : ConfigurableGroup { + Configurable cfgFillRotBkg{"cfgFillRotBkg", true, "Fill rotated background"}; + Configurable cfgMinRot{"cfgMinRot", 5.0 * constants::math::PI / 6.0, "Minimum of rotation"}; + Configurable cfgMaxRot{"cfgMaxRot", 7.0 * constants::math::PI / 6.0, "Maximum of rotation"}; + Configurable cfgRotPion{"cfgRotPion", true, "Rotate pion"}; + Configurable cfgNrotBkg{"cfgNrotBkg", 4, "Number of rotated copies (background) per each original candidate"}; + } BkgEstimationConfig; + + Configurable cfgTruthUseInelGt0{"cfgTruthUseInelGt0", true, "Truth denominator: require INEL>0"}; + Configurable cfgTruthIncludeZvtx{"cfgTruthIncludeZvtx", true, "Truth denominator: also require |vtxz| cfgHasPair{"cfgHasPair", true, "Check the existence of pairs"}; + Configurable cfgPiPiMinPt{"cfgPiPiMinPt", 0.5, "bachelor pion and secondary pion minimum pT cut"}; + + float lCentrality; + + // PDG code + int kPDGK0s = kK0Short; + int kPDGK0 = kK0; + int kPDGKstarPlus = o2::constants::physics::Pdg::kKPlusStar892; + int kPDGPiPlus = kPiPlus; + int kPDGK10 = 10313; + double fMaxPosPV = 1e-2; void init(o2::framework::InitContext&) { - std::vector centBinning = {0., 1., 5., 10., 15., 20., 25., 30., 35., 40., 45., 50., 55., 60., 65., 70., 80., 90., 100., 200.}; - AxisSpec centAxis = {centBinning, "T0M (%)"}; - AxisSpec ptAxis = {150, 0, 15, "#it{p}_{T} (GeV/#it{c})"}; - AxisSpec dcaxyAxis = {300, 0, 3, "DCA_{#it{xy}} (cm)"}; - AxisSpec dcazAxis = {500, 0, 5, "DCA_{#it{xy}} (cm)"}; - AxisSpec invMassAxisK892 = {1400 / cNbinsDiv, 0.6, 2.0, "Invariant Mass (GeV/#it{c}^2)"}; // K(892)0 - AxisSpec invMassAxisRho = {2000 / cNbinsDiv, 0.0, 2.0, "Invariant Mass (GeV/#it{c}^2)"}; // rho - AxisSpec invMassAxisReso = {1600 / cNbinsDiv, 0.9f, 2.5f, "Invariant Mass (GeV/#it{c}^2)"}; // K1 - AxisSpec invMassAxisScan = {250, 0, 2.5, "Invariant Mass (GeV/#it{c}^2)"}; // For selection - AxisSpec pidQAAxis = {130, -6.5, 6.5}; - AxisSpec dataTypeAxis = {9, 0, 9, "Histogram types"}; - AxisSpec mcTypeAxis = {4, 0, 4, "Histogram types"}; + lCentrality = -999; + + colCuts.setCuts(EventCuts.cfgEvtZvtx, EventCuts.cfgEvtTriggerCheck, EventCuts.cfgEvtOfflineCheck, /*checkRun3*/ true, EventCuts.cfgEvtTriggerTVXSel, EventCuts.cfgEvtOccupancyInTimeRangeMax, EventCuts.cfgEvtOccupancyInTimeRangeMin); + colCuts.init(&histos); + colCuts.setTriggerTVX(EventCuts.cfgEvtTriggerTVXSel); + colCuts.setApplyTFBorderCut(EventCuts.cfgEvtTFBorderCut); + colCuts.setApplyNoITSROBorderCut(EventCuts.cfgEvtNoITSROBorderCut); + colCuts.setApplyITSTPCvertex(EventCuts.cfgEvtUseITSTPCvertex); + colCuts.setApplyZvertexTimedifference(EventCuts.cfgEvtZvertexTimedifference); + colCuts.setApplyPileupRejection(EventCuts.cfgEvtPileupRejection); + colCuts.setApplyCollInTimeRangeStandard(EventCuts.cfgEvtCollInTimeRangeStandard); + colCuts.printCuts(); + + rctChecker.init(EventCuts.cfgEvtRCTFlagCheckerLabel, EventCuts.cfgEvtRCTFlagCheckerZDCCheck, EventCuts.cfgEvtRCTFlagCheckerLimitAcceptAsBad); + + AxisSpec centAxis = {AxisConfig.cfgBinsCent, "T0M (%)"}; + AxisSpec vtxzAxis = {AxisConfig.cfgBinsVtxZ, "Z Vertex (cm)"}; + AxisSpec ptAxis = {AxisConfig.cfgBinsPt, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec ptAxisQA = {AxisConfig.cfgBinsPtQA, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec radiusAxis = {50, 0, 5, "Radius (cm)"}; + AxisSpec cpaAxis = {50, 0.95, 1.0, "CPA"}; + AxisSpec tauAxis = {250, 0, 25, "Lifetime (cm)"}; + AxisSpec dcaAxis = {200, 0, 2, "DCA (cm)"}; + AxisSpec dcaxyAxis = {200, 0, 2, "DCA_{#it{xy}} (cm)"}; + AxisSpec dcazAxis = {200, 0, 2, "DCA_{#it{z}} (cm)"}; + AxisSpec yAxis = {100, -1, 1, "Rapidity"}; + AxisSpec invMassAxisK0s = {800 / AxisConfig.cNbinsDiv, 0.46, 0.54, "Invariant Mass (GeV/#it{c}^2)"}; // K0s ~497.611 + AxisSpec invMassAxisChk892 = {900 / AxisConfig.cNbinsDiv, 0.5f, 1.4f, "Invariant Mass (GeV/#it{c}^2)"}; // chK(892) ~892 + AxisSpec invMassAxisReso = {1600 / AxisConfig.cNbinsDiv, 0.9f, 2.5f, "Invariant Mass (GeV/#it{c}^2)"}; // K1 + AxisSpec pidQAAxis = {130 / AxisConfig.cNbinsDivQA, -6.5, 6.5}; + AxisSpec cutAxis{14, 0.5, 14.5, "Check"}; // 1..14 // THnSparse - AxisSpec axisAnti = {binAnti::kNAEnd, 0, binAnti::kNAEnd, "Type of bin: Normal or Anti"}; - AxisSpec axisType = {binType::kTYEnd, 0, binType::kTYEnd, "Type of bin with charge and mix"}; + AxisSpec axisType = {BinType::kTYEnd, 0, BinType::kTYEnd, "Type of bin with charge and mix"}; AxisSpec mcLabelAxis = {5, -0.5, 4.5, "MC Label"}; - // DCA QA - // Primary pion - histos.add("QA/trkppionDCAxy", "DCAxy distribution of primary pion candidates", HistType::kTH1F, {dcaxyAxis}); - histos.add("QA/trkppionDCAz", "DCAz distribution of primary pion candidates", HistType::kTH1F, {dcaxyAxis}); - histos.add("QA/trkppionpT", "pT distribution of primary pion candidates", HistType::kTH1F, {ptAxis}); - histos.add("QA/trkppionTPCPID", "TPC PID of primary pion candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); - histos.add("QA/trkppionTOFPID", "TOF PID of primary pion candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); - histos.add("QA/trkppionTPCTOFPID", "TPC-TOF PID map of primary pion candidates", HistType::kTH2F, {pidQAAxis, pidQAAxis}); - - histos.add("QAcut/trkppionDCAxy", "DCAxy distribution of primary pion candidates", HistType::kTH1F, {dcaxyAxis}); - histos.add("QAcut/trkppionDCAz", "DCAz distribution of primary pion candidates", HistType::kTH1F, {dcaxyAxis}); - histos.add("QAcut/trkppionpT", "pT distribution of primary pion candidates", HistType::kTH1F, {ptAxis}); - histos.add("QAcut/trkppionTPCPID", "TPC PID of primary pion candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); - histos.add("QAcut/trkppionTOFPID", "TOF PID of primary pion candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); - histos.add("QAcut/trkppionTPCTOFPID", "TPC-TOF PID map of primary pion candidates", HistType::kTH2F, {pidQAAxis, pidQAAxis}); + histos.add("QA/K0sCutCheck", "Check K0s cut", HistType::kTH1D, {AxisSpec{13, -0.5, 12.5, "Check"}}); + histos.add("QA/K0sCutFlow", "Check K0s cut (first-fail or pass)", HistType::kTH1F, {cutAxis}); + auto hcut = histos.get(HIST("QA/K0sCutFlow")); + hcut->GetXaxis()->SetBinLabel(1, "TOTAL"); + hcut->GetXaxis()->SetBinLabel(2, "PASS"); + hcut->GetXaxis()->SetBinLabel(3, "DauDCA>max"); + hcut->GetXaxis()->SetBinLabel(4, "PosDCAtoPVGetXaxis()->SetBinLabel(5, "NegDCAtoPVGetXaxis()->SetBinLabel(6, "pTGetXaxis()->SetBinLabel(7, "|y|>max"); + hcut->GetXaxis()->SetBinLabel(8, "Rmax"); + hcut->GetXaxis()->SetBinLabel(9, "DCAtoPV>max"); + hcut->GetXaxis()->SetBinLabel(10, "cosPAGetXaxis()->SetBinLabel(11, "ctau>max"); + hcut->GetXaxis()->SetBinLabel(12, "qtarmGetXaxis()->SetBinLabel(13, "|M(K0s)-m0|>win"); + hcut->GetXaxis()->SetBinLabel(14, "cross-mass veto"); + + histos.add("QA/before/CentDist", "Centrality distribution", {HistType::kTH1D, {centAxis}}); + histos.add("QA/before/VtxZ", "Centrality distribution", {HistType::kTH1D, {vtxzAxis}}); + histos.add("QA/before/hEvent", "Number of Events", HistType::kTH1F, {{1, 0.5, 1.5}}); + + if (BkgEstimationConfig.cfgFillRotBkg) { + histos.add("QA/RotBkg/hRotBkg", "Rotated angle of rotated background", HistType::kTH1F, {{360, 0.0, o2::constants::math::TwoPI}}); + } + + // Bachelor pion + histos.add("QA/before/trkbpionDCAxy", "DCAxy distribution of bachelor pion candidates", HistType::kTH1D, {dcaxyAxis}); + histos.add("QA/before/trkbpionDCAz", "DCAz distribution of bachelor pion candidates", HistType::kTH1D, {dcazAxis}); + histos.add("QA/before/trkbpionpT", "pT distribution of bachelor pion candidates", HistType::kTH1D, {ptAxisQA}); + histos.add("QA/before/trkbpionTPCPID", "TPC PID of bachelor pion candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); + histos.add("QA/before/trkbpionTOFPID", "TOF PID of bachelor pion candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); + histos.add("QA/before/trkbpionTPCTOFPID", "TPC-TOF PID map of bachelor pion candidates", HistType::kTH2D, {pidQAAxis, pidQAAxis}); + + histos.add("QA/after/trkbpionDCAxy", "DCAxy distribution of bachelor pion candidates", HistType::kTH1D, {dcaxyAxis}); + histos.add("QA/after/trkbpionDCAz", "DCAz distribution of bachelor pion candidates", HistType::kTH1D, {dcazAxis}); + histos.add("QA/after/trkbpionpT", "pT distribution of bachelor pion candidates", HistType::kTH1D, {ptAxisQA}); + histos.add("QA/after/trkbpionTPCPID", "TPC PID of bachelor pion candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); + histos.add("QA/after/trkbpionTOFPID", "TOF PID of bachelor pion candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); + histos.add("QA/after/trkbpionTPCTOFPID", "TPC-TOF PID map of bachelor pion candidates", HistType::kTH2D, {pidQAAxis, pidQAAxis}); // Secondary pion - histos.add("QA/trkspionDCAxy", "DCAxy distribution of secondary pion candidates", HistType::kTH1F, {dcaxyAxis}); - histos.add("QA/trkspionDCAz", "DCAz distribution of secondary pion candidates", HistType::kTH1F, {dcaxyAxis}); - histos.add("QA/trkspionpT", "pT distribution of secondary pion candidates", HistType::kTH1F, {ptAxis}); - histos.add("QA/trkspionTPCPID", "TPC PID of secondary pion candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); - histos.add("QA/trkspionTOFPID", "TOF PID of secondary pion candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); - histos.add("QA/trkspionTPCTOFPID", "TPC-TOF PID map of secondary pion candidates", HistType::kTH2F, {pidQAAxis, pidQAAxis}); - - histos.add("QAcut/trkspionDCAxy", "DCAxy distribution of secondary pion candidates", HistType::kTH1F, {dcaxyAxis}); - histos.add("QAcut/trkspionDCAz", "DCAz distribution of secondary pion candidates", HistType::kTH1F, {dcaxyAxis}); - histos.add("QAcut/trkspionpT", "pT distribution of secondary pion candidates", HistType::kTH1F, {ptAxis}); - histos.add("QAcut/trkspionTPCPID", "TPC PID of secondary pion candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); - histos.add("QAcut/trkspionTOFPID", "TOF PID of secondary pion candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); - histos.add("QAcut/trkspionTPCTOFPID", "TPC-TOF PID map of secondary pion candidates", HistType::kTH2F, {pidQAAxis, pidQAAxis}); - - // Kaon - histos.add("QA/trkkaonDCAxy", "DCAxy distribution of kaon candidates", HistType::kTH1F, {dcaxyAxis}); - histos.add("QA/trkkaonDCAz", "DCAz distribution of kaon candidates", HistType::kTH1F, {dcaxyAxis}); - histos.add("QA/trkkaonpT", "pT distribution of kaon candidates", HistType::kTH1F, {ptAxis}); - histos.add("QA/trkkaonTPCPID", "TPC PID of kaon candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); - histos.add("QA/trkkaonTOFPID", "TOF PID of kaon candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); - histos.add("QA/trkkaonTPCTOFPID", "TPC-TOF PID map of kaon candidates", HistType::kTH2F, {pidQAAxis, pidQAAxis}); - - histos.add("QAcut/trkkaonDCAxy", "DCAxy distribution of kaon candidates", HistType::kTH1F, {dcaxyAxis}); - histos.add("QAcut/trkkaonDCAz", "DCAz distribution of kaon candidates", HistType::kTH1F, {dcaxyAxis}); - histos.add("QAcut/trkkaonpT", "pT distribution of kaon candidates", HistType::kTH1F, {ptAxis}); - histos.add("QAcut/trkkaonTPCPID", "TPC PID of kaon candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); - histos.add("QAcut/trkkaonTOFPID", "TOF PID of kaon candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); - histos.add("QAcut/trkkaonTPCTOFPID", "TPC-TOF PID map of kaon candidates", HistType::kTH2F, {pidQAAxis, pidQAAxis}); + histos.add("QA/before/trkspionTPCPID", "TPC PID of secondary pion 1 (positive) candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); + histos.add("QA/before/trkspionTOFPID", "TOF PID of secondary pion 1 (positive) candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); + histos.add("QA/before/trkspionTPCTOFPID", "TPC-TOF PID map of secondary pion 1 (positive) candidates", HistType::kTH2D, {pidQAAxis, pidQAAxis}); + histos.add("QA/before/trkspionpT", "pT distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {ptAxisQA}); + histos.add("QA/before/trkspionDCAxy", "DCAxy distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {dcaxyAxis}); + histos.add("QA/before/trkspionDCAz", "DCAz distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {dcazAxis}); + + histos.add("QA/after/trkspionTPCPID", "TPC PID of secondary pion 1 (positive) candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); + histos.add("QA/after/trkspionTOFPID", "TOF PID of secondary pion 1 (positive) candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); + histos.add("QA/after/trkspionTPCTOFPID", "TPC-TOF PID map of secondary pion 1 (positive) candidates", HistType::kTH2D, {pidQAAxis, pidQAAxis}); + histos.add("QA/after/trkspionpT", "pT distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {ptAxisQA}); + histos.add("QA/after/trkspionDCAxy", "DCAxy distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {dcaxyAxis}); + histos.add("QA/after/trkspionDCAz", "DCAz distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {dcazAxis}); + + // K0s pion 1 + histos.add("QA/before/trkppionTPCPID", "TPC PID of secondary pion 1 (positive) candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); + histos.add("QA/before/trkppionTOFPID", "TOF PID of secondary pion 1 (positive) candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); + histos.add("QA/before/trkppionTPCTOFPID", "TPC-TOF PID map of secondary pion 1 (positive) candidates", HistType::kTH2D, {pidQAAxis, pidQAAxis}); + histos.add("QA/before/trkppionpT", "pT distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {ptAxisQA}); + histos.add("QA/before/trkppionDCAxy", "DCAxy distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {dcaxyAxis}); + histos.add("QA/before/trkppionDCAz", "DCAz distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {dcazAxis}); + + histos.add("QA/after/trkppionTPCPID", "TPC PID of secondary pion 1 (positive) candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); + histos.add("QA/after/trkppionTOFPID", "TOF PID of secondary pion 1 (positive) candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); + histos.add("QA/after/trkppionTPCTOFPID", "TPC-TOF PID map of secondary pion 1 (positive) candidates", HistType::kTH2D, {pidQAAxis, pidQAAxis}); + histos.add("QA/after/trkppionpT", "pT distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {ptAxisQA}); + histos.add("QA/after/trkppionDCAxy", "DCAxy distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {dcaxyAxis}); + histos.add("QA/after/trkppionDCAz", "DCAz distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {dcazAxis}); + + // K0s pion 2 + histos.add("QA/before/trknpionTPCPID", "TPC PID of secondary pion 2 (negative) candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); + histos.add("QA/before/trknpionTOFPID", "TOF PID of secondary pion 2 (negative) candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); + histos.add("QA/before/trknpionTPCTOFPID", "TPC-TOF PID map of secondary pion 2 (negative) candidates", HistType::kTH2D, {pidQAAxis, pidQAAxis}); + histos.add("QA/before/trknpionpT", "pT distribution of secondary pion 2 (negative) candidates", HistType::kTH1D, {ptAxisQA}); + histos.add("QA/before/trknpionDCAxy", "DCAxy distribution of secondary pion 2 (negative) candidates", HistType::kTH1D, {dcaxyAxis}); + histos.add("QA/before/trknpionDCAz", "DCAz distribution of secondary pion 2 (negative) candidates", HistType::kTH1D, {dcazAxis}); + + histos.add("QA/after/trknpionTPCPID", "TPC PID of secondary pion 2 (negative) candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); + histos.add("QA/after/trknpionTOFPID", "TOF PID of secondary pion 2 (negative) candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); + histos.add("QA/after/trknpionTPCTOFPID", "TPC-TOF PID map of secondary pion 2 (negative) candidates", HistType::kTH2D, {pidQAAxis, pidQAAxis}); + histos.add("QA/after/trknpionpT", "pT distribution of secondary pion 2 (negative) candidates", HistType::kTH1D, {ptAxisQA}); + histos.add("QA/after/trknpionDCAxy", "DCAxy distribution of secondary pion 2 (negative) candidates", HistType::kTH1D, {dcaxyAxis}); + histos.add("QA/after/trknpionDCAz", "DCAz distribution of secondary pion 2 (negative) candidates", HistType::kTH1D, {dcazAxis}); + + // K0s + histos.add("QA/before/hDauDCASecondary", "DCA of daughters of secondary resonance", HistType::kTH1D, {dcaAxis}); + histos.add("QA/before/hDauPosDCAtoPVSecondary", "Pos DCA to PV of daughters secondary resonance", HistType::kTH1D, {dcaAxis}); + histos.add("QA/before/hDauNegDCAtoPVSecondary", "Neg DCA to PV of daughters secondary resonance", HistType::kTH1D, {dcaAxis}); + histos.add("QA/before/hpT_Secondary", "pT distribution of secondary resonance", HistType::kTH1D, {ptAxisQA}); + histos.add("QA/before/hy_Secondary", "Rapidity distribution of secondary resonance", HistType::kTH1D, {yAxis}); + histos.add("QA/before/hRadiusSecondary", "Radius distribution of secondary resonance", HistType::kTH1D, {radiusAxis}); + histos.add("QA/before/hCPASecondary", "Cosine pointing angle distribution of secondary resonance", HistType::kTH1D, {cpaAxis}); + histos.add("QA/before/hDCAtoPVSecondary", "DCA to PV distribution of secondary resonance", HistType::kTH1D, {dcaAxis}); + histos.add("QA/before/hPropTauSecondary", "Proper Lifetime distribution of secondary resonance", HistType::kTH1D, {tauAxis}); + histos.add("QA/before/hPtAsymSecondary", "pT asymmetry distribution of secondary resonance", HistType::kTH1D, {AxisSpec{100, -1, 1, "Pair asymmetry"}}); + histos.add("QA/before/hArmSecondary", "Armenteros distribution of secondary resonance", HistType::kTH2D, {AxisSpec{100, -1, 1, "alpha"}, {200, 0, 0.5, "qtArm"}}); + histos.add("QA/before/hInvmassSecondary", "Invariant mass of unlike-sign secondary resonance", HistType::kTH1D, {invMassAxisK0s}); + + histos.add("QA/after/hDauDCASecondary", "DCA of daughters of secondary resonance", HistType::kTH1D, {dcaAxis}); + histos.add("QA/after/hDauPosDCAtoPVSecondary", "Pos DCA to PV of daughters secondary resonance", HistType::kTH1D, {dcaAxis}); + histos.add("QA/after/hDauNegDCAtoPVSecondary", "Neg DCA to PV of daughters secondary resonance", HistType::kTH1D, {dcaAxis}); + histos.add("QA/after/hpT_Secondary", "pT distribution of secondary resonance", HistType::kTH1D, {ptAxisQA}); + histos.add("QA/after/hy_Secondary", "Rapidity distribution of secondary resonance", HistType::kTH1D, {yAxis}); + histos.add("QA/after/hRadiusSecondary", "Radius distribution of secondary resonance", HistType::kTH1D, {radiusAxis}); + histos.add("QA/after/hCPASecondary", "Cosine pointing angle distribution of secondary resonance", HistType::kTH1D, {cpaAxis}); + histos.add("QA/after/hDCAtoPVSecondary", "DCA to PV distribution of secondary resonance", HistType::kTH1D, {dcaAxis}); + histos.add("QA/after/hPropTauSecondary", "Proper Lifetime distribution of secondary resonance", HistType::kTH1D, {tauAxis}); + histos.add("QA/after/hPtAsymSecondary", "pT asymmetry distribution of secondary resonance", HistType::kTH1D, {AxisSpec{100, -1, 1, "Pair asymmetry"}}); + histos.add("QA/after/hArmSecondary", "Armenteros distribution of secondary resonance", HistType::kTH2D, {AxisSpec{100, -1, 1, "alpha"}, {200, 0, 0.5, "qtArm"}}); + histos.add("QA/after/hInvmassSecondary", "Invariant mass of unlike-sign secondary resonance", HistType::kTH1D, {invMassAxisK0s}); + + // charged Kstar + histos.add("QA/before/hpT_Kstar", "pT distribution of chK(892)", HistType::kTH1D, {ptAxisQA}); + histos.add("QA/before/hy_Kstar", "Rapidity distribution of chK(892)", HistType::kTH1D, {yAxis}); + histos.add("QA/before/kstarinvmass", "Invariant mass of unlike-sign chK(892)", HistType::kTH1D, {invMassAxisChk892}); + + histos.add("QA/after/hpT_Kstar", "pT distribution of chK(892)", HistType::kTH1D, {ptAxisQA}); + histos.add("QA/after/hy_Kstar", "Rapidity distribution of chK(892)", HistType::kTH1D, {yAxis}); + histos.add("QA/after/kstarinvmass", "Invariant mass of unlike-sign chK(892)", HistType::kTH1D, {invMassAxisChk892}); // K1 - histos.add("QA/K1OA", "Opening angle of K1(1270)", HistType::kTH1F, {AxisSpec{100, 0, 3.14, "Opening angle"}}); - histos.add("QA/K1PairAssym", "Pair asymmetry of K1(1270)", HistType::kTH1F, {AxisSpec{100, -1, 1, "Pair asymmetry"}}); - histos.add("QA/hInvmassK892_Rho", "Invariant mass of K(892)0 vs Rho(770)", HistType::kTH2F, {invMassAxisK892, invMassAxisRho}); - histos.add("QA/hInvmassSecon_PiKa", "Invariant mass of secondary resonance vs pion-kaon", HistType::kTH2F, {invMassAxisK892, invMassAxisK892}); - histos.add("QA/hInvmassSecon", "Invariant mass of secondary resonance", HistType::kTH1F, {invMassAxisRho}); - histos.add("QA/hpT_Secondary", "pT distribution of secondary resonance", HistType::kTH1F, {ptAxis}); - - histos.add("QAcut/K1OA", "Opening angle of K1(1270)", HistType::kTH1F, {AxisSpec{100, 0, 3.14, "Opening angle"}}); - histos.add("QAcut/K1PairAssym", "Pair asymmetry of K1(1270)", HistType::kTH1F, {AxisSpec{100, -1, 1, "Pair asymmetry"}}); - histos.add("QAcut/hInvmassK892_Rho", "Invariant mass of K(892)0 vs Rho(770)", HistType::kTH2F, {invMassAxisK892, invMassAxisRho}); - histos.add("QAcut/hInvmassSecon_PiKa", "Invariant mass of secondary resonance vs pion-kaon", HistType::kTH2F, {invMassAxisK892, invMassAxisK892}); - histos.add("QAcut/hInvmassSecon", "Invariant mass of secondary resonance", HistType::kTH1F, {invMassAxisRho}); - histos.add("QAcut/hpT_Secondary", "pT distribution of secondary resonance", HistType::kTH1F, {ptAxis}); + histos.add("QA/before/hpT_K1", "pT distribution of K1(1270)", HistType::kTH1F, {ptAxisQA}); + histos.add("QA/before/hy_K1", "Rapidity distribution of K1(1270)", HistType::kTH1F, {yAxis}); + histos.add("QA/before/K1CPA", "Cosine pointing angle distribution of K1(1270)", HistType::kTH1F, {cpaAxis}); + histos.add("QA/before/K1PtAsym", "pT asymmetry distribution of K1(1270)", HistType::kTH1F, {AxisSpec{100, -1, 1, "Pair asymmetry"}}); + histos.add("QA/before/K1DalitzOS", "Dalitz plot of opposite-sign combination of K1(1270)", HistType::kTH2F, {AxisSpec{300, 0.0, 3.0, "#it{M}^{2}_{K_{s}^{0}#pi_{sec}}"}, {300, 0.0, 3.0, "#it{M}^{2}_{#pi_{sec}#pi_{bach}}"}}); + histos.add("QA/before/K1DalitzLS", "Dalitz plot of like-sign combination of K1(1270)", HistType::kTH2F, {AxisSpec{300, 0.0, 3.0, "#it{M}^{2}_{K_{s}^{0}#pi_{sec}}"}, {300, 0.0, 3.0, "#it{M}^{2}_{#pi_{sec}#pi_{bach}}"}}); + histos.add("QA/before/K1invmass", "Invariant mass of K1(1270) (US)", HistType::kTH1F, {invMassAxisReso}); + histos.add("QA/before/K1invmassLS", "Invariant mass of K1(1270) (LS)", HistType::kTH1F, {invMassAxisReso}); + + histos.add("QA/after/hpT_K1", "pT distribution of K1(1270)", HistType::kTH1F, {ptAxisQA}); + histos.add("QA/after/hy_K1", "Rapidity distribution of K1(1270)", HistType::kTH1F, {yAxis}); + histos.add("QA/after/K1CPA", "Cosine pointing angle of K1(1270)", HistType::kTH1F, {cpaAxis}); + histos.add("QA/after/K1PtAsym", "pT asymmetry distribution of K1(1270)", HistType::kTH1F, {AxisSpec{100, -1, 1, "Pair asymmetry"}}); + histos.add("QA/after/K1DalitzOS_Signal", "(Signal region) Dalitz plot of opposite-sign combination of K1(1270)", HistType::kTH2F, {AxisSpec{300, 0.0, 3.0, "#it{M}^{2}_{K_{s}^{0}#pi_{sec}}"}, {300, 0.0, 3.0, "#it{M}^{2}_{#pi_{sec}#pi_{bach}}"}}); + histos.add("QA/after/K1DalitzOS_SBLeft", "(SB left) Dalitz plot of opposite-sign combination of K1(1270)", HistType::kTH2F, {AxisSpec{300, 0.0, 3.0, "#it{M}^{2}_{K_{s}^{0}#pi_{sec}}"}, {300, 0.0, 3.0, "#it{M}^{2}_{#pi_{sec}#pi_{bach}}"}}); + histos.add("QA/after/K1DalitzOS_SBRight", "(SB right) Dalitz plot of opposite-sign combination of K1(1270)", HistType::kTH2F, {AxisSpec{300, 0.0, 3.0, "#it{M}^{2}_{K_{s}^{0}#pi_{sec}}"}, {300, 0.0, 3.0, "#it{M}^{2}_{#pi_{sec}#pi_{bach}}"}}); + histos.add("QA/after/K1DalitzLS_Signal", "(Signal region) Dalitz plot of like-sign combination of K1(1270)", HistType::kTH2F, {AxisSpec{300, 0.0, 3.0, "#it{M}^{2}_{K_{s}^{0}#pi_{sec}}"}, {300, 0.0, 3.0, "#it{M}^{2}_{#pi_{sec}#pi_{bach}}"}}); + histos.add("QA/after/K1DalitzLS_SBLeft", "(SB left) Dalitz plot of like-sign combination of K1(1270)", HistType::kTH2F, {AxisSpec{300, 0.0, 3.0, "#it{M}^{2}_{K_{s}^{0}#pi_{sec}}"}, {300, 0.0, 3.0, "#it{M}^{2}_{#pi_{sec}#pi_{bach}}"}}); + histos.add("QA/after/K1DalitzLS_SBRight", "(SB right) Dalitz plot of like-sign combination of K1(1270)", HistType::kTH2F, {AxisSpec{300, 0.0, 3.0, "#it{M}^{2}_{K_{s}^{0}#pi_{sec}}"}, {300, 0.0, 3.0, "#it{M}^{2}_{#pi_{sec}#pi_{bach}}"}}); + histos.add("QA/after/K1invmass", "Invariant mass of K1(1270) (US)", HistType::kTH1F, {invMassAxisReso}); + histos.add("QA/after/K1invmassLS", "Invariant mass of K1(1270) (LS)", HistType::kTH1F, {invMassAxisReso}); // Invariant mass - histos.add("hInvmass_K1", "Invariant mass of K1(1270)", HistType::kTHnSparseD, {axisAnti, axisType, centAxis, ptAxis, invMassAxisReso}); - // Mass QA (quick check) - histos.add("k1invmass", "Invariant mass of K1(1270)", HistType::kTH1F, {invMassAxisReso}); - histos.add("k1invmass_Mix", "Invariant mass of K1(1270)", HistType::kTH1F, {invMassAxisReso}); - - // MC - if (doprocessMC) { - histos.add("k1invmass_MC", "Invariant mass of K1(1270)", HistType::kTH1F, {invMassAxisReso}); - histos.add("k1invmass_MC_noK1", "Invariant mass of K1(1270)", HistType::kTH1F, {invMassAxisReso}); - - histos.add("QAMC/trkppionDCAxy", "DCAxy distribution of primary pion candidates", HistType::kTH1F, {dcaxyAxis}); - histos.add("QAMC/trkppionDCAz", "DCAz distribution of primary pion candidates", HistType::kTH1F, {dcaxyAxis}); - histos.add("QAMC/trkppionpT", "pT distribution of primary pion candidates", HistType::kTH1F, {ptAxis}); - histos.add("QAMC/trkppionTPCPID", "TPC PID of primary pion candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); - histos.add("QAMC/trkppionTOFPID", "TOF PID of primary pion candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); - histos.add("QAMC/trkppionTPCTOFPID", "TPC-TOF PID map of primary pion candidates", HistType::kTH2F, {pidQAAxis, pidQAAxis}); - - histos.add("QAMC/trkspionDCAxy", "DCAxy distribution of secondary pion candidates", HistType::kTH1F, {dcaxyAxis}); - histos.add("QAMC/trkspionDCAz", "DCAz distribution of secondary pion candidates", HistType::kTH1F, {dcaxyAxis}); - histos.add("QAMC/trkspionpT", "pT distribution of secondary pion candidates", HistType::kTH1F, {ptAxis}); - histos.add("QAMC/trkspionTPCPID", "TPC PID of secondary pion candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); - histos.add("QAMC/trkspionTOFPID", "TOF PID of secondary pion candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); - histos.add("QAMC/trkspionTPCTOFPID", "TPC-TOF PID map of secondary pion candidates", HistType::kTH2F, {pidQAAxis, pidQAAxis}); - - histos.add("QAMC/trkkaonDCAxy", "DCAxy distribution of kaon candidates", HistType::kTH1F, {dcaxyAxis}); - histos.add("QAMC/trkkaonDCAz", "DCAz distribution of kaon candidates", HistType::kTH1F, {dcaxyAxis}); - histos.add("QAMC/trkkaonpT", "pT distribution of kaon candidates", HistType::kTH1F, {ptAxis}); - histos.add("QAMC/trkkaonTPCPID", "TPC PID of kaon candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); - histos.add("QAMC/trkkaonTOFPID", "TOF PID of kaon candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); - histos.add("QAMC/trkkaonTPCTOFPID", "TPC-TOF PID map of kaon candidates", HistType::kTH2F, {pidQAAxis, pidQAAxis}); - - histos.add("QAMC/K1OA", "Opening angle of K1(1270)", HistType::kTH1F, {AxisSpec{100, 0, 3.14, "Opening angle"}}); - histos.add("QAMC/K1PairAssym", "Pair asymmetry of K1(1270)", HistType::kTH1F, {AxisSpec{100, -1, 1, "Pair asymmetry"}}); - histos.add("QAMC/hInvmassK892_Rho", "Invariant mass of K(892)0 vs Rho(770)", HistType::kTH2F, {invMassAxisK892, invMassAxisRho}); - histos.add("QAMC/hInvmassSecon_PiKa", "Invariant mass of secondary resonance vs pion-kaon", HistType::kTH2F, {invMassAxisK892, invMassAxisK892}); - histos.add("QAMC/hInvmassSecon", "Invariant mass of secondary resonance", HistType::kTH1F, {invMassAxisRho}); - histos.add("QAMC/hpT_Secondary", "pT distribution of secondary resonance", HistType::kTH1F, {ptAxis}); - } + histos.add("hInvmass_K1", "Invariant mass of K1(1270)", HistType::kTHnSparseD, {axisType, centAxis, ptAxis, invMassAxisReso}); + histos.add("hInvmass_Kstar", "Invariant mass of unlike-sign chK(892)", HistType::kTHnSparseD, {centAxis, ptAxis, invMassAxisChk892}); + histos.add("hInvmass_K0s", "Invariant mass of unlike-sign K0s", HistType::kTHnSparseD, {centAxis, ptAxis, invMassAxisK0s}); + + ccdb->setURL(CCDBConfig.cfgURL); + ccdbApi.init("http://alice-ccdb.cern.ch"); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); + // Print output histograms statistics LOG(info) << "Size of the histograms in K1 Analysis Task"; histos.print(); - } + } // init - double massKa = MassKaonCharged; - double massPi = MassPionCharged; - // double massRho770 = MassRho770; - // double massK892 = MassKStar892; - double massRho770 = 0.77526; - double massK892 = 0.892; + const int kCentFT0C = 1; + const int kCentFT0M = 2; + const float kInvalidCentrality = -999.f; - // PDG code - int kPDGRho770 = 113; - int kK1Plus = 10323; + template + float getCentrality(CollisionType const& collision) + { + if (cfgCentEst == kCentFT0C) { + return collision.centFT0C(); + } else if (cfgCentEst == kCentFT0M) { + return collision.centFT0M(); + } else { + return kInvalidCentrality; + } + } + // Track selection template - bool trackCut(const TrackType track) + bool trackCut(TrackType const& track) { - // basic track cuts - if (std::abs(track.pt()) < cMinPtcut) + if (std::abs(track.pt()) < TrackCuts.cfgMinPtcut) return false; - if (std::abs(track.dcaXY()) > cMaxDCArToPVcut) + if (std::abs(track.eta()) > TrackCuts.cfgMaxEtacut) return false; - if (std::abs(track.dcaZ()) > cMaxDCAzToPVcut) + if (track.itsNCls() < TrackCuts.cfgITScluster) return false; - if (track.tpcNClsFound() < cfgTPCcluster) + if (track.tpcNClsFound() < TrackCuts.cfgTPCcluster) return false; - if (cfgHasTOF && !track.hasTOF()) + if (track.tpcCrossedRowsOverFindableCls() < TrackCuts.cfgRatioTPCRowsOverFindableCls) return false; - if (cfgUseITSRefit && !track.passedITSRefit()) + if (track.itsChi2NCl() >= TrackCuts.cfgITSChi2NCl) return false; - if (cfgUseTPCRefit && !track.passedTPCRefit()) + if (track.tpcChi2NCl() >= TrackCuts.cfgTPCChi2NCl) return false; - if (cfgPVContributor && !track.isPVContributor()) + if (TrackCuts.cfgHasITS && !track.hasITS()) return false; - if (cfgPrimaryTrack && !track.isPrimaryTrack()) + if (TrackCuts.cfgHasTPC && !track.hasTPC()) return false; - if (cfgGlobalWoDCATrack && !track.isGlobalTrackWoDCA()) + if (TrackCuts.cfgHasTOF && !track.hasTOF()) return false; - if (cfgGlobalTrack && !track.isGlobalTrack()) + if (TrackCuts.cfgUseITSRefit && !track.passedITSRefit()) return false; - - return true; - } - - // PID selection tools - template - bool selectionPIDPion(const T& candidate) - { - bool tpcPIDPassed{false}, tofPIDPassed{false}; - if (std::abs(candidate.tpcNSigmaPi()) < cMaxTPCnSigmaPion) { - tpcPIDPassed = true; - } else { + if (TrackCuts.cfgUseTPCRefit && !track.passedTPCRefit()) return false; - } - if (candidate.hasTOF()) { - if (std::abs(candidate.tofNSigmaPi()) < cMaxTOFnSigmaPion) { - tofPIDPassed = true; - } - if ((nsigmaCutCombinedPion > 0) && (candidate.tpcNSigmaPi() * candidate.tpcNSigmaPi() + candidate.tofNSigmaPi() * candidate.tofNSigmaPi() < nsigmaCutCombinedPion * nsigmaCutCombinedPion)) { - tofPIDPassed = true; - } + if (TrackCuts.cfgPVContributor && !track.isPVContributor()) + return false; + if (TrackCuts.cfgGlobalWoDCATrack && !track.isGlobalTrackWoDCA()) + return false; + if (TrackCuts.cfgGlobalTrack && !track.isGlobalTrack()) + return false; + if (TrackCuts.cfgPrimaryTrack && !track.isPrimaryTrack()) + return false; + if (TrackCuts.cfgpTdepDCAxyCut) { + // Tuned on the LHC22f anchored MC LHC23d1d on primary pions. 7 Sigmas of the resolution + if (std::abs(track.dcaXY()) > (0.004 + (0.013 / track.pt()))) + return false; } else { - if (!cTOFVeto) { + if (std::abs(track.dcaXY()) > TrackCuts.cfgMaxbDCArToPVcut) return false; - } - tofPIDPassed = true; } - if (tpcPIDPassed && tofPIDPassed) { - return true; + if (TrackCuts.cfgpTdepDCAzCut) { + // Tuned on the LHC22f anchored MC LHC23d1d on primary pions. 7 Sigmas of the resolution + if (std::abs(track.dcaZ()) > (0.004 + (0.013 / track.pt()))) + return false; + } else { + if (std::abs(track.dcaZ()) > TrackCuts.cfgMaxbDCAzToPVcut) + return false; } - return false; + return true; } - template - bool selectionPIDKaon(const T& candidate) + + // PID selection tools + template + bool selectionPIDPion(TrackType const& candidate) { - bool tpcPIDPassed{false}, tofPIDPassed{false}; - if (std::abs(candidate.tpcNSigmaKa()) < cMaxTPCnSigmaKaon) { - tpcPIDPassed = true; - } else { + if (std::abs(candidate.tpcNSigmaPi()) >= PIDCuts.cfgMaxTPCnSigmaPion) return false; - } + if (PIDCuts.cfgTPConly) + return true; + // if (candidate.pt() <= PIDCuts.cfgTOFMinPt) + // return true; + if (candidate.hasTOF()) { - if (std::abs(candidate.tofNSigmaKa()) < cMaxTOFnSigmaKaon) { - tofPIDPassed = true; - } - if ((nsigmaCutCombinedKaon > 0) && (candidate.tpcNSigmaKa() * candidate.tpcNSigmaKa() + candidate.tofNSigmaKa() * candidate.tofNSigmaKa() < nsigmaCutCombinedKaon * nsigmaCutCombinedKaon)) { - tofPIDPassed = true; - } + const bool tofPIDPassed = std::abs(candidate.tofNSigmaPi()) < PIDCuts.cfgMaxTOFnSigmaPion; + const bool combo = (PIDCuts.cfgNsigmaCutCombinedPion > 0) && + (candidate.tpcNSigmaPi() * candidate.tpcNSigmaPi() + + candidate.tofNSigmaPi() * candidate.tofNSigmaPi() < + PIDCuts.cfgNsigmaCutCombinedPion * PIDCuts.cfgNsigmaCutCombinedPion); + return tofPIDPassed || combo; } else { - if (!cTOFVeto) { - return false; - } - tofPIDPassed = true; + return PIDCuts.cfgTOFVeto; } - if (tpcPIDPassed && tofPIDPassed) { - return true; - } - return false; } - template - bool isTrueK1(const T& trk1, const T& trk2, const T2& bTrack) + // selection K0s + template + bool selectionK0s(CollisionType const& collision, K0sType const& candidate) { - if (abs(trk1.pdgCode()) != kPiPlus || abs(trk2.pdgCode()) != kKPlus) - return false; - if (abs(bTrack.pdgCode()) != kPiPlus) - return false; - if (cfgModeK892orRho) { // K892 mode - auto mother1 = trk1.motherId(); - auto mother2 = trk2.motherId(); - if (mother1 != mother2) + auto lDauDCA = std::fabs(candidate.dcaV0daughters()); + auto lDauPosDCAtoPV = std::fabs(candidate.dcapostopv()); + auto lDauNegDCAtoPV = std::fabs(candidate.dcanegtopv()); + auto lPt = candidate.pt(); + auto lRapidity = candidate.yK0Short(); + auto lRadius = candidate.v0radius(); + auto lDCAtoPV = std::fabs(candidate.dcav0topv()); + auto lCPA = candidate.v0cosPA(); + auto lPropTauK0s = candidate.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * MassK0Short; + auto lMk0s = candidate.mK0Short(); + auto lMLambda = candidate.mLambda(); + auto lMALambda = candidate.mAntiLambda(); + + auto checkCommonCuts = [&]() { + if (std::fabs(lDauDCA) > SecondaryCuts.cfgSecondaryDauDCAMax) return false; - if (abs(trk1.motherPDG()) != kK0Star892) + if (std::fabs(lDauPosDCAtoPV) < SecondaryCuts.cfgSecondaryDauPosDCAtoPVMin) return false; - if (abs(bTrack.motherPDG()) != kK1Plus) + if (std::fabs(lDauNegDCAtoPV) < SecondaryCuts.cfgSecondaryDauNegDCAtoPVMin) return false; - auto siblings = bTrack.siblingIds(); - if (siblings[0] != mother1 && siblings[1] != mother1) + if (lPt < SecondaryCuts.cfgSecondaryPtMin) return false; - return true; - } else { // Rho mode - auto mother1 = trk1.motherId(); - auto motherb = bTrack.motherId(); - if (mother1 != motherb) + if (std::fabs(lRapidity) > SecondaryCuts.cfgSecondaryRapidityMax) + return false; + if (lRadius < SecondaryCuts.cfgSecondaryRadiusMin || lRadius > SecondaryCuts.cfgSecondaryRadiusMax) return false; - if (abs(trk1.motherPDG()) != kPDGRho770) + if (std::fabs(lDCAtoPV) > SecondaryCuts.cfgSecondaryDCAtoPVMax) return false; - if (abs(trk2.motherPDG()) != kK1Plus) + if (lCPA < SecondaryCuts.cfgSecondaryCosPAMin) return false; - auto siblings = trk2.siblingIds(); - if (siblings[0] != mother1 && siblings[1] != mother1) + if (lPropTauK0s > SecondaryCuts.cfgSecondaryProperLifetimeMax) + return false; + if (candidate.qtarm() < SecondaryCuts.cfgSecondaryparamArmenterosCut * std::fabs(candidate.alpha())) + return false; + if (std::fabs(lMk0s - MassK0Short) > SecondaryCuts.cfgSecondaryMassWindow) + return false; + if (SecondaryCuts.cfgSecondaryCrossMassHypothesisCut && + ((std::fabs(lMLambda - MassLambda0) < SecondaryCuts.cfgSecondaryCrossMassCutWindow) || (std::fabs(lMALambda - MassLambda0Bar) < SecondaryCuts.cfgSecondaryCrossMassCutWindow))) return false; return true; + }; + + if (SecondaryCuts.cfgReturnFlag) { // For cut study + bool returnFlag = true; + histos.fill(HIST("QA/K0sCutCheck"), 0); + if (lDauDCA > SecondaryCuts.cfgSecondaryDauDCAMax) { + histos.fill(HIST("QA/K0sCutCheck"), 1); + returnFlag = false; + } + if (lDauPosDCAtoPV < SecondaryCuts.cfgSecondaryDauPosDCAtoPVMin) { + histos.fill(HIST("QA/K0sCutCheck"), 2); + returnFlag = false; + } + if (lDauNegDCAtoPV < SecondaryCuts.cfgSecondaryDauNegDCAtoPVMin) { + histos.fill(HIST("QA/K0sCutCheck"), 3); + returnFlag = false; + } + if (lPt < SecondaryCuts.cfgSecondaryPtMin) { + histos.fill(HIST("QA/K0sCutCheck"), 4); + returnFlag = false; + } + if (std::fabs(lRapidity) > SecondaryCuts.cfgSecondaryRapidityMax) { + histos.fill(HIST("QA/K0sCutCheck"), 5); + returnFlag = false; + } + if (lRadius < SecondaryCuts.cfgSecondaryRadiusMin || lRadius > SecondaryCuts.cfgSecondaryRadiusMax) { + histos.fill(HIST("QA/K0sCutCheck"), 6); + returnFlag = false; + } + if (lDCAtoPV > SecondaryCuts.cfgSecondaryDCAtoPVMax) { + histos.fill(HIST("QA/K0sCutCheck"), 7); + returnFlag = false; + } + if (lCPA < SecondaryCuts.cfgSecondaryCosPAMin) { + histos.fill(HIST("QA/K0sCutCheck"), 8); + returnFlag = false; + } + if (lPropTauK0s > SecondaryCuts.cfgSecondaryProperLifetimeMax) { + histos.fill(HIST("QA/K0sCutCheck"), 9); + returnFlag = false; + } + if (candidate.qtarm() < SecondaryCuts.cfgSecondaryparamArmenterosCut * std::fabs(candidate.alpha())) { + histos.fill(HIST("QA/K0sCutCheck"), 10); + returnFlag = false; + } + if (std::fabs(lMk0s - MassK0Short) > SecondaryCuts.cfgSecondaryMassWindow) { + histos.fill(HIST("QA/K0sCutCheck"), 11); + returnFlag = false; + } + if (SecondaryCuts.cfgSecondaryCrossMassHypothesisCut && + ((std::fabs(lMLambda - MassLambda0) < SecondaryCuts.cfgSecondaryCrossMassCutWindow) || (std::fabs(lMALambda - MassLambda0Bar) < SecondaryCuts.cfgSecondaryCrossMassCutWindow))) { + histos.fill(HIST("QA/K0sCutCheck"), 12); + returnFlag = false; + } + return returnFlag; + } else { // normal usage + if (SecondaryCuts.cfgSecondaryRequire) { + return checkCommonCuts(); + } else { + return std::fabs(lMk0s - MassK0Short) <= SecondaryCuts.cfgSecondaryMassWindow; // always apply mass window cut + } } - } + } // selectionK0s - template - bool isTrueK892(const T& trk1, const T& trk2) + K1MassRegion getK1MassRegion(float mass) { - if (abs(trk1.pdgCode()) != kPiPlus || abs(trk2.pdgCode()) != kKPlus) - return false; - auto mother1 = trk1.motherId(); - auto mother2 = trk2.motherId(); - if (mother1 != mother2) - return false; - if (abs(trk1.motherPDG()) != kK0Star892) - return false; - return true; - } + constexpr float SigMin = 1.22f; + constexpr float SigMax = 1.32f; - template - bool isTrueRho(const T& trk1, const T& trk2) - { - if (abs(trk1.pdgCode()) != kPiPlus || abs(trk2.pdgCode()) != kPiPlus) - return false; - auto mother1 = trk1.motherId(); - auto mother2 = trk2.motherId(); - if (mother1 != mother2) - return false; - if (abs(trk1.motherPDG()) != kPDGRho770) - return false; - return true; + constexpr float SBLMin = 1.10f; + constexpr float SBLMax = 1.18f; + + constexpr float SBRMin = 1.36f; + constexpr float SBRMax = 1.44f; + + if (mass > SigMin && mass < SigMax) + return K1MassRegion::Signal; + if (mass > SBLMin && mass < SBLMax) + return K1MassRegion::SBLeft; + if (mass > SBRMin && mass < SBRMax) + return K1MassRegion::SBRight; + + return K1MassRegion::Outside; } - template - void fillHistograms(const CollisionType& collision, const TracksType& dTracks1, const TracksType& dTracks2) + int count = 0; + template + void fillHistograms(const CollisionType& collision, const TracksType& dTracks1, const TracksType& dTracks2, const TracksTypeK0s& dTracks3) { - auto multiplicity = collision.cent(); - TLorentzVector lDecayDaughter1, lDecayDaughter2, lResonanceSecondary, lDecayDaughter_bach, lResonanceK1; - for (auto& [trk1, trk2] : combinations(CombinationsFullIndexPolicy(dTracks2, dTracks2))) { - // Full index policy is needed to consider all possible combinations - if (trk1.index() == trk2.index()) - continue; // We need to run (0,1), (1,0) pairs as well. but same id pairs are not needed. - // Trk1: Pion, Trk2: Kaon - // apply the track cut - if (!trackCut(trk1) || !trackCut(trk2)) - continue; - auto isTrk1hasTOF = trk1.hasTOF(); - auto isTrk2hasTOF = trk2.hasTOF(); - auto trk1pt = trk1.pt(); - auto trk1NSigmaPiTPC = trk1.tpcNSigmaPi(); - auto trk1NSigmaPiTOF = (isTrk1hasTOF) ? trk1.tofNSigmaPi() : -999.; - auto trk2pt = trk2.pt(); - auto trk2NSigmaKaTPC = trk2.tpcNSigmaKa(); - auto trk2NSigmaKaTOF = (isTrk2hasTOF) ? trk2.tofNSigmaKa() : -999.; - // for rho mode - auto trk2NSigmaPiTPC = trk2.tpcNSigmaPi(); - auto trk2NSigmaPiTOF = (isTrk2hasTOF) ? trk2.tofNSigmaPi() : -999.; - - //// PID selections - if (cUseOnlyTOFTrackPi && !isTrk1hasTOF) - continue; - if (cUseOnlyTOFTrackKa && !isTrk2hasTOF) - continue; + using TrackTarget = std::decay_t; - if (cfgModeK892orRho) { // K892 mode - if (!selectionPIDPion(trk1) || !selectionPIDKaon(trk2)) - continue; - } else { // Rho mode - if (!selectionPIDPion(trk1) || !selectionPIDPion(trk2)) - continue; - } + histos.fill(HIST("QA/before/CentDist"), lCentrality); + + LorentzVectorSetXYZM lBachelor_pi, lDecayDaughter_K0s, lDecayDaughter_pi, lResoKstar, lResonanceK1, lDaughterRot, lResonanceRot; + LorentzVectorSetXYZM lPairK0sPiSec, lPairK0sPiBach, lPairPiPi; + + std::vector btrackIndices = {}; + std::vector strackIndices = {}; + std::vector k0sIndices = {}; + std::vector chK892Indices = {}; + + // check the existence of the pairs + if (cfgHasPair && (dTracks1.size() < 1 || dTracks2.size() < 1 || dTracks3.size() < 1)) + return; + + for (const auto& bTrack : dTracks1) { + auto trkbpt = bTrack.pt(); + auto istrkbhasTOF = bTrack.hasTOF(); + auto trkbNSigmaPiTPC = bTrack.tpcNSigmaPi(); + auto trkbNSigmaPiTOF = (istrkbhasTOF) ? bTrack.tofNSigmaPi() : -999.; - //// QA plots after the selection if constexpr (!IsMix) { - // --- PID QA Pion - histos.fill(HIST("QA/trkspionTPCPID"), trk1pt, trk1NSigmaPiTPC); - if (isTrk1hasTOF) { - histos.fill(HIST("QA/trkspionTOFPID"), trk1pt, trk1NSigmaPiTOF); - histos.fill(HIST("QA/trkspionTPCTOFPID"), trk1NSigmaPiTPC, trk1NSigmaPiTOF); - } - histos.fill(HIST("QA/trkspionpT"), trk1pt); - histos.fill(HIST("QA/trkspionDCAxy"), trk1.dcaXY()); - histos.fill(HIST("QA/trkspionDCAz"), trk1.dcaZ()); - - if (cfgModeK892orRho) { // K892 mode - // --- PID QA Kaon - histos.fill(HIST("QA/trkkaonTPCPID"), trk2pt, trk2NSigmaKaTPC); - if (isTrk1hasTOF) { - histos.fill(HIST("QA/trkkaonTOFPID"), trk2pt, trk2NSigmaKaTOF); - histos.fill(HIST("QA/trkkaonTPCTOFPID"), trk2NSigmaKaTPC, trk2NSigmaKaTOF); - } - histos.fill(HIST("QA/trkkaonpT"), trk2pt); - histos.fill(HIST("QA/trkkaonDCAxy"), trk2.dcaXY()); - histos.fill(HIST("QA/trkkaonDCAz"), trk2.dcaZ()); - } else { // Rho mode - // --- PID QA Pion - histos.fill(HIST("QA/trkppionTPCPID"), trk2pt, trk2NSigmaPiTPC); - if (isTrk2hasTOF) { - histos.fill(HIST("QA/trkppionTOFPID"), trk2pt, trk2NSigmaPiTOF); - histos.fill(HIST("QA/trkppionTPCTOFPID"), trk2NSigmaPiTPC, trk2NSigmaPiTOF); + if (cfgFillQAPlots) { + // Bachelor pion QA plots + histos.fill(HIST("QA/before/trkbpionTPCPID"), trkbpt, trkbNSigmaPiTPC); + if (istrkbhasTOF) { + histos.fill(HIST("QA/before/trkbpionTOFPID"), trkbpt, trkbNSigmaPiTOF); + histos.fill(HIST("QA/before/trkbpionTPCTOFPID"), trkbNSigmaPiTPC, trkbNSigmaPiTOF); } - histos.fill(HIST("QA/trkppionpT"), trk2pt); - histos.fill(HIST("QA/trkppionDCAxy"), trk2.dcaXY()); - histos.fill(HIST("QA/trkppionDCAz"), trk2.dcaZ()); + histos.fill(HIST("QA/before/trkbpionpT"), trkbpt); + histos.fill(HIST("QA/before/trkbpionDCAxy"), bTrack.dcaXY()); + histos.fill(HIST("QA/before/trkbpionDCAz"), bTrack.dcaZ()); } } - //// Resonance reconstruction - lDecayDaughter1.SetXYZM(trk1.px(), trk1.py(), trk1.pz(), massPi); - lDecayDaughter2.SetXYZM(trk2.px(), trk2.py(), trk2.pz(), (cfgModeK892orRho) ? massKa : massPi); - lResonanceSecondary = lDecayDaughter1 + lDecayDaughter2; + if (!trackCut(bTrack)) + continue; + if (!selectionPIDPion(bTrack)) + continue; if constexpr (!IsMix) { - histos.fill(HIST("QA/hInvmassSecon"), lResonanceSecondary.M()); + if (cfgFillQAPlots) { + // Bachelor pion QA plots after applying cuts + histos.fill(HIST("QA/after/trkbpionTPCPID"), trkbpt, trkbNSigmaPiTPC); + if (istrkbhasTOF) { + histos.fill(HIST("QA/after/trkbpionTOFPID"), trkbpt, trkbNSigmaPiTOF); + histos.fill(HIST("QA/after/trkbpionTPCTOFPID"), trkbNSigmaPiTPC, trkbNSigmaPiTOF); + } + histos.fill(HIST("QA/after/trkbpionpT"), trkbpt); + histos.fill(HIST("QA/after/trkbpionDCAxy"), bTrack.dcaXY()); + histos.fill(HIST("QA/after/trkbpionDCAz"), bTrack.dcaZ()); + } } + btrackIndices.push_back(bTrack.index()); + } // bTrack + + for (const auto& sTrack : dTracks2) { + auto trkspt = sTrack.pt(); + auto istrkshasTOF = sTrack.hasTOF(); + auto trksNSigmaPiTPC = sTrack.tpcNSigmaPi(); + auto trksNSigmaPiTOF = (istrkshasTOF) ? sTrack.tofNSigmaPi() : -999.; - if constexpr (IsMC) { // MC Check - if (cfgModeK892orRho) { - if (isTrueK892(trk1, trk2)) - histos.fill(HIST("QAMC/hpT_Secondary"), lResonanceSecondary.Pt()); - } else { - if (isTrueRho(trk1, trk2)) - histos.fill(HIST("QAMC/hpT_Secondary"), lResonanceSecondary.Pt()); + if constexpr (!IsMix) { + if (cfgFillQAPlots) { + // Secondary pion QA plots + histos.fill(HIST("QA/before/trkspionTPCPID"), trkspt, trksNSigmaPiTPC); + if (istrkshasTOF) { + histos.fill(HIST("QA/before/trkspionTOFPID"), trkspt, trksNSigmaPiTOF); + histos.fill(HIST("QA/before/trkspionTPCTOFPID"), trksNSigmaPiTPC, trksNSigmaPiTOF); + } + histos.fill(HIST("QA/before/trkspionpT"), trkspt); + histos.fill(HIST("QA/before/trkspionDCAxy"), sTrack.dcaXY()); + histos.fill(HIST("QA/before/trkspionDCAz"), sTrack.dcaZ()); } } - // Mass window cut - double massCut = cfgModeK892orRho ? massK892 : massRho770; - if (std::abs(lResonanceSecondary.M() - massCut) > cSecondaryMasswindow) + if (!trackCut(sTrack)) + continue; + if (!selectionPIDPion(sTrack)) continue; - // bTrack loop for K1 reconstruction - for (auto bTrack : dTracks1) { - if (bTrack.index() == trk1.index() || bTrack.index() == trk2.index()) - continue; - if (!trackCut(bTrack)) - continue; - - // Kaon or Pion - if (cfgModeK892orRho && !selectionPIDPion(bTrack)) - continue; - if (!cfgModeK892orRho && !selectionPIDKaon(bTrack)) - continue; - - // K1 reconstruction - lDecayDaughter_bach.SetXYZM(bTrack.px(), bTrack.py(), bTrack.pz(), cfgModeK892orRho ? massPi : massKa); - lResonanceK1 = lResonanceSecondary + lDecayDaughter_bach; + if constexpr (!IsMix) { + if (cfgFillQAPlots) { + // Secondary pion QA plots after applying cuts + histos.fill(HIST("QA/after/trkspionTPCPID"), trkspt, trksNSigmaPiTPC); + if (istrkshasTOF) { + histos.fill(HIST("QA/after/trkspionTOFPID"), trkspt, trksNSigmaPiTOF); + histos.fill(HIST("QA/after/trkspionTPCTOFPID"), trksNSigmaPiTPC, trksNSigmaPiTOF); + } + histos.fill(HIST("QA/after/trkspionpT"), trkspt); + histos.fill(HIST("QA/after/trkspionDCAxy"), sTrack.dcaXY()); + histos.fill(HIST("QA/after/trkspionDCAz"), sTrack.dcaZ()); + } + } + strackIndices.push_back(sTrack.index()); + } // sTrack + + for (const auto& k0sCand : dTracks3) { + + auto posDauTrack = k0sCand.template posTrack_as(); + auto negDauTrack = k0sCand.template negTrack_as(); + + /// Daughters + // Positve pion + auto trkppt = posDauTrack.pt(); + auto istrkphasTOF = posDauTrack.hasTOF(); + auto trkpNSigmaPiTPC = posDauTrack.tpcNSigmaPi(); + auto trkpNSigmaPiTOF = (istrkphasTOF) ? posDauTrack.tofNSigmaPi() : -999.; + // Negative pion + auto trknpt = negDauTrack.pt(); + auto istrknhasTOF = negDauTrack.hasTOF(); + auto trknNSigmaPiTPC = negDauTrack.tpcNSigmaPi(); + auto trknNSigmaPiTOF = (istrknhasTOF) ? negDauTrack.tofNSigmaPi() : -999.; + + /// K0s + auto trkkDauDCA = k0sCand.dcaV0daughters(); + auto trkky = k0sCand.yK0Short(); + auto trkkDCAtoPV = k0sCand.dcav0topv(); + auto trkkCPA = k0sCand.v0cosPA(); + auto trkkPropTau = k0sCand.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * MassK0Short; + auto trkkMass = k0sCand.mK0Short(); + auto trkkDauDCAPostoPV = k0sCand.dcapostopv(); + auto trkkDauDCANegtoPV = k0sCand.dcanegtopv(); + auto trkkpt = k0sCand.pt(); + auto trkkRadius = k0sCand.v0radius(); - // Cuts - if (lResonanceK1.Rapidity() > cK1MaxRap || lResonanceK1.Rapidity() < cK1MinRap) - continue; + if constexpr (!IsMix) { + if (cfgFillQAPlots) { + // Seconddary QA plots + histos.fill(HIST("QA/before/trkppionTPCPID"), trkppt, trkpNSigmaPiTPC); + if (istrkphasTOF) { + histos.fill(HIST("QA/before/trkppionTOFPID"), trkppt, trkpNSigmaPiTOF); + histos.fill(HIST("QA/before/trkppionTPCTOFPID"), trkpNSigmaPiTPC, trkpNSigmaPiTOF); + } + histos.fill(HIST("QA/before/trkppionpT"), trkppt); + histos.fill(HIST("QA/before/trkppionDCAxy"), posDauTrack.dcaXY()); + histos.fill(HIST("QA/before/trkppionDCAz"), posDauTrack.dcaZ()); + + histos.fill(HIST("QA/before/trknpionTPCPID"), trknpt, trknNSigmaPiTPC); + if (istrknhasTOF) { + histos.fill(HIST("QA/before/trknpionTOFPID"), trknpt, trknNSigmaPiTOF); + histos.fill(HIST("QA/before/trknpionTPCTOFPID"), trknNSigmaPiTPC, trknNSigmaPiTOF); + } + histos.fill(HIST("QA/before/trknpionpT"), trknpt); + histos.fill(HIST("QA/before/trknpionDCAxy"), negDauTrack.dcaXY()); + histos.fill(HIST("QA/before/trknpionDCAz"), negDauTrack.dcaZ()); + + histos.fill(HIST("QA/before/hDauDCASecondary"), trkkDauDCA); + histos.fill(HIST("QA/before/hDauPosDCAtoPVSecondary"), trkkDauDCAPostoPV); + histos.fill(HIST("QA/before/hDauNegDCAtoPVSecondary"), trkkDauDCANegtoPV); + + histos.fill(HIST("QA/before/hpT_Secondary"), trkkpt); + histos.fill(HIST("QA/before/hy_Secondary"), trkky); + histos.fill(HIST("QA/before/hRadiusSecondary"), trkkRadius); + histos.fill(HIST("QA/before/hDCAtoPVSecondary"), trkkDCAtoPV); + histos.fill(HIST("QA/before/hCPASecondary"), trkkCPA); + histos.fill(HIST("QA/before/hPropTauSecondary"), trkkPropTau); + histos.fill(HIST("QA/before/hArmSecondary"), k0sCand.alpha(), k0sCand.qtarm()); + histos.fill(HIST("QA/before/hInvmassSecondary"), trkkMass); + } + } - auto lK1Angle = lResonanceSecondary.Angle(lDecayDaughter_bach.Vect()); - auto lPairAsym = (lResonanceSecondary.E() - lDecayDaughter_bach.E()) / (lResonanceSecondary.E() + lDecayDaughter_bach.E()); + if (!SecondaryCuts.cfgByPassDauPIDSelection && !selectionPIDPion(posDauTrack)) + continue; + if (!SecondaryCuts.cfgByPassDauPIDSelection && !selectionPIDPion(negDauTrack)) + continue; + if (!selectionK0s(collision, k0sCand)) + continue; - TLorentzVector temp13 = lDecayDaughter1 + lDecayDaughter_bach; - TLorentzVector temp23 = lDecayDaughter2 + lDecayDaughter_bach; + if constexpr (!IsMix) { + if (cfgFillQAPlots) { + // Seconddary QA plots after applying cuts - // QA histograms - if constexpr (!IsMix) { - histos.fill(HIST("QA/K1OA"), lK1Angle); - histos.fill(HIST("QA/K1PairAssym"), lPairAsym); - if (cfgModeK892orRho) { - histos.fill(HIST("QA/hInvmassK892_Rho"), lResonanceSecondary.M(), temp13.M()); - } else { - histos.fill(HIST("QA/hInvmassK892_Rho"), temp13.M(), lResonanceSecondary.M()); + histos.fill(HIST("QA/after/trkppionTPCPID"), trkppt, trkpNSigmaPiTPC); + if (istrkphasTOF) { + histos.fill(HIST("QA/after/trkppionTOFPID"), trkppt, trkpNSigmaPiTOF); + histos.fill(HIST("QA/after/trkppionTPCTOFPID"), trkpNSigmaPiTPC, trkpNSigmaPiTOF); + } + histos.fill(HIST("QA/after/trkppionpT"), trkppt); + histos.fill(HIST("QA/after/trkppionDCAxy"), posDauTrack.dcaXY()); + histos.fill(HIST("QA/after/trkppionDCAz"), posDauTrack.dcaZ()); + + histos.fill(HIST("QA/after/trknpionTPCPID"), trknpt, trknNSigmaPiTPC); + if (istrknhasTOF) { + histos.fill(HIST("QA/after/trknpionTOFPID"), trknpt, trknNSigmaPiTOF); + histos.fill(HIST("QA/after/trknpionTPCTOFPID"), trknNSigmaPiTPC, trknNSigmaPiTOF); } - histos.fill(HIST("QA/hInvmassSecon_PiKa"), lResonanceSecondary.M(), temp23.M()); - histos.fill(HIST("QA/hpT_Secondary"), lResonanceSecondary.Pt()); + histos.fill(HIST("QA/after/trknpionpT"), trknpt); + histos.fill(HIST("QA/after/trknpionDCAxy"), negDauTrack.dcaXY()); + histos.fill(HIST("QA/after/trknpionDCAz"), negDauTrack.dcaZ()); + + histos.fill(HIST("QA/after/hDauDCASecondary"), trkkDauDCA); + histos.fill(HIST("QA/after/hDauPosDCAtoPVSecondary"), trkkDauDCAPostoPV); + histos.fill(HIST("QA/after/hDauNegDCAtoPVSecondary"), trkkDauDCANegtoPV); + + histos.fill(HIST("QA/after/hpT_Secondary"), trkkpt); + histos.fill(HIST("QA/after/hy_Secondary"), trkky); + histos.fill(HIST("QA/after/hRadiusSecondary"), trkkRadius); + histos.fill(HIST("QA/after/hDCAtoPVSecondary"), trkkDCAtoPV); + histos.fill(HIST("QA/after/hCPASecondary"), trkkCPA); + histos.fill(HIST("QA/after/hPropTauSecondary"), trkkPropTau); + histos.fill(HIST("QA/after/hArmSecondary"), k0sCand.alpha(), k0sCand.qtarm()); + histos.fill(HIST("QA/after/hInvmassSecondary"), trkkMass); } + histos.fill(HIST("hInvmass_K0s"), lCentrality, trkkpt, trkkMass); + } + k0sIndices.push_back(k0sCand.index()); + } // K0s - // Selection cuts - if (temp13.M() < cMinAnotherSecondaryMassCut || temp13.M() > cMaxAnotherSecondaryMassCut) - continue; - if (temp23.M() < cMinPiKaMassCut || temp23.M() > cMaxPiKaMassCut) - continue; - if (lK1Angle < cMinAngle || lK1Angle > cMaxAngle) - continue; - if (lPairAsym < cMinPairAsym || lPairAsym > cMaxPairAsym) + for (const auto& btrackIndex : btrackIndices) { + auto bTrack = dTracks1.rawIteratorAt(btrackIndex); + for (const auto& strackIndex : strackIndices) { + auto sTrack = dTracks2.rawIteratorAt(strackIndex); + + if (bTrack.index() == sTrack.index()) continue; - // QA histograms after the cuts - if constexpr (!IsMix) { - histos.fill(HIST("QAcut/K1OA"), lK1Angle); - histos.fill(HIST("QAcut/K1PairAssym"), lPairAsym); - if (cfgModeK892orRho) { - histos.fill(HIST("QAcut/hInvmassK892_Rho"), lResonanceSecondary.M(), temp13.M()); - } else { - histos.fill(HIST("QAcut/hInvmassK892_Rho"), temp13.M(), lResonanceSecondary.M()); + for (const auto& k0sIndex : k0sIndices) { + auto k0sCand = dTracks3.rawIteratorAt(k0sIndex); + + auto posDauTrack = k0sCand.template posTrack_as(); + auto negDauTrack = k0sCand.template negTrack_as(); + + if (bTrack.index() == posDauTrack.index() || bTrack.index() == negDauTrack.index()) + continue; + if (sTrack.index() == posDauTrack.index() || sTrack.index() == negDauTrack.index()) + continue; + + lBachelor_pi = LorentzVectorSetXYZM(bTrack.px(), bTrack.py(), bTrack.pz(), MassPionCharged); + lDecayDaughter_pi = LorentzVectorSetXYZM(sTrack.px(), sTrack.py(), sTrack.pz(), MassPionCharged); + lDecayDaughter_K0s = LorentzVectorSetXYZM(k0sCand.px(), k0sCand.py(), k0sCand.pz(), MassK0Short); + lResoKstar = lDecayDaughter_pi + lDecayDaughter_K0s; + lResonanceK1 = lResoKstar + lBachelor_pi; + + // QA plots for Kstar + if constexpr (!IsMix) { + if (cfgFillQAPlots) { + histos.fill(HIST("QA/before/hpT_Kstar"), lResoKstar.Pt()); + histos.fill(HIST("QA/before/hy_Kstar"), lResoKstar.Rapidity()); + histos.fill(HIST("QA/before/kstarinvmass"), lResoKstar.M()); + } } - histos.fill(HIST("QAcut/hInvmassSecon_PiKa"), lResonanceSecondary.M(), temp23.M()); - histos.fill(HIST("QAcut/hInvmassSecon"), lResonanceSecondary.M()); - histos.fill(HIST("QAcut/hpT_Secondary"), lResonanceSecondary.Pt()); - } - if constexpr (!IsMix) { - unsigned int typeK1 = bTrack.sign() > 0 ? binType::kK1P : binType::kK1N; - unsigned int typeNormal = cfgModeK892orRho ? (trk1.sign() < 0 ? binAnti::kNormal : binAnti::kAnti) : binAnti::kNormal; - histos.fill(HIST("k1invmass"), lResonanceK1.M()); - histos.fill(HIST("hInvmass_K1"), typeNormal, typeK1, multiplicity, lResonanceK1.Pt(), lResonanceK1.M()); - - if constexpr (IsMC) { - if (isTrueK1(trk1, trk2, bTrack)) { - typeK1 = bTrack.sign() > 0 ? binType::kK1P_Rec : binType::kK1N_Rec; - histos.fill(HIST("hInvmass_K1"), typeNormal, typeK1, multiplicity, lResonanceK1.Pt(), lResonanceK1.M()); - histos.fill(HIST("k1invmass_MC"), lResonanceK1.M()); - histos.fill(HIST("QAMC/K1OA"), lK1Angle); - histos.fill(HIST("QAMC/K1PairAssym"), lPairAsym); - if (cfgModeK892orRho) { - histos.fill(HIST("QAMC/hInvmassK892_Rho"), lResonanceSecondary.M(), temp13.M()); + if (lResoKstar.Rapidity() > KstarCuts.cfgKstarMaxRap || lResoKstar.Rapidity() < KstarCuts.cfgKstarMinRap) + continue; + if (lResoKstar.Pt() < KstarCuts.cfgKstarMinPt) + continue; + if (std::fabs(lResoKstar.M() - MassKPlusStar892) > KstarCuts.cfgKstarMassWindow) + continue; + + if constexpr (!IsMix) { + if (cfgFillQAPlots) { + histos.fill(HIST("QA/after/hpT_Kstar"), lResoKstar.Pt()); + histos.fill(HIST("QA/after/hy_Kstar"), lResoKstar.Rapidity()); + histos.fill(HIST("QA/after/kstarinvmass"), lResoKstar.M()); + } + histos.fill(HIST("hInvmass_Kstar"), lCentrality, lResoKstar.Pt(), lResoKstar.M()); + } // IsMix + + lPairK0sPiSec = lDecayDaughter_K0s + lDecayDaughter_pi; + lPairK0sPiBach = lDecayDaughter_K0s + lBachelor_pi; + lPairPiPi = lDecayDaughter_pi + lBachelor_pi; + + float m2K0sPiSec = lPairK0sPiSec.M2(); + // float m2K0sPiBach = lPairK0sPiBach.M2(); + float m2PiPi = lPairPiPi.M2(); + + // QA plots for K1 + if constexpr (!IsMix) { + if (cfgFillQAPlots) { + histos.fill(HIST("QA/before/hpT_K1"), lResonanceK1.Pt()); + histos.fill(HIST("QA/before/hy_K1"), lResonanceK1.Rapidity()); + if (bTrack.sign() * sTrack.sign() < 0) { + histos.fill(HIST("QA/before/K1invmass"), lResonanceK1.M()); + histos.fill(HIST("QA/before/K1DalitzOS"), m2K0sPiSec, m2PiPi); } else { - histos.fill(HIST("QAMC/hInvmassK892_Rho"), temp13.M(), lResonanceSecondary.M()); - } - histos.fill(HIST("QAMC/hInvmassSecon_PiKa"), lResonanceSecondary.M(), temp23.M()); - histos.fill(HIST("QAMC/hInvmassSecon"), lResonanceSecondary.M()); - histos.fill(HIST("QAMC/hpT_Secondary"), lResonanceSecondary.Pt()); - - // --- PID QA Pion - histos.fill(HIST("QAMC/trkspionTPCPID"), trk1pt, trk1NSigmaPiTPC); - if (isTrk1hasTOF) { - histos.fill(HIST("QAMC/trkspionTOFPID"), trk1pt, trk1NSigmaPiTOF); - histos.fill(HIST("QAMC/trkspionTPCTOFPID"), trk1NSigmaPiTPC, trk1NSigmaPiTOF); + histos.fill(HIST("QA/before/K1invmassLS"), lResonanceK1.M()); + histos.fill(HIST("QA/before/K1DalitzLS"), m2K0sPiSec, m2PiPi); } - histos.fill(HIST("QAMC/trkspionpT"), trk1pt); - histos.fill(HIST("QAMC/trkspionDCAxy"), trk1.dcaXY()); - histos.fill(HIST("QAMC/trkspionDCAz"), trk1.dcaZ()); - - if (cfgModeK892orRho) { // K892 mode - // --- PID QA Kaon - histos.fill(HIST("QAMC/trkkaonTPCPID"), trk2pt, trk2NSigmaKaTPC); - if (isTrk1hasTOF) { - histos.fill(HIST("QAMC/trkkaonTOFPID"), trk2pt, trk2NSigmaKaTOF); - histos.fill(HIST("QAMC/trkkaonTPCTOFPID"), trk2NSigmaKaTPC, trk2NSigmaKaTOF); + } + } // IsMix + + if (lResonanceK1.Rapidity() > K1Cuts.cfgK1MaxRap || lResonanceK1.Rapidity() < K1Cuts.cfgK1MinRap) + continue; + if (lResonanceK1.Pt() < K1Cuts.cfgK1MinPt) + continue; + if (lPairPiPi.Pt() < cfgPiPiMinPt) + continue; + + auto k1Region = getK1MassRegion(lResonanceK1.M()); + + if constexpr (!IsMix) { + if (cfgFillQAPlots) { + histos.fill(HIST("QA/after/hpT_K1"), lResonanceK1.Pt()); + histos.fill(HIST("QA/after/hy_K1"), lResonanceK1.Rapidity()); + if (bTrack.sign() * sTrack.sign() < 0) { + histos.fill(HIST("QA/after/K1invmass"), lResonanceK1.M()); + // histos.fill(HIST("QA/after/K1DalitzOS"), m2K0sPiSec, m2PiPi); + if (k1Region == K1MassRegion::Signal) { + histos.fill(HIST("QA/after/K1DalitzOS_Signal"), m2K0sPiSec, m2PiPi); + } else if (k1Region == K1MassRegion::SBLeft) { + histos.fill(HIST("QA/after/K1DalitzOS_SBLeft"), m2K0sPiSec, m2PiPi); + } else if (k1Region == K1MassRegion::SBRight) { + histos.fill(HIST("QA/after/K1DalitzOS_SBRight"), m2K0sPiSec, m2PiPi); } - histos.fill(HIST("QAMC/trkkaonpT"), trk2pt); - histos.fill(HIST("QAMC/trkkaonDCAxy"), trk2.dcaXY()); - histos.fill(HIST("QAMC/trkkaonDCAz"), trk2.dcaZ()); - } else { // Rho mode - // --- PID QA Pion - histos.fill(HIST("QAMC/trkppionTPCPID"), trk2pt, trk2NSigmaPiTPC); - if (isTrk2hasTOF) { - histos.fill(HIST("QAMC/trkppionTOFPID"), trk2pt, trk2NSigmaPiTOF); - histos.fill(HIST("QAMC/trkppionTPCTOFPID"), trk2NSigmaPiTPC, trk2NSigmaPiTOF); + } else { + histos.fill(HIST("QA/after/K1invmassLS"), lResonanceK1.M()); + // histos.fill(HIST("QA/after/K1DalitzLS"), m2K0sPiSec, m2PiPi); + if (k1Region == K1MassRegion::Signal) { + histos.fill(HIST("QA/after/K1DalitzLS_Signal"), m2K0sPiSec, m2PiPi); + } else if (k1Region == K1MassRegion::SBLeft) { + histos.fill(HIST("QA/after/K1DalitzLS_SBLeft"), m2K0sPiSec, m2PiPi); + } else if (k1Region == K1MassRegion::SBRight) { + histos.fill(HIST("QA/after/K1DalitzLS_SBRight"), m2K0sPiSec, m2PiPi); } - histos.fill(HIST("QAMC/trkppionpT"), trk2pt); - histos.fill(HIST("QAMC/trkppionDCAxy"), trk2.dcaXY()); - histos.fill(HIST("QAMC/trkppionDCAz"), trk2.dcaZ()); } + } + + if (bTrack.sign() * sTrack.sign() < 0) { + // bTrack sign minus for particle, plus for anti-particle + unsigned int typeK1 = bTrack.sign() < 0 ? BinType::kK1P : BinType::kK1A; + histos.fill(HIST("hInvmass_K1"), typeK1, lCentrality, lResonanceK1.Pt(), lResonanceK1.M()); } else { - histos.fill(HIST("k1invmass_MC_noK1"), lResonanceK1.M()); + unsigned int typeK1 = bTrack.sign() < 0 ? BinType::kK1P_Like : BinType::kK1A_Like; + histos.fill(HIST("hInvmass_K1"), typeK1, lCentrality, lResonanceK1.Pt(), lResonanceK1.M()); } - } // MC - } else { // Mixed event handling - unsigned int typeK1 = bTrack.sign() > 0 ? binType::kK1P_Mix : binType::kK1N_Mix; - unsigned int typeNormal = cfgModeK892orRho ? (trk1.sign() < 0 ? binAnti::kNormal : binAnti::kAnti) : binAnti::kNormal; - histos.fill(HIST("hInvmass_K1"), typeNormal, typeK1, multiplicity, lResonanceK1.Pt(), lResonanceK1.M()); - histos.fill(HIST("k1invmass_Mix"), lResonanceK1.M()); - } - } // bTrack - } - } - void processData(aod::ResoCollision& collision, - aod::ResoTracks const& resotracks) - { - fillHistograms(collision, resotracks, resotracks); - } - PROCESS_SWITCH(k1analysis, processData, "Process Event for data without Partitioning", true); + if (BkgEstimationConfig.cfgFillRotBkg) { + for (int i = 0; i < BkgEstimationConfig.cfgNrotBkg; i++) { + auto lRotAngle = BkgEstimationConfig.cfgMinRot + i * ((BkgEstimationConfig.cfgMaxRot - BkgEstimationConfig.cfgMinRot) / (BkgEstimationConfig.cfgNrotBkg - 1)); + if (cfgFillQAPlots) { + histos.fill(HIST("QA/RotBkg/hRotBkg"), lRotAngle); + } + if (BkgEstimationConfig.cfgRotPion) { + lDaughterRot = lBachelor_pi; + ROOT::Math::RotationZ rot(lRotAngle); + auto p3 = rot * lDaughterRot.Vect(); + lDaughterRot = LorentzVectorSetXYZM(p3.X(), p3.Y(), p3.Z(), lDaughterRot.M()); + lResonanceRot = lDaughterRot + lResoKstar; + } else { + lDaughterRot = lResoKstar; + ROOT::Math::RotationZ rot(lRotAngle); + auto p3 = rot * lDaughterRot; + lDaughterRot = LorentzVectorSetXYZM(p3.X(), p3.Y(), p3.Z(), lDaughterRot.M()); + lResonanceRot = lBachelor_pi + lDaughterRot; + } + unsigned int typeK1 = bTrack.sign() < 0 ? BinType::kK1P_Rot : BinType::kK1A_Rot; + histos.fill(HIST("hInvmass_K1"), typeK1, lCentrality, lResonanceRot.Pt(), lResonanceRot.M()); - void processMC(aod::ResoCollision& collision, - soa::Join const& resotracks) - { - fillHistograms(collision, resotracks, resotracks); - } - PROCESS_SWITCH(k1analysis, processMC, "Process Event for MC", false); + } // NrotBkg + } // cfgFillRotBkg + } // IsMix + } // k0sIndex + } // strackIndex + } // btrackIndex + + count++; - void processMCTrue(ResoMCCols::iterator const& collision, aod::ResoMCParents& resoParents) + } // fillHistograms + + void processData(EventCandidates::iterator const& collision, + TrackCandidates const& tracks, + V0Candidates const& v0s, + aod::BCsWithTimestamps const&) { - auto multiplicity = collision.cent(); - for (auto& part : resoParents) { // loop over all pre-filtered MC particles - if (abs(part.pdgCode()) != kK1Plus) // K892(0) - continue; - if (abs(part.y()) > 0.5) { // rapidity cut - continue; - } - bool pass1 = false; - bool pass2 = false; - if (cfgModeK892orRho) { - if (abs(part.daughterPDG1()) == 313 || abs(part.daughterPDG2()) == 313) { // At least one decay to K892 - pass2 = true; - } - if (abs(part.daughterPDG1()) == kPiPlus || abs(part.daughterPDG2()) == kPiPlus) { // At least one decay to Pion - pass1 = true; - } - if (!pass1 || !pass2) // If we have both decay products - continue; - } else { - if (abs(part.daughterPDG1()) == kPDGRho770 || abs(part.daughterPDG2()) == kPDGRho770) { // At least one decay to Rho - pass2 = true; - } - if (abs(part.daughterPDG1()) == kKPlus || abs(part.daughterPDG2()) == kKPlus) { // At least one decay to Kaon - pass1 = true; - } - if (!pass1 || !pass2) // If we have both decay products - continue; - } - auto typeNormal = part.pdgCode() > 0 ? binAnti::kNormal : binAnti::kAnti; - if (collision.isVtxIn10()) // INEL10 - { - auto typeK1 = part.pdgCode() > 0 ? binType::kK1P_GenINEL10 : binType::kK1N_GenINEL10; - histos.fill(HIST("hInvmass_K1"), typeNormal, typeK1, multiplicity, part.pt(), 1); - } - if (collision.isVtxIn10() && collision.isInSel8()) // INEL>10, vtx10 - { - auto typeK1 = part.pdgCode() > 0 ? binType::kK1P_GenINELgt10 : binType::kK1N_GenINELgt10; - histos.fill(HIST("hInvmass_K1"), typeNormal, typeK1, multiplicity, part.pt(), 1); - } - if (collision.isVtxIn10() && collision.isTriggerTVX()) // vtx10, TriggerTVX - { - auto typeK1 = part.pdgCode() > 0 ? binType::kK1P_GenTrig10 : binType::kK1N_GenTrig10; - histos.fill(HIST("hInvmass_K1"), typeNormal, typeK1, multiplicity, part.pt(), 1); - } - if (collision.isInAfterAllCuts()) // after all event selection - { - auto typeK1 = part.pdgCode() > 0 ? binType::kK1P_GenEvtSel : binType::kK1N_GenEvtSel; - histos.fill(HIST("hInvmass_K1"), typeNormal, typeK1, multiplicity, part.pt(), 1); - } + if (!colCuts.isSelected(collision)) // Default event selection + return; + if (EventCuts.cfgEvtUseRCTFlagChecker && !rctChecker(collision)) { + return; } + lCentrality = getCentrality(collision); + if (lCentrality < EventCuts.cfgEventCentralityMin || lCentrality > EventCuts.cfgEventCentralityMax) + return; + if (!collision.isInelGt0()) + return; + colCuts.fillQA(collision); + + fillHistograms(collision, tracks, tracks, v0s); } - PROCESS_SWITCH(k1analysis, processMCTrue, "Process Event for MC", false); - - // Processing Event Mixing - using BinningTypeVtxZT0M = ColumnBinningPolicy; - void processME(o2::aod::ResoCollisions& collisions, aod::ResoTracks const& resotracks) - { - auto tracksTuple = std::make_tuple(resotracks); - BinningTypeVtxZT0M colBinning{{CfgVtxBins, CfgMultBins}, true}; - SameKindPair pairs{colBinning, nEvtMixing, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip + PROCESS_SWITCH(K1analysis, processData, "Process Event for data without Partitioning", true); - for (auto& [collision1, tracks1, collision2, tracks2] : pairs) { - fillHistograms(collision1, tracks1, tracks2); - } - }; - PROCESS_SWITCH(k1analysis, processME, "Process EventMixing light without partition", false); -}; +}; // struct WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"lf-k1analysis"})}; + return WorkflowSpec{adaptAnalysisTask(cfgc)}; } From 08b76525a7dd296a1cc262a081590b810fe13fad Mon Sep 17 00:00:00 2001 From: alicja-pp <101565842+alicja-pp@users.noreply.github.com> Date: Mon, 16 Mar 2026 16:25:36 +0100 Subject: [PATCH 291/347] [PWGCF] FemtoUniverse: Correct getting PDG of particle's mother (#15411) --- .../TableProducer/femtoUniverseProducerTask.cxx | 16 +++++++++------- .../femtoUniversePairTaskTrackV0Extended.cxx | 8 +++++--- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx b/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx index a9b94fe4b0a..af0370625ca 100644 --- a/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx +++ b/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx @@ -881,12 +881,14 @@ struct FemtoUniverseProducerTask { template int32_t getMotherPDG(ParticleType particle) { - auto motherparticlesMC = particle.template mothers_as(); - if (!motherparticlesMC.empty()) { + if (particle.isPhysicalPrimary()) { + return 0; + } else if (particle.has_mothers()) { + auto motherparticlesMC = particle.template mothers_as(); auto motherparticleMC = motherparticlesMC.front(); - return particle.isPhysicalPrimary() ? 0 : motherparticleMC.pdgCode(); + return motherparticleMC.pdgCode(); } else { - return 9999; + return 999; } } @@ -926,7 +928,7 @@ struct FemtoUniverseProducerTask { outputPartsMCLabels(outputPartsMC.lastIndex()); } else { outputPartsMCLabels(-1); - outputDebugPartsMC(9999); + outputDebugPartsMC(-999); } } @@ -2169,7 +2171,7 @@ struct FemtoUniverseProducerTask { // aligned, so that they can be joined in the task. if constexpr (transientLabels) { outputPartsMCLabels(-1); - outputDebugPartsMC(9999); + outputDebugPartsMC(-999); } } if constexpr (resolveDaughs) { @@ -2214,7 +2216,7 @@ struct FemtoUniverseProducerTask { // aligned, so that they can be joined in the task. if constexpr (transientLabels) { outputPartsMCLabels(-1); - outputDebugPartsMC(9999); + outputDebugPartsMC(-999); } } } diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx index 5b55784f63f..ea63c9cc86b 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx @@ -163,6 +163,7 @@ struct FemtoUniversePairTaskTrackV0Extended { Configurable confEtaBins{"confEtaBins", 29, "Number of eta bins in deta dphi"}; ConfigurableAxis confmTBins3D{"confmTBins3D", {VARIABLE_WIDTH, 1.02f, 1.14f, 1.20f, 1.26f, 1.38f, 1.56f, 1.86f, 4.50f}, "mT Binning for the 3Dimensional plot: k* vs multiplicity vs mT (set <> to true in order to use)"}; ConfigurableAxis confMultBins3D{"confMultBins3D", {VARIABLE_WIDTH, 0.0f, 20.0f, 30.0f, 40.0f, 99999.0f}, "multiplicity Binning for the 3Dimensional plot: k* vs multiplicity vs mT (set <> to true in order to use)"}; + ConfigurableAxis confMotherPDGBins{"confMotherPDGBins", {8001, -4000, 4000}, "Binning for the mothers' PDG code in pair fractions histogram"}; struct : o2::framework::ConfigurableGroup { Configurable confIsCPR{"confIsCPR", true, "Close Pair Rejection"}; @@ -330,7 +331,7 @@ struct FemtoUniversePairTaskTrackV0Extended { registryMCtruth.add("minus/MCtruthPrPt", "MC truth protons;#it{p}_{T} (GeV/c)", {HistType::kTH1F, {{500, 0, 5}}}); if (doprocessPairFractionsMCTruthV0 || doprocessPairFractionsMCTruth) { - registryMCtruth.add("mothersTruth/motherParticle", "pair fractions;part1 mother PDG;part2 mother PDG", {HistType::kTH2F, {{8001, -4000, 4000}, {8001, -4000, 4000}}}); + registryMCtruth.add("mothersTruth/motherParticle", "pair fractions;part1 mother PDG;part2 mother PDG", {HistType::kTH2F, {confMotherPDGBins, confMotherPDGBins}}); } // MC reco @@ -356,8 +357,8 @@ struct FemtoUniversePairTaskTrackV0Extended { registryMCreco.add("minus/MCrecoPrPt", "MC reco protons;#it{p}_{T} (GeV/c)", {HistType::kTH1F, {{500, 0, 5}}}); if (doprocessPairFractions || doprocessPairFractionsV0) { - registryMCreco.add("mothersReco/motherParticle", "pair fractions;part1 mother PDG;part2 mother PDG", {HistType::kTH2F, {{8001, -4000, 4000}, {8001, -4000, 4000}}}); - registryMCreco.add("mothersReco/motherParticlePDGCheck", "pair fractions;part1 mother PDG;part2 mother PDG", {HistType::kTH2F, {{8001, -4000, 4000}, {8001, -4000, 4000}}}); + registryMCreco.add("mothersReco/motherParticle", "pair fractions;part1 mother PDG;part2 mother PDG", {HistType::kTH2F, {confMotherPDGBins, confMotherPDGBins}}); + registryMCreco.add("mothersReco/motherParticlePDGCheck", "pair fractions;part1 mother PDG;part2 mother PDG", {HistType::kTH2F, {confMotherPDGBins, confMotherPDGBins}}); } sameEventCont.init(&resultRegistry, confkstarBins, confMultBins, confkTBins, confmTBins, confMultBins3D, confmTBins3D, confEtaBins, confPhiBins, confIsMC, confUse3D); sameEventCont.setPDGCodes(ConfTrkSelection.confTrkPDGCodePartOne, ConfV0Selection.confV0PDGCodePartTwo); @@ -1464,6 +1465,7 @@ struct FemtoUniversePairTaskTrackV0Extended { continue; if ((ConfV0Selection.confV0Type2 == 0 && mcParticle2.pdgMCTruth() != kLambda0) || (ConfV0Selection.confV0Type2 == 1 && mcParticle2.pdgMCTruth() != kLambda0Bar)) continue; + registryMCreco.fill(HIST("mothersReco/motherParticlePDGCheck"), p1.motherPDG(), p2.motherPDG()); } }; From 5c157398013deb4eeca11d0d79d5bf0b973e422b Mon Sep 17 00:00:00 2001 From: Chuntai <48704924+wuctlby@users.noreply.github.com> Date: Mon, 16 Mar 2026 17:29:38 +0100 Subject: [PATCH 292/347] [PWGHF] replace eta selection with rapidity selection (#15334) Co-authored-by: ALICE Action Bot --- .../derivedDataCreatorCorrelationsReduced.cxx | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/PWGHF/HFC/TableProducer/derivedDataCreatorCorrelationsReduced.cxx b/PWGHF/HFC/TableProducer/derivedDataCreatorCorrelationsReduced.cxx index c8b4ea6c71a..9ffe580fcf5 100644 --- a/PWGHF/HFC/TableProducer/derivedDataCreatorCorrelationsReduced.cxx +++ b/PWGHF/HFC/TableProducer/derivedDataCreatorCorrelationsReduced.cxx @@ -88,7 +88,6 @@ struct HfDerivedDataCreatorCorrelationsReduced { Configurable ptCandMax{"ptCandMax", 24., "max. cand. pT"}; Configurable tpcNClsCrossedRowsMin{"tpcNClsCrossedRowsMin", 70, "min. TPC crossed rows for associated tracks"}; Configurable etaTrkMax{"etaTrkMax", 1., "max. track eta"}; - Configurable etaCandMax{"etaCandMax", 1., "max. trigger candidate eta"}; Configurable ptTrkMin{"ptTrkMin", 0.2, "min. track pT"}; Configurable ptTrkMax{"ptTrkMax", 3., "max. track pT"}; Configurable dcaXYTrkMax{"dcaXYTrkMax", 1., "max. track DCA XY"}; @@ -264,6 +263,26 @@ struct HfDerivedDataCreatorCorrelationsReduced { return outputMl; } + /// Cut on rapidity of the candidate + /// \param candidate is the charm hadron candidate + template + bool cutCandRapidity(const TCand& candidate) + { + double y = 0.0; + if constexpr (CandType == CandidateType::DsToKKPi || CandType == CandidateType::DsToPiKK) { + y = HfHelper::yDs(candidate); + } else if constexpr (CandType == CandidateType::DplusToPiKPi) { + y = HfHelper::yDplus(candidate); + } else if constexpr (CandType == CandidateType::D0ToPiK || CandType == CandidateType::D0ToKPi) { + y = HfHelper::yD0(candidate); + } else if constexpr (CandType == CandidateType::LcToPKPi) { + y = HfHelper::yLc(candidate); + } else { + return true; + } + return std::fabs(y) < yCandMax; + } + /// Check event selections for collision and fill the collision table /// \param collision is the collision template @@ -336,7 +355,7 @@ struct HfDerivedDataCreatorCorrelationsReduced { const float collCentrality) { for (const auto& trigCand : trigCands) { - if (std::fabs(trigCand.eta()) >= etaCandMax) { + if (!cutCandRapidity(trigCand)) { continue; } double trigCandPt = trigCand.pt(); @@ -392,7 +411,7 @@ struct HfDerivedDataCreatorCorrelationsReduced { void fillCharmMixedEvent(TTrigCands const& trigCands) { for (const auto& trigCand : trigCands) { - if (std::fabs(trigCand.eta()) >= etaCandMax) { + if (!cutCandRapidity(trigCand)) { continue; } registry.fill(HIST("hPhiVsPtTrig"), RecoDecay::constrainAngle(trigCand.phi(), -o2::constants::math::PIHalf), trigCand.pt()); From 651f1c554435118fa27d32a18097913b165bddf6 Mon Sep 17 00:00:00 2001 From: Deependra Sharma <38365215+deependra170598@users.noreply.github.com> Date: Tue, 17 Mar 2026 00:46:39 +0530 Subject: [PATCH 293/347] [PWGHF/HFC] providing efficiency from ccdb (#15348) --- .../HFC/Tasks/taskCorrelationDstarHadrons.cxx | 73 ++++++++++++++++++- 1 file changed, 71 insertions(+), 2 deletions(-) diff --git a/PWGHF/HFC/Tasks/taskCorrelationDstarHadrons.cxx b/PWGHF/HFC/Tasks/taskCorrelationDstarHadrons.cxx index bb312fccaac..d870eb6731d 100644 --- a/PWGHF/HFC/Tasks/taskCorrelationDstarHadrons.cxx +++ b/PWGHF/HFC/Tasks/taskCorrelationDstarHadrons.cxx @@ -29,6 +29,8 @@ #include +#include +#include #include using namespace o2; @@ -78,10 +80,19 @@ const std::vector vecEfficiencyTracksDefault(nPtBinsTrackEfficiency); struct HfTaskCorrelationDstarHadrons { Configurable applyEfficiency{"applyEfficiency", true, "Flag for applying efficiency weights"}; + Configurable useCcdbEfficiency{"useCcdbEfficiency", false, "Flag for using efficiency values from CCDB (if false, efficiency values must be provided via json files)"}; + Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable ccdbPathEfficiencyDstar{"ccdbPathEfficiencyDstar", "Users/d/desharma/HFC/Efficiency/Dstar", "path in ccdb for Dstar efficiency values"}; + Configurable ccdbPathEfficiencyTracks{"ccdbPathEfficiencyTracks", "Users/d/desharma/HFC/Efficiency/Track", "path in ccdb for track efficiency values"}; + Configurable ccdbTimestamp{"ccdbTimestamp", -1, "timestamp for retrieving efficiency values from CCDB"}; + Configurable efficiencyDstarFileName{"efficiencyDstarFileName", "efficiencyHFCDstar.root", "name of the efficiency file for Dstar"}; + Configurable efficiencyTracksFileName{"efficiencyTracksFileName", "efficiencyHFCTrack.root", "name of the efficiency file for tracks"}; + Configurable nEfficiencyHist{"nEfficiencyHist", 1, "if MB nEfficiencyHist = 1, if Centrality classes nEfficiencyHist = number of centrality classes (i.e. 10)"}; + // pT ranges for correlation plots: the default values are those embedded in hf_cuts_dplus_to_pi_k_pi (i.e. the mass pT bins), but can be redefined via json files Configurable> binsPtCorrelations{"binsPtCorrelations", std::vector{vecBinsPtCorrelationsDefault}, "pT bin limits for correlation plots"}; - // efficiency configirables for candidate Dstar + // efficiency configurables for candidate Dstar Configurable> binsPtEfficiency{"binsPtEfficiency", std::vector{o2::analysis::hf_cuts_dstar_to_d0_pi::vecBinsPt}, "pT bin limits for efficiency"}; Configurable> efficiencyDstar{"efficiencyDstar", std::vector{vecEfficiencyDstarDefault}, "efficiency values for Dstar vs pT bin"}; @@ -102,6 +113,10 @@ struct HfTaskCorrelationDstarHadrons { HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + o2::ccdb::CcdbApi ccdbApi; + std::vector vecHistEfficiencyDstar; + std::vector vecHistEfficiencyTracks; + void init(InitContext&) { @@ -120,6 +135,51 @@ struct HfTaskCorrelationDstarHadrons { registry.add("hCorrel2DPtIntSidebands", stringDHadron + stringSideband + stringDeltaPhi + stringDeltaEta + "entries", {HistType::kTH2D, {axisSpecDeltaPhi, axisSpecDeltaEta}}, true); registry.add("hDeltaEtaPtIntSidebands", stringDHadron + stringSideband + stringDeltaEta + "entries", {HistType::kTH1D, {axisSpecDeltaEta}}, true); registry.add("hDeltaPhiPtIntSidebands", stringDHadron + stringSideband + stringDeltaPhi + "entries", {HistType::kTH1D, {axisSpecDeltaPhi}}, true); + + if (applyEfficiency && useCcdbEfficiency) { + ccdbApi.init(ccdbUrl); + std::map const metadata; + bool const isEfficiencyDstarfileAvailable = ccdbApi.retrieveBlob(ccdbPathEfficiencyDstar, ".", metadata, ccdbTimestamp, false, efficiencyDstarFileName); + if (!isEfficiencyDstarfileAvailable) { + LOGF(fatal, "Failed to retrieve efficiency file for Dstar from CCDB"); + } + bool const isEfficiencyTracksfileAvailable = ccdbApi.retrieveBlob(ccdbPathEfficiencyTracks, ".", metadata, ccdbTimestamp, false, efficiencyTracksFileName); + if (!isEfficiencyTracksfileAvailable) { + LOGF(fatal, "Failed to retrieve efficiency file for tracks from CCDB"); + } + + TFile* efficiencyDstarRootFile = TFile::Open(efficiencyDstarFileName.value.c_str(), "READ"); + if (!efficiencyDstarRootFile || efficiencyDstarRootFile->IsZombie()) { + LOGF(fatal, "Failed to open efficiency file for Dstar"); + } + + TFile* efficiencyTracksRootFile = TFile::Open(efficiencyTracksFileName.value.c_str(), "READ"); + if (!efficiencyTracksRootFile || efficiencyTracksRootFile->IsZombie()) { + LOGF(fatal, "Failed to open efficiency file for tracks"); + } + + vecHistEfficiencyDstar.resize(nEfficiencyHist); + vecHistEfficiencyTracks.resize(nEfficiencyHist); + + for (int iHist = 0; iHist < nEfficiencyHist; iHist++) { + vecHistEfficiencyDstar[iHist] = dynamic_cast(efficiencyDstarRootFile->Get(Form("hEfficiencyDstar_%d", iHist))); + if (!vecHistEfficiencyDstar[iHist]) { + LOGF(fatal, "Failed to retrieve Dstar efficiency histogram hEfficiencyDstar_%d from file", iHist); + } + + vecHistEfficiencyTracks[iHist] = dynamic_cast(efficiencyTracksRootFile->Get(Form("hEfficiencyTracks_%d", iHist))); + if (!vecHistEfficiencyTracks[iHist]) { + LOGF(fatal, "Failed to retrieve track efficiency histogram hEfficiencyTracks_%d from file", iHist); + } + vecHistEfficiencyDstar[iHist]->SetDirectory(nullptr); + vecHistEfficiencyTracks[iHist]->SetDirectory(nullptr); + } + + efficiencyDstarRootFile->Close(); + efficiencyTracksRootFile->Close(); + delete efficiencyDstarRootFile; + delete efficiencyTracksRootFile; + } } void processData(aod::DstarHadronPair const& dstarHPairs) @@ -150,12 +210,21 @@ struct HfTaskCorrelationDstarHadrons { // } float netEfficiencyWeight = 1.0; - if (applyEfficiency) { + if (applyEfficiency && !useCcdbEfficiency) { float const efficiencyWeightDstar = efficiencyDstar->at(effBinPtDstar); // LOG(info)<<"efficiencyWeightDstar "<at(effBinPtTrack); // LOG(info)<<"efficiencyWeightTracks "<GetBinContent(vecHistEfficiencyDstar[0]->GetXaxis()->FindBin(ptDstar)); + // LOG(info)<<"efficiencyWeightDstar "<GetBinContent(vecHistEfficiencyTracks[0]->GetXaxis()->FindBin(ptTrack)); + // LOG(info)<<"efficiencyWeightTracks "< 1) { + // to do + LOGF(fatal, "Using CCDB efficiency with more than 1 histogram is not implemented yet"); } // check if correlation entry belongs to signal region, sidebands or is outside both, and fill correlation plots From 99e14ba9eec9febcf6f5be682b42dcd8b86ee6af Mon Sep 17 00:00:00 2001 From: Luca Aglietta <75362880+Luca610@users.noreply.github.com> Date: Mon, 16 Mar 2026 20:29:06 +0100 Subject: [PATCH 294/347] [PWGHF] Fixed bug in histogram name (#15415) --- PWGHF/D2H/Core/DataCreationCharmReso.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWGHF/D2H/Core/DataCreationCharmReso.h b/PWGHF/D2H/Core/DataCreationCharmReso.h index df88ca05069..fb44dce3b42 100644 --- a/PWGHF/D2H/Core/DataCreationCharmReso.h +++ b/PWGHF/D2H/Core/DataCreationCharmReso.h @@ -249,7 +249,7 @@ void addHistograms(o2::framework::HistogramRegistry& registry) registry.add("hMassVsPtK0s", "K0^{s} candidates;#it{p}_{T} (GeV/#it{c});inv. mass (#pi^{#plus}#pi^{#minus}) (GeV/#it{c}^{2});entries", {o2::framework::HistType::kTH2D, {axisPt, axisMassKzero}}); registry.add("hMassVsPtLambda", "Lambda candidates;#it{p}_{T} (GeV/#it{c});inv. mass (p #pi^{#minus}) (GeV/#it{c}^{2});entries", {o2::framework::HistType::kTH2D, {axisPt, axisMassLambda}}); registry.add("hAP", "Aremnteros-Podolanski plot for V0 candidates;#it{#alpha};#it{q}_{T} (GeV/#it{c});entries", {o2::framework::HistType::kTH2D, {axisAlpha, axisQt}}); - registry.add("hRadius", "Radius of V0 candidates;#it{R} (cm);entries", {o2::framework::HistType::kTH1D, {axisRadius}}); + registry.add("hV0Radius", "Radius of V0 candidates;#it{R} (cm);entries", {o2::framework::HistType::kTH1D, {axisRadius}}); registry.add("hdEdxVsP", "Tracks;#it{p} (GeV/#it{c});d#it{E}/d#it{x};entries", {o2::framework::HistType::kTH2D, {axisP, axisDeDx}}); if constexpr (DType == DMesonType::D0) { From 26b24c682a97f21962be6f12f08a2599e74186ea Mon Sep 17 00:00:00 2001 From: Rrantu <156880782+Rrantu@users.noreply.github.com> Date: Mon, 16 Mar 2026 21:34:53 +0100 Subject: [PATCH 295/347] [PWGHF] Fix UPC online gap selection bug (#15418) --- PWGHF/Utils/utilsUpcHf.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/PWGHF/Utils/utilsUpcHf.h b/PWGHF/Utils/utilsUpcHf.h index cdc923ce96c..f30d99b5598 100644 --- a/PWGHF/Utils/utilsUpcHf.h +++ b/PWGHF/Utils/utilsUpcHf.h @@ -81,6 +81,8 @@ inline auto determineGapType(TCollision const& collision, float amplitudeThresholdFT0C = defaults::AmplitudeThresholdFT0C) { using BCType = std::decay_t())>; + const float amplitudeThresholdsFDDA = -1.0f; // Not used in SGSelector, set to -1 to indicate unused + const float amplitudeThresholdsFDDC = -1.0f; // Not used in SGSelector, set to -1 to indicate unused // Configure SGSelector thresholds SGCutParHolder sgCuts; @@ -88,7 +90,7 @@ inline auto determineGapType(TCollision const& collision, sgCuts.SetMinNBCs(nBcsMin); sgCuts.SetNTracks(nContributorsPvMin, nContributorsPvMax); sgCuts.SetMaxFITtime(timeFitMax); - sgCuts.SetFITAmpLimits({amplitudeThresholdFV0A, amplitudeThresholdFT0A, amplitudeThresholdFT0C}); + sgCuts.SetFITAmpLimits({amplitudeThresholdFV0A, amplitudeThresholdFT0A, amplitudeThresholdFT0C, amplitudeThresholdsFDDA, amplitudeThresholdsFDDC}); // Get BC and BC range if (!collision.has_foundBC()) { From 4b53384a8086fc2ab8c693bbf5102518deb83094 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Tue, 17 Mar 2026 05:43:31 +0900 Subject: [PATCH 296/347] [PWGEM/Dilepton] fix phi position range (#15417) --- PWGEM/Dilepton/Core/DielectronCut.h | 1 + 1 file changed, 1 insertion(+) diff --git a/PWGEM/Dilepton/Core/DielectronCut.h b/PWGEM/Dilepton/Core/DielectronCut.h index 654c9557095..b9179122279 100644 --- a/PWGEM/Dilepton/Core/DielectronCut.h +++ b/PWGEM/Dilepton/Core/DielectronCut.h @@ -416,6 +416,7 @@ class DielectronCut : public TNamed case DielectronCuts::kTrackPhiPositionRange: { float phiPosition = track.phi() + std::asin(-0.30282 * track.sign() * (mBz * 0.1) * mRefR / (2.f * track.pt())); + phiPosition = RecoDecay::constrainAngle(phiPosition, 0, 1U); // 0-2pi if (mMinTrackPhiPosition < 0.f && mMaxTrackPhiPosition < M_PI) { // threshold across 0 rad. o2::math_utils::bringToPMPi(phiPosition); From 202c7822c23e56870ef8c9b2a676f760e4dc7dd3 Mon Sep 17 00:00:00 2001 From: Hirak Koley Date: Tue, 17 Mar 2026 02:37:42 +0530 Subject: [PATCH 297/347] [PWGLF] Adjust MC label bins and update event selection logic (#15408) --- .../Resonances/lambda1520analysisinpp.cxx | 32 ++++++++++++++----- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/PWGLF/Tasks/Resonances/lambda1520analysisinpp.cxx b/PWGLF/Tasks/Resonances/lambda1520analysisinpp.cxx index a494b545539..000957d1fdf 100644 --- a/PWGLF/Tasks/Resonances/lambda1520analysisinpp.cxx +++ b/PWGLF/Tasks/Resonances/lambda1520analysisinpp.cxx @@ -262,7 +262,7 @@ struct Lambda1520analysisinpp { AxisSpec axisTPCXrow{binsTPCXrows, "#Xrows_{TPC}"}; AxisSpec axisPIDQA{binsnSigma, "#sigma"}; AxisSpec axisTPCSignal{binsnTPCSignal, ""}; - AxisSpec axisMClabel{6, -1.5f, 6.5f, "MC Label"}; + AxisSpec axisMClabel{9, -1.f, 8.f, "MC Label"}; AxisSpec axisEtaPhi{binsEtaPhi, ""}; AxisSpec axisPhi{350, 0, 7, "#Phi"}; AxisSpec axisMultMix{configBkg.cfgMultPercentileBins, "Multiplicity Percentile"}; @@ -276,7 +276,7 @@ struct Lambda1520analysisinpp { histos.add("QAevent/hPairsCounterSameE", "total valid no. of pairs sameE", HistType::kTH1F, {{1, 0.5f, 1.5f}}); histos.add("QAevent/hnTrksSameE", "n tracks per event SameE", HistType::kTH1F, {{1000, 0.0, 1000.0}}); } - // Test on Mixed event + // Gen on Mixed event if (doprocessME) { // Histograms for Mixed Event Pool characteristics @@ -401,6 +401,7 @@ struct Lambda1520analysisinpp { // MC QA histos.add("Event/hMCEventIndices", "hMCEventIndices", kTH2D, {axisMult, idxMCAxis}); if (doprocessMCGen) { + histos.add("QA/Gen", "Gen histogram", kTH1D, {{10, 0, 10, "index"}}); histos.add("QA/MC/h2GenEtaPt_beforeanycut", " #eta-#it{p}_{T} distribution of Generated #Lambda(1520); #eta; #it{p}_{T}; Counts;", HistType::kTHnSparseF, {axisEta, axisPtQA}); histos.add("QA/MC/h2GenPhiRapidity_beforeanycut", " #phi-y distribution of Generated #Lambda(1520); #phi; y; Counts;", HistType::kTHnSparseF, {axisPhi, axisRap}); histos.add("QA/MC/h2GenEtaPt_afterEtaRapCut", " #eta-#it{p}_{T} distribution of Generated #Lambda(1520); #eta; #it{p}_{T}; Counts;", HistType::kTHnSparseF, {axisEta, axisPtQA}); @@ -1071,6 +1072,8 @@ struct Lambda1520analysisinpp { histos.fill(HIST("QAevent/hEventsMC"), 2); } + colCuts.fillQA(collision); + fillHistograms(collision, tracks, tracks); } PROCESS_SWITCH(Lambda1520analysisinpp, processMCRec, "Process Event for MC Rec without partition", false); @@ -1136,21 +1139,23 @@ struct Lambda1520analysisinpp { histos.fill(HIST("QA/MC/h2GenEtaPt_afterEtaRapCut"), part.eta(), part.pt()); histos.fill(HIST("QA/MC/h2GenPhiRapidity_afterEtaRapCut"), part.phi(), part.y()); - // without any event selection - if (part.pdgCode() > 0) + histos.fill(HIST("QA/Gen"), 1); + if (part.pdgCode() > 0) // without any event selection histos.fill(HIST("Result/MC/Genlambda1520pt"), 0, part.pt(), centrality); else histos.fill(HIST("Result/MC/Genantilambda1520pt"), 0, part.pt(), centrality); - if (inVtx10) // INEL10 + if (inVtx10) // vtx10 { + histos.fill(HIST("QA/Gen"), 2); if (part.pdgCode() > 0) histos.fill(HIST("Result/MC/Genlambda1520pt"), 1, part.pt(), centrality); else histos.fill(HIST("Result/MC/Genantilambda1520pt"), 1, part.pt(), centrality); } - if (inVtx10 && isSel8) // INEL>10, vtx10 + if (inVtx10 && isSel8) // vtx10, sel8 { + histos.fill(HIST("QA/Gen"), 3); if (part.pdgCode() > 0) histos.fill(HIST("Result/MC/Genlambda1520pt"), 2, part.pt(), centrality); else @@ -1158,25 +1163,36 @@ struct Lambda1520analysisinpp { } if (inVtx10 && isTriggerTVX) // vtx10, TriggerTVX { + histos.fill(HIST("QA/Gen"), 4); if (part.pdgCode() > 0) histos.fill(HIST("Result/MC/Genlambda1520pt"), 3, part.pt(), centrality); else histos.fill(HIST("Result/MC/Genantilambda1520pt"), 3, part.pt(), centrality); } - if (isInAfterAllCuts) // after all event selection + if (inVtx10 && isTrueINELgt0) // vtx10, INEL>0 { + histos.fill(HIST("QA/Gen"), 5); if (part.pdgCode() > 0) histos.fill(HIST("Result/MC/Genlambda1520pt"), 4, part.pt(), centrality); else histos.fill(HIST("Result/MC/Genantilambda1520pt"), 4, part.pt(), centrality); } - if (isInAfterAllCuts && isTrueINELgt0) // after all event selection + if (isInAfterAllCuts) // after all event selection { + histos.fill(HIST("QA/Gen"), 6); if (part.pdgCode() > 0) histos.fill(HIST("Result/MC/Genlambda1520pt"), 5, part.pt(), centrality); else histos.fill(HIST("Result/MC/Genantilambda1520pt"), 5, part.pt(), centrality); } + if (isInAfterAllCuts && isTrueINELgt0) // after all event selection && INEL>0 + { + histos.fill(HIST("QA/Gen"), 7); + if (part.pdgCode() > 0) + histos.fill(HIST("Result/MC/Genlambda1520pt"), 6, part.pt(), centrality); + else + histos.fill(HIST("Result/MC/Genantilambda1520pt"), 6, part.pt(), centrality); + } } // QA for Trigger efficiency From 23e32be5f74ca6361334b8f641035310c93c403a Mon Sep 17 00:00:00 2001 From: Marvin Hemmer <53471402+mhemmer-cern@users.noreply.github.com> Date: Mon, 16 Mar 2026 22:42:14 +0100 Subject: [PATCH 298/347] =?UTF-8?q?[PWGEM]=20PM:=20Overhaul=20NonLin=20wit?= =?UTF-8?q?h=20new=20centrality=20dependent=20paramenter=20=E2=80=A6=20(#1?= =?UTF-8?q?5420)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- PWGEM/PhotonMeson/Core/EMNonLin.cxx | 54 +-- PWGEM/PhotonMeson/Core/EMNonLin.h | 336 +++++------------- .../PhotonMeson/Core/MaterialBudgetWeights.h | 27 +- PWGEM/PhotonMeson/Core/V0PhotonCandidate.h | 99 +++--- .../TableProducer/nonLinProducer.cxx | 44 ++- .../TableProducer/photonconversionbuilder.cxx | 1 + 6 files changed, 208 insertions(+), 353 deletions(-) diff --git a/PWGEM/PhotonMeson/Core/EMNonLin.cxx b/PWGEM/PhotonMeson/Core/EMNonLin.cxx index 571d7efbae8..5c44ecc9f0c 100644 --- a/PWGEM/PhotonMeson/Core/EMNonLin.cxx +++ b/PWGEM/PhotonMeson/Core/EMNonLin.cxx @@ -16,56 +16,40 @@ #include "EMNonLin.h" #include +#include using namespace o2::pwgem::nonlin; -float EMNonLin::getCorrectionFactor(float x, const Context& ctx) +float EMNonLin::getCorrectionFactor(float var, const Context& ctx) { - if (!ctx.params || x == 0.f) [[unlikely]] { - return x; + if (!ctx.params || var == 0.f) [[unlikely]] { + return 1.f; } int maxIter = std::min(ctx.nIter, MaxIter - 1); - - float scale = 1.f; // cumulative scale - float refVal = x; // reference value for computing next scale + float scale = 1.f; // cumulative scale + float refVal = var; // reference value updated each iteration for (int i = 0; i <= maxIter; ++i) { if (refVal == 0.f) { break; } - const auto& p = ctx.params[i]; - // scale function (x + a + b/x)/(x + c) which goes towards 1 for large x since x >> a,b,c -> x/x = 1 - float iterScale = - (refVal + p.par0 + p.par1 / refVal) / - (refVal + p.par2); + // evaluate pol1 for each parameter at this centrality + float a = p.a0 + p.a1 * ctx.cent; + float b = p.b0 + p.b1 * ctx.cent; + float c = p.c0 + p.c1 * ctx.cent; - scale *= iterScale; // total scale = product over itertaion scale - refVal = x * scale; // next iteration uses scaled original input - } - return scale; -} - -const EMNonLin::NonLinParams* EMNonLin::resolveParams(PhotonType type, float cent) -{ - int centBin = static_cast(cent / 10.f); - if (centBin < 0) - centBin = 0; - if (centBin >= CentBins) - centBin = CentBins - 1; - - return &kNonLinTable[static_cast(type)][centBin][0]; -} + // guard against c <= 0 which would make pow(x, -c) diverge + if (c <= 0.f) { + continue; + } -const EMNonLin::NonLinParams* EMNonLin::resolveParamsMC(PhotonType type, float cent) -{ - int centBin = static_cast(cent / 10.f); - if (centBin < 0) - centBin = 0; - if (centBin >= CentBins) - centBin = CentBins - 1; + float iterScale = a + b * std::pow(refVal, -c); + scale *= iterScale; + refVal = var * scale; // next iteration uses scaled original input + } - return &kNonLinTableMC[static_cast(type)][centBin][0]; + return scale; } diff --git a/PWGEM/PhotonMeson/Core/EMNonLin.h b/PWGEM/PhotonMeson/Core/EMNonLin.h index e9bce15c260..d272d9e5593 100644 --- a/PWGEM/PhotonMeson/Core/EMNonLin.h +++ b/PWGEM/PhotonMeson/Core/EMNonLin.h @@ -18,290 +18,134 @@ #include -#include // uint8_t +#include + +#include +#include namespace o2::pwgem::nonlin { +constexpr int MaxCent = 100.f; + /// \class EMNonLin /// \brief Class to obtain non linear correction factors for PbPb. +/// Parameters are loaded from CCDB (TMatrixD: rows = iterations, cols = 6 pol1 coefficients). +/// Falls back to hardcoded static table if CCDB object is not available. +/// The correction is of type a + b * refVal^(-c), where a, b and c are themselves described by linear functions over centrality. class EMNonLin { public: - static constexpr int MaxIter = 2; + static constexpr int MaxIter = 2; // hard cap on iterations static constexpr int PhotonN = 3; - static constexpr int CentBins = 10; + static constexpr int NCols = 6; // a0, a1, b0, b1, c0, c1 enum class PhotonType : uint8_t { kEMC = 0, kPCM = 1, - kPHOS = 2 // just in case + kPHOS = 2 }; struct NonLinParams { - float par0{0.f}; - float par1{0.f}; - float par2{0.f}; + float a0{1.f}, a1{0.f}; // pol1 params for a: asymptote + float b0{0.f}, b1{0.f}; // pol1 params for b: magnitude + float c0{0.f}, c1{0.f}; // pol1 params for c: exponent }; struct Context { const NonLinParams* params = nullptr; int nIter = 0; + float cent = 0.f; + /// \brief Sets parameters for the NonLin. Used with EMNonLin::resolveParams() + /// \param newParams pointer to new NonLinParams void setParams(const NonLinParams* newParams) { params = newParams; } + /// \brief Sets iteration used for the NonLin. + /// \param iter iteration void setIter(int iter) { - if (iter < 0 || iter >= MaxIter) { - nIter = MaxIter - 1; - return; - } + nIter = (iter < 0 || iter >= MaxIter) ? MaxIter - 1 : iter; + } - nIter = iter; + /// \brief Sets current centrality. + /// \param centrality centrality + void setCent(float centrality) + { + cent = (centrality >= MaxCent) ? MaxCent : centrality; } }; - /// \brief gets the correction value for energy or pT for a specific - /// \param inputCalibValue pT or energy of the photon that needs calibration - /// \param ctx Context which has the centrality, photontype and number of iterations stored inside - static float getCorrectionFactor(float inputCalibValue, const Context& ctx); - - /// \brief sets the parameters accordingly to the photon type, centrality and the wanted iteration level - /// \param photonType type of the photon (e.g. 0 for EMC) - /// \param cent centrality of the current collision in case the correction is centrality dependent - static const NonLinParams* resolveParams(PhotonType type, float cent); - - /// \brief sets the parameters accordingly to the photon type, centrality and the wanted iteration level for MC - /// \param photonType type of the photon (e.g. 0 for EMC) - /// \param cent centrality of the current collision in case the correction is centrality dependent - static const NonLinParams* resolveParamsMC(PhotonType type, float cent); + /// \brief Load parameters from a TMatrixD fetched from CCDB. + /// Rows = iterations, cols = {a0, a1, b0, b1, c0, c1}. + /// Overwrites the static fallback for this photon type. + /// \param mat pointer to TMatrixD from CCDB (may be nullptr) + /// \param type photon type to fill + void getFromCCDBObject(const TMatrixD* mat, PhotonType type) + { + int iType = static_cast(type); + if (!mat || mat->GetNcols() != NCols) { + mCCDBLoaded[iType] = false; + return; + } + int nIter = std::min(mat->GetNrows(), MaxIter); + for (int i = 0; i < nIter; ++i) { + mCCDBParams[iType][i] = { + static_cast((*mat)(i, 0)), static_cast((*mat)(i, 1)), + static_cast((*mat)(i, 2)), static_cast((*mat)(i, 3)), + static_cast((*mat)(i, 4)), static_cast((*mat)(i, 5))}; + } + mCCDBLoaded[iType] = true; + } + + /// \brief Compute the multiplicative correction factor for energy/pT. + /// \param par energy or pT of the photon + /// \param ctx context holding centrality, iteration level, and params pointer + static float getCorrectionFactor(float var, const Context& ctx); + + /// \brief Return pointer to the params array for a given photon type. + /// \returns CCDB-loaded params if available, otherwise the static fallback. + const NonLinParams* resolveParams(PhotonType type) const + { + int iType = static_cast(type); + return mCCDBLoaded[iType] ? &mCCDBParams[iType][0] : &FallbackTable[iType][0]; + } private: - static constexpr NonLinParams kNonLinTable - [PhotonN][CentBins][MaxIter] = - { - // ============================ - // PhotonType::kEMC (0) - // ============================ - { - // 00–10 - { - {-5.33426e-01f, 1.40144e-02f, -5.24434e-01f}, // iter 0 - {0.f, 0.f, 0.f} // iter 1 - }, - // 10–20 - { - {-5.33426e-01f, 1.40144e-02f, -5.24434e-01f}, - {0.f, 0.f, 0.f}}, - // 20–30 - { - {-5.33426e-01f, 1.40144e-02f, -5.24434e-01f}, - {0.f, 0.f, 0.f}}, - // 30–40 - { - {-5.33426e-01f, 1.40144e-02f, -5.24434e-01f}, - {0.f, 0.f, 0.f}}, - // 40–50 - { - {-5.33426e-01f, 1.40144e-02f, -5.24434e-01f}, - {0.f, 0.f, 0.f}}, - // 50–60 - { - {-5.33426e-01f, 1.40144e-02f, -5.24434e-01f}, - {0.f, 0.f, 0.f}}, - // 60–70 - { - {-5.33426e-01f, 1.40144e-02f, -5.24434e-01f}, - {0.f, 0.f, 0.f}}, - // 70–80 - { - {-5.33426e-01f, 1.40144e-02f, -5.24434e-01f}, - {0.f, 0.f, 0.f}}, - // 80–90 - { - {-5.33426e-01f, 1.40144e-02f, -5.24434e-01f}, - {0.f, 0.f, 0.f}}, - // 90–100 - { - {-5.33426e-01f, 1.40144e-02f, -5.24434e-01f}, - {0.f, 0.f, 0.f}}}, - - // ============================ - // PhotonType::kPCM (1) - // ============================ - { - // 00–10 - { - {10.7203f, 0.0383968f, 10.6025f}, // iter 0 - {7.84549f, 0.0250021f, 7.86976f} // iter 1 - }, - // 10–20 - { - {10.7203f, 0.0383968f, 10.6025f}, - {7.84549f, 0.0250021f, 7.86976f}}, - // 20–30 - { - {10.7203f, 0.0383968f, 10.6025f}, - {7.84549f, 0.0250021f, 7.86976f}}, - // 30–40 - { - {10.7203f, 0.0383968f, 10.6025f}, - {7.84549f, 0.0250021f, 7.86976f}}, - // 40–50 - { - {10.7203f, 0.0383968f, 10.6025f}, - {7.84549f, 0.0250021f, 7.86976f}}, - // 50–60 - { - {10.7203f, 0.0383968f, 10.6025f}, - {7.84549f, 0.0250021f, 7.86976f}}, - // 60–70 - { - {10.7203f, 0.0383968f, 10.6025f}, - {7.84549f, 0.0250021f, 7.86976f}}, - // 70–80 - { - {10.7203f, 0.0383968f, 10.6025f}, - {7.84549f, 0.0250021f, 7.86976f}}, - // 80–90 - { - {10.7203f, 0.0383968f, 10.6025f}, - {7.84549f, 0.0250021f, 7.86976f}}, - // 90–100 - { - {10.7203f, 0.0383968f, 10.6025f}, - {7.84549f, 0.0250021f, 7.86976f}}}, - - // ============================ - // PhotonType::kPHOS (2) - // ============================ - { - // All centralities identical - {{0.f, 0.f, 0.f}, {0.f, 0.f, 0.f}}, - {{0.f, 0.f, 0.f}, {0.f, 0.f, 0.f}}, - {{0.f, 0.f, 0.f}, {0.f, 0.f, 0.f}}, - {{0.f, 0.f, 0.f}, {0.f, 0.f, 0.f}}, - {{0.f, 0.f, 0.f}, {0.f, 0.f, 0.f}}, - {{0.f, 0.f, 0.f}, {0.f, 0.f, 0.f}}, - {{0.f, 0.f, 0.f}, {0.f, 0.f, 0.f}}, - {{0.f, 0.f, 0.f}, {0.f, 0.f, 0.f}}, - {{0.f, 0.f, 0.f}, {0.f, 0.f, 0.f}}, - {{0.f, 0.f, 0.f}, {0.f, 0.f, 0.f}}}}; - - static constexpr NonLinParams kNonLinTableMC - [PhotonN][CentBins][MaxIter] = - { - // ============================ - // PhotonType::kEMC (0) - // ============================ - { - // 00–10 - { - {-5.33426e-01f, 1.40144e-02f, -5.24434e-01f}, // iter 0 - {0.f, 0.f, 0.f} // iter 1 - }, - // 10–20 - { - {-5.33426e-01f, 1.40144e-02f, -5.24434e-01f}, - {0.f, 0.f, 0.f}}, - // 20–30 - { - {-5.33426e-01f, 1.40144e-02f, -5.24434e-01f}, - {0.f, 0.f, 0.f}}, - // 30–40 - { - {-5.33426e-01f, 1.40144e-02f, -5.24434e-01f}, - {0.f, 0.f, 0.f}}, - // 40–50 - { - {-5.33426e-01f, 1.40144e-02f, -5.24434e-01f}, - {0.f, 0.f, 0.f}}, - // 50–60 - { - {-5.33426e-01f, 1.40144e-02f, -5.24434e-01f}, - {0.f, 0.f, 0.f}}, - // 60–70 - { - {-5.33426e-01f, 1.40144e-02f, -5.24434e-01f}, - {0.f, 0.f, 0.f}}, - // 70–80 - { - {-5.33426e-01f, 1.40144e-02f, -5.24434e-01f}, - {0.f, 0.f, 0.f}}, - // 80–90 - { - {-5.33426e-01f, 1.40144e-02f, -5.24434e-01f}, - {0.f, 0.f, 0.f}}, - // 90–100 - { - {-5.33426e-01f, 1.40144e-02f, -5.24434e-01f}, - {0.f, 0.f, 0.f}}}, - - // ============================ - // PhotonType::kPCM (1) - // ============================ - { - // 00–10 - { - {10.7203f, 0.0383968f, 10.6025f}, // iter 0 - {7.84549f, 0.0250021f, 7.86976f} // iter 1 - }, - // 10–20 - { - {10.7203f, 0.0383968f, 10.6025f}, - {7.84549f, 0.0250021f, 7.86976f}}, - // 20–30 - { - {10.7203f, 0.0383968f, 10.6025f}, - {7.84549f, 0.0250021f, 7.86976f}}, - // 30–40 - { - {10.7203f, 0.0383968f, 10.6025f}, - {7.84549f, 0.0250021f, 7.86976f}}, - // 40–50 - { - {10.7203f, 0.0383968f, 10.6025f}, - {7.84549f, 0.0250021f, 7.86976f}}, - // 50–60 - { - {10.7203f, 0.0383968f, 10.6025f}, - {7.84549f, 0.0250021f, 7.86976f}}, - // 60–70 - { - {10.7203f, 0.0383968f, 10.6025f}, - {7.84549f, 0.0250021f, 7.86976f}}, - // 70–80 - { - {10.7203f, 0.0383968f, 10.6025f}, - {7.84549f, 0.0250021f, 7.86976f}}, - // 80–90 - { - {10.7203f, 0.0383968f, 10.6025f}, - {7.84549f, 0.0250021f, 7.86976f}}, - // 90–100 - { - {10.7203f, 0.0383968f, 10.6025f}, - {7.84549f, 0.0250021f, 7.86976f}}}, + NonLinParams mCCDBParams[PhotonN][MaxIter] = {}; // Runtime params loaded from CCDB (per photon type, per iteration) + bool mCCDBLoaded[PhotonN] = {false, false, false}; + + // ------------------------------------------------------- + // Static fallback tables (used when CCDB object is absent) + // ------------------------------------------------------- + static constexpr NonLinParams FallbackTable[PhotonN][MaxIter] = { + // kEMC + {{1.f, 0.f, 0.f, 0.f, 0.f, 0.f}, + {1.f, 0.f, 0.f, 0.f, 0.f, 0.f}}, + // kPCM + {{1.f, 0.f, 0.010417f, -1.09508e-05f, 0.355795f, 0.00427618f}, + {1.f, 0.f, 0.f, 0.f, 0.f, 0.f}}, + // kPHOS + {{1.f, 0.f, 0.f, 0.f, 0.f, 0.f}, + {1.f, 0.f, 0.f, 0.f, 0.f, 0.f}}, + }; - // ============================ - // PhotonType::kPHOS (2) - // ============================ - { - // All centralities identical - {{0.f, 0.f, 0.f}, {0.f, 0.f, 0.f}}, - {{0.f, 0.f, 0.f}, {0.f, 0.f, 0.f}}, - {{0.f, 0.f, 0.f}, {0.f, 0.f, 0.f}}, - {{0.f, 0.f, 0.f}, {0.f, 0.f, 0.f}}, - {{0.f, 0.f, 0.f}, {0.f, 0.f, 0.f}}, - {{0.f, 0.f, 0.f}, {0.f, 0.f, 0.f}}, - {{0.f, 0.f, 0.f}, {0.f, 0.f, 0.f}}, - {{0.f, 0.f, 0.f}, {0.f, 0.f, 0.f}}, - {{0.f, 0.f, 0.f}, {0.f, 0.f, 0.f}}, - {{0.f, 0.f, 0.f}, {0.f, 0.f, 0.f}}}}; + static constexpr NonLinParams FallbackTableMC[PhotonN][MaxIter] = { + // kEMC + {{1.f, 0.f, 0.f, 0.f, 0.f, 0.f}, + {1.f, 0.f, 0.f, 0.f, 0.f, 0.f}}, + // kPCM + {{1.f, 0.f, 0.010417f, -1.09508e-05f, 0.355795f, 0.00427618f}, + {1.f, 0.f, 0.f, 0.f, 0.f, 0.f}}, + // kPHOS + {{1.f, 0.f, 0.f, 0.f, 0.f, 0.f}, + {1.f, 0.f, 0.f, 0.f, 0.f, 0.f}}, + }; }; + } // namespace o2::pwgem::nonlin #endif // PWGEM_PHOTONMESON_CORE_EMNONLIN_H_ diff --git a/PWGEM/PhotonMeson/Core/MaterialBudgetWeights.h b/PWGEM/PhotonMeson/Core/MaterialBudgetWeights.h index 41f4169f3bb..094f86ceb8a 100644 --- a/PWGEM/PhotonMeson/Core/MaterialBudgetWeights.h +++ b/PWGEM/PhotonMeson/Core/MaterialBudgetWeights.h @@ -8,47 +8,40 @@ // In applying this license CERN does not waive the privileges and immunities // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/// -/// \file materialBudgetWeights.cxx -/// + +/// \file MaterialBudgetWeights.h /// \brief This code produces a table to retrieve material budget weights. The table is to be join with V0PhotonKF -/// /// \author Youssef El Mard (youssef.el.mard.bouziani@cern.ch) -/// #ifndef PWGEM_PHOTONMESON_CORE_MATERIALBUDGETWEIGHTS_H_ #define PWGEM_PHOTONMESON_CORE_MATERIALBUDGETWEIGHTS_H_ #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/Logger.h" #include +#include +#include +#include #include #include +#include #include #include -using namespace o2; -using namespace o2::soa; -using namespace o2::framework; - using MyV0PhotonsMB = o2::soa::Join; using MyV0PhotonMB = MyV0PhotonsMB::iterator; struct MaterialBudgetWeights { - Produces omegaMBWeight; + o2::framework::Produces omegaMBWeight; - Configurable ccdbUrl{"ccdbUrl", "http://ccdb-test.cern.ch:8080", "CCDB url"}; - Configurable mbWeightsPath{"mbWeightsPath", "Users/y/yelmard/MaterialBudget/OmegaMBWeights", "Path of the mb weights"}; + o2::framework::Configurable ccdbUrl{"ccdbUrl", "http://ccdb-test.cern.ch:8080", "CCDB url"}; + o2::framework::Configurable mbWeightsPath{"mbWeightsPath", "Users/y/yelmard/MaterialBudget/OmegaMBWeights", "Path of the mb weights"}; o2::ccdb::CcdbApi ccdbApi; TH1F* hOmegaMBFromCCDB = nullptr; - void init(InitContext&) + void init(o2::framework::InitContext&) { // Load CCDB object only when the real process is enabled if (!doprocessMC) { diff --git a/PWGEM/PhotonMeson/Core/V0PhotonCandidate.h b/PWGEM/PhotonMeson/Core/V0PhotonCandidate.h index c29925b4bfb..2e98a0396b5 100644 --- a/PWGEM/PhotonMeson/Core/V0PhotonCandidate.h +++ b/PWGEM/PhotonMeson/Core/V0PhotonCandidate.h @@ -16,7 +16,6 @@ #ifndef PWGEM_PHOTONMESON_CORE_V0PHOTONCANDIDATE_H_ #define PWGEM_PHOTONMESON_CORE_V0PHOTONCANDIDATE_H_ -#include "PWGEM/Dilepton/Utils/PairUtilities.h" #include "PWGEM/PhotonMeson/Utils/PCMUtilities.h" #include "Common/Core/RecoDecay.h" @@ -228,55 +227,55 @@ struct V0PhotonCandidate { CentType getCentType() const { return centType; } private: - float conversionPointx; - float conversionPointy; - float conversionPointz; - float px; - float py; - float pz; - float posPx; - float posPy; - float posPz; - float elePx; - float elePy; - float elePz; - float pT; - float posPT; - float elePT; - float dcaXYV0ToPV; - float dcaZV0ToPV; - float alpha; - float qt; - float phiv; - float psipair; - float cospa; - float cospaRZ; - float cospaXY; - float chi2ndf; - float cent; - float pca; - float eta; - float posEta; - float eleEta; - float posdcaXY; - float posdcaZ; - float eledcaXY; - float eledcaZ; - float posTPCNClsShared; - float posTPCNClsFindable; - float posTPCNClsFindableMinusShared; - float posTPCNClsFindableMinusCrossedRows; - float posTPCChi2NCl; - float posTPCSignal; - float posITSClusterSizes; - float eleTPCNClsShared; - float eleTPCNClsFindable; - float eleTPCNClsFindableMinusShared; - float eleTPCNClsFindableMinusCrossedRows; - float eleTPCChi2NCl; - float eleTPCSignal; - float eleITSClusterSizes; - CentType centType; + float conversionPointx{0.f}; + float conversionPointy{0.f}; + float conversionPointz{0.f}; + float px{0.f}; + float py{0.f}; + float pz{0.f}; + float posPx{0.f}; + float posPy{0.f}; + float posPz{0.f}; + float elePx{0.f}; + float elePy{0.f}; + float elePz{0.f}; + float pT{0.f}; + float posPT{0.f}; + float elePT{0.f}; + float dcaXYV0ToPV{0.f}; + float dcaZV0ToPV{0.f}; + float alpha{0.f}; + float qt{0.f}; + float phiv{0.f}; + float psipair{0.f}; + float cospa{0.f}; + float cospaRZ{0.f}; + float cospaXY{0.f}; + float chi2ndf{0.f}; + float cent{0.f}; + float pca{0.f}; + float eta{0.f}; + float posEta{0.f}; + float eleEta{0.f}; + float posdcaXY{0.f}; + float posdcaZ{0.f}; + float eledcaXY{0.f}; + float eledcaZ{0.f}; + float posTPCNClsShared{0.f}; + float posTPCNClsFindable{0.f}; + float posTPCNClsFindableMinusShared{0.f}; + float posTPCNClsFindableMinusCrossedRows{0.f}; + float posTPCChi2NCl{0.f}; + float posTPCSignal{0.f}; + float posITSClusterSizes{0.f}; + float eleTPCNClsShared{0.f}; + float eleTPCNClsFindable{0.f}; + float eleTPCNClsFindableMinusShared{0.f}; + float eleTPCNClsFindableMinusCrossedRows{0.f}; + float eleTPCChi2NCl{0.f}; + float eleTPCSignal{0.f}; + float eleITSClusterSizes{0.f}; + CentType centType{CentFT0C}; }; #endif // PWGEM_PHOTONMESON_CORE_V0PHOTONCANDIDATE_H_ diff --git a/PWGEM/PhotonMeson/TableProducer/nonLinProducer.cxx b/PWGEM/PhotonMeson/TableProducer/nonLinProducer.cxx index 9feae005b6d..3e8d6cb146f 100644 --- a/PWGEM/PhotonMeson/TableProducer/nonLinProducer.cxx +++ b/PWGEM/PhotonMeson/TableProducer/nonLinProducer.cxx @@ -20,6 +20,7 @@ #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/emcalHistoDefinitions.h" +#include #include #include #include @@ -29,7 +30,10 @@ #include #include +#include + #include +#include #include using namespace o2; @@ -54,6 +58,9 @@ struct NonLinProducer { Configurable centEstimator{"centEstimator", 2, "Centrality estimation (FT0A: 1, FT0C: 2, FT0M: 3)"}; Configurable emcIteration{"emcIteration", 0, "iteration number of the non lin correction for EMCal. 0 means first iteration 1 means second and so on!"}; Configurable pcmIteration{"pcmIteration", 0, "iteration number of the non lin correction for PCM. 0 means first iteration 1 means second and so on!"}; + Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable ccdbPathEmcal{"ccdbPathEmcal", "Users/m/mhemmer/EM/NonLin/EMC", "CCDB Path to Non Lin TMatrixD for EMCal"}; + Configurable ccdbPathPcm{"ccdbPathPcm", "Users/m/mhemmer/EM/NonLin/PCM", "CCDB Path to Non Lin TMatrixD for PCM"}; HistogramRegistry historeg{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; @@ -68,6 +75,11 @@ struct NonLinProducer { EMNonLin::Context emNonLinContextEMC; EMNonLin::Context emNonLinContextPCM; + o2::framework::Service ccdb; + + TMatrixD* emcalMatrix = nullptr; + TMatrixD* pcmMatrix = nullptr; + void init(o2::framework::InitContext&) { historeg.add("QA/EMC/EIn", "Energy of EMC clusters before NonLin correction", gHistoSpecClusterE); @@ -81,6 +93,26 @@ struct NonLinProducer { emNonLinContextEMC.setIter(emcIteration); emNonLinContextPCM.setIter(pcmIteration); + + ccdb->setURL(ccdbUrl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + } + + template + void initCCDB(TCollision const& collision) + { + if (doprocessEMC) { + emcalMatrix = ccdb->getForTimeStamp(ccdbPathEmcal, collision.timestamp()); + emNonLinEMC.getFromCCDBObject(emcalMatrix, o2::pwgem::nonlin::EMNonLin::PhotonType::kEMC); + emNonLinContextEMC.setParams(emNonLinEMC.resolveParams(o2::pwgem::nonlin::EMNonLin::PhotonType::kEMC)); + } + if (doprocessPCM) { + pcmMatrix = ccdb->getForTimeStamp(ccdbPathPcm, collision.timestamp()); + emNonLinPCM.getFromCCDBObject(pcmMatrix, o2::pwgem::nonlin::EMNonLin::PhotonType::kPCM); + emNonLinContextPCM.setParams(emNonLinPCM.resolveParams(o2::pwgem::nonlin::EMNonLin::PhotonType::kPCM)); + } } /// Get the centrality @@ -113,7 +145,7 @@ struct NonLinProducer { int32_t collIndex = collision.globalIndex(); float cent = getCentrality(collision); - emNonLinContextEMC.setParams(emNonLinEMC.resolveParams(o2::pwgem::nonlin::EMNonLin::PhotonType::kEMC, cent)); + emNonLinContextEMC.setCent(cent); for (const auto& cluster : clusters) { @@ -122,7 +154,7 @@ struct NonLinProducer { collIndex = cluster.pmeventId(); collision.setCursor(collIndex); cent = getCentrality(collision); - emNonLinContextEMC.setParams(emNonLinEMC.resolveParams(o2::pwgem::nonlin::EMNonLin::PhotonType::kEMC, cent)); + emNonLinContextEMC.setCent(cent); } // fill before non lin histograms @@ -149,7 +181,7 @@ struct NonLinProducer { int32_t collIndex = collision.globalIndex(); float cent = getCentrality(collision); - emNonLinContextPCM.setParams(emNonLinPCM.resolveParams(o2::pwgem::nonlin::EMNonLin::PhotonType::kPCM, cent)); + emNonLinContextPCM.setCent(cent); for (const auto& v0 : v0s) { // check that we are at the correct collision @@ -157,14 +189,14 @@ struct NonLinProducer { collIndex = v0.pmeventId(); collision.setCursor(collIndex); cent = getCentrality(collision); - emNonLinContextPCM.setParams(emNonLinPCM.resolveParams(o2::pwgem::nonlin::EMNonLin::PhotonType::kPCM, cent)); + emNonLinContextPCM.setCent(cent); } // fill before non lin histograms historeg.fill(HIST("QA/PCM/PtIn"), v0.pt()); // get NonLin factor from class dependent on the centrality - float nonLinFactor = emNonLinEMC.getCorrectionFactor(v0.pt(), emNonLinContextPCM); + float nonLinFactor = emNonLinPCM.getCorrectionFactor(v0.pt(), emNonLinContextPCM); float nonLinPt = nonLinFactor * v0.pt(); @@ -183,6 +215,7 @@ struct NonLinProducer { } auto collision = collisions.begin(); + initCCDB(collision); runEMC(emcclusters, collision); } PROCESS_SWITCH(NonLinProducer, processEMC, "Create Non Lin table for EMC.", false); @@ -193,6 +226,7 @@ struct NonLinProducer { return; } auto collision = collisions.begin(); + initCCDB(collision); runPCM(pcmPhotons, collision); } PROCESS_SWITCH(NonLinProducer, processPCM, "Create Non Lin table for PCM.", false); diff --git a/PWGEM/PhotonMeson/TableProducer/photonconversionbuilder.cxx b/PWGEM/PhotonMeson/TableProducer/photonconversionbuilder.cxx index 33dd3e0ae31..9b2f9e0c411 100644 --- a/PWGEM/PhotonMeson/TableProducer/photonconversionbuilder.cxx +++ b/PWGEM/PhotonMeson/TableProducer/photonconversionbuilder.cxx @@ -18,6 +18,7 @@ #define HomogeneousField // needed for KFParticle::SetField(magneticField); #endif +#include "PWGEM/Dilepton/Utils/PairUtilities.h" #include "PWGEM/PhotonMeson/Core/EmMlResponsePCM.h" #include "PWGEM/PhotonMeson/Core/V0PhotonCandidate.h" #include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" From e91d6470baaf2a48772f6e0576773e35529b4dea Mon Sep 17 00:00:00 2001 From: mapalhares <165794118+mapalhares@users.noreply.github.com> Date: Tue, 17 Mar 2026 03:05:25 +0000 Subject: [PATCH 299/347] [PWGLF/NuSpEx] Added process function to compute event loss MC (#15373) Co-authored-by: ALICE Action Bot --- PWGLF/TableProducer/Nuspex/hyperRecoTask.cxx | 195 +++++++++++++++++-- 1 file changed, 182 insertions(+), 13 deletions(-) diff --git a/PWGLF/TableProducer/Nuspex/hyperRecoTask.cxx b/PWGLF/TableProducer/Nuspex/hyperRecoTask.cxx index 096b427617e..e200e66ae57 100644 --- a/PWGLF/TableProducer/Nuspex/hyperRecoTask.cxx +++ b/PWGLF/TableProducer/Nuspex/hyperRecoTask.cxx @@ -40,6 +40,8 @@ #include "MathUtils/BetheBlochAleph.h" #include "ReconstructionDataFormats/Track.h" +#include "Math/Vector4D.h" + #include #include #include @@ -49,6 +51,8 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; +using std::array; + using CollBracket = o2::math_utils::Bracket; using TracksFull = soa::Join; using CollisionsFull = soa::Join; @@ -56,6 +60,9 @@ using CollisionsFullMC = soa::Join; +using McCollisionMults = soa::Join; +using EventCandidatesMC = soa::Join; + namespace { constexpr double betheBlochDefault[1][6]{{-1.e32, -1.e32, -1.e32, -1.e32, -1.e32, -1.e32}}; @@ -77,6 +84,20 @@ std::shared_ptr hH4LMassTracked; std::shared_ptr hDecayChannel; std::shared_ptr hIsMatterGen; std::shared_ptr hIsMatterGenTwoBody; +std::shared_ptr hEvtMC; +std::shared_ptr hImpactParamGen; +std::shared_ptr hImpactParamReco; +std::shared_ptr hGen3HLBeforeEvtSel; +std::shared_ptr hGen3HLAfterSel; +std::shared_ptr hRecoCentralityColvsMultiplicityRecoEta05; +std::shared_ptr hRecoCentralityColvsImpactParamReco; +std::shared_ptr hGen3HLvsImpactParameterBeforeEvtSel; +std::shared_ptr hGen3HLvsImpactParameterAfterSel; +std::shared_ptr hGen3HLvsMultiplicityGenEta05BeforeEvtSel; +std::shared_ptr hGen3HLvsMultiplicityGenEta05AfterSel; +std::shared_ptr hGen3HLvsMultiplicityFT0CBeforeEvtSel; +std::shared_ptr hGen3HLvsMultiplicityFT0CAfterSel; + } // namespace struct hyperCandidate { @@ -147,6 +168,7 @@ struct hyperRecoTask { // PDG codes Configurable hyperPdg{"hyperPDG", 1010010030, "PDG code of the hyper-mother (could be 3LamH or 4LamH)"}; Configurable heDauPdg{"heDauPDG", 1000020030, "PDG code of the helium (could be 3He or 4He)"}; + Configurable piDauPdg{"piDauPdg", 211, "PDG code of pion"}; // Selection criteria Configurable v0cospacut{"hypcospa", 0.95, "V0 CosPA"}; @@ -199,6 +221,13 @@ struct hyperRecoTask { ConfigurableAxis zVtxBins{"zVtxBins", {100, -20.f, 20.f}, "Binning for n sigma"}; ConfigurableAxis centBins{"centBins", {100, 0.f, 100.f}, "Binning for centrality"}; + // histogram axes for EvtLossMC + ConfigurableAxis binsImpactPar{"binsImpactPar", {80, 0, 16}, "Binning of the impact parameter axis"}; + ConfigurableAxis binsCent{"binsCent", {10, 0.0, 100.0}, "Binning of the centrality axis"}; + ConfigurableAxis binsPt{"binsPt", {20, 0, 10}, "Binning of the pt"}; + ConfigurableAxis binsFT0CMult{"binsFT0CMult", {500, 0.0f, +500.0f}, "Binning of the FT0C multiplicity"}; + ConfigurableAxis binsMult{"binsMult", {500, 0.0f, +500.0f}, ""}; + // std vector of candidates std::vector hyperCandidates; // vector to keep track of MC mothers already filled @@ -219,7 +248,6 @@ struct hyperRecoTask { void init(InitContext const&) { - zorroSummary.setObject(zorro.getZorroSummary()); mRunNumber = 0; @@ -250,6 +278,11 @@ struct hyperRecoTask { const AxisSpec nSigma3HeAxis{nSigmaBins, "n_{#sigma}({}^{3}He)"}; const AxisSpec zVtxAxis{zVtxBins, "z_{vtx} (cm)"}; const AxisSpec centAxis{centBins, "Centrality"}; + const AxisSpec impactParamAxis{binsImpactPar, "Impact Parameter (b)"}; + const AxisSpec centFT0CAxis{binsCent, "Centrality (FT0C %)"}; + const AxisSpec binsFT0CMultAxis{binsFT0CMult, "FT0C multiplicity"}; + const AxisSpec ptAxis{binsPt, "#it{p}_{T} (GeV/#it{c})"}; + const AxisSpec multAxis = {binsMult, "Multiplicity #eta <0.5"}; hNsigma3HeSel = qaRegistry.add("hNsigma3HeSel", "; p_{TPC}/z (GeV/#it{c}); n_{#sigma} ({}^{3}He)", HistType::kTH2F, {rigidityAxis, nSigma3HeAxis}); hDeDx3HeSel = qaRegistry.add("hDeDx3HeSel", ";p_{TPC}/z (GeV/#it{c}); dE/dx", HistType::kTH2F, {rigidityAxis, dedxAxis}); @@ -259,11 +292,12 @@ struct hyperRecoTask { hH4LMassBefSel = qaRegistry.add("hH4LMassBefSel", ";M (GeV/#it{c}^{2}); ", HistType::kTH1D, {{60, 3.76, 3.84}}); hH4LMassTracked = qaRegistry.add("hH4LMassTracked", ";M (GeV/#it{c}^{2}); ", HistType::kTH1D, {{60, 3.76, 3.84}}); - hEvents = qaRegistry.add("hEvents", ";Events; ", HistType::kTH1D, {{4, -0.5, 3.5}}); + hEvents = qaRegistry.add("hEvents", ";Events; ", HistType::kTH1D, {{5, -0.5, 4.5}}); hEvents->GetXaxis()->SetBinLabel(1, "All"); hEvents->GetXaxis()->SetBinLabel(2, "sel8"); - hEvents->GetXaxis()->SetBinLabel(3, "kNoSameBunchPileup"); - hEvents->GetXaxis()->SetBinLabel(4, "kIsGoodZvtxFT0vsPV"); + hEvents->GetXaxis()->SetBinLabel(3, "z_{vtx}"); + hEvents->GetXaxis()->SetBinLabel(4, "kNoSameBunchPileup"); + hEvents->GetXaxis()->SetBinLabel(5, "kIsGoodZvtxFT0vsPV"); hEventsZorro = qaRegistry.add("hEventsZorro", ";Events; ", HistType::kTH1D, {{2, -0.5, 1.5}}); hEventsZorro->GetXaxis()->SetBinLabel(1, "Zorro before evsel"); @@ -284,6 +318,29 @@ struct hyperRecoTask { hCentFT0A = qaRegistry.add("hCentFT0A", ";Centrality; ", HistType::kTH1D, {{100, 0, 100}}); hCentFT0C = qaRegistry.add("hCentFT0C", ";Centrality; ", HistType::kTH1D, {{100, 0, 100}}); hCentFT0M = qaRegistry.add("hCentFT0M", ";Centrality; ", HistType::kTH1D, {{100, 0, 100}}); + + if (doprocessEventLossMC) { + hEvtMC = qaRegistry.add("QAEvent/hEvtMC", ";; ", HistType::kTH1D, {{3, -0.5, 2.5}}); + hEvtMC->GetXaxis()->SetBinLabel(1, "All gen evts"); + hEvtMC->GetXaxis()->SetBinLabel(2, "Gen evts with al least one reconstructed"); + hEvtMC->GetXaxis()->SetBinLabel(3, "Gen evts with no reconstructed collisions"); + // Infomation for all generated collisions collisions + hImpactParamGen = qaRegistry.add("QAEvent/McColAll/hImpactParamGen", "Impact parameter of generated MC events; Impact Parameter (b); Counts", HistType::kTH1D, {impactParamAxis}); + // Infomation for generated collisions collisions with at least one rec. event + hImpactParamReco = qaRegistry.add("QAEvent/McColAll/hImpactParamReco", "Impact parameter of generated MC events with at least one rec. evt; Impact Parameter (b); Counts", HistType::kTH1D, {impactParamAxis}); + hRecoCentralityColvsMultiplicityRecoEta05 = qaRegistry.add("QAEvent/McColAll/hRecoCentralityColvsMultiplicityRecoEta05", "Correlation between FT0C centrality and charged particle multiplicity in generated MC events with at least one rec. evt; Multiplicity #eta <0.5; Counts", HistType::kTH2D, {centFT0CAxis, multAxis}); + hRecoCentralityColvsImpactParamReco = qaRegistry.add("QAEvent/McColAll/hRecoCentralityColvsImpactParamReco", "Correlation between FT0C centrality and impact parameter in generated MC events with at least one rec. evt; Impact Parameter (b); Counts", HistType::kTH2D, {centFT0CAxis, impactParamAxis}); + // Information of generated 3HL in generated events + hGen3HLBeforeEvtSel = qaRegistry.add("QAEvent/McCol3HL/hGen3HLBeforeEvtSel", "3HL generated #it{p}_{T} distribution in all gen evt;#it{p}_{T} (GeV/#it{c}); Counts", HistType::kTH1D, {ptAxis}); + hGen3HLvsImpactParameterBeforeEvtSel = qaRegistry.add("QAEvent/McCol3HL/hGen3HLvsImpactParameterBeforeEvtSel", "Correlation 3HL generated #it{p}_{T} and impact parameter in all gen evt;#it{p}_{T} (GeV/#it{c}); Impact parameter (b)", HistType::kTH2D, {ptAxis, impactParamAxis}); + hGen3HLvsMultiplicityGenEta05BeforeEvtSel = qaRegistry.add("QAEvent/McCol3HL/hGen3HLvsMultiplicityGenEta05BeforeEvtSel", "Correlation 3HL generated #it{p}_{T} and charged particle multiplicity in all gen evt;#it{p}_{T} (GeV/#it{c}); Multiplicity #eta <0.5", HistType::kTH2D, {ptAxis, multAxis}); + hGen3HLvsMultiplicityFT0CBeforeEvtSel = qaRegistry.add("QAEvent/McCol3HL/hGen3HLvsMultiplicityFT0CBeforeEvtSel", "Correlation 3HL generated #it{p}_{T} and FT0C multiplicity in all gen evt;#it{p}_{T} (GeV/#it{c}); FT0C Multiplicity", HistType::kTH2D, {ptAxis, binsFT0CMultAxis}); + // Information of generated 3HL in generated events with at least one rec. event + hGen3HLAfterSel = qaRegistry.add("QAEvent/McCol3HL/hGen3HLAfterSel", "3HL generated #it{p}_{T} distribution in gen. evts with at least one rec. evt; #it{p}_{T} (GeV/#it{c}); Counts", HistType::kTH1D, {ptAxis}); + hGen3HLvsImpactParameterAfterSel = qaRegistry.add("QAEvent/McCol3HL/hGen3HLvsImpactParameterAfterSel", "Correlation 3HL generated #it{p}_{T} and impact parameter in gen. evts with at least one rec. evt;#it{p}_{T} (GeV/#it{c}); Impact parameter (b)", HistType::kTH2D, {ptAxis, impactParamAxis}); + hGen3HLvsMultiplicityGenEta05AfterSel = qaRegistry.add("QAEvent/McCol3HL/hGen3HLvsMultiplicityGenEta05AfterSel", "Correlation 3HL generated #it{p}_{T} and charged particle multiplicity in gen. evts with at least one rec. evt;#it{p}_{T} (GeV/#it{c}); Multiplicity #eta <0.5", HistType::kTH2D, {ptAxis, multAxis}); + hGen3HLvsMultiplicityFT0CAfterSel = qaRegistry.add("QAEvent/McCol3HL/hGen3HLvsMultiplicityFT0CAfterSel", "Correlation 3HL generated #it{p}_{T} and FT0C multiplicity in gen. evts with at least one rec;#it{p}_{T} (GeV/#it{c}); FT0C Multiplicity", HistType::kTH2D, {ptAxis, binsFT0CMultAxis}); + } } void initCCDB(aod::BCsWithTimestamps::iterator const& bc) @@ -366,12 +423,17 @@ struct hyperRecoTask { } } - if (!collision.selection_bit(aod::evsel::kIsTriggerTVX) || !collision.selection_bit(aod::evsel::kNoTimeFrameBorder) || std::abs(collision.posZ()) > 10) { + if (!collision.selection_bit(aod::evsel::kIsTriggerTVX) || !collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) { continue; } hEvents->Fill(1.); + if (std::abs(collision.posZ()) > 10) { + hEvents->Fill(2.); + continue; + } + if (zorroSelected) { hEventsZorro->Fill(1.); } @@ -380,14 +442,13 @@ struct hyperRecoTask { if (!collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { continue; } - hEvents->Fill(2.); + hEvents->Fill(3.); } - if (cfgEvSelkIsGoodZvtxFT0vsPV) { if (!collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) { continue; } - hEvents->Fill(3.); + hEvents->Fill(4.); } goodCollision[collision.globalIndex()] = true; @@ -408,23 +469,27 @@ struct hyperRecoTask { if (collision.has_mcCollision()) { recoCollisionIds[collision.mcCollisionId()] = collision.globalIndex(); } - if (!collision.selection_bit(aod::evsel::kIsTriggerTVX) || !collision.selection_bit(aod::evsel::kNoTimeFrameBorder) || std::abs(collision.posZ()) > 10) + if (!collision.selection_bit(aod::evsel::kIsTriggerTVX) || !collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) continue; hEvents->Fill(1.); + if (std::abs(collision.posZ()) > 10) { + hEvents->Fill(2.); + continue; + } + if (cfgEvSelkNoSameBunchPileup) { if (!collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { continue; } - hEvents->Fill(2.); + hEvents->Fill(3.); } - if (cfgEvSelkIsGoodZvtxFT0vsPV) { if (!collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) { continue; } - hEvents->Fill(3.); + hEvents->Fill(4.); } if (collision.has_mcCollision()) { @@ -437,7 +502,6 @@ struct hyperRecoTask { hCentFT0M->Fill(collision.centFT0M()); } } - template void fillHyperCand(Ttrack& heTrack, Ttrack& piTrack, CollBracket collBracket, const Tcolls& collisions, hyperCandidate& hypCand) { @@ -922,6 +986,111 @@ struct hyperRecoTask { processMC(collisions, mcCollisions, V0s, tracks, ambiTracks, bcs, trackLabelsMC, particlesMC); } PROCESS_SWITCH(hyperRecoTask, processMCTracked, "MC analysis with tracked V0s", false); + + template + bool passEvtSel(const CollType& collision) + { + if (!collision.sel8()) + return false; + + if ((std::abs(collision.posZ())) > 10) + return false; + + if (cfgEvSelkNoSameBunchPileup && !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) + return false; + + if (cfgEvSelkIsGoodZvtxFT0vsPV && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) + return false; + + return true; + } + + void processEventLossMC(McCollisionMults::iterator const& mcCollision, soa::SmallGroups const& collisions, aod::McParticles const& GenParticles) + { + if (std::abs(mcCollision.posZ()) > 10) { + return; + } + + //////////// Event loss estimation via impact parameter and multiplicity by MCFT0C + + // Fill all generated events + hEvtMC->Fill(0); + hImpactParamGen->Fill(mcCollision.impactParameter()); + + // Fill generated events with no reconstructed collisions + if (collisions.size() == 0) { + hEvtMC->Fill(1); + } + + // Define the generated events with at least one reconstructed event + bool atLeastOneRecoEvt = false; + auto centralityFT0C = -999.; + + for (auto const& col : collisions) { + if (!passEvtSel(col)) { + continue; + } + centralityFT0C = col.centFT0C(); + atLeastOneRecoEvt = true; + } + + if (atLeastOneRecoEvt) { + hEvtMC->Fill(2); + hImpactParamReco->Fill(mcCollision.impactParameter()); + hRecoCentralityColvsMultiplicityRecoEta05->Fill(centralityFT0C, mcCollision.multMCNParticlesEta05()); + hRecoCentralityColvsImpactParamReco->Fill(centralityFT0C, mcCollision.impactParameter()); + } + // Construct the H3L 4-vector based on the generated daugthers identification by PDG + ROOT::Math::PxPyPzMVector daugh1, daugh2, mother; + + for (const auto& genParticle : GenParticles) { + if (std::abs(genParticle.y()) > 1) + continue; + if (std::abs(genParticle.pdgCode()) != hyperPdg) + continue; + + auto daughters = genParticle.daughters_as(); + + bool dauHe3 = false, dauPiMinus = false, dauAntiHe3 = false, dauPiPos = true; + + for (const auto& daughter : daughters) { + if (daughter.pdgCode() == heDauPdg) { + dauHe3 = true; + daugh1 = ROOT::Math::PxPyPzMVector(daughter.px(), daughter.py(), daughter.pz(), he3Mass); + } else if (daughter.pdgCode() == -piDauPdg) { + dauPiMinus = true; + daugh2 = ROOT::Math::PxPyPzMVector(daughter.px(), daughter.py(), daughter.pz(), piMass); + } + if (daughter.pdgCode() == -heDauPdg) { + dauAntiHe3 = true; + daugh1 = ROOT::Math::PxPyPzMVector(daughter.px(), daughter.py(), daughter.pz(), he3Mass); + } else if (daughter.pdgCode() == piDauPdg) { + dauPiPos = true; + daugh2 = ROOT::Math::PxPyPzMVector(daughter.px(), daughter.py(), daughter.pz(), piMass); + } + } + // Check pairs to avoid wrong charge associations + if (!((dauHe3 && dauPiMinus) || !(dauAntiHe3 && dauPiPos))) + continue; + + mother = daugh1 + daugh2; + + // Fill informations for generated 3HL in all generated events + hGen3HLBeforeEvtSel->Fill(mother.pt()); + hGen3HLvsImpactParameterBeforeEvtSel->Fill(mother.pt(), mcCollision.impactParameter()); + hGen3HLvsMultiplicityGenEta05BeforeEvtSel->Fill(mother.pt(), mcCollision.multMCNParticlesEta05()); + hGen3HLvsMultiplicityFT0CBeforeEvtSel->Fill(mother.pt(), mcCollision.multMCFT0C()); + + // Fill informations for generated 3HL in generated events with at least one reconstructed event + if (atLeastOneRecoEvt) { + hGen3HLAfterSel->Fill(mother.pt()); + hGen3HLvsImpactParameterAfterSel->Fill(mother.pt(), mcCollision.impactParameter()); + hGen3HLvsMultiplicityGenEta05AfterSel->Fill(mother.pt(), mcCollision.multMCNParticlesEta05()); + hGen3HLvsMultiplicityFT0CAfterSel->Fill(mother.pt(), mcCollision.multMCFT0C()); + } + } + } + PROCESS_SWITCH(hyperRecoTask, processEventLossMC, "Event loss analysis", false); }; WorkflowSpec From 8fba43cf99c32d866ae3723c875bd309826fff65 Mon Sep 17 00:00:00 2001 From: jaimenorman Date: Tue, 17 Mar 2026 12:40:25 +0000 Subject: [PATCH 300/347] [PWGJE] remove outlier collision rejection (#15393) --- PWGJE/Tasks/jetFinderQA.cxx | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/PWGJE/Tasks/jetFinderQA.cxx b/PWGJE/Tasks/jetFinderQA.cxx index f42c1dad41b..40956d71038 100644 --- a/PWGJE/Tasks/jetFinderQA.cxx +++ b/PWGJE/Tasks/jetFinderQA.cxx @@ -1062,14 +1062,11 @@ struct JetFinderQATask { } PROCESS_SWITCH(JetFinderQATask, processJetsMCD, "jet finder QA mcd", false); - void processJetsMCDWeighted(soa::Filtered>::iterator const& collision, aod::JetMcCollisions const&, soa::Join const& jets, aod::JetTracks const&) + void processJetsMCDWeighted(soa::Filtered>::iterator const& collision, aod::JetMcCollisions const&, soa::Join const& jets, aod::JetTracks const&) { if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { return; } - if (collision.isOutlier()) { - return; - } for (auto const& jet : jets) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { continue; @@ -1107,7 +1104,7 @@ struct JetFinderQATask { } PROCESS_SWITCH(JetFinderQATask, processJetsMCP, "jet finder QA mcp", false); - void processJetsMCPWeighted(soa::Join::iterator const& jet, aod::JetParticles const&, soa::Join const& mcCollisions, soa::Filtered> const& collisions) + void processJetsMCPWeighted(soa::Join::iterator const& jet, aod::JetParticles const&, soa::Join const& mcCollisions, soa::Filtered const& collisions) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { return; @@ -1124,7 +1121,7 @@ struct JetFinderQATask { } if (checkMcCollisionIsMatched) { auto collisionspermcpjet = collisions.sliceBy(CollisionsPerMCPCollision, jet.mcCollisionId()); - if (collisionspermcpjet.size() >= 1 && jetderiveddatautilities::selectCollision(collisionspermcpjet.begin(), eventSelectionBits) && !collisionspermcpjet.begin().isOutlier()) { + if (collisionspermcpjet.size() >= 1 && jetderiveddatautilities::selectCollision(collisionspermcpjet.begin(), eventSelectionBits)) { fillMCPHistograms(jet, mcCollision.begin().weight(), mcCollision.begin().ptHard()); } } else { @@ -1164,7 +1161,7 @@ struct JetFinderQATask { } PROCESS_SWITCH(JetFinderQATask, processJetsMCPMCDMatched, "jet finder QA matched mcp and mcd", false); - void processJetsMCPMCDMatchedWeighted(soa::Filtered>::iterator const& collision, + void processJetsMCPMCDMatchedWeighted(soa::Filtered>::iterator const& collision, aod::JetMcCollisions const&, soa::Join const& mcdjets, soa::Join const&, @@ -1173,9 +1170,6 @@ struct JetFinderQATask { if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { return; } - if (collision.isOutlier()) { - return; - } for (const auto& mcdjet : mcdjets) { if (!jetfindingutilities::isInEtaAcceptance(mcdjet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { continue; @@ -1363,7 +1357,7 @@ struct JetFinderQATask { } PROCESS_SWITCH(JetFinderQATask, processTracks, "QA for charged tracks", false); - void processTracksWeighted(soa::Join::iterator const& collision, + void processTracksWeighted(soa::Join::iterator const& collision, aod::JetMcCollisions const&, soa::Filtered> const& tracks) { @@ -1383,11 +1377,6 @@ struct JetFinderQATask { } registry.fill(HIST("h_collisions"), 2.5); registry.fill(HIST("h_collisions_weighted"), 2.5, eventWeight); - if (collision.isOutlier()) { - return; - } - registry.fill(HIST("h_collisions"), 3.5); - registry.fill(HIST("h_collisions_weighted"), 3.5, eventWeight); fillTrackHistograms(collision, tracks, eventWeight, collision.mcCollision().ptHard()); } PROCESS_SWITCH(JetFinderQATask, processTracksWeighted, "QA for charged tracks weighted", false); From 2627cb9337c1f6855b850d45ee2bd77f433bd5f6 Mon Sep 17 00:00:00 2001 From: fuchuncui <162277233+fuchuncui@users.noreply.github.com> Date: Tue, 17 Mar 2026 21:02:10 +0800 Subject: [PATCH 301/347] [PWGCF] fix a bug about QAhisto filling of Casc (#15422) --- PWGCF/Flow/Tasks/flowGfwOmegaXi.cxx | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/PWGCF/Flow/Tasks/flowGfwOmegaXi.cxx b/PWGCF/Flow/Tasks/flowGfwOmegaXi.cxx index 7f4bb419769..7ed06b21a6c 100644 --- a/PWGCF/Flow/Tasks/flowGfwOmegaXi.cxx +++ b/PWGCF/Flow/Tasks/flowGfwOmegaXi.cxx @@ -497,6 +497,11 @@ struct FlowGfwOmegaXi { registry.add("QAhisto/Omega/hqadcaCascdauafter", "", {HistType::kTH1D, {{100, 0, 1}}}); registry.add("QAhisto/Omega/hqadcaCascV0daubefore", "", {HistType::kTH1D, {{100, 0, 1}}}); registry.add("QAhisto/Omega/hqadcaCascV0dauafter", "", {HistType::kTH1D, {{100, 0, 1}}}); + registry.add("QAhisto/Omega/hTOFnsigmaposPi", "", {HistType::kTH1D, {{1000, -100, 100}}}); + registry.add("QAhisto/Omega/hTOFnsigmaposPr", "", {HistType::kTH1D, {{1000, -100, 100}}}); + registry.add("QAhisto/Omega/hBachTOFnsigmavsPt", "", {HistType::kTH2D, {{1000, -100, 100}, cfgaxisPt}}); + registry.add("QAhisto/Omega/hLaPrTOFnsigmavsPt", "", {HistType::kTH2D, {{1000, -100, 100}, cfgaxisPt}}); + registry.add("QAhisto/Omega/hLaPiTOFnsigmavsPt", "", {HistType::kTH2D, {{1000, -100, 100}, cfgaxisPt}}); } // cumulant of flow @@ -1378,18 +1383,12 @@ struct FlowGfwOmegaXi { ((std::fabs(itsResponse.nSigmaITS(bachelor)) < cfgNSigma[6]) || bachelor.pt() > bachPtcut) && ((std::fabs(itsResponse.nSigmaITS(posdau)) < cfgNSigma[7]) || posdau.pt() > dauLaPrPtcut) && ((std::fabs(itsResponse.nSigmaITS(negdau)) < cfgNSigma[6]) || negdau.pt() > dauLaPiPtcut)) { registry.fill(HIST("InvMassXi_all"), casc.pt(), casc.mXi(), casc.eta(), cent); isXi = true; - registry.fill(HIST("QAhisto/Xi/hTOFnsigmaposPr"), casc.tofNSigmaXiLaPr()); - registry.fill(HIST("QAhisto/Xi/hBachTOFnsigmavsPt"), casc.tofNSigmaXiPi(), bachelor.pt()); - registry.fill(HIST("QAhisto/Xi/hLaPrTOFnsigmavsPt"), casc.tofNSigmaXiLaPr(), posdau.pt()); } else if (casc.sign() > 0 && std::fabs(casc.yXi()) < cfgCasc_rapidity && (std::fabs(bachelor.tpcNSigmaPi()) < cfgNSigma[0] && std::fabs(negdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(posdau.tpcNSigmaPi()) < cfgNSigma[0]) && ((std::fabs(casc.tofNSigmaXiPi()) < cfgNSigma[3] || bachelor.pt() < bachPtcut) && (std::fabs(casc.tofNSigmaXiLaPi()) < cfgNSigma[3] || posdau.pt() < dauLaPiPtcut)) && ((std::fabs(itsResponse.nSigmaITS(bachelor)) < cfgNSigma[6]) || bachelor.pt() > bachPtcut) && ((std::fabs(itsResponse.nSigmaITS(negdau)) < cfgNSigma[7]) || negdau.pt() > dauLaPrPtcut) && ((std::fabs(itsResponse.nSigmaITS(posdau)) < cfgNSigma[6]) || posdau.pt() > dauLaPiPtcut)) { registry.fill(HIST("InvMassXi_all"), casc.pt(), casc.mXi(), casc.eta(), cent); isXi = true; - registry.fill(HIST("QAhisto/Xi/hTOFnsigmaposPi"), casc.tofNSigmaXiLaPi()); - registry.fill(HIST("QAhisto/Xi/hBachTOFnsigmavsPt"), casc.tofNSigmaXiPi(), bachelor.pt()); - registry.fill(HIST("QAhisto/Xi/hLaPiTOFnsigmavsPt"), casc.tofNSigmaXiLaPi(), posdau.pt()); } } // fill QA @@ -1405,9 +1404,15 @@ struct FlowGfwOmegaXi { if (casc.sign() > 0) { registry.fill(HIST("QAhisto/Xi/hqadcaCascLaprtoPVbefore"), casc.dcapostopv()); registry.fill(HIST("QAhisto/Xi/hqadcaCascLapitoPVbefore"), casc.dcanegtopv()); + registry.fill(HIST("QAhisto/Xi/hTOFnsigmaposPi"), casc.tofNSigmaXiLaPi()); + registry.fill(HIST("QAhisto/Xi/hBachTOFnsigmavsPt"), casc.tofNSigmaXiPi(), bachelor.pt()); + registry.fill(HIST("QAhisto/Xi/hLaPiTOFnsigmavsPt"), casc.tofNSigmaXiLaPi(), posdau.pt()); } else { registry.fill(HIST("QAhisto/Xi/hqadcaCascLaprtoPVbefore"), casc.dcanegtopv()); registry.fill(HIST("QAhisto/Xi/hqadcaCascLapitoPVbefore"), casc.dcapostopv()); + registry.fill(HIST("QAhisto/Xi/hTOFnsigmaposPr"), casc.tofNSigmaXiLaPr()); + registry.fill(HIST("QAhisto/Xi/hBachTOFnsigmavsPt"), casc.tofNSigmaXiPi(), bachelor.pt()); + registry.fill(HIST("QAhisto/Xi/hLaPrTOFnsigmavsPt"), casc.tofNSigmaXiLaPr(), posdau.pt()); } } if (isOmega) { @@ -1421,9 +1426,15 @@ struct FlowGfwOmegaXi { if (casc.sign() > 0) { registry.fill(HIST("QAhisto/Omega/hqadcaCascLaprtoPVbefore"), casc.dcapostopv()); registry.fill(HIST("QAhisto/Omega/hqadcaCascLapitoPVbefore"), casc.dcanegtopv()); + registry.fill(HIST("QAhisto/Omega/hTOFnsigmaposPi"), casc.tofNSigmaXiLaPi()); + registry.fill(HIST("QAhisto/Omega/hBachTOFnsigmavsPt"), casc.tofNSigmaXiPi(), bachelor.pt()); + registry.fill(HIST("QAhisto/Omega/hLaPiTOFnsigmavsPt"), casc.tofNSigmaXiLaPi(), posdau.pt()); } else { registry.fill(HIST("QAhisto/Omega/hqadcaCascLaprtoPVbefore"), casc.dcanegtopv()); registry.fill(HIST("QAhisto/Omega/hqadcaCascLapitoPVbefore"), casc.dcapostopv()); + registry.fill(HIST("QAhisto/Omega/hTOFnsigmaposPr"), casc.tofNSigmaXiLaPr()); + registry.fill(HIST("QAhisto/Omega/hBachTOFnsigmavsPt"), casc.tofNSigmaXiPi(), bachelor.pt()); + registry.fill(HIST("QAhisto/Omega/hLaPrTOFnsigmavsPt"), casc.tofNSigmaXiLaPr(), posdau.pt()); } } } From e521f2640d91ed1c070d00f30dc40e43c1664306 Mon Sep 17 00:00:00 2001 From: nkaratze Date: Tue, 17 Mar 2026 16:04:39 +0100 Subject: [PATCH 302/347] [PWGLF] Added Nch Analysis and small changes (#15405) --- PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx | 67 ++++++++++++++++++-- 1 file changed, 60 insertions(+), 7 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx b/PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx index 32dc652f346..b3dca4c0a5c 100644 --- a/PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx +++ b/PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx @@ -70,6 +70,7 @@ struct V0PtInvMassPlots { HistogramRegistry rAntilambdaSplitMassPlotsPerPtBin{"AntiLambdaSplitMassPlotsPerPtBin", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; HistogramRegistry rFeeddownMatrices{"FeeddownMatrices", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; HistogramRegistry rMCCorrections{"MCCorrections", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rNchAnalysis{"NchAnalysis", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; // Configurable for histograms Configurable nBins{"nBins", 100, "N bins in all histos"}; @@ -81,6 +82,7 @@ struct V0PtInvMassPlots { Configurable nSigmaTPCProton{"nSigmaTPCProton", 4, "nSigmaTPCProton"}; Configurable compv0masscut{"compv0masscut", 0.01, "CompetitiveV0masscut (GeV)"}; Configurable etadau{"etadau", 0.8, "Eta Daughters"}; + Configurable etagen{"etagen", 0.8, "Eta Generated"}; Configurable rapidityCut{"rapidityCut", 0.5, "V0 Rapidity Window"}; Configurable itsMinHits{"itsMinHits", 1.0, "Minimum Hits of Daughter Tracks in the ITS"}; @@ -125,7 +127,7 @@ struct V0PtInvMassPlots { Configurable doLambdadcaposdautopv{"doLambdadcaposdautopv", true, "Enable Lambda DCA pos daughter to PV Topological Cut"}; Configurable doLambdadcanegdautopv{"doLambdadcanegdautopv", true, "Enable Lambda DCA neg daughter to PV Topological Cut"}; - // Configurables switches for Lambda selection + // Configurables switches for AntiLambda selection Configurable dotruthAntiLambda{"dotruthAntiLambda", true, "Enable AntiLambda MC Matching"}; Configurable doAntilambdaTPCPID{"doAntilambdaTPCPID", true, "Enable AntiLambda TPC PID"}; Configurable doAntilambdacomptmasscut{"doAntilambdacomptmasscut", true, "Enable AntiLambda Competitive V0 Mass Cut"}; @@ -164,10 +166,11 @@ struct V0PtInvMassPlots { Configurable antilambdamaxct{"antilambdamaxct", 30.00, "AntiLambda maximum ct value"}; Configurable antilambdaparamArmenterosCut{"antilambdaparamArmenterosCut", 0.2, "AntiLambda Armenteros Cut on parameter"}; - // Configurables for Specific V0s analysis + // Configurables for Specific Analysis Configurable kzeroAnalysis{"kzeroAnalysis", true, "Enable K0sh Pt Analysis"}; Configurable lambdaAnalysis{"lambdaAnalysis", true, "Enable Lambda Pt Analysis"}; Configurable antiLambdaAnalysis{"antiLambdaAnalysis", true, "Enable AntiLambda Pt Analysis"}; + Configurable doNchAnalysis{"doNchAnalysis", true, "Enable Nch vs Centrality Analysis"}; // Configurable string for Different Pt Bins Configurable kzeroSettingPtBinsString{"kzeroSettingPtBinsString", {"0.0,0.15,0.3,0.45,0.6,0.75,0.9,1.05,1.2,1.35,1.5,1.65,1.8,1.95,2.1,2.25,2.4,2.55,2.7,2.85,3.0"}, "K0sh Pt Bin Values"}; @@ -215,6 +218,7 @@ struct V0PtInvMassPlots { AxisSpec lambdaPtAxis = {lambdaptedgevalues, "#it{p}_{T} (GeV/#it{c})"}; AxisSpec antilambdaPtAxis = {antilambdaptedgevalues, "#it{p}_{T} (GeV/#it{c})"}; AxisSpec centAxis = {100, 0.0f, 100.0f, "#it{Centrality} (%)"}; + AxisSpec nchAxis = {100, 0.0f, 100.0f, "#it{N}_{ch} (%)"}; AxisSpec armenterosQtAxis = {nBinsArmenteros, 0.0f, 0.3f, "#it{p}_{T} (GeV/#it{c})"}; AxisSpec armenterosasymAxis = {nBinsArmenteros, -1.f, 1.f, "#it{p}^{+}_{||}-#it{p}^{-}_{||}/#it{p}^{+}_{||}+#it{p}^{-}_{||}"}; AxisSpec vertexZAxis = {nBins, -11.0f, 11.0f, "vrtx_{Z} [cm]"}; @@ -344,6 +348,12 @@ struct V0PtInvMassPlots { rMCCorrections.add("hAntiXiZeroGeneratedPtSpectrum", "hAntiXiZeroGeneratedPtSpectrum", {HistType::kTH2D, {antilambdaPtAxis, centAxis}}); rMCCorrections.add("hAntiOmegaGeneratedPtSpectrum", "hAntiOmegaGeneratedPtSpectrum", {HistType::kTH2D, {antilambdaPtAxis, centAxis}}); rMCCorrections.add("hPhiGeneratedPtSpectrum", "hPhiGeneratedPtSpectrum", {HistType::kTH2D, {k0ShortPtAxis, centAxis}}); + rMCCorrections.add("hGenPartcles", "hGenPartcles", {HistType::kTH2D, {nchAxis, centAxis}}); + + // NCh Analysis + rNchAnalysis.add("hNchCentralityGenerated", "hNchCentralityGenerated", {HistType::kTH2D, {centAxis, nchAxis}}); // Nch vs Centrality Generated + rNchAnalysis.add("hNchCentralityGeneratedAfterEventSelection", "hNchCentralityGeneratedAfterEventSelection", {HistType::kTH2D, {centAxis, nchAxis}}); // Nch vs Centrality Generated After Event Selection + rNchAnalysis.add("hNchCentrality", "hNchCentrality", {HistType::kTH2D, {centAxis, nchAxis}}); // Nch vs Centrality } // Event selection function @@ -388,6 +398,39 @@ struct V0PtInvMassPlots { return true; } + // Charged Particle Selection Function + template + bool acceptGeneratedParticle(TParticle const& particle, TCollision const& mcCollision) + { + rMCCorrections.fill(HIST("hGenPartcles"), 0.5, mcCollision.centFT0M()); + rMCCorrections.get(HIST("hGenPartcles"))->GetXaxis()->SetBinLabel(1, "All Gen Particles"); + if (!particle.isPhysicalPrimary()) { // Daughters Pseudorapidity Cut + return false; + } + rMCCorrections.fill(HIST("hGenPartcles"), 1.5, mcCollision.centFT0M()); + rMCCorrections.get(HIST("hGenPartcles"))->GetXaxis()->SetBinLabel(2, "Physical Primary"); + if (!particle.producedByGenerator()) { + return false; + } + rMCCorrections.fill(HIST("hGenPartcles"), 2.5, mcCollision.centFT0M()); + rMCCorrections.get(HIST("hGenPartcles"))->GetXaxis()->SetBinLabel(3, "Produced by Generator"); + if (std::abs(particle.eta()) > etagen) { // Eta cut + return false; + } + rMCCorrections.fill(HIST("hGenPartcles"), 3.5, mcCollision.centFT0M()); + rMCCorrections.get(HIST("hGenPartcles"))->GetXaxis()->SetBinLabel(4, "Eta Cut"); + auto pdgParticle = pdgDB->GetParticle(particle.pdgCode()); + if (pdgParticle == nullptr) { + return false; + } + if (std::abs(pdgParticle->Charge()) < 3) { + return false; + } + rMCCorrections.fill(HIST("hGenPartcles"), 4.5, mcCollision.centFT0M()); + rMCCorrections.get(HIST("hGenPartcles"))->GetXaxis()->SetBinLabel(4, "Charge Cut"); + return true; + } + // V0 selection function template bool acceptV0(TV0 const& v0, Track const& posDaughterTrack, Track const& negDaughterTrack, TCollision const& collision) @@ -710,6 +753,7 @@ struct V0PtInvMassPlots { return; } rMCCorrections.fill(HIST("hNEvents_Corrections"), 1.5, mcCollision.centFT0M()); // Event Efficiency Denominator + int NParticlesPerCollision = 0; // Counter for the number of particles per collision for the Nch analysis // Particles (of interest) Generated Pt Spectrum and Signal Loss Denominator Loop for (const auto& mcParticle : mcParticles) { if (std::abs(mcParticle.y()) < rapidityCut) { @@ -757,7 +801,11 @@ struct V0PtInvMassPlots { } } } + if (acceptGeneratedParticle(mcParticle, mcCollision)) { + NParticlesPerCollision++; + } } + rNchAnalysis.fill(HIST("hNchCentralityGenerated"), mcCollision.centFT0M(), NParticlesPerCollision); // Signal Loss Numenator Loop for (const auto& collision : collisions) { rMCCorrections.fill(HIST("hNEvents_Corrections"), 2.5, mcCollision.centFT0M()); // Number of Events Reconsctructed @@ -766,6 +814,9 @@ struct V0PtInvMassPlots { } rMCCorrections.fill(HIST("hNEvents_Corrections"), 3.5, mcCollision.centFT0M()); // Event Split Denomimator and Event Efficiency Numenator for (const auto& mcParticle : mcParticles) { + if (acceptGeneratedParticle(mcParticle, mcCollision)) { + NParticlesPerCollision++; // Counter to fill the NchCerntralityPlot after the loop + } if (!mcParticle.isPhysicalPrimary()) { continue; } @@ -786,11 +837,12 @@ struct V0PtInvMassPlots { } } } + rNchAnalysis.fill(HIST("hNchCentralityGeneratedAfterEventSelection"), mcCollision.centFT0M(), NParticlesPerCollision); // End of Signal Loss Numenator Loop } // This is the Process for the MC reconstructed Data // void recMCProcess(soa::Join::iterator const& collision, - void recMCProcess(soa::Join::iterator const& collision, + void recMCProcess(soa::Join::iterator const& collision, soa::Join const& /*mcCollisions*/, soa::Join const& V0s, DaughterTracks const&, // no need to define a variable for tracks, if we don't access them directly @@ -827,7 +879,8 @@ struct V0PtInvMassPlots { if (!acceptEvent(collision)) { // Event Selection return; } - rPtAnalysis.fill(HIST("hNRecEvents"), 0.5, mcCollision.centFT0M()); // Event Split Numenator + rPtAnalysis.fill(HIST("hNRecEvents"), 0.5, mcCollision.centFT0M()); // Event Split Numenator + rNchAnalysis.fill(HIST("hNchCentrality"), mcCollision.centFT0M(), collision.multNTracksGlobal()); // Nch vs Centrality for (const auto& v0 : V0s) { // Checking that the V0 is a true K0s/Lambdas/Antilambdas and then filling the parameter histograms and the invariant mass plots for different cuts (which are taken from namespace) const auto& posDaughterTrack = v0.template posTrack_as(); @@ -952,7 +1005,7 @@ struct V0PtInvMassPlots { } } // This is the process for Real Data - void dataProcess(soa::Join::iterator const& collision, + void dataProcess(soa::Join::iterator const& collision, aod::V0Datas const& V0s, DaughterTracks const&) { @@ -981,11 +1034,11 @@ struct V0PtInvMassPlots { for (int i = 0; i < nAntilambdaHistograms + 1; i++) { antilambdaptedgevalues[i] = std::stod(pthistos::antilambdaPtBins[i]); } - if (!acceptEvent(collision)) { // Event Selection return; } - rPtAnalysis.fill(HIST("hNRecEvents"), 0.5, collision.centFT0M()); // Number of recorded events + rPtAnalysis.fill(HIST("hNRecEvents"), 0.5, collision.centFT0M()); // Number of recorded events + rNchAnalysis.fill(HIST("hNchCentrality"), collision.centFT0M(), collision.multNTracksGlobal()); // Nch vs Centrality for (const auto& v0 : V0s) { // Checking that the V0 is a true K0s/Lambdas/Antilambdas and then filling the parameter histograms and the invariant mass plots for different cuts (which are taken from namespace) const auto& posDaughterTrack = v0.template posTrack_as(); From 2243201b5bc61fd2b997e20b4d08489faa75310c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josu=C3=A9=20Mart=C3=ADnez=20Garc=C3=ADa?= Date: Tue, 17 Mar 2026 10:39:21 -0600 Subject: [PATCH 303/347] [PWGUD] Adding selection criteria control over events (#15406) --- PWGUD/Tasks/upcPhotonuclearAnalysisJMG.cxx | 339 +++++++++++++-------- 1 file changed, 218 insertions(+), 121 deletions(-) diff --git a/PWGUD/Tasks/upcPhotonuclearAnalysisJMG.cxx b/PWGUD/Tasks/upcPhotonuclearAnalysisJMG.cxx index fd1b467951b..da1328981d9 100644 --- a/PWGUD/Tasks/upcPhotonuclearAnalysisJMG.cxx +++ b/PWGUD/Tasks/upcPhotonuclearAnalysisJMG.cxx @@ -47,6 +47,18 @@ namespace o2::aod { namespace tree { +DECLARE_SOA_COLUMN(GapSide, gapSide, float); +DECLARE_SOA_COLUMN(Sbp, sbp, int); +DECLARE_SOA_COLUMN(ITSROFb, itsROFb, int); +DECLARE_SOA_COLUMN(VtxITSTPCCut, vtxITSTPCCut, int); +DECLARE_SOA_COLUMN(ZVtxFT0vsPvCut, zVtxFT0vsPvCut, int); +DECLARE_SOA_COLUMN(TimeZNA, timeZNA, float); +DECLARE_SOA_COLUMN(TimeZNC, timeZNC, float); +DECLARE_SOA_COLUMN(EnergyZNA, energyZNA, float); +DECLARE_SOA_COLUMN(EnergyZNC, energyZNC, float); +DECLARE_SOA_COLUMN(AmplitudeFV0A, amplitudeFV0A, float); +DECLARE_SOA_COLUMN(Occupancy, occupancy, float); +DECLARE_SOA_COLUMN(UPCMode, upcMode, float); DECLARE_SOA_COLUMN(PtSideA, ptSideA, std::vector); DECLARE_SOA_COLUMN(RapSideA, rapSideA, std::vector); DECLARE_SOA_COLUMN(PhiSideA, phiSideA, std::vector); @@ -71,6 +83,18 @@ DECLARE_SOA_COLUMN(NchSideC, nchSideC, int); DECLARE_SOA_COLUMN(MultiplicitySideC, multiplicitySideC, int); } // namespace tree DECLARE_SOA_TABLE(TREE, "AOD", "Tree", + tree::GapSide, + tree::Sbp, + tree::ITSROFb, + tree::VtxITSTPCCut, + tree::ZVtxFT0vsPvCut, + tree::TimeZNA, + tree::TimeZNC, + tree::EnergyZNA, + tree::EnergyZNC, + tree::AmplitudeFV0A, + tree::Occupancy, + tree::UPCMode, tree::PtSideA, tree::RapSideA, tree::PhiSideA, @@ -117,17 +141,35 @@ struct UpcPhotonuclearAnalysisJMG { Configurable nEventsMixed{"nEventsMixed", 3, {"Events to be Mixed"}}; Configurable factorEventsMixed{"factorEventsMixed", 100, {"factorEventsMixed to events mixed"}}; Configurable myZVtxCut{"myZVtxCut", 10., {"My collision cut"}}; - Configurable myTimeZNACut{"myTimeZNACut", 2., {"My collision cut"}}; - Configurable myTimeZNCCut{"myTimeZNCCut", 2., {"My collision cut"}}; + Configurable useSBP{"useSBP", false, {"My collision cut"}}; + Configurable sbpCut{"sbpCut", 1, {"My collision cut"}}; + Configurable useITSROFb{"useITSROFb", false, {"My collision cut"}}; + Configurable itsROFbCut{"itsROFbCut", 1, {"My collision cut"}}; + Configurable useVtxITSTPC{"useVtxITSTPC", false, {"My collision cut"}}; + Configurable vtxITSTPCCut{"vtxITSTPCCut", 1, {"My collision cut"}}; + Configurable useZVtxFT0vsPv{"useZVtxFT0vsPv", false, {"My collision cut"}}; + Configurable zVtxFT0vsPvCut{"zVtxFT0vsPvCut", 1, {"My collision cut"}}; + Configurable useEnergyZN{"useEnergyZN", false, {"My collision cut"}}; + Configurable useGapSideVariable{"useGapSideVariable", false, {"My collision cut"}}; + Configurable useUPCMode{"useUPCMode", false, {"My collision cut"}}; + Configurable upcModeCut{"upcModeCut", 1, {"My collision cut"}}; + Configurable useOccupancy{"useOccupancy", false, {"My collision cut"}}; + Configurable cutOccupancy{"cutOccupancy", 1000, {"My collision cut"}}; // Declare configurables on side A gap - Configurable cutGapAMyEnergyZNA{"cutGapAMyEnergyZNA", 0., {"My collision cut. A Gap"}}; + Configurable cutGapATimeZNA{"cutGapATimeZNA", 2., {"My collision cut. Gap Side A"}}; + Configurable cutGapATimeZNC{"cutGapATimeZNC", 2., {"My collision cut. Gap Side A"}}; + Configurable cutGapAMyEnergyZNA{"cutGapAMyEnergyZNA", 0., {"My collision cut. Gap Side A"}}; // Configurable cutAGapMyAmplitudeFT0AMax{"cutAGapMyAmplitudeFT0AMax", 200., {"My collision cut. A Gap"}}; - Configurable cutGapAMyEnergyZNC{"cutGapAMyEnergyZNC", 1., {"My collision cut. A Gap"}}; + Configurable cutGapAMyEnergyZNC{"cutGapAMyEnergyZNC", 1., {"My collision cut. Gap Side A"}}; + Configurable useFV0{"useFV0", false, {"My collision cut. Gap Side A"}}; + Configurable cutGapAFV0Amplitude{"cutGapAFV0Amplitude", 50, {"My collision cut. Gap Side A"}}; // Configurable cutAGapMyAmplitudeFT0CMin{"cutAGapMyAmplitudeFT0CMin", 0., {"My collision cut. A Gap"}}; // Declare configurables on side C gap - Configurable cutGapCMyEnergyZNA{"cutGapCMyEnergyZNA", 1., {"My collision cut. C Gap"}}; + Configurable cutGapCTimeZNA{"cutGapCTimeZNA", 2., {"My collision cut. Gap Side C"}}; + Configurable cutGapCTimeZNC{"cutGapCTimeZNC", 2., {"My collision cut. Gap Side C"}}; + Configurable cutGapCMyEnergyZNA{"cutGapCMyEnergyZNA", 1., {"My collision cut. Gap Side C"}}; // Configurable cutCGapMyAmplitudeFT0AMin{"cutCGapMyAmplitudeFT0AMin", 0., {"My collision cut. A Gap"}}; - Configurable cutGapCMyEnergyZNC{"cutGapCMyEnergyZNC", 0., {"My collision cut. C Gap"}}; + Configurable cutGapCMyEnergyZNC{"cutGapCMyEnergyZNC", 0., {"My collision cut. Gap Side C"}}; // Configurable cutCGapMyAmplitudeFT0CMax{"cutCGapMyAmplitudeFT0CMax", 200., {"My collision cut. A Gap"}}; // Declare configurables on tracks Configurable cutMyptMin{"cutMyptMin", 0.2, {"My Track cut"}}; @@ -147,11 +189,6 @@ struct UpcPhotonuclearAnalysisJMG { Configurable cutMyTPCNClsCrossedRowsOverNClsFindableMin{"cutMyTPCNClsCrossedRowsOverNClsFindableMin", 0.8f, {"My Track cut"}}; Configurable cutMyTPCNClsOverFindableNClsMin{"cutMyTPCNClsOverFindableNClsMin", 0.5f, {"My Track cut"}}; Configurable cutMyTPCChi2NclMax{"cutMyTPCChi2NclMax", 4.f, {"My Track cut"}}; - Configurable myWeightMin{"myWeightMin", 0.2f, {"My Track cut"}}; - Configurable myWeightMax{"myWeightMax", 5.f, {"My Track cut"}}; - Configurable myEpsilonToWeight{"myEpsilonToWeight", 1e-6f, {"NUA correction"}}; - Configurable useEpsilon{"useEpsilon", false, {"NUA correction"}}; - Configurable useNMax{"useNMax", true, {"NUA correction"}}; Configurable> cfgPairCut{"cfgPairCut", {CFGPairCutDefaults[0], 5, @@ -168,12 +205,13 @@ struct UpcPhotonuclearAnalysisJMG { ConfigurableAxis axisEtaEfficiency{"axisEtaEfficiency", {20, -1.0, 1.0}, "eta axis for efficiency histograms"}; ConfigurableAxis axisPtEfficiency{"axisPtEfficiency", {VARIABLE_WIDTH, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.25, 1.5, 1.75, 2.0, 2.25, 2.5, 2.75, 3.0, 3.25, 3.5, 3.75, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0}, "pt axis for efficiency histograms"}; - Filter collisionZVtxFilter = nabs(aod::collision::posZ) < myZVtxCut; - Filter collisionZNTimeFilter = nabs(aod::udzdc::timeZNA) < myTimeZNACut && nabs(aod::udzdc::timeZNC) < myTimeZNCCut; - Filter collisionZNeEnergyFilter = (aod::udzdc::energyCommonZNA < cutGapAMyEnergyZNA && aod::udzdc::energyCommonZNC >= cutGapAMyEnergyZNC) || (aod::udzdc::energyCommonZNA >= cutGapCMyEnergyZNA && aod::udzdc::energyCommonZNC < cutGapCMyEnergyZNC); - Filter collisioSGFilter = aod::udcollision::gapSide == uint8_t(0) || aod::udcollision::gapSide == uint8_t(1); + // Filter collisionZVtxFilter = nabs(aod::collision::posZ) < myZVtxCut; + // Filter collisionZNTimeFilterGapA = (nabs(aod::udzdc::timeZNA) > cutGapATimeZNA && nabs(aod::udzdc::timeZNC) < cutGapATimeZNC) || (nabs(aod::udzdc::timeZNA) < cutGapCTimeZNA && nabs(aod::udzdc::timeZNC) > cutGapCTimeZNC); + // Filter collisionZNeEnergyFilter = (aod::udzdc::energyCommonZNA < cutGapAMyEnergyZNA && aod::udzdc::energyCommonZNC >= cutGapAMyEnergyZNC) || (aod::udzdc::energyCommonZNA >= cutGapCMyEnergyZNA && aod::udzdc::energyCommonZNC < cutGapCMyEnergyZNC); + // Filter collisioSGFilter = aod::udcollision::gapSide == uint8_t(0) || aod::udcollision::gapSide == uint8_t(1); - using FullSGUDCollision = soa::Filtered>; + // using FullSGUDCollision = soa::Filtered>; + using FullSGUDCollision = soa::Join; using FullUDTracks = soa::Join; // Output definitions @@ -190,6 +228,7 @@ struct UpcPhotonuclearAnalysisJMG { void init(InitContext const&) { const AxisSpec axisCollision{4, -0.5, 3.5}; + const AxisSpec axisCollisionFlow{12, -0.5, 11.5}; const AxisSpec axisZvtx{20, -10., 10.}; const AxisSpec axisPt{402, -0.05, 20.05}; const AxisSpec axisP{402, -10.05, 10.05}; @@ -235,6 +274,7 @@ struct UpcPhotonuclearAnalysisJMG { } histos.add("Events/hCountCollisions", "0 total - 1 side A - 2 side C - 3 both side; Number of analysed collision; counts", kTH1F, {axisCollision}); histos.add("Events/hCountCollisionsMixed", "0 total - 1 side A - 2 side C - 3 both side; Number of analysed collision; counts", kTH1F, {axisCollision}); + histos.add("Events/hCollisionsFlow", "; ; counts", kTH1F, {axisCollisionFlow}); histos.add("Tracks/hTracksAfterCuts", " ; ; counts", kTH1F, {axisCountTracks}); // histos to selection gap in side A @@ -322,9 +362,9 @@ struct UpcPhotonuclearAnalysisJMG { std::vector vtxBinsEdges{VARIABLE_WIDTH, -10.0f, -7.0f, -5.0f, -2.5f, 0.0f, 2.5f, 5.0f, 7.0f, 10.0f}; std::vector gapSideBinsEdges{VARIABLE_WIDTH, -0.5, 0.5, 1.5}; - struct SameEventTag { - }; - struct MixedEventTag { + enum EventType { + SameEvent = 1, + MixedEvent = 2 }; SliceCache cache; @@ -333,27 +373,65 @@ struct UpcPhotonuclearAnalysisJMG { // int countGapC = 0; // Binning only on PosZ without multiplicity - using BinningType = ColumnBinningPolicy; + // using BinningType = ColumnBinningPolicy; // BinningType bindingOnVtx{{vtxBinsEdges, gapSideBinsEdges}, true}; - // using BinningType = ColumnBinningPolicy; + using BinningType = ColumnBinningPolicy; // BinningType bindingOnVtx{{vtxBinsEdges}, true}; // SameKindPair pairs{bindingOnVtx, nEventsMixed, -1, &cache}; template bool isCollisionCutSG(CSG const& collision, int SideGap) { - bool gapSideA = (collision.energyCommonZNA() < cutGapAMyEnergyZNA) && (collision.energyCommonZNC() >= cutGapAMyEnergyZNC); - bool gapSideC = (collision.energyCommonZNA() >= cutGapCMyEnergyZNA) && (collision.energyCommonZNC() < cutGapCMyEnergyZNC); + if (std::abs(collision.posZ()) > myZVtxCut) { + return false; + } + if (useSBP && collision.sbp() != sbpCut) { + return false; + } + if (useITSROFb && collision.itsROFb() != itsROFbCut) { + return false; + } + if (useVtxITSTPC && collision.vtxITSTPC() != vtxITSTPCCut) { + return false; + } + if (useZVtxFT0vsPv && collision.zVtxFT0vPV() != zVtxFT0vsPvCut) { + return false; + } + if (useOccupancy && collision.occupancyInTime() > cutOccupancy) { + return false; + } + if (useUPCMode && collision.flags() != upcModeCut) { + return false; + } switch (SideGap) { - case 0: // Gap in A side - return gapSideA; // 0n - A side && Xn - C Side + case 0: // Gap in A side + if ((collision.timeZNA() > cutGapAMyEnergyZNA) && (collision.timeZNC() < cutGapAMyEnergyZNC)) { + return false; + } + if (useEnergyZN && ((collision.energyCommonZNA() < cutGapAMyEnergyZNA) && (collision.energyCommonZNC() >= cutGapAMyEnergyZNC))) { + return false; + } // 0n - A side && Xn - C Side + if (useGapSideVariable && collision.gapSide() != uint8_t(0)) { + return false; + } + if (useFV0 && collision.totalFV0AmplitudeA() > cutGapAFV0Amplitude) { + return false; + } // if ((collision.totalFT0AmplitudeA() < cutAGapMyAmplitudeFT0AMax && collision.totalFT0AmplitudeC() >= cutAGapMyAmplitudeFT0CMin) == false) { // return false; // } break; - case 1: // Gap in C side - return gapSideC; // Xn - A side && 0n - C Side + case 1: // Gap in C side + if ((collision.timeZNA() < cutGapCMyEnergyZNA) && (collision.timeZNC() > cutGapCMyEnergyZNC)) { + return false; + } + if (useEnergyZN && ((collision.energyCommonZNA() >= cutGapCMyEnergyZNA) && (collision.energyCommonZNC() < cutGapCMyEnergyZNC))) { + return false; + } // Xn - A side && 0n - C Side + if (useGapSideVariable && collision.gapSide() != uint8_t(1)) { + return false; + } // if ((collision.totalFT0AmplitudeA() >= cutCGapMyAmplitudeFT0AMin && collision.totalFT0AmplitudeC() < cutCGapMyAmplitudeFT0CMax) == false) { // return false; // } @@ -362,12 +440,15 @@ struct UpcPhotonuclearAnalysisJMG { return false; break; } + return true; } template bool isCollisionCutSG(CSG const& collision) { - return isCollisionCutSG(collision, 0) || isCollisionCutSG(collision, 1); + bool passGapA = isCollisionCutSG(collision, 0); + bool passGapC = isCollisionCutSG(collision, 1); + return passGapA || passGapC; } template @@ -455,8 +536,8 @@ struct UpcPhotonuclearAnalysisJMG { return true; } - template - void fillCorrelationsUD(TTarget target, const TTracks& tracks1, const TTracks& tracks2, float multiplicity, float posZ, TTag) + template + void fillCorrelationsUD(TTarget target, const TTracks& tracks1, const TTracks& tracks2, float multiplicity, float posZ, int system) { for (const auto& track1 : tracks1) { if (isTrackCut(track1) == false) { @@ -488,7 +569,7 @@ struct UpcPhotonuclearAnalysisJMG { multiplicity, deltaPhi, posZ); - if constexpr (std::is_same_v) { + if (system == SameEvent) { if (minMultiplicity <= multiplicity) { histos.fill(HIST("sameEvent2D"), deltaEta, deltaPhi); } @@ -507,7 +588,7 @@ struct UpcPhotonuclearAnalysisJMG { if (range5Min <= multiplicity && multiplicity <= range5Max) { histos.fill(HIST("sameEvent_41_50"), deltaEta, deltaPhi); } - } else if constexpr (std::is_same_v) { + } else if (system == MixedEvent) { if (minMultiplicity <= multiplicity) { histos.fill(HIST("mixedEvent2D"), deltaEta, deltaPhi); } @@ -546,7 +627,6 @@ struct UpcPhotonuclearAnalysisJMG { int nTracksChargedSideA(-222), nTracksChargedSideC(-222); int multiplicitySideA(-222), multiplicitySideC(-222); - for (const auto& track : reconstructedTracks) { if (isTrackCut(track) == false) { continue; @@ -681,7 +761,40 @@ struct UpcPhotonuclearAnalysisJMG { return; break; } - tree(vTrackPtSideA, vTrackEtaSideA, vTrackPhiSideA, vTrackTPCSignalSideA, vTrackTOFSignalSideA, vTrackTPCNSigmaPiSideA, vTrackTOFNSigmaPiSideA, vTrackTPCNSigmaKaSideA, vTrackTOFNSigmaKaSideA, vTrackPtSideC, vTrackEtaSideC, vTrackPhiSideC, vTrackTPCSignalSideA, vTrackTOFSignalSideA, vTrackTPCNSigmaPiSideA, vTrackTOFNSigmaPiSideA, vTrackTPCNSigmaKaSideA, vTrackTOFNSigmaKaSideA, nTracksChargedSideA, multiplicitySideA, nTracksChargedSideC, multiplicitySideC); + tree(sgSide, + reconstructedCollision.sbp(), + reconstructedCollision.itsROFb(), + reconstructedCollision.vtxITSTPC(), + reconstructedCollision.zVtxFT0vPV(), + reconstructedCollision.timeZNA(), + reconstructedCollision.timeZNC(), + reconstructedCollision.energyCommonZNA(), + reconstructedCollision.energyCommonZNC(), + reconstructedCollision.totalFV0AmplitudeA(), + reconstructedCollision.occupancyInTime(), + reconstructedCollision.flags(), + vTrackPtSideA, + vTrackEtaSideA, + vTrackPhiSideA, + vTrackTPCSignalSideA, + vTrackTOFSignalSideA, + vTrackTPCNSigmaPiSideA, + vTrackTOFNSigmaPiSideA, + vTrackTPCNSigmaKaSideA, + vTrackTOFNSigmaKaSideA, + vTrackPtSideC, + vTrackEtaSideC, + vTrackPhiSideC, + vTrackTPCSignalSideA, + vTrackTOFSignalSideA, + vTrackTPCNSigmaPiSideA, + vTrackTOFNSigmaPiSideA, + vTrackTPCNSigmaKaSideA, + vTrackTOFNSigmaKaSideA, + nTracksChargedSideA, + multiplicitySideA, + nTracksChargedSideC, + multiplicitySideC); // nTracksChargedSideA = nTracksChargedSideC = multiplicitySideA = multiplicitySideC = 0; } @@ -693,21 +806,8 @@ struct UpcPhotonuclearAnalysisJMG { // int sgSide = reconstructedCollision.gapSide(); // int sgSide = 0; - // int maxCount = 0; - // int maxCountGapA = 0; - // int maxCountGapC = 0; - - // if (auto histEventCount = histos.get(HIST("eventcount"))) { - // int binA = histEventCount->GetXaxis()->FindBin(-2); Gap A - // int binC = histEventCount->GetXaxis()->FindBin(-1); Gap C - - // maxCount = histEventCount->GetBinContent(binA) * factorEventsMixed; - // maxCountGapA = histEventCount->GetBinContent(binA) * factorEventsMixed; - // maxCountGapC = histEventCount->GetBinContent(binC) * factorEventsMixed; - // } - - BinningType bindingOnVtx{{vtxBinsEdges, gapSideBinsEdges}, true}; - // BinningType bindingOnVtx{{vtxBinsEdges}, true}; + // BinningType bindingOnVtx{{vtxBinsEdges, gapSideBinsEdges}, true}; + BinningType bindingOnVtx{{vtxBinsEdges}, true}; auto tracksTuple = std::make_tuple(reconstructedTracks); SameKindPair pairs{bindingOnVtx, nEventsMixed, -1, reconstructedCollision, tracksTuple, &cache}; @@ -717,10 +817,6 @@ struct UpcPhotonuclearAnalysisJMG { continue; } - // if (countGapA >= maxCountGapA && countGapC >= maxCountGapC) { - // break; - // } - float multiplicity = 0; histos.fill(HIST("Events/hCountCollisionsMixed"), 0); @@ -744,42 +840,7 @@ struct UpcPhotonuclearAnalysisJMG { histos.fill(HIST("Events/hCountCollisionsMixed"), 2); // histos.fill(HIST("eventcount"), bindingOnVtx.getBin({collision1.posZ()})); // histos.fill(HIST("eventcount"), bindingOnVtx.getBin({collision1.posZ(), collision1.gapSide()})); - fillCorrelationsUD(mixed, tracks1, tracks2, multiplicity, collision1.posZ(), MixedEventTag{}); - // LOGF(info, "Filling mixed events"); - - // if (collision1.gapSide() == 0 && collision2.gapSide() == 0) { gap on side A - // if (isCollisionCutSG(collision1, 0) == false && isCollisionCutSG(collision2, 0) == false) { - // continue; - // } - // std::cout << "Counts for Gap A: " << countGapA << " Maximum Count for Gap A " << maxCountGapA << std::endl; - // ++countGapA; - // LOGF(info, "In the pairs loop, gap side A"); - // multiplicity = tracks1.size(); - // if (fillCollisionUD(mixedGapSideA, multiplicity) == false) { - // return; - // } - // histos.fill(HIST("eventcount"), bindingOnVtx.getBin({collision1.posZ()})); - // histos.fill(HIST("eventcount"), bindingOnVtx.getBin({collision1.posZ(), collision1.gapSide()})); - // fillCorrelationsUD(mixedGapSideA, tracks1, tracks2, multiplicity, collision1.posZ()); - // LOGF(info, "Filling mixedGapSideA events, Gap for side A"); - // } - - // if (collision1.gapSide() == 1 && collision2.gapSide() == 1) { gap on side C - // if (isCollisionCutSG(collision1, 1) == false && isCollisionCutSG(collision2, 1) == false) { - // continue; - // } - // std::cout << "Counts for Gap C: " << countGapC << " Maximum Count for Gap C" << maxCountGapC << std::endl; - // ++countGapC; - // LOGF(info, "In the pairs loop, gap side C"); - // multiplicity = tracks1.size(); - // if (fillCollisionUD(mixedGapSideC, multiplicity) == false) { - // return; - // } - // fillCorrelationsUD(mixedGapSideC, tracks1, tracks2, multiplicity, collision1.posZ()); - // LOGF(info, "Filling mixedGapSideC events, Gap for side C"); - // } else { - // continue; - // } + fillCorrelationsUD(mixed, tracks1, tracks2, multiplicity, collision1.posZ(), MixedEvent); } } @@ -790,6 +851,73 @@ struct UpcPhotonuclearAnalysisJMG { // int sgSide = reconstructedCollision.gapSide(); float multiplicity = 0; + auto hEventFlow = histos.get(HIST("Events/hCollisionsFlow")); + hEventFlow->GetXaxis()->SetBinLabel(1, "All events"); + hEventFlow->GetXaxis()->SetBinLabel(2, "Z Vtx"); + hEventFlow->GetXaxis()->SetBinLabel(3, "SBP"); + hEventFlow->GetXaxis()->SetBinLabel(4, "ITS ROFb"); + hEventFlow->GetXaxis()->SetBinLabel(5, "Vtx ITS-TPC"); + hEventFlow->GetXaxis()->SetBinLabel(6, "Z Vtx FT0vsPv"); + hEventFlow->GetXaxis()->SetBinLabel(7, "Occupancy"); + hEventFlow->GetXaxis()->SetBinLabel(8, "UPC Mode"); + hEventFlow->GetXaxis()->SetBinLabel(9, "Time ZN"); + hEventFlow->GetXaxis()->SetBinLabel(10, "Energy ZN"); + hEventFlow->GetXaxis()->SetBinLabel(11, "FV0-A Amplitude"); + hEventFlow->GetXaxis()->SetBinLabel(12, "GapSide Variable"); + + histos.fill(HIST("Events/hCollisionsFlow"), 0); + if (std::abs(reconstructedCollision.posZ()) > myZVtxCut) { + return; + } + histos.fill(HIST("Events/hCollisionsFlow"), 1); + if (useSBP && reconstructedCollision.sbp() != sbpCut) { + return; + } + histos.fill(HIST("Events/hCollisionsFlow"), 2); + if (useITSROFb && reconstructedCollision.itsROFb() != itsROFbCut) { + return; + } + histos.fill(HIST("Events/hCollisionsFlow"), 3); + if (useVtxITSTPC && reconstructedCollision.vtxITSTPC() != vtxITSTPCCut) { + return; + } + histos.fill(HIST("Events/hCollisionsFlow"), 4); + if (useZVtxFT0vsPv && reconstructedCollision.zVtxFT0vPV() != zVtxFT0vsPvCut) { + return; + } + histos.fill(HIST("Events/hCollisionsFlow"), 5); + if (useOccupancy && reconstructedCollision.occupancyInTime() > cutOccupancy) { + return; + } + histos.fill(HIST("Events/hCollisionsFlow"), 6); + if (useUPCMode && reconstructedCollision.flags() != 1) { + return; + } + histos.fill(HIST("Events/hCollisionsFlow"), 7); + bool cutGapAMyTimeZN = (reconstructedCollision.timeZNA() > cutGapAMyEnergyZNA) && (reconstructedCollision.timeZNC() < cutGapAMyEnergyZNC); + bool cutGapCMyTimeZN = (reconstructedCollision.timeZNA() < cutGapCMyEnergyZNA) && (reconstructedCollision.timeZNC() > cutGapCMyEnergyZNC); + if (cutGapAMyTimeZN || cutGapCMyTimeZN) { + return; + } + histos.fill(HIST("Events/hCollisionsFlow"), 8); + + bool cutGapAMyEnergyZN = useEnergyZN && ((reconstructedCollision.energyCommonZNA() < cutGapAMyEnergyZNA) && (reconstructedCollision.energyCommonZNC() >= cutGapAMyEnergyZNC)); + bool cutGapCMyEnergyZN = useEnergyZN && ((reconstructedCollision.energyCommonZNA() >= cutGapCMyEnergyZNA) && (reconstructedCollision.energyCommonZNC() < cutGapCMyEnergyZNC)); + if (cutGapAMyEnergyZN || cutGapCMyEnergyZN) { + return; + } + histos.fill(HIST("Events/hCollisionsFlow"), 9); + if (cutGapAMyTimeZN && useFV0 && reconstructedCollision.totalFV0AmplitudeA() > cutGapAFV0Amplitude) { + return; + } + histos.fill(HIST("Events/hCollisionsFlow"), 10); + bool cutGapSideAVariable = useGapSideVariable && reconstructedCollision.gapSide() != uint8_t(0); + bool cutGapSideCVariable = useGapSideVariable && reconstructedCollision.gapSide() != uint8_t(1); + if (cutGapSideAVariable || cutGapSideCVariable) { + return; + } + histos.fill(HIST("Events/hCollisionsFlow"), 11); + if (isCollisionCutSG(reconstructedCollision) == false) { return; } @@ -914,38 +1042,7 @@ struct UpcPhotonuclearAnalysisJMG { histos.fill(HIST("eventcount"), 5); } fillQAUD(reconstructedTracks, multiplicity); - fillCorrelationsUD(same, reconstructedTracks, reconstructedTracks, multiplicity, reconstructedCollision.posZ(), SameEventTag{}); - - /*switch (sgSide) { - case 0: // gap for side A - if (isCollisionCutSG(reconstructedCollision, 0) == false) { - return; - } - multiplicity = reconstructedTracks.size(); - if (fillCollisionUD(sameGapSideA, multiplicity) == false) { - return; - } - LOGF(info, "Filling sameGapSideA events"); - histos.fill(HIST("eventcount"), -2); - fillQAUD(reconstructedTracks); - fillCorrelationsUD(sameGapSideA, reconstructedTracks, reconstructedTracks, multiplicity, reconstructedCollision.posZ()); - break; - case 1: // gap for side C - if (isCollisionCutSG(reconstructedCollision, 1) == false) { - return; - } - multiplicity = reconstructedTracks.size(); - if (fillCollisionUD(sameGapSideC, multiplicity) == false) { - return; - } - histos.fill(HIST("eventcount"), -1); - // LOGF(info, "Filling sameGapSideC events"); - fillCorrelationsUD(sameGapSideC, reconstructedTracks, reconstructedTracks, multiplicity, reconstructedCollision.posZ()); - break; - default: - return; - break; - }*/ + fillCorrelationsUD(same, reconstructedTracks, reconstructedTracks, multiplicity, reconstructedCollision.posZ(), SameEvent); } PROCESS_SWITCH(UpcPhotonuclearAnalysisJMG, processSame, "Process same event", true); From fe2348767753c113bbc18ad98dc95809cb20d0ee Mon Sep 17 00:00:00 2001 From: Francesco Mazzaschi <43742195+fmazzasc@users.noreply.github.com> Date: Tue, 17 Mar 2026 18:30:22 +0100 Subject: [PATCH 304/347] [PWGLF] Fix track access + improvements to the final thn (#15428) Co-authored-by: Francesco Mazzaschi --- .../Strangeness/sigmaHadCorr.cxx | 59 +++++++++---------- 1 file changed, 28 insertions(+), 31 deletions(-) diff --git a/PWGLF/TableProducer/Strangeness/sigmaHadCorr.cxx b/PWGLF/TableProducer/Strangeness/sigmaHadCorr.cxx index 0467ae6a660..c01ba0a264f 100644 --- a/PWGLF/TableProducer/Strangeness/sigmaHadCorr.cxx +++ b/PWGLF/TableProducer/Strangeness/sigmaHadCorr.cxx @@ -102,13 +102,13 @@ struct sigmaHadCorrTask { Configurable cutNSigmaTPC{"cutNSigmaTPC", 3, "TPC nSigma cut for hadron track"}; Configurable cutNSigmaTOF{"cutNSigmaTOF", 3, "TOF nSigma cut for hadron track"}; Configurable applyTOFPIDKinkDaughter{"applyTOFPIDKinkDaughter", false, "If true, apply TOF PID cut to the kink daughter track"}; - Configurable matchSigmaToPions{"matchSigmaToPions", false, "If true, pair Sigma with pions instead of hadrons"}; + Configurable doSigmaPion{"doSigmaPion", false, "If true, pair Sigma with pions instead of protons"}; Configurable cutMaxKStar{"cutMaxKStar", 1.5, "Maximum k* for Sigma-hadron pairs (GeV/c)"}; - Configurable useRecalculatedSigmaMomentum{"useRecalculatedSigmaMomentum", false, "If true, compute k* using Sigma momentum recalculated from daughter kinematics"}; + Configurable useRecalculatedSigmaMomentum{"useRecalculatedSigmaMomentum", true, "If true, compute k* using Sigma momentum recalculated from daughter kinematics"}; Configurable fillOutputTree{"fillOutputTree", true, "If true, fill the output tree with Sigma-hadron candidates"}; - Configurable fillSparseInvMassKstar{"fillSparseInvMassKstar", false, "If true, fill THnSparse with invmass, k*, sigma charge, proton charge, sigma decay radius, cosPA, sigma pt"}; + Configurable fillSparseInvMassKstar{"fillSparseInvMassKstar", false, "If true, fill THn with invmass, k*, sigma charge, proton charge, sigma decay radius, cosPA, sigma pt"}; ConfigurableAxis CfgVtxBins{"CfgVtxBins", {10, -10, 10}, "Mixing bins - z-vertex"}; ConfigurableAxis CfgMultBins{"CfgMultBins", {VARIABLE_WIDTH, 0.0, 40.0, 80.0, 500.0}, "Mixing bins - number of contributor"}; @@ -124,14 +124,17 @@ struct sigmaHadCorrTask { const AxisSpec ptAxis{100, -10, 10, "#it{p}_{T} (GeV/#it{c})"}; const AxisSpec massResolutionAxis{100, -0.1, 0.1, "m_{rec} - m_{gen} (GeV/#it{c}^{2})"}; const AxisSpec nSigmaHadAxis{100, -5, 5, "n#sigma_{had}"}; - const AxisSpec sigmaMassAxis{100, 1.1, 1.3, "m (GeV/#it{c}^{2})"}; + const AxisSpec sigmaMassAxis{50, 1.1, 1.3, "m (GeV/#it{c}^{2})"}; const AxisSpec kStarAxis{200, 0.0, 2., "k* (GeV/#it{c})"}; const AxisSpec ptHadAxis{100, 0.0, 10.0, "#it{p}_{T,had} (GeV/#it{c})"}; const AxisSpec sigmaPtAxis{100, 0.0, 10.0, "#it{p}_{T,#Sigma} (GeV/#it{c})"}; + const AxisSpec sigmaPtAxisCoarse{20, 0.0, 10.0, "#it{p}_{T,#Sigma} (GeV/#it{c})"}; const AxisSpec sigmaChargeAxis{2, -1.5, 1.5, "#Sigma charge"}; const AxisSpec hadronChargeAxis{2, -1.5, 1.5, "Hadron charge"}; const AxisSpec sigmaDecRadiusAxis{25, 14.5, 40.5, "#Sigma decay radius (cm)"}; + const AxisSpec sigmaDecRadiusAxisCoarse{5, 14.5, 40.5, "#Sigma decay radius (cm)"}; const AxisSpec cosPAAxis{50, 0.9, 1.0, "cos(PA)"}; + const AxisSpec cosPAAxisCoarse{5, 0.9, 1.0, "cos(PA)"}; const AxisSpec alphaAPAxis{100, -1.0, 1.0, "#alpha_{AP}"}; const AxisSpec qtAPAxis{100, 0.0, 0.5, "q_{T,AP} (GeV/#it{c})"}; const AxisSpec vertexZAxis{100, -15., 15., "vrtx_{Z} [cm]"}; @@ -148,11 +151,11 @@ struct sigmaHadCorrTask { if (fillSparseInvMassKstar) { rSigmaHad.add("hSparseSigmaHad", - "7D sparse: invmass, k*, sigma charge, hadron charge, sigma decay radius, cosPA, sigma pt", - {HistType::kTHnSparseF, {sigmaMassAxis, kStarAxis, sigmaChargeAxis, hadronChargeAxis, sigmaDecRadiusAxis, cosPAAxis, sigmaPtAxis}}); + "7D THn: invmass, k*, sigma charge, hadron charge, sigma decay radius, cosPA, sigma pt", + {HistType::kTHnF, {sigmaMassAxis, kStarAxis, sigmaChargeAxis, hadronChargeAxis, sigmaDecRadiusAxisCoarse, cosPAAxisCoarse, sigmaPtAxisCoarse}}); rSigmaHad.add("hSparseSigmaHadMC", - "8D sparse (MC): invmass, k*, sigma charge, hadron charge, sigma decay radius, cosPA, sigma pt, k* gen", - {HistType::kTHnSparseF, {sigmaMassAxis, kStarAxis, sigmaChargeAxis, hadronChargeAxis, sigmaDecRadiusAxis, cosPAAxis, sigmaPtAxis, kStarAxis}}); + "8D THn (MC): invmass, k*, sigma charge, hadron charge, sigma decay radius, cosPA, sigma pt, k* gen", + {HistType::kTHnF, {sigmaMassAxis, kStarAxis, sigmaChargeAxis, hadronChargeAxis, sigmaDecRadiusAxisCoarse, cosPAAxisCoarse, sigmaPtAxisCoarse, kStarAxis}}); } LOG(info) << "Sigma-hadron correlation task initialized"; @@ -160,7 +163,7 @@ struct sigmaHadCorrTask { LOG(info) << "Process ME enabled: " << doprocessMixedEvent; LOG(info) << "Process SE MC enabled: " << doprocessSameEventMC; LOG(info) << "Process ME MC enabled: " << doprocessMixedEventMC; - LOG(info) << "Pairing mode: " << (matchSigmaToPions ? "Sigma-pion" : "Sigma-hadron"); + LOG(info) << "Pairing mode: " << (doSigmaPion ? "Sigma-pion" : "Sigma-proton"); } float getAlphaAP(const std::array& momMother, const std::array& momKink) @@ -254,7 +257,7 @@ struct sigmaHadCorrTask { float getHadTrackMass() { - return matchSigmaToPions ? o2::constants::physics::MassPionCharged : o2::constants::physics::MassProton; + return doSigmaPion ? o2::constants::physics::MassPionCharged : o2::constants::physics::MassProton; } float getSigmaMassForKstar() @@ -265,13 +268,13 @@ struct sigmaHadCorrTask { template float getTPCNSigmaHad(const Ttrack& track) { - return matchSigmaToPions ? track.tpcNSigmaPi() : track.tpcNSigmaPr(); + return doSigmaPion ? track.tpcNSigmaPi() : track.tpcNSigmaPr(); } template float getTOFNSigmaHad(const Ttrack& track) { - return matchSigmaToPions ? track.tofNSigmaPi() : track.tofNSigmaPr(); + return doSigmaPion ? track.tofNSigmaPi() : track.tofNSigmaPr(); } TLorentzVector trackSum, PartOneCMS, PartTwoCMS, trackRelK; @@ -349,10 +352,6 @@ struct sigmaHadCorrTask { float alphaAP = getAlphaAP(momMoth, momDaug); float qtAP = getQtAP(momMoth, momDaug); - if (sigmaCand.ptMoth() < minPtSigma) { - return false; - } - if (alphaAP > alphaAPCut || (qtAP < qtAPCutLow || qtAP > qtAPCutHigh)) { return false; } @@ -418,14 +417,17 @@ struct sigmaHadCorrTask { sigmaForPt.sigmaDauPx = sigmaCand.pxDaug(); sigmaForPt.sigmaDauPy = sigmaCand.pyDaug(); sigmaForPt.sigmaDauPz = sigmaCand.pzDaug(); - auto sigmaMomForPt = getSigmaMomentumForKstar(sigmaForPt); - float sigmaPtRecal = std::hypot(sigmaMomForPt[0], sigmaMomForPt[1]); - float sigmaPtForSparse = useRecalculatedSigmaMomentum ? sigmaPtRecal : sigmaCand.ptMoth(); + auto sigmaPRecal = getSigmaMomentumForKstar(sigmaForPt); + float sigmaPtRecal = std::hypot(sigmaPRecal[0], sigmaPRecal[1]); float sigmaMassForQa = doSigmaMinus ? sigmaCand.mSigmaMinus() : sigmaCand.mSigmaPlus(); + if (sigmaPtRecal < minPtSigma) { + continue; + } + rSigmaHad.fill(HIST("QA/hSigmaPt"), sigmaCand.ptMoth()); rSigmaHad.fill(HIST("QA/hSigmaPtRecal"), sigmaPtRecal); - rSigmaHad.fill(HIST("QA/h2InvMassVsPtSigma"), sigmaPtForSparse, sigmaMassForQa); + rSigmaHad.fill(HIST("QA/h2InvMassVsPtSigma"), sigmaPtRecal, sigmaMassForQa); for (const auto& hadTrack : tracks) { if (hadTrack.globalIndex() == sigmaCand.trackDaugId()) { @@ -463,18 +465,13 @@ struct sigmaHadCorrTask { candidate.kinkDauID = sigmaCand.trackDaugId(); candidate.hadID = hadTrack.globalIndex(); - auto sigmaMomForKstar = getSigmaMomentumForKstar(candidate); - float kStar = getKStar(sigmaMomForKstar[0], sigmaMomForKstar[1], sigmaMomForKstar[2], candidate.pxHad, candidate.pyHad, candidate.pzHad); + float kStar = getKStar(sigmaPRecal[0], sigmaPRecal[1], sigmaPRecal[2], candidate.pxHad, candidate.pyHad, candidate.pzHad); if (kStar > cutMaxKStar) { continue; } - float sigmaPtUsed = std::hypot(sigmaMomForKstar[0], sigmaMomForKstar[1]); - - rSigmaHad.fill(HIST("h2PtHadNSigmaTPC"), candidate.ptHad(), candidate.nSigmaTPCHad); rSigmaHad.fill(HIST("QA/h2TPCNSigmaHadVsPtHad"), candidate.ptHad(), candidate.nSigmaTPCHad); if (hadTrack.hasTOF()) { - rSigmaHad.fill(HIST("h2PtHadNSigmaTOF"), candidate.ptHad(), candidate.nSigmaTOFHad); rSigmaHad.fill(HIST("QA/h2TOFNSigmaHadVsPtHad"), candidate.ptHad(), candidate.nSigmaTOFHad); } if (fillSparseInvMassKstar && !isMC) { @@ -485,7 +482,7 @@ struct sigmaHadCorrTask { candidate.chargeHad, candidate.sigmaDecRadius, candidate.sigmaCosPA, - sigmaPtUsed); + sigmaPtRecal); } sigmaHadCandidates.push_back(candidate); } @@ -503,7 +500,7 @@ struct sigmaHadCorrTask { continue; } rEventSelection.fill(HIST("hVertexZRec"), collision.posZ()); - fillTreeAndHistograms(kinkCands_c, tracks_c, tracks_c, collision, false); + fillTreeAndHistograms(kinkCands_c, tracks, tracks_c, collision, false); if (fillOutputTree) { // Fill output table for (const auto& candidate : sigmaHadCandidates) { @@ -550,7 +547,7 @@ struct sigmaHadCorrTask { auto kinkCands_c1 = kinkCands.sliceBy(kinkCandsPerCollisionPreslice, collision1.globalIndex()); auto tracks_c1 = tracks.sliceBy(tracksPerCollisionPreslice, collision1.globalIndex()); auto tracks_c2 = tracks.sliceBy(tracksPerCollisionPreslice, collision2.globalIndex()); - fillTreeAndHistograms(kinkCands_c1, tracks_c1, tracks_c2, collision1, false); + fillTreeAndHistograms(kinkCands_c1, tracks, tracks_c2, collision1, false); if (fillOutputTree) { // Fill output table @@ -589,7 +586,7 @@ struct sigmaHadCorrTask { continue; } rEventSelection.fill(HIST("hVertexZRec"), collision.posZ()); - fillTreeAndHistograms(kinkCands_c, tracks_c, tracks_c, collision, true); + fillTreeAndHistograms(kinkCands_c, tracks, tracks_c, collision, true); for (const auto& candidate : sigmaHadCandidates) { auto mcLabelSigma = tracks.rawIteratorAt(candidate.sigmaID); auto mcLabelSigmaDau = tracks.rawIteratorAt(candidate.kinkDauID); @@ -670,7 +667,7 @@ struct sigmaHadCorrTask { auto kinkCands_c1 = kinkCands.sliceBy(kinkCandsPerCollisionPreslice, collision1.globalIndex()); auto tracks_c1 = tracks.sliceBy(tracksPerCollisionPreslice, collision1.globalIndex()); auto tracks_c2 = tracks.sliceBy(tracksPerCollisionPreslice, collision2.globalIndex()); - fillTreeAndHistograms(kinkCands_c1, tracks_c1, tracks_c2, collision1, true); + fillTreeAndHistograms(kinkCands_c1, tracks, tracks_c2, collision1, true); for (const auto& candidate : sigmaHadCandidates) { auto mcLabelSigma = tracks.rawIteratorAt(candidate.sigmaID); From 1e81af3e1b1daff588e237e3c8cae4b405f8fdc0 Mon Sep 17 00:00:00 2001 From: somabhatta <48771326+somabhatta@users.noreply.github.com> Date: Tue, 17 Mar 2026 19:10:04 +0100 Subject: [PATCH 305/347] [PWGCF] fixing minor issues in radflow decorr (#15401) --- .../Tasks/radialFlowDecorr.cxx | 1596 ++++++++--------- 1 file changed, 798 insertions(+), 798 deletions(-) diff --git a/PWGCF/EbyEFluctuations/Tasks/radialFlowDecorr.cxx b/PWGCF/EbyEFluctuations/Tasks/radialFlowDecorr.cxx index 36fd6cd2254..ba43045979e 100644 --- a/PWGCF/EbyEFluctuations/Tasks/radialFlowDecorr.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/radialFlowDecorr.cxx @@ -199,7 +199,7 @@ struct RadialFlowDecorr { Configurable cfgUseGoodITSLayerAllCut{"cfgUseGoodITSLayerAllCut", true, "Remove time interval with dead ITS zone"}; Configurable cfgIsGoodZvtxFT0VsPV{"cfgIsGoodZvtxFT0VsPV", true, "Good Vertexing cut"}; - Configurable cfgPupnSig{"cfgPupnSig", 3.0f, "Additional Pileup Cut"}; + Configurable cfgPupnSig{"cfgPupnSig", 6.0f, "Additional Pileup Cut"}; Configurable cfgApplySigPupCut{"cfgApplySigPupCut", 0, "nSig Pileup Cut"}; Configurable cfgApplyLinPupCut{"cfgApplyLinPupCut", 0, "Lin Pileup Cut"}; Configurable cfgLinPupParam0{"cfgLinPupParam0", 3.0f, "(Upper) Linear Pileup Cut Const"}; @@ -237,15 +237,14 @@ struct RadialFlowDecorr { -0.75, -0.65, -0.55, -0.45, -0.35, -0.25, -0.15, -0.05, 0.05, 0.15, 0.25, 0.35, 0.45, 0.55, 0.65, 0.75, 0.85, 0.95, 1.05, 1.15, 1.25, 1.35, 1.45, 1.55}, - "Gaps"}; - - const AxisSpec sumAxis{{-0.775, -0.725, -0.675, -0.625, -0.575, -0.525, - -0.475, -0.425, -0.375, -0.325, -0.275, -0.225, - -0.175, -0.125, -0.075, -0.025, - 0.025, 0.075, 0.125, 0.175, 0.225, 0.275, - 0.325, 0.375, 0.425, 0.475, 0.525, 0.575, - 0.625, 0.675, 0.725, 0.775}, - "Sums"}; + "Gap"}; + + const AxisSpec sumAxis{{-1.55, -1.45, -1.35, -1.25, -1.15, -1.05, -0.95, -0.85, + -0.75, -0.65, -0.55, -0.45, -0.35, -0.25, -0.15, -0.05, + 0.05, 0.15, 0.25, 0.35, 0.45, 0.55, 0.65, 0.75, + 0.85, 0.95, 1.05, 1.15, 1.25, 1.35, 1.45, 1.55}, + "Sum"}; + Configurable cfgRunMCGetNSig{"cfgRunMCGetNSig", false, "Run MC pass to get mean of Nsig Plots"}; Configurable cfgRunGetEff{"cfgRunGetEff", false, "Run MC pass to build efficiency/fake maps"}; Configurable cfgRunGetMCFlat{"cfgRunGetMCFlat", false, "Run MC to Get Flattening Weights"}; @@ -543,10 +542,11 @@ struct RadialFlowDecorr { return (y >= limits[bin].first && y <= limits[bin].second); }; if (cfgApplySigPupCut) { - if (!checkLimits(trksize, cent, state.mLimitsNchCent, state.mMinXNchCent, state.mMaxXNchCent)) + if (!checkLimits(cent, trksize, state.mLimitsNchCent, state.mMinXNchCent, state.mMaxXNchCent)) return false; + histos.fill(HIST("hEvtCount"), 6.5); } - histos.fill(HIST("hEvtCount"), 6.5); + if (cfgApplyLinPupCut) { if (trksize > (cfgLinPupParam0 + cfgLinPupParam1 * multPV)) return false; @@ -655,22 +655,15 @@ struct RadialFlowDecorr { float getEfficiency(float mult, float pt, float eta, PIDIdx pidType, int effidx, bool cfgEff) const { if (!cfgEff) { - if (effidx == 0) - return 1.0; - if (effidx == 1) - return 0.0; + return (effidx == 0) ? 1.0f : 0.0f; } - TH3F* h = nullptr; - if (effidx == 0) - h = state.hEff[pidType]; - if (effidx == 1) - h = state.hFake[pidType]; - - if (!h) - return -1; - const int ibx = h->GetXaxis()->FindBin(mult); - const int iby = h->GetYaxis()->FindBin(pt); - const int ibz = h->GetZaxis()->FindBin(eta); + TH3F* h = (effidx == 0) ? state.hEff[pidType] : state.hFake[pidType]; + if (!h) { + return (effidx == 0) ? 1.0f : 0.0f; // Safe defaults if map is missing + } + int ibx = h->GetXaxis()->FindBin(mult); + int iby = h->GetYaxis()->FindBin(pt); + int ibz = h->GetZaxis()->FindBin(eta); float val = h->GetBinContent(ibx, iby, ibz); return val; } @@ -973,8 +966,6 @@ struct RadialFlowDecorr { } histos.add("hnTrkPVZDC", ";N_{PV};ZDC_{A+C}", kTH2F, {{nChAxis2}, {200, 0, 3000}}); histos.add("hNchZDC", ";N_{trk};ZDC_{A+C}", kTH2F, {{nChAxis2}, {200, 0, 30000}}); - histos.add("hCentnTrk", ";Centrality (%);N_{trk}", kTH2F, {{centAxis1Per}, {nChAxis2}}); - histos.add("hCentnTrkPV", ";Centrality (%);N_{trk, PV}", kTH2F, {{centAxis1Per}, {nChAxis2}}); } void declareDataMeanHists() @@ -1284,26 +1275,31 @@ struct RadialFlowDecorr { } } }; - for (int i = 0; i < KNsp; ++i) { + for (int i = 1; i < KNsp; ++i) { loadPIDMeans(static_cast(i)); } auto loadLimits = [&](const char* name, std::vector>& limits, float& xMin, float& xMax) { - auto* h2 = reinterpret_cast(pidList->FindObject(name)); + auto* h2 = reinterpret_cast(pidList->FindObject(name)); if (!h2) - return; // Skip if missing - int nBins = h2->GetXaxis()->GetNbins(); - xMin = h2->GetXaxis()->GetXmin(); - xMax = h2->GetXaxis()->GetXmax(); - limits.assign(nBins + 2, {-9999.f, 99999.f}); + return; + + std::unique_ptr prof(h2->ProfileX("ptmp", 1, -1, "S")); + + int nBins = prof->GetNbinsX(); + xMin = prof->GetXaxis()->GetXmin(); + xMax = prof->GetXaxis()->GetXmax(); + + limits.assign(nBins + 2, {-99999.f, 999999.f}); + for (int i = 1; i <= nBins; ++i) { - std::unique_ptr proj(h2->ProjectionY("_py", i, i)); - float m = proj->GetMean(); - float s = proj->GetRMS(); - limits[i] = {m - cfgPupnSig * s, m + cfgPupnSig * s}; + float mean = prof->GetBinContent(i); + float rms = prof->GetBinError(i); + + limits[i] = {mean - cfgPupnSig * rms, mean + cfgPupnSig * rms}; } }; - loadLimits("Hist2D_cent_nch", state.mLimitsNchCent, state.mMinXNchCent, state.mMaxXNchCent); + loadLimits("Hist2D_globalTracks_cent", state.mLimitsNchCent, state.mMinXNchCent, state.mMaxXNchCent); } } @@ -1874,256 +1870,259 @@ struct RadialFlowDecorr { } } - for (int isp = 0; isp < KNsp; ++isp) { - histos.fill(HIST("MCGen/Prof_Cent_Nsp_Nchrec"), cent, isp, sumWiTruth[isp][0]); - histos.fill(HIST("MCGen/Prof_Mult_Nsp_Nchrec"), multPV, isp, sumWiTruth[isp][0]); - if (sumWiTruth[isp][0] > 1.0f) { - histos.fill(HIST("MCGen/Prof_Cent_Nsp_MeanpT"), cent, isp, sumWiptiTruth[isp][0] / sumWiTruth[isp][0]); - histos.fill(HIST("MCGen/Prof_Mult_Nsp_MeanpT"), multPV, isp, sumWiptiTruth[isp][0] / sumWiTruth[isp][0]); - } - } + for (int isp = 0; isp < KNsp; ++isp) { + histos.fill(HIST("MCGen/Prof_Cent_Nsp_Nchrec"), cent, isp, sumWiTruth[isp][0]); + histos.fill(HIST("MCGen/Prof_Mult_Nsp_Nchrec"), multPV, isp, sumWiTruth[isp][0]); + if (sumWiTruth[isp][0] > 1.0f) { + histos.fill(HIST("MCGen/Prof_Cent_Nsp_MeanpT"), cent, isp, sumWiptiTruth[isp][0] / sumWiTruth[isp][0]); + histos.fill(HIST("MCGen/Prof_Mult_Nsp_MeanpT"), multPV, isp, sumWiptiTruth[isp][0] / sumWiTruth[isp][0]); + } + } - for (const auto& track : mcTracks) { - if (!isTrackSelected(track)) - continue; - float pt = track.pt(), eta = track.eta(), phi = track.phi(); - if (pt <= cfgPtMin || pt > cfgPtMax) + for (const auto& track : mcTracks) { + if (!isTrackSelected(track)) + continue; + float pt = track.pt(), eta = track.eta(), phi = track.phi(); + if (pt <= cfgPtMin || pt > cfgPtMax) + continue; + auto sign = track.sign(); + histos.fill(HIST("hPt"), pt); + histos.fill(HIST("hEta"), eta); + histos.fill(HIST("hPhi"), phi); + int id = identifyTrack(track, cent); + bool isPi = (id == KPidPionOne); + bool isKa = (id == KPidKaonTwo); + bool isPr = (id == KPidProtonThree); + bool isSpecies[KNsp] = { + true, + isPi && sign < 0, isPi && sign > 0, isPi, + isKa && sign < 0, isKa && sign > 0, isKa, + isPr && sign < 0, isPr && sign > 0, isPr}; + + for (int isp = 0; isp < KNsp; ++isp) { + if (!isSpecies[isp]) + continue; + float eff = getEfficiency(multPV, pt, eta, static_cast(isp), 0, cfgEff); + float fake = getEfficiency(multPV, pt, eta, static_cast(isp), 1, cfgEff); + float flatW = getFlatteningWeight(vz, sign, pt, eta, phi, static_cast(isp), cfgFlat); + float w = flatW * (1.0 - fake) / eff; + if (!std::isfinite(w) || w <= 0.f || eff <= KFloatEpsilon) + continue; + + for (int ieta = 0; ieta < KNEta; ++ieta) { + if (eta <= etaLw[ieta] || eta > etaUp[ieta]) continue; - auto sign = track.sign(); - int id = identifyTrack(track, cent); - bool isPi = (id == KPidPionOne); - bool isKa = (id == KPidKaonTwo); - bool isPr = (id == KPidProtonThree); - bool isSpecies[KNsp] = { - true, - isPi && sign < 0, isPi && sign > 0, isPi, - isKa && sign < 0, isKa && sign > 0, isKa, - isPr && sign < 0, isPr && sign > 0, isPr}; - - for (int isp = 0; isp < KNsp; ++isp) { - if (!isSpecies[isp]) - continue; - float eff = getEfficiency(multPV, pt, eta, static_cast(isp), 0, cfgEff); - float fake = getEfficiency(multPV, pt, eta, static_cast(isp), 1, cfgEff); - float flatW = getFlatteningWeight(vz, sign, pt, eta, phi, static_cast(isp), cfgFlat); - float w = flatW * (1.0 - fake) / eff; - if (!std::isfinite(w) || w <= 0.f || eff <= KFloatEpsilon) - continue; - - for (int ieta = 0; ieta < KNEta; ++ieta) { - if (eta <= etaLw[ieta] || eta > etaUp[ieta]) - continue; - sumWiReco[isp][ieta]++; - sumWiptiReco[isp][ieta] += pt; - sumWiRecoEffCorr[isp][ieta] += w; - sumWiptiRecoEffCorr[isp][ieta] += w * pt; - } + sumWiReco[isp][ieta]++; + sumWiptiReco[isp][ieta] += pt; + sumWiRecoEffCorr[isp][ieta] += w; + sumWiptiRecoEffCorr[isp][ieta] += w * pt; + } - if (isp == kInclusiveIdx) { - histos.fill(HIST("Eff_cent"), cent, eff); - histos.fill(HIST("Fake_cent"), cent, fake); - histos.fill(HIST("wgt_cent"), cent, w); + if (isp == kInclusiveIdx) { + histos.fill(HIST("Eff_cent"), cent, eff); + histos.fill(HIST("Fake_cent"), cent, fake); + histos.fill(HIST("wgt_cent"), cent, w); - histos.fill(HIST("Eff_Ntrk"), multPV, eff); - histos.fill(HIST("Fake_Ntrk"), multPV, fake); - histos.fill(HIST("wgt_Ntrk"), multPV, w); + histos.fill(HIST("Eff_Ntrk"), multPV, eff); + histos.fill(HIST("Fake_Ntrk"), multPV, fake); + histos.fill(HIST("wgt_Ntrk"), multPV, w); - histos.fill(HIST("Eff_pT"), pt, eff); - histos.fill(HIST("Fake_pT"), pt, fake); - histos.fill(HIST("wgt_pT"), pt, w); + histos.fill(HIST("Eff_pT"), pt, eff); + histos.fill(HIST("Fake_pT"), pt, fake); + histos.fill(HIST("wgt_pT"), pt, w); - histos.fill(HIST("Eff_eta"), eta, eff); - histos.fill(HIST("Fake_eta"), eta, fake); - histos.fill(HIST("wgt_eta"), eta, w); - } - if (isp == kInclusiveIdx) { - histos.fill(HIST("hEtaPhiReco"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoWtd"), vz, sign, pt, eta, phi, w); - histos.fill(HIST("hEtaPhiRecoEffWtd"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - } else if (isp == kPiMinusIdx) { - histos.fill(HIST("hEtaPhiReco_PiMinus"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoWtd_PiMinus"), vz, sign, pt, eta, phi, w); - histos.fill(HIST("hEtaPhiRecoEffWtd_PiMinus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - } else if (isp == kPiPlusIdx) { - histos.fill(HIST("hEtaPhiReco_PiPlus"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoWtd_PiPlus"), vz, sign, pt, eta, phi, w); - histos.fill(HIST("hEtaPhiRecoEffWtd_PiPlus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - } else if (isp == kPiAllIdx) { - histos.fill(HIST("hEtaPhiReco_PiAll"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoWtd_PiAll"), vz, sign, pt, eta, phi, w); - histos.fill(HIST("hEtaPhiRecoEffWtd_PiAll"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - } else if (isp == kKaMinusIdx) { - histos.fill(HIST("hEtaPhiReco_KaMinus"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoWtd_KaMinus"), vz, sign, pt, eta, phi, w); - histos.fill(HIST("hEtaPhiRecoEffWtd_KaMinus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - } else if (isp == kKaPlusIdx) { - histos.fill(HIST("hEtaPhiReco_KaPlus"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoWtd_KaPlus"), vz, sign, pt, eta, phi, w); - histos.fill(HIST("hEtaPhiRecoEffWtd_KaPlus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - } else if (isp == kKaAllIdx) { - histos.fill(HIST("hEtaPhiReco_KaAll"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoWtd_KaAll"), vz, sign, pt, eta, phi, w); - histos.fill(HIST("hEtaPhiRecoEffWtd_KaAll"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - } else if (isp == kPrIdx) { - histos.fill(HIST("hEtaPhiReco_Pr"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoWtd_Pr"), vz, sign, pt, eta, phi, w); - histos.fill(HIST("hEtaPhiRecoEffWtd_Pr"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - } else if (isp == kAntiPrIdx) { - histos.fill(HIST("hEtaPhiReco_AntiPr"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoWtd_AntiPr"), vz, sign, pt, eta, phi, w); - histos.fill(HIST("hEtaPhiRecoEffWtd_AntiPr"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - } else if (isp == kPrAllIdx) { - histos.fill(HIST("hEtaPhiReco_PrAll"), vz, sign, pt, eta, phi); - histos.fill(HIST("hEtaPhiRecoWtd_PrAll"), vz, sign, pt, eta, phi, w); - histos.fill(HIST("hEtaPhiRecoEffWtd_PrAll"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); - } - } + histos.fill(HIST("Eff_eta"), eta, eff); + histos.fill(HIST("Fake_eta"), eta, fake); + histos.fill(HIST("wgt_eta"), eta, w); + } + if (isp == kInclusiveIdx) { + histos.fill(HIST("hEtaPhiReco"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kPiMinusIdx) { + histos.fill(HIST("hEtaPhiReco_PiMinus"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_PiMinus"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_PiMinus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kPiPlusIdx) { + histos.fill(HIST("hEtaPhiReco_PiPlus"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_PiPlus"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_PiPlus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kPiAllIdx) { + histos.fill(HIST("hEtaPhiReco_PiAll"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_PiAll"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_PiAll"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kKaMinusIdx) { + histos.fill(HIST("hEtaPhiReco_KaMinus"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_KaMinus"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_KaMinus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kKaPlusIdx) { + histos.fill(HIST("hEtaPhiReco_KaPlus"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_KaPlus"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_KaPlus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kKaAllIdx) { + histos.fill(HIST("hEtaPhiReco_KaAll"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_KaAll"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_KaAll"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kPrIdx) { + histos.fill(HIST("hEtaPhiReco_Pr"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_Pr"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_Pr"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kAntiPrIdx) { + histos.fill(HIST("hEtaPhiReco_AntiPr"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_AntiPr"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_AntiPr"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kPrAllIdx) { + histos.fill(HIST("hEtaPhiReco_PrAll"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_PrAll"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_PrAll"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); } + } + } - for (int isp = 0; isp < KNsp; ++isp) { - histos.fill(HIST("MCReco/Prof_Cent_Nsp_Nchrec"), cent, isp, sumWiReco[isp][0]); - histos.fill(HIST("MCReco/Prof_Mult_Nsp_Nchrec"), multPV, isp, sumWiReco[isp][0]); + for (int isp = 0; isp < KNsp; ++isp) { + histos.fill(HIST("MCReco/Prof_Cent_Nsp_Nchrec"), cent, isp, sumWiReco[isp][0]); + histos.fill(HIST("MCReco/Prof_Mult_Nsp_Nchrec"), multPV, isp, sumWiReco[isp][0]); - histos.fill(HIST("MCRecoEffCorr/Prof_Cent_Nsp_Nchrec"), cent, isp, sumWiRecoEffCorr[isp][0]); - histos.fill(HIST("MCRecoEffCorr/Prof_Mult_Nsp_Nchrec"), multPV, isp, sumWiRecoEffCorr[isp][0]); + histos.fill(HIST("MCRecoEffCorr/Prof_Cent_Nsp_Nchrec"), cent, isp, sumWiRecoEffCorr[isp][0]); + histos.fill(HIST("MCRecoEffCorr/Prof_Mult_Nsp_Nchrec"), multPV, isp, sumWiRecoEffCorr[isp][0]); - if (sumWiReco[isp][0] > 1.0f) { - histos.fill(HIST("MCReco/Prof_Cent_Nsp_MeanpT"), cent, isp, sumWiptiReco[isp][0] / sumWiReco[isp][0]); - histos.fill(HIST("MCReco/Prof_Mult_Nsp_MeanpT"), multPV, isp, sumWiptiReco[isp][0] / sumWiReco[isp][0]); - } - if (sumWiRecoEffCorr[isp][0] > 1.0f) { - histos.fill(HIST("MCRecoEffCorr/Prof_Cent_Nsp_MeanpT"), cent, isp, sumWiptiRecoEffCorr[isp][0] / sumWiRecoEffCorr[isp][0]); - histos.fill(HIST("MCRecoEffCorr/Prof_Mult_Nsp_MeanpT"), multPV, isp, sumWiptiRecoEffCorr[isp][0] / sumWiRecoEffCorr[isp][0]); - } - } + if (sumWiReco[isp][0] > 1.0f) { + histos.fill(HIST("MCReco/Prof_Cent_Nsp_MeanpT"), cent, isp, sumWiptiReco[isp][0] / sumWiReco[isp][0]); + histos.fill(HIST("MCReco/Prof_Mult_Nsp_MeanpT"), multPV, isp, sumWiptiReco[isp][0] / sumWiReco[isp][0]); + } + if (sumWiRecoEffCorr[isp][0] > 1.0f) { + histos.fill(HIST("MCRecoEffCorr/Prof_Cent_Nsp_MeanpT"), cent, isp, sumWiptiRecoEffCorr[isp][0] / sumWiRecoEffCorr[isp][0]); + histos.fill(HIST("MCRecoEffCorr/Prof_Mult_Nsp_MeanpT"), multPV, isp, sumWiptiRecoEffCorr[isp][0] / sumWiRecoEffCorr[isp][0]); + } + } - for (int ietaA = 0; ietaA < KNEta; ++ietaA) { - for (int ietaC = 0; ietaC < KNEta; ++ietaC) { - for (int isp = 0; isp < KNsp; ++isp) { - float nTruAB = sumWiTruth[isp][ietaA] + sumWiTruth[isp][ietaC]; - float nRecoAB = sumWiReco[isp][ietaA] + sumWiReco[isp][ietaC]; - float nCorrAB = sumWiRecoEffCorr[isp][ietaA] + sumWiRecoEffCorr[isp][ietaC]; - - float mptsubTru = (sumWiptiTruth[isp][ietaA] + sumWiptiTruth[isp][ietaC]) / nTruAB; - float mptsubReco = (sumWiptiReco[isp][ietaA] + sumWiptiReco[isp][ietaC]) / nRecoAB; - float mptsubRecoEffCorr = (sumWiptiRecoEffCorr[isp][ietaA] + sumWiptiRecoEffCorr[isp][ietaC]) / nCorrAB; - - if (nTruAB > 0) { - if (isp == kInclusiveIdx) - histos.fill(HIST("Prof2D_MeanpTSub_Tru"), cent, ietaA, ietaC, mptsubTru); - else if (isp == kPiMinusIdx) - histos.fill(HIST("Prof2D_MeanpTSub_Tru_PiMinus"), cent, ietaA, ietaC, mptsubTru); - else if (isp == kPiPlusIdx) - histos.fill(HIST("Prof2D_MeanpTSub_Tru_PiPlus"), cent, ietaA, ietaC, mptsubTru); - else if (isp == kPiAllIdx) - histos.fill(HIST("Prof2D_MeanpTSub_Tru_PiAll"), cent, ietaA, ietaC, mptsubTru); - else if (isp == kKaMinusIdx) - histos.fill(HIST("Prof2D_MeanpTSub_Tru_KaMinus"), cent, ietaA, ietaC, mptsubTru); - else if (isp == kKaPlusIdx) - histos.fill(HIST("Prof2D_MeanpTSub_Tru_KaPlus"), cent, ietaA, ietaC, mptsubTru); - else if (isp == kKaAllIdx) - histos.fill(HIST("Prof2D_MeanpTSub_Tru_KaAll"), cent, ietaA, ietaC, mptsubTru); - else if (isp == kPrIdx) - histos.fill(HIST("Prof2D_MeanpTSub_Tru_Pr"), cent, ietaA, ietaC, mptsubTru); - else if (isp == kAntiPrIdx) - histos.fill(HIST("Prof2D_MeanpTSub_Tru_AntiPr"), cent, ietaA, ietaC, mptsubTru); - else if (isp == kPrAllIdx) - histos.fill(HIST("Prof2D_MeanpTSub_Tru_PrAll"), cent, ietaA, ietaC, mptsubTru); - } + for (int ietaA = 0; ietaA < KNEta; ++ietaA) { + for (int ietaC = 0; ietaC < KNEta; ++ietaC) { + for (int isp = 0; isp < KNsp; ++isp) { + float nTruAB = sumWiTruth[isp][ietaA] + sumWiTruth[isp][ietaC]; + float nRecoAB = sumWiReco[isp][ietaA] + sumWiReco[isp][ietaC]; + float nCorrAB = sumWiRecoEffCorr[isp][ietaA] + sumWiRecoEffCorr[isp][ietaC]; - if (nRecoAB > 0) { - if (isp == kInclusiveIdx) - histos.fill(HIST("Prof2D_MeanpTSub_Reco"), cent, ietaA, ietaC, mptsubReco); - else if (isp == kPiMinusIdx) - histos.fill(HIST("Prof2D_MeanpTSub_Reco_PiMinus"), cent, ietaA, ietaC, mptsubReco); - else if (isp == kPiPlusIdx) - histos.fill(HIST("Prof2D_MeanpTSub_Reco_PiPlus"), cent, ietaA, ietaC, mptsubReco); - else if (isp == kPiAllIdx) - histos.fill(HIST("Prof2D_MeanpTSub_Reco_PiAll"), cent, ietaA, ietaC, mptsubReco); - else if (isp == kKaMinusIdx) - histos.fill(HIST("Prof2D_MeanpTSub_Reco_KaMinus"), cent, ietaA, ietaC, mptsubReco); - else if (isp == kKaPlusIdx) - histos.fill(HIST("Prof2D_MeanpTSub_Reco_KaPlus"), cent, ietaA, ietaC, mptsubReco); - else if (isp == kKaAllIdx) - histos.fill(HIST("Prof2D_MeanpTSub_Reco_KaAll"), cent, ietaA, ietaC, mptsubReco); - else if (isp == kPrIdx) - histos.fill(HIST("Prof2D_MeanpTSub_Reco_Pr"), cent, ietaA, ietaC, mptsubReco); - else if (isp == kAntiPrIdx) - histos.fill(HIST("Prof2D_MeanpTSub_Reco_AntiPr"), cent, ietaA, ietaC, mptsubReco); - else if (isp == kPrAllIdx) - histos.fill(HIST("Prof2D_MeanpTSub_Reco_PrAll"), cent, ietaA, ietaC, mptsubReco); - } + float mptsubTru = (sumWiptiTruth[isp][ietaA] + sumWiptiTruth[isp][ietaC]) / nTruAB; + float mptsubReco = (sumWiptiReco[isp][ietaA] + sumWiptiReco[isp][ietaC]) / nRecoAB; + float mptsubRecoEffCorr = (sumWiptiRecoEffCorr[isp][ietaA] + sumWiptiRecoEffCorr[isp][ietaC]) / nCorrAB; - if (nCorrAB > 0) { - if (isp == kInclusiveIdx) - histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr"), cent, ietaA, ietaC, mptsubRecoEffCorr); - else if (isp == kPiMinusIdx) - histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr_PiMinus"), cent, ietaA, ietaC, mptsubRecoEffCorr); - else if (isp == kPiPlusIdx) - histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr_PiPlus"), cent, ietaA, ietaC, mptsubRecoEffCorr); - else if (isp == kPiAllIdx) - histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr_PiAll"), cent, ietaA, ietaC, mptsubRecoEffCorr); - else if (isp == kKaMinusIdx) - histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr_KaMinus"), cent, ietaA, ietaC, mptsubRecoEffCorr); - else if (isp == kKaPlusIdx) - histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr_KaPlus"), cent, ietaA, ietaC, mptsubRecoEffCorr); - else if (isp == kKaAllIdx) - histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr_KaAll"), cent, ietaA, ietaC, mptsubRecoEffCorr); - else if (isp == kPrIdx) - histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr_Pr"), cent, ietaA, ietaC, mptsubRecoEffCorr); - else if (isp == kAntiPrIdx) - histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr_AntiPr"), cent, ietaA, ietaC, mptsubRecoEffCorr); - else if (isp == kPrAllIdx) - histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr_PrAll"), cent, ietaA, ietaC, mptsubRecoEffCorr); - } - } + if (nTruAB > 0) { + if (isp == kInclusiveIdx) + histos.fill(HIST("Prof2D_MeanpTSub_Tru"), cent, ietaA, ietaC, mptsubTru); + else if (isp == kPiMinusIdx) + histos.fill(HIST("Prof2D_MeanpTSub_Tru_PiMinus"), cent, ietaA, ietaC, mptsubTru); + else if (isp == kPiPlusIdx) + histos.fill(HIST("Prof2D_MeanpTSub_Tru_PiPlus"), cent, ietaA, ietaC, mptsubTru); + else if (isp == kPiAllIdx) + histos.fill(HIST("Prof2D_MeanpTSub_Tru_PiAll"), cent, ietaA, ietaC, mptsubTru); + else if (isp == kKaMinusIdx) + histos.fill(HIST("Prof2D_MeanpTSub_Tru_KaMinus"), cent, ietaA, ietaC, mptsubTru); + else if (isp == kKaPlusIdx) + histos.fill(HIST("Prof2D_MeanpTSub_Tru_KaPlus"), cent, ietaA, ietaC, mptsubTru); + else if (isp == kKaAllIdx) + histos.fill(HIST("Prof2D_MeanpTSub_Tru_KaAll"), cent, ietaA, ietaC, mptsubTru); + else if (isp == kPrIdx) + histos.fill(HIST("Prof2D_MeanpTSub_Tru_Pr"), cent, ietaA, ietaC, mptsubTru); + else if (isp == kAntiPrIdx) + histos.fill(HIST("Prof2D_MeanpTSub_Tru_AntiPr"), cent, ietaA, ietaC, mptsubTru); + else if (isp == kPrAllIdx) + histos.fill(HIST("Prof2D_MeanpTSub_Tru_PrAll"), cent, ietaA, ietaC, mptsubTru); } - for (int isp = 0; isp < KNsp; ++isp) { - if (sumWiTruth[isp][ietaA] > 0) { - float val = sumWiptiTruth[isp][ietaA] / sumWiTruth[isp][ietaA]; - histos.fill(HIST("pmeanTru_nch_etabin_spbin"), multPV, ietaA, isp, val); - histos.fill(HIST("pmeanMultTru_nch_etabin_spbin"), multPV, ietaA, isp, sumWiTruth[isp][ietaA]); - } - if (sumWiReco[isp][ietaA] > 0) { - float val = sumWiptiReco[isp][ietaA] / sumWiReco[isp][ietaA]; - histos.fill(HIST("pmeanReco_nch_etabin_spbin"), multPV, ietaA, isp, val); - histos.fill(HIST("pmeanMultReco_nch_etabin_spbin"), multPV, ietaA, isp, sumWiReco[isp][ietaA]); - } - if (sumWiRecoEffCorr[isp][ietaA] > 0) { - float val = sumWiptiRecoEffCorr[isp][ietaA] / sumWiRecoEffCorr[isp][ietaA]; - histos.fill(HIST("pmeanRecoEffcorr_nch_etabin_spbin"), multPV, ietaA, isp, val); - histos.fill(HIST("pmeanMultRecoEffcorr_nch_etabin_spbin"), multPV, ietaA, isp, sumWiRecoEffCorr[isp][ietaA]); - } - } - } // end ietaA - - double amplFT0A = 0, amplFT0C = 0; - if (mcCollision.has_foundFT0()) { - const auto& ft0 = mcCollision.foundFT0(); - for (std::size_t iCh = 0; iCh < ft0.channelA().size(); iCh++) { - auto chanelid = ft0.channelA()[iCh]; - float ampl = ft0.amplitudeA()[iCh]; - amplFT0A += ampl; - auto eta = getEtaFT0(chanelid, 0); - histos.fill(HIST("pmean_cent_id_eta_FT0"), cent, chanelid, eta, ampl); - histos.fill(HIST("h3_cent_id_eta_FT0"), cent, chanelid, eta, ampl); + if (nRecoAB > 0) { + if (isp == kInclusiveIdx) + histos.fill(HIST("Prof2D_MeanpTSub_Reco"), cent, ietaA, ietaC, mptsubReco); + else if (isp == kPiMinusIdx) + histos.fill(HIST("Prof2D_MeanpTSub_Reco_PiMinus"), cent, ietaA, ietaC, mptsubReco); + else if (isp == kPiPlusIdx) + histos.fill(HIST("Prof2D_MeanpTSub_Reco_PiPlus"), cent, ietaA, ietaC, mptsubReco); + else if (isp == kPiAllIdx) + histos.fill(HIST("Prof2D_MeanpTSub_Reco_PiAll"), cent, ietaA, ietaC, mptsubReco); + else if (isp == kKaMinusIdx) + histos.fill(HIST("Prof2D_MeanpTSub_Reco_KaMinus"), cent, ietaA, ietaC, mptsubReco); + else if (isp == kKaPlusIdx) + histos.fill(HIST("Prof2D_MeanpTSub_Reco_KaPlus"), cent, ietaA, ietaC, mptsubReco); + else if (isp == kKaAllIdx) + histos.fill(HIST("Prof2D_MeanpTSub_Reco_KaAll"), cent, ietaA, ietaC, mptsubReco); + else if (isp == kPrIdx) + histos.fill(HIST("Prof2D_MeanpTSub_Reco_Pr"), cent, ietaA, ietaC, mptsubReco); + else if (isp == kAntiPrIdx) + histos.fill(HIST("Prof2D_MeanpTSub_Reco_AntiPr"), cent, ietaA, ietaC, mptsubReco); + else if (isp == kPrAllIdx) + histos.fill(HIST("Prof2D_MeanpTSub_Reco_PrAll"), cent, ietaA, ietaC, mptsubReco); } - for (std::size_t iCh = 0; iCh < ft0.channelC().size(); iCh++) { - auto chanelid = ft0.channelC()[iCh]; - auto globalId = chanelid + KnFt0cCell; - float ampl = ft0.amplitudeC()[iCh]; - auto eta = getEtaFT0(globalId, 1); - amplFT0C += ampl; - histos.fill(HIST("pmean_cent_id_eta_FT0"), cent, globalId, eta, ampl); - histos.fill(HIST("h3_cent_id_eta_FT0"), cent, globalId, eta, ampl); + + if (nCorrAB > 0) { + if (isp == kInclusiveIdx) + histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr"), cent, ietaA, ietaC, mptsubRecoEffCorr); + else if (isp == kPiMinusIdx) + histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr_PiMinus"), cent, ietaA, ietaC, mptsubRecoEffCorr); + else if (isp == kPiPlusIdx) + histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr_PiPlus"), cent, ietaA, ietaC, mptsubRecoEffCorr); + else if (isp == kPiAllIdx) + histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr_PiAll"), cent, ietaA, ietaC, mptsubRecoEffCorr); + else if (isp == kKaMinusIdx) + histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr_KaMinus"), cent, ietaA, ietaC, mptsubRecoEffCorr); + else if (isp == kKaPlusIdx) + histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr_KaPlus"), cent, ietaA, ietaC, mptsubRecoEffCorr); + else if (isp == kKaAllIdx) + histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr_KaAll"), cent, ietaA, ietaC, mptsubRecoEffCorr); + else if (isp == kPrIdx) + histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr_Pr"), cent, ietaA, ietaC, mptsubRecoEffCorr); + else if (isp == kAntiPrIdx) + histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr_AntiPr"), cent, ietaA, ietaC, mptsubRecoEffCorr); + else if (isp == kPrAllIdx) + histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr_PrAll"), cent, ietaA, ietaC, mptsubRecoEffCorr); } } + } + + for (int isp = 0; isp < KNsp; ++isp) { + if (sumWiTruth[isp][ietaA] > 0) { + float val = sumWiptiTruth[isp][ietaA] / sumWiTruth[isp][ietaA]; + histos.fill(HIST("pmeanTru_nch_etabin_spbin"), multPV, ietaA, isp, val); + histos.fill(HIST("pmeanMultTru_nch_etabin_spbin"), multPV, ietaA, isp, sumWiTruth[isp][ietaA]); + } + if (sumWiReco[isp][ietaA] > 0) { + float val = sumWiptiReco[isp][ietaA] / sumWiReco[isp][ietaA]; + histos.fill(HIST("pmeanReco_nch_etabin_spbin"), multPV, ietaA, isp, val); + histos.fill(HIST("pmeanMultReco_nch_etabin_spbin"), multPV, ietaA, isp, sumWiReco[isp][ietaA]); + } + if (sumWiRecoEffCorr[isp][ietaA] > 0) { + float val = sumWiptiRecoEffCorr[isp][ietaA] / sumWiRecoEffCorr[isp][ietaA]; + histos.fill(HIST("pmeanRecoEffcorr_nch_etabin_spbin"), multPV, ietaA, isp, val); + histos.fill(HIST("pmeanMultRecoEffcorr_nch_etabin_spbin"), multPV, ietaA, isp, sumWiRecoEffCorr[isp][ietaA]); + } + } + } // end ietaA - histos.fill(HIST("pmeanFT0Amultpv"), multPV, amplFT0A); - histos.fill(HIST("pmeanFT0A_cent"), cent, amplFT0A); - histos.fill(HIST("pmeanFT0Cmultpv"), multPV, amplFT0C); - histos.fill(HIST("pmeanFT0C_cent"), cent, amplFT0C); + double amplFT0A = 0, amplFT0C = 0; + if (mcCollision.has_foundFT0()) { + const auto& ft0 = mcCollision.foundFT0(); + for (std::size_t iCh = 0; iCh < ft0.channelA().size(); iCh++) { + auto chanelid = ft0.channelA()[iCh]; + float ampl = ft0.amplitudeA()[iCh]; + amplFT0A += ampl; + auto eta = getEtaFT0(chanelid, 0); + histos.fill(HIST("pmean_cent_id_eta_FT0"), cent, chanelid, eta, ampl); + histos.fill(HIST("h3_cent_id_eta_FT0"), cent, chanelid, eta, ampl); + } + for (std::size_t iCh = 0; iCh < ft0.channelC().size(); iCh++) { + auto chanelid = ft0.channelC()[iCh]; + auto globalId = chanelid + KnFt0cCell; + float ampl = ft0.amplitudeC()[iCh]; + auto eta = getEtaFT0(globalId, 1); + amplFT0C += ampl; + histos.fill(HIST("pmean_cent_id_eta_FT0"), cent, globalId, eta, ampl); + histos.fill(HIST("h3_cent_id_eta_FT0"), cent, globalId, eta, ampl); + } + } + + histos.fill(HIST("pmeanFT0Amultpv"), multPV, amplFT0A); + histos.fill(HIST("pmeanFT0A_cent"), cent, amplFT0A); + histos.fill(HIST("pmeanFT0Cmultpv"), multPV, amplFT0C); + histos.fill(HIST("pmeanFT0C_cent"), cent, amplFT0C); } PROCESS_SWITCH(RadialFlowDecorr, processMCMean, "process MC to calculate mean pt and Eff Hists", cfgRunMCMean); @@ -2248,6 +2247,10 @@ struct RadialFlowDecorr { float eta = track.eta(); float phi = track.phi(); auto sign = track.sign(); + histos.fill(HIST("hPt"), pt); + histos.fill(HIST("hEta"), eta); + histos.fill(HIST("hPhi"), phi); + int id = identifyTrack(track, cent); bool isPi = (id == KPidPionOne); bool isKa = (id == KPidKaonTwo); @@ -2326,570 +2329,569 @@ struct RadialFlowDecorr { } } // trkslice - for (int ieta = 0; ieta < KNEta; ++ieta) { - const int ibx = state.pmeanTruNchEtabinSpbinStep2->GetXaxis()->FindBin(mcCollision.multNTracksPV()); - const int iby = ieta + 1; - - for (int isp = 0; isp < KNsp; ++isp) { - const int ibz = isp + 1; - - meanTruMult[isp][ieta] = sumWkTru[isp][ieta][1]; - meanRecoMult[isp][ieta] = sumWkReco[isp][ieta][1]; - meanRecoEffCorMult[isp][ieta] = sumWkRecoEffCor[isp][ieta][1]; - - float mmptTru = state.pmeanTruNchEtabinSpbinStep2->GetBinContent(ibx, iby, ibz); - float mmptReco = state.pmeanRecoNchEtabinSpbinStep2->GetBinContent(ibx, iby, ibz); - float mmptRecoEffCor = state.pmeanRecoEffcorrNchEtabinSpbinStep2->GetBinContent(ibx, iby, ibz); - - float mmMultTru = state.pmeanMultTruNchEtabinSpbinStep2->GetBinContent(ibx, iby, ibz); - float mmMultReco = state.pmeanMultRecoNchEtabinSpbinStep2->GetBinContent(ibx, iby, ibz); - float mmMultRecoEffCor = state.pmeanMultRecoEffcorrNchEtabinSpbinStep2->GetBinContent(ibx, iby, ibz); - - if (std::isfinite(mmptTru)) - std::tie(meanTru[isp][ieta], c2Tru[isp][ieta]) = calculateMeanAndC2FromSums(sumPmwkTru[isp][ieta], sumWkTru[isp][ieta], mmptTru); - if (std::isfinite(mmptReco)) - std::tie(meanReco[isp][ieta], c2Reco[isp][ieta]) = calculateMeanAndC2FromSums(sumPmwkReco[isp][ieta], sumWkReco[isp][ieta], mmptReco); - if (std::isfinite(mmptRecoEffCor)) - std::tie(meanRecoEffCor[isp][ieta], c2RecoEffCor[isp][ieta]) = calculateMeanAndC2FromSums(sumPmwkRecoEffCor[isp][ieta], sumWkRecoEffCor[isp][ieta], mmptRecoEffCor); - - if (mmptTru != 0.0f) - p1kBarTru[isp][ieta] = meanTru[isp][ieta] - mmptTru; - if (mmptReco != 0.0f) - p1kBarReco[isp][ieta] = meanReco[isp][ieta] - mmptReco; - if (mmptRecoEffCor != 0.0f) - p1kBarRecoEffCor[isp][ieta] = meanRecoEffCor[isp][ieta] - mmptRecoEffCor; - - if (mmMultTru != 0.0f) - p1kBarTruMult[isp][ieta] = meanTruMult[isp][ieta] - mmMultTru; - if (mmMultReco != 0.0f) - p1kBarRecoMult[isp][ieta] = meanRecoMult[isp][ieta] - mmMultReco; - if (mmMultRecoEffCor != 0.0f) - p1kBarRecoEffCorMult[isp][ieta] = meanRecoEffCorMult[isp][ieta] - mmMultRecoEffCor; - } + for (int ieta = 0; ieta < KNEta; ++ieta) { + const int ibx = state.pmeanTruNchEtabinSpbinStep2->GetXaxis()->FindBin(mcCollision.multNTracksPV()); + const int iby = ieta + 1; + + for (int isp = 0; isp < KNsp; ++isp) { + const int ibz = isp + 1; + + meanTruMult[isp][ieta] = sumWkTru[isp][ieta][1]; + meanRecoMult[isp][ieta] = sumWkReco[isp][ieta][1]; + meanRecoEffCorMult[isp][ieta] = sumWkRecoEffCor[isp][ieta][1]; + + float mmptTru = state.pmeanTruNchEtabinSpbinStep2->GetBinContent(ibx, iby, ibz); + float mmptReco = state.pmeanRecoNchEtabinSpbinStep2->GetBinContent(ibx, iby, ibz); + float mmptRecoEffCor = state.pmeanRecoEffcorrNchEtabinSpbinStep2->GetBinContent(ibx, iby, ibz); + + float mmMultTru = state.pmeanMultTruNchEtabinSpbinStep2->GetBinContent(ibx, iby, ibz); + float mmMultReco = state.pmeanMultRecoNchEtabinSpbinStep2->GetBinContent(ibx, iby, ibz); + float mmMultRecoEffCor = state.pmeanMultRecoEffcorrNchEtabinSpbinStep2->GetBinContent(ibx, iby, ibz); + + if (std::isfinite(mmptTru)) + std::tie(meanTru[isp][ieta], c2Tru[isp][ieta]) = calculateMeanAndC2FromSums(sumPmwkTru[isp][ieta], sumWkTru[isp][ieta], mmptTru); + if (std::isfinite(mmptReco)) + std::tie(meanReco[isp][ieta], c2Reco[isp][ieta]) = calculateMeanAndC2FromSums(sumPmwkReco[isp][ieta], sumWkReco[isp][ieta], mmptReco); + if (std::isfinite(mmptRecoEffCor)) + std::tie(meanRecoEffCor[isp][ieta], c2RecoEffCor[isp][ieta]) = calculateMeanAndC2FromSums(sumPmwkRecoEffCor[isp][ieta], sumWkRecoEffCor[isp][ieta], mmptRecoEffCor); + + if (mmptTru != 0.0f) + p1kBarTru[isp][ieta] = meanTru[isp][ieta] - mmptTru; + if (mmptReco != 0.0f) + p1kBarReco[isp][ieta] = meanReco[isp][ieta] - mmptReco; + if (mmptRecoEffCor != 0.0f) + p1kBarRecoEffCor[isp][ieta] = meanRecoEffCor[isp][ieta] - mmptRecoEffCor; + + if (mmMultTru != 0.0f) + p1kBarTruMult[isp][ieta] = meanTruMult[isp][ieta] - mmMultTru; + if (mmMultReco != 0.0f) + p1kBarRecoMult[isp][ieta] = meanRecoMult[isp][ieta] - mmMultReco; + if (mmMultRecoEffCor != 0.0f) + p1kBarRecoEffCorMult[isp][ieta] = meanRecoEffCorMult[isp][ieta] - mmMultRecoEffCor; + } + } + + double amplFT0A = 0, amplFT0C = 0; + if (mcCollision.has_foundFT0()) { + const auto& ft0 = mcCollision.foundFT0(); + for (std::size_t iCh = 0; iCh < ft0.channelA().size(); iCh++) { + float ampl = ft0.amplitudeA()[iCh]; + amplFT0A += ampl; + } + for (std::size_t iCh = 0; iCh < ft0.channelC().size(); iCh++) { + float ampl = ft0.amplitudeC()[iCh]; + amplFT0C += ampl; + } + } + + for (int isp = 0; isp < KNsp; ++isp) { + for (int ieta = 0; ieta < KNEta; ++ieta) { + histos.fill(HIST("MCGen/Prof_Cent_NEta_Nsp_Nchrec"), cent, ieta, isp, sumWkTru[isp][ieta][1]); + histos.fill(HIST("MCGen/Prof_Mult_NEta_Nsp_Nchrec"), multPV, ieta, isp, sumWkTru[isp][ieta][1]); + + histos.fill(HIST("MCReco/Prof_Cent_NEta_Nsp_Nchrec"), cent, ieta, isp, sumWkReco[isp][ieta][1]); + histos.fill(HIST("MCReco/Prof_Mult_NEta_Nsp_Nchrec"), multPV, ieta, isp, sumWkReco[isp][ieta][1]); + + histos.fill(HIST("MCRecoEffCorr/Prof_Cent_NEta_Nsp_Nchrec"), cent, ieta, isp, sumWkRecoEffCor[isp][ieta][1]); + histos.fill(HIST("MCRecoEffCorr/Prof_Mult_NEta_Nsp_Nchrec"), multPV, ieta, isp, sumWkRecoEffCor[isp][ieta][1]); + + if (sumWkTru[isp][ieta][1] > 1.0f) { + histos.fill(HIST("MCGen/Prof_Cent_NEta_Nsp_MeanpT"), cent, ieta, isp, meanTru[isp][ieta]); + histos.fill(HIST("MCGen/Prof_Mult_NEta_Nsp_MeanpT"), multPV, ieta, isp, meanTru[isp][ieta]); + } + if (sumWkReco[isp][ieta][1] > 1.0f) { + histos.fill(HIST("MCReco/Prof_Cent_NEta_Nsp_MeanpT"), cent, ieta, isp, meanReco[isp][ieta]); + histos.fill(HIST("MCReco/Prof_Mult_NEta_Nsp_MeanpT"), multPV, ieta, isp, meanReco[isp][ieta]); } + if (sumWkRecoEffCor[isp][ieta][1] > 1.0f) { + histos.fill(HIST("MCRecoEffCorr/Prof_Cent_NEta_Nsp_MeanpT"), cent, ieta, isp, meanRecoEffCor[isp][ieta]); + histos.fill(HIST("MCRecoEffCorr/Prof_Mult_NEta_Nsp_MeanpT"), multPV, ieta, isp, meanRecoEffCor[isp][ieta]); + } + } + } - double amplFT0A = 0, amplFT0C = 0; - if (mcCollision.has_foundFT0()) { - const auto& ft0 = mcCollision.foundFT0(); - for (std::size_t iCh = 0; iCh < ft0.channelA().size(); iCh++) { - float ampl = ft0.amplitudeA()[iCh]; - amplFT0A += ampl; - } - for (std::size_t iCh = 0; iCh < ft0.channelC().size(); iCh++) { - float ampl = ft0.amplitudeC()[iCh]; - amplFT0C += ampl; - } + for (int ieta = 0; ieta < KNEta; ++ieta) { + for (int isp = 0; isp < KNsp; ++isp) { + if (std::isfinite(meanTru[isp][ieta])) { + histos.fill(HIST("MCGen/Prof_MeanpT_Cent_etabin_spbin"), cent, ieta, isp, meanTru[isp][ieta]); + histos.fill(HIST("MCGen/Prof_MeanpT_Mult_etabin_spbin"), multPV, ieta, isp, meanTru[isp][ieta]); + } + if (std::isfinite(c2Tru[isp][ieta])) { + histos.fill(HIST("MCGen/Prof_C2_Cent_etabin_spbin"), cent, ieta, isp, c2Tru[isp][ieta]); + histos.fill(HIST("MCGen/Prof_C2_Mult_etabin_spbin"), multPV, ieta, isp, c2Tru[isp][ieta]); + } + if (std::isfinite(meanReco[isp][ieta])) { + histos.fill(HIST("MCReco/Prof_MeanpT_Cent_etabin_spbin"), cent, ieta, isp, meanReco[isp][ieta]); + histos.fill(HIST("MCReco/Prof_MeanpT_Mult_etabin_spbin"), multPV, ieta, isp, meanReco[isp][ieta]); + } + if (std::isfinite(c2Reco[isp][ieta])) { + histos.fill(HIST("MCReco/Prof_C2_Cent_etabin_spbin"), cent, ieta, isp, c2Reco[isp][ieta]); + histos.fill(HIST("MCReco/Prof_C2_Mult_etabin_spbin"), multPV, ieta, isp, c2Reco[isp][ieta]); } + if (std::isfinite(meanRecoEffCor[isp][ieta])) { + histos.fill(HIST("MCRecoEffCorr/Prof_MeanpT_Cent_etabin_spbin"), cent, ieta, isp, meanRecoEffCor[isp][ieta]); + histos.fill(HIST("MCRecoEffCorr/Prof_MeanpT_Mult_etabin_spbin"), multPV, ieta, isp, meanRecoEffCor[isp][ieta]); + } + if (std::isfinite(c2RecoEffCor[isp][ieta])) { + histos.fill(HIST("MCRecoEffCorr/Prof_C2_Cent_etabin_spbin"), cent, ieta, isp, c2RecoEffCor[isp][ieta]); + histos.fill(HIST("MCRecoEffCorr/Prof_C2_Mult_etabin_spbin"), multPV, ieta, isp, c2RecoEffCor[isp][ieta]); + } + } + } + + p1kBarFt0A = amplFT0A - state.pmeanFT0AmultpvStep2->GetBinContent(state.pmeanFT0AmultpvStep2->GetXaxis()->FindBin(multPV)); + p1kBarFt0C = amplFT0C - state.pmeanFT0CmultpvStep2->GetBinContent(state.pmeanFT0CmultpvStep2->GetXaxis()->FindBin(multPV)); + for (int ietaA = 1; ietaA <= (KNEta - 1) / 2; ++ietaA) { + int ietaC = KNEta - ietaA; + for (int isp = 0; isp < KNsp; ++isp) { + float c2SubTru = p1kBarTru[isp][ietaA] * p1kBarTru[isp][ietaC]; + float c2SubReco = p1kBarReco[isp][ietaA] * p1kBarReco[isp][ietaC]; + float c2SubRecoEffCor = p1kBarRecoEffCor[isp][ietaA] * p1kBarRecoEffCor[isp][ietaC]; + + float covTru = p1kBarTruMult[isp][ietaA] * p1kBarTru[isp][ietaC]; + float covReco = p1kBarRecoMult[isp][ietaA] * p1kBarReco[isp][ietaC]; + float covRecoEffCor = p1kBarRecoEffCorMult[isp][ietaA] * p1kBarRecoEffCor[isp][ietaC]; + + float covFT0ATru = p1kBarFt0A * p1kBarTru[isp][ietaC]; + float covFT0AReco = p1kBarFt0A * p1kBarReco[isp][ietaC]; + float covFT0ARecoEffCor = p1kBarFt0A * p1kBarRecoEffCor[isp][ietaC]; + + float covFT0CTru = p1kBarFt0C * p1kBarTru[isp][ietaA]; + float covFT0CReco = p1kBarFt0C * p1kBarReco[isp][ietaA]; + float covFT0CRecoEffCor = p1kBarFt0C * p1kBarRecoEffCor[isp][ietaA]; + + if (std::isfinite(c2SubTru)) { + histos.fill(HIST("MCGen/Prof_C2Sub_Cent_etabin_spbin"), cent, ietaA, isp, c2SubTru); + histos.fill(HIST("MCGen/Prof_C2Sub_Mult_etabin_spbin"), multPV, ietaA, isp, c2SubTru); + } + if (std::isfinite(c2SubReco)) { + histos.fill(HIST("MCReco/Prof_C2Sub_Cent_etabin_spbin"), cent, ietaA, isp, c2SubReco); + histos.fill(HIST("MCReco/Prof_C2Sub_Mult_etabin_spbin"), multPV, ietaA, isp, c2SubReco); + } + if (std::isfinite(c2SubRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub_Cent_etabin_spbin"), cent, ietaA, isp, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub_Mult_etabin_spbin"), multPV, ietaA, isp, c2SubRecoEffCor); + } + if (std::isfinite(covTru)) { + histos.fill(HIST("MCGen/Prof_Cov_Cent_etabin_spbin"), cent, ietaA, isp, covTru); + histos.fill(HIST("MCGen/Prof_Cov_Mult_etabin_spbin"), multPV, ietaA, isp, covTru); + } + if (std::isfinite(covReco)) { + histos.fill(HIST("MCReco/Prof_Cov_Cent_etabin_spbin"), cent, ietaA, isp, covReco); + histos.fill(HIST("MCReco/Prof_Cov_Mult_etabin_spbin"), multPV, ietaA, isp, covReco); + } + if (std::isfinite(covRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_Cov_Cent_etabin_spbin"), cent, ietaA, isp, covRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_Cov_Mult_etabin_spbin"), multPV, ietaA, isp, covRecoEffCor); + } + + if (std::isfinite(covFT0ATru)) { + histos.fill(HIST("MCGen/Prof_CovFT0A_Cent_etabin_spbin"), cent, ietaA, isp, covFT0ATru); + histos.fill(HIST("MCGen/Prof_CovFT0A_Mult_etabin_spbin"), multPV, ietaA, isp, covFT0ATru); + } + if (std::isfinite(covFT0AReco)) { + histos.fill(HIST("MCReco/Prof_CovFT0A_Cent_etabin_spbin"), cent, ietaA, isp, covFT0AReco); + histos.fill(HIST("MCReco/Prof_CovFT0A_Mult_etabin_spbin"), multPV, ietaA, isp, covFT0AReco); + } + if (std::isfinite(covFT0ARecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A_Cent_etabin_spbin"), cent, ietaA, isp, covFT0ARecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A_Mult_etabin_spbin"), multPV, ietaA, isp, covFT0ARecoEffCor); + } + + if (std::isfinite(covFT0CTru)) { + histos.fill(HIST("MCGen/Prof_CovFT0C_Cent_etabin_spbin"), cent, ietaA, isp, covFT0CTru); + histos.fill(HIST("MCGen/Prof_CovFT0C_Mult_etabin_spbin"), multPV, ietaA, isp, covFT0CTru); + } + if (std::isfinite(covFT0CReco)) { + histos.fill(HIST("MCReco/Prof_CovFT0C_Cent_etabin_spbin"), cent, ietaA, isp, covFT0CReco); + histos.fill(HIST("MCReco/Prof_CovFT0C_Mult_etabin_spbin"), multPV, ietaA, isp, covFT0CReco); + } + if (std::isfinite(covFT0CRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C_Cent_etabin_spbin"), cent, ietaA, isp, covFT0CRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C_Mult_etabin_spbin"), multPV, ietaA, isp, covFT0CRecoEffCor); + } + } + } + + for (int ietaA = 1; ietaA < KNEta; ++ietaA) { + for (int ietaC = 1; ietaC < KNEta; ++ietaC) { + + float etaValA = (etaLw[ietaA] + etaUp[ietaA]) / 2.0f; + float etaValB = (etaLw[ietaC] + etaUp[ietaC]) / 2.0f; + float gap = etaValA - etaValB; + float sum = (etaValA + etaValB); for (int isp = 0; isp < KNsp; ++isp) { - for (int ieta = 0; ieta < KNEta; ++ieta) { - histos.fill(HIST("MCGen/Prof_Cent_NEta_Nsp_Nchrec"), cent, ieta, isp, sumWkTru[isp][ieta][1]); - histos.fill(HIST("MCGen/Prof_Mult_NEta_Nsp_Nchrec"), multPV, ieta, isp, sumWkTru[isp][ieta][1]); - histos.fill(HIST("MCReco/Prof_Cent_NEta_Nsp_Nchrec"), cent, ieta, isp, sumWkReco[isp][ieta][1]); - histos.fill(HIST("MCReco/Prof_Mult_NEta_Nsp_Nchrec"), multPV, ieta, isp, sumWkReco[isp][ieta][1]); + float c2SubTru = p1kBarTru[isp][ietaA] * p1kBarTru[isp][ietaC]; + float c2SubReco = p1kBarReco[isp][ietaA] * p1kBarReco[isp][ietaC]; + float c2SubRecoEffCor = p1kBarRecoEffCor[isp][ietaA] * p1kBarRecoEffCor[isp][ietaC]; + + float covTru = p1kBarTruMult[isp][ietaA] * p1kBarTru[isp][ietaC]; + float covReco = p1kBarRecoMult[isp][ietaA] * p1kBarReco[isp][ietaC]; + float covRecoEffCor = p1kBarRecoEffCorMult[isp][ietaA] * p1kBarRecoEffCor[isp][ietaC]; - histos.fill(HIST("MCRecoEffCorr/Prof_Cent_NEta_Nsp_Nchrec"), cent, ieta, isp, sumWkRecoEffCor[isp][ieta][1]); - histos.fill(HIST("MCRecoEffCorr/Prof_Mult_NEta_Nsp_Nchrec"), multPV, ieta, isp, sumWkRecoEffCor[isp][ieta][1]); + float covFT0ATru = p1kBarFt0A * p1kBarTru[isp][ietaC]; + float covFT0AReco = p1kBarFt0A * p1kBarReco[isp][ietaC]; + float covFT0ARecoEffCor = p1kBarFt0A * p1kBarRecoEffCor[isp][ietaC]; - if (sumWkTru[isp][ieta][1] > 1.0f) { - histos.fill(HIST("MCGen/Prof_Cent_NEta_Nsp_MeanpT"), cent, ieta, isp, meanTru[isp][ieta]); - histos.fill(HIST("MCGen/Prof_Mult_NEta_Nsp_MeanpT"), multPV, ieta, isp, meanTru[isp][ieta]); + float covFT0CTru = p1kBarFt0C * p1kBarTru[isp][ietaA]; + float covFT0CReco = p1kBarFt0C * p1kBarReco[isp][ietaA]; + float covFT0CRecoEffCor = p1kBarFt0C * p1kBarRecoEffCor[isp][ietaA]; + + if (isp == kInclusiveIdx) { + if (std::isfinite(c2SubTru)) { + histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC"), cent, etaValA, etaValB, c2SubTru); + histos.fill(HIST("MCGen/Prof_GapSum2D"), cent, gap, sum, c2SubTru); } - if (sumWkReco[isp][ieta][1] > 1.0f) { - histos.fill(HIST("MCReco/Prof_Cent_NEta_Nsp_MeanpT"), cent, ieta, isp, meanReco[isp][ieta]); - histos.fill(HIST("MCReco/Prof_Mult_NEta_Nsp_MeanpT"), multPV, ieta, isp, meanReco[isp][ieta]); + if (std::isfinite(c2SubReco)) { + histos.fill(HIST("MCReco/Prof_C2Sub2D_Cent_etaA_etaC"), cent, etaValA, etaValB, c2SubReco); + histos.fill(HIST("MCReco/Prof_GapSum2D"), cent, gap, sum, c2SubReco); } - if (sumWkRecoEffCor[isp][ieta][1] > 1.0f) { - histos.fill(HIST("MCReco/Prof_Cent_NEta_Nsp_MeanpT"), cent, ieta, isp, meanRecoEffCor[isp][ieta]); - histos.fill(HIST("MCReco/Prof_Mult_NEta_Nsp_MeanpT"), multPV, ieta, isp, meanRecoEffCor[isp][ieta]); + if (std::isfinite(c2SubRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub2D_Cent_etaA_etaC"), cent, etaValA, etaValB, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_GapSum2D"), cent, gap, sum, c2SubRecoEffCor); } - } - } - for (int ieta = 0; ieta < KNEta; ++ieta) { - for (int isp = 0; isp < KNsp; ++isp) { - if (std::isfinite(meanTru[isp][ieta])) { - histos.fill(HIST("MCGen/Prof_MeanpT_Cent_etabin_spbin"), cent, ieta, isp, meanTru[isp][ieta]); - histos.fill(HIST("MCGen/Prof_MeanpT_Mult_etabin_spbin"), multPV, ieta, isp, meanTru[isp][ieta]); + if (std::isfinite(covTru)) + histos.fill(HIST("MCGen/Prof_Cov2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covTru); + if (std::isfinite(covReco)) + histos.fill(HIST("MCReco/Prof_Cov2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covReco); + if (std::isfinite(covRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_Cov2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covRecoEffCor); + + if (std::isfinite(covFT0ATru)) + histos.fill(HIST("MCGen/Prof_CovFT0A2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covFT0ATru); + if (std::isfinite(covFT0AReco)) + histos.fill(HIST("MCReco/Prof_CovFT0A2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covFT0AReco); + if (std::isfinite(covFT0ARecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covFT0ARecoEffCor); + + if (std::isfinite(covFT0CTru)) + histos.fill(HIST("MCGen/Prof_CovFT0C2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covFT0CTru); + if (std::isfinite(covFT0CReco)) + histos.fill(HIST("MCReco/Prof_CovFT0C2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covFT0CReco); + if (std::isfinite(covFT0CRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covFT0CRecoEffCor); + + } else if (isp == kPiMinusIdx) { + if (std::isfinite(c2SubTru)) { + histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, c2SubTru); + histos.fill(HIST("MCGen/Prof_GapSum2D_PiMinus"), cent, gap, sum, c2SubTru); } - if (std::isfinite(c2Tru[isp][ieta])) { - histos.fill(HIST("MCGen/Prof_C2_Cent_etabin_spbin"), cent, ieta, isp, c2Tru[isp][ieta]); - histos.fill(HIST("MCGen/Prof_C2_Mult_etabin_spbin"), multPV, ieta, isp, c2Tru[isp][ieta]); + if (std::isfinite(c2SubReco)) { + histos.fill(HIST("MCReco/Prof_C2Sub2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, c2SubReco); + histos.fill(HIST("MCReco/Prof_GapSum2D_PiMinus"), cent, gap, sum, c2SubReco); } - if (std::isfinite(meanReco[isp][ieta])) { - histos.fill(HIST("MCReco/Prof_MeanpT_Cent_etabin_spbin"), cent, ieta, isp, meanReco[isp][ieta]); - histos.fill(HIST("MCReco/Prof_MeanpT_Mult_etabin_spbin"), multPV, ieta, isp, meanReco[isp][ieta]); + if (std::isfinite(c2SubRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_GapSum2D_PiMinus"), cent, gap, sum, c2SubRecoEffCor); } - if (std::isfinite(c2Reco[isp][ieta])) { - histos.fill(HIST("MCReco/Prof_C2_Cent_etabin_spbin"), cent, ieta, isp, c2Reco[isp][ieta]); - histos.fill(HIST("MCReco/Prof_C2_Mult_etabin_spbin"), multPV, ieta, isp, c2Reco[isp][ieta]); + + if (std::isfinite(covTru)) + histos.fill(HIST("MCGen/Prof_Cov2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, covTru); + if (std::isfinite(covReco)) + histos.fill(HIST("MCReco/Prof_Cov2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, covReco); + if (std::isfinite(covRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_Cov2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, covRecoEffCor); + + if (std::isfinite(covFT0ATru)) + histos.fill(HIST("MCGen/Prof_CovFT0A2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, covFT0ATru); + if (std::isfinite(covFT0AReco)) + histos.fill(HIST("MCReco/Prof_CovFT0A2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, covFT0AReco); + if (std::isfinite(covFT0ARecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, covFT0ARecoEffCor); + + if (std::isfinite(covFT0CTru)) + histos.fill(HIST("MCGen/Prof_CovFT0C2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, covFT0CTru); + if (std::isfinite(covFT0CReco)) + histos.fill(HIST("MCReco/Prof_CovFT0C2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, covFT0CReco); + if (std::isfinite(covFT0CRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, covFT0CRecoEffCor); + + } else if (isp == kPiPlusIdx) { + if (std::isfinite(c2SubTru)) { + histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, c2SubTru); + histos.fill(HIST("MCGen/Prof_GapSum2D_PiPlus"), cent, gap, sum, c2SubTru); } - if (std::isfinite(meanRecoEffCor[isp][ieta])) { - histos.fill(HIST("MCRecoEffCorr/Prof_MeanpT_Cent_etabin_spbin"), cent, ieta, isp, meanRecoEffCor[isp][ieta]); - histos.fill(HIST("MCRecoEffCorr/Prof_MeanpT_Mult_etabin_spbin"), multPV, ieta, isp, meanRecoEffCor[isp][ieta]); + if (std::isfinite(c2SubReco)) { + histos.fill(HIST("MCReco/Prof_C2Sub2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, c2SubReco); + histos.fill(HIST("MCReco/Prof_GapSum2D_PiPlus"), cent, gap, sum, c2SubReco); } - if (std::isfinite(c2RecoEffCor[isp][ieta])) { - histos.fill(HIST("MCRecoEffCorr/Prof_C2_Cent_etabin_spbin"), cent, ieta, isp, c2RecoEffCor[isp][ieta]); - histos.fill(HIST("MCRecoEffCorr/Prof_C2_Mult_etabin_spbin"), multPV, ieta, isp, c2RecoEffCor[isp][ieta]); + if (std::isfinite(c2SubRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_GapSum2D_PiPlus"), cent, gap, sum, c2SubRecoEffCor); } - } - } - p1kBarFt0A = amplFT0A - state.pmeanFT0AmultpvStep2->GetBinContent(state.pmeanFT0AmultpvStep2->GetXaxis()->FindBin(multPV)); - p1kBarFt0C = amplFT0C - state.pmeanFT0CmultpvStep2->GetBinContent(state.pmeanFT0CmultpvStep2->GetXaxis()->FindBin(multPV)); + if (std::isfinite(covTru)) + histos.fill(HIST("MCGen/Prof_Cov2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, covTru); + if (std::isfinite(covReco)) + histos.fill(HIST("MCReco/Prof_Cov2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, covReco); + if (std::isfinite(covRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_Cov2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, covRecoEffCor); + + if (std::isfinite(covFT0ATru)) + histos.fill(HIST("MCGen/Prof_CovFT0A2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, covFT0ATru); + if (std::isfinite(covFT0AReco)) + histos.fill(HIST("MCReco/Prof_CovFT0A2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, covFT0AReco); + if (std::isfinite(covFT0ARecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, covFT0ARecoEffCor); + + if (std::isfinite(covFT0CTru)) + histos.fill(HIST("MCGen/Prof_CovFT0C2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, covFT0CTru); + if (std::isfinite(covFT0CReco)) + histos.fill(HIST("MCReco/Prof_CovFT0C2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, covFT0CReco); + if (std::isfinite(covFT0CRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, covFT0CRecoEffCor); - for (int ietaA = 1; ietaA <= (KNEta - 1) / 2; ++ietaA) { - int ietaC = KNEta - ietaA; - for (int isp = 0; isp < KNsp; ++isp) { - float c2SubTru = p1kBarTru[isp][ietaA] * p1kBarTru[isp][ietaC]; - float c2SubReco = p1kBarReco[isp][ietaA] * p1kBarReco[isp][ietaC]; - float c2SubRecoEffCor = p1kBarRecoEffCor[isp][ietaA] * p1kBarRecoEffCor[isp][ietaC]; + } else if (isp == kPiAllIdx) { + if (std::isfinite(c2SubTru)) { + histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, c2SubTru); + histos.fill(HIST("MCGen/Prof_GapSum2D_PiAll"), cent, gap, sum, c2SubTru); + } + if (std::isfinite(c2SubReco)) { + histos.fill(HIST("MCReco/Prof_C2Sub2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, c2SubReco); + histos.fill(HIST("MCReco/Prof_GapSum2D_PiAll"), cent, gap, sum, c2SubReco); + } + if (std::isfinite(c2SubRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_GapSum2D_PiAll"), cent, gap, sum, c2SubRecoEffCor); + } - float covTru = p1kBarTruMult[isp][ietaA] * p1kBarTru[isp][ietaC]; - float covReco = p1kBarRecoMult[isp][ietaA] * p1kBarReco[isp][ietaC]; - float covRecoEffCor = p1kBarRecoEffCorMult[isp][ietaA] * p1kBarRecoEffCor[isp][ietaC]; + if (std::isfinite(covTru)) + histos.fill(HIST("MCGen/Prof_Cov2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, covTru); + if (std::isfinite(covReco)) + histos.fill(HIST("MCReco/Prof_Cov2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, covReco); + if (std::isfinite(covRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_Cov2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, covRecoEffCor); + + if (std::isfinite(covFT0ATru)) + histos.fill(HIST("MCGen/Prof_CovFT0A2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, covFT0ATru); + if (std::isfinite(covFT0AReco)) + histos.fill(HIST("MCReco/Prof_CovFT0A2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, covFT0AReco); + if (std::isfinite(covFT0ARecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, covFT0ARecoEffCor); + + if (std::isfinite(covFT0CTru)) + histos.fill(HIST("MCGen/Prof_CovFT0C2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, covFT0CTru); + if (std::isfinite(covFT0CReco)) + histos.fill(HIST("MCReco/Prof_CovFT0C2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, covFT0CReco); + if (std::isfinite(covFT0CRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, covFT0CRecoEffCor); - float covFT0ATru = p1kBarFt0A * p1kBarTru[isp][ietaC]; - float covFT0AReco = p1kBarFt0A * p1kBarReco[isp][ietaC]; - float covFT0ARecoEffCor = p1kBarFt0A * p1kBarRecoEffCor[isp][ietaC]; + } else if (isp == kKaMinusIdx) { + if (std::isfinite(c2SubTru)) { + histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, c2SubTru); + histos.fill(HIST("MCGen/Prof_GapSum2D_KaMinus"), cent, gap, sum, c2SubTru); + } + if (std::isfinite(c2SubReco)) { + histos.fill(HIST("MCReco/Prof_C2Sub2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, c2SubReco); + histos.fill(HIST("MCReco/Prof_GapSum2D_KaMinus"), cent, gap, sum, c2SubReco); + } + if (std::isfinite(c2SubRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_GapSum2D_KaMinus"), cent, gap, sum, c2SubRecoEffCor); + } - float covFT0CTru = p1kBarFt0C * p1kBarTru[isp][ietaA]; - float covFT0CReco = p1kBarFt0C * p1kBarReco[isp][ietaA]; - float covFT0CRecoEffCor = p1kBarFt0C * p1kBarRecoEffCor[isp][ietaA]; + if (std::isfinite(covTru)) + histos.fill(HIST("MCGen/Prof_Cov2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, covTru); + if (std::isfinite(covReco)) + histos.fill(HIST("MCReco/Prof_Cov2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, covReco); + if (std::isfinite(covRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_Cov2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, covRecoEffCor); + + if (std::isfinite(covFT0ATru)) + histos.fill(HIST("MCGen/Prof_CovFT0A2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, covFT0ATru); + if (std::isfinite(covFT0AReco)) + histos.fill(HIST("MCReco/Prof_CovFT0A2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, covFT0AReco); + if (std::isfinite(covFT0ARecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, covFT0ARecoEffCor); + + if (std::isfinite(covFT0CTru)) + histos.fill(HIST("MCGen/Prof_CovFT0C2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, covFT0CTru); + if (std::isfinite(covFT0CReco)) + histos.fill(HIST("MCReco/Prof_CovFT0C2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, covFT0CReco); + if (std::isfinite(covFT0CRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, covFT0CRecoEffCor); + } else if (isp == kKaPlusIdx) { if (std::isfinite(c2SubTru)) { - histos.fill(HIST("MCGen/Prof_C2Sub_Cent_etabin_spbin"), cent, ietaA, isp, c2SubTru); - histos.fill(HIST("MCGen/Prof_C2Sub_Mult_etabin_spbin"), multPV, ietaA, isp, c2SubTru); + histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, c2SubTru); + histos.fill(HIST("MCGen/Prof_GapSum2D_KaPlus"), cent, gap, sum, c2SubTru); } if (std::isfinite(c2SubReco)) { - histos.fill(HIST("MCReco/Prof_C2Sub_Cent_etabin_spbin"), cent, ietaA, isp, c2SubReco); - histos.fill(HIST("MCReco/Prof_C2Sub_Mult_etabin_spbin"), multPV, ietaA, isp, c2SubReco); + histos.fill(HIST("MCReco/Prof_C2Sub2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, c2SubReco); + histos.fill(HIST("MCReco/Prof_GapSum2D_KaPlus"), cent, gap, sum, c2SubReco); } if (std::isfinite(c2SubRecoEffCor)) { - histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub_Cent_etabin_spbin"), cent, ietaA, isp, c2SubRecoEffCor); - histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub_Mult_etabin_spbin"), multPV, ietaA, isp, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_GapSum2D_KaPlus"), cent, gap, sum, c2SubRecoEffCor); } - if (std::isfinite(covTru)) { - histos.fill(HIST("MCGen/Prof_Cov_Cent_etabin_spbin"), cent, ietaA, isp, covTru); - histos.fill(HIST("MCGen/Prof_Cov_Mult_etabin_spbin"), multPV, ietaA, isp, covTru); + + if (std::isfinite(covTru)) + histos.fill(HIST("MCGen/Prof_Cov2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, covTru); + if (std::isfinite(covReco)) + histos.fill(HIST("MCReco/Prof_Cov2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, covReco); + if (std::isfinite(covRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_Cov2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, covRecoEffCor); + + if (std::isfinite(covFT0ATru)) + histos.fill(HIST("MCGen/Prof_CovFT0A2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, covFT0ATru); + if (std::isfinite(covFT0AReco)) + histos.fill(HIST("MCReco/Prof_CovFT0A2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, covFT0AReco); + if (std::isfinite(covFT0ARecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, covFT0ARecoEffCor); + + if (std::isfinite(covFT0CTru)) + histos.fill(HIST("MCGen/Prof_CovFT0C2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, covFT0CTru); + if (std::isfinite(covFT0CReco)) + histos.fill(HIST("MCReco/Prof_CovFT0C2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, covFT0CReco); + if (std::isfinite(covFT0CRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, covFT0CRecoEffCor); + + } else if (isp == kKaAllIdx) { + if (std::isfinite(c2SubTru)) { + histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, c2SubTru); + histos.fill(HIST("MCGen/Prof_GapSum2D_KaAll"), cent, gap, sum, c2SubTru); } - if (std::isfinite(covReco)) { - histos.fill(HIST("MCReco/Prof_Cov_Cent_etabin_spbin"), cent, ietaA, isp, covReco); - histos.fill(HIST("MCReco/Prof_Cov_Mult_etabin_spbin"), multPV, ietaA, isp, covReco); + if (std::isfinite(c2SubReco)) { + histos.fill(HIST("MCReco/Prof_C2Sub2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, c2SubReco); + histos.fill(HIST("MCReco/Prof_GapSum2D_KaAll"), cent, gap, sum, c2SubReco); } - if (std::isfinite(covRecoEffCor)) { - histos.fill(HIST("MCRecoEffCorr/Prof_Cov_Cent_etabin_spbin"), cent, ietaA, isp, covRecoEffCor); - histos.fill(HIST("MCRecoEffCorr/Prof_Cov_Mult_etabin_spbin"), multPV, ietaA, isp, covRecoEffCor); + if (std::isfinite(c2SubRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_GapSum2D_KaAll"), cent, gap, sum, c2SubRecoEffCor); } - if (std::isfinite(covFT0ATru)) { - histos.fill(HIST("MCGen/Prof_CovFT0A_Cent_etabin_spbin"), cent, ietaA, isp, covFT0ATru); - histos.fill(HIST("MCGen/Prof_CovFT0A_Mult_etabin_spbin"), multPV, ietaA, isp, covFT0ATru); + if (std::isfinite(covTru)) + histos.fill(HIST("MCGen/Prof_Cov2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, covTru); + if (std::isfinite(covReco)) + histos.fill(HIST("MCReco/Prof_Cov2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, covReco); + if (std::isfinite(covRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_Cov2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, covRecoEffCor); + + if (std::isfinite(covFT0ATru)) + histos.fill(HIST("MCGen/Prof_CovFT0A2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, covFT0ATru); + if (std::isfinite(covFT0AReco)) + histos.fill(HIST("MCReco/Prof_CovFT0A2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, covFT0AReco); + if (std::isfinite(covFT0ARecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, covFT0ARecoEffCor); + + if (std::isfinite(covFT0CTru)) + histos.fill(HIST("MCGen/Prof_CovFT0C2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, covFT0CTru); + if (std::isfinite(covFT0CReco)) + histos.fill(HIST("MCReco/Prof_CovFT0C2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, covFT0CReco); + if (std::isfinite(covFT0CRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, covFT0CRecoEffCor); + + } else if (isp == kPrIdx) { + if (std::isfinite(c2SubTru)) { + histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, c2SubTru); + histos.fill(HIST("MCGen/Prof_GapSum2D_Pr"), cent, gap, sum, c2SubTru); } - if (std::isfinite(covFT0AReco)) { - histos.fill(HIST("MCReco/Prof_CovFT0A_Cent_etabin_spbin"), cent, ietaA, isp, covFT0AReco); - histos.fill(HIST("MCReco/Prof_CovFT0A_Mult_etabin_spbin"), multPV, ietaA, isp, covFT0AReco); + if (std::isfinite(c2SubReco)) { + histos.fill(HIST("MCReco/Prof_C2Sub2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, c2SubReco); + histos.fill(HIST("MCReco/Prof_GapSum2D_Pr"), cent, gap, sum, c2SubReco); } - if (std::isfinite(covFT0ARecoEffCor)) { - histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A_Cent_etabin_spbin"), cent, ietaA, isp, covFT0ARecoEffCor); - histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A_Mult_etabin_spbin"), multPV, ietaA, isp, covFT0ARecoEffCor); + if (std::isfinite(c2SubRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_GapSum2D_Pr"), cent, gap, sum, c2SubRecoEffCor); } - if (std::isfinite(covFT0CTru)) { - histos.fill(HIST("MCGen/Prof_CovFT0C_Cent_etabin_spbin"), cent, ietaA, isp, covFT0CTru); - histos.fill(HIST("MCGen/Prof_CovFT0C_Mult_etabin_spbin"), multPV, ietaA, isp, covFT0CTru); + if (std::isfinite(covTru)) + histos.fill(HIST("MCGen/Prof_Cov2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covTru); + if (std::isfinite(covReco)) + histos.fill(HIST("MCReco/Prof_Cov2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covReco); + if (std::isfinite(covRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_Cov2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covRecoEffCor); + + if (std::isfinite(covFT0ATru)) + histos.fill(HIST("MCGen/Prof_CovFT0A2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covFT0ATru); + if (std::isfinite(covFT0AReco)) + histos.fill(HIST("MCReco/Prof_CovFT0A2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covFT0AReco); + if (std::isfinite(covFT0ARecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covFT0ARecoEffCor); + + if (std::isfinite(covFT0CTru)) + histos.fill(HIST("MCGen/Prof_CovFT0C2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covFT0CTru); + if (std::isfinite(covFT0CReco)) + histos.fill(HIST("MCReco/Prof_CovFT0C2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covFT0CReco); + if (std::isfinite(covFT0CRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covFT0CRecoEffCor); + + } else if (isp == kAntiPrIdx) { + if (std::isfinite(c2SubTru)) { + histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, c2SubTru); + histos.fill(HIST("MCGen/Prof_GapSum2D_AntiPr"), cent, gap, sum, c2SubTru); } - if (std::isfinite(covFT0CReco)) { - histos.fill(HIST("MCReco/Prof_CovFT0C_Cent_etabin_spbin"), cent, ietaA, isp, covFT0CReco); - histos.fill(HIST("MCReco/Prof_CovFT0C_Mult_etabin_spbin"), multPV, ietaA, isp, covFT0CReco); + if (std::isfinite(c2SubReco)) { + histos.fill(HIST("MCReco/Prof_C2Sub2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, c2SubReco); + histos.fill(HIST("MCReco/Prof_GapSum2D_AntiPr"), cent, gap, sum, c2SubReco); } - if (std::isfinite(covFT0CRecoEffCor)) { - histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C_Cent_etabin_spbin"), cent, ietaA, isp, covFT0CRecoEffCor); - histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C_Mult_etabin_spbin"), multPV, ietaA, isp, covFT0CRecoEffCor); + if (std::isfinite(c2SubRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_GapSum2D_AntiPr"), cent, gap, sum, c2SubRecoEffCor); } - } - } - for (int ietaA = 1; ietaA < KNEta; ++ietaA) { - for (int ietaC = 1; ietaC < KNEta; ++ietaC) { - - float etaValA = (etaLw[ietaA] + etaUp[ietaA]) / 2.0f; - float etaValB = (etaLw[ietaC] + etaUp[ietaC]) / 2.0f; - float gap = etaValA - etaValB; - float sum = (etaValA + etaValB) / 2.0f; - for (int isp = 0; isp < KNsp; ++isp) { - - float c2SubTru = p1kBarTru[isp][ietaA] * p1kBarTru[isp][ietaC]; - float c2SubReco = p1kBarReco[isp][ietaA] * p1kBarReco[isp][ietaC]; - float c2SubRecoEffCor = p1kBarRecoEffCor[isp][ietaA] * p1kBarRecoEffCor[isp][ietaC]; - - float covTru = p1kBarTruMult[isp][ietaA] * p1kBarTru[isp][ietaC]; - float covReco = p1kBarRecoMult[isp][ietaA] * p1kBarReco[isp][ietaC]; - float covRecoEffCor = p1kBarRecoEffCorMult[isp][ietaA] * p1kBarRecoEffCor[isp][ietaC]; - - float covFT0ATru = p1kBarFt0A * p1kBarTru[isp][ietaC]; - float covFT0AReco = p1kBarFt0A * p1kBarReco[isp][ietaC]; - float covFT0ARecoEffCor = p1kBarFt0A * p1kBarRecoEffCor[isp][ietaC]; - - float covFT0CTru = p1kBarFt0C * p1kBarTru[isp][ietaA]; - float covFT0CReco = p1kBarFt0C * p1kBarReco[isp][ietaA]; - float covFT0CRecoEffCor = p1kBarFt0C * p1kBarRecoEffCor[isp][ietaA]; - - if (isp == kInclusiveIdx) { - if (std::isfinite(c2SubTru)) { - histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC"), cent, etaValA, etaValB, c2SubTru); - histos.fill(HIST("MCGen/Prof_GapSum2D"), cent, gap, sum, c2SubTru); - } - if (std::isfinite(c2SubReco)) { - histos.fill(HIST("MCReco/Prof_C2Sub2D_Cent_etaA_etaC"), cent, etaValA, etaValB, c2SubReco); - histos.fill(HIST("MCReco/Prof_GapSum2D"), cent, gap, sum, c2SubReco); - } - if (std::isfinite(c2SubRecoEffCor)) { - histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub2D_Cent_etaA_etaC"), cent, etaValA, etaValB, c2SubRecoEffCor); - histos.fill(HIST("MCRecoEffCorr/Prof_GapSum2D"), cent, gap, sum, c2SubRecoEffCor); - } - - if (std::isfinite(covTru)) - histos.fill(HIST("MCGen/Prof_Cov2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covTru); - if (std::isfinite(covReco)) - histos.fill(HIST("MCReco/Prof_Cov2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covReco); - if (std::isfinite(covRecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_Cov2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covRecoEffCor); - - if (std::isfinite(covFT0ATru)) - histos.fill(HIST("MCGen/Prof_CovFT0A2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covFT0ATru); - if (std::isfinite(covFT0AReco)) - histos.fill(HIST("MCReco/Prof_CovFT0A2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covFT0AReco); - if (std::isfinite(covFT0ARecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covFT0ARecoEffCor); - - if (std::isfinite(covFT0CTru)) - histos.fill(HIST("MCGen/Prof_CovFT0C2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covFT0CTru); - if (std::isfinite(covFT0CReco)) - histos.fill(HIST("MCReco/Prof_CovFT0C2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covFT0CReco); - if (std::isfinite(covFT0CRecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covFT0CRecoEffCor); - - } else if (isp == kPiMinusIdx) { - if (std::isfinite(c2SubTru)) { - histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, c2SubTru); - histos.fill(HIST("MCGen/Prof_GapSum2D_PiMinus"), cent, gap, sum, c2SubTru); - } - if (std::isfinite(c2SubReco)) { - histos.fill(HIST("MCReco/Prof_C2Sub2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, c2SubReco); - histos.fill(HIST("MCReco/Prof_GapSum2D_PiMinus"), cent, gap, sum, c2SubReco); - } - if (std::isfinite(c2SubRecoEffCor)) { - histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, c2SubRecoEffCor); - histos.fill(HIST("MCRecoEffCorr/Prof_GapSum2D_PiMinus"), cent, gap, sum, c2SubRecoEffCor); - } - - if (std::isfinite(covTru)) - histos.fill(HIST("MCGen/Prof_Cov2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, covTru); - if (std::isfinite(covReco)) - histos.fill(HIST("MCReco/Prof_Cov2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, covReco); - if (std::isfinite(covRecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_Cov2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, covRecoEffCor); - - if (std::isfinite(covFT0ATru)) - histos.fill(HIST("MCGen/Prof_CovFT0A2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, covFT0ATru); - if (std::isfinite(covFT0AReco)) - histos.fill(HIST("MCReco/Prof_CovFT0A2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, covFT0AReco); - if (std::isfinite(covFT0ARecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, covFT0ARecoEffCor); - - if (std::isfinite(covFT0CTru)) - histos.fill(HIST("MCGen/Prof_CovFT0C2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, covFT0CTru); - if (std::isfinite(covFT0CReco)) - histos.fill(HIST("MCReco/Prof_CovFT0C2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, covFT0CReco); - if (std::isfinite(covFT0CRecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, covFT0CRecoEffCor); - - } else if (isp == kPiPlusIdx) { - if (std::isfinite(c2SubTru)) { - histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, c2SubTru); - histos.fill(HIST("MCGen/Prof_GapSum2D_PiPlus"), cent, gap, sum, c2SubTru); - } - if (std::isfinite(c2SubReco)) { - histos.fill(HIST("MCReco/Prof_C2Sub2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, c2SubReco); - histos.fill(HIST("MCReco/Prof_GapSum2D_PiPlus"), cent, gap, sum, c2SubReco); - } - if (std::isfinite(c2SubRecoEffCor)) { - histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, c2SubRecoEffCor); - histos.fill(HIST("MCRecoEffCorr/Prof_GapSum2D_PiPlus"), cent, gap, sum, c2SubRecoEffCor); - } - - if (std::isfinite(covTru)) - histos.fill(HIST("MCGen/Prof_Cov2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, covTru); - if (std::isfinite(covReco)) - histos.fill(HIST("MCReco/Prof_Cov2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, covReco); - if (std::isfinite(covRecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_Cov2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, covRecoEffCor); - - if (std::isfinite(covFT0ATru)) - histos.fill(HIST("MCGen/Prof_CovFT0A2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, covFT0ATru); - if (std::isfinite(covFT0AReco)) - histos.fill(HIST("MCReco/Prof_CovFT0A2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, covFT0AReco); - if (std::isfinite(covFT0ARecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, covFT0ARecoEffCor); - - if (std::isfinite(covFT0CTru)) - histos.fill(HIST("MCGen/Prof_CovFT0C2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, covFT0CTru); - if (std::isfinite(covFT0CReco)) - histos.fill(HIST("MCReco/Prof_CovFT0C2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, covFT0CReco); - if (std::isfinite(covFT0CRecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, covFT0CRecoEffCor); - - } else if (isp == kPiAllIdx) { - if (std::isfinite(c2SubTru)) { - histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, c2SubTru); - histos.fill(HIST("MCGen/Prof_GapSum2D_PiAll"), cent, gap, sum, c2SubTru); - } - if (std::isfinite(c2SubReco)) { - histos.fill(HIST("MCReco/Prof_C2Sub2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, c2SubReco); - histos.fill(HIST("MCReco/Prof_GapSum2D_PiAll"), cent, gap, sum, c2SubReco); - } - if (std::isfinite(c2SubRecoEffCor)) { - histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, c2SubRecoEffCor); - histos.fill(HIST("MCRecoEffCorr/Prof_GapSum2D_PiAll"), cent, gap, sum, c2SubRecoEffCor); - } - - if (std::isfinite(covTru)) - histos.fill(HIST("MCGen/Prof_Cov2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, covTru); - if (std::isfinite(covReco)) - histos.fill(HIST("MCReco/Prof_Cov2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, covReco); - if (std::isfinite(covRecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_Cov2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, covRecoEffCor); - - if (std::isfinite(covFT0ATru)) - histos.fill(HIST("MCGen/Prof_CovFT0A2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, covFT0ATru); - if (std::isfinite(covFT0AReco)) - histos.fill(HIST("MCReco/Prof_CovFT0A2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, covFT0AReco); - if (std::isfinite(covFT0ARecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, covFT0ARecoEffCor); - - if (std::isfinite(covFT0CTru)) - histos.fill(HIST("MCGen/Prof_CovFT0C2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, covFT0CTru); - if (std::isfinite(covFT0CReco)) - histos.fill(HIST("MCReco/Prof_CovFT0C2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, covFT0CReco); - if (std::isfinite(covFT0CRecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, covFT0CRecoEffCor); - - } else if (isp == kKaMinusIdx) { - if (std::isfinite(c2SubTru)) { - histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, c2SubTru); - histos.fill(HIST("MCGen/Prof_GapSum2D_KaMinus"), cent, gap, sum, c2SubTru); - } - if (std::isfinite(c2SubReco)) { - histos.fill(HIST("MCReco/Prof_C2Sub2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, c2SubReco); - histos.fill(HIST("MCReco/Prof_GapSum2D_KaMinus"), cent, gap, sum, c2SubReco); - } - if (std::isfinite(c2SubRecoEffCor)) { - histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, c2SubRecoEffCor); - histos.fill(HIST("MCRecoEffCorr/Prof_GapSum2D_KaMinus"), cent, gap, sum, c2SubRecoEffCor); - } - - if (std::isfinite(covTru)) - histos.fill(HIST("MCGen/Prof_Cov2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, covTru); - if (std::isfinite(covReco)) - histos.fill(HIST("MCReco/Prof_Cov2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, covReco); - if (std::isfinite(covRecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_Cov2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, covRecoEffCor); - - if (std::isfinite(covFT0ATru)) - histos.fill(HIST("MCGen/Prof_CovFT0A2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, covFT0ATru); - if (std::isfinite(covFT0AReco)) - histos.fill(HIST("MCReco/Prof_CovFT0A2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, covFT0AReco); - if (std::isfinite(covFT0ARecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, covFT0ARecoEffCor); - - if (std::isfinite(covFT0CTru)) - histos.fill(HIST("MCGen/Prof_CovFT0C2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, covFT0CTru); - if (std::isfinite(covFT0CReco)) - histos.fill(HIST("MCReco/Prof_CovFT0C2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, covFT0CReco); - if (std::isfinite(covFT0CRecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, covFT0CRecoEffCor); - - } else if (isp == kKaPlusIdx) { - if (std::isfinite(c2SubTru)) { - histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, c2SubTru); - histos.fill(HIST("MCGen/Prof_GapSum2D_KaPlus"), cent, gap, sum, c2SubTru); - } - if (std::isfinite(c2SubReco)) { - histos.fill(HIST("MCReco/Prof_C2Sub2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, c2SubReco); - histos.fill(HIST("MCReco/Prof_GapSum2D_KaPlus"), cent, gap, sum, c2SubReco); - } - if (std::isfinite(c2SubRecoEffCor)) { - histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, c2SubRecoEffCor); - histos.fill(HIST("MCRecoEffCorr/Prof_GapSum2D_KaPlus"), cent, gap, sum, c2SubRecoEffCor); - } - - if (std::isfinite(covTru)) - histos.fill(HIST("MCGen/Prof_Cov2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, covTru); - if (std::isfinite(covReco)) - histos.fill(HIST("MCReco/Prof_Cov2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, covReco); - if (std::isfinite(covRecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_Cov2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, covRecoEffCor); - - if (std::isfinite(covFT0ATru)) - histos.fill(HIST("MCGen/Prof_CovFT0A2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, covFT0ATru); - if (std::isfinite(covFT0AReco)) - histos.fill(HIST("MCReco/Prof_CovFT0A2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, covFT0AReco); - if (std::isfinite(covFT0ARecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, covFT0ARecoEffCor); - - if (std::isfinite(covFT0CTru)) - histos.fill(HIST("MCGen/Prof_CovFT0C2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, covFT0CTru); - if (std::isfinite(covFT0CReco)) - histos.fill(HIST("MCReco/Prof_CovFT0C2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, covFT0CReco); - if (std::isfinite(covFT0CRecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, covFT0CRecoEffCor); - - } else if (isp == kKaAllIdx) { - if (std::isfinite(c2SubTru)) { - histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, c2SubTru); - histos.fill(HIST("MCGen/Prof_GapSum2D_KaAll"), cent, gap, sum, c2SubTru); - } - if (std::isfinite(c2SubReco)) { - histos.fill(HIST("MCReco/Prof_C2Sub2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, c2SubReco); - histos.fill(HIST("MCReco/Prof_GapSum2D_KaAll"), cent, gap, sum, c2SubReco); - } - if (std::isfinite(c2SubRecoEffCor)) { - histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, c2SubRecoEffCor); - histos.fill(HIST("MCRecoEffCorr/Prof_GapSum2D_KaAll"), cent, gap, sum, c2SubRecoEffCor); - } - - if (std::isfinite(covTru)) - histos.fill(HIST("MCGen/Prof_Cov2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, covTru); - if (std::isfinite(covReco)) - histos.fill(HIST("MCReco/Prof_Cov2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, covReco); - if (std::isfinite(covRecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_Cov2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, covRecoEffCor); - - if (std::isfinite(covFT0ATru)) - histos.fill(HIST("MCGen/Prof_CovFT0A2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, covFT0ATru); - if (std::isfinite(covFT0AReco)) - histos.fill(HIST("MCReco/Prof_CovFT0A2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, covFT0AReco); - if (std::isfinite(covFT0ARecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, covFT0ARecoEffCor); - - if (std::isfinite(covFT0CTru)) - histos.fill(HIST("MCGen/Prof_CovFT0C2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, covFT0CTru); - if (std::isfinite(covFT0CReco)) - histos.fill(HIST("MCReco/Prof_CovFT0C2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, covFT0CReco); - if (std::isfinite(covFT0CRecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, covFT0CRecoEffCor); - - } else if (isp == kPrIdx) { - if (std::isfinite(c2SubTru)) { - histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, c2SubTru); - histos.fill(HIST("MCGen/Prof_GapSum2D_Pr"), cent, gap, sum, c2SubTru); - } - if (std::isfinite(c2SubReco)) { - histos.fill(HIST("MCReco/Prof_C2Sub2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, c2SubReco); - histos.fill(HIST("MCReco/Prof_GapSum2D_Pr"), cent, gap, sum, c2SubReco); - } - if (std::isfinite(c2SubRecoEffCor)) { - histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, c2SubRecoEffCor); - histos.fill(HIST("MCRecoEffCorr/Prof_GapSum2D_Pr"), cent, gap, sum, c2SubRecoEffCor); - } - - if (std::isfinite(covTru)) - histos.fill(HIST("MCGen/Prof_Cov2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covTru); - if (std::isfinite(covReco)) - histos.fill(HIST("MCReco/Prof_Cov2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covReco); - if (std::isfinite(covRecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_Cov2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covRecoEffCor); - - if (std::isfinite(covFT0ATru)) - histos.fill(HIST("MCGen/Prof_CovFT0A2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covFT0ATru); - if (std::isfinite(covFT0AReco)) - histos.fill(HIST("MCReco/Prof_CovFT0A2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covFT0AReco); - if (std::isfinite(covFT0ARecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covFT0ARecoEffCor); - - if (std::isfinite(covFT0CTru)) - histos.fill(HIST("MCGen/Prof_CovFT0C2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covFT0CTru); - if (std::isfinite(covFT0CReco)) - histos.fill(HIST("MCReco/Prof_CovFT0C2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covFT0CReco); - if (std::isfinite(covFT0CRecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covFT0CRecoEffCor); - - } else if (isp == kAntiPrIdx) { - if (std::isfinite(c2SubTru)) { - histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, c2SubTru); - histos.fill(HIST("MCGen/Prof_GapSum2D_AntiPr"), cent, gap, sum, c2SubTru); - } - if (std::isfinite(c2SubReco)) { - histos.fill(HIST("MCReco/Prof_C2Sub2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, c2SubReco); - histos.fill(HIST("MCReco/Prof_GapSum2D_AntiPr"), cent, gap, sum, c2SubReco); - } - if (std::isfinite(c2SubRecoEffCor)) { - histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, c2SubRecoEffCor); - histos.fill(HIST("MCRecoEffCorr/Prof_GapSum2D_AntiPr"), cent, gap, sum, c2SubRecoEffCor); - } - - if (std::isfinite(covTru)) - histos.fill(HIST("MCGen/Prof_Cov2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, covTru); - if (std::isfinite(covReco)) - histos.fill(HIST("MCReco/Prof_Cov2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, covReco); - if (std::isfinite(covRecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_Cov2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, covRecoEffCor); - - if (std::isfinite(covFT0ATru)) - histos.fill(HIST("MCGen/Prof_CovFT0A2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, covFT0ATru); - if (std::isfinite(covFT0AReco)) - histos.fill(HIST("MCReco/Prof_CovFT0A2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, covFT0AReco); - if (std::isfinite(covFT0ARecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, covFT0ARecoEffCor); - - if (std::isfinite(covFT0CTru)) - histos.fill(HIST("MCGen/Prof_CovFT0C2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, covFT0CTru); - if (std::isfinite(covFT0CReco)) - histos.fill(HIST("MCReco/Prof_CovFT0C2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, covFT0CReco); - if (std::isfinite(covFT0CRecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, covFT0CRecoEffCor); - - } else if (isp == kPrAllIdx) { - if (std::isfinite(c2SubTru)) { - histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, c2SubTru); - histos.fill(HIST("MCGen/Prof_GapSum2D_PrAll"), cent, gap, sum, c2SubTru); - } - if (std::isfinite(c2SubReco)) { - histos.fill(HIST("MCReco/Prof_C2Sub2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, c2SubReco); - histos.fill(HIST("MCReco/Prof_GapSum2D_PrAll"), cent, gap, sum, c2SubReco); - } - if (std::isfinite(c2SubRecoEffCor)) { - histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, c2SubRecoEffCor); - histos.fill(HIST("MCRecoEffCorr/Prof_GapSum2D_PrAll"), cent, gap, sum, c2SubRecoEffCor); - } - - if (std::isfinite(covTru)) - histos.fill(HIST("MCGen/Prof_Cov2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, covTru); - if (std::isfinite(covReco)) - histos.fill(HIST("MCReco/Prof_Cov2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, covReco); - if (std::isfinite(covRecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_Cov2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, covRecoEffCor); - - if (std::isfinite(covFT0ATru)) - histos.fill(HIST("MCGen/Prof_CovFT0A2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, covFT0ATru); - if (std::isfinite(covFT0AReco)) - histos.fill(HIST("MCReco/Prof_CovFT0A2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, covFT0AReco); - if (std::isfinite(covFT0ARecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, covFT0ARecoEffCor); - - if (std::isfinite(covFT0CTru)) - histos.fill(HIST("MCGen/Prof_CovFT0C2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, covFT0CTru); - if (std::isfinite(covFT0CReco)) - histos.fill(HIST("MCReco/Prof_CovFT0C2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, covFT0CReco); - if (std::isfinite(covFT0CRecoEffCor)) - histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, covFT0CRecoEffCor); - } + if (std::isfinite(covTru)) + histos.fill(HIST("MCGen/Prof_Cov2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, covTru); + if (std::isfinite(covReco)) + histos.fill(HIST("MCReco/Prof_Cov2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, covReco); + if (std::isfinite(covRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_Cov2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, covRecoEffCor); + + if (std::isfinite(covFT0ATru)) + histos.fill(HIST("MCGen/Prof_CovFT0A2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, covFT0ATru); + if (std::isfinite(covFT0AReco)) + histos.fill(HIST("MCReco/Prof_CovFT0A2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, covFT0AReco); + if (std::isfinite(covFT0ARecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, covFT0ARecoEffCor); + + if (std::isfinite(covFT0CTru)) + histos.fill(HIST("MCGen/Prof_CovFT0C2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, covFT0CTru); + if (std::isfinite(covFT0CReco)) + histos.fill(HIST("MCReco/Prof_CovFT0C2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, covFT0CReco); + if (std::isfinite(covFT0CRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, covFT0CRecoEffCor); + + } else if (isp == kPrAllIdx) { + if (std::isfinite(c2SubTru)) { + histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, c2SubTru); + histos.fill(HIST("MCGen/Prof_GapSum2D_PrAll"), cent, gap, sum, c2SubTru); + } + if (std::isfinite(c2SubReco)) { + histos.fill(HIST("MCReco/Prof_C2Sub2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, c2SubReco); + histos.fill(HIST("MCReco/Prof_GapSum2D_PrAll"), cent, gap, sum, c2SubReco); + } + if (std::isfinite(c2SubRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_GapSum2D_PrAll"), cent, gap, sum, c2SubRecoEffCor); } + + if (std::isfinite(covTru)) + histos.fill(HIST("MCGen/Prof_Cov2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, covTru); + if (std::isfinite(covReco)) + histos.fill(HIST("MCReco/Prof_Cov2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, covReco); + if (std::isfinite(covRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_Cov2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, covRecoEffCor); + + if (std::isfinite(covFT0ATru)) + histos.fill(HIST("MCGen/Prof_CovFT0A2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, covFT0ATru); + if (std::isfinite(covFT0AReco)) + histos.fill(HIST("MCReco/Prof_CovFT0A2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, covFT0AReco); + if (std::isfinite(covFT0ARecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, covFT0ARecoEffCor); + + if (std::isfinite(covFT0CTru)) + histos.fill(HIST("MCGen/Prof_CovFT0C2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, covFT0CTru); + if (std::isfinite(covFT0CReco)) + histos.fill(HIST("MCReco/Prof_CovFT0C2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, covFT0CReco); + if (std::isfinite(covFT0CRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, covFT0CRecoEffCor); } } - LOGF(info, "FINISHED RUNNING processMCFluc"); + } + } } PROCESS_SWITCH(RadialFlowDecorr, processMCFluc, "process MC to calculate pt fluc", cfgRunMCFluc); @@ -2922,9 +2924,6 @@ struct RadialFlowDecorr { fillNSigmaBefCut(track, cent); } - histos.fill(HIST("hCentnTrk"), cent, ntrk); - histos.fill(HIST("hCentnTrkPV"), cent, coll.multNTracksPV()); - if (cfgZDC) { const auto& foundBC = coll.foundBC_as(); if (!foundBC.has_zdc()) { @@ -2971,6 +2970,10 @@ struct RadialFlowDecorr { float phi = track.phi(); auto sign = track.sign(); + histos.fill(HIST("hPt"), pt); + histos.fill(HIST("hEta"), eta); + histos.fill(HIST("hPhi"), phi); + if (eta > etaLw[0] && eta < etaUp[0]) ntrk++; fillNSigmaBefCut(track, cent); @@ -3042,9 +3045,6 @@ struct RadialFlowDecorr { } } - histos.fill(HIST("hCentnTrk"), cent, ntrk); - histos.fill(HIST("hCentnTrkPV"), cent, coll.multNTracksPV()); - if (cfgZDC) { const auto& foundBC = coll.foundBC_as(); if (!foundBC.has_zdc()) { @@ -3437,7 +3437,7 @@ struct RadialFlowDecorr { float etaValA = (etaLw[ietaA] + etaUp[ietaA]) / 2.0f; float etaValB = (etaLw[ietaC] + etaUp[ietaC]) / 2.0f; float gap = etaValA - etaValB; - float sum = (etaValA + etaValB) / 2.0f; + float sum = (etaValA + etaValB); for (int isp = 0; isp < KNsp; ++isp) { From c16728e5c0d3cf6952bf9f62216c151d8823c8c7 Mon Sep 17 00:00:00 2001 From: Zhenjun Xiong <108917659+zjxiongOvO@users.noreply.github.com> Date: Tue, 17 Mar 2026 19:36:51 +0100 Subject: [PATCH 306/347] [PWGDQ] add json function for event mixing (#15427) Co-authored-by: ypwangg Co-authored-by: ALICE Action Bot --- PWGDQ/Core/MixingLibrary.cxx | 43 ++++++++++++++++++++ PWGDQ/Core/MixingLibrary.h | 13 +++++- PWGDQ/Tasks/tableReader.cxx | 13 ++++-- PWGDQ/Tasks/tableReader_withAssoc.cxx | 13 ++++-- PWGDQ/Tasks/tableReader_withAssoc_direct.cxx | 13 ++++-- 5 files changed, 85 insertions(+), 10 deletions(-) diff --git a/PWGDQ/Core/MixingLibrary.cxx b/PWGDQ/Core/MixingLibrary.cxx index 37278b90971..90fd639464a 100644 --- a/PWGDQ/Core/MixingLibrary.cxx +++ b/PWGDQ/Core/MixingLibrary.cxx @@ -200,3 +200,46 @@ void o2::aod::dqmixing::SetUpMixing(MixingHandler* mh, const char* mixingVarible mh->AddMixingVariable(VarManager::kNTPCcontribLongA, fPileUpLimsHashing.size(), fPileUpLimsHashing); } } + +// Set up mixing hashing by json +void o2::aod::dqmixing::SetUpMixingFromJSON(MixingHandler* mh, const char* json) +{ + rapidjson::Document document; + + rapidjson::ParseResult ok = document.Parse(json); + if (!ok) { + LOG(fatal) << "JSON parse error"; + return; + } + + for (auto it = document.MemberBegin(); it != document.MemberEnd(); ++it) { + std::string nameStr = it->name.GetString(); + const auto& obj = it->value; + + LOG(info) << "Configuring mixing variable: " << nameStr; + + if (!obj.HasMember("var") || !obj.HasMember("LimsHashing")) { + LOG(fatal) << "Missing 'var' or 'LimsHashing' in " << nameStr; + continue; + } + + // read var + std::string varStr = obj["var"].GetString(); + + // read limits + const auto& lims = obj["LimsHashing"]; + std::vector limits; + limits.reserve(lims.Size()); + for (auto& v : lims.GetArray()) { + limits.push_back(v.GetFloat()); + } + + if (VarManager::fgVarNamesMap.find(varStr) == VarManager::fgVarNamesMap.end()) { + LOG(fatal) << "Bad variable (" << varStr << ") specified for this mixing setting"; + return; + } + + // set up mixing variable + mh->AddMixingVariable(VarManager::fgVarNamesMap[varStr], limits.size(), limits); + } +} diff --git a/PWGDQ/Core/MixingLibrary.h b/PWGDQ/Core/MixingLibrary.h index db7f92583df..c6de5b9ecd3 100644 --- a/PWGDQ/Core/MixingLibrary.h +++ b/PWGDQ/Core/MixingLibrary.h @@ -11,16 +11,27 @@ // // Contact: iarsene@cern.ch, i.c.arsene@fys.uio.no // -#include + +#ifndef PWGDQ_CORE_MIXINGLIBRARY_H_ +#define PWGDQ_CORE_MIXINGLIBRARY_H_ + #include "PWGDQ/Core/MixingHandler.h" #include "PWGDQ/Core/VarManager.h" +#include + +#include "rapidjson/document.h" + namespace o2::aod { namespace dqmixing { void SetUpMixing(MixingHandler* mh, const char* mixingVarible); +void SetUpMixingFromJSON(MixingHandler* mh, const char* json); } // namespace dqmixing } // namespace o2::aod void o2::aod::dqmixing::SetUpMixing(MixingHandler* mh, const char* mixingVarible); +void o2::aod::dqmixing::SetUpMixingFromJSON(MixingHandler* mh, const char* json); + +#endif // PWGDQ_CORE_MIXINGLIBRARY_H_ diff --git a/PWGDQ/Tasks/tableReader.cxx b/PWGDQ/Tasks/tableReader.cxx index a4126dc5f74..fdb1c4c0d6f 100644 --- a/PWGDQ/Tasks/tableReader.cxx +++ b/PWGDQ/Tasks/tableReader.cxx @@ -163,6 +163,7 @@ struct AnalysisEventSelection { OutputObj fOutputList{"output"}; // TODO: Provide the mixing variables and binning directly via configurables (e.g. vectors of float) Configurable fConfigMixingVariables{"cfgMixingVars", "", "Mixing configs separated by a comma, default no mixing"}; + Configurable fConfigMixingVariablesJson{"cfgMixingVarsJSON", "", "Mixing configs in JSON format"}; Configurable fConfigEventCuts{"cfgEventCuts", "eventStandard", "Event selection"}; Configurable fConfigQA{"cfgQA", false, "If true, fill QA histograms"}; Configurable fConfigRunZorro{"cfgRunZorro", false, "Enable event selection with zorro [WARNING: under debug, do not enable!]"}; @@ -200,12 +201,18 @@ struct AnalysisEventSelection { } TString mixVarsString = fConfigMixingVariables.value; + TString mixVarsJsonString = fConfigMixingVariablesJson.value; std::unique_ptr objArray(mixVarsString.Tokenize(",")); - if (objArray->GetEntries() > 0) { + if (objArray->GetEntries() > 0 || mixVarsJsonString != "") { fMixHandler = new MixingHandler("mixingHandler", "mixing handler"); fMixHandler->Init(); - for (int iVar = 0; iVar < objArray->GetEntries(); ++iVar) { - dqmixing::SetUpMixing(fMixHandler, objArray->At(iVar)->GetName()); + if (objArray->GetEntries() > 0) { + for (int iVar = 0; iVar < objArray->GetEntries(); ++iVar) { + dqmixing::SetUpMixing(fMixHandler, objArray->At(iVar)->GetName()); + } + } + if (mixVarsJsonString != "") { + dqmixing::SetUpMixingFromJSON(fMixHandler, mixVarsJsonString.Data()); } } diff --git a/PWGDQ/Tasks/tableReader_withAssoc.cxx b/PWGDQ/Tasks/tableReader_withAssoc.cxx index abaca5864de..3a8dbe52709 100644 --- a/PWGDQ/Tasks/tableReader_withAssoc.cxx +++ b/PWGDQ/Tasks/tableReader_withAssoc.cxx @@ -277,6 +277,7 @@ struct AnalysisEventSelection { // TODO: Provide the mixing variables and binning directly via configurables (e.g. vectors of float) Configurable fConfigMixingVariables{"cfgMixingVars", "", "Mixing configs separated by a comma, default no mixing"}; + Configurable fConfigMixingVariablesJson{"cfgMixingVarsJSON", "", "Mixing configs in JSON format"}; Configurable fConfigEventCuts{"cfgEventCuts", "eventStandard", "Event selection"}; Configurable fConfigEventCutsJSON{"cfgEventCutsJSON", "", "Additional event cuts specified in JSON format"}; Configurable fConfigAddEventHistogram{"cfgAddEventHistogram", "", "Comma separated list of histograms"}; @@ -357,12 +358,18 @@ struct AnalysisEventSelection { } TString mixVarsString = fConfigMixingVariables.value; + TString mixVarsJsonString = fConfigMixingVariablesJson.value; std::unique_ptr objArray(mixVarsString.Tokenize(",")); - if (objArray->GetEntries() > 0) { + if (objArray->GetEntries() > 0 || mixVarsJsonString != "") { fMixHandler = new MixingHandler("mixingHandler", "mixing handler"); fMixHandler->Init(); - for (int iVar = 0; iVar < objArray->GetEntries(); ++iVar) { - dqmixing::SetUpMixing(fMixHandler, objArray->At(iVar)->GetName()); + if (objArray->GetEntries() > 0) { + for (int iVar = 0; iVar < objArray->GetEntries(); ++iVar) { + dqmixing::SetUpMixing(fMixHandler, objArray->At(iVar)->GetName()); + } + } + if (mixVarsJsonString != "") { + dqmixing::SetUpMixingFromJSON(fMixHandler, mixVarsJsonString.Data()); } } diff --git a/PWGDQ/Tasks/tableReader_withAssoc_direct.cxx b/PWGDQ/Tasks/tableReader_withAssoc_direct.cxx index 49e0d596d50..1cdf8f65336 100644 --- a/PWGDQ/Tasks/tableReader_withAssoc_direct.cxx +++ b/PWGDQ/Tasks/tableReader_withAssoc_direct.cxx @@ -250,6 +250,7 @@ struct AnalysisEventSelection { OutputObj fOutputList{"output"}; OutputObj fStatsList{"Statistics"}; Configurable fConfigMixingVariables{"cfgMixingVars", "", "Mixing configs separated by a comma, default no mixing"}; + Configurable fConfigMixingVariablesJson{"cfgMixingVarsJSON", "", "Mixing configs in JSON format"}; Configurable fConfigEventCuts{"cfgEventCuts", "eventStandard", "Event selection"}; Configurable fConfigEventCutsJSON{"cfgEventCutsJSON", "", "Additional event cuts specified in JSON format"}; Configurable fConfigQA{"cfgQA", false, "If true, fill QA histograms"}; @@ -368,12 +369,18 @@ struct AnalysisEventSelection { fStatsList->AddAt(histZorroSel, kStatsZorroSel); TString mixVarsString = fConfigMixingVariables.value; + TString mixVarsJsonString = fConfigMixingVariablesJson.value; std::unique_ptr objArray(mixVarsString.Tokenize(",")); - if (objArray->GetEntries() > 0) { + if (objArray->GetEntries() > 0 || mixVarsJsonString != "") { fMixHandler = new MixingHandler("mixingHandler", "mixing handler"); fMixHandler->Init(); - for (int iVar = 0; iVar < objArray->GetEntries(); ++iVar) { - dqmixing::SetUpMixing(fMixHandler, objArray->At(iVar)->GetName()); + if (objArray->GetEntries() > 0) { + for (int iVar = 0; iVar < objArray->GetEntries(); ++iVar) { + dqmixing::SetUpMixing(fMixHandler, objArray->At(iVar)->GetName()); + } + } + if (mixVarsJsonString != "") { + dqmixing::SetUpMixingFromJSON(fMixHandler, mixVarsJsonString.Data()); } } From f73e1f81e426058c53b04ed4982bda1b8c156bc0 Mon Sep 17 00:00:00 2001 From: Marvin Hemmer <53471402+mhemmer-cern@users.noreply.github.com> Date: Tue, 17 Mar 2026 20:39:34 +0100 Subject: [PATCH 307/347] [PWGEM] PM: Increase histogram type from float to double for... (#15423) --- PWGEM/PhotonMeson/Utils/EventHistograms.h | 2 +- PWGEM/PhotonMeson/Utils/NMHistograms.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/PWGEM/PhotonMeson/Utils/EventHistograms.h b/PWGEM/PhotonMeson/Utils/EventHistograms.h index 5f2b6d91e6f..e45409dda9e 100644 --- a/PWGEM/PhotonMeson/Utils/EventHistograms.h +++ b/PWGEM/PhotonMeson/Utils/EventHistograms.h @@ -66,7 +66,7 @@ inline void addEventHistograms(o2::framework::HistogramRegistry* fRegistry) 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110}, "centrality FT0C (%)"}; - fRegistry->add("Event/before/hZvtx", "vertex z; Z_{vtx} (cm)", o2::framework::kTH1F, {{100, -50, +50}}, false); + fRegistry->add("Event/before/hZvtx", "vertex z; Z_{vtx} (cm)", o2::framework::kTH1D, {{100, -50, +50}}, false); fRegistry->add("Event/before/hMultNTracksPV", "hMultNTracksPV; N_{track} to PV", o2::framework::kTH1F, {{6001, -0.5, 6000.5}}, false); fRegistry->add("Event/before/hMultNTracksPVeta1", "hMultNTracksPVeta1; N_{track} to PV", o2::framework::kTH1F, {{6001, -0.5, 6000.5}}, false); fRegistry->add("Event/before/hMultFT0", "hMultFT0;mult. FT0A;mult. FT0C", o2::framework::kTH2F, {{200, 0, 200000}, {60, 0, 60000}}, false); diff --git a/PWGEM/PhotonMeson/Utils/NMHistograms.h b/PWGEM/PhotonMeson/Utils/NMHistograms.h index 7911957bb03..03c3dcc3f89 100644 --- a/PWGEM/PhotonMeson/Utils/NMHistograms.h +++ b/PWGEM/PhotonMeson/Utils/NMHistograms.h @@ -60,8 +60,8 @@ inline void addNMHistograms(o2::framework::HistogramRegistry* fRegistry, bool is fRegistry->add("Pair/Eta/hs_FromSameGamma", "Two clusters from same gamma that is a eta daughter (conversion)", o2::framework::kTHnSparseD, {axis_mass, axis_pt}, true); const o2::framework::AxisSpec axis_rapidity{{0.0, +0.8, +0.9}, "rapidity |y|"}; - fRegistry->add("Generated/Pi0/hPt", "pT;p_{T} (GeV/c)", o2::framework::kTH1F, {axis_pt}, true); - fRegistry->add("Generated/Pi0/hPtY", "Generated info", o2::framework::kTH2F, {axis_pt, axis_rapidity}, true); + fRegistry->add("Generated/Pi0/hPt", "pT;p_{T} (GeV/c)", o2::framework::kTH1D, {axis_pt}, true); + fRegistry->add("Generated/Pi0/hPtY", "Generated info", o2::framework::kTH2D, {axis_pt, axis_rapidity}, true); fRegistry->addClone("Generated/Pi0/", "Generated/Eta/"); fRegistry->get(HIST("Generated/Pi0/hPt"))->SetXTitle("p_{T} (GeV/c)"); From aaca6290bffb3d8af00712c5f376f5bd6105919c Mon Sep 17 00:00:00 2001 From: Stefanie Mrozinski <63045530+Steffimro@users.noreply.github.com> Date: Tue, 17 Mar 2026 21:48:03 +0100 Subject: [PATCH 308/347] [PWGEM] Rewrite Header file + Add QA histograms (#15424) --- PWGEM/PhotonMeson/Core/PhotonHBT.h | 695 ----------------- PWGEM/PhotonMeson/Tasks/CMakeLists.txt | 10 +- PWGEM/PhotonMeson/Tasks/PhotonHBTPCMPCM.cxx | 27 - PWGEM/PhotonMeson/Tasks/photonhbt.cxx | 784 ++++++++++++++++++++ 4 files changed, 789 insertions(+), 727 deletions(-) delete mode 100644 PWGEM/PhotonMeson/Core/PhotonHBT.h delete mode 100644 PWGEM/PhotonMeson/Tasks/PhotonHBTPCMPCM.cxx create mode 100644 PWGEM/PhotonMeson/Tasks/photonhbt.cxx diff --git a/PWGEM/PhotonMeson/Core/PhotonHBT.h b/PWGEM/PhotonMeson/Core/PhotonHBT.h deleted file mode 100644 index fcd9d9d9ce7..00000000000 --- a/PWGEM/PhotonMeson/Core/PhotonHBT.h +++ /dev/null @@ -1,695 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -/// \file PhotonHBT.h -/// \brief This code loops over v0 photons and makes pairs for photon HBT analysis. -/// \author Daiki Sekihata, daiki.sekihata@cern.ch - -#ifndef PWGEM_PHOTONMESON_CORE_PHOTONHBT_H_ -#define PWGEM_PHOTONMESON_CORE_PHOTONHBT_H_ - -#include "PWGEM/Dilepton/Utils/EMTrack.h" -#include "PWGEM/Dilepton/Utils/EventMixingHandler.h" -#include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" -#include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" -#include "PWGEM/PhotonMeson/DataModel/EventTables.h" -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGEM/PhotonMeson/Utils/EventHistograms.h" -// -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/EventSelection.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include // IWYU pragma: keep -#include -#include // IWYU pragma: keep -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace o2::aod::pwgem::photon::core::photonhbt -{ -enum class ggHBTPairType : int { - kPCMPCM = 0, -}; -} // namespace o2::aod::pwgem::photon::core::photonhbt - -using namespace o2; -using namespace o2::aod; -using namespace o2::framework; -using namespace o2::framework::expressions; -using namespace o2::soa; -using namespace o2::aod::pwgem::dilepton::utils; -using namespace o2::aod::pwgem::photon::core::photonhbt; - -using MyCollisions = soa::Join; -using MyCollision = MyCollisions::iterator; - -using MyV0Photons = soa::Join; -using MyV0Photon = MyV0Photons::iterator; - -template -struct PhotonHBT { - // Configurables - - // Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; - // Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; - // Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; - // Configurable skipGRPOquery{"skipGRPOquery", true, "skip grpo query"}; - // Configurable d_bz_input{"d_bz_input", -999, "bz field in kG, -999 is automatic"}; - - Configurable cfgDo3D{"cfgDo3D", false, "enable 3D analysis"}; - Configurable cfgEP2Estimator_for_Mix{"cfgEP2Estimator_for_Mix", 3, "FT0M:0, FT0A:1, FT0C:2, BTot:3, BPos:4, BNeg:5"}; - Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; - Configurable cfgOccupancyEstimator{"cfgOccupancyEstimator", 0, "FT0C:0, Track:1"}; - Configurable cfgCentMin{"cfgCentMin", -1, "min. centrality"}; - Configurable cfgCentMax{"cfgCentMax", 999, "max. centrality"}; - Configurable maxY{"maxY", 0.8, "maximum rapidity for reconstructed particles"}; - Configurable cfgDoMix{"cfgDoMix", true, "flag for event mixing"}; - Configurable ndepth{"ndepth", 100, "depth for event mixing"}; - Configurable ndiff_bc_mix{"ndiff_bc_mix", 594, "difference in global BC required in mixed events"}; - ConfigurableAxis ConfVtxBins{"ConfVtxBins", {VARIABLE_WIDTH, -10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}, "Mixing bins - z-vertex"}; - ConfigurableAxis ConfCentBins{"ConfCentBins", {VARIABLE_WIDTH, 0.0f, 5.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f, 100.f, 999.f}, "Mixing bins - centrality"}; - ConfigurableAxis ConfEPBins{"ConfEPBins", {16, -o2::constants::math::PIHalf, +o2::constants::math::PIHalf}, "Mixing bins - event plane angle"}; - ConfigurableAxis ConfOccupancyBins{"ConfOccupancyBins", {VARIABLE_WIDTH, -1, 1e+10}, "Mixing bins - occupancy"}; - Configurable cfgUseLCMS{"cfgUseLCMS", true, "measure relative momentum in LCMS for 1D"}; // always in LCMS for 3D - - ConfigurableAxis ConfQBins{"ConfQBins", {60, 0, +0.3f}, "q bins for output histograms"}; - ConfigurableAxis ConfKtBins{"ConfKtBins", {VARIABLE_WIDTH, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0}, "kT bins for output histograms"}; - - EMPhotonEventCut fEMEventCut; - struct : ConfigurableGroup { - std::string prefix = "eventcut_group"; - Configurable cfgZvtxMin{"cfgZvtxMin", -10.f, "min. Zvtx"}; - Configurable cfgZvtxMax{"cfgZvtxMax", +10.f, "max. Zvtx"}; - Configurable cfgRequireSel8{"cfgRequireSel8", true, "require sel8 in event cut"}; - Configurable cfgRequireFT0AND{"cfgRequireFT0AND", true, "require FT0AND in event cut"}; - Configurable cfgRequireNoTFB{"cfgRequireNoTFB", true, "require No time frame border in event cut"}; - Configurable cfgRequireNoITSROFB{"cfgRequireNoITSROFB", true, "require no ITS readout frame border in event cut"}; - Configurable cfgRequireNoSameBunchPileup{"cfgRequireNoSameBunchPileup", false, "require no same bunch pileup in event cut"}; - Configurable cfgRequireVertexITSTPC{"cfgRequireVertexITSTPC", false, "require Vertex ITSTPC in event cut"}; // ITS-TPC matched track contributes PV. - Configurable cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; - Configurable cfgTrackOccupancyMin{"cfgTrackOccupancyMin", -2, "min. track occupancy"}; - Configurable cfgTrackOccupancyMax{"cfgTrackOccupancyMax", 1000000000, "max. track occupancy"}; - Configurable cfgFT0COccupancyMin{"cfgFT0COccupancyMin", -2, "min. FT0C occupancy"}; - Configurable cfgFT0COccupancyMax{"cfgFT0COccupancyMax", 1000000000, "max. FT0C occupancy"}; - Configurable cfgRequireNoCollInTimeRangeStandard{"cfgRequireNoCollInTimeRangeStandard", false, "require no collision in time range standard"}; - Configurable cfgRequireNoCollInTimeRangeStrict{"cfgRequireNoCollInTimeRangeStrict", false, "require no collision in time range strict"}; - Configurable cfgRequireNoCollInITSROFStandard{"cfgRequireNoCollInITSROFStandard", false, "require no collision in time range standard"}; - Configurable cfgRequireNoCollInITSROFStrict{"cfgRequireNoCollInITSROFStrict", false, "require no collision in time range strict"}; - Configurable cfgRequireNoHighMultCollInPrevRof{"cfgRequireNoHighMultCollInPrevRof", false, "require no HM collision in previous ITS ROF"}; - Configurable cfgRequireGoodITSLayer3{"cfgRequireGoodITSLayer3", false, "number of inactive chips on ITS layer 3 are below threshold "}; - Configurable cfgRequireGoodITSLayer0123{"cfgRequireGoodITSLayer0123", false, "number of inactive chips on ITS layers 0-3 are below threshold "}; - Configurable cfgRequireGoodITSLayersAll{"cfgRequireGoodITSLayersAll", false, "number of inactive chips on all ITS layers are below threshold "}; - } eventcuts; - - V0PhotonCut fV0PhotonCut; - struct : ConfigurableGroup { - std::string prefix = "pcmcut_group"; - Configurable cfg_require_v0_with_itstpc{"cfg_require_v0_with_itstpc", false, "flag to select V0s with ITS-TPC matched tracks"}; - Configurable cfg_require_v0_with_itsonly{"cfg_require_v0_with_itsonly", false, "flag to select V0s with ITSonly tracks"}; - Configurable cfg_require_v0_with_tpconly{"cfg_require_v0_with_tpconly", false, "flag to select V0s with TPConly tracks"}; - Configurable cfg_min_pt_v0{"cfg_min_pt_v0", 0.1, "min pT for v0 photons at PV"}; - Configurable cfg_max_eta_v0{"cfg_max_eta_v0", 0.8, "max eta for v0 photons at PV"}; - Configurable cfg_min_v0radius{"cfg_min_v0radius", 16.0, "min v0 radius"}; - Configurable cfg_max_v0radius{"cfg_max_v0radius", 90.0, "max v0 radius"}; - Configurable cfg_max_alpha_ap{"cfg_max_alpha_ap", 0.95, "max alpha for AP cut"}; - Configurable cfg_max_qt_ap{"cfg_max_qt_ap", 0.01, "max qT for AP cut"}; - Configurable cfg_min_cospa{"cfg_min_cospa", 0.997, "min V0 CosPA"}; - Configurable cfg_max_pca{"cfg_max_pca", 3.0, "max distance btween 2 legs"}; - Configurable cfg_max_chi2kf{"cfg_max_chi2kf", 1e+10, "max chi2/ndf with KF"}; - Configurable cfg_reject_v0_on_itsib{"cfg_reject_v0_on_itsib", true, "flag to reject V0s on ITSib"}; - - Configurable cfg_disable_itsonly_track{"cfg_disable_itsonly_track", false, "flag to disable ITSonly tracks"}; - Configurable cfg_disable_tpconly_track{"cfg_disable_tpconly_track", false, "flag to disable TPConly tracks"}; - Configurable cfg_min_ncluster_tpc{"cfg_min_ncluster_tpc", 0, "min ncluster tpc"}; - Configurable cfg_min_ncrossedrows{"cfg_min_ncrossedrows", 40, "min ncrossed rows"}; - Configurable cfg_max_frac_shared_clusters_tpc{"cfg_max_frac_shared_clusters_tpc", 999.f, "max fraction of shared clusters in TPC"}; - Configurable cfg_max_chi2tpc{"cfg_max_chi2tpc", 4.0, "max chi2/NclsTPC"}; - Configurable cfg_max_chi2its{"cfg_max_chi2its", 36.0, "max chi2/NclsITS"}; - Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -3.0, "min. TPC n sigma for electron"}; - Configurable cfg_max_TPCNsigmaEl{"cfg_max_TPCNsigmaEl", +3.0, "max. TPC n sigma for electron"}; - } pcmcuts; - - struct : ConfigurableGroup { - std::string prefix = "ggpaircut_group"; - Configurable cfgMinDR_CosOA{"cfgMinDR_CosOA", -1, "min. dr/cosOA for kPCMPCM"}; - } ggpaircuts; - - ~PhotonHBT() - { - delete emh1; - emh1 = 0x0; - delete emh2; - emh2 = 0x0; - - map_mixed_eventId_to_globalBC.clear(); - - used_photonIds_per_col.clear(); - used_photonIds_per_col.shrink_to_fit(); - } - - HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; - // static constexpr std::string_view event_types[2] = {"before", "after"}; - static constexpr std::string_view event_pair_types[2] = {"same/", "mix/"}; - - std::mt19937 engine; - std::uniform_int_distribution dist01; - - // o2::ccdb::CcdbApi ccdbApi; - // Service ccdb; - int mRunNumber; - // float d_bz; - - std::vector zvtx_bin_edges; - std::vector cent_bin_edges; - std::vector ep_bin_edges; - std::vector occ_bin_edges; - - void init(InitContext& /*context*/) - { - mRunNumber = 0; - // d_bz = 0; - - // ccdb->setURL(ccdburl); - // ccdb->setCaching(true); - // ccdb->setLocalObjectValidityChecking(); - // ccdb->setFatalWhenNull(false); - - if (ConfVtxBins.value[0] == VARIABLE_WIDTH) { - zvtx_bin_edges = std::vector(ConfVtxBins.value.begin(), ConfVtxBins.value.end()); - zvtx_bin_edges.erase(zvtx_bin_edges.begin()); - for (const auto& edge : zvtx_bin_edges) { - LOGF(info, "VARIABLE_WIDTH: zvtx_bin_edges = %f", edge); - } - } else { - int nbins = static_cast(ConfVtxBins.value[0]); - float xmin = static_cast(ConfVtxBins.value[1]); - float xmax = static_cast(ConfVtxBins.value[2]); - zvtx_bin_edges.resize(nbins + 1); - for (int i = 0; i < nbins + 1; i++) { - zvtx_bin_edges[i] = (xmax - xmin) / (nbins)*i + xmin; - LOGF(info, "FIXED_WIDTH: zvtx_bin_edges[%d] = %f", i, zvtx_bin_edges[i]); - } - } - - if (ConfCentBins.value[0] == VARIABLE_WIDTH) { - cent_bin_edges = std::vector(ConfCentBins.value.begin(), ConfCentBins.value.end()); - cent_bin_edges.erase(cent_bin_edges.begin()); - for (const auto& edge : cent_bin_edges) { - LOGF(info, "VARIABLE_WIDTH: cent_bin_edges = %f", edge); - } - } else { - int nbins = static_cast(ConfCentBins.value[0]); - float xmin = static_cast(ConfCentBins.value[1]); - float xmax = static_cast(ConfCentBins.value[2]); - cent_bin_edges.resize(nbins + 1); - for (int i = 0; i < nbins + 1; i++) { - cent_bin_edges[i] = (xmax - xmin) / (nbins)*i + xmin; - LOGF(info, "FIXED_WIDTH: cent_bin_edges[%d] = %f", i, cent_bin_edges[i]); - } - } - - if (ConfEPBins.value[0] == VARIABLE_WIDTH) { - ep_bin_edges = std::vector(ConfEPBins.value.begin(), ConfEPBins.value.end()); - ep_bin_edges.erase(ep_bin_edges.begin()); - for (const auto& edge : ep_bin_edges) { - LOGF(info, "VARIABLE_WIDTH: ep_bin_edges = %f", edge); - } - } else { - int nbins = static_cast(ConfEPBins.value[0]); - float xmin = static_cast(ConfEPBins.value[1]); - float xmax = static_cast(ConfEPBins.value[2]); - ep_bin_edges.resize(nbins + 1); - for (int i = 0; i < nbins + 1; i++) { - ep_bin_edges[i] = (xmax - xmin) / (nbins)*i + xmin; - LOGF(info, "FIXED_WIDTH: ep_bin_edges[%d] = %f", i, ep_bin_edges[i]); - } - } - - LOGF(info, "cfgOccupancyEstimator = %d", cfgOccupancyEstimator.value); - if (ConfOccupancyBins.value[0] == VARIABLE_WIDTH) { - occ_bin_edges = std::vector(ConfOccupancyBins.value.begin(), ConfOccupancyBins.value.end()); - occ_bin_edges.erase(occ_bin_edges.begin()); - for (const auto& edge : occ_bin_edges) { - LOGF(info, "VARIABLE_WIDTH: occ_bin_edges = %f", edge); - } - } else { - int nbins = static_cast(ConfOccupancyBins.value[0]); - float xmin = static_cast(ConfOccupancyBins.value[1]); - float xmax = static_cast(ConfOccupancyBins.value[2]); - occ_bin_edges.resize(nbins + 1); - for (int i = 0; i < nbins + 1; i++) { - occ_bin_edges[i] = (xmax - xmin) / (nbins)*i + xmin; - LOGF(info, "FIXED_WIDTH: occ_bin_edges[%d] = %f", i, occ_bin_edges[i]); - } - } - - emh1 = new MyEMH(ndepth); - emh2 = new MyEMH(ndepth); - - o2::aod::pwgem::photonmeson::utils::eventhistogram::addEventHistograms(&fRegistry); - DefineEMEventCut(); - DefinePCMCut(); - - addhistograms(); - - std::random_device seed_gen; - engine = std::mt19937(seed_gen()); - dist01 = std::uniform_int_distribution(0, 1); - - fRegistry.add("Pair/mix/hDiffBC", "diff. global BC in mixed event;|BC_{current} - BC_{mixed}|", kTH1D, {{10001, -0.5, 10000.5}}, true); - } - - template - void initCCDB(TCollision const& collision) - { - if (mRunNumber == collision.runNumber()) { - return; - } - - // // In case override, don't proceed, please - no CCDB access required - // if (d_bz_input > -990) { - // d_bz = d_bz_input; - // o2::parameters::GRPMagField grpmag; - // if (std::fabs(d_bz) > 1e-5) { - // grpmag.setL3Current(30000.f / (d_bz / 5.0f)); - // } - // mRunNumber = collision.runNumber(); - // return; - // } - - // auto run3grp_timestamp = collision.timestamp(); - // o2::parameters::GRPObject* grpo = 0x0; - // o2::parameters::GRPMagField* grpmag = 0x0; - // if (!skipGRPOquery) - // grpo = ccdb->getForTimeStamp(grpPath, run3grp_timestamp); - // if (grpo) { - // // Fetch magnetic field from ccdb for current collision - // d_bz = grpo->getNominalL3Field(); - // LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; - // } else { - // grpmag = ccdb->getForTimeStamp(grpmagPath, run3grp_timestamp); - // if (!grpmag) { - // LOG(fatal) << "Got nullptr from CCDB for path " << grpmagPath << " of object GRPMagField and " << grpPath << " of object GRPObject for timestamp " << run3grp_timestamp; - // } - // // Fetch magnetic field from ccdb for current collision - // d_bz = std::lround(5.f * grpmag->getL3Current() / 30000.f); - // LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; - // } - mRunNumber = collision.runNumber(); - } - - void addhistograms() - { - // o2::aod::pwgem::dilepton::utils::eventhistogram::addEventHistograms<-1>(&fRegistry); - static constexpr std::string_view qvec_det_names[6] = {"FT0M", "FT0A", "FT0C", "BTot", "BPos", "BNeg"}; - fRegistry.add("Event/before/hEP2_CentFT0C_forMix", Form("2nd harmonics event plane for mix;centrality FT0C (%%);#Psi_{2}^{%s} (rad.)", qvec_det_names[cfgEP2Estimator_for_Mix].data()), kTH2F, {{110, 0, 110}, {180, -o2::constants::math::PIHalf, +o2::constants::math::PIHalf}}, false); - fRegistry.add("Event/after/hEP2_CentFT0C_forMix", Form("2nd harmonics event plane for mix;centrality FT0C (%%);#Psi_{2}^{%s} (rad.)", qvec_det_names[cfgEP2Estimator_for_Mix].data()), kTH2F, {{110, 0, 110}, {180, -o2::constants::math::PIHalf, +o2::constants::math::PIHalf}}, false); - - // pair info - const AxisSpec axis_kt{ConfKtBins, "k_{T} (GeV/c)"}; - const AxisSpec axis_qinv{ConfQBins, "q_{inv} (GeV/c)"}; - const AxisSpec axis_qabs_lcms{ConfQBins, "|#bf{q}|^{LCMS} (GeV/c)"}; - const AxisSpec axis_qout{ConfQBins, "q_{out} (GeV/c)"}; // qout does not change between LAB and LCMS frame - const AxisSpec axis_qside{ConfQBins, "q_{side} (GeV/c)"}; // qside does not change between LAB and LCMS frame - const AxisSpec axis_qlong{ConfQBins, "q_{long} (GeV/c)"}; - - if (cfgDo3D) { // 3D - fRegistry.add("Pair/same/hs_3d", "diphoton correlation 3D LCMS", kTHnSparseD, {axis_qout, axis_qside, axis_qlong, axis_kt}, true); - } else { // 1D - if (cfgUseLCMS) { - fRegistry.add("Pair/same/hs_1d", "diphoton correlation 1D LCMS", kTHnSparseD, {axis_qabs_lcms, axis_kt}, true); - } else { - fRegistry.add("Pair/same/hs_1d", "diphoton correlation 1D", kTHnSparseD, {axis_qinv, axis_kt}, true); - } - } - - if constexpr (pairtype == ggHBTPairType::kPCMPCM) { - fRegistry.add("Pair/same/hDeltaRCosOA", "distance between 2 conversion points;#Deltar/cos(#theta_{op}/2) (cm)", kTH1D, {{100, 0, 100}}, true); // dr/cosOA of conversion points - } - - fRegistry.addClone("Pair/same/", "Pair/mix/"); - } - - void DefineEMEventCut() - { - fEMEventCut = EMPhotonEventCut("fEMEventCut", "fEMEventCut"); - fEMEventCut.SetRequireSel8(eventcuts.cfgRequireSel8); - fEMEventCut.SetRequireFT0AND(eventcuts.cfgRequireFT0AND); - fEMEventCut.SetZvtxRange(eventcuts.cfgZvtxMin, eventcuts.cfgZvtxMax); - fEMEventCut.SetRequireNoTFB(eventcuts.cfgRequireNoTFB); - fEMEventCut.SetRequireNoITSROFB(eventcuts.cfgRequireNoITSROFB); - fEMEventCut.SetRequireNoSameBunchPileup(eventcuts.cfgRequireNoSameBunchPileup); - fEMEventCut.SetRequireVertexITSTPC(eventcuts.cfgRequireVertexITSTPC); - fEMEventCut.SetRequireGoodZvtxFT0vsPV(eventcuts.cfgRequireGoodZvtxFT0vsPV); - fEMEventCut.SetRequireNoCollInTimeRangeStandard(eventcuts.cfgRequireNoCollInTimeRangeStandard); - fEMEventCut.SetRequireNoCollInTimeRangeStrict(eventcuts.cfgRequireNoCollInTimeRangeStrict); - fEMEventCut.SetRequireNoCollInITSROFStandard(eventcuts.cfgRequireNoCollInITSROFStandard); - fEMEventCut.SetRequireNoCollInITSROFStrict(eventcuts.cfgRequireNoCollInITSROFStrict); - fEMEventCut.SetRequireNoHighMultCollInPrevRof(eventcuts.cfgRequireNoHighMultCollInPrevRof); - fEMEventCut.SetRequireGoodITSLayer3(eventcuts.cfgRequireGoodITSLayer3); - fEMEventCut.SetRequireGoodITSLayer0123(eventcuts.cfgRequireGoodITSLayer0123); - fEMEventCut.SetRequireGoodITSLayersAll(eventcuts.cfgRequireGoodITSLayersAll); - } - - void DefinePCMCut() - { - fV0PhotonCut = V0PhotonCut("fV0PhotonCut", "fV0PhotonCut"); - - // for v0 - fV0PhotonCut.SetV0PtRange(pcmcuts.cfg_min_pt_v0, 1e10f); - fV0PhotonCut.SetV0EtaRange(-pcmcuts.cfg_max_eta_v0, +pcmcuts.cfg_max_eta_v0); - fV0PhotonCut.SetMinCosPA(pcmcuts.cfg_min_cospa); - fV0PhotonCut.SetMaxPCA(pcmcuts.cfg_max_pca); - fV0PhotonCut.SetMaxChi2KF(pcmcuts.cfg_max_chi2kf); - fV0PhotonCut.SetRxyRange(pcmcuts.cfg_min_v0radius, pcmcuts.cfg_max_v0radius); - fV0PhotonCut.SetAPRange(pcmcuts.cfg_max_alpha_ap, pcmcuts.cfg_max_qt_ap); - fV0PhotonCut.RejectITSib(pcmcuts.cfg_reject_v0_on_itsib); - - // for track - fV0PhotonCut.SetMinNClustersTPC(pcmcuts.cfg_min_ncluster_tpc); - fV0PhotonCut.SetMinNCrossedRowsTPC(pcmcuts.cfg_min_ncrossedrows); - fV0PhotonCut.SetMinNCrossedRowsOverFindableClustersTPC(0.8); - fV0PhotonCut.SetMaxFracSharedClustersTPC(pcmcuts.cfg_max_frac_shared_clusters_tpc); - fV0PhotonCut.SetChi2PerClusterTPC(0.0, pcmcuts.cfg_max_chi2tpc); - fV0PhotonCut.SetTPCNsigmaElRange(pcmcuts.cfg_min_TPCNsigmaEl, pcmcuts.cfg_max_TPCNsigmaEl); - fV0PhotonCut.SetChi2PerClusterITS(-1e+10, pcmcuts.cfg_max_chi2its); - fV0PhotonCut.SetDisableITSonly(pcmcuts.cfg_disable_itsonly_track); - fV0PhotonCut.SetDisableTPConly(pcmcuts.cfg_disable_tpconly_track); - fV0PhotonCut.SetNClustersITS(0, 7); - fV0PhotonCut.SetMeanClusterSizeITSob(0.0, 16.0); - fV0PhotonCut.SetRequireITSTPC(pcmcuts.cfg_require_v0_with_itstpc); - fV0PhotonCut.SetRequireITSonly(pcmcuts.cfg_require_v0_with_itsonly); - fV0PhotonCut.SetRequireTPConly(pcmcuts.cfg_require_v0_with_tpconly); - } - - template - void fillPairHistogram(TCollision const&, const ROOT::Math::PtEtaPhiMVector v1, const ROOT::Math::PtEtaPhiMVector v2, const float weight = 1.f) - { - float rndm = std::pow(-1, dist01(engine) % 2); // +1 or -1 to randomize order between 1 and 2. - // Lab. frame - ROOT::Math::PtEtaPhiMVector q12 = (v1 - v2) * rndm; - ROOT::Math::PtEtaPhiMVector k12 = 0.5 * (v1 + v2); - float qinv = -q12.M(); // for identical particles -> qinv = 2 x kstar - float kt = k12.Pt(); - - ROOT::Math::XYZVector uv_out(k12.Px() / k12.Pt(), k12.Py() / k12.Pt(), 0); // unit vector for out. i.e. parallel to kt - ROOT::Math::XYZVector uv_long(0, 0, 1); // unit vector for long, beam axis - ROOT::Math::XYZVector uv_side = uv_out.Cross(uv_long); // unit vector for side - - ROOT::Math::PxPyPzEVector v1_cartesian(v1); - ROOT::Math::PxPyPzEVector v2_cartesian(v2); - ROOT::Math::PxPyPzEVector q12_cartesian = (v1_cartesian - v2_cartesian) * rndm; - float beta = (v1 + v2).Beta(); - // float beta_x = beta * std::cos((v1 + v2).Phi()) * std::sin((v1 + v2).Theta()); - // float beta_y = beta * std::sin((v1 + v2).Phi()) * std::sin((v1 + v2).Theta()); - float beta_z = beta * std::cos((v1 + v2).Theta()); - - // longitudinally co-moving system (LCMS) - ROOT::Math::Boost bst_z(0, 0, -beta_z); // Boost supports only PxPyPzEVector - ROOT::Math::PxPyPzEVector q12_lcms = bst_z(q12_cartesian); - ROOT::Math::XYZVector q_3d_lcms = q12_lcms.Vect(); // 3D q vector in LCMS - float qout_lcms = q_3d_lcms.Dot(uv_out); - float qside_lcms = q_3d_lcms.Dot(uv_side); - float qlong_lcms = q_3d_lcms.Dot(uv_long); - float qabs_lcms = q_3d_lcms.R(); - - // float qabs_lcms_tmp = std::sqrt(std::pow(qout_lcms, 2) + std::pow(qside_lcms, 2) + std::pow(qlong_lcms, 2)); - // LOGF(info, "qabs_lcms = %f, qabs_lcms_tmp = %f", qabs_lcms, qabs_lcms_tmp); - - // // pair rest frame (PRF) - // ROOT::Math::Boost boostPRF = ROOT::Math::Boost(-beta_x, -beta_y, -beta_z); - // ROOT::Math::PxPyPzEVector v1_prf = boostPRF(v1_cartesian); - // ROOT::Math::PxPyPzEVector v2_prf = boostPRF(v2_cartesian); - // ROOT::Math::PxPyPzEVector rel_k = (v1_prf - v2_prf) * rndm; - // float kstar = 0.5 * rel_k.P(); - // // LOGF(info, "qabs_lcms = %f, qinv = %f, kstar = %f", qabs_lcms, qinv, kstar); - - // ROOT::Math::PxPyPzEVector v1_lcms_cartesian = bst_z(v1_cartesian); - // ROOT::Math::PxPyPzEVector v2_lcms_cartesian = bst_z(v2_cartesian); - // ROOT::Math::PxPyPzEVector q12_lcms_cartesian = bst_z(q12_cartesian); - // LOGF(info, "q12.Pz() = %f, q12_cartesian.Pz() = %f", q12.Pz(), q12_cartesian.Pz()); - // LOGF(info, "v1.Pz() = %f, v2.Pz() = %f", v1.Pz(), v2.Pz()); - // LOGF(info, "v1_lcms_cartesian.Pz() = %f, v2_lcms_cartesian.Pz() = %f", v1_lcms_cartesian.Pz(), v2_lcms_cartesian.Pz()); - // LOGF(info, "q12_lcms_cartesian.Pz() = %f", q12_lcms_cartesian.Pz()); - // LOGF(info, "q_3d_lcms.Dot(uv_out) = %f, q_3d_lcms.Dot(uv_side) = %f, q_3d.Dot(uv_out) = %f, q_3d.Dot(uv_side) = %f", q_3d_lcms.Dot(uv_out), q_3d_lcms.Dot(uv_side), q_3d.Dot(uv_out), q_3d.Dot(uv_side)); - // LOGF(info, "q12_lcms.Pz() = %f, q_3d_lcms.Dot(uv_long) = %f", q12_lcms.Pz(), q_3d_lcms.Dot(uv_long)); - // ROOT::Math::PxPyPzEVector q12_lcms_tmp = bst_z(v1_cartesian) - bst_z(v2_cartesian); - // LOGF(info, "q12_lcms.Px() = %f, q12_lcms.Py() = %f, q12_lcms.Pz() = %f, q12_lcms_tmp.Px() = %f, q12_lcms_tmp.Py() = %f, q12_lcms_tmp.Pz() = %f", q12_lcms.Px(), q12_lcms.Py(), q12_lcms.Pz(), q12_lcms_tmp.Px(), q12_lcms_tmp.Py(), q12_lcms_tmp.Pz()); - // float qabs_lcms_tmp = q12_lcms.P(); - // LOGF(info, "qabs_lcms = %f, qabs_lcms_tmp = %f", qabs_lcms, qabs_lcms_tmp); - - if (cfgDo3D) { - fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("hs_3d"), std::fabs(qout_lcms), std::fabs(qside_lcms), std::fabs(qlong_lcms), kt, weight); // qosl can be [-inf, +inf] and CF is symmetric for pos and neg qosl. To reduce stat. unc. absolute value is taken here. - } else { - if (cfgUseLCMS) { - fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("hs_1d"), qabs_lcms, kt, weight); - } else { - fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("hs_1d"), qinv, kt, weight); - } - } - } - - template - void runPairing(TCollisions const& collisions, TPhotons1 const& photons1, TPhotons2 const& photons2, TSubInfos1 const&, TSubInfos2 const&, TPreslice1 const& perCollision1, TPreslice2 const& perCollision2, TCut1 const& cut1, TCut2 const& cut2) - { - for (const auto& collision : collisions) { - initCCDB(collision); - int ndiphoton = 0; - const float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; - if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { - continue; - } - const float eventplanes_2_for_mix[6] = {collision.ep2ft0m(), collision.ep2ft0a(), collision.ep2ft0c(), collision.ep2btot(), collision.ep2bpos(), collision.ep2bneg()}; - float ep2 = eventplanes_2_for_mix[cfgEP2Estimator_for_Mix]; - fRegistry.fill(HIST("Event/before/hEP2_CentFT0C_forMix"), collision.centFT0C(), ep2); - - o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<0>(&fRegistry, collision, 1.f); - if (!fEMEventCut.IsSelected(collision)) { - continue; - } - o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<1>(&fRegistry, collision, 1.f); - fRegistry.fill(HIST("Event/after/hEP2_CentFT0C_forMix"), collision.centFT0C(), ep2); - - int zbin = lower_bound(zvtx_bin_edges.begin(), zvtx_bin_edges.end(), collision.posZ()) - zvtx_bin_edges.begin() - 1; - if (zbin < 0) { - zbin = 0; - } else if (static_cast(zvtx_bin_edges.size()) - 2 < zbin) { - zbin = static_cast(zvtx_bin_edges.size()) - 2; - } - - float centrality = centralities[cfgCentEstimator]; - int centbin = lower_bound(cent_bin_edges.begin(), cent_bin_edges.end(), centrality) - cent_bin_edges.begin() - 1; - if (centbin < 0) { - centbin = 0; - } else if (static_cast(cent_bin_edges.size()) - 2 < centbin) { - centbin = static_cast(cent_bin_edges.size()) - 2; - } - - int epbin = lower_bound(ep_bin_edges.begin(), ep_bin_edges.end(), ep2) - ep_bin_edges.begin() - 1; - if (epbin < 0) { - epbin = 0; - } else if (static_cast(ep_bin_edges.size()) - 2 < epbin) { - epbin = static_cast(ep_bin_edges.size()) - 2; - } - - int occbin = -1; - if (cfgOccupancyEstimator == 0) { - occbin = lower_bound(occ_bin_edges.begin(), occ_bin_edges.end(), collision.ft0cOccupancyInTimeRange()) - occ_bin_edges.begin() - 1; - } else if (cfgOccupancyEstimator == 1) { - occbin = lower_bound(occ_bin_edges.begin(), occ_bin_edges.end(), collision.trackOccupancyInTimeRange()) - occ_bin_edges.begin() - 1; - } else { - occbin = lower_bound(occ_bin_edges.begin(), occ_bin_edges.end(), collision.ft0cOccupancyInTimeRange()) - occ_bin_edges.begin() - 1; - } - - if (occbin < 0) { - occbin = 0; - } else if (static_cast(occ_bin_edges.size()) - 2 < occbin) { - occbin = static_cast(occ_bin_edges.size()) - 2; - } - - // LOGF(info, "collision.globalIndex() = %d, collision.posZ() = %f, centrality = %f, ep2 = %f, collision.trackOccupancyInTimeRange() = %d, zbin = %d, centbin = %d, epbin = %d, occbin = %d", collision.globalIndex(), collision.posZ(), centrality, ep2, collision.trackOccupancyInTimeRange(), zbin, centbin, epbin, occbin); - - auto key_bin = std::make_tuple(zbin, centbin, epbin, occbin); - auto key_df_collision = std::make_pair(ndf, collision.globalIndex()); - - if constexpr (pairtype == ggHBTPairType::kPCMPCM) { - auto photons1_coll = photons1.sliceBy(perCollision1, collision.globalIndex()); - auto photons2_coll = photons2.sliceBy(perCollision2, collision.globalIndex()); - for (const auto& [g1, g2] : combinations(CombinationsStrictlyUpperIndexPolicy(photons1_coll, photons2_coll))) { - if (!cut1.template IsSelected(g1) || !cut2.template IsSelected(g2)) { - continue; - } - - auto pos1 = g1.template posTrack_as(); - auto ele1 = g1.template negTrack_as(); - auto pos2 = g2.template posTrack_as(); - auto ele2 = g2.template negTrack_as(); - if (pos1.trackId() == pos2.trackId() || ele1.trackId() == ele2.trackId()) { // never happens. only for protection. - continue; - } - - ROOT::Math::PtEtaPhiMVector v1(g1.pt(), g1.eta(), g1.phi(), 0.); - ROOT::Math::PtEtaPhiMVector v2(g2.pt(), g2.eta(), g2.phi(), 0.); - - float dr = std::sqrt(std::pow(g1.vx() - g2.vx(), 2) + std::pow(g1.vy() - g2.vy(), 2) + std::pow(g1.vz() - g2.vz(), 2)); - ROOT::Math::XYZVector cp1(g1.vx(), g1.vy(), g1.vz()); - ROOT::Math::XYZVector cp2(g2.vx(), g2.vy(), g2.vz()); - float opa = std::acos(cp1.Dot(cp2) / (std::sqrt(cp1.Mag2()) * std::sqrt(cp2.Mag2()))); // opening angle between 2 conversion points - o2::math_utils::bringTo02Pi(opa); - if (opa > o2::constants::math::PI) { - opa -= o2::constants::math::PI; - } - float cosOA = std::cos(opa / 2.f); - if (dr / cosOA < ggpaircuts.cfgMinDR_CosOA) { - continue; - } - fRegistry.fill(HIST("Pair/same/hDeltaRCosOA"), dr / cosOA); - - fillPairHistogram<0>(collision, v1, v2, 1.f); - ndiphoton++; - - if (std::find(used_photonIds_per_col.begin(), used_photonIds_per_col.end(), g1.globalIndex()) == used_photonIds_per_col.end()) { - EMPair g1tmp = EMPair(g1.pt(), g1.eta(), g1.phi(), 0); - g1tmp.setConversionPointXYZ(g1.vx(), g1.vy(), g1.vz()); - emh1->AddTrackToEventPool(key_df_collision, g1tmp); - used_photonIds_per_col.emplace_back(g1.globalIndex()); - } - if (std::find(used_photonIds_per_col.begin(), used_photonIds_per_col.end(), g2.globalIndex()) == used_photonIds_per_col.end()) { - EMPair g2tmp = EMPair(g2.pt(), g2.eta(), g2.phi(), 0); - g2tmp.setConversionPointXYZ(g2.vx(), g2.vy(), g2.vz()); - emh1->AddTrackToEventPool(key_df_collision, g2tmp); - used_photonIds_per_col.emplace_back(g2.globalIndex()); - } - } // end of pairing loop - } - - used_photonIds_per_col.clear(); - used_photonIds_per_col.shrink_to_fit(); - - // event mixing - if (!cfgDoMix || !(ndiphoton > 0)) { - continue; - } - - // make a vector of selected photons in this collision. - auto selected_photons1_in_this_event = emh1->GetTracksPerCollision(key_df_collision); - auto selected_photons2_in_this_event = emh2->GetTracksPerCollision(key_df_collision); - - auto collisionIds1_in_mixing_pool = emh1->GetCollisionIdsFromEventPool(key_bin); - auto collisionIds2_in_mixing_pool = emh2->GetCollisionIdsFromEventPool(key_bin); - - if constexpr (pairtype == ggHBTPairType::kPCMPCM) { - for (const auto& mix_dfId_collisionId : collisionIds1_in_mixing_pool) { - int mix_dfId = mix_dfId_collisionId.first; - int64_t mix_collisionId = mix_dfId_collisionId.second; - - if (collision.globalIndex() == mix_collisionId && ndf == mix_dfId) { // this never happens. only protection. - continue; - } - - auto globalBC_mix = map_mixed_eventId_to_globalBC[mix_dfId_collisionId]; - uint64_t diffBC = std::max(collision.globalBC(), globalBC_mix) - std::min(collision.globalBC(), globalBC_mix); - fRegistry.fill(HIST("Pair/mix/hDiffBC"), diffBC); - if (diffBC < ndiff_bc_mix) { - continue; - } - - auto photons1_from_event_pool = emh1->GetTracksPerCollision(mix_dfId_collisionId); - // LOGF(info, "Do event mixing: current event (%d, %d), ngamma = %d | event pool (%d, %d), ngamma = %d", ndf, collision.globalIndex(), selected_photons1_in_this_event.size(), mix_dfId, mix_collisionId, photons1_from_event_pool.size()); - - for (const auto& g1 : selected_photons1_in_this_event) { - for (const auto& g2 : photons1_from_event_pool) { - ROOT::Math::PtEtaPhiMVector v1(g1.pt(), g1.eta(), g1.phi(), 0.); - ROOT::Math::PtEtaPhiMVector v2(g2.pt(), g2.eta(), g2.phi(), 0.); - - float dr = std::sqrt(std::pow(g1.vx() - g2.vx(), 2) + std::pow(g1.vy() - g2.vy(), 2) + std::pow(g1.vz() - g2.vz(), 2)); - ROOT::Math::XYZVector cp1(g1.vx(), g1.vy(), g1.vz()); - ROOT::Math::XYZVector cp2(g2.vx(), g2.vy(), g2.vz()); - float opa = std::acos(cp1.Dot(cp2) / (std::sqrt(cp1.Mag2()) * std::sqrt(cp2.Mag2()))); // opening angle between 2 conversion points - o2::math_utils::bringTo02Pi(opa); - if (opa > o2::constants::math::PI) { - opa -= o2::constants::math::PI; - } - float cosOA = std::cos(opa / 2.f); - if (dr / cosOA < ggpaircuts.cfgMinDR_CosOA) { - continue; - } - fRegistry.fill(HIST("Pair/mix/hDeltaRCosOA"), dr / cosOA); - - fillPairHistogram<1>(collision, v1, v2, 1.f); - } - } - } // end of loop over mixed event pool - } - - if (ndiphoton > 0) { - emh1->AddCollisionIdAtLast(key_bin, key_df_collision); - emh2->AddCollisionIdAtLast(key_bin, key_df_collision); - map_mixed_eventId_to_globalBC[key_df_collision] = collision.globalBC(); - } - } // end of collision loop - } - - using MyEMH = o2::aod::pwgem::dilepton::utils::EventMixingHandler, std::pair, EMPair>; - MyEMH* emh1 = nullptr; - MyEMH* emh2 = nullptr; - std::vector used_photonIds_per_col; // - std::map, uint64_t> map_mixed_eventId_to_globalBC; - - SliceCache cache; - Preslice perCollision_pcm = aod::v0photonkf::pmeventId; - - Filter collisionFilter_centrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); - Filter collisionFilter_occupancy_track = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; - Filter collisionFilter_occupancy_ft0c = eventcuts.cfgFT0COccupancyMin <= o2::aod::evsel::ft0cOccupancyInTimeRange && o2::aod::evsel::ft0cOccupancyInTimeRange < eventcuts.cfgFT0COccupancyMax; - using FilteredMyCollisions = soa::Filtered; - - int ndf = 0; - void processAnalysis(FilteredMyCollisions const& collisions, Types const&... args) - { - if constexpr (pairtype == ggHBTPairType::kPCMPCM) { - auto v0photons = std::get<0>(std::tie(args...)); - auto v0legs = std::get<1>(std::tie(args...)); - runPairing(collisions, v0photons, v0photons, v0legs, v0legs, perCollision_pcm, perCollision_pcm, fV0PhotonCut, fV0PhotonCut); - } - ndf++; - } - PROCESS_SWITCH(PhotonHBT, processAnalysis, "pairing for analysis", false); - - void processDummy(MyCollisions const&) {} - PROCESS_SWITCH(PhotonHBT, processDummy, "Dummy function", true); -}; - -#endif // PWGEM_PHOTONMESON_CORE_PHOTONHBT_H_ diff --git a/PWGEM/PhotonMeson/Tasks/CMakeLists.txt b/PWGEM/PhotonMeson/Tasks/CMakeLists.txt index e0ce318628f..fe155e91fe1 100644 --- a/PWGEM/PhotonMeson/Tasks/CMakeLists.txt +++ b/PWGEM/PhotonMeson/Tasks/CMakeLists.txt @@ -131,11 +131,6 @@ o2physics_add_dpl_workflow(pi0eta-to-gammagamma-mc-emcemc PUBLIC_LINK_LIBRARIES O2::Framework O2::EMCALBase O2::EMCALCalib O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(photon-hbt-pcmpcm - SOURCES PhotonHBTPCMPCM.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore - COMPONENT_NAME Analysis) - o2physics_add_dpl_workflow(tag-and-probe SOURCES TagAndProbe.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::EMCALBase O2::EMCALCalib O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore O2Physics::MLCore @@ -200,3 +195,8 @@ o2physics_add_dpl_workflow(photon-reso-task SOURCES photonResoTask.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::EMCALBase O2::EMCALCalib O2Physics::PWGEMPhotonMesonCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(photonhbt + SOURCES photonhbt.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore + COMPONENT_NAME Analysis) diff --git a/PWGEM/PhotonMeson/Tasks/PhotonHBTPCMPCM.cxx b/PWGEM/PhotonMeson/Tasks/PhotonHBTPCMPCM.cxx deleted file mode 100644 index 0fde469c55c..00000000000 --- a/PWGEM/PhotonMeson/Tasks/PhotonHBTPCMPCM.cxx +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. -// -// ======================== -// -// This code loops over v0 photons and makes pairs for photon HBT analysis. -// Please write to: daiki.sekihata@cern.ch - -#include "PWGEM/PhotonMeson/Core/PhotonHBT.h" - -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) -{ - return WorkflowSpec{ - adaptAnalysisTask>(cfgc, TaskName{"photon-hbt-pcmpcm"})}; -} diff --git a/PWGEM/PhotonMeson/Tasks/photonhbt.cxx b/PWGEM/PhotonMeson/Tasks/photonhbt.cxx new file mode 100644 index 00000000000..bacb008cd47 --- /dev/null +++ b/PWGEM/PhotonMeson/Tasks/photonhbt.cxx @@ -0,0 +1,784 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file photonhbt.cxx +/// \brief This code loops over v0 photons and makes pairs for photon HBT analysis. +/// \author Daiki Sekihata, daiki.sekihata@cern.ch and Stefanie Mrozinski stefanie.mrozinski@cern.ch + +#include "PWGEM/Dilepton/Utils/EMTrack.h" +#include "PWGEM/Dilepton/Utils/EventMixingHandler.h" +#include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" +#include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "PWGEM/PhotonMeson/Utils/EventHistograms.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/// Single-photon track-type combo. +enum class V0Combo : int { + Inclusive = 0, + ItstpcItstpc = 1, ///< both legs ITS+TPC + ItstpcTpconly = 2, /// one ITS+TPC leg, one TPC-only + TpconlyTpconly = 3, /// both legs TPC-only +}; + +/// Photon-pair track-type combo. +enum class PairCombo : int { + Inclusive = 0, + IiXIi = 1, + IiXIt = 2, + IiXTt = 3, + ItXIt = 4, + ItXTt = 5, + TtXTt = 6, +}; + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; +using namespace o2::aod::pwgem::dilepton::utils; + +using MyCollisions = soa::Join; +using MyCollision = MyCollisions::iterator; + +using MyV0Photons = soa::Join; +using MyV0Photon = MyV0Photons::iterator; + +struct photonhbt { + + template + static inline V0Combo classifyV0Combo(TGamma const& g) + { + const auto pos = g.template posTrack_as(); + const auto neg = g.template negTrack_as(); + const bool posII = pos.hasITS() && pos.hasTPC(); + const bool posTPC = !pos.hasITS() && pos.hasTPC(); + const bool negII = neg.hasITS() && neg.hasTPC(); + const bool negTPC = !neg.hasITS() && neg.hasTPC(); + if (posII && negII) + return V0Combo::ItstpcItstpc; + if ((posII && negTPC) || (posTPC && negII)) + return V0Combo::ItstpcTpconly; + if (posTPC && negTPC) + return V0Combo::TpconlyTpconly; + return V0Combo::Inclusive; + } + + static inline PairCombo classifyPairCombo(V0Combo c1, V0Combo c2) + { + const int i1 = static_cast(c1); + const int i2 = static_cast(c2); + if (i1 <= 0 || i2 <= 0) + return PairCombo::Inclusive; + const int lo = std::min(i1, i2); + const int hi = std::max(i1, i2); + static constexpr std::array, 4> kTable = {{{0, 0, 0, 0}, {0, 1, 2, 3}, {0, 2, 4, 5}, {0, 3, 5, 6}}}; + return static_cast(kTable[lo][hi]); + } + + // --------------------------------------------------------------------------- + // Configurables: histogram axes + // --------------------------------------------------------------------------- + + // HBT physics + ConfigurableAxis confQBins{"confQBins", {60, 0, +0.3f}, "q bins for output histograms"}; + ConfigurableAxis confKtBins{"confKtBins", {VARIABLE_WIDTH, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6}, "kT bins"}; + + // Single-photon QA + ConfigurableAxis confPtBins{"confPtBins", {100, 0.f, 2.f}, "pT bins (GeV/c)"}; + ConfigurableAxis confEtaBins{"confEtaBins", {80, -0.8f, 0.8f}, "eta bins"}; + ConfigurableAxis confPhiBins{"confPhiBins", {90, -o2::constants::math::PI, o2::constants::math::PI}, "phi bins (rad)"}; + + // Pair QA + ConfigurableAxis confDeltaEtaBins{"confDeltaEtaBins", {100, -0.9f, +0.9f}, "Delta-eta bins"}; + ConfigurableAxis confDeltaPhiBins{"confDeltaPhiBins", {100, -o2::constants::math::PI, o2::constants::math::PI}, "Delta-phi bins (rad)"}; + ConfigurableAxis confEllipseValBins{"confEllipseValBins", {200, 0.f, 10.f}, "ellipse value bins"}; + ConfigurableAxis confCosThetaBins{"confCosThetaBins", {100, 0.f, 1.f}, "cos(theta*) bins"}; + ConfigurableAxis confOpeningAngleBins{"confOpeningAngleBins", {100, 0.f, o2::constants::math::PI}, "opening angle bins (rad)"}; + + // Axis specs + const AxisSpec axisKt{confKtBins, "k_{T} (GeV/c)"}; + const AxisSpec axisQinv{confQBins, "q_{inv} (GeV/c)"}; + const AxisSpec axisQabsLcms{confQBins, "|#bf{q}|^{LCMS} (GeV/c)"}; + const AxisSpec axisQout{confQBins, "q_{out} (GeV/c)"}; + const AxisSpec axisQside{confQBins, "q_{side} (GeV/c)"}; + const AxisSpec axisQlong{confQBins, "q_{long} (GeV/c)"}; + const AxisSpec axisPt{confPtBins, "p_{T} (GeV/c)"}; + const AxisSpec axisEta{confEtaBins, "#eta"}; + const AxisSpec axisPhi{confPhiBins, "#phi (rad)"}; + const AxisSpec axisDeltaEta{confDeltaEtaBins, "#Delta#eta"}; + const AxisSpec axisDeltaPhi{confDeltaPhiBins, "#Delta#phi (rad)"}; + const AxisSpec axisEllipseVal{confEllipseValBins, "(#Delta#eta/#sigma_{#eta})^{2}+(#Delta#phi/#sigma_{#phi})^{2}"}; + const AxisSpec axisCosTheta{confCosThetaBins, "cos(#theta*)"}; + const AxisSpec axisOpeningAngle{confOpeningAngleBins, "Opening angle (rad)"}; + + // --------------------------------------------------------------------------- + // Configurables: QA flags + // --------------------------------------------------------------------------- + + struct : ConfigurableGroup { + std::string prefix = "qaflags_group"; + Configurable doPairQa{"doPairQa", true, "fill pair QA histograms (Before/After ellipse cut)"}; + Configurable doSinglePhotonQa{"doSinglePhotonQa", true, "fill single-photon QA histograms (pT, eta, phi)"}; + } qaflags; + + // --------------------------------------------------------------------------- + // Configurables: HBT kind + // --------------------------------------------------------------------------- + + Configurable cfgDo3D{"cfgDo3D", false, "enable 3D analysis"}; + Configurable cfgUseLCMS{"cfgUseLCMS", true, "measure relative momentum in LCMS for 1D"}; + + // --------------------------------------------------------------------------- + // Configurables: events + // --------------------------------------------------------------------------- + + Configurable cfgCentMin{"cfgCentMin", -1, "min. centrality"}; + Configurable cfgCentMax{"cfgCentMax", 999, "max. centrality"}; + Configurable maxY{"maxY", 0.9, "maximum rapidity"}; + + // --------------------------------------------------------------------------- + // Configurables: mixed event + // --------------------------------------------------------------------------- + + Configurable cfgDoMix{"cfgDoMix", true, "flag for event mixing"}; + Configurable ndepth{"ndepth", 100, "depth for event mixing"}; + Configurable ndiffBCMix{"ndiffBCMix", 594, "difference in global BC required in mixed events"}; + Configurable cfgEP2EstimatorForMix{"cfgEP2EstimatorForMix", 3, "FT0M:0, FT0A:1, FT0C:2, FV0A:3, BTot:4, BPos:5, BNeg:6"}; + Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; + Configurable cfgOccupancyEstimator{"cfgOccupancyEstimator", 0, "FT0C:0, Track:1"}; + + ConfigurableAxis ConfVtxBins{"ConfVtxBins", {VARIABLE_WIDTH, -10.f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}, "Mixing bins - z-vertex"}; + ConfigurableAxis ConfCentBins{"ConfCentBins", {VARIABLE_WIDTH, 0.f, 5.f, 10.f, 20.f, 30.f, 40.f, 50.f, 60.f, 70.f, 80.f, 90.f, 100.f, 999.f}, "Mixing bins - centrality"}; + ConfigurableAxis ConfEPBins{"ConfEPBins", {16, -o2::constants::math::PIHalf, +o2::constants::math::PIHalf}, "Mixing bins - EP angle"}; + ConfigurableAxis ConfOccupancyBins{"ConfOccupancyBins", {VARIABLE_WIDTH, -1, 1e+10}, "Mixing bins - occupancy"}; + + // --------------------------------------------------------------------------- + // Configurables: pair cuts + // --------------------------------------------------------------------------- + + struct : ConfigurableGroup { + std::string prefix = "ggpaircut_group"; + Configurable cfgMinDR_CosOA{"cfgMinDR_CosOA", -1, "min. dr/cosOA for kPCMPCM"}; + Configurable cfgApplyEllipseCut{"cfgApplyEllipseCut", false, "reject pairs inside ellipse in DeltaEta-DeltaPhi"}; + Configurable cfgEllipseSigEta{"cfgEllipseSigEta", 0.02f, "sigma_eta for ellipse cut"}; + Configurable cfgEllipseSigPhi{"cfgEllipseSigPhi", 0.02f, "sigma_phi for ellipse cut"}; + Configurable cfgEllipseR2{"cfgEllipseR2", 1.0f, "R^2 threshold: reject if value < R^2"}; + } ggpaircuts; + + // --------------------------------------------------------------------------- + // Event cut + // --------------------------------------------------------------------------- + + EMPhotonEventCut fEMEventCut; + struct : ConfigurableGroup { + std::string prefix = "eventcut_group"; + Configurable cfgZvtxMin{"cfgZvtxMin", -10.f, "min. Zvtx"}; + Configurable cfgZvtxMax{"cfgZvtxMax", +10.f, "max. Zvtx"}; + Configurable cfgRequireSel8{"cfgRequireSel8", true, "require sel8"}; + Configurable cfgRequireFT0AND{"cfgRequireFT0AND", true, "require FT0AND"}; + Configurable cfgRequireNoTFB{"cfgRequireNoTFB", true, "require no TF border"}; + Configurable cfgRequireNoITSROFB{"cfgRequireNoITSROFB", true, "require no ITS ROF border"}; + Configurable cfgRequireNoSameBunchPileup{"cfgRequireNoSameBunchPileup", false, "require no same bunch pileup"}; + Configurable cfgRequireVertexITSTPC{"cfgRequireVertexITSTPC", false, "require Vertex ITSTPC"}; + Configurable cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx FT0 vs PV"}; + Configurable cfgTrackOccupancyMin{"cfgTrackOccupancyMin", -2, "min. track occupancy"}; + Configurable cfgTrackOccupancyMax{"cfgTrackOccupancyMax", 1000000000, "max. track occupancy"}; + Configurable cfgFT0COccupancyMin{"cfgFT0COccupancyMin", -2.f, "min. FT0C occupancy"}; + Configurable cfgFT0COccupancyMax{"cfgFT0COccupancyMax", 1000000000.f, "max. FT0C occupancy"}; + Configurable cfgRequireNoCollInTimeRangeStandard{"cfgRequireNoCollInTimeRangeStandard", false, "no coll in time range std"}; + Configurable cfgRequireNoCollInTimeRangeStrict{"cfgRequireNoCollInTimeRangeStrict", false, "no coll in time range strict"}; + Configurable cfgRequireNoCollInITSROFStandard{"cfgRequireNoCollInITSROFStandard", false, "no coll in ITS ROF std"}; + Configurable cfgRequireNoCollInITSROFStrict{"cfgRequireNoCollInITSROFStrict", false, "no coll in ITS ROF strict"}; + Configurable cfgRequireNoHighMultCollInPrevRof{"cfgRequireNoHighMultCollInPrevRof", false, "no HM coll in prev ROF"}; + Configurable cfgRequireGoodITSLayer3{"cfgRequireGoodITSLayer3", false, "ITS layer 3 OK"}; + Configurable cfgRequireGoodITSLayer0123{"cfgRequireGoodITSLayer0123", false, "ITS layers 0-3 OK"}; + Configurable cfgRequireGoodITSLayersAll{"cfgRequireGoodITSLayersAll", false, "all ITS layers OK"}; + } eventcuts; + + // --------------------------------------------------------------------------- + // PCM cut + // --------------------------------------------------------------------------- + + V0PhotonCut fV0PhotonCut; + struct : ConfigurableGroup { + std::string prefix = "pcmcut_group"; + + Configurable cfgRequireV0WithITSTPC{"cfgRequireV0WithITSTPC", false, "select V0s with ITS-TPC tracks"}; + Configurable cfgRequireV0WithITSOnly{"cfgRequireV0WithITSOnly", false, "select V0s with ITS-only tracks"}; + Configurable cfgRequireV0WithTPCOnly{"cfgRequireV0WithTPCOnly", false, "select V0s with TPC-only tracks"}; + + Configurable cfgMinPtV0{"cfgMinPtV0", 0.1, "min pT for V0 photons at PV"}; + Configurable cfgMaxEtaV0{"cfgMaxEtaV0", 0.8, "max eta for V0 photons at PV"}; + Configurable cfgMinV0Radius{"cfgMinV0Radius", 16.0, "min V0 radius"}; + Configurable cfgMaxV0Radius{"cfgMaxV0Radius", 90.0, "max V0 radius"}; + + Configurable cfgMaxAlphaAP{"cfgMaxAlphaAP", 0.95, "max alpha for AP cut"}; + Configurable cfgMaxQtAP{"cfgMaxQtAP", 0.01, "max qT for AP cut"}; + + Configurable cfgMinCosPA{"cfgMinCosPA", 0.997, "min V0 CosPA"}; + Configurable cfgMaxPCA{"cfgMaxPCA", 3.0, "max distance between 2 legs"}; + Configurable cfgMaxChi2KF{"cfgMaxChi2KF", 1e+10, "max chi2/ndf with KF"}; + + Configurable cfgRejectV0OnITSIB{"cfgRejectV0OnITSIB", true, "reject V0s on ITSib"}; + Configurable cfgDisableITSOnlyTrack{"cfgDisableITSOnlyTrack", false, "disable ITS-only tracks"}; + Configurable cfgDisableTPCOnlyTrack{"cfgDisableTPCOnlyTrack", false, "disable TPC-only tracks"}; + + Configurable cfgMinNClusterTPC{"cfgMinNClusterTPC", 70, "min ncluster TPC"}; + Configurable cfgMinNCrossedRows{"cfgMinNCrossedRows", 70, "min crossed rows"}; + Configurable cfgMaxFracSharedClustersTPC{"cfgMaxFracSharedClustersTPC", 999.f, "max fraction of shared TPC clusters"}; + Configurable cfgMaxChi2TPC{"cfgMaxChi2TPC", 4.0, "max chi2/NclsTPC"}; + Configurable cfgMaxChi2ITS{"cfgMaxChi2ITS", 36.0, "max chi2/NclsITS"}; + + Configurable cfgMinTPCNsigmaEl{"cfgMinTPCNsigmaEl", -3.5, "min TPC nsigma electron"}; + Configurable cfgMaxTPCNsigmaEl{"cfgMaxTPCNsigmaEl", +3.5, "max TPC nsigma electron"}; + } pcmcuts; + + ~photonhbt() + { + delete emh1; + emh1 = nullptr; + delete emh2; + emh2 = nullptr; + mapMixedEventIdToGlobalBC.clear(); + usedPhotonIdsPerCol.clear(); + usedPhotonIdsPerCol.shrink_to_fit(); + } + + HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; + static constexpr std::string_view event_pair_types[2] = {"same/", "mix/"}; + + std::mt19937 engine; + std::uniform_int_distribution dist01; + int mRunNumber; + + std::vector ztxBinEdges; + std::vector centBinEdges; + std::vector epBinEgdes; + std::vector occBinEdges; + + inline bool isInsideEllipse(float deta, float dphi) const + { + if (!ggpaircuts.cfgApplyEllipseCut.value) + return false; + const float sE = ggpaircuts.cfgEllipseSigEta.value; + const float sP = ggpaircuts.cfgEllipseSigPhi.value; + if (sE < 1e-9f || sP < 1e-9f) + return false; + return (deta / sE) * (deta / sE) + (dphi / sP) * (dphi / sP) < ggpaircuts.cfgEllipseR2.value; + } + + static inline float computeCosTheta(const ROOT::Math::PtEtaPhiMVector& v1, + const ROOT::Math::PtEtaPhiMVector& v2) + { + ROOT::Math::PxPyPzEVector p1(v1), p2(v2); + ROOT::Math::PxPyPzEVector pair = p1 + p2; + ROOT::Math::Boost boost(-pair.BoostToCM()); + ROOT::Math::PxPyPzEVector p1cm = boost(p1); + ROOT::Math::XYZVector pairDir(pair.Px(), pair.Py(), pair.Pz()); + ROOT::Math::XYZVector p1cmDir(p1cm.Px(), p1cm.Py(), p1cm.Pz()); + if (pairDir.R() < 1e-9 || p1cmDir.R() < 1e-9) + return -1.f; + return static_cast(pairDir.Unit().Dot(p1cmDir.Unit())); + } + + static void parseBins(const ConfigurableAxis& cfg, std::vector& edges) + { + if (cfg.value[0] == VARIABLE_WIDTH) { + edges = std::vector(cfg.value.begin(), cfg.value.end()); + edges.erase(edges.begin()); + } else { + const int n = static_cast(cfg.value[0]); + const float xmin = static_cast(cfg.value[1]); + const float xmax = static_cast(cfg.value[2]); + edges.resize(n + 1); + for (int i = 0; i <= n; ++i) + edges[i] = xmin + (xmax - xmin) / n * i; + } + } + + /// Clamp bin index to valid range [0, nmax]. + static int clampBin(int b, int nmax) { return std::clamp(b, 0, nmax); } + + /// Find the bin index for val in a sorted edge vector. + static int binOf(const std::vector& edges, float val) + { + const int b = static_cast(std::lower_bound(edges.begin(), edges.end(), val) - edges.begin()) - 1; + return clampBin(b, static_cast(edges.size()) - 2); + } + + void init(InitContext& /*context*/) + { + mRunNumber = 0; + + parseBins(ConfVtxBins, ztxBinEdges); + parseBins(ConfCentBins, centBinEdges); + parseBins(ConfEPBins, epBinEgdes); + parseBins(ConfOccupancyBins, occBinEdges); + + emh1 = new MyEMH(ndepth); + emh2 = new MyEMH(ndepth); + + o2::aod::pwgem::photonmeson::utils::eventhistogram::addEventHistograms(&fRegistry); + DefineEMEventCut(); + DefinePCMCut(); + addhistograms(); + + std::random_device seedGen; + engine = std::mt19937(seedGen()); + dist01 = std::uniform_int_distribution(0, 1); + + fRegistry.add("Pair/mix/hDiffBC", + "diff. global BC in mixed event;|BC_{current} - BC_{mixed}|", + kTH1D, {{10001, -0.5, 10000.5}}, true); + } + + template + void initCCDB(TCollision const& collision) + { + if (mRunNumber == collision.runNumber()) + return; + mRunNumber = collision.runNumber(); + } + void addQAHistogramsForStep(const std::string& path) + { + fRegistry.add((path + "hDeltaEta").c_str(), "#Delta#eta;#Delta#eta;counts", kTH1F, {axisDeltaEta}, true); + fRegistry.add((path + "hDeltaPhi").c_str(), "#Delta#phi;#Delta#phi (rad);counts", kTH1F, {axisDeltaPhi}, true); + fRegistry.add((path + "hDEtaDPhi").c_str(), "#Delta#eta vs #Delta#phi;#Delta#eta;#Delta#phi (rad)", kTH2F, {axisDeltaEta, axisDeltaPhi}, true); + fRegistry.add((path + "hDeltaEtaVsPairEta").c_str(), "#Delta#eta vs #LT#eta#GT_{pair};#LT#eta#GT_{pair};#Delta#eta", kTH2F, {axisEta, axisDeltaEta}, true); + fRegistry.add((path + "hCosTheta").c_str(), "cos(#theta*) in pair rest frame;cos(#theta*);counts", kTH1F, {axisCosTheta}, true); + fRegistry.add((path + "hOpeningAngle").c_str(), "Opening angle between conversion points;#alpha (rad);counts", kTH1F, {axisOpeningAngle}, true); + fRegistry.add((path + "hEllipseVal").c_str(), "(#Delta#eta/#sigma_{#eta})^{2}+(#Delta#phi/#sigma_{#phi})^{2};value;counts", kTH1D, {axisEllipseVal}, true); + } + + void addhistograms() + { + static constexpr std::string_view det[6] = {"FT0M", "FT0A", "FT0C", "BTot", "BPos", "BNeg"}; + fRegistry.add("Event/before/hEP2_CentFT0C_forMix", Form("2nd harmonics EP for mix;centrality FT0C (%%);#Psi_{2}^{%s} (rad.)", det[cfgEP2EstimatorForMix].data()), kTH2F, {{110, 0, 110}, {180, -o2::constants::math::PIHalf, +o2::constants::math::PIHalf}}, false); + fRegistry.add("Event/after/hEP2_CentFT0C_forMix", Form("2nd harmonics EP for mix;centrality FT0C (%%);#Psi_{2}^{%s} (rad.)", det[cfgEP2EstimatorForMix].data()), kTH2F, {{110, 0, 110}, {180, -o2::constants::math::PIHalf, +o2::constants::math::PIHalf}}, false); + + // ── Single-photon QA ───────────────────────────────────────────────────── + fRegistry.add("SinglePhoton/hPt", "V0 photon p_{T};p_{T} (GeV/c);counts", kTH1F, {axisPt}, true); + fRegistry.add("SinglePhoton/hEta", "V0 photon #eta;#eta;counts", kTH1F, {axisEta}, true); + fRegistry.add("SinglePhoton/hPhi", "V0 photon #phi;#phi (rad);counts", kTH1F, {axisPhi}, true); + fRegistry.add("SinglePhoton/hEtaVsPhi", "V0 photon acceptance;#phi (rad);#eta", kTH2F, {axisPhi, axisEta}, true); + + // ── HBT physics ────────────────────────────────────────────────────────── + if (cfgDo3D) { + fRegistry.add("Pair/same/hs_3d", "diphoton correlation 3D LCMS", kTHnSparseD, {axisQout, axisQside, axisQlong, axisKt}, true); + } else { + if (cfgUseLCMS) { + fRegistry.add("Pair/same/hs_1d", "diphoton correlation 1D LCMS", kTHnSparseD, {axisQabsLcms, axisKt}, true); + } else { + fRegistry.add("Pair/same/hs_1d", "diphoton correlation 1D", kTHnSparseD, {axisQinv, axisKt}, true); + } + } + + fRegistry.add("Pair/same/hDeltaRCosOA", "distance between 2 conversion points;#Deltar/cos(#theta_{op}/2) (cm)", kTH1D, {{100, 0, 100}}, true); + + addQAHistogramsForStep("Pair/same/QA/Before/"); + addQAHistogramsForStep("Pair/same/QA/After/"); + + fRegistry.addClone("Pair/same/", "Pair/mix/"); + } + + // --------------------------------------------------------------------------- + // DefineEMEventCut / DefinePCMCut + // --------------------------------------------------------------------------- + + void DefineEMEventCut() + { + fEMEventCut = EMPhotonEventCut("fEMEventCut", "fEMEventCut"); + fEMEventCut.SetRequireSel8(eventcuts.cfgRequireSel8); + fEMEventCut.SetRequireFT0AND(eventcuts.cfgRequireFT0AND); + fEMEventCut.SetZvtxRange(eventcuts.cfgZvtxMin, eventcuts.cfgZvtxMax); + fEMEventCut.SetRequireNoTFB(eventcuts.cfgRequireNoTFB); + fEMEventCut.SetRequireNoITSROFB(eventcuts.cfgRequireNoITSROFB); + fEMEventCut.SetRequireNoSameBunchPileup(eventcuts.cfgRequireNoSameBunchPileup); + fEMEventCut.SetRequireVertexITSTPC(eventcuts.cfgRequireVertexITSTPC); + fEMEventCut.SetRequireGoodZvtxFT0vsPV(eventcuts.cfgRequireGoodZvtxFT0vsPV); + fEMEventCut.SetRequireNoCollInTimeRangeStandard(eventcuts.cfgRequireNoCollInTimeRangeStandard); + fEMEventCut.SetRequireNoCollInTimeRangeStrict(eventcuts.cfgRequireNoCollInTimeRangeStrict); + fEMEventCut.SetRequireNoCollInITSROFStandard(eventcuts.cfgRequireNoCollInITSROFStandard); + fEMEventCut.SetRequireNoCollInITSROFStrict(eventcuts.cfgRequireNoCollInITSROFStrict); + fEMEventCut.SetRequireNoHighMultCollInPrevRof(eventcuts.cfgRequireNoHighMultCollInPrevRof); + fEMEventCut.SetRequireGoodITSLayer3(eventcuts.cfgRequireGoodITSLayer3); + fEMEventCut.SetRequireGoodITSLayer0123(eventcuts.cfgRequireGoodITSLayer0123); + fEMEventCut.SetRequireGoodITSLayersAll(eventcuts.cfgRequireGoodITSLayersAll); + } + + void DefinePCMCut() + { + fV0PhotonCut = V0PhotonCut("fV0PhotonCut", "fV0PhotonCut"); + fV0PhotonCut.SetV0PtRange(pcmcuts.cfgMinPtV0, 1e10f); + fV0PhotonCut.SetV0EtaRange(-pcmcuts.cfgMaxEtaV0, +pcmcuts.cfgMaxEtaV0); + fV0PhotonCut.SetMinCosPA(pcmcuts.cfgMinCosPA); + fV0PhotonCut.SetMaxPCA(pcmcuts.cfgMaxPCA); + fV0PhotonCut.SetMaxChi2KF(pcmcuts.cfgMaxChi2KF); + fV0PhotonCut.SetRxyRange(pcmcuts.cfgMinV0Radius, pcmcuts.cfgMaxV0Radius); + fV0PhotonCut.SetAPRange(pcmcuts.cfgMaxAlphaAP, pcmcuts.cfgMaxQtAP); + fV0PhotonCut.RejectITSib(pcmcuts.cfgRejectV0OnITSIB); + fV0PhotonCut.SetMinNClustersTPC(pcmcuts.cfgMinNClusterTPC); + fV0PhotonCut.SetMinNCrossedRowsTPC(pcmcuts.cfgMinNCrossedRows); + fV0PhotonCut.SetMinNCrossedRowsOverFindableClustersTPC(0.8); + fV0PhotonCut.SetMaxFracSharedClustersTPC(pcmcuts.cfgMaxFracSharedClustersTPC); + fV0PhotonCut.SetChi2PerClusterTPC(0.0, pcmcuts.cfgMaxChi2TPC); + fV0PhotonCut.SetTPCNsigmaElRange(pcmcuts.cfgMinTPCNsigmaEl, pcmcuts.cfgMaxTPCNsigmaEl); + fV0PhotonCut.SetChi2PerClusterITS(-1e+10, pcmcuts.cfgMaxChi2ITS); + fV0PhotonCut.SetDisableITSonly(pcmcuts.cfgDisableITSOnlyTrack); + fV0PhotonCut.SetDisableTPConly(pcmcuts.cfgDisableTPCOnlyTrack); + fV0PhotonCut.SetNClustersITS(0, 7); + fV0PhotonCut.SetMeanClusterSizeITSob(0.0, 16.0); + fV0PhotonCut.SetRequireITSTPC(pcmcuts.cfgRequireV0WithITSTPC); + fV0PhotonCut.SetRequireITSonly(pcmcuts.cfgRequireV0WithITSOnly); + fV0PhotonCut.SetRequireTPConly(pcmcuts.cfgRequireV0WithTPCOnly); + } + + template + void fillPairHistogram(TCollision const&, + ROOT::Math::PtEtaPhiMVector v1, + ROOT::Math::PtEtaPhiMVector v2, + float weight = 1.f) + { + float rndm = std::pow(-1, dist01(engine) % 2); + auto k12 = 0.5 * (v1 + v2); + float kt = k12.Pt(); + float qinv = -(((v1 - v2) * rndm).M()); + + ROOT::Math::XYZVector uv_out(k12.Px() / k12.Pt(), k12.Py() / k12.Pt(), 0); + ROOT::Math::XYZVector uv_long(0, 0, 1); + ROOT::Math::XYZVector uv_side = uv_out.Cross(uv_long); + + ROOT::Math::PxPyPzEVector v1c(v1), v2c(v2); + float beta_z = (v1 + v2).Beta() * std::cos((v1 + v2).Theta()); + ROOT::Math::Boost bst_z(0, 0, -beta_z); + auto q12_lcms = bst_z((v1c - v2c) * rndm); + auto q3_lcms = q12_lcms.Vect(); + float qabs_lcms = q3_lcms.R(); + float qout_lcms = q3_lcms.Dot(uv_out); + float qside_lcms = q3_lcms.Dot(uv_side); + float qlong_lcms = q3_lcms.Dot(uv_long); + + if (cfgDo3D) { + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("hs_3d"), + std::fabs(qout_lcms), std::fabs(qside_lcms), std::fabs(qlong_lcms), kt, weight); + } else { + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("hs_1d"), + cfgUseLCMS ? qabs_lcms : qinv, kt, weight); + } + } + + template + inline void fillPairQAStep(float deta, float dphi, float pairEta, + float cosTheta, float openingAngle) + { + if (!qaflags.doPairQa) + return; + + const float sE = ggpaircuts.cfgEllipseSigEta.value; + const float sP = ggpaircuts.cfgEllipseSigPhi.value; + + if constexpr (ev_id == 0 && IsBefore) { + fRegistry.fill(HIST("Pair/same/QA/Before/hDeltaEta"), deta); + fRegistry.fill(HIST("Pair/same/QA/Before/hDeltaPhi"), dphi); + fRegistry.fill(HIST("Pair/same/QA/Before/hDEtaDPhi"), deta, dphi); + fRegistry.fill(HIST("Pair/same/QA/Before/hDeltaEtaVsPairEta"), pairEta, deta); + fRegistry.fill(HIST("Pair/same/QA/Before/hCosTheta"), cosTheta); + fRegistry.fill(HIST("Pair/same/QA/Before/hOpeningAngle"), openingAngle); + if (sE > 1e-9f && sP > 1e-9f) + fRegistry.fill(HIST("Pair/same/QA/Before/hEllipseVal"), (deta / sE) * (deta / sE) + (dphi / sP) * (dphi / sP)); + } else if constexpr (ev_id == 0 && !IsBefore) { + fRegistry.fill(HIST("Pair/same/QA/After/hDeltaEta"), deta); + fRegistry.fill(HIST("Pair/same/QA/After/hDeltaPhi"), dphi); + fRegistry.fill(HIST("Pair/same/QA/After/hDEtaDPhi"), deta, dphi); + fRegistry.fill(HIST("Pair/same/QA/After/hDeltaEtaVsPairEta"), pairEta, deta); + fRegistry.fill(HIST("Pair/same/QA/After/hCosTheta"), cosTheta); + fRegistry.fill(HIST("Pair/same/QA/After/hOpeningAngle"), openingAngle); + if (sE > 1e-9f && sP > 1e-9f) + fRegistry.fill(HIST("Pair/same/QA/After/hEllipseVal"), (deta / sE) * (deta / sE) + (dphi / sP) * (dphi / sP)); + } else if constexpr (ev_id == 1 && IsBefore) { + fRegistry.fill(HIST("Pair/mix/QA/Before/hDeltaEta"), deta); + fRegistry.fill(HIST("Pair/mix/QA/Before/hDeltaPhi"), dphi); + fRegistry.fill(HIST("Pair/mix/QA/Before/hDEtaDPhi"), deta, dphi); + fRegistry.fill(HIST("Pair/mix/QA/Before/hDeltaEtaVsPairEta"), pairEta, deta); + fRegistry.fill(HIST("Pair/mix/QA/Before/hCosTheta"), cosTheta); + fRegistry.fill(HIST("Pair/mix/QA/Before/hOpeningAngle"), openingAngle); + if (sE > 1e-9f && sP > 1e-9f) + fRegistry.fill(HIST("Pair/mix/QA/Before/hEllipseVal"), (deta / sE) * (deta / sE) + (dphi / sP) * (dphi / sP)); + } else { + fRegistry.fill(HIST("Pair/mix/QA/After/hDeltaEta"), deta); + fRegistry.fill(HIST("Pair/mix/QA/After/hDeltaPhi"), dphi); + fRegistry.fill(HIST("Pair/mix/QA/After/hDEtaDPhi"), deta, dphi); + fRegistry.fill(HIST("Pair/mix/QA/After/hDeltaEtaVsPairEta"), pairEta, deta); + fRegistry.fill(HIST("Pair/mix/QA/After/hCosTheta"), cosTheta); + fRegistry.fill(HIST("Pair/mix/QA/After/hOpeningAngle"), openingAngle); + if (sE > 1e-9f && sP > 1e-9f) + fRegistry.fill(HIST("Pair/mix/QA/After/hEllipseVal"), (deta / sE) * (deta / sE) + (dphi / sP) * (dphi / sP)); + } + } + + template + void runPairing(TCollisions const& collisions, + TPhotons1 const& photons1, TPhotons2 const& photons2, + TSubInfos1 const&, TSubInfos2 const&, + TPreslice1 const& perCollision1, TPreslice2 const& perCollision2, + TCut1 const& cut1, TCut2 const& cut2) + { + for (const auto& collision : collisions) { + initCCDB(collision); + int ndiphoton = 0; + + const float cent[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; + if (cent[cfgCentEstimator] < cfgCentMin || cfgCentMax < cent[cfgCentEstimator]) + continue; + + const std::array epArr = {collision.ep2ft0m(), collision.ep2ft0a(), collision.ep2ft0c(), + collision.ep2fv0a(), collision.ep2btot(), collision.ep2bpos(), collision.ep2bneg()}; + float ep2 = epArr[cfgEP2EstimatorForMix]; + + fRegistry.fill(HIST("Event/before/hEP2_CentFT0C_forMix"), collision.centFT0C(), ep2); + o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<0>(&fRegistry, collision, 1.f); + if (!fEMEventCut.IsSelected(collision)) + continue; + o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<1>(&fRegistry, collision, 1.f); + fRegistry.fill(HIST("Event/after/hEP2_CentFT0C_forMix"), collision.centFT0C(), ep2); + + // Mixing-bin indices — uses static binOf helper: + int zbin = binOf(ztxBinEdges, collision.posZ()); + int centbin = binOf(centBinEdges, cent[cfgCentEstimator]); + int epbin = binOf(epBinEgdes, ep2); + int occbin = binOf(occBinEdges, + cfgOccupancyEstimator == 1 + ? static_cast(collision.trackOccupancyInTimeRange()) + : collision.ft0cOccupancyInTimeRange()); + + auto keyBin = std::make_tuple(zbin, centbin, epbin, occbin); + auto keyDFCollision = std::make_pair(ndf, collision.globalIndex()); + + auto photons1Coll = photons1.sliceBy(perCollision1, collision.globalIndex()); + auto photons2Coll = photons2.sliceBy(perCollision2, collision.globalIndex()); + + // ── Single-photon QA ───────────────────────────────────────────────── + if (qaflags.doSinglePhotonQa) { + for (const auto& g : photons1Coll) { + if (!cut1.template IsSelected(g)) + continue; + fRegistry.fill(HIST("SinglePhoton/hPt"), g.pt()); + fRegistry.fill(HIST("SinglePhoton/hEta"), g.eta()); + fRegistry.fill(HIST("SinglePhoton/hPhi"), g.phi()); + fRegistry.fill(HIST("SinglePhoton/hEtaVsPhi"), g.phi(), g.eta()); + } + } + + // ── Same-event pair loop ────────────────────────────────────────────── + for (const auto& [g1, g2] : combinations(CombinationsStrictlyUpperIndexPolicy(photons1Coll, photons2Coll))) { + if (!cut1.template IsSelected(g1) || + !cut2.template IsSelected(g2)) + continue; + + auto pos1 = g1.template posTrack_as(); + auto ele1 = g1.template negTrack_as(); + auto pos2 = g2.template posTrack_as(); + auto ele2 = g2.template negTrack_as(); + if (pos1.trackId() == pos2.trackId() || ele1.trackId() == ele2.trackId()) + continue; + + ROOT::Math::XYZVector cp1(g1.vx(), g1.vy(), g1.vz()); + ROOT::Math::XYZVector cp2(g2.vx(), g2.vy(), g2.vz()); + float dr = std::sqrt(std::pow(g1.vx() - g2.vx(), 2) + std::pow(g1.vy() - g2.vy(), 2) + std::pow(g1.vz() - g2.vz(), 2)); + float opa = std::acos(std::clamp(static_cast(cp1.Dot(cp2) / (std::sqrt(cp1.Mag2()) * std::sqrt(cp2.Mag2()))), -1.f, 1.f)); + o2::math_utils::bringTo02Pi(opa); + if (opa > o2::constants::math::PI) + opa -= o2::constants::math::PI; + float cosOA = std::cos(opa / 2.f); + if (dr / cosOA < ggpaircuts.cfgMinDR_CosOA) + continue; + fRegistry.fill(HIST("Pair/same/hDeltaRCosOA"), dr / cosOA); + + // Kinematic variables for QA + ROOT::Math::PtEtaPhiMVector v1(g1.pt(), g1.eta(), g1.phi(), 0.); + ROOT::Math::PtEtaPhiMVector v2(g2.pt(), g2.eta(), g2.phi(), 0.); + float deta = g1.eta() - g2.eta(); + float dphi = RecoDecay::constrainAngle(g1.phi() - g2.phi(), -o2::constants::math::PI); + float pairEta = 0.5f * (g1.eta() + g2.eta()); + float cosTheta = std::fabs(computeCosTheta(v1, v2)); + float openingAngle = opa; + + // ── QA: Before ellipse cut ────────────────────────────────────── + fillPairQAStep<0, true>(deta, dphi, pairEta, cosTheta, openingAngle); + + // ── Ellipse cut ───────────────────────────────────────────────── + if (isInsideEllipse(deta, dphi)) + continue; + + // ── QA: After ellipse cut ─────────────────────────────────────── + fillPairQAStep<0, false>(deta, dphi, pairEta, cosTheta, openingAngle); + + // ── Physics ───────────────────────────────────────────────── + fillPairHistogram<0>(collision, v1, v2, 1.f); + ndiphoton++; + + auto addToPool = [&](auto const& g) { + if (std::find(usedPhotonIdsPerCol.begin(), usedPhotonIdsPerCol.end(), + g.globalIndex()) == usedPhotonIdsPerCol.end()) { + EMPair gtmp(g.pt(), g.eta(), g.phi(), 0); + gtmp.setConversionPointXYZ(g.vx(), g.vy(), g.vz()); + emh1->AddTrackToEventPool(keyDFCollision, gtmp); + usedPhotonIdsPerCol.emplace_back(g.globalIndex()); + } + }; + addToPool(g1); + addToPool(g2); + + // end same-event pair loop + } + + usedPhotonIdsPerCol.clear(); + usedPhotonIdsPerCol.shrink_to_fit(); + + // ── Mixed-event loop ──────────────────────────────────────────────────── + if (!cfgDoMix || !(ndiphoton > 0)) + continue; + + auto selectedPhotons = emh1->GetTracksPerCollision(keyDFCollision); + auto poolIDs = emh1->GetCollisionIdsFromEventPool(keyBin); + + for (const auto& mixID : poolIDs) { + if (mixID.second == collision.globalIndex() && mixID.first == ndf) + continue; + + uint64_t bcMix = mapMixedEventIdToGlobalBC[mixID]; + uint64_t diffBC = std::max(collision.globalBC(), bcMix) - std::min(collision.globalBC(), bcMix); + fRegistry.fill(HIST("Pair/mix/hDiffBC"), diffBC); + if (diffBC < ndiffBCMix) + continue; + + auto poolPhotons = emh1->GetTracksPerCollision(mixID); + + for (const auto& g1 : selectedPhotons) { + for (const auto& g2 : poolPhotons) { + + ROOT::Math::XYZVector cp1(g1.vx(), g1.vy(), g1.vz()); + ROOT::Math::XYZVector cp2(g2.vx(), g2.vy(), g2.vz()); + float dr = std::sqrt(std::pow(g1.vx() - g2.vx(), 2) + std::pow(g1.vy() - g2.vy(), 2) + std::pow(g1.vz() - g2.vz(), 2)); + float opa = std::acos(std::clamp(static_cast(cp1.Dot(cp2) / (std::sqrt(cp1.Mag2()) * std::sqrt(cp2.Mag2()))), -1.f, 1.f)); + o2::math_utils::bringTo02Pi(opa); + if (opa > o2::constants::math::PI) + opa -= o2::constants::math::PI; + float cosOA = std::cos(opa / 2.f); + if (dr / cosOA < ggpaircuts.cfgMinDR_CosOA) + continue; + fRegistry.fill(HIST("Pair/mix/hDeltaRCosOA"), dr / cosOA); + + ROOT::Math::PtEtaPhiMVector v1(g1.pt(), g1.eta(), g1.phi(), 0.); + ROOT::Math::PtEtaPhiMVector v2(g2.pt(), g2.eta(), g2.phi(), 0.); + float deta = g1.eta() - g2.eta(); + float dphi = RecoDecay::constrainAngle(g1.phi() - g2.phi(), -o2::constants::math::PI); + float pairEta = 0.5f * (g1.eta() + g2.eta()); + float cosTheta = std::fabs(computeCosTheta(v1, v2)); + float openingAngle = opa; + + // QA Before cut — mix/QA/Before/ histograms. + fillPairQAStep<1, true>(deta, dphi, pairEta, cosTheta, openingAngle); + + // Apply ellipse cut + if (isInsideEllipse(deta, dphi)) + continue; + + // QA After cut + fillPairQAStep<1, false>(deta, dphi, pairEta, cosTheta, openingAngle); + + fillPairHistogram<1>(collision, v1, v2, 1.f); + } + } + } + + if (ndiphoton > 0) { + emh1->AddCollisionIdAtLast(keyBin, keyDFCollision); + emh2->AddCollisionIdAtLast(keyBin, keyDFCollision); + mapMixedEventIdToGlobalBC[keyDFCollision] = collision.globalBC(); + } + } // end collision loop + } + + using MyEMH = o2::aod::pwgem::dilepton::utils::EventMixingHandler, std::pair, EMPair>; + MyEMH* emh1 = nullptr; + MyEMH* emh2 = nullptr; + std::vector usedPhotonIdsPerCol; + std::map, uint64_t> mapMixedEventIdToGlobalBC; + + SliceCache cache; + Preslice perCollisionPCM = aod::v0photonkf::pmeventId; + + Filter collisionFilterCentrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || + (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || + (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); + Filter collisionFilterOccupancyTrack = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && + o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; + Filter collisionFilterOccupancyFT0c = eventcuts.cfgFT0COccupancyMin <= o2::aod::evsel::ft0cOccupancyInTimeRange && + o2::aod::evsel::ft0cOccupancyInTimeRange < eventcuts.cfgFT0COccupancyMax; + using FilteredMyCollisions = soa::Filtered; + + int ndf = 0; + void processAnalysis(FilteredMyCollisions const& collisions, MyV0Photons const& v0photons, aod::V0Legs const& v0legs) + { + runPairing(collisions, v0photons, v0photons, v0legs, v0legs, + perCollisionPCM, perCollisionPCM, fV0PhotonCut, fV0PhotonCut); + ndf++; + } + PROCESS_SWITCH(photonhbt, processAnalysis, "pairing for analysis", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc, TaskName{"photonhbt"})}; +} From 703b8780e11bd6ef34818be7cf2462990f8acdc3 Mon Sep 17 00:00:00 2001 From: Jerome Jung Date: Tue, 17 Mar 2026 22:33:38 +0100 Subject: [PATCH 309/347] =?UTF-8?q?[PWGEM]=20LMee:=20Adjusted=20binning=20?= =?UTF-8?q?of=20DCA=20correlation=20to=20include=20negative=E2=80=A6=20(#1?= =?UTF-8?q?5431)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- PWGEM/Dilepton/Core/Dilepton.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWGEM/Dilepton/Core/Dilepton.h b/PWGEM/Dilepton/Core/Dilepton.h index b1f5b3b3b46..5238c549445 100644 --- a/PWGEM/Dilepton/Core/Dilepton.h +++ b/PWGEM/Dilepton/Core/Dilepton.h @@ -592,7 +592,7 @@ struct Dilepton { if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { fRegistry.add("Pair/same/uls/hMvsPhiV", "m_{ee} vs. #varphi_{V};#varphi_{V} (rad.);m_{ee} (GeV/c^{2})", kTH2D, {{90, 0, M_PI}, {100, 0.0f, 1.0f}}, true); // phiv is only for dielectron fRegistry.add("Pair/same/uls/hMvsOpAng", "m_{ee} vs. angle between 2 tracks;#omega (rad.);m_{ee} (GeV/c^{2})", kTH2D, {{90, 0, M_PI}, {100, 0.0f, 1.0f}}, true); - fRegistry.add("Pair/same/uls/hDCA1vsDCA2", "DCA of leg1 vs. DCA of leg2;DCA1(#sigma);DCA2 (#sigma)", kTH2D, {{100, 0, 10.0}, {100, 0, 10}}, true); + fRegistry.add("Pair/same/uls/hDCA1vsDCA2", "DCA of leg1 vs. DCA of leg2;DCA1(#sigma);DCA2 (#sigma)", kTH2D, {{200, -10, 10.0}, {200, -10, 10}}, true); } fRegistry.addClone("Pair/same/uls/", "Pair/same/lspp/"); fRegistry.addClone("Pair/same/uls/", "Pair/same/lsmm/"); From 5c0526e2a584cd1a78118df14339845b30d25161 Mon Sep 17 00:00:00 2001 From: skundu692 <86804743+skundu692@users.noreply.github.com> Date: Tue, 17 Mar 2026 23:29:37 +0100 Subject: [PATCH 310/347] [PWGLF] Code clean up and add 2nd leg mixing in v3 (#15433) --- .../Strangeness/lambdaspincorrderived.cxx | 1230 +++++++---------- 1 file changed, 529 insertions(+), 701 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx b/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx index 222fb030962..014834942f5 100644 --- a/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx +++ b/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx @@ -209,6 +209,14 @@ struct lambdaspincorrderived { Configurable ConfWeightPathALL2{"ConfWeightPathALL2", "Users/s/skundu/My/Object/spincorr/cent010LL", "Weight path 2"}; // Mixing ///////// + struct : ConfigurableGroup { + Configurable nKinematicPt{"nKinematicPt", 1.0, "Number of pT buffer bins"}; + Configurable nKinematicEta{"nKinematicEta", 1.0, "Number of eta buffer bins"}; + Configurable nKinematicPhi{"nKinematicPhi", 1.0, "Number of phi buffer bins"}; + } cfgKinematicBins; + + Configurable ptMinMixBuffer{"ptMinMixBuffer", 0.7, "Minimum V0 pT for mix buffer"}; + Configurable ptMaxMixBuffer{"ptMaxMixBuffer", 4.1, "Maximum V0 pT for mix buffer"}; Configurable cfgMixLegMode{"cfgMixLegMode", 0, "0=replace leg-1 only, 1=replace leg-2 only, 2=do both one-leg replacements"}; Configurable cfgV5MassBins{"cfgV5MassBins", 5, "Number of fixed mass bins for V5 mixing"}; Configurable cfgV5NeighborPt{"cfgV5NeighborPt", 0, "v5: neighbor bins in pT (use symmetric ±N, edge-safe)"}; @@ -424,6 +432,91 @@ struct lambdaspincorrderived { return true; } + template + bool selectionV0Buffer(T const& candidate) + { + auto particle = ROOT::Math::PtEtaPhiMVector(candidate.lambdaPt(), candidate.lambdaEta(), candidate.lambdaPhi(), candidate.lambdaMass()); + + if (std::abs(particle.Rapidity()) > rapidity || std::abs(particle.Eta()) > v0etaMixBuffer) { + return false; + } + if (candidate.lambdaMass() < MassMin || candidate.lambdaMass() > MassMax) { + return false; + } + if (candidate.v0Cospa() < cosPA) { + return false; + } + if (checkDoubleStatus && candidate.doubleStatus()) { + return false; + } + if (candidate.v0Radius() > radiusMax) { + return false; + } + if (candidate.v0Radius() < radiusMin) { + return false; + } + if (candidate.dcaBetweenDaughter() > dcaDaughters) { + return false; + } + if (candidate.v0Status() == 0 && (std::abs(candidate.dcaPositive()) < dcaProton || std::abs(candidate.dcaNegative()) < dcaPion)) { + return false; + } + if (candidate.v0Status() == 1 && (std::abs(candidate.dcaPositive()) < dcaPion || std::abs(candidate.dcaNegative()) < dcaProton)) { + return false; + } + if (candidate.lambdaPt() < ptMinMixBuffer) { + return false; + } + if (candidate.lambdaPt() > ptMaxMixBuffer) { + return false; + } + return true; + } + + template + bool selectionV0BufferMC(T const& candidate) + { + auto particle = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(candidate), + mcacc::lamEta(candidate), + mcacc::lamPhi(candidate), + mcacc::lamMass(candidate)); + + if (std::abs(particle.Rapidity()) > rapidity || std::abs(particle.Eta()) > v0etaMixBuffer) { + return false; + } + if (mcacc::lamMass(candidate) < MassMin || mcacc::lamMass(candidate) > MassMax) { + return false; + } + if (mcacc::v0CosPA(candidate) < cosPA) { + return false; + } + if (checkDoubleStatus && mcacc::doubleStatus(candidate)) { + return false; + } + if (mcacc::v0Radius(candidate) > radiusMax) { + return false; + } + if (mcacc::v0Radius(candidate) < radiusMin) { + return false; + } + if (mcacc::dcaDau(candidate) > dcaDaughters) { + return false; + } + if (mcacc::v0Status(candidate) == 0 && (std::abs(mcacc::dcaPos(candidate)) < dcaProton || std::abs(mcacc::dcaNeg(candidate)) < dcaPion)) { + return false; + } + if (mcacc::v0Status(candidate) == 1 && (std::abs(mcacc::dcaPos(candidate)) < dcaPion || std::abs(mcacc::dcaNeg(candidate)) < dcaProton)) { + return false; + } + if (mcacc::lamPt(candidate) < ptMinMixBuffer) { + return false; + } + if (mcacc::lamPt(candidate) > ptMaxMixBuffer) { + return false; + } + return true; + } + template bool checkKinematics(T1 const& c1, T2 const& c2) { @@ -544,9 +637,8 @@ struct lambdaspincorrderived { void fillHistograms(int tag1, int tag2, const ROOT::Math::PtEtaPhiMVector& particle1, const ROOT::Math::PtEtaPhiMVector& particle2, const ROOT::Math::PtEtaPhiMVector& daughpart1, const ROOT::Math::PtEtaPhiMVector& daughpart2, - int datatype, float mixpairweight) + int datatype, float mixpairweight, int replacedLeg = 1) { - auto lambda1Mass = 0.0; auto lambda2Mass = 0.0; if (!usePDGM) { @@ -556,47 +648,43 @@ struct lambdaspincorrderived { lambda1Mass = o2::constants::physics::MassLambda; lambda2Mass = o2::constants::physics::MassLambda; } + auto particle1Dummy = ROOT::Math::PtEtaPhiMVector(particle1.Pt(), particle1.Eta(), particle1.Phi(), lambda1Mass); auto particle2Dummy = ROOT::Math::PtEtaPhiMVector(particle2.Pt(), particle2.Eta(), particle2.Phi(), lambda2Mass); auto pairDummy = particle1Dummy + particle2Dummy; - ROOT::Math::Boost boostPairToCM{pairDummy.BoostToCM()}; // boosting vector for pair CM + ROOT::Math::Boost boostPairToCM{pairDummy.BoostToCM()}; - // Step1: Boosting both Lambdas to Lambda-Lambda pair rest frame + // Step1: Boost both Lambdas to pair rest frame auto lambda1CM = boostPairToCM(particle1Dummy); auto lambda2CM = boostPairToCM(particle2Dummy); - // Step 2: Boost Each Lambda to its Own Rest Frame + // Step2: Boost each Lambda to its own rest frame ROOT::Math::Boost boostLambda1ToCM{lambda1CM.BoostToCM()}; ROOT::Math::Boost boostLambda2ToCM{lambda2CM.BoostToCM()}; - // Also boost the daughter protons to the same frame - auto proton1pairCM = boostPairToCM(daughpart1); // proton1 to pair CM - auto proton2pairCM = boostPairToCM(daughpart2); // proton2 to pair CM + // Also boost daughter protons to pair CM + auto proton1pairCM = boostPairToCM(daughpart1); + auto proton2pairCM = boostPairToCM(daughpart2); - // Boost protons into their respective Lambda rest frames + // Then into each Lambda rest frame auto proton1LambdaRF = boostLambda1ToCM(proton1pairCM); auto proton2LambdaRF = boostLambda2ToCM(proton2pairCM); - // --- STAR-style Δθ (as written: dot product of proton directions in their own Λ RFs) --- - - // Boost each proton into its parent's rest frame - ROOT::Math::Boost boostL1_LabToRF{particle1Dummy.BoostToCM()}; // Λ1 velocity in lab - ROOT::Math::Boost boostL2_LabToRF{particle2Dummy.BoostToCM()}; // Λ2 velocity in lab + // STAR-style alternative + ROOT::Math::Boost boostL1_LabToRF{particle1Dummy.BoostToCM()}; + ROOT::Math::Boost boostL2_LabToRF{particle2Dummy.BoostToCM()}; auto p1_LRF = boostL1_LabToRF(daughpart1); auto p2_LRF = boostL2_LabToRF(daughpart2); - // Unit 3-vectors (in different rest frames!) TVector3 u1 = TVector3(p1_LRF.Px(), p1_LRF.Py(), p1_LRF.Pz()).Unit(); TVector3 u2 = TVector3(p2_LRF.Px(), p2_LRF.Py(), p2_LRF.Pz()).Unit(); - // Proton unit directions in Λ rest frames TVector3 k1(proton1LambdaRF.Px(), proton1LambdaRF.Py(), proton1LambdaRF.Pz()); k1 = k1.Unit(); TVector3 k2(proton2LambdaRF.Px(), proton2LambdaRF.Py(), proton2LambdaRF.Pz()); k2 = k2.Unit(); - // STAR-style cosΔθ definition double cosDeltaTheta_STAR_naive = u1.Dot(u2); if (cosDeltaTheta_STAR_naive > 1.0) cosDeltaTheta_STAR_naive = 111.0; @@ -609,12 +697,7 @@ struct lambdaspincorrderived { if (cosDeltaTheta_hel < -1.0) cosDeltaTheta_hel = -111.0; - auto cosThetaDiff = -999.0; - if (cosDef == 0) { - cosThetaDiff = cosDeltaTheta_STAR_naive; - } else { - cosThetaDiff = cosDeltaTheta_hel; - } + double cosThetaDiff = (cosDef == 0) ? cosDeltaTheta_STAR_naive : cosDeltaTheta_hel; double pt1 = particle1.Pt(); double dphi1 = RecoDecay::constrainAngle(particle1.Phi(), 0.0F, harmonic); @@ -624,9 +707,7 @@ struct lambdaspincorrderived { double dphi2 = RecoDecay::constrainAngle(particle2.Phi(), 0.0F, harmonic); double deta2 = particle2.Eta(); - // double deta_pair = std::abs(deta1 - deta2); double dphi_pair = RecoDecay::constrainAngle(dphi1 - dphi2, -TMath::Pi(), harmonicDphi); - // double deltaR = TMath::Sqrt(deta_pair * deta_pair + dphi_pair * dphi_pair); double deltaRap = std::abs(particle1.Rapidity() - particle2.Rapidity()); double deltaR = TMath::Sqrt(deltaRap * deltaRap + dphi_pair * dphi_pair); @@ -650,89 +731,102 @@ struct lambdaspincorrderived { } if (datatype == 0) { - mixpairweight = 1.0; - histos.fill(HIST("hPtYSame"), particle1.Pt(), particle1.Rapidity(), mixpairweight); + const double weight = 1.0; + if (tag1 == 0 && tag2 == 0) { if (!userapidity) { - histos.fill(HIST("SE_LL"), dphi1, deta1, pt1, mixpairweight); - histos.fill(HIST("SE_LL2"), dphi2, deta2, pt2, mixpairweight); + histos.fill(HIST("hPtYSame"), particle1.Pt(), particle1.Rapidity(), weight); + histos.fill(HIST("SE_LL"), dphi1, deta1, pt1, weight); + histos.fill(HIST("SE_LL2"), dphi2, deta2, pt2, weight); } else { - histos.fill(HIST("SE_LL"), dphi1, particle1.Rapidity(), pt1, mixpairweight); - histos.fill(HIST("SE_LL2"), dphi2, particle2.Rapidity(), pt2, mixpairweight); + histos.fill(HIST("hPtYSame"), particle1.Pt(), particle1.Rapidity(), weight); + histos.fill(HIST("SE_LL"), dphi1, particle1.Rapidity(), pt1, weight); + histos.fill(HIST("SE_LL2"), dphi2, particle2.Rapidity(), pt2, weight); } - histos.fill(HIST("hSparseLambdaLambda"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, mixpairweight); - histos.fill(HIST("hSparseLambdaLambdaAnalysis"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, deltaRap, std::abs(dphi_pair), mixpairweight); + histos.fill(HIST("hSparseLambdaLambda"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, weight); + histos.fill(HIST("hSparseLambdaLambdaAnalysis"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, deltaRap, std::abs(dphi_pair), weight); if (useAdditionalHisto) { - histos.fill(HIST("hSparseRapLambdaLambda"), particle1.M(), particle2.M(), cosThetaDiff, deltaRap, mixpairweight); - histos.fill(HIST("hSparsePhiLambdaLambda"), particle1.M(), particle2.M(), cosThetaDiff, dphi_pair, mixpairweight); - histos.fill(HIST("hSparsePairMassLambdaLambda"), particle1.M(), particle2.M(), cosThetaDiff, pairDummy.M(), mixpairweight); + histos.fill(HIST("hSparseRapLambdaLambda"), particle1.M(), particle2.M(), cosThetaDiff, deltaRap, weight); + histos.fill(HIST("hSparsePhiLambdaLambda"), particle1.M(), particle2.M(), cosThetaDiff, dphi_pair, weight); + histos.fill(HIST("hSparsePairMassLambdaLambda"), particle1.M(), particle2.M(), cosThetaDiff, pairDummy.M(), weight); } } else if (tag1 == 0 && tag2 == 1) { if (!userapidity) { - histos.fill(HIST("SE_LAL"), dphi1, deta1, pt1, mixpairweight); - histos.fill(HIST("SE_LAL2"), dphi2, deta2, pt2, mixpairweight); + histos.fill(HIST("SE_LAL"), dphi1, deta1, pt1, weight); + histos.fill(HIST("SE_LAL2"), dphi2, deta2, pt2, weight); } else { - histos.fill(HIST("SE_LAL"), dphi1, particle1.Rapidity(), pt1, mixpairweight); - histos.fill(HIST("SE_LAL2"), dphi2, particle2.Rapidity(), pt2, mixpairweight); + histos.fill(HIST("SE_LAL"), dphi1, particle1.Rapidity(), pt1, weight); + histos.fill(HIST("SE_LAL2"), dphi2, particle2.Rapidity(), pt2, weight); } - histos.fill(HIST("hSparseLambdaAntiLambda"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, mixpairweight); - histos.fill(HIST("hSparseLambdaAntiLambdaAnalysis"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, deltaRap, std::abs(dphi_pair), mixpairweight); + histos.fill(HIST("hSparseLambdaAntiLambda"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, weight); + histos.fill(HIST("hSparseLambdaAntiLambdaAnalysis"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, deltaRap, std::abs(dphi_pair), weight); if (useAdditionalHisto) { - histos.fill(HIST("hSparseRapLambdaAntiLambda"), particle1.M(), particle2.M(), cosThetaDiff, deltaRap, mixpairweight); - histos.fill(HIST("hSparsePhiLambdaAntiLambda"), particle1.M(), particle2.M(), cosThetaDiff, dphi_pair, mixpairweight); - histos.fill(HIST("hSparsePairMassLambdaAntiLambda"), particle1.M(), particle2.M(), cosThetaDiff, pairDummy.M(), mixpairweight); + histos.fill(HIST("hSparseRapLambdaAntiLambda"), particle1.M(), particle2.M(), cosThetaDiff, deltaRap, weight); + histos.fill(HIST("hSparsePhiLambdaAntiLambda"), particle1.M(), particle2.M(), cosThetaDiff, dphi_pair, weight); + histos.fill(HIST("hSparsePairMassLambdaAntiLambda"), particle1.M(), particle2.M(), cosThetaDiff, pairDummy.M(), weight); } } else if (tag1 == 1 && tag2 == 0) { - histos.fill(HIST("hSparseAntiLambdaLambda"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, mixpairweight); - histos.fill(HIST("hSparseAntiLambdaLambdaAnalysis"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, deltaRap, std::abs(dphi_pair), mixpairweight); if (!userapidity) { - histos.fill(HIST("SE_ALL"), dphi1, deta1, pt1, mixpairweight); - histos.fill(HIST("SE_ALL2"), dphi2, deta2, pt2, mixpairweight); + histos.fill(HIST("SE_ALL"), dphi1, deta1, pt1, weight); + histos.fill(HIST("SE_ALL2"), dphi2, deta2, pt2, weight); } else { - histos.fill(HIST("SE_ALL"), dphi1, particle1.Rapidity(), pt1, mixpairweight); - histos.fill(HIST("SE_ALL2"), dphi2, particle2.Rapidity(), pt2, mixpairweight); + histos.fill(HIST("SE_ALL"), dphi1, particle1.Rapidity(), pt1, weight); + histos.fill(HIST("SE_ALL2"), dphi2, particle2.Rapidity(), pt2, weight); } + histos.fill(HIST("hSparseAntiLambdaLambda"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, weight); + histos.fill(HIST("hSparseAntiLambdaLambdaAnalysis"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, deltaRap, std::abs(dphi_pair), weight); if (useAdditionalHisto) { - histos.fill(HIST("hSparseRapAntiLambdaLambda"), particle1.M(), particle2.M(), cosThetaDiff, deltaRap, mixpairweight); - histos.fill(HIST("hSparsePhiAntiLambdaLambda"), particle1.M(), particle2.M(), cosThetaDiff, dphi_pair, mixpairweight); - histos.fill(HIST("hSparsePairMassAntiLambdaLambda"), particle1.M(), particle2.M(), cosThetaDiff, pairDummy.M(), mixpairweight); + histos.fill(HIST("hSparseRapAntiLambdaLambda"), particle1.M(), particle2.M(), cosThetaDiff, deltaRap, weight); + histos.fill(HIST("hSparsePhiAntiLambdaLambda"), particle1.M(), particle2.M(), cosThetaDiff, dphi_pair, weight); + histos.fill(HIST("hSparsePairMassAntiLambdaLambda"), particle1.M(), particle2.M(), cosThetaDiff, pairDummy.M(), weight); } } else if (tag1 == 1 && tag2 == 1) { - histos.fill(HIST("hSparseAntiLambdaAntiLambda"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, mixpairweight); - histos.fill(HIST("hSparseAntiLambdaAntiLambdaAnalysis"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, deltaRap, std::abs(dphi_pair), mixpairweight); if (!userapidity) { - histos.fill(HIST("SE_ALAL"), dphi1, deta1, pt1, mixpairweight); - histos.fill(HIST("SE_ALAL2"), dphi2, deta2, pt2, mixpairweight); + histos.fill(HIST("SE_ALAL"), dphi1, deta1, pt1, weight); + histos.fill(HIST("SE_ALAL2"), dphi2, deta2, pt2, weight); } else { - histos.fill(HIST("SE_ALAL"), dphi1, particle1.Rapidity(), pt1, mixpairweight); - histos.fill(HIST("SE_ALAL2"), dphi2, particle2.Rapidity(), pt2, mixpairweight); + histos.fill(HIST("SE_ALAL"), dphi1, particle1.Rapidity(), pt1, weight); + histos.fill(HIST("SE_ALAL2"), dphi2, particle2.Rapidity(), pt2, weight); } + histos.fill(HIST("hSparseAntiLambdaAntiLambda"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, weight); + histos.fill(HIST("hSparseAntiLambdaAntiLambdaAnalysis"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, deltaRap, std::abs(dphi_pair), weight); if (useAdditionalHisto) { - histos.fill(HIST("hSparseRapAntiLambdaAntiLambda"), particle1.M(), particle2.M(), cosThetaDiff, deltaRap, mixpairweight); - histos.fill(HIST("hSparsePhiAntiLambdaAntiLambda"), particle1.M(), particle2.M(), cosThetaDiff, dphi_pair, mixpairweight); - histos.fill(HIST("hSparsePairMassAntiLambdaAntiLambda"), particle1.M(), particle2.M(), cosThetaDiff, pairDummy.M(), mixpairweight); + histos.fill(HIST("hSparseRapAntiLambdaAntiLambda"), particle1.M(), particle2.M(), cosThetaDiff, deltaRap, weight); + histos.fill(HIST("hSparsePhiAntiLambdaAntiLambda"), particle1.M(), particle2.M(), cosThetaDiff, dphi_pair, weight); + histos.fill(HIST("hSparsePairMassAntiLambdaAntiLambda"), particle1.M(), particle2.M(), cosThetaDiff, pairDummy.M(), weight); } } + } else if (datatype == 1) { double weight = mixpairweight; + if (useweight) { - if (usebothweight) { - weight = mixpairweight / (epsWeight1 * epsWeight2); - } else { - weight = mixpairweight / (epsWeight1); + const double epsWeightReplaced = (replacedLeg == 2) ? epsWeight2 : epsWeight1; + if (!std::isfinite(epsWeightReplaced) || epsWeightReplaced <= 0.0) { + return; } + weight = mixpairweight / epsWeightReplaced; } - if (weight <= 0.0) { - weight = 1.0; + + if (!std::isfinite(weight) || weight <= 0.0) { + return; } - histos.fill(HIST("hPtYMix"), particle1.Pt(), particle1.Rapidity(), weight); + if (tag1 == 0 && tag2 == 0) { - if (!userapidity) { - histos.fill(HIST("ME_LL"), dphi1, deta1, pt1, mixpairweight); - histos.fill(HIST("ME_LL2"), dphi2, deta2, pt2, mixpairweight); + if (replacedLeg == 1) { + if (!userapidity) { + histos.fill(HIST("hPtYMix"), particle1.Pt(), particle1.Rapidity(), weight); + histos.fill(HIST("ME_LL"), dphi1, deta1, pt1, weight); + } else { + histos.fill(HIST("hPtYMix"), particle1.Pt(), particle1.Rapidity(), weight); + histos.fill(HIST("ME_LL"), dphi1, particle1.Rapidity(), pt1, weight); + } } else { - histos.fill(HIST("ME_LL"), dphi1, particle1.Rapidity(), pt1, mixpairweight); - histos.fill(HIST("ME_LL2"), dphi2, particle2.Rapidity(), pt2, mixpairweight); + if (!userapidity) { + histos.fill(HIST("ME_LL2"), dphi2, deta2, pt2, weight); + } else { + histos.fill(HIST("ME_LL2"), dphi2, particle2.Rapidity(), pt2, weight); + } } histos.fill(HIST("hSparseLambdaLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, weight); histos.fill(HIST("hSparseLambdaLambdaMixedAnalysis"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, deltaRap, std::abs(dphi_pair), weight); @@ -741,13 +835,20 @@ struct lambdaspincorrderived { histos.fill(HIST("hSparsePhiLambdaLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, dphi_pair, weight); histos.fill(HIST("hSparsePairMassLambdaLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, pairDummy.M(), weight); } + } else if (tag1 == 0 && tag2 == 1) { - if (!userapidity) { - histos.fill(HIST("ME_LAL"), dphi1, deta1, pt1, mixpairweight); - histos.fill(HIST("ME_LAL2"), dphi2, deta2, pt2, mixpairweight); + if (replacedLeg == 1) { + if (!userapidity) { + histos.fill(HIST("ME_LAL"), dphi1, deta1, pt1, weight); + } else { + histos.fill(HIST("ME_LAL"), dphi1, particle1.Rapidity(), pt1, weight); + } } else { - histos.fill(HIST("ME_LAL"), dphi1, particle1.Rapidity(), pt1, mixpairweight); - histos.fill(HIST("ME_LAL2"), dphi2, particle2.Rapidity(), pt2, mixpairweight); + if (!userapidity) { + histos.fill(HIST("ME_LAL2"), dphi2, deta2, pt2, weight); + } else { + histos.fill(HIST("ME_LAL2"), dphi2, particle2.Rapidity(), pt2, weight); + } } histos.fill(HIST("hSparseLambdaAntiLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, weight); histos.fill(HIST("hSparseLambdaAntiLambdaMixedAnalysis"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, deltaRap, std::abs(dphi_pair), weight); @@ -756,13 +857,20 @@ struct lambdaspincorrderived { histos.fill(HIST("hSparsePhiLambdaAntiLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, dphi_pair, weight); histos.fill(HIST("hSparsePairMassLambdaAntiLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, pairDummy.M(), weight); } + } else if (tag1 == 1 && tag2 == 0) { - if (!userapidity) { - histos.fill(HIST("ME_ALL"), dphi1, deta1, pt1, mixpairweight); - histos.fill(HIST("ME_ALL2"), dphi2, deta2, pt2, mixpairweight); + if (replacedLeg == 1) { + if (!userapidity) { + histos.fill(HIST("ME_ALL"), dphi1, deta1, pt1, weight); + } else { + histos.fill(HIST("ME_ALL"), dphi1, particle1.Rapidity(), pt1, weight); + } } else { - histos.fill(HIST("ME_ALL"), dphi1, particle1.Rapidity(), pt1, mixpairweight); - histos.fill(HIST("ME_ALL2"), dphi2, particle2.Rapidity(), pt2, mixpairweight); + if (!userapidity) { + histos.fill(HIST("ME_ALL2"), dphi2, deta2, pt2, weight); + } else { + histos.fill(HIST("ME_ALL2"), dphi2, particle2.Rapidity(), pt2, weight); + } } histos.fill(HIST("hSparseAntiLambdaLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, weight); histos.fill(HIST("hSparseAntiLambdaLambdaMixedAnalysis"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, deltaRap, std::abs(dphi_pair), weight); @@ -771,13 +879,20 @@ struct lambdaspincorrderived { histos.fill(HIST("hSparsePhiAntiLambdaLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, dphi_pair, weight); histos.fill(HIST("hSparsePairMassAntiLambdaLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, pairDummy.M(), weight); } + } else if (tag1 == 1 && tag2 == 1) { - if (!userapidity) { - histos.fill(HIST("ME_ALAL"), dphi1, deta1, pt1, mixpairweight); - histos.fill(HIST("ME_ALAL2"), dphi2, deta2, pt2, mixpairweight); + if (replacedLeg == 1) { + if (!userapidity) { + histos.fill(HIST("ME_ALAL"), dphi1, deta1, pt1, weight); + } else { + histos.fill(HIST("ME_ALAL"), dphi1, particle1.Rapidity(), pt1, weight); + } } else { - histos.fill(HIST("ME_ALAL"), dphi1, particle1.Rapidity(), pt1, mixpairweight); - histos.fill(HIST("ME_ALAL2"), dphi2, particle2.Rapidity(), pt2, mixpairweight); + if (!userapidity) { + histos.fill(HIST("ME_ALAL2"), dphi2, deta2, pt2, weight); + } else { + histos.fill(HIST("ME_ALAL2"), dphi2, particle2.Rapidity(), pt2, weight); + } } histos.fill(HIST("hSparseAntiLambdaAntiLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, weight); histos.fill(HIST("hSparseAntiLambdaAntiLambdaMixedAnalysis"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, deltaRap, std::abs(dphi_pair), weight); @@ -789,7 +904,6 @@ struct lambdaspincorrderived { } } } - static inline int pairTypeCode(int tag1, int tag2) { if (tag1 == 0 && tag2 == 0) { @@ -802,6 +916,7 @@ struct lambdaspincorrderived { return 3; // ALAL } } + ROOT::Math::PtEtaPhiMVector lambda0, proton0; ROOT::Math::PtEtaPhiMVector lambda, proton; ROOT::Math::PtEtaPhiMVector lambda2, proton2; @@ -878,220 +993,191 @@ struct lambdaspincorrderived { for (auto& collision1 : collisions) { const int bin = colBinning.getBin(std::make_tuple(collision1.posz(), collision1.cent())); + if (bin < 0) { + continue; + } + + auto poolA = V0s.sliceBy(tracksPerCollisionV0, collision1.index()); // if pool empty, push and continue if (eventPools[bin].empty()) { - auto sliced = V0s.sliceBy(tracksPerCollisionV0, collision1.index()); - eventPools[bin].emplace_back(collision1.index(), std::move(sliced)); - if ((int)eventPools[bin].size() > nEvtMixing) + eventPools[bin].emplace_back(collision1.index(), std::move(poolA)); + if ((int)eventPools[bin].size() > nEvtMixing) { eventPools[bin].pop_front(); + } continue; } - // current event slice - auto poolA = V0s.sliceBy(tracksPerCollisionV0, collision1.index()); - - // loop over SE unordered pairs (t1,t2) for (auto& [t1, t2] : soa::combinations(o2::soa::CombinationsFullIndexPolicy(poolA, poolA))) { - if (!selectionV0(t1) || !selectionV0(t2)) + if (!selectionV0(t1) || !selectionV0(t2)) { continue; - if (t2.index() <= t1.index()) + } + if (t2.index() <= t1.index()) { continue; - if (t1.protonIndex() == t2.protonIndex()) + } + + if (t1.protonIndex() == t2.protonIndex()) { continue; - if (t1.pionIndex() == t2.pionIndex()) + } + if (t1.pionIndex() == t2.pionIndex()) { continue; - if (t1.protonIndex() == t2.pionIndex()) + } + if (t1.protonIndex() == t2.pionIndex()) { continue; - if (t1.pionIndex() == t2.protonIndex()) + } + if (t1.pionIndex() == t2.protonIndex()) { continue; + } + + const bool doMixLeg1 = (cfgMixLegMode.value == 0 || cfgMixLegMode.value == 2); + const bool doMixLeg2 = (cfgMixLegMode.value == 1 || cfgMixLegMode.value == 2); - // scan prior events for replacements for t1 struct PV { AllTrackCandidates* pool; - int nRepl; + int nRepl1 = 0; + int nRepl2 = 0; }; + std::vector usable; int totalRepl = 0; int mixes = 0; - for (auto it = eventPools[bin].rbegin(); - it != eventPools[bin].rend() && mixes < nEvtMixing; ++it, ++mixes) { + for (auto it = eventPools[bin].rbegin(); it != eventPools[bin].rend() && mixes < nEvtMixing; ++it, ++mixes) { const int collision2idx = it->first; auto& poolB = it->second; - if (collision2idx == collision1.index()) + + if (collision2idx == collision1.index()) { continue; + } + + int nRepl1 = 0; + int nRepl2 = 0; - int nRepl = 0; for (auto& tX : poolB) { - if (!selectionV0(tX)) + if (!selectionV0(tX)) { continue; - if (checkKinematics(t1, tX)) - ++nRepl; + } + + if (doMixLeg1) { + if (checkKinematics(t1, tX) && checkPairKinematics(t1, t2, tX)) { + ++nRepl1; + } + } + + if (doMixLeg2) { + if (checkKinematics(t2, tX) && checkPairKinematics(t2, t1, tX)) { + ++nRepl2; + } + } } - if (nRepl > 0) { - usable.push_back(PV{&poolB, nRepl}); - totalRepl += nRepl; + + if (nRepl1 > 0 || nRepl2 > 0) { + usable.push_back(PV{&poolB, nRepl1, nRepl2}); + totalRepl += nRepl1 + nRepl2; } } - if (totalRepl == 0) + if (totalRepl <= 0) { continue; + } + const float wBase = 1.0f / static_cast(totalRepl); - // emit mixed pairs: tX replaces t1; t2 stays for (auto& pv : usable) { auto& poolB = *pv.pool; + for (auto& tX : poolB) { - if (!selectionV0(tX)) - continue; - if (!checkKinematics(t1, tX)) + if (!selectionV0(tX)) { continue; + } - auto proton = ROOT::Math::PtEtaPhiMVector(tX.protonPt(), tX.protonEta(), tX.protonPhi(), o2::constants::physics::MassProton); - auto lambda = ROOT::Math::PtEtaPhiMVector(tX.lambdaPt(), tX.lambdaEta(), tX.lambdaPhi(), tX.lambdaMass()); - auto proton2 = ROOT::Math::PtEtaPhiMVector(t2.protonPt(), t2.protonEta(), t2.protonPhi(), o2::constants::physics::MassProton); - auto lambda2 = ROOT::Math::PtEtaPhiMVector(t2.lambdaPt(), t2.lambdaEta(), t2.lambdaPhi(), t2.lambdaMass()); + // -------- leg-1 replacement: (tX, t2) + if (doMixLeg1) { + if (checkKinematics(t1, tX) && checkPairKinematics(t1, t2, tX)) { + auto proton = ROOT::Math::PtEtaPhiMVector(tX.protonPt(), tX.protonEta(), tX.protonPhi(), + o2::constants::physics::MassProton); + auto lambda = ROOT::Math::PtEtaPhiMVector(tX.lambdaPt(), tX.lambdaEta(), tX.lambdaPhi(), + tX.lambdaMass()); + auto proton2 = ROOT::Math::PtEtaPhiMVector(t2.protonPt(), t2.protonEta(), t2.protonPhi(), + o2::constants::physics::MassProton); + auto lambda2 = ROOT::Math::PtEtaPhiMVector(t2.lambdaPt(), t2.lambdaEta(), t2.lambdaPhi(), + t2.lambdaMass()); + + const float dPhi = RecoDecay::constrainAngle( + RecoDecay::constrainAngle(lambda.Phi(), 0.0F, harmonic) - + RecoDecay::constrainAngle(lambda2.Phi(), 0.0F, harmonic), + -TMath::Pi(), harmonicDphi); + + histos.fill(HIST("deltaPhiMix"), dPhi, wBase); + fillHistograms(tX.v0Status(), t2.v0Status(), + lambda, lambda2, proton, proton2, + 1, wBase, 1); + } + } - const float dPhi = RecoDecay::constrainAngle(RecoDecay::constrainAngle(lambda.Phi(), 0.0F, harmonic) - RecoDecay::constrainAngle(lambda2.Phi(), 0.0F, harmonic), -TMath::Pi(), harmonicDphi); - histos.fill(HIST("deltaPhiMix"), dPhi, wBase); - fillHistograms(tX.v0Status(), t2.v0Status(), lambda, lambda2, proton, proton2, 1, wBase); + // -------- leg-2 replacement: (t1, tX) + if (doMixLeg2) { + if (checkKinematics(t2, tX) && checkPairKinematics(t2, t1, tX)) { + auto proton = ROOT::Math::PtEtaPhiMVector(t1.protonPt(), t1.protonEta(), t1.protonPhi(), + o2::constants::physics::MassProton); + auto lambda = ROOT::Math::PtEtaPhiMVector(t1.lambdaPt(), t1.lambdaEta(), t1.lambdaPhi(), + t1.lambdaMass()); + auto proton2 = ROOT::Math::PtEtaPhiMVector(tX.protonPt(), tX.protonEta(), tX.protonPhi(), + o2::constants::physics::MassProton); + auto lambda2 = ROOT::Math::PtEtaPhiMVector(tX.lambdaPt(), tX.lambdaEta(), tX.lambdaPhi(), + tX.lambdaMass()); + + const float dPhi = RecoDecay::constrainAngle( + RecoDecay::constrainAngle(lambda.Phi(), 0.0F, harmonic) - + RecoDecay::constrainAngle(lambda2.Phi(), 0.0F, harmonic), + -TMath::Pi(), harmonicDphi); + + histos.fill(HIST("deltaPhiMix"), dPhi, wBase); + fillHistograms(t1.v0Status(), tX.v0Status(), + lambda, lambda2, proton, proton2, + 1, wBase, 2); + } + } } } } + // push current event into pool auto sliced = V0s.sliceBy(tracksPerCollisionV0, collision1.index()); eventPools[bin].emplace_back(collision1.index(), std::move(sliced)); - if ((int)eventPools[bin].size() > nEvtMixing) + if ((int)eventPools[bin].size() > nEvtMixing) { eventPools[bin].pop_front(); + } } } PROCESS_SWITCH(lambdaspincorrderived, processMEV3, "Process data ME (first-leg, pair-3D maps)", false); static constexpr int N_STATUS = 2; // v0Status ∈ {0,1} - - struct MixBinner { - // constructed from the task's configurables; φ is assumed already constrained upstream - float ptMin, ptMax, ptStep; - float etaMin, etaMax, etaStep; - float phiMin, phiMax, phiStep; - - // configurable fixed mass-binning for mixing buffer - float mMin, mMax, mStep; - int nM_; - - int nPt_, nEta_, nPhi_; - - MixBinner(float ptMin_, float ptMax_, float ptStep_, - float etaAbsMax, float etaStep_, - float phiStep_, - float mMin_, float mMax_, int nMassBins_) - : ptMin(ptMin_), - ptMax(ptMax_), - ptStep(ptStep_), - etaMin(-etaAbsMax), - etaMax(+etaAbsMax), - etaStep(etaStep_), - phiMin(-static_cast(TMath::Pi())), - phiMax(+static_cast(TMath::Pi())), - phiStep(phiStep_), - mMin(mMin_), - mMax(mMax_), - mStep(0.f), - nM_(std::max(1, nMassBins_)), - nPt_(0), - nEta_(0), - nPhi_(0) - // If you want phi in [0, 2pi), use: - // : ... phiMin(0.f), phiMax(static_cast(2.0 * TMath::Pi())), ... - { - ptStep = (ptStep > 0.f ? ptStep : 0.1f); - etaStep = (etaStep > 0.f ? etaStep : 0.1f); - phiStep = (phiStep > 0.f ? phiStep : 0.1f); - - if (!(mMax > mMin)) { - mMin = 1.09f; - mMax = 1.14f; - } - mStep = (mMax - mMin) / static_cast(nM_); - - nPt_ = std::max(1, static_cast(std::floor((ptMax - ptMin) / ptStep + 0.5f))); - nEta_ = std::max(1, static_cast(std::floor((etaMax - etaMin) / etaStep + 0.5f))); - nPhi_ = std::max(1, static_cast(std::ceil((phiMax - phiMin) / phiStep))); - } - - inline int nPt() const { return nPt_; } - inline int nEta() const { return nEta_; } - inline int nPhi() const { return nPhi_; } - inline int nM() const { return nM_; } - - inline int binFromValue(float v, float vmin, float step, int nBins) const - { - if (!std::isfinite(v) || !std::isfinite(vmin) || !std::isfinite(step) || step <= 0.f || nBins <= 0) { - return -1; - } - const float x = (v - vmin) / step; - int b = static_cast(std::floor(x + 1e-6f)); - if (b < 0) { - return -1; - } - if (b >= nBins) { - b = nBins - 1; // clamp exact-top edge - } - return b; - } - - inline int ptBin(float pt) const { return binFromValue(pt, ptMin, ptStep, nPt_); } - inline int etaBin(float eta) const { return binFromValue(eta, etaMin, etaStep, nEta_); } - inline int phiBin(float phi) const { return binFromValue(phi, phiMin, phiStep, nPhi_); } // φ already constrained upstream - inline int massBin(float m) const { return binFromValue(m, mMin, mStep, nM_); } - }; - - struct BufferCand { - int64_t collisionIdx; // from col.index() - int64_t rowIndex; // global row id in V0s - uint8_t v0Status; - uint16_t ptBin, etaBin, phiBin, mBin; - }; - struct MatchRef { int64_t collisionIdx; int64_t rowIndex; }; - // 6D key: (colBin, status, pt, eta, phi, mass) - static inline size_t linearKey(int colBin, int statBin, - int ptBin, int etaBin, int phiBin, int mBin, - int nStatus, int nPt, int nEta, int nPhi, int nM) + static inline void limitMatchesToNEvents(std::vector& matches, int nMixEvents) { - return ((((((static_cast(colBin) * nStatus + statBin) * nPt + ptBin) * nEta + etaBin) * nPhi + phiBin) * nM + mBin)); - } + if (nMixEvents <= 0 || matches.empty()) { + return; + } - static inline void collectPhiNeighborBins(int phiB, int nPhi, int nNeighbor, std::vector& out) - { - out.clear(); - out.reserve(2 * nNeighbor + 1); - for (int d = -nNeighbor; d <= nNeighbor; ++d) { - int b = phiB + d; - // wrap into [0, nPhi-1] - b %= nPhi; - if (b < 0) - b += nPhi; - out.push_back(b); - } - // optional: unique (in case nNeighbor >= nPhi) - std::sort(out.begin(), out.end()); - out.erase(std::unique(out.begin(), out.end()), out.end()); - } + std::vector kept; + kept.reserve(matches.size()); - static inline std::vector makeRadiusEdges(const ConfigurableAxis& ax) - { - std::vector edges; - edges.reserve(ax.value.size()); - for (auto v : ax.value) { - edges.push_back(static_cast(v)); + std::unordered_set usedEvents; + usedEvents.reserve(nMixEvents * 2); + + for (const auto& m : matches) { + if (usedEvents.count(m.collisionIdx) || (int)usedEvents.size() < nMixEvents) { + kept.push_back(m); + usedEvents.insert(m.collisionIdx); + } } - return edges; + + matches.swap(kept); } struct MixBinnerR { @@ -1211,170 +1297,11 @@ struct lambdaspincorrderived { return (((((((static_cast(colBin) * nStatus + statBin) * nPt + ptBin) * nEta + etaBin) * nPhi + phiBin) * nM + mBin) * nR + rBin)); } - // ===================== Main mixing (with mass-bin + random unique sampling) ===================== - void processMEV4(EventCandidates const& collisions, AllTrackCandidates const& V0s) - { - MixBinner mb{ - ptMin.value, ptMax.value, ptMix.value, - v0etaMixBuffer.value, etaMix.value, - phiMix.value, - MassMin.value, MassMax.value, cfgV5MassBins.value}; - - const int nCol = colBinning.getAllBinsCount(); // event-class bins (vz, centrality) - const int nStat = N_STATUS; // 2 - const int nPt = mb.nPt(); - const int nEta = mb.nEta(); - const int nPhi = mb.nPhi(); - const int nM = mb.nM(); - - const size_t nKeys = static_cast(nCol) * nStat * nPt * nEta * nPhi * nM; - std::vector> buffer(nKeys); - - // ---- PASS 1: fill 6D buffer ---- - for (auto const& col : collisions) { - const int colBin = colBinning.getBin(std::make_tuple(col.posz(), col.cent())); - auto slice = V0s.sliceBy(tracksPerCollisionV0, col.index()); - - for (auto const& t : slice) { - if (!selectionV0(t)) - continue; - - const int status = static_cast(t.v0Status()); - if (status < 0 || status >= nStat) - continue; - - // Bin kinematics (φ already constrained via your call-site) - const int ptB = mb.ptBin(t.lambdaPt()); - const int etaB = mb.etaBin(t.lambdaEta()); - const int phiB = mb.phiBin(RecoDecay::constrainAngle(t.lambdaPhi(), -TMath::Pi(), harmonic)); - const int mB = mb.massBin(t.lambdaMass()); - if (ptB < 0 || etaB < 0 || phiB < 0 || mB < 0) - continue; - - const size_t key = linearKey(colBin, status, ptB, etaB, phiB, mB, - nStat, nPt, nEta, nPhi, nM); - - buffer[key].push_back(BufferCand{ - .collisionIdx = static_cast(col.index()), - .rowIndex = static_cast(t.globalIndex()), - .v0Status = static_cast(status), - .ptBin = static_cast(ptB), - .etaBin = static_cast(etaB), - .phiBin = static_cast(phiB), - .mBin = static_cast(mB)}); - } - } - - // ---- PASS 2: mixing over same-event pairs ---- - for (auto const& collision1 : collisions) { - const int colBin = colBinning.getBin(std::make_tuple(collision1.posz(), collision1.cent())); - auto poolA = V0s.sliceBy(tracksPerCollisionV0, collision1.index()); - - for (auto const& [t1, t2] : - soa::combinations(o2::soa::CombinationsFullIndexPolicy(poolA, poolA))) { - - if (!selectionV0(t1) || !selectionV0(t2)) - continue; - if (t2.index() <= t1.index()) - continue; - - // no shared daughters - if (t1.protonIndex() == t2.protonIndex()) - continue; - if (t1.pionIndex() == t2.pionIndex()) - continue; - if (t1.protonIndex() == t2.pionIndex()) - continue; - if (t1.pionIndex() == t2.protonIndex()) - continue; - - const int status = static_cast(t1.v0Status()); - if (status < 0 || status >= nStat) - continue; - - // Bin of t1 defines where to search (exact bin, but handle φ wrap at edges) - const int ptB = mb.ptBin(t1.lambdaPt()); - const int etaB = mb.etaBin(t1.lambdaEta()); - const int phiB = mb.phiBin(RecoDecay::constrainAngle(t1.lambdaPhi(), -TMath::Pi(), harmonic)); - const int mB = mb.massBin(t1.lambdaMass()); - if (ptB < 0 || etaB < 0 || phiB < 0 || mB < 0) - continue; - - // Collect partners from nominal key, plus wrapped neighbor only for φ-edge bins - std::vector matches; - matches.reserve(128); // or keep binVec.size() if you prefer - const int64_t curColIdx = static_cast(collision1.index()); - - auto collectFrom = [&](int phiBinUse) { - const size_t keyUse = linearKey(colBin, status, ptB, etaB, phiBinUse, mB, - nStat, nPt, nEta, nPhi, nM); - auto const& vec = buffer[keyUse]; - for (const auto& bc : vec) { - if (bc.collisionIdx == curColIdx) { - continue; // must be from different event - } - auto tX = V0s.iteratorAt(static_cast(bc.rowIndex)); - if (!selectionV0(tX)) { - continue; - } - if (!checkKinematics(t1, tX)) { - continue; - } - if (!checkPairKinematics(t1, t2, tX)) { - continue; - } - matches.push_back(MatchRef{bc.collisionIdx, bc.rowIndex}); - } - }; - // 1) nominal φ-bin - collectFrom(phiB); - - // 2) wrap only at boundaries: 0 <-> nPhi-1 - if (phiB == 0) { - collectFrom(nPhi - 1); - } else if (phiB == nPhi - 1) { - collectFrom(0); - } - - if (matches.empty()) { - continue; - } - - // Optional safety: dedupe exact same (collision,row) just in case - std::sort(matches.begin(), matches.end(), - [](auto& a, auto& b) { return std::tie(a.collisionIdx, a.rowIndex) < std::tie(b.collisionIdx, b.rowIndex); }); - matches.erase(std::unique(matches.begin(), matches.end(), - [](auto& a, auto& b) { return a.collisionIdx == b.collisionIdx && a.rowIndex == b.rowIndex; }), - matches.end()); - if (matches.empty()) { - continue; - } - const float wBase = 1.0f / static_cast(matches.size()); - for (const auto& m : matches) { - auto tX = V0s.iteratorAt(static_cast(m.rowIndex)); - - auto proton = ROOT::Math::PtEtaPhiMVector(tX.protonPt(), tX.protonEta(), tX.protonPhi(), o2::constants::physics::MassProton); - auto lambda = ROOT::Math::PtEtaPhiMVector(tX.lambdaPt(), tX.lambdaEta(), tX.lambdaPhi(), tX.lambdaMass()); - auto proton2 = ROOT::Math::PtEtaPhiMVector(t2.protonPt(), t2.protonEta(), t2.protonPhi(), o2::constants::physics::MassProton); - auto lambda2 = ROOT::Math::PtEtaPhiMVector(t2.lambdaPt(), t2.lambdaEta(), t2.lambdaPhi(), t2.lambdaMass()); - - const float dPhi = RecoDecay::constrainAngle( - RecoDecay::constrainAngle(lambda.Phi(), 0.0F, harmonic) - RecoDecay::constrainAngle(lambda2.Phi(), 0.0F, harmonic), - -TMath::Pi(), harmonicDphi); - - histos.fill(HIST("deltaPhiMix"), dPhi, wBase); - fillHistograms(tX.v0Status(), t2.v0Status(), lambda, lambda2, proton, proton2, 1, wBase); - } - } - } - } - PROCESS_SWITCH(lambdaspincorrderived, processMEV4, "Process data ME (5d buffer)", false); - - // ------------------------------------- - // 2) MC-only selection + kinematics cuts - // ------------------------------------- - template - bool selectionV0MC(T const& candidate) + // ------------------------------------- + // 2) MC-only selection + kinematics cuts + // ------------------------------------- + template + bool selectionV0MC(T const& candidate) { auto particle = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(candidate), mcacc::lamEta(candidate), @@ -1532,6 +1459,169 @@ struct lambdaspincorrderived { } PROCESS_SWITCH(lambdaspincorrderived, processMC, "Process MC (SE)", false); + void processMCMEV3(EventCandidatesMC const& collisions, AllTrackCandidatesMC const& V0sMC) + { + auto nBins = colBinning.getAllBinsCount(); + std::vector>> eventPools(nBins); + + for (auto& collision1 : collisions) { + const int bin = colBinning.getBin(std::make_tuple(mcacc::posz(collision1), mcacc::cent(collision1))); + if (bin < 0) { + continue; + } + + auto poolA = V0sMC.sliceBy(tracksPerCollisionV0mc, collision1.index()); + + if (eventPools[bin].empty()) { + eventPools[bin].emplace_back(collision1.index(), std::move(poolA)); + if ((int)eventPools[bin].size() > nEvtMixing) { + eventPools[bin].pop_front(); + } + continue; + } + + for (auto& [t1, t2] : soa::combinations(o2::soa::CombinationsFullIndexPolicy(poolA, poolA))) { + if (!selectionV0MC(t1) || !selectionV0MC(t2)) { + continue; + } + if (t2.index() <= t1.index()) { + continue; + } + + if (mcacc::prIdx(t1) == mcacc::prIdx(t2)) { + continue; + } + if (mcacc::piIdx(t1) == mcacc::piIdx(t2)) { + continue; + } + if (mcacc::prIdx(t1) == mcacc::piIdx(t2)) { + continue; + } + if (mcacc::piIdx(t1) == mcacc::prIdx(t2)) { + continue; + } + + const bool doMixLeg1 = (cfgMixLegMode.value == 0 || cfgMixLegMode.value == 2); + const bool doMixLeg2 = (cfgMixLegMode.value == 1 || cfgMixLegMode.value == 2); + + struct PV { + AllTrackCandidatesMC* pool; + int nRepl1 = 0; + int nRepl2 = 0; + }; + + std::vector usable; + int totalRepl = 0; + + int mixes = 0; + for (auto it = eventPools[bin].rbegin(); it != eventPools[bin].rend() && mixes < nEvtMixing; ++it, ++mixes) { + const int collision2idx = it->first; + auto& poolB = it->second; + + if (collision2idx == collision1.index()) { + continue; + } + + int nRepl1 = 0; + int nRepl2 = 0; + + for (auto& tX : poolB) { + if (!selectionV0MC(tX)) { + continue; + } + + if (doMixLeg1) { + if (checkKinematicsMC(t1, tX) && checkPairKinematicsMC(t1, t2, tX)) { + ++nRepl1; + } + } + + if (doMixLeg2) { + if (checkKinematicsMC(t2, tX) && checkPairKinematicsMC(t2, t1, tX)) { + ++nRepl2; + } + } + } + + if (nRepl1 > 0 || nRepl2 > 0) { + usable.push_back(PV{&poolB, nRepl1, nRepl2}); + totalRepl += nRepl1 + nRepl2; + } + } + + if (totalRepl <= 0) { + continue; + } + + const float wBase = 1.0f / static_cast(totalRepl); + + for (auto& pv : usable) { + auto& poolB = *pv.pool; + + for (auto& tX : poolB) { + if (!selectionV0MC(tX)) { + continue; + } + + // -------- leg-1 replacement: (tX, t2) + if (doMixLeg1) { + if (checkKinematicsMC(t1, tX) && checkPairKinematicsMC(t1, t2, tX)) { + auto pX = ROOT::Math::PtEtaPhiMVector(mcacc::prPt(tX), mcacc::prEta(tX), mcacc::prPhi(tX), + o2::constants::physics::MassProton); + auto lX = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(tX), mcacc::lamEta(tX), mcacc::lamPhi(tX), + mcacc::lamMass(tX)); + auto p2 = ROOT::Math::PtEtaPhiMVector(mcacc::prPt(t2), mcacc::prEta(t2), mcacc::prPhi(t2), + o2::constants::physics::MassProton); + auto l2 = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(t2), mcacc::lamEta(t2), mcacc::lamPhi(t2), + mcacc::lamMass(t2)); + + const float dPhi = RecoDecay::constrainAngle( + RecoDecay::constrainAngle(lX.Phi(), 0.0F, harmonic) - + RecoDecay::constrainAngle(l2.Phi(), 0.0F, harmonic), + -TMath::Pi(), harmonicDphi); + + histos.fill(HIST("deltaPhiMix"), dPhi, wBase); + fillHistograms(mcacc::v0Status(tX), mcacc::v0Status(t2), + lX, l2, pX, p2, + 1, wBase, 1); + } + } + + // -------- leg-2 replacement: (t1, tX) + if (doMixLeg2) { + if (checkKinematicsMC(t2, tX) && checkPairKinematicsMC(t2, t1, tX)) { + auto p1 = ROOT::Math::PtEtaPhiMVector(mcacc::prPt(t1), mcacc::prEta(t1), mcacc::prPhi(t1), + o2::constants::physics::MassProton); + auto l1 = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(t1), mcacc::lamEta(t1), mcacc::lamPhi(t1), + mcacc::lamMass(t1)); + auto pX = ROOT::Math::PtEtaPhiMVector(mcacc::prPt(tX), mcacc::prEta(tX), mcacc::prPhi(tX), + o2::constants::physics::MassProton); + auto lX = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(tX), mcacc::lamEta(tX), mcacc::lamPhi(tX), + mcacc::lamMass(tX)); + + const float dPhi = RecoDecay::constrainAngle( + RecoDecay::constrainAngle(l1.Phi(), 0.0F, harmonic) - + RecoDecay::constrainAngle(lX.Phi(), 0.0F, harmonic), + -TMath::Pi(), harmonicDphi); + + histos.fill(HIST("deltaPhiMix"), dPhi, wBase); + fillHistograms(mcacc::v0Status(t1), mcacc::v0Status(tX), + l1, lX, p1, pX, + 1, wBase, 2); + } + } + } + } + } + + auto sliced = V0sMC.sliceBy(tracksPerCollisionV0mc, collision1.index()); + eventPools[bin].emplace_back(collision1.index(), std::move(sliced)); + if ((int)eventPools[bin].size() > nEvtMixing) { + eventPools[bin].pop_front(); + } + } + } + PROCESS_SWITCH(lambdaspincorrderived, processMCMEV3, "Process MC ME v3 FIFO", false); static inline float phi0To2Pi(float phi) { // harmonic=1, min=0 => [0, 2pi) @@ -1550,22 +1640,6 @@ struct lambdaspincorrderived { return std::abs(deltaPhiMinusPiToPi(phiA, phiB)); } - // symmetric neighbors for continuous mixing (pt/eta): include bin, ±1, ±2..., edge-safe - static inline void collectNeighborBins1D(int b, int nBins, int nNeighbor, std::vector& out) - { - out.clear(); - out.reserve(2 * nNeighbor + 1); - for (int d = -nNeighbor; d <= nNeighbor; ++d) { - const int bb = b + d; - if (bb < 0 || bb >= nBins) { - continue; - } - out.push_back(bb); - } - std::sort(out.begin(), out.end()); - out.erase(std::unique(out.begin(), out.end()), out.end()); - } - // symmetric neighbors for phi: periodic wrap static inline void collectNeighborBinsPhi(int b, int nPhi, int nNeighbor, std::vector& out) { @@ -1595,21 +1669,6 @@ struct lambdaspincorrderived { } } - static inline void collectPhiBinsWithEdgeWrap(int phiB, int nPhi, std::vector& out) - { - out.clear(); - out.reserve(2); - out.push_back(phiB); - if (nPhi <= 1) { - return; - } - if (phiB == 0) { - out.push_back(nPhi - 1); - } else if (phiB == nPhi - 1) { - out.push_back(0); - } - } - static inline uint64_t splitmix64(uint64_t x) { // simple deterministic hash for reproducible shuffling @@ -1619,252 +1678,18 @@ struct lambdaspincorrderived { return x ^ (x >> 31); } - static inline uint64_t splitmixmc64(uint64_t x) - { - x += 0x9e3779b97f4a7c15ULL; - x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9ULL; - x = (x ^ (x >> 27)) * 0x94d049bb133111ebULL; - return x ^ (x >> 31); - } - - void processMEV5(EventCandidates const& collisions, AllTrackCandidates const& V0s) - { - MixBinner mb{ - ptMin.value, ptMax.value, ptMix.value, - v0etaMixBuffer.value, etaMix.value, - phiMix.value, - MassMin.value, MassMax.value, cfgV5MassBins.value}; - - const int nCol = colBinning.getAllBinsCount(); - const int nStat = N_STATUS; - const int nPt = mb.nPt(); - const int nEta = mb.nEta(); // logical "nY" if userapidity=true - const int nPhi = mb.nPhi(); - const int nM = mb.nM(); - - const size_t nKeys = static_cast(nCol) * nStat * nPt * nEta * nPhi * nM; - std::vector> buffer(nKeys); - - // -------- PASS 1: fill buffer -------- - for (auto const& col : collisions) { - const int colBin = colBinning.getBin(std::make_tuple(col.posz(), col.cent())); - if (colBin < 0) { - continue; - } - - auto slice = V0s.sliceBy(tracksPerCollisionV0, col.index()); - - for (auto const& t : slice) { - if (!selectionV0(t)) { - continue; - } - - const int status = static_cast(t.v0Status()); - if (status < 0 || status >= nStat) { - continue; - } - - const int ptB = mb.ptBin(t.lambdaPt()); - - int etaB = mb.etaBin(t.lambdaEta()); - if (userapidity) { - const auto lv = ROOT::Math::PtEtaPhiMVector(t.lambdaPt(), t.lambdaEta(), t.lambdaPhi(), t.lambdaMass()); - etaB = mb.etaBin(lv.Rapidity()); // treat "eta axis" as rapidity axis - } - - const int phiB = mb.phiBin(RecoDecay::constrainAngle(t.lambdaPhi(), -TMath::Pi(), harmonic)); - const int mB = mb.massBin(t.lambdaMass()); - - if (ptB < 0 || etaB < 0 || phiB < 0 || mB < 0) { - continue; - } - - const size_t key = linearKey(colBin, status, ptB, etaB, phiB, mB, - nStat, nPt, nEta, nPhi, nM); - - buffer[key].push_back(BufferCand{ - .collisionIdx = static_cast(col.index()), - .rowIndex = static_cast(t.globalIndex()), - .v0Status = static_cast(status), - .ptBin = static_cast(ptB), - .etaBin = static_cast(etaB), - .phiBin = static_cast(phiB), - .mBin = static_cast(mB)}); - } - } - - // Neighbor policy from configurables - const int nN_pt = std::max(0, cfgV5NeighborPt.value); - const int nN_eta = std::max(0, cfgV5NeighborEta.value); - const int nN_phi = std::max(0, cfgV5NeighborPhi.value); - - std::vector ptBins, etaBins, phiBins; - std::vector matches; - matches.reserve(256); - - // -------- PASS 2: mix (replace t1 by tX, keep t2 from same event) -------- - for (auto const& col1 : collisions) { - const int colBin = colBinning.getBin(std::make_tuple(col1.posz(), col1.cent())); - if (colBin < 0) { - continue; - } - - const int64_t curColIdx = static_cast(col1.index()); - auto poolA = V0s.sliceBy(tracksPerCollisionV0, col1.index()); - - for (auto const& [t1, t2] : - soa::combinations(o2::soa::CombinationsFullIndexPolicy(poolA, poolA))) { - - if (!selectionV0(t1) || !selectionV0(t2)) { - continue; - } - if (t2.index() <= t1.index()) { - continue; // same-event ordering - } - - // no shared daughters (same-event) - if (t1.protonIndex() == t2.protonIndex()) - continue; - if (t1.pionIndex() == t2.pionIndex()) - continue; - if (t1.protonIndex() == t2.pionIndex()) - continue; - if (t1.pionIndex() == t2.protonIndex()) - continue; - - const int status = static_cast(t1.v0Status()); - if (status < 0 || status >= nStat) { - continue; - } - - const int ptB = mb.ptBin(t1.lambdaPt()); - - int etaB = mb.etaBin(t1.lambdaEta()); - if (userapidity) { - const auto lv1 = ROOT::Math::PtEtaPhiMVector(t1.lambdaPt(), t1.lambdaEta(), t1.lambdaPhi(), t1.lambdaMass()); - etaB = mb.etaBin(lv1.Rapidity()); - } - - const int phiB = mb.phiBin(RecoDecay::constrainAngle(t1.lambdaPhi(), -TMath::Pi(), harmonic)); - const int mB = mb.massBin(t1.lambdaMass()); - - if (ptB < 0 || etaB < 0 || phiB < 0 || mB < 0) { - continue; - } - - collectNeighborBinsClamp(ptB, nPt, nN_pt, ptBins); - collectNeighborBinsClamp(etaB, nEta, nN_eta, etaBins); - collectNeighborBinsPhi(phiB, nPhi, nN_phi, phiBins); - - matches.clear(); - - for (int ptUse : ptBins) { - for (int etaUse : etaBins) { - for (int phiUse : phiBins) { - const size_t keyUse = linearKey(colBin, status, ptUse, etaUse, phiUse, mB, - nStat, nPt, nEta, nPhi, nM); - auto const& vec = buffer[keyUse]; - - for (auto const& bc : vec) { - if (bc.collisionIdx == curColIdx) { - continue; // enforce different event - } - - auto tX = V0s.iteratorAt(static_cast(bc.rowIndex)); - if (!selectionV0(tX)) { - continue; - } - - if (!checkKinematics(t1, tX)) { - continue; - } - - if (tX.globalIndex() == t1.globalIndex()) - continue; - if (tX.globalIndex() == t2.globalIndex()) - continue; - - matches.push_back(MatchRef{bc.collisionIdx, bc.rowIndex}); - } - } - } - } - - if (matches.empty()) { - continue; - } - - std::sort(matches.begin(), matches.end(), - [](auto const& a, auto const& b) { - return std::tie(a.collisionIdx, a.rowIndex) < std::tie(b.collisionIdx, b.rowIndex); - }); - matches.erase(std::unique(matches.begin(), matches.end(), - [](auto const& a, auto const& b) { - return a.collisionIdx == b.collisionIdx && a.rowIndex == b.rowIndex; - }), - matches.end()); - if (matches.empty()) { - continue; - } - - if (cfgV5MaxMatches.value > 0 && (int)matches.size() > cfgV5MaxMatches.value) { - uint64_t seed = cfgMixSeed.value; - seed ^= splitmix64((uint64_t)t1.globalIndex()); - seed ^= splitmix64((uint64_t)t2.globalIndex() + 0x1234567ULL); - seed ^= splitmix64((uint64_t)curColIdx + 0x9abcULL); - - const int K = cfgV5MaxMatches.value; - for (int i = 0; i < K; ++i) { - seed = splitmix64(seed); - const int j = i + (int)(seed % (uint64_t)(matches.size() - i)); - std::swap(matches[i], matches[j]); - } - matches.resize(K); - } - - const float wBase = 1.0f / static_cast(matches.size()); - - for (auto const& m : matches) { - auto tX = V0s.iteratorAt(static_cast(m.rowIndex)); - - auto proton = ROOT::Math::PtEtaPhiMVector(tX.protonPt(), tX.protonEta(), tX.protonPhi(), - o2::constants::physics::MassProton); - auto lambda = ROOT::Math::PtEtaPhiMVector(tX.lambdaPt(), tX.lambdaEta(), tX.lambdaPhi(), - tX.lambdaMass()); - - auto proton2 = ROOT::Math::PtEtaPhiMVector(t2.protonPt(), t2.protonEta(), t2.protonPhi(), - o2::constants::physics::MassProton); - auto lambda2 = ROOT::Math::PtEtaPhiMVector(t2.lambdaPt(), t2.lambdaEta(), t2.lambdaPhi(), - t2.lambdaMass()); - - const int ptype = pairTypeCode(tX.v0Status(), t2.v0Status()); - double centPairWeight = 1.0; - if (hweightCentPair) { - const int bin = hweightCentPair->FindBin(col1.cent(), ptype); - centPairWeight = hweightCentPair->GetBinContent(bin); - if (centPairWeight <= 0.0) { - centPairWeight = 1.0; - } - } - const float meWeight = wBase * centPairWeight; - const float dPhi = deltaPhiMinusPiToPi((float)lambda.Phi(), (float)lambda2.Phi()); - histos.fill(HIST("deltaPhiMix"), dPhi, wBase); - histos.fill(HIST("hCentPairTypeME"), col1.cent(), ptype, wBase); - fillHistograms(tX.v0Status(), t2.v0Status(), - lambda, lambda2, proton, proton2, - /*datatype=*/1, /*mixpairweight=*/meWeight); - } - } - } - } - PROCESS_SWITCH(lambdaspincorrderived, processMEV5, "Process data ME v5", false); void processMEV6(EventCandidates const& collisions, AllTrackCandidates const& V0s) { MixBinnerR mb{ - ptMin.value, ptMax.value, ptMix.value, - v0etaMixBuffer.value, etaMix.value, - phiMix.value, - MassMin.value, MassMax.value, cfgV5MassBins.value, + ptMinMixBuffer.value, + ptMaxMixBuffer.value, + static_cast((ptMaxMixBuffer.value - ptMinMixBuffer.value) / cfgKinematicBins.nKinematicPt.value), + v0etaMixBuffer.value, + static_cast((2.0 * v0etaMixBuffer.value) / cfgKinematicBins.nKinematicEta.value), + static_cast((2.0 * TMath::Pi()) / cfgKinematicBins.nKinematicPhi.value), + MassMin.value, + MassMax.value, + cfgV5MassBins.value, cfgMixRadiusParam.cfgMixRadiusBins.value}; const int nCol = colBinning.getAllBinsCount(); @@ -1888,7 +1713,7 @@ struct lambdaspincorrderived { auto slice = V0s.sliceBy(tracksPerCollisionV0, col.index()); for (auto const& t : slice) { - if (!selectionV0(t)) { + if (!selectionV0Buffer(t)) { continue; } @@ -2061,16 +1886,16 @@ struct lambdaspincorrderived { if (doMixLeg1) { collectMatchesForReplacedLeg(t1, t2, colBin, curColIdx, matches1); - downsampleMatches(matches1, - (uint64_t)t1.globalIndex() ^ (splitmix64((uint64_t)t2.globalIndex()) + 0x111ULL) ^ splitmix64((uint64_t)curColIdx)); + limitMatchesToNEvents(matches1, nEvtMixing.value); + downsampleMatches(matches1, (uint64_t)t1.globalIndex() ^ (splitmix64((uint64_t)t2.globalIndex()) + 0x111ULL) ^ splitmix64((uint64_t)curColIdx)); } else { matches1.clear(); } if (doMixLeg2) { collectMatchesForReplacedLeg(t2, t1, colBin, curColIdx, matches2); - downsampleMatches(matches2, - (uint64_t)t2.globalIndex() ^ (splitmix64((uint64_t)t1.globalIndex()) + 0x222ULL) ^ splitmix64((uint64_t)curColIdx)); + limitMatchesToNEvents(matches2, nEvtMixing.value); + downsampleMatches(matches2, (uint64_t)t2.globalIndex() ^ (splitmix64((uint64_t)t1.globalIndex()) + 0x222ULL) ^ splitmix64((uint64_t)curColIdx)); } else { matches2.clear(); } @@ -2106,7 +1931,7 @@ struct lambdaspincorrderived { histos.fill(HIST("deltaPhiMix"), dPhi, wSE); histos.fill(HIST("hCentPairTypeME"), col1.cent(), ptype, wSE); - fillHistograms(tX.v0Status(), t2.v0Status(), lambda, lambda2, proton, proton2, 1, meWeight); + fillHistograms(tX.v0Status(), t2.v0Status(), lambda, lambda2, proton, proton2, 1, meWeight, 1); } } @@ -2134,7 +1959,7 @@ struct lambdaspincorrderived { histos.fill(HIST("deltaPhiMix"), dPhi, wSE); histos.fill(HIST("hCentPairTypeME"), col1.cent(), ptype, wSE); - fillHistograms(t1.v0Status(), tY.v0Status(), lambda, lambda2, proton, proton2, 1, meWeight); + fillHistograms(t1.v0Status(), tY.v0Status(), lambda, lambda2, proton, proton2, 1, meWeight, 2); } } } @@ -2144,10 +1969,15 @@ struct lambdaspincorrderived { void processMCMEV6(EventCandidatesMC const& collisions, AllTrackCandidatesMC const& V0sMC) { MixBinnerR mb{ - ptMin.value, ptMax.value, ptMix.value, - v0etaMixBuffer.value, etaMix.value, - phiMix.value, - MassMin.value, MassMax.value, cfgV5MassBins.value, + ptMinMixBuffer.value, + ptMaxMixBuffer.value, + static_cast((ptMaxMixBuffer.value - ptMinMixBuffer.value) / cfgKinematicBins.nKinematicPt.value), + v0etaMixBuffer.value, + static_cast((2.0 * v0etaMixBuffer.value) / cfgKinematicBins.nKinematicEta.value), + static_cast((2.0 * TMath::Pi()) / cfgKinematicBins.nKinematicPhi.value), + MassMin.value, + MassMax.value, + cfgV5MassBins.value, cfgMixRadiusParam.cfgMixRadiusBins.value}; const int nCol = colBinning.getAllBinsCount(); @@ -2171,7 +2001,7 @@ struct lambdaspincorrderived { auto slice = V0sMC.sliceBy(tracksPerCollisionV0mc, col.index()); for (auto const& t : slice) { - if (!selectionV0MC(t)) { + if (!selectionV0BufferMC(t)) { continue; } @@ -2344,20 +2174,18 @@ struct lambdaspincorrderived { if (doMixLeg1) { collectMatchesForReplacedLeg(t1, t2, colBin, curColIdx, matches1); - downsampleMatches(matches1, - (uint64_t)t1.globalIndex() ^ (splitmix64((uint64_t)t2.globalIndex()) + 0x111ULL) ^ splitmix64((uint64_t)curColIdx)); + limitMatchesToNEvents(matches1, nEvtMixing.value); + downsampleMatches(matches1, (uint64_t)t1.globalIndex() ^ (splitmix64((uint64_t)t2.globalIndex()) + 0x111ULL) ^ splitmix64((uint64_t)curColIdx)); } else { matches1.clear(); } - if (doMixLeg2) { collectMatchesForReplacedLeg(t2, t1, colBin, curColIdx, matches2); - downsampleMatches(matches2, - (uint64_t)t2.globalIndex() ^ (splitmix64((uint64_t)t1.globalIndex()) + 0x222ULL) ^ splitmix64((uint64_t)curColIdx)); + limitMatchesToNEvents(matches2, nEvtMixing.value); + downsampleMatches(matches2, (uint64_t)t2.globalIndex() ^ (splitmix64((uint64_t)t1.globalIndex()) + 0x222ULL) ^ splitmix64((uint64_t)curColIdx)); } else { matches2.clear(); } - const int nReuse = static_cast(matches1.size() + matches2.size()); if (nReuse <= 0) { continue; @@ -2395,7 +2223,7 @@ struct lambdaspincorrderived { fillHistograms(mcacc::v0Status(tX), mcacc::v0Status(t2), lX, l2, pX, p2, - 1, meWeight); + 1, meWeight, 1); } } @@ -2429,7 +2257,7 @@ struct lambdaspincorrderived { fillHistograms(mcacc::v0Status(t1), mcacc::v0Status(tY), l1, lY, p1, pY, - 1, meWeight); + 1, meWeight, 2); } } } From 953e362e901046bd57911356f25745d3a8aefd4a Mon Sep 17 00:00:00 2001 From: Himanshu Sharma Date: Wed, 18 Mar 2026 00:38:08 +0100 Subject: [PATCH 311/347] [PWGHF] Add UPC QA histograms to D0 task (#15430) Co-authored-by: ALICE Action Bot --- PWGHF/D2H/Tasks/taskD0.cxx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/PWGHF/D2H/Tasks/taskD0.cxx b/PWGHF/D2H/Tasks/taskD0.cxx index 9f4cdd4e01f..c7064ab0c67 100644 --- a/PWGHF/D2H/Tasks/taskD0.cxx +++ b/PWGHF/D2H/Tasks/taskD0.cxx @@ -382,6 +382,8 @@ struct HfTaskD0 { registry.add("Data/fitInfo/ampFT0A_vs_ampFT0C", "FT0-A vs FT0-C amplitude;FT0-A amplitude (a.u.);FT0-C amplitude (a.u.)", {HistType::kTH2F, {{2500, 0., 250}, {2500, 0., 250}}}); registry.add("Data/zdc/energyZNA_vs_energyZNC", "ZNA vs ZNC common energy;E_{ZNA}^{common} (a.u.);E_{ZNC}^{common} (a.u.)", {HistType::kTH2F, {{200, 0., 20}, {200, 0., 20}}}); registry.add("Data/hUpcGapAfterSelection", "UPC gap type after selection;Gap type;Counts", {HistType::kTH1F, {{7, -1.5, 5.5}}}); + registry.add("Data/hGapVsEta", "UPC gap vs Eta;Gap type;Eta", {HistType::kTH2F, {{7, -1.5, 5.5}, {50, -1., 1.}}}); + registry.add("Data/hGapVsRap", "UPC gap vs Eta;Gap type;Eta", {HistType::kTH2F, {{7, -1.5, 5.5}, {50, -1., 1.}}}); hfEvSel.addHistograms(registry); @@ -633,6 +635,8 @@ struct HfTaskD0 { const float massD0 = HfHelper::invMassD0ToPiK(candidate); const float massD0bar = HfHelper::invMassD0barToKPi(candidate); const auto ptCandidate = candidate.pt(); + registry.fill(HIST("Data/hGapVsEta"), gap, candidate.eta()); + registry.fill(HIST("Data/hGapVsRap"), gap, HfHelper::yD0(candidate)); if (candidate.isSelD0() >= selectionFlagD0) { registry.fill(HIST("hMass"), massD0, ptCandidate); From 4e3e10540e06d4ae0d1e2e0015899b011da1399b Mon Sep 17 00:00:00 2001 From: Zhengqing Wang Date: Wed, 18 Mar 2026 01:34:01 +0100 Subject: [PATCH 312/347] [PWGLF] Add NTPCCrossedRows selection (#15434) Co-authored-by: Qing --- PWGLF/DataModel/LFHypernucleiTables.h | 10 ++++---- PWGLF/TableProducer/Nuspex/hyperRecoTask.cxx | 24 ++++++++++++++++---- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/PWGLF/DataModel/LFHypernucleiTables.h b/PWGLF/DataModel/LFHypernucleiTables.h index ca389cf928b..9ff524dd347 100644 --- a/PWGLF/DataModel/LFHypernucleiTables.h +++ b/PWGLF/DataModel/LFHypernucleiTables.h @@ -59,6 +59,8 @@ DECLARE_SOA_COLUMN(NTPCclusHe, nTPCclusHe, uint8_t); // Number DECLARE_SOA_COLUMN(NTPCclusPi, nTPCclusPi, uint8_t); // Number of TPC clusters of the Pi daughter DECLARE_SOA_COLUMN(NTPCpidClusHe, nTPCpidClusHe, uint8_t); // Number of TPC clusters with PID information of the He daughter DECLARE_SOA_COLUMN(NTPCpidClusPi, nTPCpidClusPi, uint8_t); // Number of TPC clusters with PID information of the Pi daughter +DECLARE_SOA_COLUMN(NTPCCrossedRowsHe, nTPCCrossedRowsHe, uint8_t); // Number of TPC crossed rows of the He daughter +DECLARE_SOA_COLUMN(NTPCCrossedRowsPi, nTPCCrossedRowsPi, uint8_t); // Number of TPC crossed rows of the Pi daughter DECLARE_SOA_COLUMN(TPCsignalHe, tpcSignalHe, uint16_t); // TPC signal of the He daughter DECLARE_SOA_COLUMN(TPCsignalPi, tpcSignalPi, uint16_t); // TPC signal of the Pi daughter DECLARE_SOA_COLUMN(TPCChi2He, tpcChi2He, float); // TPC chi2 of the He daughter @@ -99,7 +101,7 @@ DECLARE_SOA_TABLE(DataHypCands, "AOD", "HYPCANDS", hyperrec::PtPi, hyperrec::PhiPi, hyperrec::EtaPi, hyperrec::XDecVtx, hyperrec::YDecVtx, hyperrec::ZDecVtx, hyperrec::DcaV0Daug, hyperrec::DcaHe, hyperrec::DcaPi, - hyperrec::NSigmaHe, hyperrec::NTPCclusHe, hyperrec::NTPCclusPi, hyperrec::NTPCpidClusHe, hyperrec::NTPCpidClusPi, + hyperrec::NSigmaHe, hyperrec::NTPCclusHe, hyperrec::NTPCclusPi, hyperrec::NTPCpidClusHe, hyperrec::NTPCpidClusPi, hyperrec::NTPCCrossedRowsHe, hyperrec::NTPCCrossedRowsPi, hyperrec::TPCmomHe, hyperrec::TPCmomPi, hyperrec::TPCsignalHe, hyperrec::TPCsignalPi, hyperrec::TPCChi2He, hyperrec::ITSChi2He, hyperrec::ITSChi2Pi, hyperrec::TOFMass, hyperrec::ITSclusterSizesHe, hyperrec::ITSclusterSizesPi, @@ -118,7 +120,7 @@ DECLARE_SOA_TABLE(DataHypCandsFlow, "AOD", "HYPCANDSFLOW", hyperrec::PtPi, hyperrec::PhiPi, hyperrec::EtaPi, hyperrec::XDecVtx, hyperrec::YDecVtx, hyperrec::ZDecVtx, hyperrec::DcaV0Daug, hyperrec::DcaHe, hyperrec::DcaPi, - hyperrec::NSigmaHe, hyperrec::NTPCclusHe, hyperrec::NTPCclusPi, hyperrec::NTPCpidClusHe, hyperrec::NTPCpidClusPi, + hyperrec::NSigmaHe, hyperrec::NTPCclusHe, hyperrec::NTPCclusPi, hyperrec::NTPCpidClusHe, hyperrec::NTPCpidClusPi, hyperrec::NTPCCrossedRowsHe, hyperrec::NTPCCrossedRowsPi, hyperrec::TPCmomHe, hyperrec::TPCmomPi, hyperrec::TPCsignalHe, hyperrec::TPCsignalPi, hyperrec::TPCChi2He, hyperrec::ITSChi2He, hyperrec::ITSChi2Pi, hyperrec::TOFMass, hyperrec::ITSclusterSizesHe, hyperrec::ITSclusterSizesPi, @@ -134,7 +136,7 @@ DECLARE_SOA_TABLE(MCHypCands, "AOD", "MCHYPCANDS", hyperrec::PtPi, hyperrec::PhiPi, hyperrec::EtaPi, hyperrec::XDecVtx, hyperrec::YDecVtx, hyperrec::ZDecVtx, hyperrec::DcaV0Daug, hyperrec::DcaHe, hyperrec::DcaPi, - hyperrec::NSigmaHe, hyperrec::NTPCclusHe, hyperrec::NTPCclusPi, hyperrec::NTPCpidClusHe, hyperrec::NTPCpidClusPi, + hyperrec::NSigmaHe, hyperrec::NTPCclusHe, hyperrec::NTPCclusPi, hyperrec::NTPCpidClusHe, hyperrec::NTPCpidClusPi, hyperrec::NTPCCrossedRowsHe, hyperrec::NTPCCrossedRowsPi, hyperrec::TPCmomHe, hyperrec::TPCmomPi, hyperrec::TPCsignalHe, hyperrec::TPCsignalPi, hyperrec::TPCChi2He, hyperrec::ITSChi2He, hyperrec::ITSChi2Pi, hyperrec::TOFMass, hyperrec::ITSclusterSizesHe, hyperrec::ITSclusterSizesPi, @@ -163,7 +165,7 @@ DECLARE_SOA_TABLE(DataHypCandsWColl, "AOD", "HYPCANDSWCOLL", hyperrec::PtPi, hyperrec::PhiPi, hyperrec::EtaPi, hyperrec::XDecVtx, hyperrec::YDecVtx, hyperrec::ZDecVtx, hyperrec::DcaV0Daug, hyperrec::DcaHe, hyperrec::DcaPi, - hyperrec::NSigmaHe, hyperrec::NTPCclusHe, hyperrec::NTPCclusPi, hyperrec::NTPCpidClusHe, hyperrec::NTPCpidClusPi, + hyperrec::NSigmaHe, hyperrec::NTPCclusHe, hyperrec::NTPCclusPi, hyperrec::NTPCpidClusHe, hyperrec::NTPCpidClusPi, hyperrec::NTPCCrossedRowsHe, hyperrec::NTPCCrossedRowsPi, hyperrec::TPCmomHe, hyperrec::TPCmomPi, hyperrec::TPCsignalHe, hyperrec::TPCsignalPi, hyperrec::TPCChi2He, hyperrec::ITSChi2He, hyperrec::ITSChi2Pi, hyperrec::TOFMass, hyperrec::ITSclusterSizesHe, hyperrec::ITSclusterSizesPi, diff --git a/PWGLF/TableProducer/Nuspex/hyperRecoTask.cxx b/PWGLF/TableProducer/Nuspex/hyperRecoTask.cxx index e200e66ae57..2d922f613a5 100644 --- a/PWGLF/TableProducer/Nuspex/hyperRecoTask.cxx +++ b/PWGLF/TableProducer/Nuspex/hyperRecoTask.cxx @@ -138,6 +138,8 @@ struct hyperCandidate { uint8_t nTPCClustersPi = 0u; uint8_t nTPCpidClusHe3 = 0u; uint8_t nTPCpidClusPi = 0u; + uint8_t nTPCCrossedRowsHe3 = 0u; + uint8_t nTPCCrossedRowsPi = 0u; uint32_t clusterSizeITSHe3 = 0u; uint32_t clusterSizeITSPi = 0u; @@ -182,6 +184,8 @@ struct hyperRecoTask { Configurable nSigmaMaxHe{"nSigmaMaxHe", 5, "helium dEdx cut (n sigma)"}; Configurable nTPCClusMinHe{"nTPCClusMinHe", 70, "helium NTPC clusters cut"}; Configurable nTPCClusMinPi{"nTPCClusMinPi", -1., "pion NTPC clusters cut"}; + Configurable nTPCCrossedRowsMinHe{"nTPCCrossedRowsMinHe", 70, "helium minimum crossed rows"}; + Configurable nTPCCrossedRowsMinPi{"nTPCCrossedRowsMinPi", -1., "pion minimum crossed rows"}; Configurable mcSignalOnly{"mcSignalOnly", true, "If true, save only signal in MC"}; Configurable cfgSkimmedProcessing{"cfgSkimmedProcessing", false, "Skimmed dataset processing"}; Configurable isEventUsedForEPCalibration{"isEventUsedForEPCalibration", 1, "Event is used for EP calibration"}; @@ -509,10 +513,12 @@ struct hyperRecoTask { hypCand.isMatter = heTrack.sign() > 0; hypCand.nSigmaHe3 = computeNSigmaHe3(heTrack); hypCand.nTPCClustersHe3 = heTrack.tpcNClsFound(); + hypCand.nTPCCrossedRowsHe3 = heTrack.tpcNClsCrossedRows(); hypCand.tpcSignalHe3 = heTrack.tpcSignal(); hypCand.nTPCpidClusHe3 = static_cast(heTrack.tpcNClsFindable()) - heTrack.tpcNClsFindableMinusPID(); hypCand.clusterSizeITSHe3 = heTrack.itsClusterSizes(); hypCand.nTPCClustersPi = piTrack.tpcNClsFound(); + hypCand.nTPCCrossedRowsPi = piTrack.tpcNClsCrossedRows(); hypCand.nTPCpidClusPi = static_cast(piTrack.tpcNClsFindable()) - piTrack.tpcNClsFindableMinusPID(); hypCand.tpcSignalPi = piTrack.tpcSignal(); hypCand.tpcChi2He3 = heTrack.tpcChi2NCl(); @@ -673,6 +679,9 @@ struct hyperRecoTask { if (heTrack.tpcNClsFound() < nTPCClusMinHe || piTrack.tpcNClsFound() < nTPCClusMinPi) { continue; } + if (heTrack.tpcNClsCrossedRows() < nTPCCrossedRowsMinHe || piTrack.tpcNClsCrossedRows() < nTPCCrossedRowsMinPi) { + continue; + } hyperCandidate hypCand; hypCand.v0ID = v0.globalIndex(); @@ -707,6 +716,10 @@ struct hyperRecoTask { continue; if (!isHe && track.tpcNClsFound() < nTPCClusMinPi) continue; + if (isHe && track.tpcNClsCrossedRows() < nTPCCrossedRowsMinHe) + continue; + if (!isHe && track.tpcNClsCrossedRows() < nTPCCrossedRowsMinPi) + continue; svCreator.appendTrackCand(track, collisions, pdgHypo, ambiguousTracks, bcs); } @@ -793,6 +806,7 @@ struct hyperRecoTask { hypCand.dcaV0dau, hypCand.he3DCAXY, hypCand.piDCAXY, hypCand.nSigmaHe3, hypCand.nTPCClustersHe3, hypCand.nTPCClustersPi, hypCand.nTPCpidClusHe3, hypCand.nTPCpidClusPi, + hypCand.nTPCCrossedRowsHe3, hypCand.nTPCCrossedRowsPi, hypCand.momHe3TPC, hypCand.momPiTPC, hypCand.tpcSignalHe3, hypCand.tpcSignalPi, hypCand.tpcChi2He3, hypCand.itsChi2He3, hypCand.itsChi2Pi, hypCand.massTOFHe3, hypCand.clusterSizeITSHe3, hypCand.clusterSizeITSPi, hypCand.flags, trackedHypClSize); @@ -828,6 +842,7 @@ struct hyperRecoTask { hypCand.dcaV0dau, hypCand.he3DCAXY, hypCand.piDCAXY, hypCand.nSigmaHe3, hypCand.nTPCClustersHe3, hypCand.nTPCClustersPi, hypCand.nTPCpidClusHe3, hypCand.nTPCpidClusPi, + hypCand.nTPCCrossedRowsHe3, hypCand.nTPCCrossedRowsPi, hypCand.momHe3TPC, hypCand.momPiTPC, hypCand.tpcSignalHe3, hypCand.tpcSignalPi, hypCand.tpcChi2He3, hypCand.itsChi2He3, hypCand.itsChi2Pi, hypCand.massTOFHe3, hypCand.clusterSizeITSHe3, hypCand.clusterSizeITSPi, hypCand.flags, trackedHypClSize); @@ -856,6 +871,7 @@ struct hyperRecoTask { hypCand.dcaV0dau, hypCand.he3DCAXY, hypCand.piDCAXY, hypCand.nSigmaHe3, hypCand.nTPCClustersHe3, hypCand.nTPCClustersPi, hypCand.nTPCpidClusHe3, hypCand.nTPCpidClusPi, + hypCand.nTPCCrossedRowsHe3, hypCand.nTPCCrossedRowsPi, hypCand.momHe3TPC, hypCand.momPiTPC, hypCand.tpcSignalHe3, hypCand.tpcSignalPi, hypCand.tpcChi2He3, hypCand.itsChi2He3, hypCand.itsChi2Pi, hypCand.massTOFHe3, hypCand.clusterSizeITSHe3, hypCand.clusterSizeITSPi, hypCand.flags, trackedHypClSize); @@ -890,7 +906,7 @@ struct hyperRecoTask { hypCand.recoPtPi(), hypCand.recoPhiPi(), hypCand.recoEtaPi(), hypCand.decVtx[0], hypCand.decVtx[1], hypCand.decVtx[2], hypCand.dcaV0dau, hypCand.he3DCAXY, hypCand.piDCAXY, - hypCand.nSigmaHe3, hypCand.nTPCClustersHe3, hypCand.nTPCClustersPi, hypCand.nTPCpidClusHe3, hypCand.nTPCpidClusPi, + hypCand.nSigmaHe3, hypCand.nTPCClustersHe3, hypCand.nTPCClustersPi, hypCand.nTPCpidClusHe3, hypCand.nTPCpidClusPi, hypCand.nTPCCrossedRowsHe3, hypCand.nTPCCrossedRowsPi, hypCand.momHe3TPC, hypCand.momPiTPC, hypCand.tpcSignalHe3, hypCand.tpcSignalPi, hypCand.tpcChi2He3, hypCand.itsChi2He3, hypCand.itsChi2Pi, hypCand.massTOFHe3, hypCand.clusterSizeITSHe3, hypCand.clusterSizeITSPi, hypCand.flags, trackedHypClSize, @@ -960,14 +976,14 @@ struct hyperRecoTask { } outputMCTable(centFT0A, centFT0C, centFT0M, - mRunNumber, -1, -1, -1, - 0, -1, -1, -1, + mRunNumber, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 0, 0, 0, 0, -1, -1, -1, false, chargeFactor * hypCand.genPt(), hypCand.genPhi(), hypCand.genEta(), hypCand.genPtHe3(), hypCand.gDecVtx[0], hypCand.gDecVtx[1], hypCand.gDecVtx[2], From 223a91da723515a38f0bbc3036c69512a7c6570c Mon Sep 17 00:00:00 2001 From: FabiolaLP <150402425+FabiolaLP@users.noreply.github.com> Date: Tue, 17 Mar 2026 20:27:37 -0600 Subject: [PATCH 313/347] [PWGLF] Update nucleiAntineutronCex task (#15341) --- PWGLF/DataModel/LFAntinCexTables.h | 24 ++- .../Nuspex/nucleiAntineutronCex.cxx | 157 +++++++++++++++++- 2 files changed, 170 insertions(+), 11 deletions(-) diff --git a/PWGLF/DataModel/LFAntinCexTables.h b/PWGLF/DataModel/LFAntinCexTables.h index 9e8f4ce1ca8..0e762f03e17 100644 --- a/PWGLF/DataModel/LFAntinCexTables.h +++ b/PWGLF/DataModel/LFAntinCexTables.h @@ -26,11 +26,12 @@ namespace o2::aod namespace antin_cex { // Metadata -DECLARE_SOA_COLUMN(IsCex, isCex, bool); // 1=CEX (from antin), 0=BG -DECLARE_SOA_COLUMN(MotherPdg, motherPdg, int32_t); // mother PDG -DECLARE_SOA_COLUMN(ColId, colId, int32_t); // mcCollisionId -DECLARE_SOA_COLUMN(PId, pId, int32_t); // proton MC id -DECLARE_SOA_COLUMN(AntipId, antipId, int32_t); // antiproton MC id +DECLARE_SOA_COLUMN(IsCex, isCex, bool); // 1=CEX (from antin), 0=BG +DECLARE_SOA_COLUMN(MotherPdg, motherPdg, int32_t); // mother PDG +DECLARE_SOA_COLUMN(MotherNHitIB, motherNHitIB, int); // mother IB Hits +DECLARE_SOA_COLUMN(ColId, colId, int32_t); // mcCollisionId +DECLARE_SOA_COLUMN(PId, pId, int32_t); // proton MC id +DECLARE_SOA_COLUMN(AntipId, antipId, int32_t); // antiproton MC id // MC (pair) DECLARE_SOA_COLUMN(McPairP, mcPairP, float); @@ -41,6 +42,12 @@ DECLARE_SOA_COLUMN(McAngleDeg, mcAngleDeg, float); DECLARE_SOA_COLUMN(McVtxX, mcVtxX, float); DECLARE_SOA_COLUMN(McVtxY, mcVtxY, float); DECLARE_SOA_COLUMN(McVtxZ, mcVtxZ, float); +DECLARE_SOA_COLUMN(VtxNAll, vtxNAll, int16_t); +DECLARE_SOA_COLUMN(VtxNCh, vtxNCh, int16_t); +DECLARE_SOA_COLUMN(VtxNNeut, vtxNNeut, int16_t); +DECLARE_SOA_COLUMN(VtxNPi0, vtxNPi0, int16_t); +DECLARE_SOA_COLUMN(VtxNGamma, vtxNGamma, int16_t); +DECLARE_SOA_COLUMN(VtxNN, vtxNN, int16_t); // Tracks (pair, fitter) DECLARE_SOA_COLUMN(TrkPairP, trkPairP, float); @@ -85,6 +92,8 @@ DECLARE_SOA_COLUMN(AntipTrkNClsIts, antipTrkNClsIts, int16_t); DECLARE_SOA_COLUMN(SelMask, selMask, uint32_t); DECLARE_SOA_COLUMN(PairPointingAngleDeg, pairPointingAngleDeg, float); +DECLARE_SOA_COLUMN(PvsvThetaDeg, pvsvThetaDeg, float); +DECLARE_SOA_COLUMN(PvsvPhiDeg, pvsvPhiDeg, float); DECLARE_SOA_COLUMN(PairPBalance, pairPBalance, float); DECLARE_SOA_COLUMN(PairPtBalance, pairPtBalance, float); DECLARE_SOA_COLUMN(PairQ, pairQ, float); @@ -118,9 +127,10 @@ DECLARE_SOA_COLUMN(AntipTrkTgl, antipTrkTgl, float); // Table DECLARE_SOA_TABLE(AntinCexPairs, "AOD", "ANTINCEX", antin_cex::IsCex, - antin_cex::MotherPdg, antin_cex::ColId, antin_cex::PId, antin_cex::AntipId, + antin_cex::MotherPdg, antin_cex::MotherNHitIB, antin_cex::ColId, antin_cex::PId, antin_cex::AntipId, antin_cex::McPairP, antin_cex::McPairPt, antin_cex::McPairPz, antin_cex::McDplane, antin_cex::McAngleDeg, antin_cex::McVtxX, antin_cex::McVtxY, antin_cex::McVtxZ, + antin_cex::VtxNAll, antin_cex::VtxNCh, antin_cex::VtxNNeut, antin_cex::VtxNPi0, antin_cex::VtxNGamma, antin_cex::VtxNN, antin_cex::TrkPairP, antin_cex::TrkPairPt, antin_cex::TrkPairPz, antin_cex::TrkAngleDeg, antin_cex::TrkVtxfitDcaPair, antin_cex::TrkVtxfitR, antin_cex::TrkVtxfitDistToPv, antin_cex::TrkVtxfitSecVtxX, antin_cex::TrkVtxfitSecVtxY, antin_cex::TrkVtxfitSecVtxZ, @@ -129,7 +139,7 @@ DECLARE_SOA_TABLE(AntinCexPairs, "AOD", "ANTINCEX", antin_cex::PTrkP, antin_cex::PTrkPx, antin_cex::PTrkPy, antin_cex::PTrkPz, antin_cex::PTrkEta, antin_cex::PTrkTpcSignal, antin_cex::PTrkNClsIts, antin_cex::AntipTrkP, antin_cex::AntipTrkPx, antin_cex::AntipTrkPy, antin_cex::AntipTrkPz, antin_cex::AntipTrkEta, antin_cex::AntipTrkTpcSignal, antin_cex::AntipTrkNClsIts, antin_cex::SelMask, - antin_cex::PairPointingAngleDeg, antin_cex::PairPBalance, antin_cex::PairPtBalance, antin_cex::PairQ, + antin_cex::PairPointingAngleDeg, antin_cex::PvsvThetaDeg, antin_cex::PvsvPhiDeg, antin_cex::PairPBalance, antin_cex::PairPtBalance, antin_cex::PairQ, antin_cex::DPairP, antin_cex::DPairPt, antin_cex::DPairPz, antin_cex::DOpenAngle, antin_cex::SVNearestLayerId, antin_cex::SVDeltaRToLayer, antin_cex::PTrkItsHitMap, antin_cex::APTrkItsHitMap, antin_cex::PLayersOk, antin_cex::APLayersOk, diff --git a/PWGLF/TableProducer/Nuspex/nucleiAntineutronCex.cxx b/PWGLF/TableProducer/Nuspex/nucleiAntineutronCex.cxx index 4ba3316a0b7..71cbd488d71 100644 --- a/PWGLF/TableProducer/Nuspex/nucleiAntineutronCex.cxx +++ b/PWGLF/TableProducer/Nuspex/nucleiAntineutronCex.cxx @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -53,7 +54,7 @@ struct NucleiAntineutronCex { static constexpr double kIts2MaxR = 48.0; // ITS2 max radius [cm] static constexpr double kIts2MaxVz = 39.0; // ITS2 max |vz| [cm] static constexpr double kAccMaxEta = 1.2; // acceptance |eta| - static constexpr double kAccMaxVz = 5.3; // acceptance |vz| [cm] + static constexpr double kAccMaxVz = 10.0; // acceptance |vz| [cm] static constexpr double kStrictEta = 0.9; // tighter eta cut static constexpr double kInitDplane = 10.0; // init dplane static constexpr double kHuge = 1e9; // fallback for bad denom @@ -102,8 +103,24 @@ struct NucleiAntineutronCex { histos.add("pEta", "Pseudorapidity;#eta;Entries", kTH1F, {{100, -10., 10.}}); histos.add("pP_ITScuts", "Momentum with ITS cuts;|p| (GeV/c);Entries", kTH1F, {{100, 0., 10.}}); - // test (MC) - histos.add("antip_test", "Secondary antiprotons;|p| (GeV/c);Entries", kTH1F, {{100, 0., 10.}}); + // Process enum breakdown (secondary antiproton that anchors the SV) + histos.add("hProcEnumAP_CEX", "procEnum of secondary #bar{p} (CEX);procEnum;Entries", kTH1I, {{100, -0.5, 99.5}}); + histos.add("hProcEnumAP_BG", "procEnum of secondary #bar{p} (BG);procEnum;Entries", kTH1I, {{100, -0.5, 99.5}}); + + // Multiplicity/composition at the SV (MC truth, for FINAL selected candidates) + histos.add("hVtxNAll_CEX", "N(all) secondaries at SV (CEX);N;Entries", kTH1I, {{60, -0.5, 59.5}}); + histos.add("hVtxNAll_BG", "N(all) secondaries at SV (BG);N;Entries", kTH1I, {{60, -0.5, 59.5}}); + histos.add("hVtxNCh_CEX", "N(charged) secondaries at SV (CEX);N;Entries", kTH1I, {{60, -0.5, 59.5}}); + histos.add("hVtxNCh_BG", "N(charged) secondaries at SV (BG);N;Entries", kTH1I, {{60, -0.5, 59.5}}); + histos.add("hVtxNNeut_CEX", "N(neutral) secondaries at SV (CEX);N;Entries", kTH1I, {{60, -0.5, 59.5}}); + histos.add("hVtxNNeut_BG", "N(neutral) secondaries at SV (BG);N;Entries", kTH1I, {{60, -0.5, 59.5}}); + + histos.add("hVtxNPi0_CEX", "N(#pi^{0}) at SV (CEX);N;Entries", kTH1I, {{40, -0.5, 39.5}}); + histos.add("hVtxNPi0_BG", "N(#pi^{0}) at SV (BG);N;Entries", kTH1I, {{40, -0.5, 39.5}}); + histos.add("hVtxNGamma_CEX", "N(#gamma) at SV (CEX);N;Entries", kTH1I, {{60, -0.5, 59.5}}); + histos.add("hVtxNGamma_BG", "N(#gamma) at SV (BG);N;Entries", kTH1I, {{60, -0.5, 59.5}}); + histos.add("hVtxNN_CEX", "N(n) at SV (CEX);N;Entries", kTH1I, {{40, -0.5, 39.5}}); + histos.add("hVtxNN_BG", "N(n) at SV (BG);N;Entries", kTH1I, {{40, -0.5, 39.5}}); // CEX pair from antineutron (MC) histos.add("cexPairMcP", "CEX pair total momentum;|p| (GeV/c);Entries", kTH1F, {{100, 0., 10.}}); @@ -130,6 +147,13 @@ struct NucleiAntineutronCex { histos.add("cexbg_pairmc_vtxz", "Background secondary vertex Z;Z (cm);Entries", kTH1F, {{200, -60., 60.}}); histos.add("cexbg_pairmc_pITScuts", "Background momentum (ITS cuts);|p| (GeV/c);Entries", kTH1F, {{100, 0., 10.}}); + histos.add("hDeltaP_CEX", "|p_{mother}-Σp_{SV}| (CEX);Δp (GeV/c);Entries", kTH1F, {{200, 0., 10.}}); + histos.add("hDeltaP_BG", "|p_{mother}-Σp_{SV}| (BG);Δp (GeV/c);Entries", kTH1F, {{200, 0., 10.}}); + + // Mother IB hits + histos.add("hMotherNHitIB_CEX", "Mother IB hit layers (L0-L2) (CEX);N_{IB layers};Entries", kTH1I, {{5, -1.5, 4.5}}); + histos.add("hMotherNHitIB_BG", "Mother IB hit layers (L0-L2) (BG);N_{IB layers};Entries", kTH1I, {{5, -1.5, 4.5}}); + // CEX pair from antineutron (TRK) histos.add("cex_pairtrk_angle", "Pair opening angle (tracks);Angle (°);Entries", kTH1F, {{180, 0., 180.}}); histos.add("cexPairTrkP", "Pair momentum (tracks);|p| (GeV/c);Entries", kTH1F, {{120, 0., 12.}}); @@ -260,26 +284,31 @@ struct NucleiAntineutronCex { const bool isSecondaryFromMaterial = (!particle.producedByGenerator()) && (procEnum == kPHadronic || procEnum == kPHInhelastic); if (particle.pdgCode() != -kProton || !isSecondaryFromMaterial || particle.mothersIds().empty()) continue; - histos.fill(HIST("antip_test"), particle.p()); // Primary mother bool hasPrimaryMotherAntip = false; double motherPt = 0.0; + double motherPx = 0.0; + double motherPy = 0.0; double motherPz = 0.0; double motherVz = 0.0; double motherP = 0.0; double motherEta = 0.0; int motherPdg = 0; + int motherId = -1; for (const auto& mother : particle.mothers_as()) { if (mother.isPhysicalPrimary()) { hasPrimaryMotherAntip = true; motherPt = mother.pt(); + motherPx = mother.px(); + motherPy = mother.py(); motherPz = mother.pz(); motherVz = mother.vz(); motherP = mother.p(); motherEta = mother.eta(); motherPdg = mother.pdgCode(); + motherId = mother.globalIndex(); break; } } @@ -530,6 +559,9 @@ struct NucleiAntineutronCex { int8_t antipTrkItsPidValid = 0; float antipTrkTgl = 0.f; + bool motherHasTrack = false; + int motherNHitIB = -1; // number of hits in IB (L0-L2) + o2::aod::ITSResponse itsResponse; for (const auto& track : tracks) { @@ -557,6 +589,11 @@ struct NucleiAntineutronCex { int nITS = track.itsNCls(); bool layerCondition = (!hitIB) && hitOuter && (nITS >= kMinItsHits); + if (mc.globalIndex() == motherId) { + motherHasTrack = true; + motherNHitIB = static_cast(hitL0) + static_cast(hitL1) + static_cast(hitL2); + } + if (mc.globalIndex() == antipId) { antipTrkP = track.p(); antipTrkPx = track.px(); @@ -695,6 +732,13 @@ struct NucleiAntineutronCex { const TVector3 pv2sv(secX - pvtxX, secY - pvtxY, secZ - pvtxZ); const double pairPointingAngleDeg = pv2sv.Angle(total_trk_pVec) * Rad2Deg; + const double pvsvThetaDeg = pv2sv.Theta() * Rad2Deg; + + double pvsvPhiDeg = pv2sv.Phi() * Rad2Deg; + if (pvsvPhiDeg < 0.) { + pvsvPhiDeg += 360.; + } + const double pP = pVecProton_trk.Mag(); const double pAP = AntipVecProton_trk.Mag(); const double ptP = pVecProton_trk.Pt(); @@ -757,16 +801,112 @@ struct NucleiAntineutronCex { const bool isCex = (motherPdg == -kNeutron); + // Nature of the process + if (isCex) { + histos.fill(HIST("hProcEnumAP_CEX"), static_cast(procEnum)); + } else { + histos.fill(HIST("hProcEnumAP_BG"), static_cast(procEnum)); + } + + // Count material secondaries produced at the same SV as the selected secondary antiproton. + int vtxNAll = 0; + int vtxNCh = 0; + int vtxNNeut = 0; + int vtxNPi0 = 0; + int vtxNGamma = 0; + int vtxNN = 0; + double sumPx_vtx = 0.0; + double sumPy_vtx = 0.0; + double sumPz_vtx = 0.0; + auto* pdgDB = TDatabasePDG::Instance(); + + for (const auto& particle5 : mcPartsThis) { + if (particle5.mcCollisionId() != colId) { + continue; + } + // Same SV (use the SV of the selected secondary antiproton) + if (std::abs(particle5.vx() - antipVx) >= kVtxTol || std::abs(particle5.vy() - antipVy) >= kVtxTol || std::abs(particle5.vz() - antipVz) >= kVtxTol) { + continue; + } + const auto proc5Enum = particle5.getProcess(); + const bool isSecondaryFromMaterial5 = + (!particle5.producedByGenerator()) && (proc5Enum == kPHadronic || proc5Enum == kPHInhelastic); + if (!isSecondaryFromMaterial5) { + continue; + } + ++vtxNAll; + sumPx_vtx += particle5.px(); + sumPy_vtx += particle5.py(); + sumPz_vtx += particle5.pz(); + const int pdg = particle5.pdgCode(); + if (pdg == kPi0) { + ++vtxNPi0; + } + if (pdg == kGamma) { + ++vtxNGamma; + } + if (pdg == kNeutron) { + ++vtxNN; + } + // Charged vs neutral via PDG database (Charge() is in units of e/3) + double q = 0.0; + if (auto* part = pdgDB->GetParticle(pdg)) { + q = part->Charge() / 3.0; + } + if (std::abs(q) > 0.0) { + ++vtxNCh; + } else { + ++vtxNNeut; + } + } + + // Fill histos (final selected candidates only) + if (isCex) { + histos.fill(HIST("hVtxNAll_CEX"), vtxNAll); + histos.fill(HIST("hVtxNCh_CEX"), vtxNCh); + histos.fill(HIST("hVtxNNeut_CEX"), vtxNNeut); + histos.fill(HIST("hVtxNPi0_CEX"), vtxNPi0); + histos.fill(HIST("hVtxNGamma_CEX"), vtxNGamma); + histos.fill(HIST("hVtxNN_CEX"), vtxNN); + } else { + histos.fill(HIST("hVtxNAll_BG"), vtxNAll); + histos.fill(HIST("hVtxNCh_BG"), vtxNCh); + histos.fill(HIST("hVtxNNeut_BG"), vtxNNeut); + histos.fill(HIST("hVtxNPi0_BG"), vtxNPi0); + histos.fill(HIST("hVtxNGamma_BG"), vtxNGamma); + histos.fill(HIST("hVtxNN_BG"), vtxNN); + } + const float vtxfitDX = secX - antipVx; const float vtxfitDY = secY - antipVy; const float vtxfitDZ = secZ - antipVz; const float vtxfitD3D = std::sqrt(vtxfitDX * vtxfitDX + vtxfitDY * vtxfitDY + vtxfitDZ * vtxfitDZ); + const double dPx = motherPx - sumPx_vtx; + const double dPy = motherPy - sumPy_vtx; + const double dPz = motherPz - sumPz_vtx; + const double deltaP = std::sqrt(dPx * dPx + dPy * dPy + dPz * dPz); + + if (isCex) { + histos.fill(HIST("hDeltaP_CEX"), deltaP); + } else { + histos.fill(HIST("hDeltaP_BG"), deltaP); + } + + if (motherHasTrack) { + if (isCex) { + histos.fill(HIST("hMotherNHitIB_CEX"), motherNHitIB); + } else { + histos.fill(HIST("hMotherNHitIB_BG"), motherNHitIB); + } + } + const uint32_t selMask = 0u; outPairs( isCex, motherPdg, + motherNHitIB, colId, pId, antipId, @@ -780,6 +920,13 @@ struct NucleiAntineutronCex { antipVy, antipVz, + static_cast(vtxNAll), + static_cast(vtxNCh), + static_cast(vtxNNeut), + static_cast(vtxNPi0), + static_cast(vtxNGamma), + static_cast(vtxNN), + cexPairTrkP, cexPairTrkPt, cexPairTrkPz, @@ -818,6 +965,8 @@ struct NucleiAntineutronCex { selMask, pairPointingAngleDeg, + pvsvThetaDeg, + pvsvPhiDeg, pairPBalance, pairPtBalance, pairQ, From c42d40c0e1df669f2a9e8dda945de025fd936e91 Mon Sep 17 00:00:00 2001 From: dyx-11 <1260971129@qq.com> Date: Wed, 18 Mar 2026 15:12:07 +0800 Subject: [PATCH 314/347] [PWGUD] modify the codes and select only gapsideC data (#15407) --- PWGUD/Tasks/flowCorrelationsUpc.cxx | 156 +++++++--------------------- 1 file changed, 38 insertions(+), 118 deletions(-) diff --git a/PWGUD/Tasks/flowCorrelationsUpc.cxx b/PWGUD/Tasks/flowCorrelationsUpc.cxx index fd64d11702a..06da62eef5b 100644 --- a/PWGUD/Tasks/flowCorrelationsUpc.cxx +++ b/PWGUD/Tasks/flowCorrelationsUpc.cxx @@ -62,9 +62,8 @@ using namespace o2::framework::expressions; struct CalcNchUpc { O2_DEFINE_CONFIGURABLE(cfgZVtxCut, float, 10.0f, "Accepted z-vertex range") - O2_DEFINE_CONFIGURABLE(cfgPtCutMin, float, 0.2f, "minimum accepted track pT") - O2_DEFINE_CONFIGURABLE(cfgPtCutMax, float, 10.0f, "maximum accepted track pT") - O2_DEFINE_CONFIGURABLE(cfgEtaCut, float, 0.8f, "Eta cut") + O2_DEFINE_CONFIGURABLE(cfgPtCutMin, float, 0.1f, "minimum accepted track pT") + O2_DEFINE_CONFIGURABLE(cfgEtaCut, float, 0.9f, "Eta cut") O2_DEFINE_CONFIGURABLE(cfgMinMixEventNum, int, 5, "Minimum number of events to mix") // Added UPC Cuts @@ -89,22 +88,27 @@ struct CalcNchUpc { { AxisSpec axisNch = {100, 0, 100}; AxisSpec axisVrtx = {10, -10, 10}; - AxisSpec axisgap = {12, -6, 6}; + // AxisSpec axisgap = {12, -6, 6}; + // std::vector trueGapBins = {-2, -1, 0, 1, 2, 3}; + // AxisSpec axisgap = {trueGapBins, "true gap side"}; + + std::vector binEdges = {-1.5, -0.5, 0.5, 1.5, 2.5, 3.5}; + AxisSpec axisgap = {binEdges, "true gap side"}; + registry.add("truegap", "truegap", {HistType::kTH1D, {axisgap}}); registry.add("Ncharge", "N_{charge}", {HistType::kTH1D, {axisNch}}); registry.add("zVtx_all", "zVtx_all", {HistType::kTH1D, {axisVrtx}}); registry.add("Nch_vs_zVtx", "Nch vs zVtx", {HistType::kTH2D, {axisVrtx, axisNch}}); - registry.add("truegap", "truegap", {HistType::kTH1D, {axisgap}}); + // registry.add("truegap", "truegap", {HistType::kTH1D, {axisgap}}); } void process(UDCollisionsFull::iterator const& collision, UdTracksFull const& tracks) { multiplicityNch(tracks.size()); truegapside(sgSelector.trueGap(collision, cfgCutFV0, cfgCutFT0A, cfgCutFT0C, cfgCutZDC)); + // LOG(info) << "truegapside=" << sgSelector.trueGap(collision, cfgCutFV0, cfgCutFT0A, cfgCutFT0C, cfgCutZDC); registry.fill(HIST("Ncharge"), tracks.size()); - registry.fill(HIST("truegap"), sgSelector.trueGap(collision, cfgCutFV0, cfgCutFT0A, cfgCutFT0C, cfgCutZDC)); registry.fill(HIST("zVtx_all"), collision.posZ()); - registry.fill(HIST("Nch_vs_zVtx"), collision.posZ(), tracks.size()); } }; @@ -113,7 +117,7 @@ struct FlowCorrelationsUpc { O2_DEFINE_CONFIGURABLE(cfgIfVertex, bool, false, "choose vertex or not") O2_DEFINE_CONFIGURABLE(cfgPtCutMin, float, 0.1f, "minimum accepted track pT") O2_DEFINE_CONFIGURABLE(cfgPtCutMax, float, 10.0f, "maximum accepted track pT") - O2_DEFINE_CONFIGURABLE(cfgEtaCut, float, 0.8f, "Eta cut") + O2_DEFINE_CONFIGURABLE(cfgEtaCut, float, 0.9f, "Eta cut") O2_DEFINE_CONFIGURABLE(cfgMinMixEventNum, int, 5, "Minimum number of events to mix") O2_DEFINE_CONFIGURABLE(cfgMinMult, int, 0, "Minimum multiplicity for collision") O2_DEFINE_CONFIGURABLE(cfgMaxMult, int, 10, "Maximum multiplicity for collision") @@ -124,7 +128,7 @@ struct FlowCorrelationsUpc { O2_DEFINE_CONFIGURABLE(cfgRadiusLow, float, 0.8, "Low radius for merging cut") O2_DEFINE_CONFIGURABLE(cfgRadiusHigh, float, 2.5, "High radius for merging cut") O2_DEFINE_CONFIGURABLE(cfgIsGoodItsLayers, bool, false, "whether choose itslayers") - O2_DEFINE_CONFIGURABLE(cfgGapSide, int, 0, "0: gapside A;1:C") + O2_DEFINE_CONFIGURABLE(cfgGapSide, int, 1, "0: gapside A;1:C") O2_DEFINE_CONFIGURABLE(cfgGapSideMerge, bool, false, "whether merge A and C side together") O2_DEFINE_CONFIGURABLE(cfgDcaxy, bool, true, "choose dcaxy") O2_DEFINE_CONFIGURABLE(cfgDcaz, bool, false, "choose dcaz") @@ -161,12 +165,11 @@ struct FlowCorrelationsUpc { // make the filters and cuts. Filter trackFilter = (aod::udtrack::isPVContributor == true); - Filter collisionFilter = (((cfgGapSideMerge == true && (aod::udcollision::gapSide == (uint8_t)1 || aod::udcollision::gapSide == (uint8_t)0)) || aod::udcollision::gapSide == (uint8_t)cfgGapSide) && (cfgIfVertex == false || aod::collision::posZ < cfgZVtxCut) && (aod::udcollision::occupancyInTime > 0 && aod::udcollision::occupancyInTime < cfgCutOccupancyHigh) && ((cfgGapSideMerge == true && (aod::flowcorrupc::truegapside == 0 || aod::flowcorrupc::truegapside == 1)) || aod::flowcorrupc::truegapside == cfgGapSide) && (aod::flowcorrupc::multiplicity > cfgMinMult) && (aod::flowcorrupc::multiplicity < cfgMaxMult)); - // Filter collisionFilter = (nabs(aod::collision::posZ) < cfgZVtxCut) && (aod::flowcorrupc::multiplicity) > cfgMinMult && (aod::flowcorrupc::multiplicity) < cfgMaxMult && (aod::evsel::sel8) == true; - // Filter trackFilter = (nabs(aod::track::eta) < cfgEtaCut) && (aod::track::pt > cfgPtCutMin) && (aod::track::pt < cfgPtCutMax) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)); + Filter collisionFilter = (aod::udcollision::gapSide == (uint8_t)cfgGapSide && (cfgIfVertex == false || aod::collision::posZ < cfgZVtxCut) && (aod::udcollision::occupancyInTime > 0 && aod::udcollision::occupancyInTime < cfgCutOccupancyHigh) && aod::flowcorrupc::truegapside == 1); using UdTracks = soa::Filtered>; using UdTracksFull = soa::Filtered>; + using UDCollisionsFull = soa::Filtered>; // Define the outputs @@ -177,6 +180,8 @@ struct FlowCorrelationsUpc { void init(InitContext&) { + LOG(info) << "cfgGapSide = " << cfgGapSide; + LOG(info) << "cfgGapSide value type: " << typeid(cfgGapSide).name(); LOGF(info, "Starting init"); // Make histograms to check the distributions after cuts registry.add("deltaEta_deltaPhi_same", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEta}}); // check to see the delta eta and delta phi distribution @@ -187,10 +192,16 @@ struct FlowCorrelationsUpc { registry.add("Nch", "N_{ch}", {HistType::kTH1D, {axisMultiplicity}}); registry.add("zVtx", "zVtx", {HistType::kTH1D, {axisVertex}}); registry.add("Nch_vs_zVtx", "Nch vs zVtx", {HistType::kTH2D, {axisVertex, axisMultiplicity}}); + registry.add("Nch_same", "Nch same event", {HistType::kTH1D, {axisMultiplicity}}); + registry.add("Nch_mixed", "Nch mixed event", {HistType::kTH1D, {axisMultiplicity}}); registry.add("Trig_hist", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisPtTrigger}}}); - registry.add("eventcount", "bin", {HistType::kTH1F, {{10, 0, 10, "bin"}}}); // histogram to see how many events are in the same and mixed event + registry.add("eventcount_same", "bin", {HistType::kTH1F, {{10, 0, 10, "bin"}}}); // histogram to see how many events are in the same and mixed event + registry.add("eventcount_mixed", "bin", {HistType::kTH1F, {{10, 0, 10, "bin"}}}); // histogram to see how many events are in the same and mixed event + + registry.add("trackcount_same", "bin", {HistType::kTH1F, {{10, 0, 10, "bin"}}}); // histogram to see how many tracks are in the same and mixed event + registry.add("trackcount_mixed", "bin", {HistType::kTH1F, {{10, 0, 10, "bin"}}}); // histogram to see how many tracks are in the same and mixed event std::vector corrAxis = {{axisSample, "Sample"}, {axisVertex, "z-vtx (cm)"}, @@ -210,8 +221,7 @@ struct FlowCorrelationsUpc { } enum EventType { SameEvent = 1, - MixedEvent = 3, - MixedFinal = 9 + MixedEvent = 3 }; template @@ -234,9 +244,6 @@ struct FlowCorrelationsUpc { if (dPhiStar > constants::math::PI) dPhiStar = constants::math::TwoPI - dPhiStar; - if (dPhiStar < -constants::math::PI) - dPhiStar = -constants::math::TwoPI - dPhiStar; - return dPhiStar; } @@ -352,42 +359,14 @@ struct FlowCorrelationsUpc { void processSame(UDCollisionsFull::iterator const& collision, UdTracksFull const& tracks) { - // if (tracks.size() < cfgMinMult || tracks.size() > cfgMaxMult) { - // return; - // } - // if (cfgIsGoodItsLayers && collision.trs() == 0) { - // return; - // } - - // if (cfgGapSideMerge) { - // int gapSide = collision.gapSide(); - // if (gapSide != 0 && gapSide != 1) { - // return; - // } - // int trueGapSide = sgSelector.trueGap(collision, cfgCutFV0, cfgCutFT0A, cfgCutFT0C, cfgCutZDC); - // int gapSide1 = trueGapSide; - // if (gapSide1 != 0 && gapSide1 != 1) { - // return; - // } - // } - // if (!cfgGapSideMerge) { - // int trueGapSide = sgSelector.trueGap(collision, cfgCutFV0, cfgCutFT0A, cfgCutFT0C, cfgCutZDC); - // int gapSide1 = trueGapSide; - // if (gapSide1 != cfgGapSide) { - // return; - // } - // } - // float vtxz = collision.posZ(); - // if (cfgIfVertex && abs(vtxz) > cfgZVtxCut) { - // return; - // } - // int occupancy = collision.occupancyInTime(); - // if (cfgEvSelOccupancy && (occupancy < cfgCutOccupancyLow || occupancy > cfgCutOccupancyHigh)) { - // return; - // } + LOG(info) << "Event passed filter: truegapside=" << collision.truegapside(); + if (tracks.size() < cfgMinMult || tracks.size() > cfgMaxMult) { + return; + } + registry.fill(HIST("eventcount_same"), 3.5); int runIndex = collision.runNumber(); - registry.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin + // registry.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin registry.fill(HIST("Nch_vs_zVtx"), collision.posZ(), tracks.size()); fillYield(collision, tracks); fillCorrelations(tracks, tracks, collision.posZ(), SameEvent, runIndex); // fill the SE histogram and Sparse @@ -397,80 +376,21 @@ struct FlowCorrelationsUpc { // event mixing SliceCache cache; - // using MixedBinning = FlexibleBinningPolicy, aod::collision::PosZ, aod::flowcorrupc::Multiplicity>; using MixedBinning = ColumnBinningPolicy; // the process for filling the mixed events void processMixed(UDCollisionsFull const& collisions, UdTracksFull const& tracks) { MixedBinning binningOnVtxAndMult{{vtxMix, multMix}, true}; // true is for 'ignore overflows' (true by default) - auto tracksTuple = std::make_tuple(tracks, tracks); - Pair pairs{binningOnVtxAndMult, cfgMinMixEventNum, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip + auto tracksTuple = std::make_tuple(tracks); + SameKindPair pairs{binningOnVtxAndMult, cfgMinMixEventNum, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip for (auto const& [collision1, tracks1, collision2, tracks2] : pairs) { - registry.fill(HIST("eventcount"), MixedEvent); // fill the mixed event in the 3 bin - // if (tracks1.size() < cfgMinMult || tracks1.size() > cfgMaxMult || tracks2.size() < cfgMinMult || tracks2.size() > cfgMaxMult) { - // continue; - // } - // registry.fill(HIST("eventcount"), 4.5); - // if (cfgIsGoodItsLayers && (collision1.trs() == 0 || collision2.trs() == 0)) { - // continue; - // } - // registry.fill(HIST("eventcount"), 5.5); - // if (cfgGapSideMerge) { - // int gapSide = collision1.gapSide(); - // if (gapSide != 0 && gapSide != 1) { - // continue; - // } - // int trueGapSide = sgSelector.trueGap(collision1, cfgCutFV0, cfgCutFT0A, cfgCutFT0C, cfgCutZDC); - // int gapSide1 = trueGapSide; - // if (gapSide1 != 0 && gapSide1 != 1) { - // continue; - // } - // } - // if (!cfgGapSideMerge) { - // int trueGapSide = sgSelector.trueGap(collision1, cfgCutFV0, cfgCutFT0A, cfgCutFT0C, cfgCutZDC); - // int gapSide1 = trueGapSide; - // if (gapSide1 != cfgGapSide) { - // continue; - // } - // } - // if (cfgGapSideMerge) { - // int gapSide = collision2.gapSide(); - // if (gapSide != 0 && gapSide != 1) { - // continue; - // } - // int trueGapSide = sgSelector.trueGap(collision2, cfgCutFV0, cfgCutFT0A, cfgCutFT0C, cfgCutZDC); - // int gapSide2 = trueGapSide; - // if (gapSide2 != 0 && gapSide2 != 1) { - // continue; - // } - // } - // if (!cfgGapSideMerge) { - // int trueGapSide = sgSelector.trueGap(collision2, cfgCutFV0, cfgCutFT0A, cfgCutFT0C, cfgCutZDC); - // int gapSide2 = trueGapSide; - // if (gapSide2 != cfgGapSide) { - // continue; - // } - // } - registry.fill(HIST("eventcount"), 6.5); - // float vtxz = collision1.posZ(); - // if (cfgIfVertex && abs(vtxz) > cfgZVtxCut) { - // continue; - // } - // int occupancy = collision1.occupancyInTime(); - // if (cfgEvSelOccupancy && (occupancy < cfgCutOccupancyLow || occupancy > cfgCutOccupancyHigh)) { - // continue; - // } - // vtxz = collision2.posZ(); - // if (cfgIfVertex && abs(vtxz) > cfgZVtxCut) { - // continue; - // } - // occupancy = collision2.occupancyInTime(); - // if (cfgEvSelOccupancy && (occupancy < cfgCutOccupancyLow || occupancy > cfgCutOccupancyHigh)) { - // continue; - // } - registry.fill(HIST("eventcount"), MixedFinal); + // registry.fill(HIST("eventcount"), MixedEvent); // fill the mixed event in the 3 bin + if (tracks1.size() < cfgMinMult || tracks1.size() > cfgMaxMult || tracks2.size() < cfgMinMult || tracks2.size() > cfgMaxMult) { + continue; + } + registry.fill(HIST("eventcount_same"), 4.5); fillCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent, collision1.runNumber()); // fill the ME histogram and Sparse } } From d9ae6fd2ebf8db495d240b968f640d48c382b95e Mon Sep 17 00:00:00 2001 From: Kegang Xiong Date: Wed, 18 Mar 2026 15:36:36 +0800 Subject: [PATCH 315/347] [PWGCF] Add run2 process (#15435) Co-authored-by: kegangxiong Co-authored-by: ALICE Action Bot --- PWGCF/Flow/Tasks/flowZdcEnergy.cxx | 256 +++++++++++++++++------------ 1 file changed, 147 insertions(+), 109 deletions(-) diff --git a/PWGCF/Flow/Tasks/flowZdcEnergy.cxx b/PWGCF/Flow/Tasks/flowZdcEnergy.cxx index 11f9c2fe4c3..f812b999c33 100644 --- a/PWGCF/Flow/Tasks/flowZdcEnergy.cxx +++ b/PWGCF/Flow/Tasks/flowZdcEnergy.cxx @@ -10,106 +10,85 @@ // or submit itself to any jurisdiction. /// \file flowZdcEnergy.cxx -/// \author Kegang Xiong (kegang.xiong@cern.ch) +/// \author Kegang Xiong /// \since 03/2026 -/// \brief A try to use the znc energy. +/// \brief Study ZDC energy observables versus centrality for Run 2 / Run 3. -#include "Common/Core/EventPlaneHelper.h" -#include "Common/Core/RecoDecay.h" -#include "Common/Core/TrackSelection.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/Qvectors.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPLHCIFData.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "Framework/ASoAHelpers.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" #include "Framework/RunningWorkflowInfo.h" #include "Framework/runDataProcessing.h" -#include "TF1.h" -#include "TPDGCode.h" - -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include using namespace o2; using namespace o2::framework; -using namespace o2::framework::expressions; -using namespace o2::aod::rctsel; -// using namespace o2::analysis; #define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable NAME{#NAME, DEFAULT, HELP}; struct flowZdcEnergy { - struct : ConfigurableGroup { - // Additional event selections - O2_DEFINE_CONFIGURABLE(cfgCentMin, float, 0, "Minimum cenrality for selected events"); - O2_DEFINE_CONFIGURABLE(cfgCentMax, float, 90, "Maximum cenrality for selected events"); - O2_DEFINE_CONFIGURABLE(cfgVtxZ, float, 10.0f, "Accepted z-vertex range for selected events") - } EvSel; - - // Configurables containing vector - O2_DEFINE_CONFIGURABLE(cfgEtaMax, float, 0.8f, "Maximum track #eta") - O2_DEFINE_CONFIGURABLE(cfgPtMin, float, 0.2f, "Minimum track #P_{t}") - O2_DEFINE_CONFIGURABLE(cfgPtMax, float, 10.0f, "Maximum track #P_{t}") - O2_DEFINE_CONFIGURABLE(cfgDcaXYMax, float, 0.2f, "Maximum DCAxy") - O2_DEFINE_CONFIGURABLE(cfgDcaZMax, float, 2.0f, "Maximum DCAz") - - enum SelectionCriteria { - evSel_AllEvent, - evSel_sel8, - evSel_Zvtx, - evSel_CentCuts, - evSel_BCHasZDC, - evSel_isSelectedZDC, - nEventSelections + struct : ConfigurableGroup{ + O2_DEFINE_CONFIGURABLE(cfgCentMin, float, 0.f, "Minimum centrality for selected events") + O2_DEFINE_CONFIGURABLE(cfgCentMax, float, 90.f, "Maximum centrality for selected events") + O2_DEFINE_CONFIGURABLE(cfgVtxZ, float, 10.f, "Accepted z-vertex range")} evsel; + + ConfigurableAxis axisCent{"axisCent", {90, 0, 90}, "Centrality (%)"}; + ConfigurableAxis axisMult{"axisMult", {100, 0, 100000}, "Multiplicity"}; + ConfigurableAxis axisEnergy{"axisEnergy", {300, 0, 300}, "Energy"}; + ConfigurableAxis axisRescaledDiff{"axisRescaledDiff", {400, -1, 1}, "(EA-EC)/(EA+EC)"}; + + // Event counter bins + enum SelectionCriteria : uint8_t { + kAllEvents = 0, + kSeln, + kZvtx, + kCentrality, + kBCHasZDC, + kSelectedZDC, + kNSelections }; - ConfigurableAxis axisCent = {"axisCent", {100, 0, 100}, "Centrality(%)"}; - ConfigurableAxis axisEnergy = {"axisEnergy", {300, 0, 300}, "Energy"}; - ConfigurableAxis axisRescaledDiff = {"axisRescaledDiff", {400, -1, 1}, "(#E_{A}-#E_{C}) / (#E_{A}+#E_{C})"}; - - // Filter trackFilter = nabs(aod::track::eta) < cfgEtaMax && aod::track::pt > cfgPtMin&& aod::track::pt < cfgPtMax && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)) && nabs(aod::track::dcaXY) < cfgDcaXYMax&& nabs(aod::track::dcaZ) < cfgDcaZMax; - - // using UsedTracks = soa::Filtered>; - using ZDCCollisions = soa::Join; - using BCsRun3 = soa::Join; - - // Connect to ccdb Service ccdb; - HistogramRegistry registry{"registry"}; + // Run 3 + using CollisionsRun3 = soa::Join; + using BCsRun3 = soa::Join; + // Run 2 + using CollisionsRun2 = soa::Join; + using BCsRun2 = soa::Join; + void init(InitContext const&) { ccdb->setURL("http://alice-ccdb.cern.ch"); ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); - int64_t now = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + auto now = std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()) + .count(); ccdb->setCreatedNotAfter(now); - // QA hist - registry.add("hEventCount", "Number of Event; Cut; #Events Passed Cut", {HistType::kTH1D, {{nEventSelections, 0, nEventSelections}}}); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_AllEvent + 1, "All events"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_sel8 + 1, "Sel8"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_Zvtx + 1, "Z vertex cut event"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_CentCuts + 1, "Cenrality range"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_BCHasZDC + 1, "BCHasZDC"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_isSelectedZDC + 1, "isSelected"); - // ana hist + registry.add("hEventCount", "Event counter;Selection;Events", {HistType::kTH1D, {{kNSelections, 0, kNSelections}}}); + auto hCount = registry.get(HIST("hEventCount")); + hCount->GetXaxis()->SetBinLabel(kAllEvents + 1, "All events"); + hCount->GetXaxis()->SetBinLabel(kSeln + 1, "Sel7/8"); + hCount->GetXaxis()->SetBinLabel(kZvtx + 1, "Zvtx"); + hCount->GetXaxis()->SetBinLabel(kCentrality + 1, "Centrality"); + hCount->GetXaxis()->SetBinLabel(kBCHasZDC + 1, "BC has ZDC"); + hCount->GetXaxis()->SetBinLabel(kSelectedZDC + 1, "Selected ZDC"); + + registry.add("hCentrality", "", {HistType::kTH1D, {axisCent}}); + registry.add("hMultiplicity", "", {HistType::kTH1D, {axisMult}}); + registry.add("hEnergyWithCent_ZNA_Common", "", {HistType::kTH2D, {axisEnergy, axisCent}}); registry.add("hEnergyWithCent_ZNC_Common", "", {HistType::kTH2D, {axisEnergy, axisCent}}); registry.add("hEnergyWithCent_RescaledDiff", "", {HistType::kTH2D, {axisRescaledDiff, axisCent}}); @@ -126,65 +105,124 @@ struct flowZdcEnergy { registry.add("hEnergyWithCent_RescaledSumDiff", "", {HistType::kTH2D, {axisRescaledDiff, axisCent}}); } - void process(ZDCCollisions::iterator const& collision, BCsRun3 const& /*bcs*/, aod::Zdcs const& /*zdcs*/) + // Helper: event selection + template + bool acceptEvent(TCollision const& collision, float centrality, const int runmode) { + registry.fill(HIST("hEventCount"), kAllEvents); - double centrality = collision.centFT0C(); - // event selection - registry.fill(HIST("hEventCount"), evSel_AllEvent); - if (!collision.sel8()) { - return; + if (runmode == 2 && !collision.sel7()) { + return false; } - registry.fill(HIST("hEventCount"), evSel_sel8); - if (std::abs(collision.posZ()) > EvSel.cfgVtxZ) { - return; + if (runmode == 3 && !collision.sel8()) { + return false; } - registry.fill(HIST("hEventCount"), evSel_Zvtx); - if (centrality < EvSel.cfgCentMin || centrality > EvSel.cfgCentMax) { - return; + registry.fill(HIST("hEventCount"), kSeln); + + if (std::abs(collision.posZ()) > evsel.cfgVtxZ) { + return false; + } + registry.fill(HIST("hEventCount"), kZvtx); + + if (centrality < evsel.cfgCentMin || centrality > evsel.cfgCentMax) { + return false; } - registry.fill(HIST("hEventCount"), evSel_CentCuts); + registry.fill(HIST("hEventCount"), kCentrality); - const auto& foundBC = collision.foundBC_as(); + return true; + } + + // Helper: fill ZDC observables + template + void fillZDCObservables(TCollision const& collision, float centrality) + { + const auto& foundBC = collision.template foundBC_as(); if (!foundBC.has_zdc()) { return; } - registry.fill(HIST("hEventCount"), evSel_BCHasZDC); + registry.fill(HIST("hEventCount"), kBCHasZDC); - const auto& zdcCol = foundBC.zdc(); - if (zdcCol.energyCommonZNA() <= 0 || zdcCol.energyCommonZNC() <= 0) { + const auto& zdc = foundBC.zdc(); + if (zdc.energyCommonZNA() <= 1.f || zdc.energyCommonZNC() <= 1.f) { return; } - registry.fill(HIST("hEventCount"), evSel_isSelectedZDC); + registry.fill(HIST("hEventCount"), kSelectedZDC); + + const float energyCommonZNA = zdc.energyCommonZNA(); + const float energyCommonZNC = zdc.energyCommonZNC(); + const float energySectorZNA1 = zdc.energySectorZNA()[0]; + const float energySectorZNA2 = zdc.energySectorZNA()[1]; + const float energySectorZNA3 = zdc.energySectorZNA()[2]; + const float energySectorZNA4 = zdc.energySectorZNA()[3]; + const float energySectorZNC1 = zdc.energySectorZNC()[0]; + const float energySectorZNC2 = zdc.energySectorZNC()[1]; + const float energySectorZNC3 = zdc.energySectorZNC()[2]; + const float energySectorZNC4 = zdc.energySectorZNC()[3]; + + const float sumEnergyZNA = energySectorZNA1 + energySectorZNA2 + energySectorZNA3 + energySectorZNA4; + const float sumEnergyZNC = energySectorZNC1 + energySectorZNC2 + energySectorZNC3 + energySectorZNC4; + + const float commonDen = energyCommonZNA + energyCommonZNC; + const float sumDen = sumEnergyZNA + sumEnergyZNC; + + registry.fill(HIST("hEnergyWithCent_ZNA_Common"), energyCommonZNA, centrality); + registry.fill(HIST("hEnergyWithCent_ZNC_Common"), energyCommonZNC, centrality); + registry.fill(HIST("hEnergyWithCent_ZNA_1"), energySectorZNA1, centrality); + registry.fill(HIST("hEnergyWithCent_ZNA_2"), energySectorZNA2, centrality); + registry.fill(HIST("hEnergyWithCent_ZNA_3"), energySectorZNA3, centrality); + registry.fill(HIST("hEnergyWithCent_ZNA_4"), energySectorZNA4, centrality); + registry.fill(HIST("hEnergyWithCent_ZNC_1"), energySectorZNC1, centrality); + registry.fill(HIST("hEnergyWithCent_ZNC_2"), energySectorZNC2, centrality); + registry.fill(HIST("hEnergyWithCent_ZNC_3"), energySectorZNC3, centrality); + registry.fill(HIST("hEnergyWithCent_ZNC_4"), energySectorZNC4, centrality); + registry.fill(HIST("hEnergyWithCent_ZNA_SumSectors"), sumEnergyZNA, centrality); + registry.fill(HIST("hEnergyWithCent_ZNC_SumSectors"), sumEnergyZNC, centrality); + + if (commonDen > 1.e-6f) { + registry.fill(HIST("hEnergyWithCent_RescaledDiff"), (energyCommonZNA - energyCommonZNC) / commonDen, centrality); + } + if (sumDen > 1.e-6f) { + registry.fill(HIST("hEnergyWithCent_RescaledSumDiff"), (sumEnergyZNA - sumEnergyZNC) / sumDen, centrality); + } + } - double SumEnergyZNA = zdcCol.energySectorZNA()[0] + zdcCol.energySectorZNA()[1] + zdcCol.energySectorZNA()[2] + zdcCol.energySectorZNA()[3]; - double SumEnergyZNC = zdcCol.energySectorZNC()[0] + zdcCol.energySectorZNC()[1] + zdcCol.energySectorZNC()[2] + zdcCol.energySectorZNC()[3]; - double commonDen = zdcCol.energyCommonZNA() + zdcCol.energyCommonZNC(); - double sumDen = SumEnergyZNA + SumEnergyZNC; + // Run 3 process + void processRun3(CollisionsRun3::iterator const& collision, + BCsRun3 const&, + aod::Zdcs const&) + { + const float centrality = collision.centFT0C(); + const float multi = collision.multFT0C(); - if (commonDen > 1e-3) { - registry.fill(HIST("hEnergyWithCent_RescaledDiff"), - (zdcCol.energyCommonZNA() - zdcCol.energyCommonZNC()) / commonDen, - centrality); + if (!acceptEvent(collision, centrality, 3)) { + return; } - if (sumDen > 1e-3) { - registry.fill(HIST("hEnergyWithCent_RescaledSumDiff"), - (SumEnergyZNA - SumEnergyZNC) / sumDen, - centrality); + registry.fill(HIST("hCentrality"), centrality); + registry.fill(HIST("hMultiplicity"), multi); + + fillZDCObservables(collision, centrality); + } + + // Run 2 process + void processRun2(CollisionsRun2::iterator const& collision, + BCsRun2 const&, + aod::Zdcs const&) + { + const float centrality = collision.centRun2V0M(); + const float multi = collision.multFV0M(); + + if (!acceptEvent(collision, centrality, 2)) { + return; } - registry.fill(HIST("hEnergyWithCent_ZNA_Common"), zdcCol.energyCommonZNA(), centrality); - registry.fill(HIST("hEnergyWithCent_ZNC_Common"), zdcCol.energyCommonZNC(), centrality); - registry.fill(HIST("hEnergyWithCent_ZNA_1"), zdcCol.energySectorZNA()[0], centrality); - registry.fill(HIST("hEnergyWithCent_ZNA_2"), zdcCol.energySectorZNA()[1], centrality); - registry.fill(HIST("hEnergyWithCent_ZNA_3"), zdcCol.energySectorZNA()[2], centrality); - registry.fill(HIST("hEnergyWithCent_ZNA_4"), zdcCol.energySectorZNA()[3], centrality); - registry.fill(HIST("hEnergyWithCent_ZNC_1"), zdcCol.energySectorZNC()[0], centrality); - registry.fill(HIST("hEnergyWithCent_ZNC_2"), zdcCol.energySectorZNC()[1], centrality); - registry.fill(HIST("hEnergyWithCent_ZNC_3"), zdcCol.energySectorZNC()[2], centrality); - registry.fill(HIST("hEnergyWithCent_ZNC_4"), zdcCol.energySectorZNC()[3], centrality); - registry.fill(HIST("hEnergyWithCent_ZNA_SumSectors"), SumEnergyZNA, centrality); - registry.fill(HIST("hEnergyWithCent_ZNC_SumSectors"), SumEnergyZNC, centrality); + registry.fill(HIST("hCentrality"), centrality); + registry.fill(HIST("hMultiplicity"), multi); + + fillZDCObservables(collision, centrality); } + + // Process switches + PROCESS_SWITCH(flowZdcEnergy, processRun3, "Process Run 3 data", true); + PROCESS_SWITCH(flowZdcEnergy, processRun2, "Process Run 2 data", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) From 7761640c51ec8a7ff260926d2983602d6d23abc8 Mon Sep 17 00:00:00 2001 From: Maxim Virta <84773378+MaximVirta@users.noreply.github.com> Date: Wed, 18 Mar 2026 09:46:04 +0100 Subject: [PATCH 316/347] [PWGCF] V02 analysis initial commit (#15426) Co-authored-by: MaximVirta Co-authored-by: ALICE Action Bot --- PWGCF/GenericFramework/Tasks/CMakeLists.txt | 4 + PWGCF/GenericFramework/Tasks/flowGfwV02.cxx | 740 ++++++++++++++++++++ 2 files changed, 744 insertions(+) create mode 100644 PWGCF/GenericFramework/Tasks/flowGfwV02.cxx diff --git a/PWGCF/GenericFramework/Tasks/CMakeLists.txt b/PWGCF/GenericFramework/Tasks/CMakeLists.txt index 338f173aa73..6238192e1be 100644 --- a/PWGCF/GenericFramework/Tasks/CMakeLists.txt +++ b/PWGCF/GenericFramework/Tasks/CMakeLists.txt @@ -18,3 +18,7 @@ o2physics_add_dpl_workflow(flow-gfw-light-ions SOURCES flowGfwLightIons.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::GFWCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(flow-gfw-v02 + SOURCES flowGfwV02.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::GFWCore + COMPONENT_NAME Analysis) \ No newline at end of file diff --git a/PWGCF/GenericFramework/Tasks/flowGfwV02.cxx b/PWGCF/GenericFramework/Tasks/flowGfwV02.cxx new file mode 100644 index 00000000000..725e86277f4 --- /dev/null +++ b/PWGCF/GenericFramework/Tasks/flowGfwV02.cxx @@ -0,0 +1,740 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +// +/// \file flowGfwV02.cxx +/// \brief Skeleton copy of flowGfwLightIons with empty function bodies +/// \author Emil Gorm Nielsen, NBI, emil.gorm.nielsen@cern.ch + +#include "FlowContainer.h" +#include "FlowPtContainer.h" +#include "GFW.h" +#include "GFWConfig.h" +#include "GFWCumulant.h" +#include "GFWPowerArray.h" +#include "GFWWeights.h" +#include "GFWWeightsList.h" + +#include "PWGCF/DataModel/CorrelationsDerived.h" +#include "PWGCF/JCorran/DataModel/JCatalyst.h" + +#include "Common/Core/TrackSelection.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponseITS.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/PID.h" +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace o2; +using namespace o2::framework; + +#define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable NAME{#NAME, DEFAULT, HELP}; +static constexpr float LongArrayFloat[3][20] = {{1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2}, {2.1, 2.2, 2.3, -2.1, -2.2, -2.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2}, {3.1, 3.2, 3.3, -3.1, -3.2, -3.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2}}; + +namespace o2::analysis::gfw +{ +std::vector ptbinning = {0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2, 2.2, 2.4, 2.6, 2.8, 3, 3.5, 4, 5, 6, 8, 10}; +float ptpoilow = 0.2, ptpoiup = 10.0; +float ptreflow = 0.2, ptrefup = 3.0; +float ptlow = 0.2, ptup = 10.0; +int etabins = 16; +float etalow = -0.8, etaup = 0.8; +int vtxZbins = 40; +float vtxZlow = -10.0, vtxZup = 10.0; +int phibins = 72; +float philow = 0.0; +float phiup = o2::constants::math::TwoPI; +int nchbins = 300; +float nchlow = 0; +float nchup = 3000; +std::vector centbinning(90); +int nBootstrap = 10; +std::vector> etagapsPtPt; +GFWRegions regions; +GFWCorrConfigs configs; +} // namespace o2::analysis::gfw + +struct FlowGfwV02 { + O2_DEFINE_CONFIGURABLE(cfgNbootstrap, int, 10, "Number of subsamples") + O2_DEFINE_CONFIGURABLE(cfgMpar, int, 4, "Highest order of pt-pt correlations") + O2_DEFINE_CONFIGURABLE(cfgCentEstimator, int, 0, "0:FT0C; 1:FT0CVariant1; 2:FT0M; 3:FT0A") + O2_DEFINE_CONFIGURABLE(cfgEfficiency, std::string, "", "CCDB path to efficiency object") + O2_DEFINE_CONFIGURABLE(cfgAcceptance, std::string, "", "CCDB path to acceptance object") + O2_DEFINE_CONFIGURABLE(cfgFixedMultMin, int, 1, "Minimum for fixed nch range"); + O2_DEFINE_CONFIGURABLE(cfgFixedMultMax, int, 3000, "Maximum for fixed nch range"); + O2_DEFINE_CONFIGURABLE(cfgTofPtCut, float, 0.5f, "Minimum pt to use TOF N-sigma") + O2_DEFINE_CONFIGURABLE(cfgUseItsPID, bool, true, "Use ITS PID for particle identification") + O2_DEFINE_CONFIGURABLE(cfgGetNsigmaQA, bool, true, "Get QA histograms for selection of pions, kaons, and protons") + O2_DEFINE_CONFIGURABLE(cfgUseMultiplicityFlowWeights, bool, true, "Enable or disable the use of multiplicity-based event weighting"); + O2_DEFINE_CONFIGURABLE(cfgConsistentEventFlag, int, 15, "Flag for consistent event selection"); + + Configurable cfgGFWBinning{"cfgGFWBinning", {40, 16, 72, 300, 0, 3000, 0.2, 10.0, 0.2, 5.0, {0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1, 1.25, 1.5, 1.75, 2, 2.25, 2.5, 2.75, 3, 3.25, 3.5, 3.75, 4, 4.5, 5}, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90}}, "Configuration for binning"}; + Configurable cfgRegions{"cfgRegions", {{"refN", "refP", "refFull", "refMid", "piP", "kaP", "prP"}, {-0.8, 0.5, -0.8, -0.4, 0.5, 0.5, 0.5}, {-0.5, 0.8, 0.8, 0.4, 0.8, 0.8, 0.8}, {0, 0, 0, 0, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1}}, "Configurations for GFW regions"}; + + Configurable cfgCorrConfig{"cfgCorrConfig", {{"refP {2} refN {-2}", "piP {2} refN {-2}", "kaP {2} refN {-2}", "prP {2} refN {-2}", "refFull {2 -2}", "refFull {2 -2}", "refFull {2 -2}", "refFull {2 -2}", "refFull {2 -2}", "refFull {2 -2}", "refFull {2 -2}", "refFull {2 -2}", "refFull {2 -2}"}, {"ChGap22", "PiGap22", "KaGap22", "PrGap22", "ChFull22", "nchCh", "nchPi", "nchKa", "nchPr", "v02ptCh", "v02ptPi", "v02ptKa", "v02ptPr"}, {0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {15, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, "Configurations for each correlation to calculate"}; + Configurable> nSigmas{"nSigmas", {LongArrayFloat[0], 6, 3, {"UpCut_pi", "UpCut_ka", "UpCut_pr", "LowCut_pi", "LowCut_ka", "LowCut_pr"}, {"TPC", "TOF", "ITS"}}, "Labeled array for n-sigma values for TPC, TOF, ITS for pions, kaons, protons (positive and negative)"}; + + struct : ConfigurableGroup { + Configurable cfgPtMin{"cfgPtMin", 0.2f, "Minimum pT used for track selection."}; + Configurable cfgPtMax{"cfgPtMax", 5.0f, "Maximum pT used for track selection."}; + Configurable cfgEtaMax{"cfgEtaMax", 0.8f, "Maximum eta used for track selection."}; + } cfgTrackCuts; + + struct : ConfigurableGroup { + Configurable cfgZvtxMax{"cfgZvtxMax", 10.0f, "Maximum primary vertex cut applied for the events."}; + Configurable cfgMultMin{"cfgMultMin", 10, "Minimum number of particles required for the event to have."}; + } cfgEventCuts; + + // // Filters to be applied to the received data. + // // The analysis assumes the data has been subjected to a QA of its selection, + // // and thus only the final distributions of the data for analysis are saved. + o2::framework::expressions::Filter collFilter = (nabs(aod::collision::posZ) < cfgEventCuts.cfgZvtxMax); + o2::framework::expressions::Filter trackFilter = (aod::track::pt > cfgTrackCuts.cfgPtMin) && (aod::track::pt < cfgTrackCuts.cfgPtMax) && (nabs(aod::track::eta) < cfgTrackCuts.cfgEtaMax); + o2::framework::expressions::Filter cftrackFilter = (aod::cftrack::pt > cfgTrackCuts.cfgPtMin) && (aod::cftrack::pt < cfgTrackCuts.cfgPtMax); // eta cuts done by jfluc + + // Connect to ccdb + Service ccdb; + + struct Config { + TH1D* mEfficiency = nullptr; + GFWWeights* mAcceptance; + bool correctionsLoaded = false; + } cfg; + + // Define output + OutputObj fFC{FlowContainer("FlowContainer")}; + HistogramRegistry registry{"registry"}; + + std::unique_ptr fGFW{std::make_unique()}; + std::unique_ptr fRndm{std::make_unique(0)}; + std::unique_ptr fSecondAxis{nullptr}; + std::vector corrconfigs; + int lastRun = -1; + + // region indices for consistency flag + int posRegionIndex = -1; + int negRegionIndex = -1; + int fullRegionIndex = -1; + int midRegionIndex = -1; + // PID + + struct PIDState { + o2::aod::ITSResponse itsResponse; + std::array tofNsigmaCut; + std::array itsNsigmaCut; + std::array tpcNsigmaCut; + TH1D* hPtMid[4] = {nullptr, nullptr, nullptr, nullptr}; + ConfigurableAxis axisPt{"axisPt", {VARIABLE_WIDTH, 0.2, 0.5, 1, 1.5, 2, 3, 4, 6, 10}, "pt axis for histograms"}; + ConfigurableAxis axisNsigmaTPC{"axisNsigmaTPC", {80, -5, 5}, "nsigmaTPC axis"}; + ConfigurableAxis axisNsigmaTOF{"axisNsigmaTOF", {80, -5, 5}, "nsigmaTOF axis"}; + ConfigurableAxis axisNsigmaITS{"axisNsigmaITS", {80, -5, 5}, "nsigmaITS axis"}; + ConfigurableAxis axisTpcSignal{"axisTpcSignal", {250, 0, 250}, "dEdx axis for TPC"}; + }; + PIDState pidStates; + + using GFWTracks = soa::Filtered>; + + enum PIDIndex { + kCharged = 0, + kPions, + kKaons, + kProtons + }; + enum PiKpArrayIndex { + iPionUp = 0, + iKaonUp, + iProtonUp, + iPionLow, + iKaonLow, + iProtonLow + }; + enum DetectorType { + kTPC = 0, + kTOF, + kITS + }; + + void init(InitContext const&) + { + + pidStates.tpcNsigmaCut[iPionUp] = nSigmas->getData()[iPionUp][kTPC]; + pidStates.tpcNsigmaCut[iKaonUp] = nSigmas->getData()[iKaonUp][kTPC]; + pidStates.tpcNsigmaCut[iProtonUp] = nSigmas->getData()[iProtonUp][kTPC]; + pidStates.tpcNsigmaCut[iPionLow] = nSigmas->getData()[iPionLow][kTPC]; + pidStates.tpcNsigmaCut[iKaonLow] = nSigmas->getData()[iKaonLow][kTPC]; + pidStates.tpcNsigmaCut[iProtonLow] = nSigmas->getData()[iProtonLow][kTPC]; + + pidStates.tofNsigmaCut[iPionUp] = nSigmas->getData()[iPionUp][kTOF]; + pidStates.tofNsigmaCut[iKaonUp] = nSigmas->getData()[iKaonUp][kTOF]; + pidStates.tofNsigmaCut[iProtonUp] = nSigmas->getData()[iProtonUp][kTOF]; + pidStates.tofNsigmaCut[iPionLow] = nSigmas->getData()[iPionLow][kTOF]; + pidStates.tofNsigmaCut[iKaonLow] = nSigmas->getData()[iKaonLow][kTOF]; + pidStates.tofNsigmaCut[iProtonLow] = nSigmas->getData()[iProtonLow][kTOF]; + + pidStates.itsNsigmaCut[iPionUp] = nSigmas->getData()[iPionUp][kITS]; + pidStates.itsNsigmaCut[iKaonUp] = nSigmas->getData()[iKaonUp][kITS]; + pidStates.itsNsigmaCut[iProtonUp] = nSigmas->getData()[iProtonUp][kITS]; + pidStates.itsNsigmaCut[iPionLow] = nSigmas->getData()[iPionLow][kITS]; + pidStates.itsNsigmaCut[iKaonLow] = nSigmas->getData()[iKaonLow][kITS]; + pidStates.itsNsigmaCut[iProtonLow] = nSigmas->getData()[iProtonLow][kITS]; + + if (cfgGetNsigmaQA) { + if (!cfgUseItsPID) { + registry.add("TofTpcNsigma_before", "", {HistType::kTHnSparseD, {{pidStates.axisNsigmaTPC, pidStates.axisNsigmaTOF, pidStates.axisPt}}}); + registry.add("TofTpcNsigma_after", "", {HistType::kTHnSparseD, {{pidStates.axisNsigmaTPC, pidStates.axisNsigmaTOF, pidStates.axisPt}}}); + } + if (cfgUseItsPID) { + registry.add("TofItsNsigma_before", "", {HistType::kTHnSparseD, {{pidStates.axisNsigmaITS, pidStates.axisNsigmaTOF, pidStates.axisPt}}}); + registry.add("TofItsNsigma_after", "", {HistType::kTHnSparseD, {{pidStates.axisNsigmaITS, pidStates.axisNsigmaTOF, pidStates.axisPt}}}); + } + + registry.add("TpcdEdx_ptwise", "", {HistType::kTH2D, {{pidStates.axisTpcSignal, pidStates.axisPt}}}); + registry.add("TpcdEdx_ptwise_afterCut", "", {HistType::kTH2D, {{pidStates.axisTpcSignal, pidStates.axisPt}}}); + } + + o2::analysis::gfw::regions.SetNames(cfgRegions->GetNames()); + o2::analysis::gfw::regions.SetEtaMin(cfgRegions->GetEtaMin()); + o2::analysis::gfw::regions.SetEtaMax(cfgRegions->GetEtaMax()); + o2::analysis::gfw::regions.SetpTDifs(cfgRegions->GetpTDifs()); + o2::analysis::gfw::regions.SetBitmasks(cfgRegions->GetBitmasks()); + o2::analysis::gfw::configs.SetCorrs(cfgCorrConfig->GetCorrs()); + o2::analysis::gfw::configs.SetHeads(cfgCorrConfig->GetHeads()); + o2::analysis::gfw::configs.SetpTDifs(cfgCorrConfig->GetpTDifs()); + o2::analysis::gfw::configs.SetpTCorrMasks(cfgCorrConfig->GetpTCorrMasks()); + o2::analysis::gfw::regions.Print(); + o2::analysis::gfw::configs.Print(); + o2::analysis::gfw::ptbinning = cfgGFWBinning->GetPtBinning(); + o2::analysis::gfw::ptpoilow = cfgGFWBinning->GetPtPOImin(); + o2::analysis::gfw::ptpoiup = cfgGFWBinning->GetPtPOImax(); + o2::analysis::gfw::ptreflow = cfgGFWBinning->GetPtRefMin(); + o2::analysis::gfw::ptrefup = cfgGFWBinning->GetPtRefMax(); + o2::analysis::gfw::ptlow = cfgTrackCuts.cfgPtMin; + o2::analysis::gfw::ptup = cfgTrackCuts.cfgPtMax; + o2::analysis::gfw::etabins = cfgGFWBinning->GetEtaBins(); + o2::analysis::gfw::vtxZbins = cfgGFWBinning->GetVtxZbins(); + o2::analysis::gfw::phibins = cfgGFWBinning->GetPhiBins(); + o2::analysis::gfw::philow = 0.0f; + o2::analysis::gfw::phiup = o2::constants::math::TwoPI; + o2::analysis::gfw::nchbins = cfgGFWBinning->GetNchBins(); + o2::analysis::gfw::nchlow = cfgGFWBinning->GetNchMin(); + o2::analysis::gfw::nchup = cfgGFWBinning->GetNchMax(); + o2::analysis::gfw::centbinning = cfgGFWBinning->GetCentBinning(); + cfgGFWBinning->Print(); + + // Initialise pt spectra histograms for different particles + pidStates.hPtMid[kCharged] = new TH1D("hPtMid_charged", "hPtMid_charged", o2::analysis::gfw::ptbinning.size() - 1, &o2::analysis::gfw::ptbinning[0]); + pidStates.hPtMid[kPions] = new TH1D("hPtMid_pions", "hPtMid_pions", o2::analysis::gfw::ptbinning.size() - 1, &o2::analysis::gfw::ptbinning[0]); + pidStates.hPtMid[kKaons] = new TH1D("hPtMid_kaons", "hPtMid_kaons", o2::analysis::gfw::ptbinning.size() - 1, &o2::analysis::gfw::ptbinning[0]); + pidStates.hPtMid[kProtons] = new TH1D("hPtMid_protons", "hPtMid_protons", o2::analysis::gfw::ptbinning.size() - 1, &o2::analysis::gfw::ptbinning[0]); + pidStates.hPtMid[kCharged]->SetDirectory(nullptr); + pidStates.hPtMid[kPions]->SetDirectory(nullptr); + pidStates.hPtMid[kKaons]->SetDirectory(nullptr); + pidStates.hPtMid[kProtons]->SetDirectory(nullptr); + + AxisSpec phiAxis = {o2::analysis::gfw::phibins, o2::analysis::gfw::philow, o2::analysis::gfw::phiup, "#phi"}; + AxisSpec etaAxis = {o2::analysis::gfw::etabins, -cfgTrackCuts.cfgEtaMax, cfgTrackCuts.cfgEtaMax, "#eta"}; + AxisSpec vtxAxis = {o2::analysis::gfw::vtxZbins, -cfgEventCuts.cfgZvtxMax, cfgEventCuts.cfgZvtxMax, "Vtx_{z} (cm)"}; + AxisSpec ptAxis = {o2::analysis::gfw::ptbinning, "#it{p}_{T} GeV/#it{c}"}; + + std::string sCentralityEstimator = "FT0C centrality (%)"; + AxisSpec centAxis = {o2::analysis::gfw::centbinning, sCentralityEstimator.c_str()}; + + std::vector nchbinning; + int nchskip = (o2::analysis::gfw::nchup - o2::analysis::gfw::nchlow) / o2::analysis::gfw::nchbins; + for (int i = 0; i <= o2::analysis::gfw::nchbins; ++i) { + nchbinning.push_back(nchskip * i + o2::analysis::gfw::nchlow + 0.5); + } + AxisSpec nchAxis = {nchbinning, "N_{ch}"}; + registry.add("v02pt", "", {HistType::kTProfile2D, {ptAxis, centAxis}}); + registry.add("nchMid", "", {HistType::kTProfile2D, {ptAxis, centAxis}}); + + ccdb->setURL("http://alice-ccdb.cern.ch"); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + + int64_t now = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + ccdb->setCreatedNotAfter(now); + + int ptbins = o2::analysis::gfw::ptbinning.size() - 1; + fSecondAxis = std::make_unique(ptbins, &o2::analysis::gfw::ptbinning[0]); + + // QA histograms + registry.add("trackQA/before/phi_eta_vtxZ", "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); + registry.add("trackQA/before/nch_pt", "#it{p}_{T} vs multiplicity; N_{ch}; #it{p}_{T}", {HistType::kTH2D, {nchAxis, ptAxis}}); + registry.addClone("trackQA/before/", "trackQA/after/"); + registry.add("trackQA/after/pt_ref", "", {HistType::kTH1D, {{100, o2::analysis::gfw::ptreflow, o2::analysis::gfw::ptrefup}}}); + registry.add("trackQA/after/pt_poi", "", {HistType::kTH1D, {{100, o2::analysis::gfw::ptpoilow, o2::analysis::gfw::ptpoiup}}}); + + registry.add("eventQA/before/multiplicity", "", {HistType::kTH1D, {nchAxis}}); + registry.add("eventQA/before/centrality", "", {HistType::kTH1D, {centAxis}}); + registry.addClone("eventQA/before/", "eventQA/after/"); + + if (o2::analysis::gfw::regions.GetSize() < 0) + LOGF(error, "Configuration contains vectors of different size - check the GFWRegions configurable"); + for (auto i(0); i < o2::analysis::gfw::regions.GetSize(); ++i) { + fGFW->AddRegion(o2::analysis::gfw::regions.GetNames()[i], o2::analysis::gfw::regions.GetEtaMin()[i], o2::analysis::gfw::regions.GetEtaMax()[i], (o2::analysis::gfw::regions.GetpTDifs()[i]) ? ptbins + 1 : 1, o2::analysis::gfw::regions.GetBitmasks()[i]); + } + for (auto i = 0; i < o2::analysis::gfw::configs.GetSize(); ++i) { + corrconfigs.push_back(fGFW->GetCorrelatorConfig(o2::analysis::gfw::configs.GetCorrs()[i], o2::analysis::gfw::configs.GetHeads()[i], o2::analysis::gfw::configs.GetpTDifs()[i])); + } + if (corrconfigs.empty()) + LOGF(error, "Configuration contains vectors of different size - check the GFWCorrConfig configurable"); + fGFW->CreateRegions(); + TObjArray* oba = new TObjArray(); + addConfigObjectsToObjArray(oba, corrconfigs); + LOGF(info, "Number of correlators: %d", oba->GetEntries()); + fFC->SetName("FlowContainer"); + fFC->SetXAxis(fSecondAxis.get()); + fFC->Initialize(oba, centAxis, cfgNbootstrap); + delete oba; + + if (cfgConsistentEventFlag) { + posRegionIndex = [&]() { + auto begin = cfgRegions->GetNames().begin(); + auto end = cfgRegions->GetNames().end(); + auto it = std::find(begin, end, "refP"); + return (it != end) ? std::distance(begin, it) : -1; + }(); + negRegionIndex = [&]() { + auto begin = cfgRegions->GetNames().begin(); + auto end = cfgRegions->GetNames().end(); + auto it = std::find(begin, end, "refN"); + return (it != end) ? std::distance(begin, it) : -1; + }(); + fullRegionIndex = [&]() { + auto begin = cfgRegions->GetNames().begin(); + auto end = cfgRegions->GetNames().end(); + auto it = std::find(begin, end, "refFull"); + return (it != end) ? std::distance(begin, it) : -1; + }(); + midRegionIndex = [&]() { + auto begin = cfgRegions->GetNames().begin(); + auto end = cfgRegions->GetNames().end(); + auto it = std::find(begin, end, "refMid"); + return (it != end) ? std::distance(begin, it) : -1; + }(); + } + } + + static constexpr std::string_view FillTimeName[] = {"before/", "after/"}; + enum QAFillTime { + kBefore, + kAfter + }; + + void addConfigObjectsToObjArray(TObjArray* oba, const std::vector& configs) + { + for (auto it = configs.begin(); it != configs.end(); ++it) { + if (it->pTDif) { + std::string suffix = "_ptDiff"; + for (auto i = 0; i < fSecondAxis->GetNbins(); ++i) { + std::string index = Form("_pt_%i", i + 1); + oba->Add(new TNamed(it->Head.c_str() + index, it->Head.c_str() + suffix)); + } + } else { + oba->Add(new TNamed(it->Head.c_str(), it->Head.c_str())); + } + } + } + + template + int getNsigmaPID(TTrack track) + { + // Computing Nsigma arrays for pion, kaon, and protons + std::array nSigmaTPC = {track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr()}; + std::array nSigmaTOF = {track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr()}; + std::array nSigmaITS = {pidStates.itsResponse.nSigmaITS(track), pidStates.itsResponse.nSigmaITS(track), pidStates.itsResponse.nSigmaITS(track)}; + int pid = -1; // -1 = not identified, 1 = pion, 2 = kaon, 3 = proton + + std::array nSigmaToUse = cfgUseItsPID ? nSigmaITS : nSigmaTPC; // Choose which nSigma to use: TPC or ITS + std::array detectorNsigmaCut = cfgUseItsPID ? pidStates.itsNsigmaCut : pidStates.tpcNsigmaCut; // Choose which nSigma to use: TPC or ITS + + bool isPion, isKaon, isProton; + bool isDetectedPion = nSigmaToUse[iPionUp] < detectorNsigmaCut[iPionUp] && nSigmaToUse[iPionUp] > detectorNsigmaCut[iPionLow]; + bool isDetectedKaon = nSigmaToUse[iKaonUp] < detectorNsigmaCut[iKaonUp] && nSigmaToUse[iKaonUp] > detectorNsigmaCut[iKaonLow]; + bool isDetectedProton = nSigmaToUse[iProtonUp] < detectorNsigmaCut[iProtonUp] && nSigmaToUse[iProtonUp] > detectorNsigmaCut[iProtonLow]; + + bool isTofPion = nSigmaTOF[iPionUp] < pidStates.tofNsigmaCut[iPionUp] && nSigmaTOF[iPionUp] > pidStates.tofNsigmaCut[iPionLow]; + bool isTofKaon = nSigmaTOF[iKaonUp] < pidStates.tofNsigmaCut[iKaonUp] && nSigmaTOF[iKaonUp] > pidStates.tofNsigmaCut[iKaonLow]; + bool isTofProton = nSigmaTOF[iProtonUp] < pidStates.tofNsigmaCut[iProtonUp] && nSigmaTOF[iProtonUp] > pidStates.tofNsigmaCut[iProtonLow]; + + if (track.pt() > cfgTofPtCut && !track.hasTOF()) { + return -1; + } else if (track.pt() > cfgTofPtCut && track.hasTOF()) { + isPion = isTofPion && isDetectedPion; + isKaon = isTofKaon && isDetectedKaon; + isProton = isTofProton && isDetectedProton; + } else { + isPion = isDetectedPion; + isKaon = isDetectedKaon; + isProton = isDetectedProton; + } + + if ((isPion && isKaon) || (isPion && isProton) || (isKaon && isProton)) { + return -1; // more than one particle satisfy the criteria + } + + if (isPion) { + pid = kPions; + } else if (isKaon) { + pid = kKaons; + } else if (isProton) { + pid = kProtons; + } else { + return -1; // no particle satisfies the criteria + } + + return pid; // -1 = not identified, 1 = pion, 2 = kaon, 3 = proton + } + + void loadCorrections(aod::BCsWithTimestamps::iterator const& bc) + { + uint64_t timestamp = bc.timestamp(); + if (cfg.correctionsLoaded) + return; + if (!cfgAcceptance.value.empty()) { + cfg.mAcceptance = ccdb->getForRun(cfgAcceptance.value, timestamp); + } + if (!cfgEfficiency.value.empty()) { + cfg.mEfficiency = ccdb->getForTimeStamp(cfgEfficiency, timestamp); + if (cfg.mEfficiency == nullptr) { + LOGF(fatal, "Could not load efficiency histogram from %s", cfgEfficiency.value.c_str()); + } + LOGF(info, "Loaded efficiency histogram from %s (%p)", cfgEfficiency.value.c_str(), (void*)cfg.mEfficiency); + } + cfg.correctionsLoaded = true; + } + + void loadCorrections(int runnumber) + { + if (cfg.correctionsLoaded) + return; + if (!cfgAcceptance.value.empty()) { + cfg.mAcceptance = ccdb->getForRun(cfgAcceptance.value, runnumber); + } + if (!cfgEfficiency.value.empty()) { + cfg.mEfficiency = ccdb->getForRun(cfgEfficiency.value, runnumber); + } + cfg.correctionsLoaded = true; + } + + template + double getAcceptance(TTrack track, const double& /*vtxz*/, const int& /*pidInd*/ = 0) + { + double wacc = 1; + if constexpr (requires { track.weightNUA(); }) + wacc = 1. / track.weightNUA(); + return wacc; + } + + template + double getEfficiency(TTrack track, const int& /*pidInd*/ = 0) + { + double eff = 1.; + if constexpr (requires { track.weightEff(); }) + eff = track.weightEff(); + return eff; + } + + // Define the data type + enum DataType { + kReco, + kGen + }; + + int getPIDIndex(const std::string& corrconfig) + { + if (boost::ifind_first(corrconfig, "pi")) + return kPions; + if (boost::ifind_first(corrconfig, "ka")) + return kKaons; + if (boost::ifind_first(corrconfig, "pr")) + return kProtons; + return kCharged; + } + + GFW::CorrConfig getRelevantCorrName(const int& pidInd) + { + if (pidInd == kPions) + return fGFW->GetCorrelatorConfig("piP {2} refN {-2}", "PiGap22", kFALSE); + if (pidInd == kKaons) + return fGFW->GetCorrelatorConfig("kaP {2} refN {-2}", "KaGap22", kFALSE); + if (pidInd == kProtons) + return fGFW->GetCorrelatorConfig("prP {2} refN {-2}", "PrGap22", kFALSE); + return fGFW->GetCorrelatorConfig("refP {2} refN {-2}", "ChGap22", kFALSE); + } + + template + void fillOutputContainers(const float& centmult, const double& rndm, const int& /*run*/ = 0) + { + for (uint l_ind = 0; l_ind < corrconfigs.size(); ++l_ind) { + if (!corrconfigs.at(l_ind).pTDif) { + auto dnx = fGFW->Calculate(corrconfigs.at(l_ind), 0, kTRUE).real(); + if (dnx == 0) + continue; + auto val = fGFW->Calculate(corrconfigs.at(l_ind), 0, kFALSE).real() / dnx; + + if (std::abs(val) < 1) { + fFC->FillProfile(corrconfigs.at(l_ind).Head.c_str(), centmult, val, (cfgUseMultiplicityFlowWeights) ? dnx : 1.0, rndm); + } + continue; + } + + // Fill pt profiles for different particles + int pidInd = getPIDIndex(corrconfigs.at(l_ind).Head.c_str()); + + // Find the corresponding non-pT-differential correlation configuration + GFW::CorrConfig corrName = getRelevantCorrName(pidInd); // May be used later for QA + + auto dnx = fGFW->Calculate(corrconfigs.at(0), 0, kTRUE).real(); + if (dnx == 0) + continue; + auto val = fGFW->Calculate(corrconfigs.at(0), 0, kFALSE).real() / dnx; + for (int i = 1; i <= fSecondAxis->GetNbins(); i++) { + if (corrconfigs.at(l_ind).Head.find("nch") != std::string::npos) + val = 1.0; + double ptFraction = 0; + if (pidStates.hPtMid[pidInd]->Integral() > 0) { + ptFraction = pidStates.hPtMid[pidInd]->GetBinContent(i) / pidStates.hPtMid[pidInd]->Integral(); + if (std::abs(val) < 1.01) + fFC->FillProfile(Form("%s_pt_%i", corrconfigs.at(l_ind).Head.c_str(), i), centmult, val * ptFraction, (cfgUseMultiplicityFlowWeights) ? dnx : 1.0, rndm); + } + } + } + // Fill the profiles for each pT bin + // printf("Config name: %s\n", corrconfigs.at(0).Head.c_str()); + auto dnx = fGFW->Calculate(corrconfigs.at(0), 0, kTRUE).real(); + if (dnx == 0) + return; + auto val = fGFW->Calculate(corrconfigs.at(0), 0, kFALSE).real() / dnx; + for (int i = 1; i <= fSecondAxis->GetNbins(); i++) { + double ptFraction = 0; + if (pidStates.hPtMid[kCharged]->Integral() > 0) { + ptFraction = pidStates.hPtMid[kCharged]->GetBinContent(i) / pidStates.hPtMid[kCharged]->Integral(); + if (std::abs(val) < 1) + registry.fill(HIST("v02pt"), fSecondAxis->GetBinCenter(i), centmult, val * ptFraction, (cfgUseMultiplicityFlowWeights) ? dnx : 1.0); + // printf("bincenter hPtMid: %f, fsecondaxis: %f\n", hPtMid->GetBinCenter(i), fSecondAxis->GetBinCenter(i)); + registry.fill(HIST("nchMid"), fSecondAxis->GetBinCenter(i), centmult, ptFraction); + } + } + return; + } + + struct XAxis { + float centrality; + int64_t multiplicity; + double time; + }; + + struct AcceptedTracks { + int nPos; + int nNeg; + int nFull; + int nMid; + }; + + template + void processCollision(TCollision collision, TTracks tracks, const XAxis& xaxis, const int& run) + { + float vtxz = collision.posZ(); + if (tracks.size() < 1) + return; + if (xaxis.centrality >= 0 && (xaxis.centrality < o2::analysis::gfw::centbinning.front() || xaxis.centrality > o2::analysis::gfw::centbinning.back())) + return; + if (xaxis.multiplicity < cfgFixedMultMin || xaxis.multiplicity > cfgFixedMultMax) + return; + fGFW->Clear(); + pidStates.hPtMid[kCharged]->Reset(); + pidStates.hPtMid[kPions]->Reset(); + pidStates.hPtMid[kKaons]->Reset(); + pidStates.hPtMid[kProtons]->Reset(); + + float lRandom = fRndm->Rndm(); + + // Loop over tracks and check if they are accepted + AcceptedTracks acceptedTracks{0, 0, 0, 0}; + for (const auto& track : tracks) { + processTrack(track, vtxz, xaxis.multiplicity, run, acceptedTracks); + pidStates.hPtMid[kCharged]->Fill(track.pt(), getEfficiency(track)); + // If PID is identified, fill pt spectrum for the corresponding particle + int pidInd = getNsigmaPID(track); + if (pidInd != -1 && track.eta() > -0.4 && track.eta() < 0.4) { + pidStates.hPtMid[pidInd]->Fill(track.pt(), getEfficiency(track, pidInd)); + } + } + if (cfgConsistentEventFlag & 1) + if (!acceptedTracks.nPos || !acceptedTracks.nNeg) + return; + if (cfgConsistentEventFlag & 2) + if (acceptedTracks.nFull < 4) // o2-linter: disable=magic-number (at least four tracks in full acceptance) + return; + if (cfgConsistentEventFlag & 4) + if (acceptedTracks.nPos < 2 || acceptedTracks.nNeg < 2) // o2-linter: disable=magic-number (at least two tracks in each subevent) + return; + if (cfgConsistentEventFlag & 8) + if (acceptedTracks.nPos < 2 || acceptedTracks.nMid < 2 || acceptedTracks.nNeg < 2) // o2-linter: disable=magic-number (at least two tracks in all three subevents) + return; + // Fill output containers + fillOutputContainers
(xaxis.centrality, lRandom, run); + } + + template + void fillAcceptedTracks(TTrack track, AcceptedTracks& acceptedTracks) + { + if (posRegionIndex >= 0 && track.eta() > o2::analysis::gfw::regions.GetEtaMin()[posRegionIndex] && track.eta() < o2::analysis::gfw::regions.GetEtaMax()[posRegionIndex]) + ++acceptedTracks.nPos; + if (negRegionIndex >= 0 && track.eta() > o2::analysis::gfw::regions.GetEtaMin()[negRegionIndex] && track.eta() < o2::analysis::gfw::regions.GetEtaMax()[negRegionIndex]) + ++acceptedTracks.nNeg; + if (fullRegionIndex >= 0 && track.eta() > o2::analysis::gfw::regions.GetEtaMin()[fullRegionIndex] && track.eta() < o2::analysis::gfw::regions.GetEtaMax()[fullRegionIndex]) + ++acceptedTracks.nFull; + if (midRegionIndex >= 0 && track.eta() > o2::analysis::gfw::regions.GetEtaMin()[midRegionIndex] && track.eta() < o2::analysis::gfw::regions.GetEtaMax()[midRegionIndex]) + ++acceptedTracks.nMid; + } + + template + inline void processTrack(TTrack const& track, const float& vtxz, const int& multiplicity, const int& /*run*/, AcceptedTracks& acceptedTracks) + { + // fillPtSums(track); // Fill pT sums + fillTrackQA(track, vtxz); + registry.fill(HIST("trackQA/before/nch_pt"), multiplicity, track.pt()); + + fillGFW(track, vtxz); // Fill GFW + fillAcceptedTracks(track, acceptedTracks); // Fill accepted tracks + fillTrackQA(track, vtxz); + registry.fill(HIST("trackQA/after/nch_pt"), multiplicity, track.pt()); + } + + template + inline void fillGFW(TTrack track, const double& vtxz) + { + int pidInd = getNsigmaPID(track); + + bool withinPtRef = (track.pt() > o2::analysis::gfw::ptreflow && track.pt() < o2::analysis::gfw::ptrefup); + bool withinPtPOI = (track.pt() > o2::analysis::gfw::ptpoilow && track.pt() < o2::analysis::gfw::ptpoiup); + + if (!withinPtPOI && !withinPtRef) + return; + double weff = getEfficiency(track, pidInd); + if (weff < 0) + return; + + double wacc = getAcceptance(track, vtxz, pidInd); + + // Fill cumulants for different particles + // ***Need to add proper weights for each particle!*** + if (withinPtRef) + fGFW->Fill(track.eta(), fSecondAxis->FindBin(track.pt()) - 1, track.phi(), weff * wacc, 0); + if (withinPtPOI && pidInd == kPions) + fGFW->Fill(track.eta(), fSecondAxis->FindBin(track.pt()) - 1, track.phi(), weff * wacc, kPions); + if (withinPtPOI && pidInd == kKaons) + fGFW->Fill(track.eta(), fSecondAxis->FindBin(track.pt()) - 1, track.phi(), weff * wacc, kKaons); + if (withinPtPOI && pidInd == kProtons) + fGFW->Fill(track.eta(), fSecondAxis->FindBin(track.pt()) - 1, track.phi(), weff * wacc, kProtons); + return; + } + + template + inline void fillTrackQA(TTrack track, const float vtxz) + { + double wacc = getAcceptance(track, vtxz); + registry.fill(HIST("trackQA/") + HIST(FillTimeName[ft]) + HIST("phi_eta_vtxZ"), track.phi(), track.eta(), vtxz, (ft == kAfter) ? wacc : 1.0); + if (ft == kAfter) { + registry.fill(HIST("trackQA/") + HIST(FillTimeName[ft]) + HIST("pt_ref"), track.pt()); + registry.fill(HIST("trackQA/") + HIST(FillTimeName[ft]) + HIST("pt_poi"), track.pt()); + } + return; + } + + double getTimeSinceStartOfFill(uint64_t, int) { return 0.0; } + + void processData(soa::Filtered>::iterator const& collision, aod::BCsWithTimestamps const&, GFWTracks const& tracks) + { + auto bc = collision.bc_as(); + int run = bc.runNumber(); + if (run != lastRun) { + lastRun = run; + LOGF(info, "run = %d", run); + } + + loadCorrections(bc); + const XAxis xaxis{collision.centFT0C(), tracks.size(), -1.0}; + processCollision(collision, tracks, xaxis, run); + } + PROCESS_SWITCH(FlowGfwV02, processData, "Process analysis for non-derived data", true); + + void processCFDerived(aod::CFCollision const& collision, soa::Filtered const& tracks) + { + int run = collision.runNumber(); + if (run != lastRun) { + lastRun = run; + LOGF(info, "run = %d", run); + } + loadCorrections(run); + const XAxis xaxis{collision.multiplicity(), tracks.size(), -1.0}; + + registry.fill(HIST("eventQA/after/centrality"), xaxis.centrality); + registry.fill(HIST("eventQA/after/multiplicity"), xaxis.multiplicity); + + // processCollision(collision, tracks, xaxis, run); + } + PROCESS_SWITCH(FlowGfwV02, processCFDerived, "Process analysis for CF derived data", false); + void processCFDerivedCorrected(aod::CFCollision const& collision, soa::Filtered> const& tracks) + { + int run = collision.runNumber(); + if (run != lastRun) { + lastRun = run; + LOGF(info, "run = %d", run); + } + const XAxis xaxis{collision.multiplicity(), tracks.size(), -1.0}; + registry.fill(HIST("eventQA/after/centrality"), xaxis.centrality); + registry.fill(HIST("eventQA/after/multiplicity"), xaxis.multiplicity); + // processCollision(collision, tracks, xaxis, run); + } + PROCESS_SWITCH(FlowGfwV02, processCFDerivedCorrected, "Process analysis for CF derived data with corrections", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc), + }; +} From 3a05a2a05b73da78cf30b6e99335976b7e39da23 Mon Sep 17 00:00:00 2001 From: gengjiabin12 <997406694@qq.com> Date: Wed, 18 Mar 2026 17:56:25 +0800 Subject: [PATCH 317/347] [PWGLF] Change the MC generated cut (#15413) --- .../Tasks/Strangeness/hStrangeCorrelation.cxx | 33 ++++++++++++------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx b/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx index 0f9dfe5a616..0c0c04f1448 100644 --- a/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx +++ b/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx @@ -90,6 +90,7 @@ struct HStrangeCorrelation { Configurable mixingParameter{"mixingParameter", 10, "how many events are mixed"}; Configurable doMCassociation{"doMCassociation", false, "fill everything only for MC associated"}; Configurable doTriggPhysicalPrimary{"doTriggPhysicalPrimary", false, "require physical primary for trigger particles"}; + Configurable applyNewMCSelection{"applyNewMCSelection", false, "apply new MC Generated selection"}; } masterConfigurations; // master analysis switches @@ -2532,7 +2533,7 @@ struct HStrangeCorrelation { } // Perform basic event selection on both collisions - if ((masterConfigurations.doPPAnalysis && (!isCollisionSelected(collision1) || !isCollisionSelected(collision2))) || (!masterConfigurations.doPPAnalysis && (!isCollisionSelectedPbPb(collision1, true) || (!isCollisionSelectedPbPb(collision2, true))))) { + if ((masterConfigurations.doPPAnalysis && (!isCollisionSelected(collision1) || !isCollisionSelected(collision2))) || (!masterConfigurations.doPPAnalysis && (!isCollisionSelectedPbPb(collision1, false) || (!isCollisionSelectedPbPb(collision2, false))))) { continue; } if (cent1 > axisRanges[5][1] || cent1 < axisRanges[5][0]) @@ -2588,7 +2589,7 @@ struct HStrangeCorrelation { } // Perform basic event selection on both collisions - if ((masterConfigurations.doPPAnalysis && (!isCollisionSelected(collision1) || !isCollisionSelected(collision2))) || (!masterConfigurations.doPPAnalysis && (!isCollisionSelectedPbPb(collision1, true) || (!isCollisionSelectedPbPb(collision2, true))))) { + if ((masterConfigurations.doPPAnalysis && (!isCollisionSelected(collision1) || !isCollisionSelected(collision2))) || (!masterConfigurations.doPPAnalysis && (!isCollisionSelectedPbPb(collision1, false) || (!isCollisionSelectedPbPb(collision2, false))))) { continue; } if (cent1 > axisRanges[5][1] || cent1 < axisRanges[5][0]) @@ -2706,6 +2707,7 @@ struct HStrangeCorrelation { float bestCollisionVtxZ = 0.0f; bool bestCollisionSel8 = false; bool bestCollisionINELgtZERO = false; + bool isCollisionSelect = false; uint32_t bestCollisionTriggerPresenceMap = 0; for (auto const& collision : collisions) { @@ -2713,9 +2715,13 @@ struct HStrangeCorrelation { biggestNContribs = collision.numContrib(); bestCollisionFT0Mpercentile = collision.centFT0M(); bestCollisionFT0Cpercentile = collision.centFT0C(); - bestCollisionSel8 = collision.sel8(); - bestCollisionVtxZ = collision.posZ(); - bestCollisionINELgtZERO = collision.isInelGt0(); + if (masterConfigurations.applyNewMCSelection) { + isCollisionSelect = ((masterConfigurations.doPPAnalysis && isCollisionSelected(collision)) || (!masterConfigurations.doPPAnalysis && isCollisionSelectedPbPb(collision, false))); + } else { + bestCollisionSel8 = collision.sel8(); + bestCollisionVtxZ = collision.posZ(); + bestCollisionINELgtZERO = collision.isInelGt0(); + } if (triggerPresenceMap.size() > 0) bestCollisionTriggerPresenceMap = triggerPresenceMap[collision.globalIndex()]; } @@ -2745,12 +2751,17 @@ struct HStrangeCorrelation { if (triggerPresenceMap.size() > 0 && !TESTBIT(bestCollisionTriggerPresenceMap, triggerBinToSelect)) { return; } - if (!bestCollisionSel8) - return; - if (std::abs(bestCollisionVtxZ) > masterConfigurations.zVertexCut) - return; - if (!bestCollisionINELgtZERO) - return; + if (masterConfigurations.applyNewMCSelection) { + if (!isCollisionSelect) + return; + } else { + if (!bestCollisionSel8) + return; + if (std::abs(bestCollisionVtxZ) > masterConfigurations.zVertexCut) + return; + if (!bestCollisionINELgtZERO) + return; + } histos.fill(HIST("hClosureTestEventCounter"), 3.5f); From 74ff8aa2e372bf86bb890833c36573536ee1d986 Mon Sep 17 00:00:00 2001 From: ariedel-cern <85537041+ariedel-cern@users.noreply.github.com> Date: Wed, 18 Mar 2026 12:42:44 +0100 Subject: [PATCH 318/347] [PWGCF] Fix in femto framework (#15436) --- PWGCF/Femto/Core/partitions.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/PWGCF/Femto/Core/partitions.h b/PWGCF/Femto/Core/partitions.h index c4b039e8c05..ae2ee46a3f9 100644 --- a/PWGCF/Femto/Core/partitions.h +++ b/PWGCF/Femto/Core/partitions.h @@ -17,11 +17,12 @@ #define PWGCF_FEMTO_CORE_PARTITIONS_H_ // collsion selection -#define MAKE_COLLISION_FILTER(selection) \ - (o2::aod::femtocollisions::posZ >= selection.vtxZMin && o2::aod::femtocollisions::posZ <= selection.vtxZMax) && \ - (o2::aod::femtocollisions::mult >= selection.multMin && o2::aod::femtocollisions::mult <= selection.multMax) && \ - (o2::aod::femtocollisions::cent >= selection.centMin && o2::aod::femtocollisions::cent <= selection.centMax) && \ - (o2::aod::femtocollisions::magField >= static_cast(selection.magFieldMin) && o2::aod::femtocollisions::magField <= static_cast(selection.magFieldMax)) && \ +#define MAKE_COLLISION_FILTER(selection) \ + (o2::aod::femtocollisions::posZ >= selection.vtxZMin && o2::aod::femtocollisions::posZ <= selection.vtxZMax) && \ + (o2::aod::femtocollisions::mult >= selection.multMin && o2::aod::femtocollisions::mult <= selection.multMax) && \ + (o2::aod::femtocollisions::cent >= selection.centMin && o2::aod::femtocollisions::cent <= selection.centMax) && \ + (o2::aod::femtocollisions::magField >= o2::framework::expressions::as(selection.magFieldMin) && \ + o2::aod::femtocollisions::magField <= o2::framework::expressions::as(selection.magFieldMax)) && \ ncheckbit(o2::aod::femtocollisions::mask, selection.collisionMask) // macro for track momentum, i.e. ||q|*pT/q| * cosh(eta) From 81858c7d6f3a42e4de6d02ff678e57b9e50e5768 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Tiek=C3=B6tter?= Date: Wed, 18 Mar 2026 14:21:14 +0100 Subject: [PATCH 319/347] [PWGDQ] Changed MyEvents to MyEventsBasic in PrefilterSelection task (#15437) --- PWGDQ/Tasks/tableReader_withAssoc.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWGDQ/Tasks/tableReader_withAssoc.cxx b/PWGDQ/Tasks/tableReader_withAssoc.cxx index 3a8dbe52709..89455c999aa 100644 --- a/PWGDQ/Tasks/tableReader_withAssoc.cxx +++ b/PWGDQ/Tasks/tableReader_withAssoc.cxx @@ -1188,7 +1188,7 @@ struct AnalysisPrefilterSelection { } // end loop over combinations } - void processBarrelSkimmed(MyEvents const& events, soa::Join const& assocs, MyBarrelTracks const& tracks) + void processBarrelSkimmed(MyEventsBasic const& events, soa::Join const& assocs, MyBarrelTracks const& tracks) { fPrefilterMap.clear(); From 248ec335f3038c84aa4c7bffbffb8e5b282b9c89 Mon Sep 17 00:00:00 2001 From: Himanshu Sharma Date: Wed, 18 Mar 2026 16:51:51 +0100 Subject: [PATCH 320/347] [PWGHF] Add nPVcontributors in THnSparse of Upc process in D0 task (#15438) --- PWGHF/D2H/Tasks/taskD0.cxx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/PWGHF/D2H/Tasks/taskD0.cxx b/PWGHF/D2H/Tasks/taskD0.cxx index c7064ab0c67..64d228b45d7 100644 --- a/PWGHF/D2H/Tasks/taskD0.cxx +++ b/PWGHF/D2H/Tasks/taskD0.cxx @@ -369,6 +369,7 @@ struct HfTaskD0 { axes.push_back(thnAxisFDDC); axes.push_back(thnAxisZNA); axes.push_back(thnAxisZNC); + axes.push_back(thnAxisNumPvContr); } if (applyMl) { @@ -591,6 +592,7 @@ struct HfTaskD0 { // Determine gap type using SGSelector with BC range checking const auto gapResult = hf_upc::determineGapType(collision, bcs, upcThresholds); const int gap = gapResult.value; + const auto numPvContributors = collision.numContrib(); // Use the BC with FIT activity if available from SGSelector auto bcForUPC = bc; @@ -652,7 +654,7 @@ struct HfTaskD0 { // Fill THnSparse with structure matching histogram axes: [mass, pt, (mlScores if FillMl), rapidity, d0Type, (cent if storeCentrality), (occ, ir if storeOccupancyAndIR), gapType, FT0A, FT0C, FV0A, FDDA, FDDC, ZNA, ZNC] auto fillTHnData = [&](float mass, int d0Type) { // Pre-calculate vector size to avoid reallocations - constexpr int NAxesBase = 12; // mass, pt, rapidity, d0Type, gapType, FT0A, FT0C, FV0A, FDDA, FDDC, ZNA, ZNC + constexpr int NAxesBase = 13; // mass, pt, rapidity, d0Type, gapType, FT0A, FT0C, FV0A, FDDA, FDDC, ZNA, ZNC, nPVcontr constexpr int NAxesMl = FillMl ? 3 : 0; // 3 ML scores if FillMl int const nAxesCent = storeCentrality ? 1 : 0; // centrality if storeCentrality int const nAxesOccIR = storeOccupancyAndIR ? 2 : 0; // occupancy and IR if storeOccupancyAndIR @@ -686,6 +688,7 @@ struct HfTaskD0 { valuesToFill.push_back(static_cast(fitInfo.ampFDDC)); valuesToFill.push_back(static_cast(zdcEnergyZNA)); valuesToFill.push_back(static_cast(zdcEnergyZNC)); + valuesToFill.push_back(static_cast(numPvContributors)); if constexpr (FillMl) { registry.get(HIST("hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsD0Type"))->Fill(valuesToFill.data()); From f8c5ae75ab476a871c35af9efa76ad529123f39e Mon Sep 17 00:00:00 2001 From: Francesco Mazzaschi <43742195+fmazzasc@users.noreply.github.com> Date: Wed, 18 Mar 2026 17:01:51 +0100 Subject: [PATCH 321/347] [PWGLF] sigmahadrontask: convert thn into thnsparse (#15441) Co-authored-by: Francesco Mazzaschi --- PWGLF/TableProducer/Strangeness/sigmaHadCorr.cxx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/PWGLF/TableProducer/Strangeness/sigmaHadCorr.cxx b/PWGLF/TableProducer/Strangeness/sigmaHadCorr.cxx index c01ba0a264f..d31c384addf 100644 --- a/PWGLF/TableProducer/Strangeness/sigmaHadCorr.cxx +++ b/PWGLF/TableProducer/Strangeness/sigmaHadCorr.cxx @@ -151,11 +151,11 @@ struct sigmaHadCorrTask { if (fillSparseInvMassKstar) { rSigmaHad.add("hSparseSigmaHad", - "7D THn: invmass, k*, sigma charge, hadron charge, sigma decay radius, cosPA, sigma pt", - {HistType::kTHnF, {sigmaMassAxis, kStarAxis, sigmaChargeAxis, hadronChargeAxis, sigmaDecRadiusAxisCoarse, cosPAAxisCoarse, sigmaPtAxisCoarse}}); + "7D THnSparse: invmass, k*, sigma charge, hadron charge, sigma decay radius, cosPA, sigma pt", + {HistType::kTHnSparseF, {sigmaMassAxis, kStarAxis, sigmaChargeAxis, hadronChargeAxis, sigmaDecRadiusAxisCoarse, cosPAAxisCoarse, sigmaPtAxisCoarse}}); rSigmaHad.add("hSparseSigmaHadMC", - "8D THn (MC): invmass, k*, sigma charge, hadron charge, sigma decay radius, cosPA, sigma pt, k* gen", - {HistType::kTHnF, {sigmaMassAxis, kStarAxis, sigmaChargeAxis, hadronChargeAxis, sigmaDecRadiusAxisCoarse, cosPAAxisCoarse, sigmaPtAxisCoarse, kStarAxis}}); + "8D THnSparse (MC): invmass, k*, sigma charge, hadron charge, sigma decay radius, cosPA, sigma pt, k* gen", + {HistType::kTHnSparseF, {sigmaMassAxis, kStarAxis, sigmaChargeAxis, hadronChargeAxis, sigmaDecRadiusAxisCoarse, cosPAAxisCoarse, sigmaPtAxisCoarse, kStarAxis}}); } LOG(info) << "Sigma-hadron correlation task initialized"; From 38c4dce674adb4f84dcd79594d3ec3560e5b590c Mon Sep 17 00:00:00 2001 From: Sushanta Tripathy Date: Wed, 18 Mar 2026 18:02:13 +0100 Subject: [PATCH 322/347] [PWGCF] Adding FT0Cvariant2 option for centrality (#15414) Co-authored-by: Sushanta Tripathy --- PWGCF/TableProducer/filterCorrelations.cxx | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/PWGCF/TableProducer/filterCorrelations.cxx b/PWGCF/TableProducer/filterCorrelations.cxx index 3977682397c..6ceaaa6c815 100644 --- a/PWGCF/TableProducer/filterCorrelations.cxx +++ b/PWGCF/TableProducer/filterCorrelations.cxx @@ -590,6 +590,9 @@ struct MultiplicitySelector { if (doprocessFT0CVariant1) { enabledFunctions++; } + if (doprocessFT0CVariant2) { + enabledFunctions++; + } if (doprocessFT0A) { enabledFunctions++; } @@ -635,6 +638,14 @@ struct MultiplicitySelector { } PROCESS_SWITCH(MultiplicitySelector, processFT0CVariant1, "Select FT0CVariant1 centrality as multiplicity", false); + void processFT0CVariant2(aod::CentFT0CVariant2s const& centralities) + { + for (auto& c : centralities) { + output(c.centFT0CVariant2()); + } + } + PROCESS_SWITCH(MultiplicitySelector, processFT0CVariant2, "Select FT0CVariant2 centrality as multiplicity", false); + void processFT0A(aod::CentFT0As const& centralities) { for (auto& c : centralities) { From 2c81c815d8b0c80ddc8fa18386bf63b12ff57b7e Mon Sep 17 00:00:00 2001 From: Marvin Hemmer <53471402+mhemmer-cern@users.noreply.github.com> Date: Wed, 18 Mar 2026 18:25:36 +0100 Subject: [PATCH 323/347] [PWGEM] PM: Add TooCloseV0 cut to `AreSelectedRunning` function call: (#15442) --- PWGEM/PhotonMeson/Core/V0PhotonCut.cxx | 22 +++ PWGEM/PhotonMeson/Core/V0PhotonCut.h | 210 ++++++++++++++++++++--- PWGEM/PhotonMeson/Tasks/calibTaskEmc.cxx | 40 ++++- 3 files changed, 246 insertions(+), 26 deletions(-) diff --git a/PWGEM/PhotonMeson/Core/V0PhotonCut.cxx b/PWGEM/PhotonMeson/Core/V0PhotonCut.cxx index 5abc97c5d1c..0511e72d0c7 100644 --- a/PWGEM/PhotonMeson/Core/V0PhotonCut.cxx +++ b/PWGEM/PhotonMeson/Core/V0PhotonCut.cxx @@ -115,6 +115,28 @@ void V0PhotonCut::RejectITSib(bool flag) mRejectITSib = flag; LOG(info) << "V0 Photon Cut, reject photon on ITSib: " << mRejectITSib; } + +void V0PhotonCut::setTooCloseType(V0PhotonCut::TooCloseCuts type) +{ + mTooCloseType = type; + LOG(info) << "V0 Photon Cut, TooCloseV0 cut type: " << static_cast(mTooCloseType); +} +void V0PhotonCut::setMinV0DistSquared(float value) +{ + mMinV0DistSquared = value; + LOG(info) << "V0 Photon Cut, min V0 distance squared: " << mMinV0DistSquared; +} +void V0PhotonCut::setDeltaR(float value) +{ + mDeltaR = value; + LOG(info) << "V0 Photon Cut, delta R for too close V0: " << mDeltaR; +} +void V0PhotonCut::setMinOpeningAngle(float value) +{ + mMinOpeningAngle = value; + LOG(info) << "V0 Photon Cut, min opening angle for too close V0: " << mMinOpeningAngle; +} + void V0PhotonCut::SetTPCNsigmaElRange(float min, float max) { mMinTPCNsigmaEl = min; diff --git a/PWGEM/PhotonMeson/Core/V0PhotonCut.h b/PWGEM/PhotonMeson/Core/V0PhotonCut.h index f73cbf6d16a..664981df21e 100644 --- a/PWGEM/PhotonMeson/Core/V0PhotonCut.h +++ b/PWGEM/PhotonMeson/Core/V0PhotonCut.h @@ -27,6 +27,9 @@ #include #include +#include // IWYU pragma: keep +#include +#include #include #include @@ -183,6 +186,7 @@ class V0PhotonCut : public TNamed kRZLine, kOnWwireIB, kOnWwireOB, + kIsTooClose, // leg cut kTrackPtRange, kTrackEtaRange, @@ -206,6 +210,12 @@ class V0PhotonCut : public TNamed kNCuts }; + enum class TooCloseCuts : uint8_t { + kNoCut = 0, + kDistance3D = 1, + kRadAndAngle = 2 + }; + /// \brief add histograms to registry /// \param fRegistry pointer to histogram registry void addQAHistograms(o2::framework::HistogramRegistry* fRegistry = nullptr) const @@ -268,26 +278,27 @@ class V0PhotonCut : public TNamed hPhotonQualityCuts->GetXaxis()->SetBinLabel(12, "RZ_{line}"); hPhotonQualityCuts->GetXaxis()->SetBinLabel(13, "Wire_{IB}"); hPhotonQualityCuts->GetXaxis()->SetBinLabel(14, "Wire_{OB}"); - hPhotonQualityCuts->GetXaxis()->SetBinLabel(15, "#it{p}_{T,leg}"); - hPhotonQualityCuts->GetXaxis()->SetBinLabel(16, "#it{#eta}_{leg}"); - hPhotonQualityCuts->GetXaxis()->SetBinLabel(17, "#it{N}_{cl,TPC}"); - hPhotonQualityCuts->GetXaxis()->SetBinLabel(18, "#it{N}_{cr,TPC}"); - hPhotonQualityCuts->GetXaxis()->SetBinLabel(19, "#it{N}_{cr,TPC}/#it{N}_{cl,TPC}"); - hPhotonQualityCuts->GetXaxis()->SetBinLabel(20, "FracSharedCl"); - hPhotonQualityCuts->GetXaxis()->SetBinLabel(21, "#chi^{2}_{TPC}/NDF"); - hPhotonQualityCuts->GetXaxis()->SetBinLabel(22, "#it{N#sigma}_{e,TPC}"); - hPhotonQualityCuts->GetXaxis()->SetBinLabel(23, "#it{N#sigma}_{#pi,TPC}"); - hPhotonQualityCuts->GetXaxis()->SetBinLabel(24, "DCA_{xy}"); - hPhotonQualityCuts->GetXaxis()->SetBinLabel(25, "DCA_{z}"); - hPhotonQualityCuts->GetXaxis()->SetBinLabel(26, "#it{N}_{cl,ITS}"); - hPhotonQualityCuts->GetXaxis()->SetBinLabel(27, "#chi^{2}_{ITS}/NDF"); - hPhotonQualityCuts->GetXaxis()->SetBinLabel(28, "size_{ITS}"); - hPhotonQualityCuts->GetXaxis()->SetBinLabel(29, "ITSTPC"); - hPhotonQualityCuts->GetXaxis()->SetBinLabel(30, "ITSOnly"); - hPhotonQualityCuts->GetXaxis()->SetBinLabel(31, "TPCOnly"); - hPhotonQualityCuts->GetXaxis()->SetBinLabel(32, "TPCTRD"); - hPhotonQualityCuts->GetXaxis()->SetBinLabel(33, "TPCTOF"); - hPhotonQualityCuts->GetXaxis()->SetBinLabel(34, "Out"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(15, "IsTooClose"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(16, "#it{p}_{T,leg}"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(17, "#it{#eta}_{leg}"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(18, "#it{N}_{cl,TPC}"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(19, "#it{N}_{cr,TPC}"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(20, "#it{N}_{cr,TPC}/#it{N}_{cl,TPC}"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(21, "FracSharedCl"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(22, "#chi^{2}_{TPC}/NDF"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(23, "#it{N#sigma}_{e,TPC}"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(24, "#it{N#sigma}_{#pi,TPC}"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(25, "DCA_{xy}"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(26, "DCA_{z}"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(27, "#it{N}_{cl,ITS}"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(28, "#chi^{2}_{ITS}/NDF"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(29, "size_{ITS}"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(30, "ITSTPC"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(31, "ITSOnly"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(32, "TPCOnly"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(33, "TPCTRD"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(34, "TPCTOF"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(35, "Out"); } } @@ -351,6 +362,119 @@ class V0PhotonCut : public TNamed fRegistry->fill(HIST("QA/V0Photon/after/Neg/hTPCHits"), ele.tpcNClsFound(), ele.tpcNClsCrossedRows()); } + /// \brief creates a mask for the V0s if they are too close to another V0 and have higher chi^2 + /// \param v0s V0 table + template + void createCloseV0CutMask(TV0 const& v0s) const + { + const bool useDistance3D = (mTooCloseType == TooCloseCuts::kDistance3D); + const float windowWidth = useDistance3D ? std::sqrt(mMinV0DistSquared) : mDeltaR; + const float cosMinAngle = std::cos(mMinOpeningAngle); + + int tableSize = v0s.size(); + std::vector rejectMask(tableSize, 0); + + if (mTooCloseType == TooCloseCuts::kNoCut) { + mRejectMask = rejectMask; + return; + } + + auto currentV0Iter = v0s.begin(); + auto otherV0Iter = v0s.begin(); + + int groupStart = 0; + while (groupStart < tableSize) { + + // --- find the end of this collision's group --- + int currentCollisionId = v0s.iteratorAt(groupStart).collisionId(); + int groupEnd = groupStart + 1; + while (groupEnd < tableSize && v0s.iteratorAt(groupEnd).collisionId() == currentCollisionId) { + groupEnd++; + } + + int groupSize = groupEnd - groupStart; + + std::vector> indexedRadii(groupSize); + for (int k = 0; k < groupSize; k++) { + currentV0Iter.setCursor(groupStart + k); + indexedRadii[k] = {groupStart + k, currentV0Iter.v0radius()}; + } + std::sort(indexedRadii.begin(), indexedRadii.end(), [](const auto& a, const auto& b) { + return a.second < b.second; + }); + // extract sorted indices and pre-sorted radii + std::vector sortedIndices(groupSize); + std::vector sortedRadii(groupSize); + for (int k = 0; k < groupSize; k++) { + sortedIndices[k] = indexedRadii[k].first; + sortedRadii[k] = indexedRadii[k].second; + } + + // --- sliding window within this group --- + int windowStart = 0; // reset per group + for (int i = 0; i < groupSize; i++) { + + float currentRadius = sortedRadii[i]; + while (windowStart < groupSize && sortedRadii[windowStart] < currentRadius - windowWidth) { + windowStart++; + } + + currentV0Iter.setCursor(sortedIndices[i]); + + float vx1 = currentV0Iter.vx(); + float vy1 = currentV0Iter.vy(); + float vz1 = currentV0Iter.vz(); + + float px1 = currentV0Iter.px(); + float py1 = currentV0Iter.py(); + float pz1 = currentV0Iter.pz(); + float chi2I = currentV0Iter.chiSquareNDF(); + + for (int j = windowStart; j < groupSize; j++) { + if (j == i) { + continue; + } + if (sortedRadii[j] > currentRadius + windowWidth) { + break; + } + + otherV0Iter.setCursor(sortedIndices[j]); + + bool tooClose = false; + if (useDistance3D) { + float dx = vx1 - otherV0Iter.vx(); + float dy = vy1 - otherV0Iter.vy(); + float dz = vz1 - otherV0Iter.vz(); + float distSquared = dx * dx + dy * dy + dz * dz; + tooClose = distSquared < mMinV0DistSquared; + } else { + float px2 = otherV0Iter.px(), py2 = otherV0Iter.py(), pz2 = otherV0Iter.pz(); + float dot = px1 * px2 + py1 * py2 + pz1 * pz2; + float mag1 = px1 * px1 + py1 * py1 + pz1 * pz1; + float mag2 = px2 * px2 + py2 * py2 + pz2 * pz2; + float denom = std::sqrt(mag1 * mag2); + if (denom > 0) { + float cosAngle = dot / denom; + cosAngle = std::clamp(cosAngle, -1.0f, 1.0f); + tooClose = cosAngle > cosMinAngle; + } + } + + if (tooClose) { + if (chi2I > otherV0Iter.chiSquareNDF()) { + rejectMask[sortedIndices[i]] = 1; + + } else { + rejectMask[sortedIndices[j]] = 1; + } + } + } + } + groupStart = groupEnd; + } + mRejectMask = rejectMask; + } + /// \brief check if given v0 photon survives all cuts /// \param flags EMBitFlags where results will be stored /// \param v0s v0 photon table to check @@ -360,6 +484,8 @@ class V0PhotonCut : public TNamed if (v0s.size() <= 0) { return; } + + createCloseV0CutMask(v0s); // auto legIter = legs.begin(); // auto legEnd = legs.end(); size_t iV0 = 0; @@ -489,6 +615,13 @@ class V0PhotonCut : public TNamed } } + if (!IsSelectedV0(v0, V0PhotonCuts::kIsTooClose)) { + if (doQA) { + fRegistry->fill(HIST("QA/V0Photon/hPhotonQualityCuts"), static_cast(V0PhotonCuts::kIsTooClose) + 1, v0Pt); + } + return false; + } + for (const auto& track : {pos, ele}) { if (!IsSelectedTrack(track, V0PhotonCuts::kTrackPtRange)) { if (doQA) { @@ -707,11 +840,24 @@ class V0PhotonCut : public TNamed case V0PhotonCuts::kAP: return std::pow(v0.alpha() / mMaxAlpha, 2) + std::pow(v0.qtarm() / mMaxQt, 2) < 1.0; - case V0PhotonCuts::kPsiPair: - return true; + // TODO: implement fully + case V0PhotonCuts::kPsiPair: { + if constexpr (requires { v0.psipair(); }) { + // return (std::fabs(v0.psipair() < 0.18f * std::exp( -0.55f * v0.chiSquareNDF()))); + return true; + } else { + return true; + } + } - case V0PhotonCuts::kPhiV: - return true; + // TODO: implement fully + case V0PhotonCuts::kPhiV: { + if constexpr (requires { v0.phiv(); }) { + return true; + } else { + return true; + } + } case V0PhotonCuts::kRxy: { if (v0.v0radius() < mMinRxy || mMaxRxy < v0.v0radius()) { @@ -775,6 +921,12 @@ class V0PhotonCut : public TNamed float dxy = std::sqrt(std::pow(x - x_exp, 2) + std::pow(y - y_exp, 2)); return !(dxy > margin_xy); } + case V0PhotonCuts::kIsTooClose: { + if (mRejectMask.size() == 0) { + return true; + } + return (mRejectMask[v0.globalIndex()] == 0); + } default: return false; } @@ -950,6 +1102,11 @@ class V0PhotonCut : public TNamed void SetOnWwireOB(bool flag = false); void RejectITSib(bool flag = false); + void setTooCloseType(V0PhotonCut::TooCloseCuts type); + void setMinV0DistSquared(float value); + void setDeltaR(float value); + void setMinOpeningAngle(float value); + void SetTrackPtRange(float minPt = 0.f, float maxPt = 1e10f); void SetTrackEtaRange(float minEta = -1e10f, float maxEta = 1e10f); void SetMinNClustersTPC(int minNClustersTPC); @@ -1017,6 +1174,11 @@ class V0PhotonCut : public TNamed bool mIsOnWwireIB{false}; bool mIsOnWwireOB{false}; bool mRejectITSib{false}; + TooCloseCuts mTooCloseType{V0PhotonCut::TooCloseCuts::kRadAndAngle}; // for TooCloseV0Cut: either squared distance between conversion points OR opening angle and deltaR + float mMinV0DistSquared{1.}; // for TooCloseV0Cut: cut value when using squared distance between conversion points + float mDeltaR{6.}; // for TooCloseV0Cut: V0PhotonCut::TooCloseCuts::kRadAndAngle when deltaR < this -> compare chi2 + float mMinOpeningAngle{0.02}; // for TooCloseV0Cut: V0PhotonCut::TooCloseCuts::kRadAndAngle when opening angle < this -> compare chi2 + mutable std::vector mRejectMask{}; // ML cuts bool mApplyMlCuts{false}; diff --git a/PWGEM/PhotonMeson/Tasks/calibTaskEmc.cxx b/PWGEM/PhotonMeson/Tasks/calibTaskEmc.cxx index 1d9ca1dbfeb..8d0b0ee7b3a 100644 --- a/PWGEM/PhotonMeson/Tasks/calibTaskEmc.cxx +++ b/PWGEM/PhotonMeson/Tasks/calibTaskEmc.cxx @@ -183,6 +183,11 @@ struct CalibTaskEmc { o2::framework::Configurable rejectV0onITSib{"rejectV0onITSib", true, "flag to reject V0s on ITSib"}; o2::framework::Configurable applyPrefilter{"applyPrefilter", false, "flag to apply prefilter to V0"}; + o2::framework::Configurable mTooCloseType{"mTooCloseType", 2, "type of cut for too close (0 = no, 1 = squared distance, 2 = opening angle + dR) "}; + o2::framework::Configurable mMinV0DistSquared{"mMinV0DistSquared", 4.f, "min squared distance for mTooCloseType == 1"}; + o2::framework::Configurable mDeltaR{"mDeltaR", 6.f, "deltaR for mTooCloseType == 2"}; + o2::framework::Configurable mMinOpeningAngle{"mMinOpeningAngle", 0.02, "min opening angle for mTooCloseType == 2"}; + o2::framework::Configurable minNClusterTPC{"minNClusterTPC", 0, "min NCluster TPC"}; o2::framework::Configurable minNCrossedRowsTPC{"minNCrossedRowsTPC", 40, "min ncrossed rows in TPC"}; o2::framework::Configurable minNCrossedRowsOverFindableClustersTPC{"minNCrossedRowsOverFindableClustersTPC", 0.8f, "min fraction of crossed rows over findable clusters in TPC"}; @@ -324,6 +329,10 @@ struct CalibTaskEmc { fV0PhotonCut.SetRxyRange(pcmcuts.minRV0, pcmcuts.maxRV0); fV0PhotonCut.SetAPRange(pcmcuts.maxAlphaAP, pcmcuts.maxQtAP); fV0PhotonCut.RejectITSib(pcmcuts.rejectV0onITSib); + fV0PhotonCut.setTooCloseType(static_cast(pcmcuts.mTooCloseType.value)); + fV0PhotonCut.setMinV0DistSquared(pcmcuts.mMinV0DistSquared); + fV0PhotonCut.setDeltaR(pcmcuts.mDeltaR); + fV0PhotonCut.setMinOpeningAngle(pcmcuts.mMinOpeningAngle); // for track fV0PhotonCut.SetMinNClustersTPC(pcmcuts.minNClusterTPC); @@ -364,20 +373,25 @@ struct CalibTaskEmc { const AxisSpec thAxisEnergy{1000, 0., 100., "#it{E}_{clus} (GeV)"}; const AxisSpec thAxisEta{320, -0.8, 0.8, "#eta"}; const AxisSpec thAxisPhi{500, 0, 2 * 3.14159, "phi"}; + const AxisSpec thAxisOpeningAngle{180, 0, o2::constants::math::PI, "opening angle (rad)"}; const AxisSpec thnAxisMixingVtx{mixingConfig.cfgVtxBins, "#it{z} (cm)"}; const AxisSpec thnAxisMixingCent{mixingConfig.cfgCentBins, "Centrality (%)"}; if (doprocessEMCal || doprocessEMCalPCMC) { - registry.add("hSparsePi0", "m_{inv} vs p_T vs cent for same event", HistType::kTH3D, {thnAxisInvMass, thAxisEnergyCalib, thnAxisCent}); + registry.add("hSparsePi0", "m_{inv} vs E vs cent for same event", HistType::kTH3D, {thnAxisInvMass, thAxisEnergyCalib, thnAxisCent}); + registry.add("hOpeningAngleSE", "opening vs E vs cent for same event", HistType::kTH3D, {thAxisOpeningAngle, thAxisEnergyCalib, thnAxisCent}); } else if (doprocessPCM) { registry.add("hSparsePi0", "m_{inv} vs p_T vs cent for same event", HistType::kTH3D, {thnAxisInvMass, thnAxisPtCalib, thnAxisCent}); + registry.add("hOpeningAngleSE", "opening vs p_T vs cent for same event", HistType::kTH3D, {thAxisOpeningAngle, thnAxisPtCalib, thnAxisCent}); } if (doprocessEMCalMixed || doprocessEMCalPCMMixed) { registry.add("hSparseBkgMix", "m_{inv} vs p_T vs cent for mixed event", HistType::kTH3D, {thnAxisInvMass, thAxisEnergyCalib, thnAxisCent}); + registry.add("hOpeningAngleME", "opening vs E vs cent for same event", HistType::kTH3D, {thAxisOpeningAngle, thAxisEnergyCalib, thnAxisCent}); } else if (doprocessPCMMixed) { registry.add("hSparseBkgMix", "m_{inv} vs p_T vs cent for mixed event", HistType::kTH3D, {thnAxisInvMass, thnAxisPtCalib, thnAxisCent}); + registry.add("hOpeningAngleME", "opening vs p_T vs cent for same event", HistType::kTH3D, {thAxisOpeningAngle, thnAxisPtCalib, thnAxisCent}); } if (doprocessEMCalMixed || doprocessEMCalPCMMixed || doprocessPCMMixed) { @@ -428,7 +442,6 @@ struct CalibTaskEmc { /// \param mass is the invariant mass of the candidate /// \param pt is the transverse momentum of the candidate /// \param cent is the centrality of the collision - /// \param sp is the scalar product template void fillThn(const float mass, const float pt, const float cent) { @@ -436,6 +449,17 @@ struct CalibTaskEmc { registry.fill(HIST(HistTypes[histType]), mass, pt, cent); } + /// Fill THnSparse + /// \param openingAngle opening angle between the two photons + /// \param pt is the transverse momentum of the candidate + /// \param cent is the centrality of the collision + template + void fillOpeningAngleHisto(const float openingAngle, const float pt, const float cent) + { + static constexpr std::string_view HistTypes[3] = {"hOpeningAngleSE", "hOpeningAngleRot", "hOpeningAngleME"}; + registry.fill(HIST(HistTypes[histType]), openingAngle, pt, cent); + } + /// Get the centrality /// \param collision is the collision with the centrality information template @@ -636,6 +660,8 @@ struct CalibTaskEmc { continue; } registry.fill(HIST("hMesonCuts"), 6); + float cent = getCentrality(collision); + fillOpeningAngleHisto<0>(openingAngle, vMeson.Pt(), cent); runFlowAnalysis<0>(collision, vMeson, g1.e()); } } @@ -747,6 +773,8 @@ struct CalibTaskEmc { continue; } registry.fill(HIST("hMesonCutsMixed"), 6); + float cent = getCentrality(c1); + fillOpeningAngleHisto<2>(openingAngle, vMeson.Pt(), cent); runFlowAnalysis<2>(c1, vMeson, g1.e()); } } @@ -823,6 +851,8 @@ struct CalibTaskEmc { registry.fill(HIST("hMesonCuts"), 5); continue; } + float cent = getCentrality(collision); + fillOpeningAngleHisto<0>(openingAngle, vMeson.Pt(), cent); runFlowAnalysis<0>(collision, vMeson, g1.corrE()); } } @@ -913,6 +943,8 @@ struct CalibTaskEmc { continue; } registry.fill(HIST("hMesonCutsMixed"), 6); + float cent = getCentrality(c1); + fillOpeningAngleHisto<2>(openingAngle, vMeson.Pt(), cent); runFlowAnalysis<2>(c1, vMeson, g1.corrE()); } } @@ -973,6 +1005,8 @@ struct CalibTaskEmc { registry.fill(HIST("mesonQA/hAlphaPt"), asymmetry, photon1Pt); } registry.fill(HIST("hMesonCuts"), 6); + float cent = getCentrality(collision); + fillOpeningAngleHisto<0>(openingAngle, vMeson.Pt(), cent); runFlowAnalysis<0>(collision, vMeson, photon1Pt); } } // end of loop over collisions @@ -1047,6 +1081,8 @@ struct CalibTaskEmc { registry.fill(HIST("mesonQA/hAlphaPtMixed"), asymmetry, photon1Pt); } registry.fill(HIST("hMesonCutsMixed"), 6); + float cent = getCentrality(c1); + fillOpeningAngleHisto<2>(openingAngle, vMeson.Pt(), cent); runFlowAnalysis<2>(c1, vMeson, photon1Pt); } } From 2715387c780783e906e4b0b3917c1e7743939b1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <26327373+vkucera@users.noreply.github.com> Date: Wed, 18 Mar 2026 19:47:25 +0100 Subject: [PATCH 324/347] [Infrastructure] Sync clang-format version in pre-commit hooks with the CI (#15445) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5d7b8a3726a..f837e1ad5a0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -7,7 +7,7 @@ repos: - id: trailing-whitespace - id: end-of-file-fixer - repo: https://github.com/pre-commit/mirrors-clang-format - rev: v18.1.3 # clang-format version + rev: v20.1.3 # clang-format version (keep synced with https://github.com/alisw/ali-bot/blob/master/.github/workflows/c++-code-formatting.yml) hooks: - id: clang-format - repo: https://github.com/cpplint/cpplint From 26f2805a2a1241ed3e611546131af83edc27be2b Mon Sep 17 00:00:00 2001 From: rolavick Date: Wed, 18 Mar 2026 19:47:55 +0100 Subject: [PATCH 325/347] [PWGUD] Updating the table producer for VM->twotracks Monte Carlo (#15443) Co-authored-by: Roman Lavicka --- .../twoTracksEventTableProducer.cxx | 107 ++++++++++-------- 1 file changed, 61 insertions(+), 46 deletions(-) diff --git a/PWGUD/TableProducer/twoTracksEventTableProducer.cxx b/PWGUD/TableProducer/twoTracksEventTableProducer.cxx index 874761db585..3af6a964021 100644 --- a/PWGUD/TableProducer/twoTracksEventTableProducer.cxx +++ b/PWGUD/TableProducer/twoTracksEventTableProducer.cxx @@ -626,6 +626,7 @@ struct TwoTracksEventTableProducer { // get particles associated to generated collision auto const& partsFromMcColl = parts.sliceBy(partPerMcCollision, mccoll.globalIndex()); int countMothers = 0; + int totalChargedDaughters = 0; for (const auto& particle : partsFromMcColl) { // select only mothers with checking if particle has no mother if (particle.has_mothers()) @@ -644,74 +645,85 @@ struct TwoTracksEventTableProducer { trueMotherY[countMothers - 1] = particle.py(); trueMotherZ[countMothers - 1] = particle.pz(); - // get daughters of the tau + // get daughters of the mother const auto& daughters = particle.daughters_as(); - int countDaughters = 0; for (const auto& daughter : daughters) { // check if it is the charged particle (= no pi0 or neutrino) if (enumMyParticle(daughter.pdgCode()) == -1) continue; - countDaughters++; - // check there is only 1 charged daughter related to 1 tau - if (countDaughters > 1) { + // check we do not have more than 2 charged daughters in total + if (totalChargedDaughters >= 2) { if (verboseInfo) - printLargeMessage("Truth collision has more than 1 charged daughters of no mother particles. Breaking the daughter loop."); + printLargeMessage("Truth collision has more than 2 total charged daughters. Breaking the daughter loop."); histos.get(HIST("Truth/hTroubles"))->Fill(3); problem = true; break; } // fill info for each daughter - trueDaugX[countMothers - 1] = daughter.px(); - trueDaugY[countMothers - 1] = daughter.py(); - trueDaugZ[countMothers - 1] = daughter.pz(); - trueDaugPdgCode[countMothers - 1] = daughter.pdgCode(); + trueDaugX[totalChargedDaughters] = daughter.px(); + trueDaugY[totalChargedDaughters] = daughter.py(); + trueDaugZ[totalChargedDaughters] = daughter.pz(); + trueDaugPdgCode[totalChargedDaughters] = daughter.pdgCode(); // get tracks associated to MC daughter (how well the daughter was reconstructed) auto const& tracksFromDaughter = trks.sliceBy(trackPerMcParticle, daughter.globalIndex()); // check there is exactly 1 track per 1 particle + if (tracksFromDaughter.size() == 0) { + if (verboseInfo) + printLargeMessage("Daughter has no associated track. Skipping this daughter."); + histos.get(HIST("Truth/hTroubles"))->Fill(5); + problem = true; + totalChargedDaughters++; + continue; + } if (tracksFromDaughter.size() > 1) { if (verboseInfo) printLargeMessage("Daughter has more than 1 associated track. Skipping this daughter."); histos.get(HIST("Truth/hTroubles"))->Fill(4); problem = true; + totalChargedDaughters++; continue; } - // grab the track and fill info for reconstructed track (should be done twice) + // grab the track and fill info for reconstructed track const auto& trk = tracksFromDaughter.iteratorAt(0); - px[countMothers - 1] = trk.px(); - py[countMothers - 1] = trk.py(); - pz[countMothers - 1] = trk.pz(); - sign[countMothers - 1] = trk.sign(); - dcaxy[countMothers - 1] = trk.dcaXY(); - dcaz[countMothers - 1] = trk.dcaZ(); - trkTimeRes[countMothers - 1] = trk.trackTimeRes(); - if (countMothers == 1) { + px[totalChargedDaughters] = trk.px(); + py[totalChargedDaughters] = trk.py(); + pz[totalChargedDaughters] = trk.pz(); + sign[totalChargedDaughters] = trk.sign(); + dcaxy[totalChargedDaughters] = trk.dcaXY(); + dcaz[totalChargedDaughters] = trk.dcaZ(); + trkTimeRes[totalChargedDaughters] = trk.trackTimeRes(); + if (totalChargedDaughters == 0) { itsClusterSizesTrk1 = trk.itsClusterSizes(); } else { itsClusterSizesTrk2 = trk.itsClusterSizes(); } - tpcSignal[countMothers - 1] = trk.tpcSignal(); - tpcEl[countMothers - 1] = trk.tpcNSigmaEl(); - tpcMu[countMothers - 1] = trk.tpcNSigmaMu(); - tpcPi[countMothers - 1] = trk.tpcNSigmaPi(); - tpcKa[countMothers - 1] = trk.tpcNSigmaKa(); - tpcPr[countMothers - 1] = trk.tpcNSigmaPr(); - tpcIP[countMothers - 1] = trk.tpcInnerParam(); - tofSignal[countMothers - 1] = trk.tofSignal(); - tofEl[countMothers - 1] = trk.tofNSigmaEl(); - tofMu[countMothers - 1] = trk.tofNSigmaMu(); - tofPi[countMothers - 1] = trk.tofNSigmaPi(); - tofKa[countMothers - 1] = trk.tofNSigmaKa(); - tofPr[countMothers - 1] = trk.tofNSigmaPr(); - tofEP[countMothers - 1] = trk.tofExpMom(); + tpcSignal[totalChargedDaughters] = trk.tpcSignal(); + tpcEl[totalChargedDaughters] = trk.tpcNSigmaEl(); + tpcMu[totalChargedDaughters] = trk.tpcNSigmaMu(); + tpcPi[totalChargedDaughters] = trk.tpcNSigmaPi(); + tpcKa[totalChargedDaughters] = trk.tpcNSigmaKa(); + tpcPr[totalChargedDaughters] = trk.tpcNSigmaPr(); + tpcIP[totalChargedDaughters] = trk.tpcInnerParam(); + tofSignal[totalChargedDaughters] = trk.tofSignal(); + tofEl[totalChargedDaughters] = trk.tofNSigmaEl(); + tofMu[totalChargedDaughters] = trk.tofNSigmaMu(); + tofPi[totalChargedDaughters] = trk.tofNSigmaPi(); + tofKa[totalChargedDaughters] = trk.tofNSigmaKa(); + tofPr[totalChargedDaughters] = trk.tofNSigmaPr(); + tofEP[totalChargedDaughters] = trk.tofExpMom(); + totalChargedDaughters++; } // daughters + if (problem) + break; } // particles } else { // get only the truth information. The reco-level info is left on default // get particles associated to generated collision auto const& partsFromMcColl = parts.sliceBy(partPerMcCollision, mccoll.globalIndex()); int countMothers = 0; + int totalChargedDaughters = 0; for (const auto& particle : partsFromMcColl) { - // select only tauons with checking if particle has no mother + // select only motherless particles if (particle.has_mothers()) continue; countMothers++; @@ -723,39 +735,42 @@ struct TwoTracksEventTableProducer { problem = true; break; } - // fill info for each tau + // fill info for each mother trueMotherX[countMothers - 1] = particle.px(); trueMotherY[countMothers - 1] = particle.py(); trueMotherZ[countMothers - 1] = particle.pz(); - // get daughters of the tau + // get daughters of the mother const auto& daughters = particle.daughters_as(); - int countDaughters = 0; for (const auto& daughter : daughters) { // select only the charged particle (= no pi0 or neutrino) if (enumMyParticle(daughter.pdgCode()) == -1) continue; - countDaughters++; - // check there is only 1 charged daughter related to 1 tau - if (countDaughters > 1) { + // check we do not have more than 2 charged daughters in total + if (totalChargedDaughters >= 2) { if (verboseInfo) - printLargeMessage("Truth collision has more than 1 charged daughters of no mother particles. Breaking the daughter loop."); + printLargeMessage("Truth collision has more than 2 total charged daughters. Breaking the daughter loop."); histos.get(HIST("Truth/hTroubles"))->Fill(13); problem = true; break; } // fill info for each daughter - trueDaugX[countMothers - 1] = daughter.px(); - trueDaugY[countMothers - 1] = daughter.py(); - trueDaugZ[countMothers - 1] = daughter.pz(); - trueDaugPdgCode[countMothers - 1] = daughter.pdgCode(); + trueDaugX[totalChargedDaughters] = daughter.px(); + trueDaugY[totalChargedDaughters] = daughter.py(); + trueDaugZ[totalChargedDaughters] = daughter.pz(); + trueDaugPdgCode[totalChargedDaughters] = daughter.pdgCode(); + totalChargedDaughters++; } // daughters + if (problem) + break; } // particles } // collisions - // decide the channel and set the variable. Only two cahnnels suported now. + // decide the channel and set the variable if ((enumMyParticle(trueDaugPdgCode[0]) == P_ELECTRON) && (enumMyParticle(trueDaugPdgCode[1]) == P_ELECTRON)) trueChannel = CH_EE; + if ((enumMyParticle(trueDaugPdgCode[0]) == P_MUON) && (enumMyParticle(trueDaugPdgCode[1]) == P_MUON)) + trueChannel = CH_MUMU; if ((enumMyParticle(trueDaugPdgCode[0]) == P_ELECTRON) && ((enumMyParticle(trueDaugPdgCode[1]) == P_PION) || (enumMyParticle(trueDaugPdgCode[1]) == P_MUON))) trueChannel = CH_EMUPI; if ((enumMyParticle(trueDaugPdgCode[1]) == P_ELECTRON) && ((enumMyParticle(trueDaugPdgCode[0]) == P_PION) || (enumMyParticle(trueDaugPdgCode[0]) == P_MUON))) From 808c496a01eb5bcb32c1478239d652b889e006c1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 19 Mar 2026 05:53:56 +0900 Subject: [PATCH 326/347] [Infrastructure] Bump actions/upload-artifact from 6 to 7 (#15212) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/mega-linter.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/mega-linter.yml b/.github/workflows/mega-linter.yml index 531bc39add4..7b558e9e825 100644 --- a/.github/workflows/mega-linter.yml +++ b/.github/workflows/mega-linter.yml @@ -49,7 +49,7 @@ jobs: # Upload MegaLinter artifacts - name: Archive production artifacts - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 if: success() || failure() with: name: MegaLinter reports From 088898297de12097ef8f05d3437179580e26bb92 Mon Sep 17 00:00:00 2001 From: Cristian-Moscatelli Date: Thu, 19 Mar 2026 09:12:06 +0100 Subject: [PATCH 327/347] [PWGLF] Implementation of Zorro as event selector in nucleiSpectra.cxx (#15421) Co-authored-by: Cristian Moscatelli --- PWGLF/TableProducer/Nuspex/nucleiSpectra.cxx | 24 ++++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/PWGLF/TableProducer/Nuspex/nucleiSpectra.cxx b/PWGLF/TableProducer/Nuspex/nucleiSpectra.cxx index f4422453858..a412b6a93c4 100644 --- a/PWGLF/TableProducer/Nuspex/nucleiSpectra.cxx +++ b/PWGLF/TableProducer/Nuspex/nucleiSpectra.cxx @@ -256,6 +256,7 @@ enum EvGenSel : uint8_t { kGenTVX = 1 << 0, kGenZvtx = 1 << 1, kGenINELgt0 = 1 << 2, + kHasRecoEv = 1 << 3 }; } // namespace nuclei @@ -347,6 +348,7 @@ struct nucleiSpectra { Configurable cfgSkimmedProcessing{"cfgSkimmedProcessing", false, "Skimmed dataset processing"}; Configurable cfgTriggerList{"cfgTriggerList", "fHe", "Trigger List"}; + Configurable cfgSelectTrgEv{"cfgSelectTrgEv", false, "If true, select events with active trigger list"}; // running variables for track tuner o2::dataformats::DCA mDcaInfoCov; @@ -362,7 +364,7 @@ struct nucleiSpectra { using TrackCandidates = soa::Join; - // Collisions with chentrality + // Collisions with centrality using CollWithCent = soa::Join::iterator; // Flow analysis @@ -613,8 +615,15 @@ struct nucleiSpectra { { auto bc = collision.template bc_as(); initCCDB(bc); + + bool isTriggered = true; + + // Using zorro for selecting only events with active trigger if (cfgSkimmedProcessing) { - zorro.isSelected(bc.globalBC()); /// Just let Zorro do the accounting + isTriggered = zorro.isSelected(bc.globalBC()); /// Just let Zorro do the accounting + if (cfgSelectTrgEv && !isTriggered) { + return; + } } gRandom->SetSeed(bc.timestamp()); @@ -929,7 +938,6 @@ struct nucleiSpectra { { nuclei::candidates.clear(); - bool selectINELgt0 = cfgEventSelections->get(nuclei::evSel::kINELgt0); std::vector goodCollisions(mcCollisions.size(), false); std::vector eventMask(mcCollisions.size(), 0); @@ -971,10 +979,8 @@ struct nucleiSpectra { mask |= nuclei::kGenZvtx; // INEL > 0 selection - if (selectINELgt0) { - if (o2::pwglf::isINELgt0mc(slicedParticles, pdgDB)) { - mask |= nuclei::kGenINELgt0; - } + if (o2::pwglf::isINELgt0mc(slicedParticles, pdgDB)) { + mask |= nuclei::kGenINELgt0; } eventMask[c.globalIndex()] = mask; @@ -987,6 +993,10 @@ struct nucleiSpectra { continue; } goodCollisions[collision.mcCollisionId()] = true; + auto& mask = eventMask[collision.mcCollisionId()]; + mask |= nuclei::kHasRecoEv; + + GenEventMCSel(mask); const auto& slicedTracks = tracks.sliceBy(tracksPerCollisions, collision.globalIndex()); fillDataInfo(collision, slicedTracks); } From 42ffd5a01f37ac4888395668b9ea8684f0328dfd Mon Sep 17 00:00:00 2001 From: EmilGorm <50658075+EmilGorm@users.noreply.github.com> Date: Thu, 19 Mar 2026 09:17:17 +0100 Subject: [PATCH 328/347] [PWGCF] containers and output for pid radial flow (#15440) --- .../Tasks/flowGenericFramework.cxx | 237 ++++++++++++------ 1 file changed, 163 insertions(+), 74 deletions(-) diff --git a/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx b/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx index 7f27550ef6c..de8731f61ca 100644 --- a/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx +++ b/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx @@ -77,6 +77,7 @@ std::vector centbinning(90); int nBootstrap = 10; GFWRegions regions; GFWCorrConfigs configs; +GFWCorrConfigs configsradial; std::vector multGlobalCorrCutPars; std::vector multPVCorrCutPars; std::vector multGlobalPVCorrCutPars; @@ -94,7 +95,7 @@ struct FlowGenericFramework { O2_DEFINE_CONFIGURABLE(cfgFillWeights, bool, false, "Fill NUA weights") O2_DEFINE_CONFIGURABLE(cfgRunByRun, bool, false, "Fill histograms on a run-by-run basis") O2_DEFINE_CONFIGURABLE(cfgFillQA, bool, false, "Fill QA histograms") - O2_DEFINE_CONFIGURABLE(cfgMultCut, bool, true, "Use additional event cut on mult correlations"); + O2_DEFINE_CONFIGURABLE(cfgMultCut, bool, false, "Use additional event cut on mult correlations"); O2_DEFINE_CONFIGURABLE(cfgUseCentralMoments, bool, true, "Use central moments in vn-pt calculations") O2_DEFINE_CONFIGURABLE(cfgUsePID, bool, true, "Enable PID information") O2_DEFINE_CONFIGURABLE(cfgUseGapMethod, bool, false, "Use gap method in vn-pt calculations") @@ -108,7 +109,7 @@ struct FlowGenericFramework { struct : ConfigurableGroup { O2_DEFINE_CONFIGURABLE(cfgDCAxyNSigma, float, 7, "Cut on number of sigma deviations from expected DCA in the transverse direction"); O2_DEFINE_CONFIGURABLE(cfgDCAz, float, 2, "Cut on DCA in the longitudinal direction (cm)"); - O2_DEFINE_CONFIGURABLE(cfgNTPCCls, float, 70, "Cut on number of TPC clusters found"); + O2_DEFINE_CONFIGURABLE(cfgNTPCCls, float, 50, "Cut on number of TPC clusters found"); O2_DEFINE_CONFIGURABLE(cfgNTPCXrows, float, 70, "Cut on number of TPC crossed rows"); O2_DEFINE_CONFIGURABLE(cfgMinNITSCls, float, 5, "Cut on minimum number of ITS clusters found"); O2_DEFINE_CONFIGURABLE(cfgChi2PrITSCls, float, 36, "Cut on chi^2 per ITS clusters found"); @@ -130,7 +131,6 @@ struct FlowGenericFramework { O2_DEFINE_CONFIGURABLE(cfgOccupancySelection, int, 2000, "Max occupancy selection, -999 to disable"); O2_DEFINE_CONFIGURABLE(cfgDoOccupancySel, bool, true, "Bool for event selection on detector occupancy"); O2_DEFINE_CONFIGURABLE(cfgMagField, float, 99999, "Configurable magnetic field; default CCDB will be queried"); - O2_DEFINE_CONFIGURABLE(cfgTofPtCut, float, 0.5, "pt cut on TOF for PID"); O2_DEFINE_CONFIGURABLE(cfgUseDensityDependentCorrection, bool, false, "Use density dependent efficiency correction based on Run 2 measurements"); Configurable> cfgTrackDensityP0{"cfgTrackDensityP0", std::vector{0.7217476707, 0.7384792571, 0.7542625668, 0.7640680200, 0.7701951667, 0.7755299053, 0.7805901710, 0.7849446786, 0.7957356586, 0.8113039262, 0.8211968966, 0.8280558878, 0.8329342135}, "parameter 0 for track density efficiency correction"}; Configurable> cfgTrackDensityP1{"cfgTrackDensityP1", std::vector{-2.169488e-05, -2.191913e-05, -2.295484e-05, -2.556538e-05, -2.754463e-05, -2.816832e-05, -2.846502e-05, -2.843857e-05, -2.705974e-05, -2.477018e-05, -2.321730e-05, -2.203315e-05, -2.109474e-05}, "parameter 1 for track density efficiency correction"}; @@ -151,11 +151,16 @@ struct FlowGenericFramework { O2_DEFINE_CONFIGURABLE(cfgGlobalT0ALowSigma, float, -3., "Number of sigma deviations below expected value in global vs T0A correlation"); O2_DEFINE_CONFIGURABLE(cfgGlobalT0AHighSigma, float, 4, "Number of sigma deviations above expected value in global vs T0A correlation"); } cfgGlobalAsideCorrCuts; + struct ConfigurableGroup { + O2_DEFINE_CONFIGURABLE(cfgUseStrictPID, bool, true, "Use strict PID cuts for TPC") + O2_DEFINE_CONFIGURABLE(cfgTofPtCut, float, 0.5, "pt cut on TOF for PID"); + } cfgPIDCuts; Configurable cfgGFWBinning{"cfgGFWBinning", {40, 16, 72, 300, 0, 3000, 0.2, 10.0, 0.2, 3.0, {0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1, 1.25, 1.5, 1.75, 2, 2.25, 2.5, 2.75, 3, 3.25, 3.5, 3.75, 4, 4.5, 5, 5.5, 6, 7, 8, 9, 10}, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90}}, "Configuration for binning"}; Configurable cfgRegions{"cfgRegions", {{"refN", "refP", "refFull"}, {-0.8, 0.4, -0.8}, {-0.4, 0.8, 0.8}, {0, 0, 0}, {1, 1, 1}}, "Configurations for GFW regions"}; Configurable cfgCorrConfig{"cfgCorrConfig", {{"refP {2} refN {-2}", "refP {3} refN {-3}", "refP {4} refN {-4}", "refFull {2 -2}", "refFull {2 2 -2 -2}"}, {"ChGap22", "ChGap32", "ChGap42", "ChFull22", "ChFull24"}, {0, 0, 0, 0, 0}, {15, 1, 1, 0, 0}}, "Configurations for each correlation to calculate"}; + Configurable cfgCorrConfigRadial{"cfgCorrConfigRadial", {{"refP {2} refN {-2}", "refP {3} refN {-3}", "refP {4} refN {-4}"}, {"ChGap22", "ChGap32", "ChGap42"}, {1, 1, 1}, {0, 0, 0}}, "Configurations for each radial flow correlation to calculate"}; // #include "PWGCF/TwoParticleCorrelations/TableProducer/Productions/skimmingconf_20221115.cxx" // NOLINT // Connect to ccdb @@ -169,10 +174,15 @@ struct FlowGenericFramework { // Define output OutputObj fFC{FlowContainer("FlowContainer")}; - OutputObj fFCpt{FlowPtContainer("FlowPtContainer")}; + OutputObj fFCpt_ch{FlowPtContainer("FlowPtContainer_ch")}; + OutputObj fFCpt_pi{FlowPtContainer("FlowPtContainer_pi")}; + OutputObj fFCpt_ka{FlowPtContainer("FlowPtContainer_ka")}; + OutputObj fFCpt_pr{FlowPtContainer("FlowPtContainer_pr")}; OutputObj fFCgen{FlowContainer("FlowContainer_gen")}; HistogramRegistry registry{"registry"}; + std::vector fFCpts = {&(*fFCpt_ch), &(*fFCpt_pi), &(*fFCpt_ka), &(*fFCpt_pr)}; + // QA outputs std::map>> th1sList; std::map>> th3sList; @@ -245,11 +255,12 @@ struct FlowGenericFramework { GFW* fGFW = new GFW(); std::vector corrconfigs; + std::vector corrconfigsradial; + TRandom3* fRndm = new TRandom3(0); TAxis* fPtAxis; int lastRun = -1; std::vector runNumbers; - TH1D* event_pt_spectrum; // Density dependent eff correction std::vector funcEff; @@ -285,7 +296,7 @@ struct FlowGenericFramework { void init(InitContext const&) { - LOGF(info, "flowGenericFramework::init()"); + LOGF(info, "FlowGenericFramework::init()"); o2::analysis::gfw::regions.SetNames(cfgRegions->GetNames()); o2::analysis::gfw::regions.SetEtaMin(cfgRegions->GetEtaMin()); o2::analysis::gfw::regions.SetEtaMax(cfgRegions->GetEtaMax()); @@ -297,6 +308,11 @@ struct FlowGenericFramework { o2::analysis::gfw::configs.SetpTCorrMasks(cfgCorrConfig->GetpTCorrMasks()); o2::analysis::gfw::regions.Print(); o2::analysis::gfw::configs.Print(); + o2::analysis::gfw::configsradial.SetCorrs(cfgCorrConfigRadial->GetCorrs()); + o2::analysis::gfw::configsradial.SetHeads(cfgCorrConfigRadial->GetHeads()); + o2::analysis::gfw::configsradial.SetpTDifs(cfgCorrConfigRadial->GetpTDifs()); + o2::analysis::gfw::configsradial.SetpTCorrMasks(cfgCorrConfigRadial->GetpTCorrMasks()); + o2::analysis::gfw::configsradial.Print(); o2::analysis::gfw::ptbinning = cfgGFWBinning->GetPtBinning(); o2::analysis::gfw::ptpoilow = cfgGFWBinning->GetPtPOImin(); o2::analysis::gfw::ptpoiup = cfgGFWBinning->GetPtPOImax(); @@ -398,6 +414,11 @@ struct FlowGenericFramework { registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(10, "after Mult cuts"); registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(11, "has track + within cent"); + registry.add("npt_ch", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTH2D, {ptAxis, centAxis}}); + registry.add("npt_pi", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTH2D, {ptAxis, centAxis}}); + registry.add("npt_ka", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTH2D, {ptAxis, centAxis}}); + registry.add("npt_pr", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTH2D, {ptAxis, centAxis}}); + if (!cfgRunByRun) { if (cfgUsePID) { registry.add("phi_eta_vtxz_ref", "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); @@ -410,14 +431,6 @@ struct FlowGenericFramework { } } - // v0 - const TArrayD* bins = fPtAxis->GetXbins(); - if (bins->fN > 0) { - event_pt_spectrum = new TH1D("event_pt_spectrum", "event_pt_spectrum", bins->fN - 1, bins->fArray); - } - registry.add("meanNpt", "", {HistType::kTProfile2D, {ptAxis, multAxis}}); - registry.add("meanpt", "", {HistType::kTProfile, {multAxis}}); - registry.add("Npt_pt", "", {HistType::kTProfile2D, {ptAxis, multAxis}}); registry.add("trackQA/after/Nch_corrected", "", {HistType::kTH1D, {nchAxis}}); registry.add("trackQA/after/Nch_uncorrected", "", {HistType::kTH1D, {nchAxis}}); } @@ -432,9 +445,19 @@ struct FlowGenericFramework { } if (corrconfigs.empty()) LOGF(error, "Configuration contains vectors of different size - check the GFWCorrConfig configurable"); + + // Radial flow configs + for (auto i = 0; i < o2::analysis::gfw::configsradial.GetSize(); ++i) { + corrconfigsradial.push_back(fGFW->GetCorrelatorConfig(o2::analysis::gfw::configsradial.GetCorrs()[i], o2::analysis::gfw::configsradial.GetHeads()[i], o2::analysis::gfw::configsradial.GetpTDifs()[i])); + } + if (corrconfigsradial.empty()) + LOGF(error, "Radial configuration contains vectors of different size - check the GFWCorrConfig configurable"); + fGFW->CreateRegions(); TObjArray* oba = new TObjArray(); addConfigObjectsToObjArray(oba, corrconfigs); + addConfigObjectsToObjArray(oba, corrconfigsradial); + if (doprocessData || doprocessRun2 || doprocessMCReco) { fFC->SetName("FlowContainer"); fFC->SetXAxis(fPtAxis); @@ -446,9 +469,11 @@ struct FlowGenericFramework { fFCgen->Initialize(oba, multAxis, cfgNbootstrap); } delete oba; - fFCpt->setUseCentralMoments(cfgUseCentralMoments); - fFCpt->setUseGapMethod(cfgUseGapMethod); - fFCpt->initialise(multAxis, cfgMpar, o2::analysis::gfw::configs, cfgNbootstrap); + for (auto& container : fFCpts) { + container->setUseCentralMoments(cfgUseCentralMoments); + container->setUseGapMethod(cfgUseGapMethod); + container->initialise(multAxis, cfgMpar, o2::analysis::gfw::configs, cfgNbootstrap); + } // Multiplicity correlation cuts if (cfgMultCut) { @@ -617,18 +642,25 @@ struct FlowGenericFramework { float nsigma = 3.0; // Choose which nSigma to use - std::array nSigmaToUse = (track.pt() > cfgTofPtCut && track.hasTOF()) ? nSigmaCombined : nSigmaTPC; - if (track.pt() >= cfgTofPtCut && !track.hasTOF()) - return -1; + std::array nSigmaToUse = (track.pt() > cfgPIDCuts.cfgTofPtCut && track.hasTOF()) ? nSigmaCombined : nSigmaTPC; + if (track.pt() > cfgPIDCuts.cfgTofPtCut && !track.hasTOF()) + return 0; + const int numSpecies = 3; + int pidCount = 0; // Select particle with the lowest nsigma - const int nspecies = 3; - for (int i = 0; i < nspecies; ++i) { + for (int i = 0; i < numSpecies; ++i) { if (std::abs(nSigmaToUse[i]) < nsigma) { + if (pidCount > 0 && cfgPIDCuts.cfgUseStrictPID) + return 0; // more than one particle with low nsigma + + pidCount++; pid = i; - nsigma = std::abs(nSigmaToUse[i]); + if (!cfgPIDCuts.cfgUseStrictPID) + nsigma = std::abs(nSigmaToUse[i]); } } + return pid + 1; // shift the pid by 1, 1 = pion, 2 = kaon, 3 = proton } @@ -745,7 +777,7 @@ struct FlowGenericFramework { { if (std::fabs(track.dcaXY()) > (0.0105f + 0.0035f / track.pt())) return false; - return ((track.tpcNClsCrossedRows() >= 70) && (track.tpcNClsFound() >= 70) && (track.itsNCls() >= 5)); + return ((track.tpcNClsCrossedRows() >= 70) && (track.tpcNClsFound() >= 50) && (track.itsNCls() >= 5)); } enum DataType { @@ -838,14 +870,35 @@ struct FlowGenericFramework { return; } + struct AcceptedTracks { + explicit AcceptedTracks(std::size_t nptbins) + : nch(nptbins, 0.f), + npi(nptbins, 0.f), + nka(nptbins, 0.f), + npr(nptbins, 0.f) + { + } + + float total = 0; + unsigned int total_uncorr = 0; + + std::vector nch; + std::vector npi; + std::vector nka; + std::vector npr; + }; + template - void fillOutputContainers(const float& centmult, const double& rndm) + void fillOutputContainers(const float& centmult, const double& rndm, AcceptedTracks acceptedtracks) { - fFCpt->calculateCorrelations(); - fFCpt->fillPtProfiles(centmult, rndm); - fFCpt->fillCMProfiles(centmult, rndm); - if (!cfgUseGapMethod) - fFCpt->fillVnPtStdProfiles(centmult, rndm); + for (auto container : fFCpts) { + container->calculateCorrelations(); + container->fillPtProfiles(centmult, rndm); + container->fillCMProfiles(centmult, rndm); + if (!cfgUseGapMethod) + container->fillVnPtStdProfiles(centmult, rndm); + } + for (uint l_ind = 0; l_ind < corrconfigs.size(); ++l_ind) { if (!corrconfigs.at(l_ind).pTDif) { auto dnx = fGFW->Calculate(corrconfigs.at(l_ind), 0, kTRUE).real(); @@ -854,8 +907,11 @@ struct FlowGenericFramework { auto val = fGFW->Calculate(corrconfigs.at(l_ind), 0, kFALSE).real() / dnx; if (std::abs(val) < 1) { (dt == kGen) ? fFCgen->FillProfile(corrconfigs.at(l_ind).Head.c_str(), centmult, val, dnx, rndm) : fFC->FillProfile(corrconfigs.at(l_ind).Head.c_str(), centmult, val, dnx, rndm); - if (cfgUseGapMethod) - fFCpt->fillVnPtProfiles(centmult, val, dnx, rndm, o2::analysis::gfw::configs.GetpTCorrMasks()[l_ind]); + if (cfgUseGapMethod) { + for (auto container : fFCpts) { + container->fillVnPtProfiles(centmult, val, dnx, rndm, o2::analysis::gfw::configs.GetpTCorrMasks()[l_ind]); + } + } } continue; } @@ -869,13 +925,41 @@ struct FlowGenericFramework { } } - // Only consider events where mean pt can be calculated - if (fFCpt->corrDen[1] != 0) { - double mean_pt = fFCpt->corrNum[1] / fFCpt->corrDen[1]; - registry.fill(HIST("meanpt"), centmult, mean_pt); - for (int bin = 1; bin <= event_pt_spectrum->GetNbinsX(); ++bin) { - registry.fill(HIST("meanNpt"), event_pt_spectrum->GetXaxis()->GetBinCenter(bin), centmult, event_pt_spectrum->GetBinContent(bin)); - registry.fill(HIST("Npt_pt"), event_pt_spectrum->GetXaxis()->GetBinCenter(bin), centmult, event_pt_spectrum->GetBinContent(bin) * mean_pt); + int total = (cfgUseNchCorrection) ? acceptedtracks.total : acceptedtracks.total_uncorr; + + if (total == 0) + return; + + for (std::size_t i = 0; i < acceptedtracks.nch.size(); ++i) + registry.fill(HIST("npt_ch"), fPtAxis->GetBinCenter(i + 1), centmult, acceptedtracks.nch[i] / total); + for (std::size_t i = 0; i < acceptedtracks.npi.size(); ++i) + registry.fill(HIST("npt_pi"), fPtAxis->GetBinCenter(i + 1), centmult, acceptedtracks.npi[i] / total); + for (std::size_t i = 0; i < acceptedtracks.nka.size(); ++i) + registry.fill(HIST("npt_ka"), fPtAxis->GetBinCenter(i + 1), centmult, acceptedtracks.nka[i] / total); + for (std::size_t i = 0; i < acceptedtracks.npr.size(); ++i) + registry.fill(HIST("npt_pr"), fPtAxis->GetBinCenter(i + 1), centmult, acceptedtracks.npr[i] / total); + + std::vector> inputs = {acceptedtracks.nch, acceptedtracks.npi, acceptedtracks.nka, acceptedtracks.npr}; + std::vector> fractions; + fractions.reserve(inputs.size()); + + for (const auto& vec : inputs) { + fractions.emplace_back(); + fractions.back().reserve(vec.size()); + + std::transform(vec.begin(), vec.end(), + std::back_inserter(fractions.back()), + [&](double x) { return x / total; }); + } + + for (uint l_ind = 0; l_ind < corrconfigsradial.size(); ++l_ind) { + for (int i = 1; i <= fPtAxis->GetNbins(); i++) { + auto dnx = fGFW->Calculate(corrconfigsradial.at(l_ind), i - 1, kTRUE).real(); + if (dnx == 0) + continue; + auto val = fGFW->Calculate(corrconfigsradial.at(l_ind), i - 1, kFALSE).real() / dnx; + if (std::abs(val) < 1) + (dt == kGen) ? fFCgen->FillProfile(Form("%s_pt_%i", corrconfigsradial.at(l_ind).Head.c_str(), i), centmult, val * fractions[l_ind][i - 1], dnx, rndm) : fFC->FillProfile(Form("%s_pt_%i", corrconfigsradial.at(l_ind).Head.c_str(), i), centmult, val * fractions[l_ind][i - 1], dnx, rndm); } } @@ -901,8 +985,9 @@ struct FlowGenericFramework { th1sList[run][hCent]->Fill(centrality); } fGFW->Clear(); - fFCpt->clearVector(); - event_pt_spectrum->Reset(); + for (auto& container : fFCpts) + container->clearVector(); + float lRandom = fRndm->Rndm(); // be cautious, this only works for Pb-Pb @@ -940,13 +1025,13 @@ struct FlowGenericFramework { densitycorrections.density = tracks.size(); } - AcceptedTracks acceptedTracks; + AcceptedTracks acceptedTracks(o2::analysis::gfw::ptbinning.size() - 1); for (const auto& track : tracks) { processTrack(track, vtxz, field, run, densitycorrections, acceptedTracks); } - registry.fill(HIST("trackQA/after/Nch_corrected"), acceptedTracks.corrected); - registry.fill(HIST("trackQA/after/Nch_uncorrected"), acceptedTracks.uncorrected); + registry.fill(HIST("trackQA/after/Nch_corrected"), acceptedTracks.total); + registry.fill(HIST("trackQA/after/Nch_uncorrected"), acceptedTracks.total_uncorr); int multiplicity = 0; switch (cfgUseNchCorrection) { @@ -954,10 +1039,10 @@ struct FlowGenericFramework { multiplicity = tracks.size(); break; case 1: - multiplicity = acceptedTracks.corrected; + multiplicity = acceptedTracks.total; break; case 2: - multiplicity = acceptedTracks.uncorrected; + multiplicity = acceptedTracks.total_uncorr; break; default: multiplicity = tracks.size(); @@ -965,14 +1050,9 @@ struct FlowGenericFramework { } if (!cfgFillWeights) - fillOutputContainers
((cfgUseNch) ? multiplicity : centrality, lRandom); + fillOutputContainers
((cfgUseNch) ? multiplicity : centrality, lRandom, acceptedTracks); } - struct AcceptedTracks { - float corrected = 0; - unsigned int uncorrected = 0; - }; - template inline void processTrack(TTrack const& track, const float& vtxz, const int field, const int run, DensityCorr densitycorrections, AcceptedTracks& acceptedTracks) { @@ -993,8 +1073,8 @@ struct FlowGenericFramework { if (!nchSelected(track)) return; - acceptedTracks.corrected += getEfficiency(track); - ++acceptedTracks.uncorrected; + acceptedTracks.total += getEfficiency(track); + ++acceptedTracks.total_uncorr; if (!trackSelected(track, field)) return; @@ -1012,7 +1092,7 @@ struct FlowGenericFramework { if (cfgFillWeights) { fillWeights(mcParticle, vtxz, 0, run); } else { - fillPtSums(track, vtxz); + fillPtSums(track, vtxz, pidIndex); fillGFW(mcParticle, vtxz, pidIndex, densitycorrections); } @@ -1042,9 +1122,9 @@ struct FlowGenericFramework { if (std::abs(track.pdgCode()) == kProton) pidIndex = 3; } - ++acceptedTracks.corrected; - ++acceptedTracks.uncorrected; - fillPtSums(track, vtxz); + ++acceptedTracks.total; + ++acceptedTracks.total_uncorr; + fillPtSums(track, vtxz, pidIndex); fillGFW(track, vtxz, pidIndex, densitycorrections); if (cfgFillQA) @@ -1052,27 +1132,34 @@ struct FlowGenericFramework { } else { if (cfgFillQA) fillTrackQA(track, vtxz); - // Select tracks with nominal cuts always if (!nchSelected(track)) return; - - acceptedTracks.corrected += getEfficiency(track); - ++acceptedTracks.uncorrected; + acceptedTracks.total += getEfficiency(track); + ++acceptedTracks.total_uncorr; if (!trackSelected(track, field)) return; - - int pidIndex = 0; - if (cfgUsePID) - pidIndex = getNsigmaPID(track); + // int pidIndex = 0; + // if (cfgUsePID) Need PID for v02 + int pidIndex = getNsigmaPID(track); + + std::size_t ptBinIndex = fPtAxis->FindBin(track.pt()) - 1; + if (!(ptBinIndex > o2::analysis::gfw::ptbinning.size())) { + acceptedTracks.nch[ptBinIndex] += (cfgUseNchCorrection) ? getEfficiency(track) : 1.0; + if (pidIndex == 1) + acceptedTracks.npi[ptBinIndex] += (cfgUseNchCorrection) ? getEfficiency(track) : 1.0; + if (pidIndex == 2) + acceptedTracks.nka[ptBinIndex] += (cfgUseNchCorrection) ? getEfficiency(track) : 1.0; + if (pidIndex == 3) + acceptedTracks.npr[ptBinIndex] += (cfgUseNchCorrection) ? getEfficiency(track) : 1.0; + } if (cfgFillWeights) { fillWeights(track, vtxz, pidIndex, run); } else { - fillPtSums(track, vtxz); + fillPtSums(track, vtxz, pidIndex); fillGFW(track, vtxz, pidIndex, densitycorrections); - event_pt_spectrum->Fill(track.pt(), (cfgUseNchCorrection == 1) ? getEfficiency(track) : 1.); } if (cfgFillQA) { fillTrackQA(track, vtxz); @@ -1085,20 +1172,22 @@ struct FlowGenericFramework { } template - inline void fillPtSums(TTrack track, const double& vtxz) + inline void fillPtSums(TTrack track, const double& vtxz, const int pidIndex) { double wacc = (dt == kGen) ? 1. : getAcceptance(track, vtxz, 0); double weff = (dt == kGen) ? 1. : getEfficiency(track); if (weff < 0) return; if (std::abs(track.eta()) < cfgEtaPtPt) { - fFCpt->fill(weff, track.pt()); + fFCpt_ch->fill(weff, track.pt()); + if (pidIndex) + fFCpts[pidIndex]->fill(weff, track.pt()); } if (!cfgUseGapMethod) { std::complex q2p = {weff * wacc * std::cos(2 * track.phi()), weff * wacc * std::sin(2 * track.phi())}; std::complex q2n = {weff * wacc * std::cos(-2 * track.phi()), weff * wacc * std::sin(-2 * track.phi())}; - fFCpt->fillArray(q2p, q2n, weff * track.pt(), weff); - fFCpt->fillArray(weff * wacc, weff * wacc, weff, weff); + fFCpt_ch->fillArray(q2p, q2n, weff * track.pt(), weff); + fFCpt_ch->fillArray(weff * wacc, weff * wacc, weff, weff); } } @@ -1222,8 +1311,8 @@ struct FlowGenericFramework { o2::framework::expressions::Filter collisionFilter = nabs(aod::collision::posZ) < cfgVtxZ; o2::framework::expressions::Filter trackFilter = nabs(aod::track::eta) < cfgEta && aod::track::pt > cfgPtmin&& aod::track::pt < cfgPtmax && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)) && (aod::track::itsChi2NCl < cfgTrackCuts.cfgChi2PrITSCls) && (aod::track::tpcChi2NCl < cfgTrackCuts.cfgChi2PrTPCCls) && nabs(aod::track::dcaZ) < cfgTrackCuts.cfgDCAz; - using GFWTracks = soa::Filtered>; - // using GFWTracks = soa::Filtered>; + // using GFWTracks = soa::Filtered>; + using GFWTracks = soa::Filtered>; void processData(soa::Filtered>::iterator const& collision, aod::BCsWithTimestamps const&, GFWTracks const& tracks) { From 5be1e993d4a8764f12fece1bd9d43a6dc0600152 Mon Sep 17 00:00:00 2001 From: jaimenorman Date: Thu, 19 Mar 2026 09:26:38 +0000 Subject: [PATCH 329/347] [PWGJE] Include pThat rejection for particles (#15444) --- PWGJE/Tasks/trackEfficiency.cxx | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/PWGJE/Tasks/trackEfficiency.cxx b/PWGJE/Tasks/trackEfficiency.cxx index d6886619555..1228de53867 100644 --- a/PWGJE/Tasks/trackEfficiency.cxx +++ b/PWGJE/Tasks/trackEfficiency.cxx @@ -85,6 +85,7 @@ struct TrackEfficiency { Configurable ptHatMax{"ptHatMax", 999, "max pT hat of collisions"}; Configurable pTHatExponent{"pTHatExponent", 4.0, "exponent of the event weight for the calculation of pTHat"}; Configurable pTHatMaxFractionMCD{"pTHatMaxFractionMCD", 999.0, "maximum fraction of hard scattering for reconstructed track acceptance in MC"}; + Configurable pTHatMaxFractionMCP{"pTHatMaxFractionMCP", 999.0, "maximum fraction of hard scattering for particle acceptance in MC"}; Configurable useTrueTrackWeight{"useTrueTrackWeight", true, "test configurable, should be set to 1 then config removed once well tested"}; @@ -174,6 +175,10 @@ struct TrackEfficiency { float centrality = checkCentFT0M ? collisions.begin().centFT0M() : collisions.begin().centFT0C(); for (auto const& mcparticle : mcparticles) { + float pTHat = simPtRef / (std::pow(weight, 1.0 / pTHatExponent)); + if (mcparticle.pt() > pTHatMaxFractionMCP * pTHat) { + continue; + } registry.fill(HIST("h2_centrality_particle_pt"), centrality, mcparticle.pt(), weight); registry.fill(HIST("h2_centrality_particle_eta"), centrality, mcparticle.eta(), weight); registry.fill(HIST("h2_centrality_particle_phi"), centrality, mcparticle.phi(), weight); @@ -657,6 +662,9 @@ struct TrackEfficiency { registry.fill(HIST("hMcCollCutsCounts"), 6.5, mcCollision.weight()); // ptHat condition for (auto const& jMcParticle : jMcParticles) { + if (jMcParticle.pt() > pTHatMaxFractionMCP * pTHat) { + continue; + } registry.fill(HIST("hMcPartCutsCounts"), 0.5, mcCollision.weight()); // allPartsInSelMcColl if (!isChargedParticle(jMcParticle.pdgCode())) { @@ -720,6 +728,9 @@ struct TrackEfficiency { float trueTrackCollEventWeight = useTrueTrackWeight ? trueTrackMcCollision.weight() : mcCollEventWeight; auto jMcParticleFromTrack = track.mcParticle_as(); + if (jMcParticleFromTrack.pt() > pTHatMaxFractionMCP * pTHat) { + continue; + } if (!jMcParticleFromTrack.isPhysicalPrimary()) { registry.fill(HIST("h3_track_pt_track_eta_track_phi_associatedtrack_nonprimary"), track.pt(), track.eta(), track.phi(), trueTrackCollEventWeight); registry.fill(HIST("h3_particle_pt_particle_eta_particle_phi_associatedtrack_nonprimary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi(), trueTrackCollEventWeight); From 2e9b2a737f4a8b4017b243414bbe4cdcb3fca265 Mon Sep 17 00:00:00 2001 From: dyx-11 <1260971129@qq.com> Date: Thu, 19 Mar 2026 17:28:43 +0800 Subject: [PATCH 330/347] [PWGUD] simplified log (#15453) --- PWGUD/Tasks/flowCorrelationsUpc.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWGUD/Tasks/flowCorrelationsUpc.cxx b/PWGUD/Tasks/flowCorrelationsUpc.cxx index 06da62eef5b..a8138f126e6 100644 --- a/PWGUD/Tasks/flowCorrelationsUpc.cxx +++ b/PWGUD/Tasks/flowCorrelationsUpc.cxx @@ -359,7 +359,7 @@ struct FlowCorrelationsUpc { void processSame(UDCollisionsFull::iterator const& collision, UdTracksFull const& tracks) { - LOG(info) << "Event passed filter: truegapside=" << collision.truegapside(); + // LOG(info) << "Event passed filter: truegapside=" << collision.truegapside(); if (tracks.size() < cfgMinMult || tracks.size() > cfgMaxMult) { return; } From 0267a03e70626d5186d22d66c9b66abb7413f21d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josu=C3=A9=20Mart=C3=ADnez=20Garc=C3=ADa?= Date: Thu, 19 Mar 2026 04:47:08 -0600 Subject: [PATCH 331/347] [PWGUD] fixing time ZN selection criteria (#15452) Co-authored-by: rolavick --- PWGUD/Tasks/upcPhotonuclearAnalysisJMG.cxx | 32 +++++++++++++++------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/PWGUD/Tasks/upcPhotonuclearAnalysisJMG.cxx b/PWGUD/Tasks/upcPhotonuclearAnalysisJMG.cxx index da1328981d9..c1ba0124327 100644 --- a/PWGUD/Tasks/upcPhotonuclearAnalysisJMG.cxx +++ b/PWGUD/Tasks/upcPhotonuclearAnalysisJMG.cxx @@ -48,6 +48,7 @@ namespace o2::aod namespace tree { DECLARE_SOA_COLUMN(GapSide, gapSide, float); +DECLARE_SOA_COLUMN(GapSideTimeZN, gapSideTimeZN, float); DECLARE_SOA_COLUMN(Sbp, sbp, int); DECLARE_SOA_COLUMN(ITSROFb, itsROFb, int); DECLARE_SOA_COLUMN(VtxITSTPCCut, vtxITSTPCCut, int); @@ -84,6 +85,7 @@ DECLARE_SOA_COLUMN(MultiplicitySideC, multiplicitySideC, int); } // namespace tree DECLARE_SOA_TABLE(TREE, "AOD", "Tree", tree::GapSide, + tree::GapSideTimeZN, tree::Sbp, tree::ITSROFb, tree::VtxITSTPCCut, @@ -406,7 +408,7 @@ struct UpcPhotonuclearAnalysisJMG { switch (SideGap) { case 0: // Gap in A side - if ((collision.timeZNA() > cutGapAMyEnergyZNA) && (collision.timeZNC() < cutGapAMyEnergyZNC)) { + if (!(std::abs(collision.timeZNA()) > cutGapATimeZNA && std::abs(collision.timeZNC()) < cutGapATimeZNC)) { return false; } if (useEnergyZN && ((collision.energyCommonZNA() < cutGapAMyEnergyZNA) && (collision.energyCommonZNC() >= cutGapAMyEnergyZNC))) { @@ -423,7 +425,7 @@ struct UpcPhotonuclearAnalysisJMG { // } break; case 1: // Gap in C side - if ((collision.timeZNA() < cutGapCMyEnergyZNA) && (collision.timeZNC() > cutGapCMyEnergyZNC)) { + if (!(std::abs(collision.timeZNA()) < cutGapCTimeZNA && std::abs(collision.timeZNC()) > cutGapCTimeZNC)) { return false; } if (useEnergyZN && ((collision.energyCommonZNA() >= cutGapCMyEnergyZNA) && (collision.energyCommonZNC() < cutGapCMyEnergyZNC))) { @@ -616,6 +618,7 @@ struct UpcPhotonuclearAnalysisJMG { { histos.fill(HIST("Events/hCountCollisions"), 0); int sgSide = reconstructedCollision.gapSide(); + int sgSideTimeZN = -1; int nTracksCharged = 0; float sumPt = 0; int nchPVGapSideA = 0; @@ -634,8 +637,16 @@ struct UpcPhotonuclearAnalysisJMG { float phiVal = RecoDecay::constrainAngle(phi(track.px(), track.py()), 0.f); histos.fill(HIST("etaphiVtx"), reconstructedCollision.posZ(), eta(track.px(), track.py(), track.pz()), phiVal); } + bool isGapATimeZN = (std::abs(reconstructedCollision.timeZNA()) > cutGapATimeZNA) && (std::abs(reconstructedCollision.timeZNC()) < cutGapATimeZNC); + bool isGapCTimeZN = (std::abs(reconstructedCollision.timeZNA()) < cutGapCTimeZNA) && (std::abs(reconstructedCollision.timeZNC()) > cutGapCTimeZNC); + if (isGapATimeZN) { + sgSideTimeZN = 0; + } + if (isGapCTimeZN) { + sgSideTimeZN = 1; + } - switch (sgSide) { + switch (sgSideTimeZN) { case 0: // gap for side A if (isCollisionCutSG(reconstructedCollision, 0) == false) { return; @@ -762,6 +773,7 @@ struct UpcPhotonuclearAnalysisJMG { break; } tree(sgSide, + sgSideTimeZN, reconstructedCollision.sbp(), reconstructedCollision.itsROFb(), reconstructedCollision.vtxITSTPC(), @@ -894,20 +906,20 @@ struct UpcPhotonuclearAnalysisJMG { return; } histos.fill(HIST("Events/hCollisionsFlow"), 7); - bool cutGapAMyTimeZN = (reconstructedCollision.timeZNA() > cutGapAMyEnergyZNA) && (reconstructedCollision.timeZNC() < cutGapAMyEnergyZNC); - bool cutGapCMyTimeZN = (reconstructedCollision.timeZNA() < cutGapCMyEnergyZNA) && (reconstructedCollision.timeZNC() > cutGapCMyEnergyZNC); - if (cutGapAMyTimeZN || cutGapCMyTimeZN) { + bool isGapATimeZN = (std::abs(reconstructedCollision.timeZNA()) > cutGapATimeZNA) && (std::abs(reconstructedCollision.timeZNC()) < cutGapATimeZNC); + bool isGapCTimeZN = (std::abs(reconstructedCollision.timeZNA()) < cutGapCTimeZNA) && (std::abs(reconstructedCollision.timeZNC()) > cutGapCTimeZNC); + if (!(isGapATimeZN || isGapCTimeZN)) { return; } histos.fill(HIST("Events/hCollisionsFlow"), 8); - bool cutGapAMyEnergyZN = useEnergyZN && ((reconstructedCollision.energyCommonZNA() < cutGapAMyEnergyZNA) && (reconstructedCollision.energyCommonZNC() >= cutGapAMyEnergyZNC)); - bool cutGapCMyEnergyZN = useEnergyZN && ((reconstructedCollision.energyCommonZNA() >= cutGapCMyEnergyZNA) && (reconstructedCollision.energyCommonZNC() < cutGapCMyEnergyZNC)); - if (cutGapAMyEnergyZN || cutGapCMyEnergyZN) { + bool isGapAMyEnergyZN = useEnergyZN && ((reconstructedCollision.energyCommonZNA() < cutGapAMyEnergyZNA) && (reconstructedCollision.energyCommonZNC() >= cutGapAMyEnergyZNC)); + bool isGapCMyEnergyZN = useEnergyZN && ((reconstructedCollision.energyCommonZNA() >= cutGapCMyEnergyZNA) && (reconstructedCollision.energyCommonZNC() < cutGapCMyEnergyZNC)); + if (isGapAMyEnergyZN || isGapCMyEnergyZN) { return; } histos.fill(HIST("Events/hCollisionsFlow"), 9); - if (cutGapAMyTimeZN && useFV0 && reconstructedCollision.totalFV0AmplitudeA() > cutGapAFV0Amplitude) { + if (isGapATimeZN && useFV0 && reconstructedCollision.totalFV0AmplitudeA() > cutGapAFV0Amplitude) { return; } histos.fill(HIST("Events/hCollisionsFlow"), 10); From ee071d1a9d8aac8d98cfcd27eff730af3d0f9897 Mon Sep 17 00:00:00 2001 From: Jinhyun Park <125851562+jinhyunni@users.noreply.github.com> Date: Thu, 19 Mar 2026 22:47:35 +0900 Subject: [PATCH 332/347] [PWGHF] First draft of Xic0Omegac0 workflow update (#11697) Co-authored-by: Jinhyun Park --- PWGHF/Core/SelectorCuts.h | 38 +- PWGHF/D2H/Tasks/taskXic0ToXiPi.cxx | 65 +- PWGHF/TableProducer/CMakeLists.txt | 15 + .../candidateCreatorXic0Omegac0Qa.cxx | 2154 +++++++++++++++++ .../candidateSelectorToXiPiQa.cxx | 770 ++++++ PWGHF/TableProducer/treeCreatorToXiPiQa.cxx | 982 ++++++++ 6 files changed, 3992 insertions(+), 32 deletions(-) create mode 100644 PWGHF/TableProducer/candidateCreatorXic0Omegac0Qa.cxx create mode 100644 PWGHF/TableProducer/candidateSelectorToXiPiQa.cxx create mode 100644 PWGHF/TableProducer/treeCreatorToXiPiQa.cxx diff --git a/PWGHF/Core/SelectorCuts.h b/PWGHF/Core/SelectorCuts.h index a1bdfa0265f..17a223bcd20 100644 --- a/PWGHF/Core/SelectorCuts.h +++ b/PWGHF/Core/SelectorCuts.h @@ -764,7 +764,7 @@ static const std::vector labelsCutVar = {"pT Ka from Omegac"}; namespace hf_cuts_xic_to_xi_pi { -static constexpr int NBinsPt = 11; +static constexpr int NBinsPt = 12; static constexpr int NCutVars = 28; // default values for the pT bin edges (can be used to configure histogram axis) // offset by 1 from the bin numbers in cuts array @@ -780,22 +780,24 @@ constexpr double BinsPt[NBinsPt + 1] = { 10.0, 12.0, 16.0, - 24.0}; + 24.0, + 50.0}; const auto vecBinsPt = std::vector{BinsPt, BinsPt + NBinsPt + 1}; // default values for the cuts -constexpr double Cuts[NBinsPt][NCutVars] = {{0.2, 0.99, 0.97, 0.99, 0.99, 0.1, 0.2, 1.0, 0.04, 0.06, 0.06, 0.05, 0.3, 70, 60, 100, 120, 250, 250, 0.4, 100, 300, 0., 0., 1.5, 0., 0., 0.4}, /* 0 < pt < 1 */ - {0.5, 0.99, 0.97, 0.99, 0.99, 0.1, 0.2, 1.0, 0.04, 0.06, 0.06, 0.05, 0.3, 70, 60, 100, 120, 250, 250, 0.4, 100, 300, 0., 0., 1.5, 0., 0., 0.4}, /* 1 < pt < 2 */ - {0.5, 0.99, 0.97, 0.99, 0.99, 0.1, 0.2, 1.0, 0.04, 0.06, 0.06, 0.05, 0.3, 70, 60, 100, 120, 250, 250, 0.4, 100, 300, 0., 0., 1.5, 0., 0., 0.4}, /* 2 < pt < 3 */ - {0.5, 0.99, 0.97, 0.99, 0.99, 0.1, 0.2, 1.0, 0.04, 0.06, 0.06, 0.05, 0.3, 70, 60, 100, 120, 250, 250, 0.4, 100, 300, 0., 0., 1.5, 0., 0., 0.4}, /* 3 < pt < 4 */ - {0.5, 0.99, 0.97, 0.99, 0.99, 0.1, 0.2, 1.0, 0.04, 0.06, 0.06, 0.05, 0.3, 70, 60, 100, 120, 250, 250, 0.4, 100, 300, 0., 0., 1.5, 0., 0., 0.4}, /* 4 < pt < 5 */ - {0.5, 0.99, 0.97, 0.99, 0.99, 0.1, 0.2, 1.0, 0.04, 0.06, 0.06, 0.05, 0.3, 70, 60, 100, 120, 250, 250, 0.4, 100, 300, 0., 0., 1.5, 0., 0., 0.4}, /* 5 < pt < 6 */ - {0.5, 0.99, 0.97, 0.99, 0.99, 0.1, 0.2, 1.0, 0.04, 0.06, 0.06, 0.05, 0.3, 70, 60, 100, 120, 250, 250, 0.4, 100, 300, 0., 0., 1.5, 0., 0., 0.4}, /* 6 < pt < 8 */ - {0.5, 0.99, 0.97, 0.99, 0.99, 0.1, 0.2, 1.0, 0.04, 0.06, 0.06, 0.05, 0.3, 70, 60, 100, 120, 250, 250, 0.4, 100, 300, 0., 0., 1.5, 0., 0., 0.4}, /* 8 < pt < 10 */ - {0.5, 0.99, 0.97, 0.99, 0.99, 0.1, 0.2, 1.0, 0.04, 0.06, 0.06, 0.05, 0.3, 70, 60, 100, 120, 250, 250, 0.4, 100, 300, 0., 0., 1.5, 0., 0., 0.4}, /* 10 < pt < 12 */ - {0.5, 0.99, 0.97, 0.99, 0.99, 0.1, 0.2, 1.0, 0.04, 0.06, 0.06, 0.05, 0.3, 70, 60, 100, 120, 250, 250, 0.4, 100, 300, 0., 0., 1.5, 0., 0., 0.4}, /* 12 < pt < 16 */ - {0.5, 0.99, 0.97, 0.99, 0.99, 0.1, 0.2, 1.0, 0.04, 0.06, 0.06, 0.05, 0.3, 70, 60, 100, 120, 250, 250, 0.4, 100, 300, 0., 0., 1.5, 0., 0., 0.4}}; /* 16 < pt < 24 */ +constexpr double Cuts[NBinsPt][NCutVars] = {{0.2, 0.97, 0.97, 0.99, 0.99, 2.0, 1.0, 1.0, 0.04, 0.06, 0.06, 0.05, 0.3, 70, 60, 100, 120, 250, 250, 0.4, 100, 300, 0., 0., 1.5, 0., 0., 0.4}, /* 0 < pt < 1 */ + {0.2, 0.97, 0.97, 0.99, 0.99, 2.0, 1.0, 1.0, 0.04, 0.06, 0.06, 0.05, 0.3, 70, 60, 100, 120, 250, 250, 0.4, 100, 300, 0., 0., 1.5, 0., 0., 0.4}, /* 1 < pt < 2 */ + {0.2, 0.97, 0.97, 0.99, 0.99, 2.0, 1.0, 1.0, 0.04, 0.06, 0.06, 0.05, 0.3, 70, 60, 100, 120, 250, 250, 0.4, 100, 300, 0., 0., 1.5, 0., 0., 0.4}, /* 2 < pt < 3 */ + {0.2, 0.97, 0.97, 0.99, 0.99, 2.0, 1.0, 1.0, 0.04, 0.06, 0.06, 0.05, 0.3, 70, 60, 100, 120, 250, 250, 0.4, 100, 300, 0., 0., 1.5, 0., 0., 0.4}, /* 3 < pt < 4 */ + {0.2, 0.97, 0.97, 0.99, 0.99, 2.0, 1.0, 1.0, 0.04, 0.06, 0.06, 0.05, 0.3, 70, 60, 100, 120, 250, 250, 0.4, 100, 300, 0., 0., 1.5, 0., 0., 0.4}, /* 4 < pt < 5 */ + {0.2, 0.97, 0.97, 0.99, 0.99, 2.0, 1.0, 1.0, 0.04, 0.06, 0.06, 0.05, 0.3, 70, 60, 100, 120, 250, 250, 0.4, 100, 300, 0., 0., 1.5, 0., 0., 0.4}, /* 5 < pt < 6 */ + {0.2, 0.97, 0.97, 0.99, 0.99, 2.0, 1.0, 1.0, 0.04, 0.06, 0.06, 0.05, 0.3, 70, 60, 100, 120, 250, 250, 0.4, 100, 300, 0., 0., 1.5, 0., 0., 0.4}, /* 6 < pt < 8 */ + {0.2, 0.97, 0.97, 0.99, 0.99, 2.0, 1.0, 1.0, 0.04, 0.06, 0.06, 0.05, 0.3, 70, 60, 100, 120, 250, 250, 0.4, 100, 300, 0., 0., 1.5, 0., 0., 0.4}, /* 8 < pt < 10 */ + {0.2, 0.97, 0.97, 0.99, 0.99, 2.0, 1.0, 1.0, 0.04, 0.06, 0.06, 0.05, 0.3, 70, 60, 100, 120, 250, 250, 0.4, 100, 300, 0., 0., 1.5, 0., 0., 0.4}, /* 10 < pt < 12 */ + {0.2, 0.97, 0.97, 0.99, 0.99, 2.0, 1.0, 1.0, 0.04, 0.06, 0.06, 0.05, 0.3, 70, 60, 100, 120, 250, 250, 0.4, 100, 300, 0., 0., 1.5, 0., 0., 0.4}, /* 12 < pt < 16 */ + {0.2, 0.97, 0.97, 0.99, 0.99, 2.0, 1.0, 1.0, 0.04, 0.06, 0.06, 0.05, 0.3, 70, 60, 100, 120, 250, 250, 0.4, 100, 300, 0., 0., 1.5, 0., 0., 0.4}, /* 16 < pt < 24 */ + {0.2, 0.97, 0.97, 0.99, 0.99, 2.0, 1.0, 1.0, 0.04, 0.06, 0.06, 0.05, 0.3, 70, 60, 100, 120, 250, 250, 0.4, 100, 300, 0., 0., 1.5, 0., 0., 0.4}}; /* 24 < pt < 50 -> Implemented just for test*/ // row labels static const std::vector labelsPt = { @@ -809,11 +811,15 @@ static const std::vector labelsPt = { "pT bin 7", "pT bin 8", "pT bin 9", - "pT bin 10"}; + "pT bin 10", + "pT bin 11"}; // column labels -static const std::vector labelsCutVar = {"ptPiFromCharmBaryon", "cosPACasc", "cosPAV0", "cosPaCascToXic", "cosPaV0ToCasc", - "dcaCharmBaryonDau", "dcaCascDau", "dcaV0Dau", "dcaXYToPvCascDau", "dcaXYToPvV0Dau0", "dcaXYToPvV0Dau1", "kfDcaXYPiFromXic", "kfDcaXYCascToPv", +static const std::vector labelsCutVar = {"ptPiFromCharmBaryon", "cosPACasc", "cosPAV0", + "cosPaCascToXic", "cosPaV0ToCasc", + "dcaCharmBaryonDau", "dcaCascDau", "dcaV0Dau", + "dcaXYToPvCascDau", "dcaXYToPvV0Dau0", "dcaXYToPvV0Dau1", + "kfDcaXYPiFromXic", "kfDcaXYCascToPv", "chi2GeoXic", "chi2GeoCasc", "chi2GeoV0", "chi2TopoXicToPv", "chi2TopoPiFromXicToPv", "chi2TopoCascToPv", "chi2TopoV0ToPv", "chi2TopoV0ToCasc", "chi2TopoCascToXic", "cascldl", "v0ldl", "decayLenXYXic", "decayLenXYCasc", "decayLenXYLambda", "cTauXic"}; diff --git a/PWGHF/D2H/Tasks/taskXic0ToXiPi.cxx b/PWGHF/D2H/Tasks/taskXic0ToXiPi.cxx index 92e8ff37531..31091e68555 100644 --- a/PWGHF/D2H/Tasks/taskXic0ToXiPi.cxx +++ b/PWGHF/D2H/Tasks/taskXic0ToXiPi.cxx @@ -165,6 +165,19 @@ struct HfTaskXic0ToXiPi { registry.add("hMassVsPtVsYVsCentVsPtPion", "Thn for Xic0 candidates with Cent&pTpi", HistType::kTHnSparseD, axesWithCent); registry.get(HIST("hBdtScoreVsMassVsPtVsYVsCentVsPtPion"))->Sumw2(); registry.get(HIST("hMassVsPtVsYVsCentVsPtPion"))->Sumw2(); + } else { + const AxisSpec thnAxisPromptScore{thnConfigAxisPromptScore, "BDT score prompt."}; + const AxisSpec thnAxisPtPion{thnConfigAxisPtPion, "Pt of Pion from Xic0."}; + std::vector const axesWithBdtWithoutCent = {thnAxisPromptScore, thnAxisMass, thnAxisPt, thnAxisY, thnAxisPtPion, thnConfigAxisNumPvContr}; + std::vector const axesWithoutCent = {thnAxisMass, thnAxisPt, thnAxisY, thnAxisPtPion, thnConfigAxisNumPvContr}; + registry.add("hBdtScoreVsMassVsPtVsYVsPtPion", "Thn for Xic0 candidates with BDT&Cent&pTpi", HistType::kTHnSparseD, axesWithBdtWithoutCent); + registry.add("hMassVsPtVsYVsPtPion", "Thn for Xic0 candidates with Cent&pTpi", HistType::kTHnSparseD, axesWithoutCent); + registry.get(HIST("hBdtScoreVsMassVsPtVsYVsPtPion"))->Sumw2(); + registry.get(HIST("hMassVsPtVsYVsPtPion"))->Sumw2(); + } + + if (yCandRecMax >= 0) { + registry.add("hNumRejCandidate_RapidityCut", "# of rejected candidate using rap cut;Rej;entries", {HistType::kTH1F, {thnAxisY}}); } } @@ -181,6 +194,7 @@ struct HfTaskXic0ToXiPi { yCharmBaryon = candidate.y(o2::constants::physics::MassXiC0); } if (yCandRecMax >= 0. && std::abs(yCharmBaryon) > yCandRecMax) { + registry.fill(HIST("hNumRejCandidate_RapidityCut"), yCharmBaryon); return; } @@ -192,22 +206,41 @@ struct HfTaskXic0ToXiPi { double const ptXic = RecoDecay::pt(candidate.pxCharmBaryon(), candidate.pyCharmBaryon()); double const ptPiFromXic = RecoDecay::pt(candidate.pxBachFromCharmBaryon(), candidate.pyBachFromCharmBaryon()); if constexpr (ApplyMl) { - registry.fill(HIST("hBdtScoreVsMassVsPtVsYVsCentVsPtPion"), - candidate.mlProbToXiPi()[0], - candidate.invMassCharmBaryon(), - ptXic, - yCharmBaryon, - centrality, - ptPiFromXic, - numPvContributors); + if constexpr (UseCentrality) { + registry.fill(HIST("hBdtScoreVsMassVsPtVsYVsCentVsPtPion"), + candidate.mlProbToXiPi()[0], + candidate.invMassCharmBaryon(), + ptXic, + yCharmBaryon, + centrality, + ptPiFromXic, + numPvContributors); + } else { + registry.fill(HIST("hBdtScoreVsMassVsPtVsYVsPtPion"), + candidate.mlProbToXiPi()[0], + candidate.invMassCharmBaryon(), + ptXic, + yCharmBaryon, + ptPiFromXic, + numPvContributors); + } } else { - registry.fill(HIST("hMassVsPtVsYVsCentVsPtPion"), - candidate.invMassCharmBaryon(), - ptXic, - yCharmBaryon, - centrality, - ptPiFromXic, - numPvContributors); + if constexpr (UseCentrality) { + registry.fill(HIST("hMassVsPtVsYVsCentVsPtPion"), + candidate.invMassCharmBaryon(), + ptXic, + yCharmBaryon, + centrality, + ptPiFromXic, + numPvContributors); + } else { + registry.fill(HIST("hMassVsPtVsYVsPtPion"), + candidate.invMassCharmBaryon(), + ptXic, + yCharmBaryon, + ptPiFromXic, + numPvContributors); + } } } @@ -348,7 +381,7 @@ struct HfTaskXic0ToXiPi { } } } - PROCESS_SWITCH(HfTaskXic0ToXiPi, processDataWithKFParticle, "process HfTaskXic0ToXiPi with KFParticle", true); + PROCESS_SWITCH(HfTaskXic0ToXiPi, processDataWithKFParticle, "process HfTaskXic0ToXiPi with KFParticle", false); void processDataWithDCAFitterMl(Xic0CandsMl const& candidates, CollisionsWithEvSels const& collisions) diff --git a/PWGHF/TableProducer/CMakeLists.txt b/PWGHF/TableProducer/CMakeLists.txt index 4ae18ad282e..174cbfa9621 100644 --- a/PWGHF/TableProducer/CMakeLists.txt +++ b/PWGHF/TableProducer/CMakeLists.txt @@ -90,6 +90,11 @@ o2physics_add_dpl_workflow(candidate-creator-xic0-omegac0 PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter KFParticle::KFParticle O2Physics::AnalysisCCDB O2Physics::EventFilteringUtils COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(candidate-creator-xic0-omegac0-qa + SOURCES candidateCreatorXic0Omegac0Qa.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter KFParticle::KFParticle O2Physics::EventFilteringUtils + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(candidate-creator-xic-to-xi-pi-pi SOURCES candidateCreatorXicToXiPiPi.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter KFParticle::KFParticle O2Physics::AnalysisCCDB O2Physics::EventFilteringUtils @@ -182,6 +187,11 @@ o2physics_add_dpl_workflow(candidate-selector-to-xi-pi PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::MLCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(candidate-selector-to-xi-pi-qa + SOURCES candidateSelectorToXiPiQa.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::MLCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(candidate-selector-xic-to-p-k-pi SOURCES candidateSelectorXicToPKPi.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::MLCore @@ -274,6 +284,11 @@ o2physics_add_dpl_workflow(tree-creator-to-xi-pi PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(tree-creator-to-xi-pi-qa + SOURCES treeCreatorToXiPiQa.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(tree-creator-xic0-to-xi-pi-kf SOURCES treeCreatorXic0ToXiPiKf.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore diff --git a/PWGHF/TableProducer/candidateCreatorXic0Omegac0Qa.cxx b/PWGHF/TableProducer/candidateCreatorXic0Omegac0Qa.cxx new file mode 100644 index 00000000000..b67ea5cd15e --- /dev/null +++ b/PWGHF/TableProducer/candidateCreatorXic0Omegac0Qa.cxx @@ -0,0 +1,2154 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file candidateCreatorXic0Omegac0Qa.cxx +/// \brief Reconstruction of Xic0 and Xicp candiates with hadronic decay chain +/// +/// \author Jinhyun Park , Pusan National University +/// \author Krista Smith , Pusan National University + +#ifndef HomogeneousField +#define HomogeneousField // o2-linter: disable=name/macro (required by KFParticle) +#endif + +#include "PWGHF/Core/DecayChannelsLegacy.h" +#include "PWGHF/DataModel/AliasTables.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/DataModel/TrackIndexSkimmingTables.h" +#include "PWGHF/Utils/utilsBfieldCCDB.h" +#include "PWGHF/Utils/utilsEvSelHf.h" +#include "PWGHF/Utils/utilsTrkCandHf.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGLF/DataModel/mcCentrality.h" +#include "PWGLF/Utils/strangenessBuilderHelper.h" // -> Added to test removal of strangeness builder workflow + +#include "Common/Core/ZorroSummary.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/CollisionAssociationTables.h" +#include "Common/DataModel/EventSelection.h" +#include "Tools/KFparticle/KFUtilities.h" + +#include "CommonConstants/PhysicsConstants.h" +#include "DCAFitter/DCAFitterN.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/DCA.h" + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::hf_centrality; +using namespace o2::hf_occupancy; +using namespace o2::constants::physics; +using namespace o2::hf_evsel; + +struct HfCandidateCreatorXic0Omegac0Qa { + + // Cursor to fill tables + struct : ProducesGroup { + // Candidates created with DCAFitter + Produces rowCandToXiPi; + Produces rowCandToOmegaPi; + Produces rowCandToOmegaKa; + // Candidate created with KFParticle + Produces rowCandToXiPiKf; + Produces rowCandToOmegaPiKf; + Produces rowCandToOmegaKaKf; + } cursors; + + // Configurables + struct : ConfigurableGroup { + + // Options for internal cascade building - DCAFitter settings + // ...Initial vaules taken from PWGLF/Utils/strangenessBuilderHelper + // ---------------------------------------------------------------- + Configurable propagateToPCALF{"propagateToPCALF", true, "Create tracks version propagated to PCA"}; + Configurable maxRLF{"maxRLF", 200., "Reject PCA's above this radius"}; + Configurable maxDZIniLF{"maxDZIniLF", 1e9, "Reject (if>0) PCA candidate if tracks DZ exceeds this threshold"}; + Configurable maxDXYIniLF{"maxDXYIniLF", 4.0f, "Reject (if>0) PCA candidate if tracks DXY exceeds this threshold"}; + Configurable minParamChangeLF{"minParamChangeLF", 1.e-3, "Stop iteration if largest change of any X is smaller than this"}; + Configurable minRelChi2ChangeLF{"minRelChi2ChangeLF", 0.9, "Stop iteration if Chi2/Chi2old > this"}; + Configurable maxChi2LF{"maxChi2LF", 1e9, "Discard vertices with Chi2/Nprongs > this(or sum {DCAi^2}/Nprongs for abs. distance minimization)"}; + Configurable useAbsDCALF{"useAbsDCALF", true, "Minimise abs. distance rather than chi2"}; + Configurable useWeightedFinalPCALF{"useWeightedFinalPCALF", false, "Recalculate vertex position using track covariance, effective only if useAbsDCA is true"}; + Configurable refitWithMaterialCorrectionLF{"refitWithMaterialCorrectionLF", false, "Do refit after material correction applied"}; + + // Options for internal V0 building + // ...Initial values taken from PWGLF/Utiles/strangenessBuilderModule.h + // ...Modified according to the configurable in core wagon + // --------------------------------------------------------------------- + Configurable minCrossedRowsFromLF{"minCrossedRowsFromLF", 50, "minimun TPC crossed rows for daughter tracks. Used for internal V0 Building"}; + Configurable dcanegtopvFromLF{"dcanegtopvFromLF", .1, "DCV Neg to PV"}; + Configurable dcapostopvFromLF{"dcapostopvFromLF", .1, "DCV Pos To PV"}; + Configurable v0cospaFromLF{"v0cospaFromLF", 0.95, "V0 CosPA"}; + Configurable dcav0dauFromLF{"dcav0dauFromLF", 1.0, "DCA V0 Daughters"}; + Configurable v0radiusFromLF{"v0radiusFromLF", 0.9, "v0radius"}; + Configurable maxDaughterEtaFromLF{"maxDaughterEtaFromLF", 5.0, "Maximun daughter eta (in abs value)"}; + + // Options for internal cascade building + // ...Initial values taken from PWGLF/Utiles/strangenessBuilderModule.h + // ...Modified according to the configurable in core wagon + // -------------------------------------------------------------------- + Configurable dcabachtopvFromLF{"dcabachtopvFromLF", .05, "DCV Bach to PV"}; + Configurable cascradiusFromLF{"cascradiusFromLF", .9, "DCV Bach to PV"}; + Configurable casccospaFromLF{"casccospaFromLF", 0.95, "Cascade CosPA"}; + Configurable dcacascdauFromLF{"dcacascdauFromLF", 1.0, "DCA cascade daughters"}; + Configurable lambdaMassWindowFromLF{"lambdaMassWindowFromLF", 0.01, "Distance from Lambda mass(does not apply to KF path)"}; + + // Options for internal cascade building - KF Building specifics + // ...Initial values taken from PWGLF/Utiles/strangenessBuilderModule.h + // -------------------------------------------------------------------- + Configurable kfTuneForOmegaFromLF{"kfTuneForOmegaFromLF", false, "if enabled, take main cascade properties from omega fit instread of Xi fit(=default)"}; + Configurable kfConstructMethodFromLF{"kfConstructMethodFromLF", 2, "2 : Daughter particle masses stay fixed in construction process"}; + Configurable kfUseV0MassConstraintFromLF{"kfUseV0MassConstraintFromLF", true, "KF : Use Lambda mass constraint"}; + Configurable kfUseCascadeMassConstraintFromLF{"kfUseCascadeMassConstraintFromLF", false, "KF : Use Cascade mass constraint - WARNING : Not adequate for inv mass analysis of Xi"}; + Configurable kfDoDCAFitterPreMinimV0FromLF{"kfDoDCAFitterPreMinimV0FromLF", true, "KF : do DCAFitter pre-optimization before KF fit to include material correction for V0"}; + Configurable kfDoDCAFitterPreMinimCascFromLF{"kfDoDCAFitterPreMinimCascFromLF", false, "KF : do DCAFitter pre-optimization before KF fit to include material correction for Xi"}; + } LFConfigs; + + // For cascade building using LF strangeness builder + o2::pwglf::strangenessBuilderHelper straHelper; + + // Configurables + struct : ConfigurableGroup { + // Switch for filling histograms + // ----------------------------- + Configurable fillHistograms{"fillHistograms", true, "fill validation plots"}; + + // Magnetic field setting from CCDB + // -------------------------------- + Configurable isRun2{"isRun2", false, "enable Run2 or Run3 GRP objects for magnetic field"}; + Configurable ccdbUrl{"ccdbUrl", "https://alice-ccdb.cern.ch", "url of the ccdb object"}; + Configurable ccdbPathLut{"ccdbPathLut", "GLO/Param/MatLUT", "Path for LUT parameterization"}; + Configurable ccdbPathGrp{"ccdbPathGrp", "GLO/GRP/GRP", "path of the group file (Run2)"}; + Configurable ccdbPathGrpMag{"ccdbPathGrpMag", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object (Run3)"}; + + // Cascade pre selection + // --------------------- + Configurable doCascadePreselection{"doCascadePreselection", true, "Use invariant mass and dcaXY cuts to preselect cascade candidates"}; + Configurable massToleranceCascade{"massToleranceCascade", 0.01, "Invariant mass tolerance for cascades"}; + Configurable dcaXYToPVCascadeMax{"dcaXYToPVCascadeMax", 3, "Max cascade DCA to PV in XY plane"}; + Configurable dcaV0DaughtersMax{"dcaV0DaughtersMax", 1.0, "Max DCA of V0 daughter"}; + Configurable dcaCascDaughtersMax{"dcaCascDaughtersMax", 1.0, "Max DCA of cascade daughter"}; + + // Options for DCAFitter + // --------------------- + Configurable propagateToPCA{"propagateToPCA", true, "Create tracks version propagated to PCA"}; + Configurable maxR{"maxR", 200., "Reject PCA's above this radius"}; + Configurable maxDZIni{"maxDZIni", 4., "Reject (if>0) PCA candidate if tracks DZ exceeds this threshold"}; + Configurable maxDXYIni{"maxDXYIni", 4., "Reject (if>0) PCA candidate if tracks DXY exceeds this threshold"}; + Configurable minParamChange{"minParamChange", 1.e-3, "Stop iteration if largest change of any X is smaller than this"}; + Configurable minRelChi2Change{"minRelChi2Change", 0.9, "Stop iteration if Chi2/Chi2old > this"}; + Configurable maxChi2{"maxChi2", 100, "Discard vertices with Chi2/Nprongs > this(or sum {DCAi^2}/Nprongs for abs. distance minimization)"}; + Configurable useAbsDCA{"useAbsDCA", true, "Minimise abs. distance rather than chi2"}; + Configurable useWeightedFinalPCA{"useWeightedFinalPCA", true, "Recalculate vertex position using track covariance, effective only if useAbsDCA is true"}; + + // Options for KFParticle + // ---------------------- + // V0 cuts + Configurable lambdaMassWindow{"lambdaMassWindow", 0.0075, "Distance from LambdaMass"}; + // For KF Particle operation + Configurable kfConstructMethod{"kfConstructMethod", 2, "KF Construct method"}; + Configurable kfUseV0MassConstraint{"kfUseV0MassConstraint", false, "KF: Use lambda mass constraint"}; + Configurable kfUseCascadeMassConstraint{"kfUseCascadeMassConstraint", false, "KF: Use lambda mass constraint"}; + + // Options for QA histogram binning + // ----------------------------- + // For Cascade + Configurable nBinMassCasc{"nBinMassCasc", 1000, "nBinCascMass"}; + Configurable minMassCasc{"minMassCasc", 1.0, "xiMassMin"}; + Configurable maxMassCasc{"maxMassCasc", 2.0, "xiMassMax"}; + Configurable nBinPtCasc{"nBinPtCasc", 100, "nBinPtXi"}; + Configurable minPtCasc{"minPtCasc", 0.0, "minimun value of cascade"}; + Configurable maxPtCasc{"maxPtCasc", 20.0, "maximum value of cascade"}; + + // For Prong0 + Configurable nBinMassProng0{"nBinMassProng0", 100, "nBinMassPi"}; + Configurable minMassProng0{"minMassProng0", 0.0, "ptPiMin"}; + Configurable maxMassProng0{"maxMassProng0", 20.0, "ptPiMax"}; + Configurable nBinPtProng0{"nBinPtProng0", 100, "nBinPtProng0"}; + Configurable minPtProng0{"minPtProng0", 0.0, "ptPiMin"}; + Configurable maxPtProng0{"maxPtProng0", 20.0, "ptPiMax"}; + + // For Charm Baryon + Configurable nBinMassCharmBaryon{"nBinMassCharmBaryon", 3000, "nBinXic0Mass"}; + Configurable minMassCharmBaryon{"minMassCharmBaryon", 1.0, "xic0MassMin"}; + Configurable maxMassCharmBaryon{"maxMassCharmBaryon", 4.0, "xic0MassMax"}; + Configurable nBinPtCharmBaryon{"nBinPtCharmBaryon", 100, "nBinXic0Pt"}; + Configurable minPtCharmBaryon{"minPtCharmBaryon", 0.0, "xic0PtMin"}; + Configurable maxPtCharmBaryon{"maxPtCharmBaryon", 20.0, "xic0PtMax"}; + + // Etc + Configurable nBinCpa2Prong{"nBinCpa2Prong", 240, "nBinCpa2Prong"}; + Configurable cpa2ProngMin{"cpa2ProngMin", -1.2, "cpa2ProngMin"}; + Configurable cpa2ProngMax{"cpa2ProngMax", 1.2, "cpa2ProngMax"}; + Configurable nBinImpParXYXi{"nBinImpParXYXi", 30, "nBinImpParXYXi"}; + Configurable impParXYXiMin{"impParXYXiMin", -1.5, "impParXYXiMin"}; + Configurable impParXYXiMax{"impParXYXiMax", 1.5, "impParXYXiMax"}; + Configurable nBinImpParXYPi{"nBinImpParXYPi", 30, "nBinImpParXYPi"}; + Configurable impParXYPiMin{"impParXYPiMin", -1.5, "impParXYPiMin"}; + Configurable impParXYPiMax{"impParXYPiMax", 1.5, "impParXYPiMax"}; + } configs; + + Service ccdb{}; + Service pdgdb{}; + o2::base::MatLayerCylSet* lut; + o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; + + // DCAFitter + o2::vertexing::DCAFitterN<2> df; + + int runNumber{0}; + double magneticField{0.}; + + enum CharmBaryonCandCounter { All = 0, + HfFlagPass, + CascReconstructed, + VertexFit }; + + // Table aliases + using SelectedCollisions = soa::Join; + using TracksWCovIU = soa::Join; + using TracksWCovDcaExtraPidPrPiKa = soa::Join; + using TracksWCovExtraPidIU = soa::Join; + + HistogramRegistry registry{"hists"}; + OutputObj zorroSummary{"zorroSummary"}; + HfEventSelection hfEvSel; + + // PDG Id of daughter tracks & V0s & cascades & charm baryons - Used in KFParticle + int pdgIdOfV0DauPos, pdgIdOfV0DauNeg, pdgIdOfBach, pdgIdOfCharmBach; + int pdgIdOfAntiV0DauPos, pdgIdOfAntiV0DauNeg, pdgIdOfAntiBach, pdgIdOfAntiCharmBach; + int pdgIdOfV0, pdgIdOfCascade, pdgIdOfCharmBaryon; + + // Track PID - Used in DCAFitter + int trackPidOfCascade; + + // Mass of daughter tracks & V0s & cascades & charm baryons; + float massOfV0DauPos, massOfV0DauNeg, massOfBach, massOfCharmBach; + float massOfV0, massOfCascade, massOfCharmBaryon; + + // Pointer of histograms for QA + std::shared_ptr hInvMassCharmBaryonToXiPi, hInvMassCharmBaryonToOmegaPi, hInvMassCharmBaryonToOmegaKa; + std::shared_ptr hCandidateCounterToXiPi, hCandidateCounterToOmegaPi, hCandidateCounterToOmegaKa; + + void init(InitContext const&) + { + std::vector processesToXiPiDca{doprocessToXiPiWithDCAFitterNoCent, /*doprocessToXiPiWithDCAFitterNoCentWithTrackedCasc,*/ doprocessToXiPiWithDCAFitterCentFT0C, doprocessToXiPiWithDCAFitterCentFT0M}; + std::vector processesToOmegaPiDca{doprocessToOmegaPiWithDCAFitterNoCent, doprocessToOmegaPiWithDCAFitterCentFT0C, doprocessToOmegaPiWithDCAFitterCentFT0M}; + std::vector processesToOmegaKaDca{doprocessToOmegaKaWithDCAFitterNoCent, doprocessToOmegaKaWithDCAFitterCentFT0C, doprocessToOmegaKaWithDCAFitterCentFT0M}; + std::vector processesToXiPiKf{doprocessToXiPiWithKFParticleNoCent, doprocessToXiPiWithKFParticleCentFT0C, doprocessToXiPiWithKFParticleCentFT0M}; + std::vector processesToOmegaPiKf{doprocessToOmegaPiWithKFParticleNoCent, doprocessToOmegaPiWithKFParticleCentFT0C, doprocessToOmegaPiWithKFParticleCentFT0M}; + std::vector processesToOmegaKaKf{doprocessToOmegaKaWithKFParticleNoCent, doprocessToOmegaKaWithKFParticleCentFT0C, doprocessToOmegaKaWithKFParticleCentFT0M}; + std::vector processesCollMonitoring{doprocessCollisionsNoCent, doprocessCollisionsCentFT0C, doprocessCollisionsCentFT0M}; + + int xipiEnabledDca = std::accumulate(processesToXiPiDca.begin(), processesToXiPiDca.end(), 0); + int xipiEnabledKf = std::accumulate(processesToXiPiKf.begin(), processesToXiPiKf.end(), 0); + int omegapiEnabledDca = std::accumulate(processesToOmegaPiDca.begin(), processesToOmegaPiDca.end(), 0); + int omegapiEnabledKf = std::accumulate(processesToOmegaPiKf.begin(), processesToOmegaPiKf.end(), 0); + int omegakaEnabledDca = std::accumulate(processesToOmegaKaDca.begin(), processesToOmegaKaDca.end(), 0); + int omegakaEnabledKf = std::accumulate(processesToOmegaKaKf.begin(), processesToOmegaKaKf.end(), 0); + + // Exit if workflow is not configured correctly - More than one process function enabled for candidate to XiPi + if ((xipiEnabledDca > 0) && (xipiEnabledKf > 0)) { + LOGP(fatal, "More than one process function enabled for candidte decaying to xi pi"); + } + + // Exit if workflow is not configured correctly - More than one process function enabled for candidate to OmegaPi + if ((omegapiEnabledDca > 0) && (omegapiEnabledKf > 0)) { + LOGP(fatal, "More than one process function enabled for candidte decaying to omega pi"); + } + + // Exit if workflow is not configured correctly - More than one process function enabled for candidate to OmegaKa + if ((omegakaEnabledDca > 0) && (omegakaEnabledKf > 0)) { + LOGP(fatal, "More than one process function enabled for candidte decaying to omega ka"); + } + + // Exit if workflow is not configured correctly - More than one process enabled for collision monitoring + if (std::accumulate(processesCollMonitoring.begin(), processesCollMonitoring.end(), 0) > 1) { + LOGP(fatal, "More than one process fucntion for CollMonitoring was enabled. Please choose only one process function"); + } + + // Assign pdg & mass hypothesis for each decay channel + if (xipiEnabledDca > 0 || xipiEnabledKf > 0) { + pdgIdOfV0DauPos = kProton; + pdgIdOfV0DauNeg = kPiMinus; + pdgIdOfBach = kPiMinus; + pdgIdOfCharmBach = kPiPlus; + + pdgIdOfAntiV0DauPos = kPiPlus; + pdgIdOfAntiV0DauNeg = kProton; + pdgIdOfAntiBach = kPiPlus; + pdgIdOfAntiCharmBach = kPiMinus; + + pdgIdOfV0 = kLambda0; + pdgIdOfCascade = kXiMinus; + pdgIdOfCharmBaryon = kXiC0; + + trackPidOfCascade = o2::track::PID::XiMinus; + + massOfCharmBach = o2::constants::physics::MassPiPlus; + massOfV0DauPos = o2::constants::physics::MassProton; + massOfV0DauNeg = o2::constants::physics::MassPionCharged; + massOfV0 = o2::constants::physics::MassLambda; + massOfCascade = o2::constants::physics::MassXiMinus; + } else if (omegapiEnabledDca > 0 || omegapiEnabledKf > 0) { + pdgIdOfV0DauPos = kProton; + pdgIdOfV0DauNeg = kPiMinus; + pdgIdOfBach = kKMinus; + pdgIdOfCharmBach = kPiPlus; + + pdgIdOfAntiV0DauPos = kPiPlus; + pdgIdOfAntiV0DauNeg = kProton; + pdgIdOfAntiBach = kKPlus; + pdgIdOfAntiCharmBach = kPiMinus; + + pdgIdOfV0 = kLambda0; + pdgIdOfCascade = kOmegaMinus; + pdgIdOfCharmBaryon = kOmegaC0; + + trackPidOfCascade = o2::track::PID::OmegaMinus; + + massOfCharmBach = o2::constants::physics::MassPiPlus; + massOfV0DauPos = o2::constants::physics::MassProton; + massOfV0DauNeg = o2::constants::physics::MassPionCharged; + massOfV0 = o2::constants::physics::MassLambda; + massOfCascade = o2::constants::physics::MassOmegaMinus; + } else if (omegakaEnabledDca > 0 || omegakaEnabledKf > 0) { + pdgIdOfV0DauPos = kProton; + pdgIdOfV0DauNeg = kPiMinus; + pdgIdOfBach = kKMinus; + pdgIdOfCharmBach = kKPlus; + + pdgIdOfAntiV0DauPos = kPiPlus; + pdgIdOfAntiV0DauNeg = kProton; + pdgIdOfAntiBach = kKPlus; + pdgIdOfAntiCharmBach = kKMinus; + + pdgIdOfV0 = kLambda0; + pdgIdOfCascade = kOmegaMinus; + pdgIdOfCharmBaryon = kOmegaC0; + + trackPidOfCascade = o2::track::PID::OmegaMinus; + + massOfCharmBach = o2::constants::physics::MassKPlus; + massOfV0DauPos = o2::constants::physics::MassProton; + massOfV0DauNeg = o2::constants::physics::MassPionCharged; + massOfV0 = o2::constants::physics::MassLambda; + massOfCascade = o2::constants::physics::MassOmegaMinus; + } + LOGF(info, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); + LOGF(info, "PDG ID of V0 positive daughter: %d", pdgIdOfV0DauPos); + LOGF(info, "PDG ID of V0 negative daughter: %d", pdgIdOfV0DauNeg); + LOGF(info, "PDG ID of Bachelor: %d", pdgIdOfBach); + LOGF(info, "PDG ID of Charm Bachelor: %d", pdgIdOfCharmBach); + LOGF(info, "-------------------------------------------"); + LOGF(info, "PDG ID of anti V0 positive daughter: %d", pdgIdOfAntiV0DauPos); + LOGF(info, "PDG ID of anti V0 negative daughter: %d", pdgIdOfAntiV0DauNeg); + LOGF(info, "PDG ID of anti Bachelor: %d", pdgIdOfAntiBach); + LOGF(info, "PDG ID of anti Charm Bachelor: %d", pdgIdOfAntiCharmBach); + LOGF(info, "-------------------------------------------"); + LOGF(info, "PDG ID of V0: %d", pdgIdOfV0); + LOGF(info, "PDG ID of Cascade: %d", pdgIdOfCascade); + LOGF(info, "PDG ID of Charm Baryon: %d", pdgIdOfCharmBaryon); + LOGF(info, "-------------------------------------------"); + LOGF(info, "Mass of V0 set as: %f", massOfV0); + LOGF(info, "Mass of CharmBach set as: %f", massOfCharmBach); + LOGF(info, "Mass of Casc as: %f", massOfCascade); + LOGF(info, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); + + // Add histogram to indicate which sv method was used + registry.add("hVertexerType", "Use KF or DCAFitterN;Vertexer type;entries", {kTH1F, {{2, 0.0, 2.0}}}); + registry.get(HIST("hVertexerType"))->GetXaxis()->SetBinLabel(1 + aod::hf_cand::VertexerType::DCAFitter, "DCAFitter"); + registry.get(HIST("hVertexerType"))->GetXaxis()->SetBinLabel(1 + aod::hf_cand::VertexerType::KfParticle, "KFParticle"); + + // initialize ccdb + // --------------- + ccdb->setURL(configs.ccdbUrl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get(configs.ccdbPathLut)); + straHelper.lut = lut; + runNumber = 0; + + // Initilization for strangeness builder helper + // -------------------------------------------- + + // Settings for internal V0 building + straHelper.v0selections.minCrossedRows = LFConfigs.minCrossedRowsFromLF; + straHelper.v0selections.dcanegtopv = LFConfigs.dcanegtopvFromLF; + straHelper.v0selections.dcapostopv = LFConfigs.dcapostopvFromLF; + straHelper.v0selections.v0cospa = LFConfigs.v0cospaFromLF; + straHelper.v0selections.dcav0dau = LFConfigs.dcav0dauFromLF; + straHelper.v0selections.v0radius = LFConfigs.v0radiusFromLF; + straHelper.v0selections.maxDaughterEta = LFConfigs.maxDaughterEtaFromLF; + + // Settings for internal Cascade building + straHelper.cascadeselections.minCrossedRows = LFConfigs.minCrossedRowsFromLF; + straHelper.cascadeselections.dcabachtopv = LFConfigs.dcabachtopvFromLF; + straHelper.cascadeselections.cascradius = LFConfigs.cascradiusFromLF; + straHelper.cascadeselections.casccospa = LFConfigs.casccospaFromLF; + straHelper.cascadeselections.dcacascdau = LFConfigs.dcacascdauFromLF; + straHelper.cascadeselections.lambdaMassWindow = LFConfigs.lambdaMassWindowFromLF; + straHelper.cascadeselections.maxDaughterEta = LFConfigs.maxDaughterEtaFromLF; + + // Fitter setting + straHelper.fitter.setPropagateToPCA(LFConfigs.propagateToPCALF); + straHelper.fitter.setMaxR(LFConfigs.maxRLF); + straHelper.fitter.setMaxDZIni(LFConfigs.maxDZIniLF); + straHelper.fitter.setMaxDXYIni(LFConfigs.maxDXYIniLF); + straHelper.fitter.setMinParamChange(LFConfigs.minParamChangeLF); + straHelper.fitter.setMinRelChi2Change(LFConfigs.minRelChi2ChangeLF); + straHelper.fitter.setMaxChi2(LFConfigs.maxChi2LF); + straHelper.fitter.setUseAbsDCA(LFConfigs.useAbsDCALF); + straHelper.fitter.setWeightedFinalPCA(LFConfigs.useWeightedFinalPCALF); + straHelper.fitter.setRefitWithMatCorr(LFConfigs.refitWithMaterialCorrectionLF); + + // Extra initialization for DCAFitter + // ---------------------------------- + if (xipiEnabledDca == 1 || omegapiEnabledDca == 1 || omegakaEnabledDca == 1) { + registry.get(HIST("hVertexerType"))->Fill(aod::hf_cand::VertexerType::DCAFitter); + df.setPropagateToPCA(configs.propagateToPCA); + df.setMaxR(configs.maxR); + df.setMaxDZIni(configs.maxDZIni); + df.setMaxDXYIni(configs.maxDXYIni); + df.setMinParamChange(configs.minParamChange); + df.setMinRelChi2Change(configs.minRelChi2Change); + df.setMaxChi2(configs.maxChi2); + df.setUseAbsDCA(configs.useAbsDCA); + df.setWeightedFinalPCA(configs.useWeightedFinalPCA); + } + + // Extra initialization for KFParticle + // ----------------------------------- + if (xipiEnabledKf == 1 || omegapiEnabledKf == 1 || omegakaEnabledKf == 1) { + registry.get(HIST("hVertexerType"))->Fill(aod::hf_cand::VertexerType::KfParticle); + } + + // initailize HF event selection helper + // ------------------------------------ + hfEvSel.init(registry, &zorroSummary); + + // Histograms for QA + // ----------------- + registry.add("ReconstructedDecayChannel", "DecyayChannel", {kTH1F, {{3, 0.0, 3.0}}}); + registry.get(HIST("ReconstructedDecayChannel"))->GetXaxis()->SetBinLabel(1 + hf_cand_casc_lf::DecayType2Prong::XiczeroOmegaczeroToXiPi, "To #Xi #pi"); + registry.get(HIST("ReconstructedDecayChannel"))->GetXaxis()->SetBinLabel(1 + hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaPi, "To #Omega #pi"); + registry.get(HIST("ReconstructedDecayChannel"))->GetXaxis()->SetBinLabel(1 + hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaK, "To #Omega K"); + + if (xipiEnabledDca != 0 || xipiEnabledKf != 0) { + hInvMassCharmBaryonToXiPi = registry.add("hInvMassCharmBaryonToXiPi", "Charm baryon invariant mass - #Xi #pi decay;inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH1D, {{configs.nBinMassCharmBaryon, configs.minMassCharmBaryon, configs.maxMassCharmBaryon}}}); + hCandidateCounterToXiPi = registry.add("hCandidateCounterToXiPi", "Candidate counter wrt derived data - #Xi #pi decay;status;entries", {HistType::kTH1D, {{4, -0.5, 3.5}}}); + registry.get(HIST("hCandidateCounterToXiPi"))->GetXaxis()->SetBinLabel(1 + All, "Total"); + registry.get(HIST("hCandidateCounterToXiPi"))->GetXaxis()->SetBinLabel(1 + HfFlagPass, "HfFlagPass"); + registry.get(HIST("hCandidateCounterToXiPi"))->GetXaxis()->SetBinLabel(1 + CascReconstructed, "CascReconstructed"); + registry.get(HIST("hCandidateCounterToXiPi"))->GetXaxis()->SetBinLabel(1 + VertexFit, "VertexFit"); + registry.get(HIST("ReconstructedDecayChannel"))->Fill(hf_cand_casc_lf::DecayType2Prong::XiczeroOmegaczeroToXiPi); + } + + if (omegapiEnabledDca != 0 || omegapiEnabledKf != 0) { + hInvMassCharmBaryonToOmegaPi = registry.add("hInvMassCharmBaryonToOmegaPi", "Charm baryon invariant mass - #Omega #pi decay;inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH1D, {{configs.nBinMassCharmBaryon, configs.minMassCharmBaryon, configs.maxMassCharmBaryon}}}); + hCandidateCounterToOmegaPi = registry.add("hCandidateCounterToOmegaPi", "Candidate counter wrt derived data - #Omega #pi decay;status;entries", {HistType::kTH1D, {{4, -0.5, 3.5}}}); + registry.get(HIST("hCandidateCounterToOmegaPi"))->GetXaxis()->SetBinLabel(1 + All, "Total"); + registry.get(HIST("hCandidateCounterToOmegaPi"))->GetXaxis()->SetBinLabel(1 + HfFlagPass, "HfFlagPass"); + registry.get(HIST("hCandidateCounterToOmegaPi"))->GetXaxis()->SetBinLabel(1 + CascReconstructed, "CascReconstructed"); + registry.get(HIST("hCandidateCounterToOmegaPi"))->GetXaxis()->SetBinLabel(1 + VertexFit, "VertexFit"); + registry.get(HIST("ReconstructedDecayChannel"))->Fill(hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaPi); + } + + if (omegakaEnabledDca != 0 || omegakaEnabledKf != 0) { + hInvMassCharmBaryonToOmegaKa = registry.add("hInvMassCharmBaryonToOmegaKa", "Charm baryon invariant mass - #Omega K decay;inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH1D, {{configs.nBinMassCharmBaryon, configs.minMassCharmBaryon, configs.maxMassCharmBaryon}}}); + hCandidateCounterToOmegaKa = registry.add("hCandidateCounterToOmegaKa", "Candidate counter wrt derived data - #Omega K decay;status;entries", {HistType::kTH1D, {{4, -0.5, 3.5}}}); + registry.get(HIST("hCandidateCounterToOmegaKa"))->GetXaxis()->SetBinLabel(1 + All, "Total"); + registry.get(HIST("hCandidateCounterToOmegaKa"))->GetXaxis()->SetBinLabel(1 + HfFlagPass, "HfFlagPass"); + registry.get(HIST("hCandidateCounterToOmegaKa"))->GetXaxis()->SetBinLabel(1 + CascReconstructed, "CascReconstructed"); + registry.get(HIST("hCandidateCounterToOmegaKa"))->GetXaxis()->SetBinLabel(1 + VertexFit, "VertexFit"); + registry.get(HIST("ReconstructedDecayChannel"))->Fill(hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaK); + } + + registry.add("hCascMass", "Inv mass of reconstructed cascade;Inv mass;Entries", {HistType::kTH1F, {{configs.nBinMassCasc, configs.minMassCasc, configs.maxMassCasc}}}); + registry.add("hCascPt", "Pt of reconstructed cascade;pT;Entries", {HistType::kTH1F, {{configs.nBinPtCasc, configs.minPtCasc, configs.maxPtCasc}}}); + + } // end of initialization + + //////////////////////////////////////////////////////////// + // // + // Candidate reconstruction with DCAFitter // + // // + //////////////////////////////////////////////////////////// + + // template function for running charm baryon reconstruction with DCAFitter + /// \brief centEstimator is for different centrality estimators + /// \brief decayChannel is for different decay channels. 0 for XiczeroOmegaczeroToXiPi, 1 for OmegaczeroToOmegaPi, 2 for OmegaczeroToOmeagaK + /// \brief Colls is for collision tables joined with different centraltiy estimators + /// \brief Hist is for QA histograms + template + void runCreatorWithDCAFitter(Colls const&, + aod::HfCascLf2Prongs const& candidates, + aod::Cascades const&, // -> Internal cascade building + aod::V0s const&, // -> Internal v0 building + aod::TracksWCovDca const& tracks, + TracksWCovIU const& lfTracks, + aod::BCsWithTimestamps const&, + Hist& hInvMassCharmBaryon, + Hist& hCandCounter) + { + // arrays which holds values for different decay channel reconstruction + + // Loop over candidate + for (auto const& cand : candidates) { + + // Fill cascandidates before selection + if (configs.fillHistograms) { + hCandCounter->Fill(All); + } + + // Apply hfflag selection for different candidate reconstruction + if (!TESTBIT(cand.hfflag(), decayChannel)) { + continue; + } else { + if (configs.fillHistograms) { + hCandCounter->Fill(HfFlagPass); + } + } + + // Event selection + auto collision = cand.collision_as(); + float centrality{-1.f}; + const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); + if (rejectionMask != 0) { // None of the event selection satisfied -> Reject this candidate + continue; + } + + //------------------------------Set Magnetic field------------------------------ + auto bc = collision.template bc_as(); + if (runNumber != bc.runNumber()) { + LOG(info) << ">>>>>>>>>> Current run Number : " << runNumber; + initCCDB(bc, runNumber, ccdb, configs.isRun2 ? configs.ccdbPathGrp : configs.ccdbPathGrpMag, lut, configs.isRun2); + magneticField = o2::base::Propagator::Instance()->getNominalBz(); + LOG(info) << ">>>>>>>>>> Magnetic field: " << magneticField; + runNumber = bc.runNumber(); + } + straHelper.fitter.setBz(magneticField); // -> Magnetic field setting for internal cascade building + df.setBz(magneticField); // -> Magnetic field setting for charm baryon building + + //------------------Intenal Cascade building------------------ + auto cascAodElement = cand.cascade_as(); + auto v0AodElement = cascAodElement.v0_as(); + auto posTrack = lfTracks.rawIteratorAt(v0AodElement.posTrackId()); + auto negTrack = lfTracks.rawIteratorAt(v0AodElement.negTrackId()); + auto bachTrack = lfTracks.rawIteratorAt(cascAodElement.bachelorId()); + + // Make cascade starting from V0 + // If success, fill Cascade and V0 information for reconstruction + if (!straHelper.buildCascadeCandidate(collision.globalIndex(), + collision.posX(), collision.posY(), collision.posZ(), + posTrack, + negTrack, + bachTrack, + false, // calculateBachelorBaryonVariable + false, // useCascadeMomentumAtPV + true)) { + continue; + } else { + float storeMass = (decayChannel == 0) ? straHelper.cascade.massXi : straHelper.cascade.massOmega; + float storePt = RecoDecay::pt(straHelper.cascade.cascadeMomentum); + registry.fill(HIST("hCascMass"), storeMass); + registry.fill(HIST("hCascPt"), storePt); + if (configs.fillHistograms) { + hCandCounter->Fill(CascReconstructed); + } + } + + //------------------------------Info of V0 and cascade------------------------------ + // V0 quantities from LF strangeness builder + std::array vertexV0 = {straHelper.cascade.v0Position[0], straHelper.cascade.v0Position[1], straHelper.cascade.v0Position[2]}; + std::array pVecV0DauPos = {straHelper.cascade.positiveMomentum[0], straHelper.cascade.positiveMomentum[1], straHelper.cascade.positiveMomentum[2]}; + std::array pVecV0DauNeg = {straHelper.cascade.negativeMomentum[0], straHelper.cascade.negativeMomentum[1], straHelper.cascade.negativeMomentum[2]}; + std::array pVecV0 = {pVecV0DauPos[0] + pVecV0DauNeg[0], pVecV0DauPos[1] + pVecV0DauNeg[1], pVecV0DauPos[2] + pVecV0DauNeg[2]}; + + // pseudo rapidity - V0 daughters + // float pseudorapV0Dau0 = RecoDecay::eta(pVecV0DauPos); + // float pseudorapV0Dau1 = RecoDecay::eta(pVecV0DauNeg); + + // Cascade quantities from LF strangeness builder + std::array vertexCasc = {straHelper.cascade.cascadePosition[0], straHelper.cascade.cascadePosition[1], straHelper.cascade.cascadePosition[2]}; + std::array const pVecCasc = {straHelper.cascade.cascadeMomentum[0], straHelper.cascade.cascadeMomentum[1], straHelper.cascade.cascadeMomentum[2]}; + std::array covCasc = {0.}; + constexpr int NumCovElement = 6; + constexpr int MomInd[NumCovElement] = {9, 13, 14, 18, 19, 20}; + for (int i = 0; i < NumCovElement; i++) { + covCasc[MomInd[i]] = straHelper.cascade.covariance[MomInd[i]]; + covCasc[i] = straHelper.cascade.covariance[i]; + } + + // pseudo rapidity - cascade bachelor + // float pseudorapCascBachelor = RecoDecay::eta(straHelper.cascade.bachelorMomentum); + + //------------------------------Create cascade track------------------------------ + + o2::track::TrackParCov trackCasc; + if (bachTrack.sign() < 0) { // Xi- or Omega- + trackCasc = o2::track::TrackParCov(vertexCasc, pVecCasc, covCasc, -1, true); + } else if (bachTrack.sign() > 0) { // Xi+ or Omega+ + trackCasc = o2::track::TrackParCov(vertexCasc, pVecCasc, covCasc, 1, true); + } else { + continue; + } + + trackCasc.setAbsCharge(1); + trackCasc.setPID(trackPidOfCascade); + + //------------------------------Fit SV & Create Charm Baryon track------------------------------ + + // Perform secondary vertex fitting + auto trackCharmBachelor = tracks.rawIteratorAt(cand.prong0Id()); + auto trackParCovCharmBachelor = getTrackParCov(trackCharmBachelor); + try { + if (df.process(trackCasc, trackParCovCharmBachelor) == 0) { + continue; + } + } catch (const std::runtime_error& error) { + LOG(info) << "Run time error found: " << error.what() << ". DCAFitter cannot work. Skipping this candidate"; + continue; + } + + if (configs.fillHistograms) { + hCandCounter->Fill(VertexFit); + } + + //------------------------------Calculate physical properties----------------------------- + + // get track momenta + std::array pVecCascAsD, pVecCharmBachAsD; + df.getTrack(0).getPxPyPzGlo(pVecCascAsD); + df.getTrack(1).getPxPyPzGlo(pVecCharmBachAsD); + + std::array pVecCharmBaryon = {pVecCascAsD[0] + pVecCharmBachAsD[0], pVecCascAsD[1] + pVecCharmBachAsD[1], pVecCascAsD[2] + pVecCharmBachAsD[2]}; + std::array pVecBach = {straHelper.cascade.bachelorMomentum[0], straHelper.cascade.bachelorMomentum[1], straHelper.cascade.bachelorMomentum[2]}; + + // get PV Properties + auto primaryVertex = getPrimaryVertex(collision); + auto covMatrixPV = primaryVertex.getCov(); + std::array pvCoord = {collision.posX(), collision.posY(), collision.posZ()}; + + // get SV Properties + auto const& secondaryVertex = df.getPCACandidate(); + auto covMatrixSV = df.calcPCACovMatrixFlat(); + + // DCAxy and DCAz. Computed with propagatToDCABxByBz method + auto trackParCovV0DauPos = getTrackParCov(posTrack); + auto trackParCovV0DauNeg = getTrackParCov(negTrack); + auto trackParCovBach = getTrackParCov(bachTrack); + + o2::dataformats::DCA impactParameterV0DauPos, impactParameterV0DauNeg, impactParameterBach; + o2::base::Propagator::Instance()->propagateToDCABxByBz(primaryVertex, trackParCovV0DauPos, 2.f, matCorr, &impactParameterV0DauPos); + o2::base::Propagator::Instance()->propagateToDCABxByBz(primaryVertex, trackParCovV0DauNeg, 2.f, matCorr, &impactParameterV0DauNeg); + o2::base::Propagator::Instance()->propagateToDCABxByBz(primaryVertex, trackParCovBach, 2.f, matCorr, &impactParameterBach); + + float dcaxyV0DauPos = impactParameterV0DauPos.getY(); + float dcaxyV0DauNeg = impactParameterV0DauNeg.getY(); + float dcaxyBach = impactParameterBach.getY(); + float dcazV0DauPos = impactParameterV0DauPos.getZ(); + float dcazV0DauNeg = impactParameterV0DauNeg.getZ(); + float dcazBach = impactParameterBach.getZ(); + + // get impact parameter. Compute with propagateToDCABxByBz method + o2::dataformats::DCA impactParameterCasc, impactParameterCharmBach; + o2::base::Propagator::Instance()->propagateToDCABxByBz(primaryVertex, trackCasc, 2.f, matCorr, &impactParameterCasc); // trackCasc is TrackParCov object + o2::base::Propagator::Instance()->propagateToDCABxByBz(primaryVertex, trackParCovCharmBachelor, 2.f, matCorr, &impactParameterCharmBach); + // float impactParCharmBachFromCharmBayonXY = impactParameterCharmBach.getY(); + // float impactParCharmBachFromCharmBayonZ = impactParameterCharmBach.getZ(); + + // get v0 invariant mass - from LF Table + float mLambda = RecoDecay::m(std::array{pVecV0DauPos, pVecV0DauNeg}, (straHelper.cascade.charge < 0) ? std::array{massOfV0DauPos, massOfV0DauNeg} : std::array{massOfV0DauNeg, massOfV0DauPos}); + + // get Casc mass - from LF Table + float mCasc = (decayChannel != hf_cand_casc_lf::DecayType2Prong::XiczeroOmegaczeroToXiPi) ? straHelper.cascade.massOmega : straHelper.cascade.massXi; + + // get Charm baryon invariant mass + float massCharmBaryonCand = RecoDecay::m(std::array{pVecCascAsD, pVecCharmBachAsD}, std::array{massOfCascade, massOfCharmBach}); + if (configs.fillHistograms) { + hInvMassCharmBaryon->Fill(massCharmBaryonCand); + } + + // calculate cosine of pointing angle + std::array vtxCoordCharmBaryon = df.getPCACandidatePos(); + float cpaV0 = RecoDecay::cpa(pvCoord, vertexV0, pVecV0); + float cpaCasc = RecoDecay::cpa(pvCoord, vertexCasc, pVecCasc); + float cpaCharmBaryon = RecoDecay::cpa(pvCoord, vtxCoordCharmBaryon, pVecCharmBaryon); + float cpaxyV0 = RecoDecay::cpaXY(pvCoord, vertexV0, pVecV0); + float cpaxyCasc = RecoDecay::cpaXY(pvCoord, vertexCasc, pVecCasc); + float cpaxyCharmBaryon = RecoDecay::cpaXY(pvCoord, vtxCoordCharmBaryon, pVecCharmBaryon); + + // calculate decay length + float decLenV0 = RecoDecay::distance(vertexCasc, vertexV0); + float decLenCasc = RecoDecay::distance(vtxCoordCharmBaryon, vertexCasc); + float decLenCharmBaryon = RecoDecay::distance(pvCoord, vtxCoordCharmBaryon); + float phi, theta; + getPointDirection(std::array{primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}, secondaryVertex, phi, theta); + auto errorDecayLength = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, theta) + getRotatedCovMatrixXX(covMatrixSV, phi, theta)); + auto errorDecayLengthXY = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, 0.) + getRotatedCovMatrixXX(covMatrixSV, phi, 0.)); + + // calcuate ctau + float ctV0 = RecoDecay::ct(pVecV0, decLenV0, MassLambda0); + float ctCasc = RecoDecay::ct(pVecCasc, decLenCasc, massOfCascade); + float ctOmegac0 = RecoDecay::ct(pVecCharmBaryon, decLenCharmBaryon, MassOmegaC0); + float ctXic0 = RecoDecay::ct(pVecCharmBaryon, decLenCharmBaryon, MassXiC0); + + // get eta + float etaV0DauPos = posTrack.eta(); + float etaV0DauNeg = negTrack.eta(); + float etaBach = bachTrack.eta(); + float etaCharmBach = trackCharmBachelor.eta(); + float etaV0 = RecoDecay::eta(pVecV0); + float etaCasc = RecoDecay::eta(pVecCasc); + float etaCharmBaryon = RecoDecay::eta(pVecCharmBaryon); + + // DCA between daughters + float dcaV0Dau = straHelper.cascade.v0DaughterDCA; + float dcaCascDau = straHelper.cascade.cascadeDaughterDCA; + float dcaCharmBaryonDau = std::sqrt(df.getChi2AtPCACandidate()); + + //------------------------------Fill QA histograms----------------------------- + + //------------------------------Fill the table----------------------------- + if constexpr (decayChannel == hf_cand_casc_lf::DecayType2Prong::XiczeroOmegaczeroToXiPi) { + cursors.rowCandToXiPi(collision.globalIndex(), + pvCoord[0], pvCoord[1], pvCoord[2], + secondaryVertex[0], secondaryVertex[1], secondaryVertex[2], + vertexCasc[0], vertexCasc[1], vertexCasc[2], + vertexV0[0], vertexV0[1], vertexV0[2], + bachTrack.sign(), + covMatrixSV[0], covMatrixSV[1], covMatrixSV[2], covMatrixSV[3], covMatrixSV[4], covMatrixSV[5], + pVecCharmBaryon[0], pVecCharmBaryon[1], pVecCharmBaryon[2], + pVecCascAsD[0], pVecCascAsD[1], pVecCascAsD[2], + pVecCharmBachAsD[0], pVecCharmBachAsD[1], pVecCharmBachAsD[2], + pVecV0[0], pVecV0[1], pVecV0[2], + pVecBach[0], pVecBach[1], pVecBach[2], + pVecV0DauPos[0], pVecV0DauPos[1], pVecV0DauPos[2], + pVecV0DauNeg[0], pVecV0DauNeg[1], pVecV0DauNeg[2], + impactParameterCasc.getY(), impactParameterCharmBach.getY(), + impactParameterCasc.getZ(), impactParameterCharmBach.getZ(), + std::sqrt(impactParameterCasc.getSigmaY2()), std::sqrt(impactParameterCharmBach.getSigmaY2()), + cascAodElement.v0Id(), v0AodElement.posTrackId(), v0AodElement.negTrackId(), + cand.cascadeId(), trackCharmBachelor.globalIndex(), cand.prong0Id(), + mLambda, mCasc, massCharmBaryonCand, + cpaV0, cpaCharmBaryon, cpaCasc, + cpaxyV0, cpaxyCharmBaryon, cpaxyCasc, + ctOmegac0, ctCasc, ctV0, ctXic0, + etaV0DauPos, etaV0DauNeg, etaBach, etaCharmBach, etaCharmBaryon, etaCasc, etaV0, + dcaxyV0DauPos, dcaxyV0DauNeg, dcaxyBach, + dcazV0DauPos, dcazV0DauNeg, dcazBach, + dcaCascDau, dcaV0Dau, dcaCharmBaryonDau, + decLenCharmBaryon, decLenCasc, decLenV0, errorDecayLength, errorDecayLengthXY); + } else if constexpr (decayChannel == hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaPi) { + cursors.rowCandToOmegaPi(collision.globalIndex(), + pvCoord[0], pvCoord[1], pvCoord[2], + secondaryVertex[0], secondaryVertex[1], secondaryVertex[2], + vertexCasc[0], vertexCasc[1], vertexCasc[2], + vertexV0[0], vertexV0[1], vertexV0[2], + bachTrack.sign(), + covMatrixSV[0], covMatrixSV[1], covMatrixSV[2], covMatrixSV[3], covMatrixSV[4], covMatrixSV[5], + pVecCharmBaryon[0], pVecCharmBaryon[1], pVecCharmBaryon[2], + pVecCascAsD[0], pVecCascAsD[1], pVecCascAsD[2], + pVecCharmBachAsD[0], pVecCharmBachAsD[1], pVecCharmBachAsD[2], + pVecV0[0], pVecV0[1], pVecV0[2], + pVecBach[0], pVecBach[1], pVecBach[2], + pVecV0DauPos[0], pVecV0DauPos[1], pVecV0DauPos[2], + pVecV0DauNeg[0], pVecV0DauNeg[1], pVecV0DauNeg[2], + impactParameterCasc.getY(), impactParameterCharmBach.getY(), + impactParameterCasc.getZ(), impactParameterCharmBach.getZ(), + std::sqrt(impactParameterCasc.getSigmaY2()), std::sqrt(impactParameterCharmBach.getSigmaY2()), + cascAodElement.v0Id(), v0AodElement.posTrackId(), v0AodElement.negTrackId(), + cand.cascadeId(), trackCharmBachelor.globalIndex(), cand.prong0Id(), + mLambda, mCasc, massCharmBaryonCand, + cpaV0, cpaCharmBaryon, cpaCasc, + cpaxyV0, cpaxyCharmBaryon, cpaxyCasc, + ctOmegac0, ctCasc, ctV0, + etaV0DauPos, etaV0DauNeg, etaBach, etaCharmBach, etaCharmBaryon, etaCasc, etaV0, + dcaxyV0DauPos, dcaxyV0DauNeg, dcaxyBach, + dcazV0DauPos, dcazV0DauNeg, dcazBach, + dcaCascDau, dcaV0Dau, dcaCharmBaryonDau, + decLenCharmBaryon, decLenCasc, decLenV0, errorDecayLength, errorDecayLengthXY, cand.hfflag()); + } else { + cursors.rowCandToOmegaKa(collision.globalIndex(), + pvCoord[0], pvCoord[1], pvCoord[2], + secondaryVertex[0], secondaryVertex[1], secondaryVertex[2], + vertexCasc[0], vertexCasc[1], vertexCasc[2], + vertexV0[0], vertexV0[1], vertexV0[2], + bachTrack.sign(), + covMatrixSV[0], covMatrixSV[1], covMatrixSV[2], covMatrixSV[3], covMatrixSV[4], covMatrixSV[5], + pVecCharmBaryon[0], pVecCharmBaryon[1], pVecCharmBaryon[2], + pVecCascAsD[0], pVecCascAsD[1], pVecCascAsD[2], + pVecCharmBachAsD[0], pVecCharmBachAsD[1], pVecCharmBachAsD[2], + pVecV0[0], pVecV0[1], pVecV0[2], + pVecBach[0], pVecBach[1], pVecBach[2], + pVecV0DauPos[0], pVecV0DauPos[1], pVecV0DauPos[2], + pVecV0DauNeg[0], pVecV0DauNeg[1], pVecV0DauNeg[2], + impactParameterCasc.getY(), impactParameterCharmBach.getY(), + impactParameterCasc.getZ(), impactParameterCharmBach.getZ(), + std::sqrt(impactParameterCasc.getSigmaY2()), std::sqrt(impactParameterCharmBach.getSigmaY2()), + cascAodElement.v0Id(), v0AodElement.posTrackId(), v0AodElement.negTrackId(), + cand.cascadeId(), trackCharmBachelor.globalIndex(), cand.prong0Id(), + mLambda, mCasc, massCharmBaryonCand, + cpaV0, cpaCharmBaryon, cpaCasc, + cpaxyV0, cpaxyCharmBaryon, cpaxyCasc, + ctOmegac0, ctCasc, ctV0, + etaV0DauPos, etaV0DauNeg, etaBach, etaCharmBach, etaCharmBaryon, etaCasc, etaV0, + dcaxyV0DauPos, dcaxyV0DauNeg, dcaxyBach, + dcazV0DauPos, dcazV0DauNeg, dcazBach, + dcaCascDau, dcaV0Dau, dcaCharmBaryonDau, + decLenCharmBaryon, decLenCasc, decLenV0, errorDecayLength, errorDecayLengthXY); + } + } // candidate loop + } // end of run function + + // template function for running Charm Baryon reconstruction via KFParticle method + /// \brief centEstimator is for different centrality estimators + /// \brief decayChannel is for different decay channels. 0 for XiczeroOmegaczeroToXiPi, 1 for OmegaczeroToOmegaPi, 2 for OmegaczeroToOmegaK + /// \brief Colls is for collision tables joined with different centrality estimators + /// \brief Hist is for QA histograms + template + void runCreatorWithKfParticle(Colls const&, + aod::HfCascLf2Prongs const& candidates, + aod::Cascades const&, // -> Implemented for internal cascade building + aod::V0s const&, // -> Implemented for internal cascade building + TracksWCovDcaExtraPidPrPiKa const& tracks, + TracksWCovExtraPidIU const& lfTracks, + aod::BCsWithTimestamps const&, + Hist& hInvMassCharmBaryon, + Hist& hCandCounter) + { + // Loop over candidates + for (auto const& cand : candidates) { + + // Fill cascandidates before selection + if (configs.fillHistograms) { + hCandCounter->Fill(All); + } + + // Apply hfflag selection + if (!TESTBIT(cand.hfflag(), decayChannel)) { + continue; + } else { + if (configs.fillHistograms) { + hCandCounter->Fill(HfFlagPass); + } + } + + // Event selection + auto collision = cand.collision_as(); + float centrality{-1.f}; + const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); + if (rejectionMask != 0) { // None of the event seletion satisfied -> Reject this candidate + continue; + } + + //------------------------------Set Magnetic field------------------------------ + auto bc = collision.template bc_as(); + if (runNumber != bc.runNumber()) { + LOG(info) << ">>>>>>>>>> Current run Number : " << runNumber; + initCCDB(bc, runNumber, ccdb, configs.isRun2 ? configs.ccdbPathGrp : configs.ccdbPathGrpMag, lut, configs.isRun2); + magneticField = o2::base::Propagator::Instance()->getNominalBz(); + LOG(info) << ">>>>>>>>>> Magnetic field: " << magneticField; + runNumber = bc.runNumber(); + } + // magnetic field setting for KFParticle + straHelper.fitter.setBz(magneticField); // -> Manetic field setting for internal cascade building + KFParticle::SetField(magneticField); // -> Magnetic field setting for CharmBaryon building + + //------------------Intenal Cascade building------------------ + auto cascAodElement = cand.cascade_as(); + auto v0AodElement = cascAodElement.v0_as(); + auto posTrack = lfTracks.rawIteratorAt(v0AodElement.posTrackId()); + auto negTrack = lfTracks.rawIteratorAt(v0AodElement.negTrackId()); + auto bachTrack = lfTracks.rawIteratorAt(cascAodElement.bachelorId()); + + // Make cascade starting from V0 + // If success, fill Cascade and V0 information for reconstruction + if (!straHelper.buildCascadeCandidateWithKF(collision.globalIndex(), + collision.posX(), collision.posY(), collision.posZ(), + posTrack, + negTrack, + bachTrack, + false, // calculateBachelorBaryonVariables + LFConfigs.kfConstructMethodFromLF, + LFConfigs.kfTuneForOmegaFromLF, + LFConfigs.kfUseV0MassConstraintFromLF, + LFConfigs.kfUseCascadeMassConstraintFromLF, + LFConfigs.kfDoDCAFitterPreMinimV0FromLF, + LFConfigs.kfDoDCAFitterPreMinimCascFromLF)) { + continue; + } else { + float storeMass = (decayChannel == 0) ? straHelper.cascade.massXi : straHelper.cascade.massOmega; + float storePt = RecoDecay::pt(straHelper.cascade.cascadeMomentum); + registry.fill(HIST("hCascMass"), storeMass); + registry.fill(HIST("hCascPt"), storePt); + if (configs.fillHistograms) { + hCandCounter->Fill(CascReconstructed); + } + } + + //------------------------------Cascade pre-selection------------------------------ + // ! only for Xic0, Omegac0 -> Omega K + if constexpr (decayChannel == hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaK) { + if (configs.doCascadePreselection) { + if (std::abs(straHelper.cascade.cascadeDCAxy) > configs.dcaXYToPVCascadeMax) { + continue; + } + // pre selection on dcaV0Daughters + if (std::abs(straHelper.cascade.v0DaughterDCA) > configs.dcaV0DaughtersMax) { + continue; + } + // pre selection on dcaCascDaughters + if (std::abs(straHelper.cascade.cascadeDaughterDCA) > configs.dcaCascDaughtersMax) { + continue; + } + // pre selection on invariantmass + if (std::abs(straHelper.cascade.massOmega - massOfCascade) > configs.massToleranceCascade) { + continue; + } + } + } + + //----------Create charm bayron as KF Partible object starting from V0---------- + + // Create KFParticle object of V0 Daughter & Bachelor + const KFPTrack kfTrack0 = createKFPTrackFromTrack(posTrack); + const KFPTrack kfTrack1 = createKFPTrackFromTrack(negTrack); + const KFPTrack kfTrackBach = createKFPTrackFromTrack(bachTrack); + + bool isAnti = (bachTrack.signed1Pt() > 0 ? true : false); + + KFParticle kfPos(kfTrack0, (isAnti ? pdgIdOfAntiV0DauPos : pdgIdOfV0DauPos)); + KFParticle kfNeg(kfTrack1, (isAnti ? pdgIdOfAntiV0DauNeg : pdgIdOfV0DauNeg)); + KFParticle kfBach(kfTrackBach, (isAnti ? pdgIdOfAntiBach : pdgIdOfBach)); + KFParticle kfBachRej(kfTrackBach, (isAnti ? pdgIdOfAntiBach : pdgIdOfBach)); // Rej -> Used for Omegac0->OmegaPi only + + // ~~~~~~~Construct V0 with KF~~~~~~~ + const KFParticle* v0Daughters[2] = {&kfPos, &kfNeg}; + KFParticle kfV0; + kfV0.SetConstructMethod(configs.kfConstructMethod); + try { + kfV0.Construct(v0Daughters, 2); + } catch (std::runtime_error& e) { + LOG(debug) << "Failed to construct v0" << e.what(); + continue; + } + + // Require lambda pre-selection before mass constraint + float massLam, sigMassLam; + kfV0.GetMass(massLam, sigMassLam); + if (std::abs(massLam - MassLambda0) > configs.lambdaMassWindow) { + continue; + } + if (sigMassLam <= 0) { + continue; + } + if ((kfV0.GetNDF() <= 0) || (kfV0.GetChi2() <= 0)) { + continue; + } + + // Set mass constraint to lambda + KFParticle kfV0MassConstrained = kfV0; + kfV0MassConstrained.SetNonlinearMassConstraint(massOfV0); + if (configs.kfUseV0MassConstraint) { + kfV0 = kfV0MassConstrained; + } + kfV0.TransportToDecayVertex(); + + //~~~~~~~Construct cascade with KF~~~~~~~ + const KFParticle* cascDaughters[2] = {&kfBach, &kfV0}; + const KFParticle* cascDaughtersRej[2] = {&kfBachRej, &kfV0}; + KFParticle kfCasc, kfCascRej; + + kfCasc.SetConstructMethod(configs.kfConstructMethod); + try { + kfCasc.Construct(cascDaughters, 2); + } catch (std::runtime_error& e) { + LOG(debug) << "Failed to construct Cascade: " << e.what(); + } + + float massCasc, sigMassCasc, massCascRej, sigMassCascRej; + kfCasc.GetMass(massCasc, sigMassCasc); + + if (sigMassCasc <= 0) { + continue; + } + if (std::abs(massCasc - massCasc) > configs.massToleranceCascade) { + continue; + } + if (kfCasc.GetNDF() <= 0 || kfCasc.GetChi2() <= 0) { + continue; + } + + // perform cascade building on casc_rej - only for Omega + if constexpr (decayChannel != hf_cand_casc_lf::DecayType2Prong::XiczeroOmegaczeroToXiPi) { + kfCascRej.SetConstructMethod(configs.kfConstructMethod); + try { + kfCascRej.Construct(cascDaughtersRej, 2); + } catch (std::runtime_error& e) { + LOG(debug) << "Failed to construct Cascade_rej: " << e.what(); + } + + kfCascRej.GetMass(massCascRej, sigMassCascRej); + } + + // Set mass constraint to cascade + KFParticle kfCascMassConstrained = kfCasc; + kfCascMassConstrained.SetNonlinearMassConstraint(massOfCascade); + if (configs.kfUseCascadeMassConstraint) { + kfCasc = kfCascMassConstrained; + } + kfCasc.TransportToDecayVertex(); + + //~~~~~~~Construct Charm Baryon with KF~~~~~~~ + auto trackCharmBachelor = tracks.rawIteratorAt(cand.prong0Id()); + const KFPTrack kfTrackCharmBach = createKFPTrackFromTrack(trackCharmBachelor); + const KFParticle kfCharmBach(kfTrackCharmBach, (isAnti ? pdgIdOfAntiCharmBach : pdgIdOfCharmBach)); + const KFParticle* charmBaryonDaughters[2] = {&kfCharmBach, &kfCasc}; + + KFParticle kfCharmBaryon; + kfCharmBaryon.SetConstructMethod(configs.kfConstructMethod); + try { + kfCharmBaryon.Construct(charmBaryonDaughters, 2); + } catch (std::runtime_error& e) { + LOG(debug) << "Failed to construct Charm baryon: " << e.what(); + } + + float massCharmBaryon, sigMassCharmBaryon; + kfCharmBaryon.GetMass(massCharmBaryon, sigMassCharmBaryon); + if (sigMassCharmBaryon <= 0) { + continue; + } + if (kfCharmBaryon.GetNDF() <= 0 || kfCharmBaryon.GetChi2() <= 0) { + continue; + } + kfCharmBaryon.TransportToDecayVertex(); + if (configs.fillHistograms) { + hCandCounter->Fill(VertexFit); + hInvMassCharmBaryon->Fill(massCharmBaryon); + } + + // Set production vertex + // PV + const KFPVertex kfVertex = createKFPVertexFromCollision(collision); + const KFParticle kfPv(kfVertex); + const KFParticle kfPosOrigin = kfPos; + const KFParticle kfNegOrigin = kfNeg; + + // To V0 + kfPos.SetProductionVertex(kfV0); + kfNeg.SetProductionVertex(kfV0); + + // To Casc + KFParticle kfBachToCasc = kfBach; + KFParticle kfV0ToCasc = kfV0; + kfBach.SetProductionVertex(kfCasc); + kfV0ToCasc.SetProductionVertex(kfCasc); + + // To Charm baryon + KFParticle kfCascToCharmBaryon = kfCasc; + KFParticle kfCharmBachToCharmBaryon = kfCharmBach; + kfCascToCharmBaryon.SetProductionVertex(kfCharmBaryon); + kfCharmBachToCharmBaryon.SetProductionVertex(kfCharmBaryon); + + // To Pv + KFParticle kfV0ToPv = kfV0; + KFParticle kfCascToPv = kfCasc; + KFParticle kfCharmBachToPv = kfCharmBach; + KFParticle kfCharmBaryonToPv = kfCharmBaryon; + kfV0ToPv.SetProductionVertex(kfPv); + kfCascToPv.SetProductionVertex(kfPv); + kfCharmBachToPv.SetProductionVertex(kfPv); + kfCharmBaryonToPv.SetProductionVertex(kfPv); + + //----------Reconstruct information after vertex fit---------- + std::array vertexV0 = {kfV0.GetX(), kfV0.GetY(), kfV0.GetZ()}; + std::array vertexCasc = {kfCasc.GetX(), kfCasc.GetY(), kfCasc.GetZ()}; + + std::array pVecV0DauPos = {kfPos.GetPx(), kfPos.GetPy(), kfPos.GetPz()}; + std::array pVecV0DauNeg = {kfNeg.GetPx(), kfNeg.GetPy(), kfNeg.GetPz()}; + std::array pVecV0 = {kfV0.GetPx(), kfV0.GetPy(), kfV0.GetPz()}; + std::array pVecBach = {kfBachToCasc.GetPx(), kfBachToCasc.GetPy(), kfBachToCasc.GetPz()}; + std::array pVecCharmBachelorAsD = {kfCharmBachToCharmBaryon.GetPx(), kfCharmBachToCharmBaryon.GetPy(), kfCharmBachToCharmBaryon.GetPz()}; + std::array pVecCharmBaryon = {kfCharmBaryon.GetPx(), kfCharmBaryon.GetPy(), kfCharmBaryon.GetPy()}; + + auto* covVtxCharmBaryon = kfCharmBaryon.CovarianceMatrix(); + float covMatrixPv[6]; + kfVertex.GetCovarianceMatrix(covMatrixPv); + + std::array pvCoord = {collision.posX(), collision.posY(), collision.posZ()}; + + auto trackParCovV0DauPos = getTrackParCovFromKFP(kfPos, kfPos.GetPDG(), 1); + auto trackParCovV0DauNeg = getTrackParCovFromKFP(kfNeg, kfNeg.GetPDG(), -1); + auto trackParCovBach = getTrackParCovFromKFP(kfBachToCasc, kfBachToCasc.GetPDG(), (isAnti ? 1 : -1)); + auto trackParCovCharmBach = getTrackParCovFromKFP(kfCharmBachToCharmBaryon, kfCharmBachToCharmBaryon.GetPDG(), (isAnti ? -1 : 1)); + auto trackParCovCasc = getTrackParCovFromKFP(kfCascToCharmBaryon, kfCascToCharmBaryon.GetPDG(), (isAnti ? 1 : -1)); + trackParCovV0DauPos.setAbsCharge(1); + trackParCovV0DauNeg.setAbsCharge(1); + trackParCovBach.setAbsCharge(1); + trackParCovCharmBach.setAbsCharge(1); + trackParCovCasc.setAbsCharge(1); + + //----------Calculate physical quantities and fill candidate table---------- + + // impact parameters + std::array impactParameterV0DauPos; + std::array impactParameterV0DauNeg; + std::array impactParameterBach; + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, trackParCovV0DauPos, 2.f, matCorr, &impactParameterV0DauPos); + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, trackParCovV0DauNeg, 2.f, matCorr, &impactParameterV0DauNeg); + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, trackParCovBach, 2.f, matCorr, &impactParameterBach); + float dcaxyV0DauPos = impactParameterV0DauPos[0]; + float dcaxyV0DauNeg = impactParameterV0DauNeg[0]; + float dcaxyBach = impactParameterBach[0]; + float dcazV0DauPos = impactParameterV0DauPos[1]; + float dcazV0DauNeg = impactParameterV0DauNeg[1]; + float dcazBach = impactParameterBach[1]; + + o2::dataformats::DCA impactParameterCasc, impactParameterCharmBachelor; + auto primaryVertex = getPrimaryVertex(collision); + o2::base::Propagator::Instance()->propagateToDCABxByBz(primaryVertex, trackParCovCasc, 2.f, matCorr, &impactParameterCasc); + o2::base::Propagator::Instance()->propagateToDCABxByBz(primaryVertex, trackParCovCharmBach, 2.f, matCorr, &impactParameterCharmBachelor); + + // get Chi2Topo/NDF + float chi2NdfTopoV0ToPv = kfV0ToPv.GetChi2() / kfV0ToPv.GetNDF(); + float chi2NdfTopoCascToPv = kfCascToPv.GetChi2() / kfCascToPv.GetNDF(); + float chi2NdfTopoCharmBachToPv = kfCharmBachToPv.GetChi2() / kfCharmBachToPv.GetNDF(); + float chi2NdfTopoCharmBaryonToPv = kfCharmBaryonToPv.GetChi2() / kfCharmBaryonToPv.GetNDF(); + float chi2NdfTopoBachToCasc = kfBachToCasc.GetChi2() / kfBachToCasc.GetNDF(); + float chi2NdfTopoV0ToCasc = kfV0ToCasc.GetChi2() / kfV0ToCasc.GetNDF(); + float chi2NdfTopoCharmBachToCharmBaryon = kfCharmBachToCharmBaryon.GetChi2() / kfCharmBachToCharmBaryon.GetChi2(); + float chi2NdfTopoCascToCharmBaryon = kfCascToCharmBaryon.GetChi2() / kfCascToCharmBaryon.GetChi2(); + + // get ldl + float ldlV0 = ldlFromKF(kfV0, kfPv); + float ldlCasc = ldlFromKF(kfCasc, kfPv); + float ldlCharmBaryon = ldlFromKF(kfCharmBaryon, kfPv); + + // get DCAs + float kfDcaV0Daughters = kfNeg.GetDistanceFromParticle(kfPos); + float kfDcaCascDaughters = kfBachToCasc.GetDistanceFromParticle(kfV0ToCasc); + float kfDcaCharmBaryonDaughters = kfCharmBachToCharmBaryon.GetDistanceFromParticle(kfCascToCharmBaryon); + float kfDcaXYCharmBachelorToPv = kfCharmBachToCharmBaryon.GetDistanceFromVertexXY(kfPv); + float kfDcaXYCascToPv = kfCascToCharmBaryon.GetDistanceFromVertexXY(kfPv); + + // get decay length - In XY + float decayLXYV0, errDecayLXYV0; + kfV0ToCasc.GetDecayLengthXY(decayLXYV0, errDecayLXYV0); + + float decayLXYCasc, errDecayLXYCasc; + kfCascToCharmBaryon.GetDecayLengthXY(decayLXYCasc, errDecayLXYCasc); + + float decayLXYCharmBaryon, errDecayLXYCharmBaryon; + kfCharmBaryonToPv.GetDecayLengthXY(decayLXYCharmBaryon, errDecayLXYCharmBaryon); + + // get decay length - In XYZ + float decayLV0 = RecoDecay::distance(std::array{kfCasc.GetX(), kfCasc.GetY(), kfCasc.GetZ()}, std::array{kfV0.GetX(), kfV0.GetY(), kfV0.GetZ()}); + float decayLCasc = RecoDecay::distance(std::array{kfCharmBaryon.GetX(), kfCharmBaryon.GetY(), kfCharmBaryon.GetZ()}, std::array{kfCasc.GetX(), kfCasc.GetY(), kfCasc.GetZ()}); + float decayLCharmBaryon = RecoDecay::distance(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{kfCharmBaryon.GetX(), kfCharmBaryon.GetY(), kfCharmBaryon.GetZ()}); + + double phiCharmBaryon, thetaCharmBaryon; + getPointDirection(std::array{kfV0.GetX(), kfV0.GetY(), kfV0.GetZ()}, std::array{kfCharmBaryon.GetX(), kfCharmBaryon.GetY(), kfCharmBaryon.GetZ()}, phiCharmBaryon, thetaCharmBaryon); + float errDecayLCharmBaryon = std::sqrt(getRotatedCovMatrixXX(covMatrixPv, phiCharmBaryon, thetaCharmBaryon) + getRotatedCovMatrixXX(covVtxCharmBaryon, phiCharmBaryon, thetaCharmBaryon)); + + // get cosine of pointing angle + float cosPaV0ToPv = cpaFromKF(kfV0, kfPv); + float cosPaCascToPv = cpaFromKF(kfCasc, kfPv); + float cosPaCharmBaryonToPv = cpaFromKF(kfCharmBaryon, kfPv); + + float cosPaXYV0ToPv = RecoDecay::cpaXY(pvCoord, vertexV0, pVecV0); + float cosPaXYCascToPv = cpaXYFromKF(kfCasc, kfPv); + float cosPaXYCharmBaryonToPv = cpaXYFromKF(kfCharmBaryon, kfPv); + + float cosPaV0ToCasc = cpaFromKF(kfV0, kfCasc); + float cosPaCascToCharmBaryon = cpaFromKF(kfCasc, kfCharmBaryon); + float cosPaXYV0ToCasc = RecoDecay::cpaXY(vertexCasc, vertexV0, pVecV0); + float cosPaXYCascToCharmBaryon = cpaXYFromKF(kfCasc, kfCharmBaryon); + + float deviationCharmBachToPv = kfCalculateChi2ToPrimaryVertex(kfCharmBaryon, kfPv); // -> For Omegac0 + + // KF pT, eta + float ptCasc = kfCascToCharmBaryon.GetPt(); + float ptCharmBachelor = kfCharmBachToCharmBaryon.GetPt(); + float ptCharmBaryon = kfCharmBaryon.GetPt(); + float yCharmBaryon = kfCharmBaryon.GetRapidity(); + + // get KF cosThetaStar + float cosThetaStarCharmBachelor = -99.0; + float cosThetaStarKaFromOmegac0 = -99.0; + float cosThetaStarKaFromXic0 = -99.0; + + if constexpr (decayChannel == hf_cand_casc_lf::DecayType2Prong::XiczeroOmegaczeroToXiPi) { + cosThetaStarCharmBachelor = cosThetaStarFromKF(0, pdgIdOfCharmBaryon, pdgIdOfCharmBach, pdgIdOfCascade, kfCharmBachToCharmBaryon, kfCascToCharmBaryon, pdgdb); + } + if constexpr (decayChannel == hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaK) { // -> Only requeted to be calculated and filled for Xic0/Omegac0 -> Omega K + cosThetaStarKaFromOmegac0 = cosThetaStarFromKF(0, 4332, 321, 3334, kfCharmBachToCharmBaryon, kfCascToCharmBaryon, pdgdb); + cosThetaStarKaFromXic0 = cosThetaStarFromKF(0, 4132, 321, 3334, kfCharmBachToCharmBaryon, kfCascToCharmBaryon, pdgdb); + } + + // KF ct + float ctV0 = kfV0ToCasc.GetLifeTime(); + float ctCasc = kfCascToCharmBaryon.GetLifeTime(); + float ctCharmBaryon = kfCharmBaryonToPv.GetLifeTime(); + + //------------------------------Calculate physical quantities and fill candidate table------------------------------ + + //------------------------------Fill the table------------------------------ + if constexpr (decayChannel == hf_cand_casc_lf::DecayType2Prong::XiczeroOmegaczeroToXiPi) { + cursors.rowCandToXiPiKf(collision.globalIndex(), // Global index of collision + pvCoord[0], pvCoord[1], pvCoord[2], // coordination of PV + vertexCasc[0], vertexCasc[1], vertexCasc[2], // Decay position of kfCasc + vertexV0[0], vertexV0[1], vertexV0[2], + bachTrack.sign(), + covVtxCharmBaryon[0], covVtxCharmBaryon[1], covVtxCharmBaryon[2], covVtxCharmBaryon[3], covVtxCharmBaryon[4], covVtxCharmBaryon[5], + pVecCharmBaryon[0], pVecCharmBaryon[1], pVecCharmBaryon[2], // x, y, z momentum of charm baryon + kfCascToCharmBaryon.GetPx(), kfCascToCharmBaryon.GetPy(), kfCascToCharmBaryon.GetPz(), + pVecCharmBachelorAsD[0], pVecCharmBachelorAsD[1], pVecCharmBachelorAsD[2], + pVecV0[0], pVecV0[1], pVecV0[2], + pVecBach[0], pVecBach[1], pVecBach[2], + pVecV0DauPos[0], pVecV0DauPos[1], pVecV0DauPos[2], + pVecV0DauNeg[0], pVecV0DauNeg[1], pVecV0DauNeg[2], + cascAodElement.v0Id(), v0AodElement.posTrackId(), v0AodElement.negTrackId(), + cand.cascadeId(), trackCharmBachelor.globalIndex(), cand.prong0Id(), + massLam, massCasc, massCharmBaryon, + cosPaV0ToPv, cosPaCascToPv, + ctCasc, ctV0, ctCharmBaryon, + kfPos.GetEta(), kfNeg.GetEta(), kfBach.GetEta(), kfCharmBachToCharmBaryon.GetEta(), + kfCharmBaryon.GetEta(), kfCasc.GetEta(), kfV0.GetEta(), + dcaxyV0DauPos, dcaxyV0DauNeg, dcaxyBach, + kfDcaCascDaughters, kfDcaV0Daughters, kfDcaCharmBaryonDaughters, + kfDcaXYCharmBachelorToPv, kfDcaXYCascToPv, + kfV0.GetChi2(), kfCasc.GetChi2(), kfCharmBaryon.GetChi2(), kfV0MassConstrained.GetChi2(), kfCascMassConstrained.GetChi2(), + ldlV0, ldlCasc, // ldlCharmBaryon, + chi2NdfTopoV0ToPv, chi2NdfTopoCascToPv, chi2NdfTopoCharmBachToPv, chi2NdfTopoCharmBaryonToPv, + chi2NdfTopoV0ToCasc, chi2NdfTopoCascToCharmBaryon, + decayLXYV0, decayLXYCasc, decayLXYCharmBaryon, + cosPaV0ToCasc, cosPaCascToCharmBaryon, // cosPaXYV0ToCasc, cosPaXYCascToCharmBaryon, + yCharmBaryon, // ptCharmBachelor, ptCharmBaryon, + cosThetaStarCharmBachelor, + kfV0.GetNDF(), kfCasc.GetNDF(), kfCharmBaryon.GetNDF(), kfV0MassConstrained.GetNDF(), kfCascMassConstrained.GetNDF(), + kfV0.GetChi2() / kfV0.GetNDF(), kfCasc.GetChi2() / kfCasc.GetNDF(), kfCharmBaryon.GetChi2() / kfCharmBaryon.GetNDF(), kfV0MassConstrained.GetChi2() / kfV0MassConstrained.GetNDF(), kfCascMassConstrained.GetChi2() / kfCascMassConstrained.GetNDF()); + } else if constexpr (decayChannel == hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaPi) { + cursors.rowCandToOmegaPi(collision.globalIndex(), + pvCoord[0], pvCoord[1], pvCoord[2], + 0.f, 0.f, 0.f, // -> vertexCharmBaryonFromFitter. For KF, this is 0 + vertexCasc[0], vertexCasc[1], vertexCasc[2], + vertexV0[0], vertexV0[1], vertexV0[2], + trackCharmBachelor.sign(), + covVtxCharmBaryon[0], covVtxCharmBaryon[1], covVtxCharmBaryon[2], covVtxCharmBaryon[3], covVtxCharmBaryon[4], covVtxCharmBaryon[5], + kfCharmBaryon.GetPx(), kfCharmBaryon.GetPy(), kfCharmBaryon.GetPz(), + kfCascToCharmBaryon.GetPx(), kfCascToCharmBaryon.GetPy(), kfCascToCharmBaryon.GetPz(), + kfCharmBachToCharmBaryon.GetPx(), kfCharmBachToCharmBaryon.GetPy(), kfCharmBachToCharmBaryon.GetPz(), + pVecV0[0], pVecV0[1], pVecV0[2], + pVecBach[0], pVecBach[1], pVecBach[2], + pVecV0DauPos[0], pVecV0DauPos[1], pVecV0DauPos[2], + pVecV0DauNeg[0], pVecV0DauNeg[1], pVecV0DauNeg[2], + impactParameterCasc.getY(), impactParameterCharmBachelor.getY(), + impactParameterCasc.getZ(), impactParameterCharmBachelor.getZ(), + std::sqrt(impactParameterCasc.getSigmaY2()), std::sqrt(impactParameterCharmBachelor.getSigmaY2()), + cascAodElement.v0Id(), v0AodElement.posTrackId(), v0AodElement.negTrackId(), + cand.cascadeId(), trackCharmBachelor.globalIndex(), cand.prong0Id(), + massLam, massCasc, massCharmBaryon, + cosPaV0ToPv, cosPaCharmBaryonToPv, cosPaCascToPv, cosPaXYV0ToPv, cosPaXYCharmBaryonToPv, cosPaXYCascToPv, + ctCharmBaryon, ctCasc, ctV0, + kfPos.GetEta(), kfNeg.GetEta(), kfBach.GetEta(), kfCharmBachToCharmBaryon.GetEta(), + kfCharmBaryon.GetEta(), kfCasc.GetEta(), kfV0.GetEta(), + dcaxyV0DauPos, dcaxyV0DauNeg, dcaxyBach, + dcazV0DauPos, dcazV0DauNeg, dcazBach, + kfDcaCascDaughters, straHelper.cascade.v0DaughterDCA, kfDcaCharmBaryonDaughters, + decayLCharmBaryon, decayLCasc, decayLV0, errDecayLCharmBaryon, errDecayLXYCharmBaryon, cand.hfflag()); + + cursors.rowCandToOmegaPiKf(kfDcaXYCharmBachelorToPv, kfDcaXYCascToPv, + kfV0.GetChi2(), kfCasc.GetChi2(), kfCharmBaryon.GetChi2(), kfV0MassConstrained.GetChi2(), kfCascMassConstrained.GetChi2(), + ldlV0, ldlCasc, ldlCharmBaryon, + chi2NdfTopoV0ToPv, chi2NdfTopoCascToPv, chi2NdfTopoCharmBachToPv, chi2NdfTopoCharmBaryonToPv, deviationCharmBachToPv, + chi2NdfTopoV0ToCasc, chi2NdfTopoCascToCharmBaryon, + decayLXYV0, decayLXYCasc, decayLXYCharmBaryon, + cosPaV0ToCasc, cosPaCascToCharmBaryon, cosPaXYV0ToCasc, cosPaXYCascToCharmBaryon, + kfCharmBaryon.GetRapidity(), ptCharmBachelor, ptCharmBaryon, + cosThetaStarKaFromOmegac0, + kfV0.GetNDF(), kfCasc.GetNDF(), kfCharmBaryon.GetNDF(), kfV0MassConstrained.GetNDF(), kfCascMassConstrained.GetNDF(), + kfV0.GetChi2() / kfV0.GetNDF(), kfCasc.Chi2() / kfCasc.GetNDF(), kfCharmBaryon.GetChi2() / kfCharmBaryon.GetNDF(), + kfV0MassConstrained.GetChi2() / kfV0.GetNDF(), kfCascMassConstrained.Chi2() / kfCasc.GetNDF(), + massCascRej); + + } else { + cursors.rowCandToOmegaKaKf(collision.globalIndex(), + collision.posX(), collision.posY(), collision.posZ(), + kfPv.GetX(), kfPv.GetY(), kfPv.GetZ(), + straHelper.cascade.v0Position[0], straHelper.cascade.v0Position[1], straHelper.cascade.v0Position[2], + straHelper.cascade.v0Momentum[0], straHelper.cascade.v0Momentum[1], straHelper.cascade.v0Momentum[2], + straHelper.cascade.cascadePosition[0], straHelper.cascade.cascadePosition[1], straHelper.cascade.cascadePosition[2], + straHelper.cascade.cascadeMomentum[0], straHelper.cascade.cascadeMomentum[1], straHelper.cascade.cascadeMomentum[2], + kfV0.GetX(), kfV0.GetY(), kfV0.GetZ(), + kfV0.GetPx(), kfV0.GetPy(), kfV0.GetPz(), + kfCasc.GetX(), kfCasc.GetY(), kfCasc.GetZ(), + kfCasc.GetPx(), kfCasc.GetPy(), kfCasc.GetPz(), + kfCharmBaryon.GetX(), kfCharmBaryon.GetY(), kfCharmBaryon.GetZ(), + kfCharmBaryon.GetPx(), kfCharmBaryon.GetPy(), kfCharmBaryon.GetPz(), + straHelper.cascade.charge, + kfPos.GetEta(), kfNeg.GetEta(), kfBach.GetEta(), kfCharmBach.GetEta(), kfV0.GetEta(), kfCasc.GetEta(), kfCharmBaryon.GetEta(), kfCharmBaryon.GetRapidity(), + impactParameterCharmBachelor.getY(), std::sqrt(impactParameterCharmBachelor.getSigmaY2()), impactParameterCasc.getY(), std::sqrt(impactParameterCasc.getSigmaY2()), + kfDcaV0Daughters, kfDcaCascDaughters, kfDcaCharmBaryonDaughters, + cosPaV0ToPv, cosPaCascToPv, cosPaCharmBaryonToPv, cosPaXYV0ToPv, cosPaXYCascToPv, cosPaXYCharmBaryonToPv, cosPaV0ToCasc, cosPaCascToCharmBaryon, cosPaXYV0ToCasc, cosPaXYCascToCharmBaryon, + kfV0.GetChi2() / kfV0.GetNDF(), kfCasc.GetChi2() / kfCasc.GetNDF(), kfCharmBaryon.GetChi2() / kfCharmBaryon.GetNDF(), + kfV0MassConstrained.GetChi2() / kfV0MassConstrained.GetNDF(), kfCascMassConstrained.GetChi2() / kfCascMassConstrained.GetNDF(), + chi2NdfTopoV0ToCasc, chi2NdfTopoBachToCasc, chi2NdfTopoCharmBachToCharmBaryon, chi2NdfTopoCascToCharmBaryon, // Topological constraints to mother + chi2NdfTopoV0ToPv, chi2NdfTopoCascToPv, chi2NdfTopoCharmBachToPv, chi2NdfTopoCharmBaryonToPv, // Topological constraints to PV + ldlV0, ldlCasc, ldlCharmBaryon, + decayLXYV0, decayLXYCasc, decayLXYCharmBaryon, + massLam, sigMassLam, massCasc, sigMassCasc, massCascRej, sigMassCascRej, massCharmBaryon, sigMassCharmBaryon, + ptCharmBaryon, ptCharmBachelor, ptCasc, + cosThetaStarKaFromOmegac0, cosThetaStarKaFromXic0, ctV0, ctCasc, ctCharmBaryon, + cascAodElement.v0Id(), v0AodElement.posTrackId(), v0AodElement.negTrackId(), cand.cascadeId(), cand.prong0Id(), trackCharmBachelor.globalIndex()); + } + } // end candidate loop + } // end of runCreator + + ///////////////////////////////////////////////////// + /// /// + /// Process functions with DCAFitter /// + /// /// + ///////////////////////////////////////////////////// + + /*~~~~~~~~~~~~~~*/ + /*~~~To Xi Pi~~~*/ + /*~~~~~~~~~~~~~~*/ + void processToXiPiWithDCAFitterNoCent(SelectedCollisions const& collisions, + aod::HfCascLf2Prongs const& candidates, + aod::Cascades const& cascades, + aod::V0s const& v0s, + aod::TracksWCovDca const& tracks, + TracksWCovIU const& lfTracks, + aod::BCsWithTimestamps const& bcsWithTimestamps) + { + runCreatorWithDCAFitter(collisions, candidates, cascades, v0s, tracks, lfTracks, bcsWithTimestamps, hInvMassCharmBaryonToXiPi, hCandidateCounterToXiPi); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Qa, processToXiPiWithDCAFitterNoCent, "Charm candidte reconstruction with Xi Pi via DcaFitter method, no centrality", true); + +#if 0 + void processToXiPiWithDCAFitterNoCentWithTrackedCasc(SelectedCollisions const& collisions, + aod::HfCascLf2Prongs const& candidates, + aod::TrackedCascades const& cascades, + aod::V0s const& v0s, + TrackedCascLinked const& trackedCascLinked, + TracksWCovDcaExtraPidPrPiKa const& tracks, + aod::BCsWithTimestamps const& bcsWithTimestamps) + { + runCreatorWithDCAFitter(collisions, candidates, trackedCascFull, trackedCascLinked, tracks, bcsWithTimestamps, hInvMassCharmBaryonToXiPi, hCandidateCounterToXiPi); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Qa, processToXiPiWithDCAFitterNoCentWithTrackedCasc, "Charm candidte reconstruction with Xi Pi via DcaFitter method with tracked cascade, no centrality", false); +#endif + + void processToXiPiWithDCAFitterCentFT0C(soa::Join const& collisions, + aod::HfCascLf2Prongs const& candidates, + aod::Cascades const& cascades, + aod::V0s const& v0s, + aod::TracksWCovDca const& tracks, + TracksWCovIU const& lfTracks, + aod::BCsWithTimestamps const& bcsWithTimestamps) + { + runCreatorWithDCAFitter(collisions, candidates, cascades, v0s, tracks, lfTracks, bcsWithTimestamps, hInvMassCharmBaryonToXiPi, hCandidateCounterToXiPi); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Qa, processToXiPiWithDCAFitterCentFT0C, "Charm candidate reconstruction with Xi Pi via DcaFitter method, centrality selection on FT0C", false); + + void processToXiPiWithDCAFitterCentFT0M(soa::Join const& collisions, + aod::HfCascLf2Prongs const& candidates, + aod::Cascades const& cascades, + aod::V0s const& v0s, + aod::TracksWCovDca const& tracks, + TracksWCovIU const& lfTracks, + aod::BCsWithTimestamps const& bcsWithTimestamps) + { + runCreatorWithDCAFitter(collisions, candidates, cascades, v0s, tracks, lfTracks, bcsWithTimestamps, hInvMassCharmBaryonToXiPi, hCandidateCounterToXiPi); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Qa, processToXiPiWithDCAFitterCentFT0M, "Charm candidate reconstruction with Xi Pi via DcaFitter method, centrality selection on FT0M", false); + + /*~~~~~~~~~~~~~~~~~*/ + /*~~~To Omega Pi~~~*/ + /*~~~~~~~~~~~~~~~~~*/ + void processToOmegaPiWithDCAFitterNoCent(SelectedCollisions const& collisions, + aod::HfCascLf2Prongs const& candidates, + aod::Cascades const& cascades, + aod::V0s const& v0s, + aod::TracksWCovDca const& tracks, + TracksWCovIU const& lfTracks, + aod::BCsWithTimestamps const& bcsWithTimestamps) + { + runCreatorWithDCAFitter(collisions, candidates, cascades, v0s, tracks, lfTracks, bcsWithTimestamps, hInvMassCharmBaryonToOmegaPi, hCandidateCounterToOmegaPi); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Qa, processToOmegaPiWithDCAFitterNoCent, "Charm candidte reconstruction with Omega Pi via DcaFitter method, no centrality", false); + + void processToOmegaPiWithDCAFitterCentFT0C(soa::Join const& collisions, + aod::HfCascLf2Prongs const& candidates, + aod::Cascades const& cascades, + aod::V0s const& v0s, + aod::TracksWCovDca const& tracks, + TracksWCovIU const& lfTracks, + aod::BCsWithTimestamps const& bcsWithTimestamps) + { + runCreatorWithDCAFitter(collisions, candidates, cascades, v0s, tracks, lfTracks, bcsWithTimestamps, hInvMassCharmBaryonToOmegaPi, hCandidateCounterToOmegaPi); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Qa, processToOmegaPiWithDCAFitterCentFT0C, "Charm candidate reconstruction with Omega Pi via DcaFitter method, centrality selection on FT0C", false); + + void processToOmegaPiWithDCAFitterCentFT0M(soa::Join const& collisions, + aod::HfCascLf2Prongs const& candidates, + aod::Cascades const& cascades, + aod::V0s const& v0s, + aod::TracksWCovDca const& tracks, + TracksWCovIU const& lfTracks, + aod::BCsWithTimestamps const& bcsWithTimestamps) + { + runCreatorWithDCAFitter(collisions, candidates, cascades, v0s, tracks, lfTracks, bcsWithTimestamps, hInvMassCharmBaryonToOmegaPi, hInvMassCharmBaryonToOmegaPi); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Qa, processToOmegaPiWithDCAFitterCentFT0M, "Charm candidate reconstruction with Omega Pi via DcaFitter method, centrality selection on FT0M", false); + + /*~~~~~~~~~~~~~~~~~*/ + /*~~~To Omega Ka~~~*/ + /*~~~~~~~~~~~~~~~~~*/ + void processToOmegaKaWithDCAFitterNoCent(SelectedCollisions const& collisions, + aod::HfCascLf2Prongs const& candidates, + aod::Cascades const& cascades, + aod::V0s const& v0s, + aod::TracksWCovDca const& tracks, + TracksWCovIU const& lfTracks, + aod::BCsWithTimestamps const& bcsWithTimestamps) + { + runCreatorWithDCAFitter(collisions, candidates, cascades, v0s, tracks, lfTracks, bcsWithTimestamps, hInvMassCharmBaryonToOmegaKa, hCandidateCounterToOmegaKa); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Qa, processToOmegaKaWithDCAFitterNoCent, "Charm candidte reconstruction with Omega Ka via DcaFitter method, no centrality", false); + + void processToOmegaKaWithDCAFitterCentFT0C(soa::Join const& collisions, + aod::HfCascLf2Prongs const& candidates, + aod::Cascades const& cascades, + aod::V0s const& v0s, + aod::TracksWCovDca const& tracks, + TracksWCovIU const& lfTracks, + aod::BCsWithTimestamps const& bcsWithTimestamps) + { + runCreatorWithDCAFitter(collisions, candidates, cascades, v0s, tracks, lfTracks, bcsWithTimestamps, hInvMassCharmBaryonToOmegaKa, hCandidateCounterToOmegaKa); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Qa, processToOmegaKaWithDCAFitterCentFT0C, "Charm candidate reconstruction with Omega Ka via DcaFitter method, centrality selection on FT0C", false); + + void processToOmegaKaWithDCAFitterCentFT0M(soa::Join const& collisions, + aod::HfCascLf2Prongs const& candidates, + aod::Cascades const& cascades, + aod::V0s const& v0s, + aod::TracksWCovDca const& tracks, + TracksWCovIU const& lfTracks, + aod::BCsWithTimestamps const& bcsWithTimestamps) + { + runCreatorWithDCAFitter(collisions, candidates, cascades, v0s, tracks, lfTracks, bcsWithTimestamps, hInvMassCharmBaryonToOmegaKa, hCandidateCounterToOmegaPi); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Qa, processToOmegaKaWithDCAFitterCentFT0M, "Charm candidate reconstruction with Omega Ka via DcaFitter method, centrality selection on FT0M", false); + + ///////////////////////////////////////////////////// + /// /// + /// Process functions with KFParticle /// + /// /// + ///////////////////////////////////////////////////// + + /*~~~~~~~~~~~~~~*/ + /*~~~To Xi Pi~~~*/ + /*~~~~~~~~~~~~~~*/ + void processToXiPiWithKFParticleNoCent(SelectedCollisions const& collisions, + aod::HfCascLf2Prongs const& candidates, + aod::Cascades const& cascades, + aod::V0s const& v0s, + TracksWCovDcaExtraPidPrPiKa const& tracks, + TracksWCovExtraPidIU const& lfTracks, + aod::BCsWithTimestamps const& bcsWithTimestamps) + { + runCreatorWithKfParticle(collisions, candidates, cascades, v0s, tracks, lfTracks, bcsWithTimestamps, hInvMassCharmBaryonToXiPi, hCandidateCounterToXiPi); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Qa, processToXiPiWithKFParticleNoCent, "Charm Baryon decaying to Xi Pi reconstruction via KFParticle method, no centrality", false); + + void processToXiPiWithKFParticleCentFT0C(soa::Join const& collisions, + aod::HfCascLf2Prongs const& candidates, + aod::Cascades const& cascades, + aod::V0s const& v0s, + TracksWCovDcaExtraPidPrPiKa const& tracks, + TracksWCovExtraPidIU const& lfTracks, + aod::BCsWithTimestamps const& bcsWithTimestamps) + { + runCreatorWithKfParticle(collisions, candidates, cascades, v0s, tracks, lfTracks, bcsWithTimestamps, hInvMassCharmBaryonToXiPi, hCandidateCounterToXiPi); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Qa, processToXiPiWithKFParticleCentFT0C, "Charm Baryon decaying to Xi Pi reconstruction via KFParticle method, centrality on FT0C", false); + + void processToXiPiWithKFParticleCentFT0M(soa::Join const& collisions, + aod::HfCascLf2Prongs const& candidates, + aod::Cascades const& cascades, + aod::V0s const& v0s, + TracksWCovDcaExtraPidPrPiKa const& tracks, + TracksWCovExtraPidIU const& lfTracks, + aod::BCsWithTimestamps const& bcsWithTimestamps) + { + runCreatorWithKfParticle(collisions, candidates, cascades, v0s, tracks, lfTracks, bcsWithTimestamps, hInvMassCharmBaryonToXiPi, hCandidateCounterToXiPi); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Qa, processToXiPiWithKFParticleCentFT0M, "Charm Baryon decaying to Xi Pireconstruction via KFParticle method, centrality on FT0M", false); + + /*~~~~~~~~~~~~~~~~~*/ + /*~~~To Omega Pi~~~*/ + /*~~~~~~~~~~~~~~~~~*/ + void processToOmegaPiWithKFParticleNoCent(SelectedCollisions const& collisions, + aod::HfCascLf2Prongs const& candidates, + aod::Cascades const& cascades, + aod::V0s const& v0s, + TracksWCovDcaExtraPidPrPiKa const& tracks, + TracksWCovExtraPidIU const& lfTracks, + aod::BCsWithTimestamps const& bcsWithTimestamps) + { + runCreatorWithKfParticle(collisions, candidates, cascades, v0s, tracks, lfTracks, bcsWithTimestamps, hInvMassCharmBaryonToOmegaPi, hCandidateCounterToOmegaPi); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Qa, processToOmegaPiWithKFParticleNoCent, "Charm Baryon decaying to Omega Pi reconstruction via KFParticle method, no centrality", false); + + void processToOmegaPiWithKFParticleCentFT0C(soa::Join const& collisions, + aod::HfCascLf2Prongs const& candidates, + aod::Cascades const& cascades, + aod::V0s const& v0s, + TracksWCovDcaExtraPidPrPiKa const& tracks, + TracksWCovExtraPidIU const& lfTracks, + aod::BCsWithTimestamps const& bcsWithTimestamps) + { + runCreatorWithKfParticle(collisions, candidates, cascades, v0s, tracks, lfTracks, bcsWithTimestamps, hInvMassCharmBaryonToOmegaPi, hCandidateCounterToOmegaPi); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Qa, processToOmegaPiWithKFParticleCentFT0C, "Charm Baryon decaying to Omega Pi reconstruction via KFParticle method, centrality on FT0C", false); + + void processToOmegaPiWithKFParticleCentFT0M(soa::Join const& collisions, + aod::HfCascLf2Prongs const& candidates, + aod::Cascades const& cascades, + aod::V0s const& v0s, + TracksWCovDcaExtraPidPrPiKa const& tracks, + TracksWCovExtraPidIU const& lfTracks, + aod::BCsWithTimestamps const& bcsWithTimestamps) + { + runCreatorWithKfParticle(collisions, candidates, cascades, v0s, tracks, lfTracks, bcsWithTimestamps, hInvMassCharmBaryonToOmegaPi, hCandidateCounterToOmegaPi); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Qa, processToOmegaPiWithKFParticleCentFT0M, "Charm Baryong decaying to Omega Pi reconstruction via KFParticle method, centrality on FT0M", false); + + /*~~~~~~~~~~~~~~~~~*/ + /*~~~To Omega Ka~~~*/ + /*~~~~~~~~~~~~~~~~~*/ + void processToOmegaKaWithKFParticleNoCent(SelectedCollisions const& collisions, + aod::HfCascLf2Prongs const& candidates, + aod::Cascades const& cascades, + aod::V0s const& v0s, + TracksWCovDcaExtraPidPrPiKa const& tracks, + TracksWCovExtraPidIU const& lfTracks, + aod::BCsWithTimestamps const& bcsWithTimestamps) + { + runCreatorWithKfParticle(collisions, candidates, cascades, v0s, tracks, lfTracks, bcsWithTimestamps, hInvMassCharmBaryonToOmegaKa, hCandidateCounterToOmegaKa); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Qa, processToOmegaKaWithKFParticleNoCent, "Charm Baryon decaying to Omega Ka reconstruction via KFParticle method, no centrality", false); + + void processToOmegaKaWithKFParticleCentFT0C(soa::Join const& collisions, + aod::HfCascLf2Prongs const& candidates, + aod::Cascades const& cascades, + aod::V0s const& v0s, + TracksWCovDcaExtraPidPrPiKa const& tracks, + TracksWCovExtraPidIU const& lfTracks, + aod::BCsWithTimestamps const& bcsWithTimestamps) + { + runCreatorWithKfParticle(collisions, candidates, cascades, v0s, tracks, lfTracks, bcsWithTimestamps, hInvMassCharmBaryonToOmegaKa, hCandidateCounterToOmegaKa); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Qa, processToOmegaKaWithKFParticleCentFT0C, "Charm Baryon decaying to Omega Ka reconstruction via KFParticle method, centrality on FT0C", false); + + void processToOmegaKaWithKFParticleCentFT0M(soa::Join const& collisions, + aod::HfCascLf2Prongs const& candidates, + aod::Cascades const& cascades, + aod::V0s const& v0s, + TracksWCovDcaExtraPidPrPiKa const& tracks, + TracksWCovExtraPidIU const& lfTracks, + aod::BCsWithTimestamps const& bcsWithTimestamps) + { + runCreatorWithKfParticle(collisions, candidates, cascades, v0s, tracks, lfTracks, bcsWithTimestamps, hInvMassCharmBaryonToOmegaKa, hCandidateCounterToOmegaKa); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Qa, processToOmegaKaWithKFParticleCentFT0M, "Charm Baryong decaying to Omega Ka reconstruction via KFParticle method, centrality on FT0M", false); + + /////////////////////////////////////////////////////////////// + /// /// + /// Process functions for Collision monitoring /// + /// /// + /////////////////////////////////////////////////////////////// + + void processCollisionsNoCent(soa::Join const& collisions, + aod::BCsWithTimestamps const&) + { + for (const auto& collision : collisions) { + + // bitmask with event selection info + float centrality{-1.f}; + float occupancy = getOccupancyColl(collision, OccupancyEstimator::Its); + const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); + + // monitor the satisfied event selection + hfEvSel.fillHistograms(collision, rejectionMask, centrality, occupancy); + } + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Qa, processCollisionsNoCent, "Collision monitoring - No Centrality", true); + + void processCollisionsCentFT0C(soa::Join const& collisions, + aod::BCsWithTimestamps const&) + { + for (const auto& collision : collisions) { + + // bitmask with event selection info + float centrality{-1.f}; + float occupancy = getOccupancyColl(collision, OccupancyEstimator::Its); + const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); + + // monitor the satisfied event selection + hfEvSel.fillHistograms(collision, rejectionMask, centrality, occupancy); + } + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Qa, processCollisionsCentFT0C, "Collision monitoring - Centrality selection with FT0C", false); + + void processCollisionsCentFT0M(soa::Join const& collisions, + aod::BCsWithTimestamps const&) + { + for (const auto& collision : collisions) { + + // bitmask with event selection info + float centrality{-1.f}; + float occupancy = getOccupancyColl(collision, OccupancyEstimator::Its); + const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); + + // monitor the satisfied event selection + hfEvSel.fillHistograms(collision, rejectionMask, centrality, occupancy); + } + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Qa, processCollisionsCentFT0M, "Collision monitoring - Centrality selection with FT0M", false); +}; + +struct HfCandidateCreatorXic0Omegac0QaMc { + + // Cursor to fill tables + struct : ProducesGroup { + + Produces rowMcMatchRecXicToXiPi; + Produces rowMcMatchGenXicToXiPi; + Produces rowMcMatchRecOmegacToXiPi; + Produces rowMcMatchGenOmegacToXiPi; + Produces rowMcMatchRecToOmegaPi; + Produces rowMcMatchGenToOmegaPi; + Produces rowMcMatchRecToOmegaKa; + Produces rowMcMatchGenToOmegaKa; + + } cursors; + + // Configurables + struct : ConfigurableGroup { + + Configurable rejectBackground{"rejectBackground", false, "Reject particles from background events"}; // -> Used for only Xic0 + Configurable acceptTrackInteractionWithMaterial{"acceptTrackInteractionWithMaterial", false, "Accept candidates with final daughters interacting with materials"}; + Configurable fillMcHistograms{"fillMcHistograms", true, "Fill validation plots"}; + Configurable fillResidualTable{"fillResidualTable", true, "Fill table contaning residuals and pulls of PV and SV"}; + // Configurable matchDecayedPions{"matchedDecayedPions", true, "Match also candidates with daughter pion tracks that decay with kinked toploogy"}; + + } configs; + + enum McMatchFlag : uint8_t { + None = 0, + CharmBaryonUnmatched, + CascUnmatched, + V0Unmatched, + NumberMcMatchFlag + }; + + std::array pdgOfCharmBaryon{+kXiC0, +kOmegaC0, +kOmegaC0, +kOmegaC0}; + std::array pdgOfCascade{+kXiMinus, +kXiMinus, +kOmegaMinus, +kOmegaMinus}; + std::array pdgOfCharmBachelor{+kPiPlus, +kPiPlus, +kPiPlus, +kKPlus}; + std::array pdgOfBachelor{+kPiMinus, +kPiMinus, +kKMinus, +kKMinus}; + + // Table aliases + using TracksWMcIU = soa::Join; + using McCollisionsNoCents = soa::Join; + using McCollisionsFT0Cs = soa::Join; + using McCollisionsFT0Ms = soa::Join; + using McCollisionsCentFT0Ms = soa::Join; // -> Used for subscription for process functions of centrality with FT0Ms + using BCsInfo = soa::Join; + + Preslice mcParticlesPerMcCollision = aod::mcparticle::mcCollisionId; + PresliceUnsorted colPerMcCollision = aod::mccollisionlabel::mcCollisionId; // -> Why use unsorted?? + PresliceUnsorted colPerMcCollisionFT0C = aod::mccollisionlabel::mcCollisionId; + PresliceUnsorted colPerMcCollisionFT0M = aod::mccollisionlabel::mcCollisionId; + + HistogramRegistry registry{"registry"}; + HfEventSelectionMc hfEvSelMc; + + void init(InitContext& initContext) + { + const auto& workflows = initContext.services().get(); + for (const DeviceSpec& device : workflows.devices) { + if (device.name.compare("hf-candidate-creator-xic0-omegac0-qa") == 0) { + hfEvSelMc.init(device, registry); + break; + } + } + + // Add histograms for QA + if (configs.fillMcHistograms) { + registry.add("hGenCharmBaryonPtRapidityTight", "Generated charm baryon #it{p}_{T};#it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1D, {{20, 0.0, 20.0}}}); + registry.add("hGenCharmBaryonPtRapidityLoose", "Generated charm baryon #it{p}_{T};#it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1D, {{20, 0.0, 20.0}}}); + } + } + + // Helper function to fill in table for MC Rec + ///@brief decay Channel is the chosen reconstruction channel + ///@brief flag + ///@brief debug + ///@brief origin + ///@brief collisionMatched + ///@brief pt + ///@brief pdgcode + template + void fillRecoMcTableByDecayChannel(int8_t flag, int8_t debug, int8_t origin, bool collisionMatched, float pt, int pdgCode) + { + if constexpr (decayChannel == aod::hf_cand_xic0_omegac0::DecayType::XiczeroToXiPi) { + cursors.rowMcMatchRecXicToXiPi(flag, debug, origin, collisionMatched, pt, pdgCode); + } else if constexpr (decayChannel == aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToXiPi) { + cursors.rowMcMatchRecOmegacToXiPi(flag, debug, origin, collisionMatched, pt, pdgCode); + } else if constexpr (decayChannel == aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToOmegaPi) { + cursors.rowMcMatchRecToOmegaPi(flag, debug, origin, collisionMatched, pt, pdgCode); + } else { + cursors.rowMcMatchRecToOmegaKa(flag, debug, origin, collisionMatched, pt, pdgCode); + } + } + + // Helper function to fill in table for MC Gen + ///@brief decay Channel is the chosen reconstruction channel + ///@brief flag + ///@brief debug + ///@brief origin + ///@brief collisionMatched + ///@brief pt + ///@brief pdgcode + template + void fillGenMcTableByDecayChannel(int8_t flag, int8_t debugGenCharmBaryon, int8_t debugGenCascade, int8_t debugGenLambda, float ptCharmBaryon, float yCharmBaryon, int8_t origin, int idxMother) + { + if constexpr (decayChannel == aod::hf_cand_xic0_omegac0::DecayType::XiczeroToXiPi) { + cursors.rowMcMatchGenXicToXiPi(flag, debugGenCharmBaryon, debugGenCascade, debugGenLambda, ptCharmBaryon, yCharmBaryon, origin, idxMother); + } else if constexpr (decayChannel == aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToXiPi) { + cursors.rowMcMatchGenOmegacToXiPi(flag, debugGenCharmBaryon, debugGenCascade, debugGenLambda, ptCharmBaryon, yCharmBaryon, origin, idxMother); + } else if constexpr (decayChannel == aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToOmegaPi) { + cursors.rowMcMatchGenToOmegaPi(flag, debugGenCharmBaryon, debugGenCascade, debugGenLambda, ptCharmBaryon, yCharmBaryon, origin, idxMother); + } else { + cursors.rowMcMatchGenToOmegaKa(flag, debugGenCharmBaryon, debugGenCascade, debugGenLambda, ptCharmBaryon, yCharmBaryon, origin, idxMother); + } + } + + template + void runXic0Omegac0Mc(TRecoCand const& candidates, + TracksWMcIU const&, + aod::McParticles const& mcParticles, + Colls const& collsWithMcLabels, + McCollisions const& mcCollisions, + BCsInfo const&) + { + int indexRec{-1}; + int indexRecCharmBaryon{-1}; + int8_t sign{-9}; + int8_t signCasc{-9}; + int8_t signV0{-9}; + int8_t flag{0}; + int8_t origin{0}; + int8_t debug{0}; + int8_t debugGenCharmBaryon{0}; + int8_t debugGenCasc{0}; + int8_t debugGenV0{0}; + bool collisionMatched = false; + float ptCharmBaryonGen = -999.; + float yCharmBaryonGen = -999.; + + //////////////////////////////////// + // Match reconstructed candidates // + //////////////////////////////////// + + for (const auto& candidate : candidates) { + + flag = 0; + origin = RecoDecay::OriginType::None; + debug = McMatchFlag::None; + collisionMatched = false; + std::vector idxBhadMothers{}; + + auto arrayDaughters = std::array{candidate.template bachelorFromCharmBaryon_as(), + candidate.template bachelor_as(), + candidate.template posTrack_as(), + candidate.template negTrack_as()}; + auto arrayDaughtersCasc = std::array{candidate.template bachelor_as(), + candidate.template posTrack_as(), + candidate.template negTrack_as()}; + auto arrayDaughtersV0 = std::array{candidate.template posTrack_as(), + candidate.template negTrack_as()}; + + // Reject particles from background events + if (configs.rejectBackground) { + bool fromBkg{false}; + for (auto const& daughter : arrayDaughters) { + if (daughter.has_mcParticle()) { + auto mcParticle = daughter.mcParticle(); + if (mcParticle.fromBackgroundEvent()) { + fromBkg = true; + break; + } + } + } + if (fromBkg) { + // fill the tables + fillRecoMcTableByDecayChannel(flag, debug, origin, collisionMatched, -1.f, 0); + continue; + } + } + + // CharmBaryon -> Charm bachelor + Cascade + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, pdgOfCharmBaryon[decayChannel], std::array{pdgOfCharmBachelor[decayChannel], pdgOfBachelor[decayChannel], +kProton, +kPiMinus}, true, &sign, 3); + indexRecCharmBaryon = indexRec; + if (indexRec == -1) { // Xic0 not reconstructed + debug = McMatchFlag::CharmBaryonUnmatched; + } + if (indexRec > -1) { + // Cascade -> Bachelor + V0 + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughtersCasc, pdgOfCascade[decayChannel], std::array{pdgOfBachelor[decayChannel], +kProton, +kPiMinus}, true, &signCasc, 2); + if (indexRec == -1) { // Xi- not reconstructed + debug = McMatchFlag::CascUnmatched; + } + if (indexRec > -1) { + // V0 -> Pos + Neg + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughtersV0, +kLambda0, std::array{+kProton, +kPiMinus}, true, &signV0, 1); + if (indexRec == -1) { // V0 not reconstructed + debug = McMatchFlag::V0Unmatched; + } + if (indexRec > -1) { + flag = sign * (1 << decayChannel); + collisionMatched = candidate.template collision_as().mcCollisionId() == mcParticles.iteratorAt(indexRecCharmBaryon).mcCollisionId(); + } + } + } + + // Check if charm baryon is from b-hadron decay(prompt vs non-prompt) + if (flag != 0) { + auto particle = mcParticles.rawIteratorAt(indexRecCharmBaryon); + origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle, false, &idxBhadMothers); + } + if (origin == RecoDecay::OriginType::NonPrompt) { + auto bHadMother = mcParticles.rawIteratorAt(idxBhadMothers[0]); + fillRecoMcTableByDecayChannel(flag, debug, origin, collisionMatched, bHadMother.pt(), bHadMother.pdgCode()); + } else { + fillRecoMcTableByDecayChannel(flag, debug, origin, collisionMatched, -1.f, 0); + } + if (debug == McMatchFlag::CascUnmatched || debug == McMatchFlag::V0Unmatched) { + LOGF(info, "WARNING: Charm baryon decays in the expected final state but the condition on the intermediate states are not fullfilled"); + } + } // candidate loop + + /////////////////////////////// + // Match generated particles // + /////////////////////////////// + + for (const auto& mcCollision : mcCollisions) { + + const auto& mcParticlesPerMcColl = mcParticles.sliceBy(mcParticlesPerMcCollision, mcCollision.globalIndex()); + + float centrality{-1.f}; + o2::hf_evsel::HfCollisionRejectionMask rejectionMask{}; + int nSplitColl{0}; + + if constexpr (centEstimator == o2::hf_centrality::CentralityEstimator::None) { + const auto collSlice = collsWithMcLabels.sliceBy(colPerMcCollision, mcCollision.globalIndex()); + rejectionMask = hfEvSelMc.getHfMcCollisionRejectionMask(mcCollision, collSlice, centrality); + nSplitColl = collSlice.size(); + } else if constexpr (centEstimator == o2::hf_centrality::CentralityEstimator::FT0C) { + const auto collSlice = collsWithMcLabels.sliceBy(colPerMcCollisionFT0C, mcCollision.globalIndex()); + rejectionMask = hfEvSelMc.getHfMcCollisionRejectionMask(mcCollision, collSlice, centrality); + nSplitColl = collSlice.size(); + } else if constexpr (centEstimator == o2::hf_centrality::CentralityEstimator::FT0M) { + const auto collSlice = collsWithMcLabels.sliceBy(colPerMcCollisionFT0M, mcCollision.globalIndex()); + rejectionMask = hfEvSelMc.getHfMcCollisionRejectionMask(mcCollision, collSlice, centrality); + nSplitColl = collSlice.size(); + } + + hfEvSelMc.fillHistograms(mcCollision, rejectionMask, nSplitColl); + + if (rejectionMask != 0) { // At least one event selection not satisfied --> Reject all particles from this event + for (unsigned int i = 0; i < mcParticlesPerMcColl.size(); ++i) { + fillGenMcTableByDecayChannel(0, 0, 0, 0, -999., -999., RecoDecay::OriginType::None, -1); + } + continue; + } + + // Match generated particles + for (auto const& particle : mcParticlesPerMcColl) { + ptCharmBaryonGen = -999.; + yCharmBaryonGen = -999.; + flag = 0; + sign = -9; + debugGenCharmBaryon = 0; + debugGenCasc = 0; + debugGenV0 = 0; + origin = RecoDecay::OriginType::None; + std::vector idxBhadMothers{}; + const float kYCutTight = 0.5; + const float kYCutLoose = 0.8; + + // Reject particles from background events + if (particle.fromBackgroundEvent() && configs.rejectBackground) { + fillGenMcTableByDecayChannel(flag, debugGenCharmBaryon, debugGenCasc, debugGenV0, ptCharmBaryonGen, yCharmBaryonGen, origin, -1); + continue; + } + + // Charm Baryon -> Cascade + Charm bachelor + if (RecoDecay::isMatchedMCGen(mcParticles, particle, pdgOfCharmBaryon[decayChannel], std::array{pdgOfCascade[decayChannel], pdgOfCharmBachelor[decayChannel]}, true, &sign)) { + debugGenCharmBaryon = 1; + ptCharmBaryonGen = particle.pt(); + yCharmBaryonGen = particle.y(); + + for (auto const& daughterCharm : particle.template daughters_as()) { + if (std::abs(daughterCharm.pdgCode()) != pdgOfCascade[decayChannel]) { + continue; + } + // Xi -> Lambda + pi + if (RecoDecay::isMatchedMCGen(mcParticles, daughterCharm, pdgOfCascade[decayChannel], std::array{+kLambda0, pdgOfBachelor[decayChannel]}, true)) { + debugGenCasc = 1; // -> Matched Xi- + for (auto const& daughterCascade : daughterCharm.template daughters_as()) { + if (std::abs(daughterCascade.pdgCode()) != +kLambda0) { + continue; + } + + // Lambda -> p + pi + if (RecoDecay::isMatchedMCGen(mcParticles, daughterCascade, +kLambda0, std::array{+kProton, +kPiMinus}, true)) { + debugGenV0 = 1; // -> Matched Lambda0 + flag = sign * (1 << decayChannel); + } + } // V0 daughter loop + } // cascade daughter loop + } + } // charm daughter loop + + if (flag != 0) { + origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle, false, &idxBhadMothers); + if (std::abs(yCharmBaryonGen) < kYCutTight) { + registry.fill(HIST("hGenCharmBaryonPtRapidityTight"), ptCharmBaryonGen); + } + if (std::abs(yCharmBaryonGen) < kYCutLoose) { + registry.fill(HIST("hGenCharmBaryonPtRapidityLoose"), ptCharmBaryonGen); + } + } + + // Check if charm is prompt or non-prompt + if (origin == RecoDecay::OriginType::NonPrompt) { + fillGenMcTableByDecayChannel(flag, debugGenCharmBaryon, debugGenCasc, debugGenV0, ptCharmBaryonGen, yCharmBaryonGen, origin, idxBhadMothers[0]); + } else { + fillGenMcTableByDecayChannel(flag, debugGenCharmBaryon, debugGenCasc, debugGenV0, ptCharmBaryonGen, yCharmBaryonGen, origin, -1); + } + + } // particle loop + + } // end of collision loop + + } // template run function + + void processMcEmpty(aod::Collisions const&) + { + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0QaMc, processMcEmpty, "Empty process function to prevent workflow from getting stuck", true); + + ///////////////////////////////////////////////////// + /// /// + /// Process functions with DCAFitter /// + /// /// + ///////////////////////////////////////////////////// + + //~~~~~~~~~~~~~~~~// + //~~~~To Xi Pi~~~~// + //~~~~~~~~~~~~~~~~// + void processMcXicToXiPiWithDCAFitterNoCent(aod::HfCandToXiPi const& candidates, + TracksWMcIU const& tracks, + aod::McParticles const& mcParticles, + aod::McCollisions const& mcCollisions, + McCollisionsNoCents const& collsWithMcLabels, + BCsInfo const& bcs) + { + runXic0Omegac0Mc(candidates, tracks, mcParticles, collsWithMcLabels, mcCollisions, bcs); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0QaMc, processMcXicToXiPiWithDCAFitterNoCent, "Perform MC matching of DCAFitter reconstructed Xic0 to Xi Pi. No cents", false); + + void processMcXicToXiPiWithDCAFitterCentFT0C(aod::HfCandToXiPi const& candidates, + TracksWMcIU const& tracks, + aod::McParticles const& mcParticles, + aod::McCollisions const& mcCollisions, + McCollisionsFT0Cs const& collsWithMcLabels, + BCsInfo const& bcs) + { + runXic0Omegac0Mc(candidates, tracks, mcParticles, collsWithMcLabels, mcCollisions, bcs); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0QaMc, processMcXicToXiPiWithDCAFitterCentFT0C, "Perform MC matching of DCAFitter reconstructed Xic0 to Xi Pi. Cents with FT0C", false); + + void processMcXicToXiPiWithDCAFitterCentFT0M(aod::HfCandToXiPi const& candidates, + TracksWMcIU const& tracks, + aod::McParticles const& mcParticles, + McCollisionsCentFT0Ms const& mcCollisions, + McCollisionsFT0Ms const& collsWithMcLabels, + BCsInfo const& bcs) + { + runXic0Omegac0Mc(candidates, tracks, mcParticles, collsWithMcLabels, mcCollisions, bcs); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0QaMc, processMcXicToXiPiWithDCAFitterCentFT0M, "Perform MC matching of DCAFitter reconstructed Xic0 to Xi Pi. Cents with FT0M", false); + + void processMcOmegacToXiPiWithDCAFitterNoCent(aod::HfCandToXiPi const& candidates, + TracksWMcIU const& tracks, + aod::McParticles const& mcParticles, + aod::McCollisions const& mcCollisions, + McCollisionsNoCents const& collsWithMcLabels, + BCsInfo const& bcs) + { + runXic0Omegac0Mc(candidates, tracks, mcParticles, collsWithMcLabels, mcCollisions, bcs); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0QaMc, processMcOmegacToXiPiWithDCAFitterNoCent, "Perform MC matching of DCAFitter reconstructed Omegac0 to Xi Pi. No cents", false); + + void processMcOmegacToXiPiWithDCAFitterCentFT0C(aod::HfCandToXiPi const& candidates, + TracksWMcIU const& tracks, + aod::McParticles const& mcParticles, + aod::McCollisions const& mcCollisions, + McCollisionsFT0Cs const& collsWithMcLabels, + BCsInfo const& bcs) + { + runXic0Omegac0Mc(candidates, tracks, mcParticles, collsWithMcLabels, mcCollisions, bcs); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0QaMc, processMcOmegacToXiPiWithDCAFitterCentFT0C, "Perform MC matching of DCAFitter reconstructed Omeagc0 to Xi Pi. Cents with FT0C", false); + + void processMcOmegacToXiPiWithDCAFitterCentFT0M(aod::HfCandToXiPi const& candidates, + TracksWMcIU const& tracks, + aod::McParticles const& mcParticles, + McCollisionsCentFT0Ms const& mcCollisions, + McCollisionsFT0Ms const& collsWithMcLabels, + BCsInfo const& bcs) + { + runXic0Omegac0Mc(candidates, tracks, mcParticles, collsWithMcLabels, mcCollisions, bcs); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0QaMc, processMcOmegacToXiPiWithDCAFitterCentFT0M, "Perform MC matching of DCAFitter reconstructed Omegac0 to Xi Pi. Cents with FT0M", false); + + //~~~~~~~~~~~~~~~~~~~// + //~~~~To Omega Pi~~~~// + //~~~~~~~~~~~~~~~~~~~// + void processMcOmegacToOmegaPiWithDCAFitterNoCent(aod::HfCandToOmegaPi const& candidates, + TracksWMcIU const& tracks, + aod::McParticles const& mcParticles, + aod::McCollisions const& mcCollisions, + McCollisionsNoCents const& collsWithMcLabels, + BCsInfo const& bcs) + { + runXic0Omegac0Mc(candidates, tracks, mcParticles, collsWithMcLabels, mcCollisions, bcs); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0QaMc, processMcOmegacToOmegaPiWithDCAFitterNoCent, "Perform MC matching of DCAFitter reconstructed Omegac0 to Omega Pi. No cents", false); + + void processMcOmegacToOmegaPiWithDCAFitterCentFT0C(aod::HfCandToOmegaPi const& candidates, + TracksWMcIU const& tracks, + aod::McParticles const& mcParticles, + aod::McCollisions const& mcCollisions, + McCollisionsFT0Cs const& collsWithMcLabels, + BCsInfo const& bcs) + { + runXic0Omegac0Mc(candidates, tracks, mcParticles, collsWithMcLabels, mcCollisions, bcs); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0QaMc, processMcOmegacToOmegaPiWithDCAFitterCentFT0C, "Perform MC matching of DCAFitter reconstructed Omegac0 to Omega Pi. Cents with FT0C", false); + + void processMcOmegacToOmegaPiWithDCAFitterCentFT0M(aod::HfCandToOmegaPi const& candidates, + TracksWMcIU const& tracks, + aod::McParticles const& mcParticles, + McCollisionsCentFT0Ms const& mcCollisions, + McCollisionsFT0Ms const& collsWithMcLabels, + BCsInfo const& bcs) + { + runXic0Omegac0Mc(candidates, tracks, mcParticles, collsWithMcLabels, mcCollisions, bcs); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0QaMc, processMcOmegacToOmegaPiWithDCAFitterCentFT0M, "Perform MC matching of DCAFitter reconstructed Omegac0 to Omega Pi. Cents with FT0M", false); + + //~~~~~~~~~~~~~~~~~~// + //~~~~To Omega Ka~~~~// + //~~~~~~~~~~~~~~~~~~// + void processMcOmegacToOmegaKaWithDCAFitterNoCent(aod::HfCandToOmegaK const& candidates, + TracksWMcIU const& tracks, + aod::McParticles const& mcParticles, + aod::McCollisions const& mcCollisions, + McCollisionsNoCents const& collsWithMcLabels, + BCsInfo const& bcs) + { + runXic0Omegac0Mc(candidates, tracks, mcParticles, collsWithMcLabels, mcCollisions, bcs); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0QaMc, processMcOmegacToOmegaKaWithDCAFitterNoCent, "Perform MC matching of DCAFitter reconstructed Omegac0 to Omega Ka. No cents", false); + + void processMcOmegacToOmegaKaWithDCAFitterCentFT0C(aod::HfCandToOmegaK const& candidates, + TracksWMcIU const& tracks, + aod::McParticles const& mcParticles, + aod::McCollisions const& mcCollisions, + McCollisionsFT0Cs const& collsWithMcLabels, + BCsInfo const& bcs) + { + runXic0Omegac0Mc(candidates, tracks, mcParticles, collsWithMcLabels, mcCollisions, bcs); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0QaMc, processMcOmegacToOmegaKaWithDCAFitterCentFT0C, "Perform MC matching of DCAFitter reconstructed Omegac0 to Omega Ka. Cents with FT0C", false); + + void processMcOmegacToOmegaKaWithDCAFitterCentFT0M(aod::HfCandToOmegaK const& candidates, + TracksWMcIU const& tracks, + aod::McParticles const& mcParticles, + McCollisionsCentFT0Ms const& mcCollisions, + McCollisionsFT0Ms const& collsWithMcLabels, + BCsInfo const& bcs) + { + runXic0Omegac0Mc(candidates, tracks, mcParticles, collsWithMcLabels, mcCollisions, bcs); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0QaMc, processMcOmegacToOmegaKaWithDCAFitterCentFT0M, "Perform MC matching of DCAFitter reconstructed Omegac0 to Omega Ka. Cents with FT0M", false); + + ///////////////////////////////////////////////////// + /// /// + /// Process functions with KFParticle /// + /// /// + ///////////////////////////////////////////////////// + void processMcXicToXiPiWithKFParticleNoCent(aod::HfCandToXiPiKf const& candidates, + TracksWMcIU const& tracks, + aod::McParticles const& mcParticles, + aod::McCollisions const& mcCollisions, + McCollisionsNoCents const& collsWithMcLabels, + BCsInfo const& bcs) + { + runXic0Omegac0Mc(candidates, tracks, mcParticles, collsWithMcLabels, mcCollisions, bcs); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0QaMc, processMcXicToXiPiWithKFParticleNoCent, "Perform MC matching of KFParticle reconstructed Xic0 to Xi Pi. No cents", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/TableProducer/candidateSelectorToXiPiQa.cxx b/PWGHF/TableProducer/candidateSelectorToXiPiQa.cxx new file mode 100644 index 00000000000..55f5e2adae3 --- /dev/null +++ b/PWGHF/TableProducer/candidateSelectorToXiPiQa.cxx @@ -0,0 +1,770 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file candidateSelectorToXiPiQa.cxx +/// \brief Selection of Xic0 and Xicp candidates +/// +/// \author Jinhyun Park , Pusan National University +/// \author Krista Smith , Pusan National University + +#include "PWGHF/Core/HfMlResponseXic0ToXiPi.h" +#include "PWGHF/Core/HfMlResponseXic0ToXiPiKf.h" +#include "PWGHF/Core/SelectorCuts.h" +#include "PWGHF/DataModel/AliasTables.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/Utils/utilsAnalysis.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/Core/TrackSelectorPID.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::analysis; + +enum PidInfoStored { + PiFromLam = 0, + PrFromLam, + PiFromCasc, + PiFromCharm +}; + +enum { + doDcaFitter = 0, + doKfParticle +}; + +/// Struct for applying Omegac0/Xic0 selection cuts +struct HfCandidateSelectorToXiPiQa { + + // DCAFitter + Produces hfSelToXiPi; + // KFParticle + Produces hfSelToXiPiKf; + // ML selection - Filled with both DCAFitter and KFParticle + Produces hfMlToXiPi; + + // cuts from SelectorCuts.h - pT dependent cuts + Configurable> binsPt{"binsPt", std::vector{hf_cuts_xic_to_xi_pi::vecBinsPt}, "pT bin limits"}; + Configurable> cuts{"cuts", {hf_cuts_xic_to_xi_pi::Cuts[0], hf_cuts_xic_to_xi_pi::NBinsPt, hf_cuts_xic_to_xi_pi::NCutVars, hf_cuts_xic_to_xi_pi::labelsPt, hf_cuts_xic_to_xi_pi::labelsCutVar}, "Xic0 candidate selection per Pt Bin"}; + // ML inference + Configurable applyMl{"applyMl", false, "Flag to apply ML selections"}; + Configurable> binsPtMl{"binsPtMl", std::vector{hf_cuts_ml::vecBinsPt}, "pT bin limits for ML application"}; + Configurable> cutDirMl{"cutDirMl", std::vector{hf_cuts_ml::vecCutDir}, "Whether to reject score values greater or smaller than the threshold"}; + Configurable> cutsMl{"cutsMl", {hf_cuts_ml::Cuts[0], hf_cuts_ml::NBinsPt, hf_cuts_ml::NCutScores, hf_cuts_ml::labelsPt, hf_cuts_ml::labelsCutScore}, "ML selections per pT bin"}; + Configurable nClassesMl{"nClassesMl", static_cast(hf_cuts_ml::NCutScores), "Number of classes in ML model"}; + Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"feature1", "feature2"}, "Names of ML model input features"}; + // CCDB configuration + Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable> modelPathsCCDB{"modelPathsCCDB", std::vector{"EventFiltering/PWGHF/BDTXic0ToXipiKf"}, "Paths of models on CCDB"}; + Configurable> onnxFileNames{"onnxFileNames", std::vector{"ModelHandler_onnx_Xic0ToXipiKf.onnx"}, "ONNX file names for each pT bin (if not from CCDB full path)"}; + Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB"}; + Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; + // LF analysis selections + Configurable etaTrackCharmBachMax{"etaTrackCharmBachMax", 0.8, "Max absolute value of eta for charm baryon bachelor"}; + Configurable etaTrackLFDauMax{"etaTrackLFDauMax", 1.0, "Max absolute value of eta for V0 and cascade daughters"}; + Configurable ptPiFromCascMin{"ptPiFromCascMin", 0.15, "Min pT pi <--Casc"}; + Configurable radiusCascMin{"radiusCascMin", 0.6, "Min Cascade radius"}; + Configurable radiusV0Min{"radiusV0Min", 1.2, "Min V0 radius"}; + Configurable impactParXYPiFromCharmBaryonMin{"impactParXYPiFromCharmBaryonMin", 0., "Min dcaxy pi from charm baryon track to pV"}; + Configurable impactParXYPiFromCharmBaryonMax{"impactParXYPiFromCharmBaryonMax", 10., "Max dcaxy pi from charm baryon track to pV"}; + Configurable impactParXYCascMin{"impactParXYCascMin", 0., "Min dcaxy casc track to pV"}; + Configurable impactParXYCascMax{"impactParXYCascMax", 10., "Max dcaxy casc track to pV"}; + Configurable impactParZPiFromCharmBaryonMin{"impactParZPiFromCharmBaryonMin", 0., "Min dcaz pi from charm baryon track to pV"}; + Configurable impactParZPiFromCharmBaryonMax{"impactParZPiFromCharmBaryonMax", 10., "Max dcaz pi from charm baryon track to pV"}; + Configurable impactParZCascMin{"impactParZCascMin", 0., "Min dcaz casc track to pV"}; + Configurable impactParZCascMax{"impactParZCascMax", 10., "Max dcaz casc track to pV"}; + Configurable applyTrkSelLf{"applyTrkSelLf", true, "Apply track selection for LF daughters"}; + // Mass window + Configurable v0MassWindow{"v0MassWindow", 0.01, "v0 mass window"}; + Configurable cascMassWindow{"cascMassWindow", 0.01, "cascade mass window"}; + Configurable invMassCharmBaryonMin{"invMassCharmBaryonMin", 2.0, "Lower limit of invariant mass spectrum charm baryon"}; + Configurable invMassCharmBaryonMax{"invMassCharmBaryonMax", 3.1, "Lower limit of invariant mass spectrum charm baryon"}; + // PID options + Configurable usePidTpcOnly{"usePidTpcOnly", false, "Perform PID using only TPC"}; + Configurable usePidTpcTofCombined{"usePidTpcTofCombined", true, "Perform PID using TPC & TOF"}; + // PID - TPC selections + Configurable ptPiPidTpcMin{"ptPiPidTpcMin", -1, "Lower bound of track pT for TPC PID for pion selection"}; + Configurable ptPiPidTpcMax{"ptPiPidTpcMax", 9999.9, "Upper bound of track pT for TPC PID for pion selection"}; + Configurable nSigmaTpcPiMax{"nSigmaTpcPiMax", 3., "Nsigma cut on TPC only for pion selection"}; + Configurable nSigmaTpcCombinedPiMax{"nSigmaTpcCombinedPiMax", 0., "Nsigma cut on TPC combined with TOF for pion selection"}; + Configurable ptPrPidTpcMin{"ptPrPidTpcMin", -1, "Lower bound of track pT for TPC PID for proton selection"}; + Configurable ptPrPidTpcMax{"ptPrPidTpcMax", 9999.9, "Upper bound of track pT for TPC PID for proton selection"}; + Configurable nSigmaTpcPrMax{"nSigmaTpcPrMax", 3., "Nsigma cut on TPC only for proton selection"}; + Configurable nSigmaTpcCombinedPrMax{"nSigmaTpcCombinedPrMax", 0., "Nsigma cut on TPC combined with TOF for proton selection"}; + // PID - TOF selections + Configurable ptPiPidTofMin{"ptPiPidTofMin", -1, "Lower bound of track pT for TOF PID for pion selection"}; + Configurable ptPiPidTofMax{"ptPiPidTofMax", 9999.9, "Upper bound of track pT for TOF PID for pion selection"}; + Configurable nSigmaTofPiMax{"nSigmaTofPiMax", 3., "Nsigma cut on TOF only for pion selection"}; + Configurable nSigmaTofCombinedPiMax{"nSigmaTofCombinedPiMax", 0., "Nsigma cut on TOF combined with TPC for pion selection"}; + Configurable ptPrPidTofMin{"ptPrPidTofMin", -1, "Lower bound of track pT for TOF PID for proton selection"}; + Configurable ptPrPidTofMax{"ptPrPidTofMax", 9999.9, "Upper bound of track pT for TOF PID for proton selection"}; + Configurable nSigmaTofPrMax{"nSigmaTofPrMax", 3., "Nsigma cut on TOF only for proton selection"}; + Configurable nSigmaTofCombinedPrMax{"nSigmaTofCombinedPrMax", 0., "Nsigma cut on TOF combined with TPC for proton selection"}; + // detector track quality selections + Configurable nClustersTpcMin{"nClustersTpcMin", 70, "Minimum number of TPC clusters requirement"}; + Configurable nTpcCrossedRowsMin{"nTpcCrossedRowsMin", 70, "Minimum number of TPC crossed rows requirement"}; + Configurable tpcCrossedRowsOverFindableClustersRatioMin{"tpcCrossedRowsOverFindableClustersRatioMin", 0.8, "Minimum ratio TPC crossed rows over findable clusters requirement"}; + Configurable tpcChi2PerClusterMax{"tpcChi2PerClusterMax", 4, "Maximum value of chi2 fit over TPC clusters"}; + Configurable nClustersItsMin{"nClustersItsMin", 3, "Minimum number of ITS clusters requirement for pi <- charm baryon"}; + Configurable nClustersItsInnBarrMin{"nClustersItsInnBarrMin", 1, "Minimum number of ITS clusters in inner barrel requirement for pi <- charm baryon"}; + Configurable itsChi2PerClusterMax{"itsChi2PerClusterMax", 36, "Maximum value of chi2 fit over ITS clusters for pi <- charm baryon"}; + + o2::analysis::HfMlResponseXic0ToXiPi hfMlResponseDca; + o2::analysis::HfMlResponseXic0ToXiPiKf hfMlResponseKf; + std::vector outputMlXic0ToXiPi = {}; + o2::ccdb::CcdbApi ccdbApi; + + TrackSelectorPi selectorPion; + TrackSelectorPr selectorProton; + + using TracksSel = soa::Join; + using TracksSelLf = soa::Join; + + HistogramRegistry registry{"registry"}; // for QA of selections + + void init(InitContext const&) + { + selectorPion.setRangePtTpc(ptPiPidTpcMin, ptPiPidTpcMax); + selectorPion.setRangeNSigmaTpc(-nSigmaTpcPiMax, nSigmaTpcPiMax); + selectorPion.setRangeNSigmaTpcCondTof(-nSigmaTpcCombinedPiMax, nSigmaTpcCombinedPiMax); + selectorPion.setRangePtTof(ptPiPidTofMin, ptPiPidTofMax); + selectorPion.setRangeNSigmaTof(-nSigmaTofPiMax, nSigmaTofPiMax); + selectorPion.setRangeNSigmaTofCondTpc(-nSigmaTofCombinedPiMax, nSigmaTofCombinedPiMax); + + selectorProton.setRangePtTpc(ptPrPidTpcMin, ptPrPidTpcMax); + selectorProton.setRangeNSigmaTpc(-nSigmaTpcPrMax, nSigmaTpcPrMax); + selectorProton.setRangeNSigmaTpcCondTof(-nSigmaTpcCombinedPrMax, nSigmaTpcCombinedPrMax); + selectorProton.setRangePtTof(ptPrPidTofMin, ptPrPidTofMax); + selectorProton.setRangeNSigmaTof(-nSigmaTofPrMax, nSigmaTofPrMax); + selectorProton.setRangeNSigmaTofCondTpc(-nSigmaTofCombinedPrMax, nSigmaTofCombinedPrMax); + + const AxisSpec axisSel{2, -0.5, 1.5, "status"}; + const AxisSpec axisSelOnLfDca{14, -0.5, 13.5, "status"}; + const AxisSpec axisSelOnLfKf{23, -0.5, 22.5, "status"}; + const AxisSpec axisSelOnHfDca{6, -0.5, 5.5, "status"}; + const AxisSpec axisSelOnHfKf{12, -0.5, 11.5, "status"}; + + registry.add("hSelSignDec", "hSelSignDec;status;entries", {HistType::kTH1F, {axisSel}}); + registry.add("hSelStatusCluster", "hSelStatusCluster:# of events Passed;;", {HistType::kTH1F, {{6, -0.5, 5.5}}}); + registry.get(HIST("hSelStatusCluster"))->GetXaxis()->SetBinLabel(1, "All"); + registry.get(HIST("hSelStatusCluster"))->GetXaxis()->SetBinLabel(2, "TpcCluster PiFromV0"); + registry.get(HIST("hSelStatusCluster"))->GetXaxis()->SetBinLabel(3, "TpcCluster PrFromV0"); + registry.get(HIST("hSelStatusCluster"))->GetXaxis()->SetBinLabel(4, "TpcCluster PiFromCasc"); + registry.get(HIST("hSelStatusCluster"))->GetXaxis()->SetBinLabel(5, "TpcCluster PiFromCharm"); + registry.get(HIST("hSelStatusCluster"))->GetXaxis()->SetBinLabel(6, "ItsCluster PiFromCharm"); + + registry.add("hSelStatusPID", "hSelStatusPID;# of events Passed;;", {HistType::kTH1F, {{4, -0.5, 3.5}}}); + registry.get(HIST("hSelStatusPID"))->GetXaxis()->SetBinLabel(1, "All"); + registry.get(HIST("hSelStatusPID"))->GetXaxis()->SetBinLabel(2, "Lambda"); + registry.get(HIST("hSelStatusPID"))->GetXaxis()->SetBinLabel(3, "Cascade"); + registry.get(HIST("hSelStatusPID"))->GetXaxis()->SetBinLabel(4, "CharmBaryon"); + + // For QA of LF & HF selection + if (doprocessSelectionDCAFitter) { + registry.add("hSelStatusLf", "hSelStatusLf;# of candidate passed;", {HistType::kTH1F, {axisSelOnLfDca}}); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(1, "All"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(2, "etaV0Dau"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(3, "radiusV0"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(4, "radiusCasc"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(5, "cosPAV0"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(6, "cosPACasc"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(7, "dcaV0Dau"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(8, "dcaCascDau"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(9, "dcaXYToPvV0Dau0"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(10, "dcaXYToPvV0Dau1"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(11, "dcaXYToPvCascDau"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(12, "ptPiFromCasc"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(13, "impactParCascXY"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(14, "impactParCascZ"); + + registry.add("hSelStatusHf", "hSelStatusHf;# of candidate passed;", {HistType::kTH1F, {axisSelOnHfDca}}); + registry.get(HIST("hSelStatusHf"))->GetXaxis()->SetBinLabel(1, "All"); + registry.get(HIST("hSelStatusHf"))->GetXaxis()->SetBinLabel(2, "etaTrackCharmBach"); + registry.get(HIST("hSelStatusHf"))->GetXaxis()->SetBinLabel(3, "dcaCharmBaryonDau"); + registry.get(HIST("hSelStatusHf"))->GetXaxis()->SetBinLabel(4, "ptPiFromCharmBaryon"); + registry.get(HIST("hSelStatusHf"))->GetXaxis()->SetBinLabel(5, "impactParBachFromCharmXY"); + registry.get(HIST("hSelStatusHf"))->GetXaxis()->SetBinLabel(6, "impactParBachFromCharmZ"); + } + + if (doprocessSelectionKFParticle) { + registry.add("hSelStatusLf", "hSelStatusLf;# of candidate passed;", {HistType::kTH1F, {axisSelOnLfKf}}); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(1, "All"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(2, "etaV0Dau"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(3, "radiusV0"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(4, "radiusCasc"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(5, "cosPAV0"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(6, "cosPACasc"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(7, "dcaV0Dau"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(8, "dcaCascDau"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(9, "dcaXYToPvV0Dau0"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(10, "dcaXYToPvV0Dau1"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(11, "dcaXYToPvCascDau"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(12, "ptPiFromCasc"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(13, "cosPAV0ToCasc"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(14, "kfDcaXYCascToPv"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(15, "chi2GeoV0"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(16, "chi2GeoCasc"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(17, "chi2TopoV0ToPv"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(18, "chi2TopoCascToPv"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(19, "chi2TopoV0ToCasc"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(20, "v0ldl"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(21, "cascldl"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(22, "decayLenXYLambda"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(23, "decayLenXYCasc"); + + registry.add("hSelStatusHf", "hSelStatusHf;# of candidate passed;", {HistType::kTH1F, {axisSelOnHfKf}}); + registry.get(HIST("hSelStatusHf"))->GetXaxis()->SetBinLabel(1, "All"); + registry.get(HIST("hSelStatusHf"))->GetXaxis()->SetBinLabel(2, "etaTrackCharmBach"); + registry.get(HIST("hSelStatusHf"))->GetXaxis()->SetBinLabel(3, "dcaCharmBaryonDau"); + registry.get(HIST("hSelStatusHf"))->GetXaxis()->SetBinLabel(4, "ptPiFromCharmBaryon"); + registry.get(HIST("hSelStatusHf"))->GetXaxis()->SetBinLabel(5, "cosPaCascToXic"); + registry.get(HIST("hSelStatusHf"))->GetXaxis()->SetBinLabel(6, "kfDcaXYPiFromXic"); + registry.get(HIST("hSelStatusHf"))->GetXaxis()->SetBinLabel(7, "chi2GeoXic"); + registry.get(HIST("hSelStatusHf"))->GetXaxis()->SetBinLabel(8, "chi2TopoXicToPv"); + registry.get(HIST("hSelStatusHf"))->GetXaxis()->SetBinLabel(9, "chi2TopoPiFromXicToPv"); + registry.get(HIST("hSelStatusHf"))->GetXaxis()->SetBinLabel(10, "chi2TopoCascToXic"); + registry.get(HIST("hSelStatusHf"))->GetXaxis()->SetBinLabel(11, "decayLenXYXic"); + registry.get(HIST("hSelStatusHf"))->GetXaxis()->SetBinLabel(12, "cTauXic"); + } + + // invarinat mass histograms + registry.add("hInvMassCharmBaryonWoPidInvMassCut", "Charm baryon invariant mass; int mass; entries", {HistType::kTH1F, {{1500, 1.5, 4.5}}}); + registry.add("hInvMassCharmBaryon", "Charm baryon invariant mass; int mass; entries", {HistType::kTH1F, {{1500, 1.5, 4.5}}}); + registry.add("hInvMassCharmBaryonBkg", "Charm baryon invariant mass, rejected; int mass; entries", {HistType::kTH1F, {{1500, 1.5, 4.5}}}); + + // HfMlResponse initialization + if (applyMl) { + if (doprocessSelectionDCAFitter) { + hfMlResponseDca.configure(binsPtMl, cutsMl, cutDirMl, nClassesMl); + if (loadModelsFromCCDB) { + ccdbApi.init(ccdbUrl); + hfMlResponseDca.setModelPathsCCDB(onnxFileNames, ccdbApi, modelPathsCCDB, timestampCCDB); + } else { + hfMlResponseDca.setModelPathsLocal(onnxFileNames); + } + hfMlResponseDca.cacheInputFeaturesIndices(namesInputFeatures); + hfMlResponseDca.init(); + } else { + hfMlResponseKf.configure(binsPtMl, cutsMl, cutDirMl, nClassesMl); + if (loadModelsFromCCDB) { + ccdbApi.init(ccdbUrl); + hfMlResponseKf.setModelPathsCCDB(onnxFileNames, ccdbApi, modelPathsCCDB, timestampCCDB); + } else { + hfMlResponseKf.setModelPathsLocal(onnxFileNames); + } + hfMlResponseKf.cacheInputFeaturesIndices(namesInputFeatures); + hfMlResponseKf.init(); + } + } + } + + // LF cuts - Cuts on LF tracks reco + // Selection on LF related informations + // returns true if all cuts are passed + template + bool SelectOnLF(const T& candidate, const int& inputPtBin) + { + + registry.fill(HIST("hSelStatusLf"), 0.0); + + // Eta selection of V0, Cascade daughters + double etaV0PosDau = candidate.etaV0PosDau(); + double etaV0NegDau = candidate.etaV0NegDau(); + double etaPiFromCasc = candidate.etaBachFromCasc(); + + if (std::abs(etaV0PosDau) > etaTrackLFDauMax || std::abs(etaV0NegDau) > etaTrackLFDauMax || std::abs(etaPiFromCasc) > etaTrackLFDauMax) { + return false; + } + registry.fill(HIST("hSelStatusLf"), 1.0); + + // Minimum radius cut + double radiusV0 = RecoDecay::sqrtSumOfSquares(candidate.xDecayVtxV0(), candidate.yDecayVtxV0()); + double radiusCasc = RecoDecay::sqrtSumOfSquares(candidate.xDecayVtxCascade(), candidate.yDecayVtxCascade()); + + if (radiusV0 < radiusV0Min) { + return false; + } + registry.fill(HIST("hSelStatusLf"), 2.0); + if (radiusCasc < radiusCascMin) { + return false; + } + registry.fill(HIST("hSelStatusLf"), 3.0); + + // Cosine of pointing angle + if (candidate.cosPAV0() < cuts->get(inputPtBin, "cosPAV0")) { + return false; + } + registry.fill(HIST("hSelStatusLf"), 4.0); + if (candidate.cosPACasc() < cuts->get(inputPtBin, "cosPACasc")) { + return false; + } + registry.fill(HIST("hSelStatusLf"), 5.0); + + // Distance of Closest Approach(DCA) + if (candidate.dcaV0Dau() > cuts->get(inputPtBin, "dcaV0Dau")) { + return false; + } + registry.fill(HIST("hSelStatusLf"), 6.0); + + if (candidate.dcaCascDau() > cuts->get(inputPtBin, "dcaCascDau")) { + return false; + } + registry.fill(HIST("hSelStatusLf"), 7.0); + + if (std::abs(candidate.dcaXYToPvV0Dau0()) < cuts->get(inputPtBin, "dcaXYToPvV0Dau0")) { + return false; + } + registry.fill(HIST("hSelStatusLf"), 8.0); + + if (std::abs(candidate.dcaXYToPvV0Dau1()) < cuts->get(inputPtBin, "dcaXYToPvV0Dau1")) { + return false; + } + registry.fill(HIST("hSelStatusLf"), 9.0); + + if (std::abs(candidate.dcaXYToPvCascDau()) < cuts->get(inputPtBin, "dcaXYToPvCascDau")) { + return false; + } + registry.fill(HIST("hSelStatusLf"), 10.0); + + // pT: Bachelor + double ptPiFromCasc = RecoDecay::sqrtSumOfSquares(candidate.pxBachFromCasc(), candidate.pyBachFromCasc()); + if (std::abs(ptPiFromCasc) < ptPiFromCascMin) { + return false; + } + registry.fill(HIST("hSelStatusLf"), 11.0); + + // Extra cuts for KFParticle + if constexpr (svReco == doKfParticle) { + // Cosine of Pointing angle + if (candidate.cosPaV0ToCasc() < cuts->get(inputPtBin, "cosPaV0ToCasc")) { + return false; + } + registry.fill(HIST("hSelStatusLf"), 12.0); + + // DCA + if (std::abs(candidate.kfDcaXYCascToPv()) > cuts->get(inputPtBin, "kfDcaXYCascToPv")) { + return false; + } + registry.fill(HIST("hSelStatusLf"), 13.0); + + // Chi2 + if (candidate.chi2GeoV0() < 0 || candidate.chi2GeoV0() > cuts->get(inputPtBin, "chi2GeoV0")) { + return false; + } + registry.fill(HIST("hSelStatusLf"), 14.0); + if (candidate.chi2GeoCasc() < 0 || candidate.chi2GeoCasc() > cuts->get(inputPtBin, "chi2GeoCasc")) { + return false; + } + registry.fill(HIST("hSelStatusLf"), 15.0); + if (candidate.chi2TopoV0ToPv() > 0 && candidate.chi2TopoV0ToPv() < cuts->get(inputPtBin, "chi2TopoV0ToPv")) { + return false; + } + registry.fill(HIST("hSelStatusLf"), 16.0); + if (candidate.chi2TopoCascToPv() < 0 || candidate.chi2TopoCascToPv() > cuts->get(inputPtBin, "chi2TopoCascToPv")) { + return false; + } + registry.fill(HIST("hSelStatusLf"), 17.0); + if (candidate.chi2TopoV0ToCasc() < 0 || candidate.chi2TopoV0ToCasc() > cuts->get(inputPtBin, "chi2TopoV0ToCasc")) { + return false; + } + registry.fill(HIST("hSelStatusLf"), 18.0); + + // ldl + if (candidate.v0ldl() < cuts->get(inputPtBin, "v0ldl")) { + return false; + } + registry.fill(HIST("hSelStatusLf"), 19.0); + if (candidate.cascldl() < cuts->get(inputPtBin, "cascldl")) { + return false; + } + registry.fill(HIST("hSelStatusLf"), 20.0); + + // Decay length + if (std::abs(candidate.decayLenXYLambda()) < cuts->get(inputPtBin, "decayLenXYLambda")) { + return false; + } + registry.fill(HIST("hSelStatusLf"), 21.0); + if (std::abs(candidate.decayLenXYCasc()) < cuts->get(inputPtBin, "decayLenXYCasc")) { + return false; + } + registry.fill(HIST("hSelStatusLf"), 22.0); + + } else { + // Impact parameter(DCA?) + if (std::abs(candidate.impactParCascXY()) < impactParXYCascMin || std::abs(candidate.impactParCascXY()) > impactParXYCascMax) { + return false; + } + registry.fill(HIST("hSelStatusLf"), 12.0); + if (std::abs(candidate.impactParCascZ()) < impactParZCascMin || std::abs(candidate.impactParCascZ()) > impactParZCascMax) { + return false; + } + registry.fill(HIST("hSelStatusLf"), 13.0); + } + + // If passes all cuts, return true + return true; + } + + // HF cuts - Cuts on Charm baryon reco + // Apply cuts with charm baryon & charm bachelor related informations + // returns true if all cuts are passed + template + bool SelectOnHF(const T& candidate, const int& inputPtBin) + { + + registry.fill(HIST("hSelStatusHf"), 0.0); + + // eta selection on charm bayron bachelor + if (std::abs(candidate.etaBachFromCharmBaryon()) > etaTrackCharmBachMax) { + return false; + } + registry.fill(HIST("hSelStatusHf"), 1.0); + // Distance of Closest Approach(DCA) + if (candidate.dcaCharmBaryonDau() > cuts->get(inputPtBin, "dcaCharmBaryonDau")) { + return false; + } + registry.fill(HIST("hSelStatusHf"), 2.0); + + // pT: Charm Bachelor + double ptPiFromCharmBaryon = RecoDecay::sqrtSumOfSquares(candidate.pxBachFromCharmBaryon(), candidate.pyBachFromCharmBaryon()); + if (ptPiFromCharmBaryon < cuts->get(inputPtBin, "ptPiFromCharmBaryon")) { + return false; + } + registry.fill(HIST("hSelStatusHf"), 3.0); + + // specific selections with KFParticle output + if constexpr (svReco == doKfParticle) { + // Cosine of pointing angle + if (candidate.cosPaCascToXic() < cuts->get(inputPtBin, "cosPaCascToXic")) { + return false; + } + registry.fill(HIST("hSelStatusHf"), 4.0); + + // DCA + if (std::abs(candidate.kfDcaXYPiFromXic()) > cuts->get(inputPtBin, "kfDcaXYPiFromXic")) { + return false; + } + registry.fill(HIST("hSelStatusHf"), 5.0); + + // Chi2 + if (candidate.chi2GeoXic() < 0 || candidate.chi2GeoXic() > cuts->get(inputPtBin, "chi2GeoXic")) { + return false; + } + registry.fill(HIST("hSelStatusHf"), 6.0); + if (candidate.chi2TopoXicToPv() < 0 || candidate.chi2TopoXicToPv() > cuts->get(inputPtBin, "chi2TopoXicToPv")) { + return false; + } + registry.fill(HIST("hSelStatusHf"), 7.0); + if (candidate.chi2TopoPiFromXicToPv() < 0 || candidate.chi2TopoPiFromXicToPv() > cuts->get(inputPtBin, "chi2TopoPiFromXicToPv")) { + return false; + } + registry.fill(HIST("hSelStatusHf"), 8.0); + if (candidate.chi2TopoCascToXic() < 0 || candidate.chi2TopoCascToXic() > cuts->get(inputPtBin, "chi2TopoCascToXic")) { + return false; + } + registry.fill(HIST("hSelStatusHf"), 9.0); + + // Decay Length + if (std::abs(candidate.decayLenXYXic()) > cuts->get(inputPtBin, "decayLenXYXic")) { + return false; + } + registry.fill(HIST("hSelStatusHf"), 10.0); + + // ctau + if (std::abs(candidate.cTauXic()) > cuts->get(inputPtBin, "cTauXic")) { + return false; + } + registry.fill(HIST("hSelStatusHf"), 11.0); + } else { + // Impact parameter(DCA?) + if ((std::abs(candidate.impactParBachFromCharmBaryonXY()) < impactParXYPiFromCharmBaryonMin) || (std::abs(candidate.impactParBachFromCharmBaryonXY()) > impactParXYPiFromCharmBaryonMax)) { + return false; + } + registry.fill(HIST("hSelStatusHf"), 4.0); + if ((std::abs(candidate.impactParBachFromCharmBaryonZ()) < impactParZPiFromCharmBaryonMin) || (std::abs(candidate.impactParBachFromCharmBaryonZ()) > impactParZPiFromCharmBaryonMax)) { + return false; + } + registry.fill(HIST("hSelStatusHf"), 5.0); + } + + // If passes all cuts, return true + return true; + } + + template + void runSelection(TCandTable const& candidates, + TracksSel const& tracks, + TracksSelLf const& lfTracks) + { + // looping over charm baryon candidates + for (const auto& candidate : candidates) { + + bool resultSelections = true; // True if the candidate passes all the selections, False otherwise + outputMlXic0ToXiPi.clear(); + + auto trackV0PosDau = lfTracks.rawIteratorAt(candidate.posTrackId()); + auto trackV0NegDau = lfTracks.rawIteratorAt(candidate.negTrackId()); + auto trackPiFromCasc = lfTracks.rawIteratorAt(candidate.bachelorId()); + auto trackPiFromCharm = tracks.rawIteratorAt(candidate.bachelorFromCharmBaryonId()); + + auto trackPiFromLam = trackV0NegDau; + auto trackPrFromLam = trackV0PosDau; + + int8_t signDecay = candidate.signDecay(); // sign of pi <- cascade + + if (signDecay > 0) { + trackPiFromLam = trackV0PosDau; + trackPrFromLam = trackV0NegDau; + registry.fill(HIST("hSelSignDec"), 1); // anti-particle decay + } else { + registry.fill(HIST("hSelSignDec"), 0); // particle decay + } + + // pT selection + auto ptCandXic0 = RecoDecay::pt(candidate.pxCharmBaryon(), candidate.pyCharmBaryon()); + int pTBin = findBin(binsPt, ptCandXic0); + if (pTBin == -1) { + resultSelections = false; + } + + // Topological selection + const bool selectionResOnLF = SelectOnLF(candidate, pTBin); + const bool selectionResOnHF = SelectOnHF(candidate, pTBin); + if (!selectionResOnLF || !selectionResOnHF) { + resultSelections = false; + } + + // TPC clusters selections + if (resultSelections) { + registry.fill(HIST("hSelStatusCluster"), 0.0); + } + if (applyTrkSelLf) { + if (!isSelectedTrackTpcQuality(trackPiFromLam, nClustersTpcMin, nTpcCrossedRowsMin, tpcCrossedRowsOverFindableClustersRatioMin, tpcChi2PerClusterMax)) { + resultSelections = false; + } else { + if (resultSelections) { + registry.fill(HIST("hSelStatusCluster"), 1.0); + } + } + + if (!isSelectedTrackTpcQuality(trackPrFromLam, nClustersTpcMin, nTpcCrossedRowsMin, tpcCrossedRowsOverFindableClustersRatioMin, tpcChi2PerClusterMax)) { + resultSelections = false; + } else { + if (resultSelections) { + registry.fill(HIST("hSelStatusCluster"), 2.0); + } + } + + if (!isSelectedTrackTpcQuality(trackPiFromCasc, nClustersTpcMin, nTpcCrossedRowsMin, tpcCrossedRowsOverFindableClustersRatioMin, tpcChi2PerClusterMax)) { + resultSelections = false; + } else { + if (resultSelections) { + registry.fill(HIST("hSelStatusCluster"), 3.0); + } + } + } + + if (!isSelectedTrackTpcQuality(trackPiFromCharm, nClustersTpcMin, nTpcCrossedRowsMin, tpcCrossedRowsOverFindableClustersRatioMin, tpcChi2PerClusterMax)) { + resultSelections = false; + } else { + if (resultSelections) { + registry.fill(HIST("hSelStatusCluster"), 4.0); + } + } + + // ITS clusters selection + if (!isSelectedTrackItsQuality(trackPiFromCharm, nClustersItsMin, itsChi2PerClusterMax) || trackPiFromCharm.itsNClsInnerBarrel() < nClustersItsInnBarrMin) { + resultSelections = false; + } else { + if (resultSelections) { + registry.fill(HIST("hSelStatusCluster"), 5.0); + } + } + + // Track level PID selection + if (resultSelections) { + registry.fill(HIST("hSelStatusPID"), 0.0); + } + int statusPidPrFromLam = -999; + int statusPidPiFromLam = -999; + int statusPidPiFromCasc = -999; + int statusPidPiFromCharmBaryon = -999; + + int infoTpcStored = 0; + int infoTofStored = 0; + + if (usePidTpcOnly == usePidTpcTofCombined) { + LOGF(fatal, "Check the PID configurables, usePidTpcOnly and usePidTpcTofCombined can't have the same value"); + } + + if (trackPiFromLam.hasTPC()) { + SETBIT(infoTpcStored, PiFromLam); + } + if (trackPrFromLam.hasTPC()) { + SETBIT(infoTpcStored, PrFromLam); + } + if (trackPiFromCasc.hasTPC()) { + SETBIT(infoTpcStored, PiFromCasc); + } + if (trackPiFromCharm.hasTPC()) { + SETBIT(infoTpcStored, PiFromCharm); + } + if (trackPiFromLam.hasTOF()) { + SETBIT(infoTofStored, PiFromLam); + } + if (trackPrFromLam.hasTOF()) { + SETBIT(infoTofStored, PrFromLam); + } + if (trackPiFromCasc.hasTOF()) { + SETBIT(infoTofStored, PiFromCasc); + } + if (trackPiFromCharm.hasTOF()) { + SETBIT(infoTofStored, PiFromCharm); + } + + if (usePidTpcOnly) { + statusPidPrFromLam = selectorProton.statusTpc(trackPrFromLam); + statusPidPiFromLam = selectorPion.statusTpc(trackPiFromLam); + statusPidPiFromCasc = selectorPion.statusTpc(trackPiFromCasc); + statusPidPiFromCharmBaryon = selectorPion.statusTpc(trackPiFromCharm); + } else if (usePidTpcTofCombined) { + statusPidPrFromLam = selectorProton.statusTpcOrTof(trackPrFromLam); + statusPidPiFromLam = selectorPion.statusTpcOrTof(trackPiFromLam); + statusPidPiFromCasc = selectorPion.statusTpcOrTof(trackPiFromCasc); + statusPidPiFromCharmBaryon = selectorPion.statusTpcOrTof(trackPiFromCharm); + } + + bool statusPidLambda = (statusPidPrFromLam == TrackSelectorPID::Accepted) && (statusPidPiFromLam == TrackSelectorPID::Accepted); + if (statusPidLambda && resultSelections) { + registry.fill(HIST("hSelStatusPID"), 1.0); + } + bool statusPidCascade = (statusPidLambda && statusPidPiFromCasc == TrackSelectorPID::Accepted); + if (statusPidCascade && resultSelections) { + registry.fill(HIST("hSelStatusPID"), 2.0); + } + bool statusPidCharmBaryon = (statusPidCascade && statusPidPiFromCharmBaryon == TrackSelectorPID::Accepted); + if (statusPidCharmBaryon && resultSelections) { + registry.fill(HIST("hSelStatusPID"), 3.0); + } + + // invariant mass cuts + bool statusInvMassLambda = false; + bool statusInvMassCascade = false; + bool statusInvMassCharmBaryon = false; + + double invMassLambda = candidate.invMassLambda(); + double invMassCascade = candidate.invMassCascade(); + double invMassCharmBaryon = candidate.invMassCharmBaryon(); + + if (std::abs(invMassLambda - o2::constants::physics::MassLambda0) < v0MassWindow) { + statusInvMassLambda = true; + } + if (std::abs(invMassCascade - o2::constants::physics::MassXiMinus) < cascMassWindow) { + statusInvMassCascade = true; + } + if ((invMassCharmBaryon >= invMassCharmBaryonMin) && (invMassCharmBaryon <= invMassCharmBaryonMax)) { + statusInvMassCharmBaryon = true; + } + + // ML BDT selection + if (applyMl) { + bool isSelectedMlXic0 = false; + std::vector inputFeaturesXic0 = {}; + if constexpr (svReco == doDcaFitter) { + inputFeaturesXic0 = hfMlResponseDca.getInputFeatures(candidate, trackPiFromLam, trackPiFromCasc, trackPiFromCharm); + isSelectedMlXic0 = hfMlResponseDca.isSelectedMl(inputFeaturesXic0, ptCandXic0, outputMlXic0ToXiPi); + } else { + inputFeaturesXic0 = hfMlResponseKf.getInputFeatures(candidate, trackPiFromLam, trackPiFromCasc, trackPiFromCharm); + isSelectedMlXic0 = hfMlResponseKf.isSelectedMl(inputFeaturesXic0, ptCandXic0, outputMlXic0ToXiPi); + } + if (!isSelectedMlXic0) { + continue; + } + hfMlToXiPi(outputMlXic0ToXiPi); + } + + // Fill in selection result + if constexpr (svReco == doDcaFitter) { + hfSelToXiPi(statusPidLambda, statusPidCascade, statusPidCharmBaryon, statusInvMassLambda, statusInvMassCascade, statusInvMassCharmBaryon, resultSelections, infoTpcStored, infoTofStored, + trackPiFromCharm.tpcNSigmaPi(), trackPiFromCasc.tpcNSigmaPi(), trackPiFromLam.tpcNSigmaPi(), trackPrFromLam.tpcNSigmaPr(), + trackPiFromCharm.tofNSigmaPi(), trackPiFromCasc.tofNSigmaPi(), trackPiFromLam.tofNSigmaPi(), trackPrFromLam.tofNSigmaPr()); + } else { + // Convert resultSelectrions to false if one of pid status and inv status is false + // This is only needed for KF(currently) since output selection table doesn't contain those information + if (!statusPidCharmBaryon || !statusInvMassLambda || !statusInvMassCascade || !statusInvMassCharmBaryon) { + resultSelections = false; + } + hfSelToXiPiKf(resultSelections, + trackPiFromCharm.tpcNSigmaPi(), trackPiFromCasc.tpcNSigmaPi(), trackPiFromLam.tpcNSigmaPi(), trackPrFromLam.tpcNSigmaPr(), + trackPiFromCharm.tofNSigmaPi(), trackPiFromCasc.tofNSigmaPi(), trackPiFromLam.tofNSigmaPi(), trackPrFromLam.tofNSigmaPr()); + } + + // Fill in invariant mass histogram + if (resultSelections) { + registry.fill(HIST("hInvMassCharmBaryonWoPidInvMassCut"), invMassCharmBaryon); + } + if (statusPidLambda && statusPidCascade && statusPidCharmBaryon && statusInvMassLambda && statusInvMassCascade && statusInvMassCharmBaryon && resultSelections) { + registry.fill(HIST("hInvMassCharmBaryon"), invMassCharmBaryon); + } else { + registry.fill(HIST("hInvMassCharmBaryonBkg"), invMassCharmBaryon); + } + + } // end of candidate loop + } // end run fuction + + /////////////////////////////////// + /// Process with DCAFitter // + /////////////////////////////////// + void processSelectionDCAFitter(aod::HfCandToXiPi const& candidates, TracksSel const& tracks, TracksSelLf const& lfTracks) + { + runSelection(candidates, tracks, lfTracks); + } + PROCESS_SWITCH(HfCandidateSelectorToXiPiQa, processSelectionDCAFitter, "Xic0 candidate selection with DCAFitter output", true); + + //////////////////////////////////// + /// Process with KFParticle // + //////////////////////////////////// + void processSelectionKFParticle(aod::HfCandToXiPiKf const& candidates, TracksSel const& tracks, TracksSelLf const& lfTracks) + { + runSelection(candidates, tracks, lfTracks); + } + PROCESS_SWITCH(HfCandidateSelectorToXiPiQa, processSelectionKFParticle, "Xic0 candidate selection with KFParticle output", false); + +}; // end struct + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/TableProducer/treeCreatorToXiPiQa.cxx b/PWGHF/TableProducer/treeCreatorToXiPiQa.cxx new file mode 100644 index 00000000000..2e219e14355 --- /dev/null +++ b/PWGHF/TableProducer/treeCreatorToXiPiQa.cxx @@ -0,0 +1,982 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file treeCreatorToXiPiQa.cxx +/// \brief Writer of the omegac0 or xic0 to Xi Pi candidates in the form of flat tables to be stored in TTrees. +/// In this file are defined and filled the output tables +/// +/// \author Jinhyun Park , Pusan National University +/// \author Krista Smith , Pusan National University + +#include "PWGHF/Core/CentralityEstimation.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace o2; +using namespace o2::framework; + +// SV Reco method +enum { + DCAFITTER = 0, + KFPARTICLE +}; + +// Table size +enum { + FULL = 0, + LITE +}; + +namespace o2::aod +{ +namespace full +{ +// collision info +DECLARE_SOA_COLUMN(IsEventSel8, isEventSel8, bool); +DECLARE_SOA_COLUMN(IsEventSelZ, isEventSelZ, bool); +DECLARE_SOA_COLUMN(Centrality, centrality, float); +// from creator +DECLARE_SOA_COLUMN(XPv, xPv, float); +DECLARE_SOA_COLUMN(YPv, yPv, float); +DECLARE_SOA_COLUMN(ZPv, zPv, float); +DECLARE_SOA_COLUMN(XDecayVtxCharmBaryon, xDecayVtxCharmBaryon, float); +DECLARE_SOA_COLUMN(YDecayVtxCharmBaryon, yDecayVtxCharmBaryon, float); +DECLARE_SOA_COLUMN(ZDecayVtxCharmBaryon, zDecayVtxCharmBaryon, float); +DECLARE_SOA_COLUMN(XDecayVtxCascade, xDecayVtxCascade, float); +DECLARE_SOA_COLUMN(YDecayVtxCascade, yDecayVtxCascade, float); +DECLARE_SOA_COLUMN(ZDecayVtxCascade, zDecayVtxCascade, float); +DECLARE_SOA_COLUMN(XDecayVtxV0, xDecayVtxV0, float); +DECLARE_SOA_COLUMN(YDecayVtxV0, yDecayVtxV0, float); +DECLARE_SOA_COLUMN(ZDecayVtxV0, zDecayVtxV0, float); +DECLARE_SOA_COLUMN(SignDecay, signDecay, int8_t); // sign of pi <- xi +DECLARE_SOA_COLUMN(CovVtxCharmBaryonXX, covVtxCharmBaryonXX, float); +DECLARE_SOA_COLUMN(CovVtxCharmBaryonYY, covVtxCharmBaryonYY, float); +DECLARE_SOA_COLUMN(CovVtxCharmBaryonZZ, covVtxCharmBaryonZZ, float); +DECLARE_SOA_COLUMN(PxCharmBaryon, pxCharmBaryon, float); +DECLARE_SOA_COLUMN(PyCharmBaryon, pyCharmBaryon, float); +DECLARE_SOA_COLUMN(PzCharmBaryon, pzCharmBaryon, float); +DECLARE_SOA_COLUMN(PxCasc, pxCasc, float); +DECLARE_SOA_COLUMN(PyCasc, pyCasc, float); +DECLARE_SOA_COLUMN(PzCasc, pzCasc, float); +DECLARE_SOA_COLUMN(PxPiFromCharmBaryon, pxPiFromCharmBaryon, float); +DECLARE_SOA_COLUMN(PyPiFromCharmBaryon, pyPiFromCharmBaryon, float); +DECLARE_SOA_COLUMN(PzPiFromCharmBaryon, pzPiFromCharmBaryon, float); +DECLARE_SOA_COLUMN(PxLambda, pxLambda, float); +DECLARE_SOA_COLUMN(PyLambda, pyLambda, float); +DECLARE_SOA_COLUMN(PzLambda, pzLambda, float); +DECLARE_SOA_COLUMN(PtCharmBaryon, ptCharmBaryon, float); +DECLARE_SOA_COLUMN(PtPiFromCharmBaryon, ptPiFromCharmBaryon, float); +DECLARE_SOA_COLUMN(PxPiFromCasc, pxPiFromCasc, float); +DECLARE_SOA_COLUMN(PyPiFromCasc, pyPiFromCasc, float); +DECLARE_SOA_COLUMN(PzPiFromCasc, pzPiFromCasc, float); +DECLARE_SOA_COLUMN(PxPosV0Dau, pxPosV0Dau, float); +DECLARE_SOA_COLUMN(PyPosV0Dau, pyPosV0Dau, float); +DECLARE_SOA_COLUMN(PzPosV0Dau, pzPosV0Dau, float); +DECLARE_SOA_COLUMN(PxNegV0Dau, pxNegV0Dau, float); +DECLARE_SOA_COLUMN(PyNegV0Dau, pyNegV0Dau, float); +DECLARE_SOA_COLUMN(PzNegV0Dau, pzNegV0Dau, float); +DECLARE_SOA_COLUMN(ImpactParCascXY, impactParCascXY, float); +DECLARE_SOA_COLUMN(ImpactParPiFromCharmBaryonXY, impactParPiFromCharmBaryonXY, float); +DECLARE_SOA_COLUMN(ImpactParCascZ, impactParCascZ, float); +DECLARE_SOA_COLUMN(ImpactParPiFromCharmBaryonZ, impactParPiFromCharmBaryonZ, float); +DECLARE_SOA_COLUMN(ErrImpactParCascXY, errImpactParCascXY, float); +DECLARE_SOA_COLUMN(ErrImpactParPiFromCharmBaryonXY, errImpactParPiFromCharmBaryonXY, float); +DECLARE_SOA_COLUMN(InvMassLambda, invMassLambda, float); +DECLARE_SOA_COLUMN(InvMassCascade, invMassCascade, float); +DECLARE_SOA_COLUMN(InvMassCharmBaryon, invMassCharmBaryon, float); +DECLARE_SOA_COLUMN(CosPAV0, cosPAV0, float); +DECLARE_SOA_COLUMN(CosPACharmBaryon, cosPACharmBaryon, float); +DECLARE_SOA_COLUMN(CosPACasc, cosPACasc, float); +DECLARE_SOA_COLUMN(CosPAXYV0, cosPAXYV0, float); +DECLARE_SOA_COLUMN(CosPAXYCharmBaryon, cosPAXYCharmBaryon, float); +DECLARE_SOA_COLUMN(CosPAXYCasc, cosPAXYCasc, float); +DECLARE_SOA_COLUMN(CTauOmegac, cTauOmegac, float); +DECLARE_SOA_COLUMN(CTauCascade, cTauCascade, float); +DECLARE_SOA_COLUMN(CTauV0, cTauV0, float); +DECLARE_SOA_COLUMN(CTauXic, cTauXic, float); +DECLARE_SOA_COLUMN(EtaV0PosDau, etaV0PosDau, float); +DECLARE_SOA_COLUMN(EtaV0NegDau, etaV0NegDau, float); +DECLARE_SOA_COLUMN(EtaPiFromCasc, etaPiFromCasc, float); +DECLARE_SOA_COLUMN(EtaPiFromCharmBaryon, etaPiFromCharmBaryon, float); +DECLARE_SOA_COLUMN(EtaCharmBaryon, etaCharmBaryon, float); +DECLARE_SOA_COLUMN(EtaCascade, etaCascade, float); +DECLARE_SOA_COLUMN(EtaV0, etaV0, float); +DECLARE_SOA_COLUMN(DcaXYToPvV0Dau0, dcaXYToPvV0Dau0, float); +DECLARE_SOA_COLUMN(DcaXYToPvV0Dau1, dcaXYToPvV0Dau1, float); +DECLARE_SOA_COLUMN(DcaXYToPvCascDau, dcaXYToPvCascDau, float); +DECLARE_SOA_COLUMN(DcaZToPvV0Dau0, dcaZToPvV0Dau0, float); +DECLARE_SOA_COLUMN(DcaZToPvV0Dau1, dcaZToPvV0Dau1, float); +DECLARE_SOA_COLUMN(DcaZToPvCascDau, dcaZToPvCascDau, float); +DECLARE_SOA_COLUMN(DcaCascDau, dcaCascDau, float); +DECLARE_SOA_COLUMN(DcaV0Dau, dcaV0Dau, float); +DECLARE_SOA_COLUMN(DcaCharmBaryonDau, dcaCharmBaryonDau, float); +DECLARE_SOA_COLUMN(DecLenCharmBaryon, decLenCharmBaryon, float); +DECLARE_SOA_COLUMN(DecLenCascade, decLenCascade, float); +DECLARE_SOA_COLUMN(DecLenV0, decLenV0, float); +DECLARE_SOA_COLUMN(ErrorDecayLengthCharmBaryon, errorDecayLengthCharmBaryon, float); +DECLARE_SOA_COLUMN(ErrorDecayLengthXYCharmBaryon, errorDecayLengthXYCharmBaryon, float); +DECLARE_SOA_COLUMN(NormImpParCascade, normImpParCascade, double); +DECLARE_SOA_COLUMN(NormImpParPiFromCharmBar, normImpParPiFromCharmBar, double); +DECLARE_SOA_COLUMN(NormDecayLenCharmBar, normDecayLenCharmBar, double); +DECLARE_SOA_COLUMN(IsPionGlbTrkWoDca, isPionGlbTrkWoDca, bool); +DECLARE_SOA_COLUMN(PionItsNCls, pionItsNCls, uint8_t); +DECLARE_SOA_COLUMN(NTpcRowsPion, nTpcRowsPion, int16_t); +DECLARE_SOA_COLUMN(NTpcRowsPiFromCasc, nTpcRowsPiFromCasc, int16_t); +DECLARE_SOA_COLUMN(NTpcRowsPosV0Dau, nTpcRowsPosV0Dau, int16_t); +DECLARE_SOA_COLUMN(NTpcRowsNegV0Dau, nTpcRowsNegV0Dau, int16_t); +// from creator - MC +DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); // reconstruction level +DECLARE_SOA_COLUMN(DebugMcRec, debugMcRec, int8_t); // debug flag for mis-association reconstruction level +DECLARE_SOA_COLUMN(OriginRec, originRec, int8_t); +DECLARE_SOA_COLUMN(CollisionMatched, collisionMatched, bool); +// from selector +DECLARE_SOA_COLUMN(StatusPidLambda, statusPidLambda, bool); +DECLARE_SOA_COLUMN(StatusPidCascade, statusPidCascade, bool); +DECLARE_SOA_COLUMN(StatusPidCharmBaryon, statusPidCharmBaryon, bool); +DECLARE_SOA_COLUMN(StatusInvMassLambda, statusInvMassLambda, bool); +DECLARE_SOA_COLUMN(StatusInvMassCascade, statusInvMassCascade, bool); +DECLARE_SOA_COLUMN(StatusInvMassCharmBaryon, statusInvMassCharmBaryon, bool); +DECLARE_SOA_COLUMN(ResultSelections, resultSelections, bool); +DECLARE_SOA_COLUMN(PidTpcInfoStored, pidTpcInfoStored, int); +DECLARE_SOA_COLUMN(PidTofInfoStored, pidTofInfoStored, int); +DECLARE_SOA_COLUMN(TpcNSigmaPiFromCharmBaryon, tpcNSigmaPiFromCharmBaryon, float); +DECLARE_SOA_COLUMN(TpcNSigmaPiFromCasc, tpcNSigmaPiFromCasc, float); +DECLARE_SOA_COLUMN(TpcNSigmaPiFromLambda, tpcNSigmaPiFromLambda, float); +DECLARE_SOA_COLUMN(TpcNSigmaPrFromLambda, tpcNSigmaPrFromLambda, float); +DECLARE_SOA_COLUMN(TofNSigmaPiFromCharmBaryon, tofNSigmaPiFromCharmBaryon, float); +DECLARE_SOA_COLUMN(TofNSigmaPiFromCasc, tofNSigmaPiFromCasc, float); +DECLARE_SOA_COLUMN(TofNSigmaPiFromLambda, tofNSigmaPiFromLambda, float); +DECLARE_SOA_COLUMN(TofNSigmaPrFromLambda, tofNSigmaPrFromLambda, float); +// from creator KF +DECLARE_SOA_COLUMN(KfDcaXYPiFromXic, kfDcaXYPiFromXic, float); +DECLARE_SOA_COLUMN(KfDcaXYCascToPv, kfDcaXYCascToPv, float); +DECLARE_SOA_COLUMN(Chi2GeoV0, chi2GeoV0, float); +DECLARE_SOA_COLUMN(Chi2GeoCasc, chi2GeoCasc, float); +DECLARE_SOA_COLUMN(Chi2GeoXic, chi2GeoXic, float); +DECLARE_SOA_COLUMN(Chi2MassV0, chi2MassV0, float); +DECLARE_SOA_COLUMN(Chi2MassCasc, chi2MassCasc, float); +DECLARE_SOA_COLUMN(V0ldl, v0ldl, float); +DECLARE_SOA_COLUMN(Cascldl, cascldl, float); +DECLARE_SOA_COLUMN(Xicldl, xicldl, float); +DECLARE_SOA_COLUMN(Chi2TopoV0ToPv, chi2TopoV0ToPv, float); +DECLARE_SOA_COLUMN(Chi2TopoCascToPv, chi2TopoCascToPv, float); +DECLARE_SOA_COLUMN(Chi2TopoPiFromXicToPv, chi2TopoPiFromXicToPv, float); +DECLARE_SOA_COLUMN(Chi2TopoXicToPv, chi2TopoXicToPv, float); +DECLARE_SOA_COLUMN(Chi2TopoV0ToCasc, chi2TopoV0ToCasc, float); +DECLARE_SOA_COLUMN(Chi2TopoCascToXic, chi2TopoCascToXic, float); +DECLARE_SOA_COLUMN(DecayLenXYLambda, decayLenXYLambda, float); +DECLARE_SOA_COLUMN(DecayLenXYCasc, decayLenXYCasc, float); +DECLARE_SOA_COLUMN(DecayLenXYXic, decayLenXYXic, float); +DECLARE_SOA_COLUMN(CosPaV0ToCasc, cosPaV0ToCasc, float); +DECLARE_SOA_COLUMN(CosPaV0ToPv, cosPaV0ToPv, float); +DECLARE_SOA_COLUMN(CosPaCascToXic, cosPaCascToXic, float); +DECLARE_SOA_COLUMN(CosPaCascToPv, cosPaCascToPv, float); +DECLARE_SOA_COLUMN(CosPaXicToPv, cosPaXicToPv, float); +DECLARE_SOA_COLUMN(KfRapXic, kfRapXic, float); +DECLARE_SOA_COLUMN(KfptPiFromXic, kfptPiFromXic, float); +DECLARE_SOA_COLUMN(KfptXic, kfptXic, float); +DECLARE_SOA_COLUMN(CosThetaStarPiFromXic, cosThetaStarPiFromXic, float); +DECLARE_SOA_COLUMN(CtXic, ctXic, float); +DECLARE_SOA_COLUMN(EtaXic, etaXic, float); +DECLARE_SOA_COLUMN(V0Ndf, v0Ndf, float); +DECLARE_SOA_COLUMN(CascNdf, cascNdf, float); +DECLARE_SOA_COLUMN(XicNdf, xicNdf, float); +DECLARE_SOA_COLUMN(MassV0Ndf, massV0Ndf, float); +DECLARE_SOA_COLUMN(MassCascNdf, massCascNdf, float); +DECLARE_SOA_COLUMN(V0Chi2OverNdf, v0Chi2OverNdf, float); +DECLARE_SOA_COLUMN(CascChi2OverNdf, cascChi2OverNdf, float); +DECLARE_SOA_COLUMN(XicChi2OverNdf, xicChi2OverNdf, float); +DECLARE_SOA_COLUMN(MassV0Chi2OverNdf, massV0Chi2OverNdf, float); +DECLARE_SOA_COLUMN(MassCascChi2OverNdf, massCascChi2OverNdf, float); +} // namespace full + +DECLARE_SOA_TABLE(HfToXiPiEvs, "AOD", "HFTOXIPIEV", + full::IsEventSel8, full::IsEventSelZ); + +DECLARE_SOA_TABLE(HfToXiPiFulls, "AOD", "HFTOXIPIFULL", + full::XPv, full::YPv, full::ZPv, full::Centrality, collision::NumContrib, collision::Chi2, + full::XDecayVtxCharmBaryon, full::YDecayVtxCharmBaryon, full::ZDecayVtxCharmBaryon, + full::XDecayVtxCascade, full::YDecayVtxCascade, full::ZDecayVtxCascade, + full::XDecayVtxV0, full::YDecayVtxV0, full::ZDecayVtxV0, + full::SignDecay, + full::CovVtxCharmBaryonXX, full::CovVtxCharmBaryonYY, full::CovVtxCharmBaryonZZ, + full::PtCharmBaryon, full::PtPiFromCharmBaryon, + full::PxCharmBaryon, full::PyCharmBaryon, full::PzCharmBaryon, + full::PxCasc, full::PyCasc, full::PzCasc, + full::PxPiFromCharmBaryon, full::PyPiFromCharmBaryon, full::PzPiFromCharmBaryon, + full::PxLambda, full::PyLambda, full::PzLambda, + full::PxPiFromCasc, full::PyPiFromCasc, full::PzPiFromCasc, + full::PxPosV0Dau, full::PyPosV0Dau, full::PzPosV0Dau, + full::PxNegV0Dau, full::PyNegV0Dau, full::PzNegV0Dau, + full::ImpactParCascXY, full::ImpactParPiFromCharmBaryonXY, + full::ImpactParCascZ, full::ImpactParPiFromCharmBaryonZ, + full::ErrImpactParCascXY, full::ErrImpactParPiFromCharmBaryonXY, + full::InvMassLambda, full::InvMassCascade, full::InvMassCharmBaryon, + full::CosPAV0, full::CosPACharmBaryon, full::CosPACasc, full::CosPAXYV0, full::CosPAXYCharmBaryon, full::CosPAXYCasc, + full::CTauOmegac, full::CTauCascade, full::CTauV0, full::CTauXic, + full::EtaV0PosDau, full::EtaV0NegDau, full::EtaPiFromCasc, full::EtaPiFromCharmBaryon, + full::EtaCharmBaryon, full::EtaCascade, full::EtaV0, + full::DcaXYToPvV0Dau0, full::DcaXYToPvV0Dau1, full::DcaXYToPvCascDau, + full::DcaZToPvV0Dau0, full::DcaZToPvV0Dau1, full::DcaZToPvCascDau, + full::DcaCascDau, full::DcaV0Dau, full::DcaCharmBaryonDau, + full::DecLenCharmBaryon, full::DecLenCascade, full::DecLenV0, full::ErrorDecayLengthCharmBaryon, full::ErrorDecayLengthXYCharmBaryon, + full::NormImpParCascade, full::NormImpParPiFromCharmBar, full::NormDecayLenCharmBar, full::IsPionGlbTrkWoDca, full::PionItsNCls, + full::NTpcRowsPion, full::NTpcRowsPiFromCasc, full::NTpcRowsPosV0Dau, full::NTpcRowsNegV0Dau, + full::StatusPidLambda, full::StatusPidCascade, full::StatusPidCharmBaryon, + full::StatusInvMassLambda, full::StatusInvMassCascade, full::StatusInvMassCharmBaryon, full::ResultSelections, + full::PidTpcInfoStored, full::PidTofInfoStored, + full::TpcNSigmaPiFromCharmBaryon, full::TpcNSigmaPiFromCasc, full::TpcNSigmaPiFromLambda, full::TpcNSigmaPrFromLambda, + full::TofNSigmaPiFromCharmBaryon, full::TofNSigmaPiFromCasc, full::TofNSigmaPiFromLambda, full::TofNSigmaPrFromLambda, + full::FlagMcMatchRec, full::DebugMcRec, full::OriginRec, full::CollisionMatched); + +DECLARE_SOA_TABLE(HfToXiPiLites, "AOD", "HFTOXIPILITE", + full::XPv, full::YPv, full::ZPv, full::Centrality, collision::NumContrib, collision::Chi2, + full::XDecayVtxCharmBaryon, full::YDecayVtxCharmBaryon, full::ZDecayVtxCharmBaryon, + full::XDecayVtxCascade, full::YDecayVtxCascade, full::ZDecayVtxCascade, + full::XDecayVtxV0, full::YDecayVtxV0, full::ZDecayVtxV0, + full::SignDecay, + full::PtCharmBaryon, full::PtPiFromCharmBaryon, + full::PxCharmBaryon, full::PyCharmBaryon, full::PzCharmBaryon, + full::PxPiFromCharmBaryon, full::PyPiFromCharmBaryon, full::PzPiFromCharmBaryon, + full::PxPiFromCasc, full::PyPiFromCasc, full::PzPiFromCasc, + full::PxPosV0Dau, full::PyPosV0Dau, full::PzPosV0Dau, + full::PxNegV0Dau, full::PyNegV0Dau, full::PzNegV0Dau, + full::ImpactParCascXY, full::ImpactParPiFromCharmBaryonXY, + full::ErrImpactParCascXY, full::ErrImpactParPiFromCharmBaryonXY, + full::InvMassLambda, full::InvMassCascade, full::InvMassCharmBaryon, + full::CosPAV0, full::CosPACharmBaryon, full::CosPACasc, + full::EtaV0PosDau, full::EtaV0NegDau, full::EtaPiFromCasc, full::EtaPiFromCharmBaryon, full::EtaCharmBaryon, + full::DcaXYToPvV0Dau0, full::DcaXYToPvV0Dau1, full::DcaXYToPvCascDau, + full::DcaCascDau, full::DcaV0Dau, full::DcaCharmBaryonDau, + full::ErrorDecayLengthCharmBaryon, full::NormImpParCascade, full::NormImpParPiFromCharmBar, + full::IsPionGlbTrkWoDca, full::PionItsNCls, + full::NTpcRowsPion, full::NTpcRowsPiFromCasc, full::NTpcRowsPosV0Dau, full::NTpcRowsNegV0Dau, + full::PidTpcInfoStored, full::PidTofInfoStored, + full::TpcNSigmaPiFromCharmBaryon, full::TpcNSigmaPiFromCasc, full::TpcNSigmaPiFromLambda, full::TpcNSigmaPrFromLambda, + full::TofNSigmaPiFromCharmBaryon, full::TofNSigmaPiFromCasc, full::TofNSigmaPiFromLambda, full::TofNSigmaPrFromLambda, + full::FlagMcMatchRec, full::OriginRec, full::CollisionMatched); + +DECLARE_SOA_TABLE(HfKfXicFulls, "AOD", "HFKFXICFULL", + full::Centrality, + full::TpcNSigmaPiFromCharmBaryon, full::TofNSigmaPiFromCharmBaryon, full::TpcNSigmaPiFromCasc, full::TofNSigmaPiFromCasc, + full::TpcNSigmaPiFromLambda, full::TofNSigmaPiFromLambda, full::TpcNSigmaPrFromLambda, full::TofNSigmaPrFromLambda, + full::KfDcaXYPiFromXic, full::DcaCascDau, full::DcaV0Dau, full::DcaCharmBaryonDau, full::KfDcaXYCascToPv, + full::DcaXYToPvV0Dau0, full::DcaXYToPvV0Dau1, full::DcaXYToPvCascDau, + full::Chi2GeoV0, full::Chi2GeoCasc, full::Chi2GeoXic, + full::Chi2MassV0, full::Chi2MassCasc, + full::V0ldl, full::Cascldl, + full::Chi2TopoV0ToPv, full::Chi2TopoCascToPv, full::Chi2TopoPiFromXicToPv, full::Chi2TopoXicToPv, + full::Chi2TopoV0ToCasc, full::Chi2TopoCascToXic, + full::DecayLenXYLambda, full::DecayLenXYCasc, full::DecayLenXYXic, + full::CosPaV0ToCasc, full::CosPaV0ToPv, full::CosPaCascToXic, full::CosPaCascToPv, // full::CosPaXicToPv, + full::InvMassLambda, full::InvMassCascade, full::InvMassCharmBaryon, + full::KfRapXic, full::KfptPiFromXic, full::KfptXic, + full::CosThetaStarPiFromXic, full::CtXic, full::EtaXic, + full::V0Ndf, full::CascNdf, full::XicNdf, + full::MassV0Ndf, full::MassCascNdf, + full::V0Chi2OverNdf, full::CascChi2OverNdf, full::XicChi2OverNdf, + full::MassV0Chi2OverNdf, full::MassCascChi2OverNdf, + full::ResultSelections, + full::FlagMcMatchRec, full::DebugMcRec, full::OriginRec, full::CollisionMatched); + +} // namespace o2::aod + +/// Writes the full information in an output TTree +struct HfTreeCreatorToXiPiQa { + + Produces rowCandidateFull; + Produces rowCandidateLite; + Produces rowKfCandidate; + Produces rowEv; + + Configurable zPvCut{"zPvCut", 10., "Cut on absolute value of primary vertex z coordinate"}; + + using MyTrackTable = soa::Join; + using MyEventTable = soa::Join; + using MyEventTableWithFT0C = soa::Join; + using MyEventTableWithFT0M = soa::Join; + using MyEventTableWithNTracksPV = soa::Join; + + void init(InitContext const&) + { + if ((doprocessMcLiteXic0 && doprocessMcLiteOmegac0) || (doprocessMcFullXic0 && doprocessMcFullOmegac0)) { + LOGF(fatal, "Both Xic0 and Omegac0 MC processes enabled, please choose ONLY one!"); + } + } + + ////////////////////////////////////////////////////// + // // + // Fill functions to fill in the tables // + // // + ////////////////////////////////////////////////////// + + template + void fillEvent(const T& collision, float cutZPv) + { + rowEv(collision.sel8(), std::abs(collision.posZ()) < cutZPv); + } + + template + void fillCandidate(const T& candidate, int8_t flagMc, int8_t debugMc, int8_t originMc, bool collisionMatched) + { + // save all candidate information + float centrality = -999.f; + if constexpr (useCentrality) { + const auto& collision = candidate.template collision_as(); + centrality = o2::hf_centrality::getCentralityColl(collision); + } + + if constexpr (svReco == DCAFITTER) { + if constexpr (tableSize == LITE) { + rowCandidateLite(candidate.xPv(), + candidate.yPv(), + candidate.zPv(), + centrality, + candidate.template collision_as().numContrib(), + candidate.template collision_as().chi2(), + candidate.xDecayVtxCharmBaryon(), + candidate.yDecayVtxCharmBaryon(), + candidate.zDecayVtxCharmBaryon(), + candidate.xDecayVtxCascade(), + candidate.yDecayVtxCascade(), + candidate.zDecayVtxCascade(), + candidate.xDecayVtxV0(), + candidate.yDecayVtxV0(), + candidate.zDecayVtxV0(), + candidate.signDecay(), + RecoDecay::pt(candidate.pxCharmBaryon(), candidate.pyCharmBaryon()), + RecoDecay::pt(candidate.pxBachFromCharmBaryon(), candidate.pyBachFromCharmBaryon()), + candidate.pxCharmBaryon(), + candidate.pyCharmBaryon(), + candidate.pzCharmBaryon(), + candidate.pxBachFromCharmBaryon(), + candidate.pyBachFromCharmBaryon(), + candidate.pzBachFromCharmBaryon(), + candidate.pxBachFromCasc(), + candidate.pyBachFromCasc(), + candidate.pzBachFromCasc(), + candidate.pxPosV0Dau(), + candidate.pyPosV0Dau(), + candidate.pzPosV0Dau(), + candidate.pxNegV0Dau(), + candidate.pyNegV0Dau(), + candidate.pzNegV0Dau(), + candidate.impactParCascXY(), + candidate.impactParBachFromCharmBaryonXY(), + candidate.errImpactParCascXY(), + candidate.errImpactParBachFromCharmBaryonXY(), + candidate.invMassLambda(), + candidate.invMassCascade(), + candidate.invMassCharmBaryon(), + candidate.cosPAV0(), + candidate.cosPACharmBaryon(), + candidate.cosPACasc(), + candidate.etaV0PosDau(), + candidate.etaV0NegDau(), + candidate.etaBachFromCasc(), + candidate.etaBachFromCharmBaryon(), + candidate.etaCharmBaryon(), + candidate.dcaXYToPvV0Dau0(), + candidate.dcaXYToPvV0Dau1(), + candidate.dcaXYToPvCascDau(), + candidate.dcaCascDau(), + candidate.dcaV0Dau(), + candidate.dcaCharmBaryonDau(), + candidate.errorDecayLengthCharmBaryon(), + candidate.impactParCascXY() / candidate.errImpactParCascXY(), + candidate.impactParBachFromCharmBaryonXY() / candidate.errImpactParBachFromCharmBaryonXY(), + candidate.template bachelorFromCharmBaryon_as().isGlobalTrackWoDCA(), + candidate.template bachelorFromCharmBaryon_as().itsNCls(), + candidate.template bachelorFromCharmBaryon_as().tpcNClsCrossedRows(), + candidate.template bachelor_as().tpcNClsCrossedRows(), + candidate.template posTrack_as().tpcNClsCrossedRows(), + candidate.template negTrack_as().tpcNClsCrossedRows(), + candidate.pidTpcInfoStored(), + candidate.pidTofInfoStored(), + candidate.tpcNSigmaPiFromCharmBaryon(), + candidate.tpcNSigmaPiFromCasc(), + candidate.tpcNSigmaPiFromLambda(), + candidate.tpcNSigmaPrFromLambda(), + candidate.tofNSigmaPiFromCharmBaryon(), + candidate.tofNSigmaPiFromCasc(), + candidate.tofNSigmaPiFromLambda(), + candidate.tofNSigmaPrFromLambda(), + flagMc, + originMc, + collisionMatched); + } else { + rowCandidateFull(candidate.xPv(), + candidate.yPv(), + candidate.zPv(), + centrality, + candidate.template collision_as().numContrib(), + candidate.template collision_as().chi2(), + candidate.xDecayVtxCharmBaryon(), + candidate.yDecayVtxCharmBaryon(), + candidate.zDecayVtxCharmBaryon(), + candidate.xDecayVtxCascade(), + candidate.yDecayVtxCascade(), + candidate.zDecayVtxCascade(), + candidate.xDecayVtxV0(), + candidate.yDecayVtxV0(), + candidate.zDecayVtxV0(), + candidate.signDecay(), + candidate.covVtxCharmBaryon0(), + candidate.covVtxCharmBaryon3(), + candidate.covVtxCharmBaryon5(), + RecoDecay::pt(candidate.pxCharmBaryon(), candidate.pyCharmBaryon()), + RecoDecay::pt(candidate.pxBachFromCharmBaryon(), candidate.pyBachFromCharmBaryon()), + candidate.pxCharmBaryon(), + candidate.pyCharmBaryon(), + candidate.pzCharmBaryon(), + candidate.pxCasc(), + candidate.pyCasc(), + candidate.pzCasc(), + candidate.pxBachFromCharmBaryon(), + candidate.pyBachFromCharmBaryon(), + candidate.pzBachFromCharmBaryon(), + candidate.pxLambda(), + candidate.pyLambda(), + candidate.pzLambda(), + candidate.pxBachFromCasc(), + candidate.pyBachFromCasc(), + candidate.pzBachFromCasc(), + candidate.pxPosV0Dau(), + candidate.pyPosV0Dau(), + candidate.pzPosV0Dau(), + candidate.pxNegV0Dau(), + candidate.pyNegV0Dau(), + candidate.pzNegV0Dau(), + candidate.impactParCascXY(), + candidate.impactParBachFromCharmBaryonXY(), + candidate.impactParCascZ(), + candidate.impactParBachFromCharmBaryonZ(), + candidate.errImpactParCascXY(), + candidate.errImpactParBachFromCharmBaryonXY(), + candidate.invMassLambda(), + candidate.invMassCascade(), + candidate.invMassCharmBaryon(), + candidate.cosPAV0(), + candidate.cosPACharmBaryon(), + candidate.cosPACasc(), + candidate.cosPAXYV0(), + candidate.cosPAXYCharmBaryon(), + candidate.cosPAXYCasc(), + candidate.cTauOmegac(), + candidate.cTauCascade(), + candidate.cTauV0(), + candidate.cTauXic(), + candidate.etaV0PosDau(), + candidate.etaV0NegDau(), + candidate.etaBachFromCasc(), + candidate.etaBachFromCharmBaryon(), + candidate.etaCharmBaryon(), + candidate.etaCascade(), + candidate.etaV0(), + candidate.dcaXYToPvV0Dau0(), + candidate.dcaXYToPvV0Dau1(), + candidate.dcaXYToPvCascDau(), + candidate.dcaZToPvV0Dau0(), + candidate.dcaZToPvV0Dau1(), + candidate.dcaZToPvCascDau(), + candidate.dcaCascDau(), + candidate.dcaV0Dau(), + candidate.dcaCharmBaryonDau(), + candidate.decLenCharmBaryon(), + candidate.decLenCascade(), + candidate.decLenV0(), + candidate.errorDecayLengthCharmBaryon(), + candidate.errorDecayLengthXYCharmBaryon(), + candidate.impactParCascXY() / candidate.errImpactParCascXY(), + candidate.impactParBachFromCharmBaryonXY() / candidate.errImpactParBachFromCharmBaryonXY(), + candidate.decLenCharmBaryon() / candidate.errorDecayLengthCharmBaryon(), + candidate.template bachelorFromCharmBaryon_as().isGlobalTrackWoDCA(), + candidate.template bachelorFromCharmBaryon_as().itsNCls(), + candidate.template bachelorFromCharmBaryon_as().tpcNClsCrossedRows(), + candidate.template bachelor_as().tpcNClsCrossedRows(), + candidate.template posTrack_as().tpcNClsCrossedRows(), + candidate.template negTrack_as().tpcNClsCrossedRows(), + candidate.statusPidLambda(), + candidate.statusPidCascade(), + candidate.statusPidCharmBaryon(), + candidate.statusInvMassLambda(), + candidate.statusInvMassCascade(), + candidate.statusInvMassCharmBaryon(), + candidate.resultSelections(), + candidate.pidTpcInfoStored(), + candidate.pidTofInfoStored(), + candidate.tpcNSigmaPiFromCharmBaryon(), + candidate.tpcNSigmaPiFromCasc(), + candidate.tpcNSigmaPiFromLambda(), + candidate.tpcNSigmaPrFromLambda(), + candidate.tofNSigmaPiFromCharmBaryon(), + candidate.tofNSigmaPiFromCasc(), + candidate.tofNSigmaPiFromLambda(), + candidate.tofNSigmaPrFromLambda(), + flagMc, + debugMc, + originMc, + collisionMatched); + } + } else { + if constexpr (tableSize == LITE) { + // currently, no lite sized table for KFParticle + } else { + rowKfCandidate(centrality, + candidate.tpcNSigmaPiFromCharmBaryon(), + candidate.tofNSigmaPiFromCharmBaryon(), + candidate.tpcNSigmaPiFromCasc(), + candidate.tofNSigmaPiFromCasc(), + candidate.tpcNSigmaPiFromLambda(), + candidate.tofNSigmaPiFromLambda(), + candidate.tpcNSigmaPrFromLambda(), + candidate.tofNSigmaPrFromLambda(), + candidate.kfDcaXYPiFromXic(), + candidate.dcaCascDau(), + candidate.dcaV0Dau(), + candidate.dcaCharmBaryonDau(), + candidate.kfDcaXYCascToPv(), + candidate.dcaXYToPvV0Dau0(), + candidate.dcaXYToPvV0Dau1(), + candidate.dcaXYToPvCascDau(), + candidate.chi2GeoV0(), + candidate.chi2GeoCasc(), + candidate.chi2GeoXic(), + candidate.chi2MassV0(), + candidate.chi2MassCasc(), + candidate.v0ldl(), + candidate.cascldl(), + candidate.chi2TopoV0ToPv(), + candidate.chi2TopoCascToPv(), + candidate.chi2TopoPiFromXicToPv(), + candidate.chi2TopoXicToPv(), + candidate.chi2TopoV0ToCasc(), + candidate.chi2TopoCascToXic(), + candidate.decayLenXYLambda(), + candidate.decayLenXYCasc(), + candidate.decayLenXYXic(), + candidate.cosPaV0ToCasc(), + candidate.cosPAV0(), + candidate.cosPaCascToXic(), + candidate.cosPACasc(), + candidate.invMassLambda(), + candidate.invMassCascade(), + candidate.invMassCharmBaryon(), + candidate.kfRapXic(), + RecoDecay::sqrtSumOfSquares(candidate.pxBachFromCharmBaryon(), candidate.pyBachFromCharmBaryon()), + RecoDecay::sqrtSumOfSquares(candidate.pxCharmBaryon(), candidate.pyCharmBaryon()), + candidate.cosThetaStarPiFromXic(), + candidate.cTauXic(), + candidate.etaCharmBaryon(), + candidate.v0Ndf(), + candidate.cascNdf(), + candidate.xicNdf(), + candidate.massV0Ndf(), + candidate.massCascNdf(), + candidate.v0Chi2OverNdf(), + candidate.cascChi2OverNdf(), + candidate.xicChi2OverNdf(), + candidate.massV0Chi2OverNdf(), + candidate.massCascChi2OverNdf(), + candidate.resultSelections(), + flagMc, + debugMc, + originMc, + collisionMatched); + } + } + } + + //////////////////////////////////// + // // + // Process functions // + // // + //////////////////////////////////// + + //*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*// + //*~~~~~~~Data with DCAFitter~~~~~~~~*// + //*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*// + + void processDataFull(MyEventTable const& collisions, MyTrackTable const&, + soa::Join const& candidates) + { + // Filling event properties + rowEv.reserve(collisions.size()); + for (const auto& collision : collisions) { + fillEvent(collision, zPvCut); + } + + // Filling candidate properties + rowCandidateFull.reserve(candidates.size()); + for (const auto& candidate : candidates) { + fillCandidate(candidate, -7, -7, RecoDecay::OriginType::None, false); + } + } + + void processDataLite(MyEventTable const& collisions, MyTrackTable const&, + soa::Join const& candidates) + { + // Filling event properties + rowEv.reserve(collisions.size()); + for (const auto& collision : collisions) { + fillEvent(collision, zPvCut); + } + + // Filling candidate properties + rowCandidateLite.reserve(candidates.size()); + for (const auto& candidate : candidates) { + fillCandidate(candidate, -7, -7, RecoDecay::OriginType::None, false); + } + } + + void processDataLiteWithFT0M(MyEventTableWithFT0M const& collisions, MyTrackTable const&, + soa::Join const& candidates) + { + // Filling event properties + rowEv.reserve(collisions.size()); + for (const auto& collision : collisions) { + fillEvent(collision, zPvCut); + } + + // Filling candidate properties + rowCandidateLite.reserve(candidates.size()); + for (const auto& candidate : candidates) { + fillCandidate(candidate, -7, -7, RecoDecay::OriginType::None, false); + } + } + + void processDataLiteWithFT0C(MyEventTableWithFT0C const& collisions, MyTrackTable const&, + soa::Join const& candidates) + { + // Filling event properties + rowEv.reserve(collisions.size()); + for (const auto& collision : collisions) { + fillEvent(collision, zPvCut); + } + + // Filling candidate properties + rowCandidateLite.reserve(candidates.size()); + for (const auto& candidate : candidates) { + fillCandidate(candidate, -7, -7, RecoDecay::OriginType::None, false); + } + } + + void processDataLiteWithNTracksPV(MyEventTableWithNTracksPV const& collisions, MyTrackTable const&, + soa::Join const& candidates) + { + // Filling event properties + rowEv.reserve(collisions.size()); + for (const auto& collision : collisions) { + fillEvent(collision, zPvCut); + } + + // Filling candidate properties + rowCandidateLite.reserve(candidates.size()); + for (const auto& candidate : candidates) { + fillCandidate(candidate, -7, -7, RecoDecay::OriginType::None, false); + } + } + + PROCESS_SWITCH(HfTreeCreatorToXiPiQa, processDataFull, "Process data with full information w/o centrality", false); + PROCESS_SWITCH(HfTreeCreatorToXiPiQa, processDataLite, "Process data and produce lite table version", true); + PROCESS_SWITCH(HfTreeCreatorToXiPiQa, processDataLiteWithFT0M, "Process data and produce lite table version with FT0M", false); + PROCESS_SWITCH(HfTreeCreatorToXiPiQa, processDataLiteWithFT0C, "Process data and produce lite table version with FT0C", false); + PROCESS_SWITCH(HfTreeCreatorToXiPiQa, processDataLiteWithNTracksPV, "Process data and produce lite table version with NTracksPV", false); + + //*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*// + //*~~~~~~~Data with KFParticle~~~~~~~~*// + //*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*// + void processKfData(MyEventTable const& collisions, MyTrackTable const&, + soa::Join const& candidates) + { + // Filling event properties + rowEv.reserve(collisions.size()); + for (const auto& collision : collisions) { + fillEvent(collision, zPvCut); + } + + // Filling candidate properties + rowKfCandidate.reserve(candidates.size()); + for (const auto& candidate : candidates) { + fillCandidate(candidate, -7, -7, RecoDecay::OriginType::None, false); + } + } + + void processKfDataWithFT0M(MyEventTableWithFT0M const& collisions, MyTrackTable const&, + soa::Join const& candidates) + { + // Filling event properties + rowEv.reserve(collisions.size()); + for (const auto& collision : collisions) { + fillEvent(collision, zPvCut); + } + + // Filling candidate properties + rowKfCandidate.reserve(candidates.size()); + for (const auto& candidate : candidates) { + fillCandidate(candidate, -7, -7, RecoDecay::OriginType::None, false); + } + } + + void processKfDataWithFT0C(MyEventTableWithFT0C const& collisions, MyTrackTable const&, + soa::Join const& candidates) + { + // Filling event properties + rowEv.reserve(collisions.size()); + for (const auto& collision : collisions) { + fillEvent(collision, zPvCut); + } + + // Filling candidate properties + rowKfCandidate.reserve(candidates.size()); + for (const auto& candidate : candidates) { + fillCandidate(candidate, -7, -7, RecoDecay::OriginType::None, false); + } + } + + void processKfDataWithNTracksPV(MyEventTableWithNTracksPV const& collisions, MyTrackTable const&, + soa::Join const& candidates) + { + // Filling event properties + rowEv.reserve(collisions.size()); + for (const auto& collision : collisions) { + fillEvent(collision, zPvCut); + } + + // Filling candidate properties + rowKfCandidate.reserve(candidates.size()); + for (const auto& candidate : candidates) { + fillCandidate(candidate, -7, -7, RecoDecay::OriginType::None, false); + } + } + + PROCESS_SWITCH(HfTreeCreatorToXiPiQa, processKfData, "Process KF data, no cent", false); + PROCESS_SWITCH(HfTreeCreatorToXiPiQa, processKfDataWithFT0M, "Process KF data, with FT0M", false); + PROCESS_SWITCH(HfTreeCreatorToXiPiQa, processKfDataWithFT0C, "Process KF data, with FT0C", false); + PROCESS_SWITCH(HfTreeCreatorToXiPiQa, processKfDataWithNTracksPV, "Process KF data, with NTracksPV", false); + + //*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*// + //*~~~~~~~MC with DCAFitter~~~~~~~~*// + //*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*// + + void processMcFullXic0(MyEventTable const& collisions, MyTrackTable const&, + soa::Join const& candidates) + { + // Filling event properties + rowEv.reserve(collisions.size()); + for (const auto& collision : collisions) { + fillEvent(collision, zPvCut); + } + + // Filling candidate properties + rowCandidateFull.reserve(candidates.size()); + for (const auto& candidate : candidates) { + fillCandidate(candidate, candidate.flagMcMatchRec(), candidate.debugMcRec(), candidate.originMcRec(), candidate.collisionMatched()); + } + } + + void processMcFullOmegac0(MyEventTable const& collisions, MyTrackTable const&, + soa::Join const& candidates) + { + // Filling event properties + rowEv.reserve(collisions.size()); + for (const auto& collision : collisions) { + fillEvent(collision, zPvCut); + } + + // Filling candidate properties + rowCandidateFull.reserve(candidates.size()); + for (const auto& candidate : candidates) { + fillCandidate(candidate, candidate.flagMcMatchRec(), candidate.debugMcRec(), candidate.originMcRec(), candidate.collisionMatched()); + } + } + + void processMcLiteXic0(MyEventTable const& collisions, MyTrackTable const&, + soa::Join const& candidates) + { + // Filling event properties + rowEv.reserve(collisions.size()); + for (const auto& collision : collisions) { + fillEvent(collision, zPvCut); + } + + // Filling candidate properties + rowCandidateLite.reserve(candidates.size()); + for (const auto& candidate : candidates) { + fillCandidate(candidate, candidate.flagMcMatchRec(), -7, candidate.originMcRec(), candidate.collisionMatched()); + } + } + + void processMcLiteXic0WithFT0C(MyEventTableWithFT0C const& collisions, MyTrackTable const&, + soa::Join const& candidates) + { + // Filling event properties + rowEv.reserve(collisions.size()); + for (const auto& collision : collisions) { + fillEvent(collision, zPvCut); + } + + // Filling candidate properties + rowCandidateLite.reserve(candidates.size()); + for (const auto& candidate : candidates) { + fillCandidate(candidate, candidate.flagMcMatchRec(), -7, candidate.originMcRec(), candidate.collisionMatched()); + } + } + + void processMcLiteXic0WithFT0M(MyEventTableWithFT0M const& collisions, MyTrackTable const&, + soa::Join const& candidates) + { + // Filling event properties + rowEv.reserve(collisions.size()); + for (const auto& collision : collisions) { + fillEvent(collision, zPvCut); + } + + // Filling candidate properties + rowCandidateLite.reserve(candidates.size()); + for (const auto& candidate : candidates) { + fillCandidate(candidate, candidate.flagMcMatchRec(), -7, candidate.originMcRec(), candidate.collisionMatched()); + } + } + + void processMcLiteXic0WithNTracksPV(MyEventTableWithNTracksPV const& collisions, MyTrackTable const&, + soa::Join const& candidates) + { + // Filling event properties + rowEv.reserve(collisions.size()); + for (const auto& collision : collisions) { + fillEvent(collision, zPvCut); + } + + // Filling candidate properties + rowCandidateLite.reserve(candidates.size()); + for (const auto& candidate : candidates) { + fillCandidate(candidate, candidate.flagMcMatchRec(), -7, candidate.originMcRec(), candidate.collisionMatched()); + } + } + + void processMcLiteOmegac0(MyEventTable const& collisions, MyTrackTable const&, + soa::Join const& candidates) + { + // Filling event properties + rowEv.reserve(collisions.size()); + for (const auto& collision : collisions) { + fillEvent(collision, zPvCut); + } + + // Filling candidate properties + rowCandidateLite.reserve(candidates.size()); + for (const auto& candidate : candidates) { + fillCandidate(candidate, candidate.flagMcMatchRec(), -7, candidate.originMcRec(), candidate.collisionMatched()); + } + } + + PROCESS_SWITCH(HfTreeCreatorToXiPiQa, processMcFullXic0, "Process MC with full information for xic0 w/o centrality", false); + PROCESS_SWITCH(HfTreeCreatorToXiPiQa, processMcFullOmegac0, "Process MC with full information for omegac0", false); + PROCESS_SWITCH(HfTreeCreatorToXiPiQa, processMcLiteXic0, "Process MC and produce lite table version for xic0", false); + PROCESS_SWITCH(HfTreeCreatorToXiPiQa, processMcLiteXic0WithFT0C, "Process MC and produce lite table version for Xic0 with FT0C", false); + PROCESS_SWITCH(HfTreeCreatorToXiPiQa, processMcLiteXic0WithFT0M, "Process MC and produce lite table version for Xic0 with FT0M", false); + PROCESS_SWITCH(HfTreeCreatorToXiPiQa, processMcLiteXic0WithNTracksPV, "Process MC and produce lite table version for Xic0 with NTracksPV", false); + PROCESS_SWITCH(HfTreeCreatorToXiPiQa, processMcLiteOmegac0, "Process MC and produce lite table version for omegac0", false); + + //*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*// + //*~~~~~~~MC with KFParticle~~~~~~~~*// + //*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*// + void processKfMcXic0(MyEventTable const& collisions, MyTrackTable const&, + soa::Join const& candidates) + { + // Filling event properties + rowEv.reserve(collisions.size()); + for (const auto& collision : collisions) { + fillEvent(collision, zPvCut); + } + + // Filling candidate properties + rowKfCandidate.reserve(candidates.size()); + for (const auto& candidate : candidates) { + fillCandidate(candidate, candidate.flagMcMatchRec(), candidate.debugMcRec(), candidate.originMcRec(), candidate.collisionMatched()); + } + } + + void processKfMcXic0WithFT0C(MyEventTableWithFT0C const& collisions, MyTrackTable const&, + soa::Join const& candidates) + { + // Filling event properties + rowEv.reserve(collisions.size()); + for (const auto& collision : collisions) { + fillEvent(collision, zPvCut); + } + + // Filling candidate properties + rowKfCandidate.reserve(candidates.size()); + for (const auto& candidate : candidates) { + fillCandidate(candidate, candidate.flagMcMatchRec(), candidate.debugMcRec(), candidate.originMcRec(), candidate.collisionMatched()); + } + } + + void processKfMcXic0WithFT0M(MyEventTableWithFT0M const& collisions, MyTrackTable const&, + soa::Join const& candidates) + { + // Filling event properties + rowEv.reserve(collisions.size()); + for (const auto& collision : collisions) { + fillEvent(collision, zPvCut); + } + + // Filling candidate properties + rowKfCandidate.reserve(candidates.size()); + for (const auto& candidate : candidates) { + fillCandidate(candidate, candidate.flagMcMatchRec(), candidate.debugMcRec(), candidate.originMcRec(), candidate.collisionMatched()); + } + } + + void processKfMcXic0WithNTracksPV(MyEventTableWithNTracksPV const& collisions, MyTrackTable const&, + soa::Join const& candidates) + { + // Filling event properties + rowEv.reserve(collisions.size()); + for (const auto& collision : collisions) { + fillEvent(collision, zPvCut); + } + + // Filling candidate table + rowKfCandidate.reserve(candidates.size()); + for (const auto& candidate : candidates) { + fillCandidate(candidate, candidate.flagMcMatchRec(), candidate.debugMcRec(), candidate.originMcRec(), candidate.collisionMatched()); + } + } + + PROCESS_SWITCH(HfTreeCreatorToXiPiQa, processKfMcXic0, "Process MC with information for xic0", false); + PROCESS_SWITCH(HfTreeCreatorToXiPiQa, processKfMcXic0WithFT0C, "Process MC with information for xic0 at FT0C", false); + PROCESS_SWITCH(HfTreeCreatorToXiPiQa, processKfMcXic0WithFT0M, "Process MC with information for xic0 at FT0M", false); + PROCESS_SWITCH(HfTreeCreatorToXiPiQa, processKfMcXic0WithNTracksPV, "Process MC with information for xic0 at Ntrack", false); +}; // end of struct + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} From 632997850b5324c5258e67662058e41dbbf1ad7e Mon Sep 17 00:00:00 2001 From: alicja-pp <101565842+alicja-pp@users.noreply.github.com> Date: Thu, 19 Mar 2026 15:05:12 +0100 Subject: [PATCH 333/347] [PWGCF] FemtoUniverse: Change range of deta-dphi histograms (#15451) --- .../Core/FemtoUniverseDetaDphiStar.h | 78 +++++++++---------- ...iversePairTaskTrackTrackMultKtExtended.cxx | 71 +++++++++++++++-- .../femtoUniversePairTaskTrackV0Extended.cxx | 56 +++++++++++-- 3 files changed, 156 insertions(+), 49 deletions(-) diff --git a/PWGCF/FemtoUniverse/Core/FemtoUniverseDetaDphiStar.h b/PWGCF/FemtoUniverse/Core/FemtoUniverseDetaDphiStar.h index c939a4f269d..3a7738b2cc1 100644 --- a/PWGCF/FemtoUniverse/Core/FemtoUniverseDetaDphiStar.h +++ b/PWGCF/FemtoUniverse/Core/FemtoUniverseDetaDphiStar.h @@ -66,31 +66,31 @@ class FemtoUniverseDetaDphiStar if constexpr (kPartOneType == o2::aod::femtouniverseparticle::ParticleType::kTrack && kPartTwoType == o2::aod::femtouniverseparticle::ParticleType::kTrack) { std::string dirName = static_cast(DirNames[0]); - histdetadpisame[0][0] = mHistogramRegistry->add((dirName + static_cast(HistNamesSame[0][0])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); - histdetadpisame[0][1] = mHistogramRegistry->add((dirName + static_cast(HistNamesSame[1][0])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); - histdetadpimixed[0][0] = mHistogramRegistry->add((dirName + static_cast(HistNamesMixed[0][0])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); - histdetadpimixed[0][1] = mHistogramRegistry->add((dirName + static_cast(HistNamesMixed[1][0])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); + histdetadpisame[0][0] = mHistogramRegistry->add((dirName + static_cast(HistNamesSame[0][0])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{200, -0.3, 0.3}, {200, -0.3, 0.3}}); + histdetadpisame[0][1] = mHistogramRegistry->add((dirName + static_cast(HistNamesSame[1][0])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{200, -0.3, 0.3}, {200, -0.3, 0.3}}); + histdetadpimixed[0][0] = mHistogramRegistry->add((dirName + static_cast(HistNamesMixed[0][0])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{200, -0.3, 0.3}, {200, -0.3, 0.3}}); + histdetadpimixed[0][1] = mHistogramRegistry->add((dirName + static_cast(HistNamesMixed[1][0])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{200, -0.3, 0.3}, {200, -0.3, 0.3}}); - histdetadpiqlcmssame = mHistogramRegistry->add((dirName + static_cast(HistNamesSame[1][7])).c_str(), "; #it{q}_{LCMS}; #Delta #eta; #Delta #phi", kTH3F, {{100, 0.0, 0.5}, {100, -0.15, 0.15}, {100, -0.15, 0.15}}); - histdetadpiqlcmsmixed = mHistogramRegistry->add((dirName + static_cast(HistNamesMixed[1][7])).c_str(), "; #it{q}_{LCMS}; #Delta #eta; #Delta #phi", kTH3F, {{100, 0.0, 0.5}, {100, -0.15, 0.15}, {100, -0.15, 0.15}}); + histdetadpiqlcmssame = mHistogramRegistry->add((dirName + static_cast(HistNamesSame[1][7])).c_str(), "; #it{q}_{LCMS}; #Delta #eta; #Delta #phi", kTH3F, {{100, 0.0, 0.5}, {200, -0.3, 0.3}, {200, -0.3, 0.3}}); + histdetadpiqlcmsmixed = mHistogramRegistry->add((dirName + static_cast(HistNamesMixed[1][7])).c_str(), "; #it{q}_{LCMS}; #Delta #eta; #Delta #phi", kTH3F, {{100, 0.0, 0.5}, {200, -0.3, 0.3}, {200, -0.3, 0.3}}); if (plotForEveryRadii) { for (int i = 0; i < 9; i++) { - histdetadpiRadii[0][i] = mHistogramRegistryQA->add((dirName + static_cast(HistNamesRadii[0][i])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); + histdetadpiRadii[0][i] = mHistogramRegistryQA->add((dirName + static_cast(HistNamesRadii[0][i])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{200, -0.3, 0.3}, {200, -0.3, 0.3}}); } } } if constexpr (kPartOneType == o2::aod::femtouniverseparticle::ParticleType::kTrack && kPartTwoType == o2::aod::femtouniverseparticle::ParticleType::kV0) { for (int i = 0; i < 2; i++) { std::string dirName = static_cast(DirNames[1]); - histdetadpisame[i][0] = mHistogramRegistry->add((dirName + static_cast(HistNamesSame[0][i])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); - histdetadpisame[i][1] = mHistogramRegistry->add((dirName + static_cast(HistNamesSame[1][i])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); - histdetadpimixed[i][0] = mHistogramRegistry->add((dirName + static_cast(HistNamesMixed[0][i])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); - histdetadpimixed[i][1] = mHistogramRegistry->add((dirName + static_cast(HistNamesMixed[1][i])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); + histdetadpisame[i][0] = mHistogramRegistry->add((dirName + static_cast(HistNamesSame[0][i])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{200, -0.3, 0.3}, {200, -0.3, 0.3}}); + histdetadpisame[i][1] = mHistogramRegistry->add((dirName + static_cast(HistNamesSame[1][i])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{200, -0.3, 0.3}, {200, -0.3, 0.3}}); + histdetadpimixed[i][0] = mHistogramRegistry->add((dirName + static_cast(HistNamesMixed[0][i])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{200, -0.3, 0.3}, {200, -0.3, 0.3}}); + histdetadpimixed[i][1] = mHistogramRegistry->add((dirName + static_cast(HistNamesMixed[1][i])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{200, -0.3, 0.3}, {200, -0.3, 0.3}}); if (plotForEveryRadii) { for (int j = 0; j < 9; j++) { - histdetadpiRadii[i][j] = mHistogramRegistryQA->add((dirName + static_cast(HistNamesRadii[i][j])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); + histdetadpiRadii[i][j] = mHistogramRegistryQA->add((dirName + static_cast(HistNamesRadii[i][j])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{200, -0.3, 0.3}, {200, -0.3, 0.3}}); } } } @@ -99,13 +99,13 @@ class FemtoUniverseDetaDphiStar /// V0-V0 combination for (int k = 0; k < 2; k++) { std::string dirName = static_cast(DirNames[2]); - histdetadpisame[k][0] = mHistogramRegistry->add((dirName + static_cast(HistNamesSame[0][k])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); - histdetadpisame[k][1] = mHistogramRegistry->add((dirName + static_cast(HistNamesSame[1][k])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); - histdetadpimixed[k][0] = mHistogramRegistry->add((dirName + static_cast(HistNamesMixed[0][k])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); - histdetadpimixed[k][1] = mHistogramRegistry->add((dirName + static_cast(HistNamesMixed[1][k])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); + histdetadpisame[k][0] = mHistogramRegistry->add((dirName + static_cast(HistNamesSame[0][k])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{200, -0.3, 0.3}, {200, -0.3, 0.3}}); + histdetadpisame[k][1] = mHistogramRegistry->add((dirName + static_cast(HistNamesSame[1][k])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{200, -0.3, 0.3}, {200, -0.3, 0.3}}); + histdetadpimixed[k][0] = mHistogramRegistry->add((dirName + static_cast(HistNamesMixed[0][k])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{200, -0.3, 0.3}, {200, -0.3, 0.3}}); + histdetadpimixed[k][1] = mHistogramRegistry->add((dirName + static_cast(HistNamesMixed[1][k])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{200, -0.3, 0.3}, {200, -0.3, 0.3}}); if (plotForEveryRadii) { for (int l = 0; l < 9; l++) { - histdetadpiRadii[k][l] = mHistogramRegistryQA->add((dirName + static_cast(HistNamesRadii[k][l])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); + histdetadpiRadii[k][l] = mHistogramRegistryQA->add((dirName + static_cast(HistNamesRadii[k][l])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{200, -0.3, 0.3}, {200, -0.3, 0.3}}); } } } @@ -114,13 +114,13 @@ class FemtoUniverseDetaDphiStar /// Cascade-Cascade combination for (int k = 0; k < 7; k++) { std::string dirName = static_cast(DirNames[5]); - histdetadpisame[k][0] = mHistogramRegistry->add((dirName + static_cast(HistNamesSame[0][k])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); - histdetadpisame[k][1] = mHistogramRegistry->add((dirName + static_cast(HistNamesSame[1][k])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); - histdetadpimixed[k][0] = mHistogramRegistry->add((dirName + static_cast(HistNamesMixed[0][k])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); - histdetadpimixed[k][1] = mHistogramRegistry->add((dirName + static_cast(HistNamesMixed[1][k])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); + histdetadpisame[k][0] = mHistogramRegistry->add((dirName + static_cast(HistNamesSame[0][k])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{200, -0.3, 0.3}, {200, -0.3, 0.3}}); + histdetadpisame[k][1] = mHistogramRegistry->add((dirName + static_cast(HistNamesSame[1][k])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{200, -0.3, 0.3}, {200, -0.3, 0.3}}); + histdetadpimixed[k][0] = mHistogramRegistry->add((dirName + static_cast(HistNamesMixed[0][k])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{200, -0.3, 0.3}, {200, -0.3, 0.3}}); + histdetadpimixed[k][1] = mHistogramRegistry->add((dirName + static_cast(HistNamesMixed[1][k])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{200, -0.3, 0.3}, {200, -0.3, 0.3}}); if (plotForEveryRadii) { for (int l = 0; l < 9; l++) { - histdetadpiRadii[k][l] = mHistogramRegistryQA->add((dirName + static_cast(HistNamesRadii[k][l])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); + histdetadpiRadii[k][l] = mHistogramRegistryQA->add((dirName + static_cast(HistNamesRadii[k][l])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{200, -0.3, 0.3}, {200, -0.3, 0.3}}); } } } @@ -129,13 +129,13 @@ class FemtoUniverseDetaDphiStar /// Track-Cascade combination for (int k = 0; k < 3; k++) { std::string dirName = static_cast(DirNames[6]); - histdetadpisame[k][0] = mHistogramRegistry->add((dirName + static_cast(HistNamesSame[0][k])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); - histdetadpisame[k][1] = mHistogramRegistry->add((dirName + static_cast(HistNamesSame[1][k])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); - histdetadpimixed[k][0] = mHistogramRegistry->add((dirName + static_cast(HistNamesMixed[0][k])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); - histdetadpimixed[k][1] = mHistogramRegistry->add((dirName + static_cast(HistNamesMixed[1][k])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); + histdetadpisame[k][0] = mHistogramRegistry->add((dirName + static_cast(HistNamesSame[0][k])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{200, -0.3, 0.3}, {200, -0.3, 0.3}}); + histdetadpisame[k][1] = mHistogramRegistry->add((dirName + static_cast(HistNamesSame[1][k])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{200, -0.3, 0.3}, {200, -0.3, 0.3}}); + histdetadpimixed[k][0] = mHistogramRegistry->add((dirName + static_cast(HistNamesMixed[0][k])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{200, -0.3, 0.3}, {200, -0.3, 0.3}}); + histdetadpimixed[k][1] = mHistogramRegistry->add((dirName + static_cast(HistNamesMixed[1][k])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{200, -0.3, 0.3}, {200, -0.3, 0.3}}); if (plotForEveryRadii) { for (int l = 0; l < 9; l++) { - histdetadpiRadii[k][l] = mHistogramRegistryQA->add((dirName + static_cast(HistNamesRadii[k][l])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); + histdetadpiRadii[k][l] = mHistogramRegistryQA->add((dirName + static_cast(HistNamesRadii[k][l])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{200, -0.3, 0.3}, {200, -0.3, 0.3}}); } } } @@ -144,13 +144,13 @@ class FemtoUniverseDetaDphiStar /// V0-Cascade combination for (int k = 0; k < 3; k++) { std::string dirName = static_cast(DirNames[7]); - histdetadpisame[k][0] = mHistogramRegistry->add((dirName + static_cast(HistNamesSame[0][k])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); - histdetadpisame[k][1] = mHistogramRegistry->add((dirName + static_cast(HistNamesSame[1][k])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); - histdetadpimixed[k][0] = mHistogramRegistry->add((dirName + static_cast(HistNamesMixed[0][k])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); - histdetadpimixed[k][1] = mHistogramRegistry->add((dirName + static_cast(HistNamesMixed[1][k])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); + histdetadpisame[k][0] = mHistogramRegistry->add((dirName + static_cast(HistNamesSame[0][k])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{200, -0.3, 0.3}, {200, -0.3, 0.3}}); + histdetadpisame[k][1] = mHistogramRegistry->add((dirName + static_cast(HistNamesSame[1][k])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{200, -0.3, 0.3}, {200, -0.3, 0.3}}); + histdetadpimixed[k][0] = mHistogramRegistry->add((dirName + static_cast(HistNamesMixed[0][k])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{200, -0.3, 0.3}, {200, -0.3, 0.3}}); + histdetadpimixed[k][1] = mHistogramRegistry->add((dirName + static_cast(HistNamesMixed[1][k])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{200, -0.3, 0.3}, {200, -0.3, 0.3}}); if (plotForEveryRadii) { for (int l = 0; l < 9; l++) { - histdetadpiRadii[k][l] = mHistogramRegistryQA->add((dirName + static_cast(HistNamesRadii[k][l])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); + histdetadpiRadii[k][l] = mHistogramRegistryQA->add((dirName + static_cast(HistNamesRadii[k][l])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{200, -0.3, 0.3}, {200, -0.3, 0.3}}); } } } @@ -165,7 +165,7 @@ class FemtoUniverseDetaDphiStar if (plotForEveryRadii) { for (int j = 0; j < 9; j++) { - histdetadpiRadii[i][j] = mHistogramRegistryQA->add((dirName + static_cast(HistNamesRadii[i][j])).c_str(), "; #Delta #eta; #Delta #varphi*", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); + histdetadpiRadii[i][j] = mHistogramRegistryQA->add((dirName + static_cast(HistNamesRadii[i][j])).c_str(), "; #Delta #eta; #Delta #varphi*", kTH2F, {{200, -0.3, 0.3}, {200, -0.3, 0.3}}); } } } @@ -173,14 +173,14 @@ class FemtoUniverseDetaDphiStar if constexpr (kPartOneType == o2::aod::femtouniverseparticle::ParticleType::kTrack && kPartTwoType == o2::aod::femtouniverseparticle::ParticleType::kD0) { for (int i = 0; i < 2; i++) { std::string dirName = static_cast(DirNames[4]); - histdetadpisame[i][0] = mHistogramRegistry->add((dirName + static_cast(HistNamesSame[0][i])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); - histdetadpisame[i][1] = mHistogramRegistry->add((dirName + static_cast(HistNamesSame[1][i])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); - histdetadpimixed[i][0] = mHistogramRegistry->add((dirName + static_cast(HistNamesMixed[0][i])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); - histdetadpimixed[i][1] = mHistogramRegistry->add((dirName + static_cast(HistNamesMixed[1][i])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); + histdetadpisame[i][0] = mHistogramRegistry->add((dirName + static_cast(HistNamesSame[0][i])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{200, -0.3, 0.3}, {200, -0.3, 0.3}}); + histdetadpisame[i][1] = mHistogramRegistry->add((dirName + static_cast(HistNamesSame[1][i])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{200, -0.3, 0.3}, {200, -0.3, 0.3}}); + histdetadpimixed[i][0] = mHistogramRegistry->add((dirName + static_cast(HistNamesMixed[0][i])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{200, -0.3, 0.3}, {200, -0.3, 0.3}}); + histdetadpimixed[i][1] = mHistogramRegistry->add((dirName + static_cast(HistNamesMixed[1][i])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{200, -0.3, 0.3}, {200, -0.3, 0.3}}); if (plotForEveryRadii) { for (int j = 0; j < 9; j++) { - histdetadpiRadii[i][j] = mHistogramRegistryQA->add((dirName + static_cast(HistNamesRadii[i][j])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); + histdetadpiRadii[i][j] = mHistogramRegistryQA->add((dirName + static_cast(HistNamesRadii[i][j])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{200, -0.3, 0.3}, {200, -0.3, 0.3}}); } } } @@ -207,7 +207,7 @@ class FemtoUniverseDetaDphiStar histdetadphisamebeforekT[j] = mHistogramRegistry->add((dirName + histFolderkT + "detadphidetadphiBeforeSame").c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); histdetadphimixedbeforekT[j] = mHistogramRegistry->add((dirName + histFolderkT + "detadphidetadphiBeforeMixed").c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); histdetadphisameafterkT[j] = mHistogramRegistry->add((dirName + histFolderkT + "detadphidetadphiAfterSame").c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); - histdetadphimixedafterkT[j] = mHistogramRegistry->add((dirName + histFolderkT + "detadphidetadphiAfterMixed").c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); + histdetadphimixedafterkT[j] = mHistogramRegistry->add((dirName + histFolderkT + "detadphidetadphiAfterMixed").c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {200, -0.3, 0.3}}); } } } diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackMultKtExtended.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackMultKtExtended.cxx index 76a3c989494..2fc0a3543b9 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackMultKtExtended.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackMultKtExtended.cxx @@ -34,6 +34,8 @@ #include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/PID.h" +#include "TRandom2.h" + #include #include @@ -173,7 +175,8 @@ struct FemtoUniversePairTaskTrackTrackMultKtExtended { Configurable confCPRdeltaPhiCutMin{"confCPRdeltaPhiCutMin", 0.0, "Delta Phi min cut for Close Pair Rejection"}; Configurable confCPRdeltaEtaCutMax{"confCPRdeltaEtaCutMax", 0.0, "Delta Eta max cut for Close Pair Rejection"}; Configurable confCPRdeltaEtaCutMin{"confCPRdeltaEtaCutMin", 0.0, "Delta Eta min cut for Close Pair Rejection"}; - Configurable confCPRChosenRadii{"confCPRChosenRadii", 0.80, "Delta Eta cut for Close Pair Rejection"}; + Configurable confCPRChosenRadii{"confCPRChosenRadii", 0.80, "Chosen CPR radii"}; + Configurable confRandomizeCPR{"confRandomizeCPR", false, "Fill Dete-Dphi histograms in random order: p1, p2 or p2, p1"}; Configurable isPairIdentical{"isPairIdentical", true, "'true' for identical particles, 'false' for non-identical particles"}; struct : o2::framework::ConfigurableGroup { @@ -230,6 +233,8 @@ struct FemtoUniversePairTaskTrackTrackMultKtExtended { HistogramRegistry sphericityRegistry{"SphericityHisto", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + TRandom2* randgen; + /// TPC Pion/Kaon/Proton Sigma selection (general) bool isNSigma(float mom, float nsigmaTPC, float nsigmaTOF) { @@ -473,7 +478,21 @@ struct FemtoUniversePairTaskTrackTrackMultKtExtended { } if (confIsCPR.value) { - if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla, femto_universe_container::EventType::same)) { + double rand; + auto part1 = p1; + auto part2 = p2; + + if (confRandomizeCPR) { + randgen = new TRandom2(0); + rand = randgen->Rndm(); + + if (rand > 0.5) { + part1 = p2; + part2 = p1; + } + delete randgen; + } + if (pairCloseRejection.isClosePair(part1, part2, parts, magFieldTesla, femto_universe_container::EventType::same)) { continue; } } @@ -503,7 +522,21 @@ struct FemtoUniversePairTaskTrackTrackMultKtExtended { } if (confIsCPR.value) { - if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla, femto_universe_container::EventType::same)) { + double rand; + auto part1 = p1; + auto part2 = p2; + + if (confRandomizeCPR) { + randgen = new TRandom2(0); + rand = randgen->Rndm(); + + if (rand > 0.5) { + part1 = p2; + part2 = p1; + } + delete randgen; + } + if (pairCloseRejection.isClosePair(part1, part2, parts, magFieldTesla, femto_universe_container::EventType::same)) { continue; } } @@ -638,7 +671,21 @@ struct FemtoUniversePairTaskTrackTrackMultKtExtended { } if (confIsCPR.value) { - if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla, femto_universe_container::EventType::mixed)) { + double rand; + auto part1 = p1; + auto part2 = p2; + + if (confRandomizeCPR) { + randgen = new TRandom2(0); + rand = randgen->Rndm(); + + if (rand > 0.5) { + part1 = p2; + part2 = p1; + } + delete randgen; + } + if (pairCloseRejection.isClosePair(part1, part2, parts, magFieldTesla, femto_universe_container::EventType::mixed)) { continue; } } @@ -799,7 +846,21 @@ struct FemtoUniversePairTaskTrackTrackMultKtExtended { } if (confIsCPR.value) { - if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla, femto_universe_container::EventType::mixed)) { + double rand; + auto part1 = p1; + auto part2 = p2; + + if (confRandomizeCPR) { + randgen = new TRandom2(0); + rand = randgen->Rndm(); + + if (rand > 0.5) { + part1 = p2; + part2 = p1; + } + delete randgen; + } + if (pairCloseRejection.isClosePair(part1, part2, parts, magFieldTesla, femto_universe_container::EventType::mixed)) { return; } } diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx index ea63c9cc86b..b49b9b98119 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx @@ -29,6 +29,7 @@ #include "Framework/O2DatabasePDGPlugin.h" #include "Framework/runDataProcessing.h" +#include "TRandom2.h" #include #include #include @@ -174,6 +175,7 @@ struct FemtoUniversePairTaskTrackV0Extended { Configurable confCPRdeltaEtaCutMax{"confCPRdeltaEtaCutMax", 0.0, "Delta Eta max cut for Close Pair Rejection"}; Configurable confCPRdeltaEtaCutMin{"confCPRdeltaEtaCutMin", 0.0, "Delta Eta min cut for Close Pair Rejection"}; Configurable confCPRChosenRadii{"confCPRChosenRadii", 0.80, "Delta Eta cut for Close Pair Rejection"}; + Configurable confRandomizeCPR{"confRandomizeCPR", false, "Fill Dete-Dphi histograms in random order: v01, v02 or v02, v01 - does not apply to track-V0"}; } ConfCPR; // Efficiency @@ -204,6 +206,8 @@ struct FemtoUniversePairTaskTrackV0Extended { std::unique_ptr pEffHistp2; Service ccdb; + TRandom2* randgen; + bool isNSigmaCombined(float mom, float nsigmaTPCParticle, float nsigmaTOFParticle, bool hasTOF) { if (mom <= confmom || hasTOF == 0) { @@ -741,9 +745,23 @@ struct FemtoUniversePairTaskTrackV0Extended { } if (ConfCPR.confIsCPR.value) { - if (ConfCPR.confRectV0V0CPR && pairCloseRejectionV0.isClosePair(p1, p2, parts, magFieldTesla, femto_universe_container::EventType::same)) { + double rand; + auto part1 = p1; + auto part2 = p2; + + if (ConfCPR.confRandomizeCPR) { + randgen = new TRandom2(0); + rand = randgen->Rndm(); + + if (rand > 0.5) { + part1 = p2; + part2 = p1; + } + delete randgen; + } + if (ConfCPR.confRectV0V0CPR && pairCloseRejectionV0.isClosePair(part1, part2, parts, magFieldTesla, femto_universe_container::EventType::same)) { return false; - } else if (!ConfCPR.confRectV0V0CPR && pairCloseRejectionV0.isClosePair(p1, p2, parts, magFieldTesla, femto_universe_container::EventType::same)) { + } else if (!ConfCPR.confRectV0V0CPR && pairCloseRejectionV0.isClosePair(part1, part2, parts, magFieldTesla, femto_universe_container::EventType::same)) { return false; } } @@ -1119,9 +1137,23 @@ struct FemtoUniversePairTaskTrackV0Extended { continue; } if (ConfCPR.confIsCPR.value) { - if (ConfCPR.confRectV0V0CPR && pairCloseRejectionV0.isClosePair(p1, p2, parts, magFieldTesla1, femto_universe_container::EventType::mixed)) { + double rand; + auto part1 = p1; + auto part2 = p2; + + if (ConfCPR.confRandomizeCPR) { + randgen = new TRandom2(0); + rand = randgen->Rndm(); + + if (rand > 0.5) { + part1 = p2; + part2 = p1; + } + delete randgen; + } + if (ConfCPR.confRectV0V0CPR && pairCloseRejectionV0.isClosePair(part1, part2, parts, magFieldTesla1, femto_universe_container::EventType::mixed)) { continue; - } else if (!ConfCPR.confRectV0V0CPR && pairCloseRejectionV0.isClosePair(p1, p2, parts, magFieldTesla1, femto_universe_container::EventType::mixed)) { + } else if (!ConfCPR.confRectV0V0CPR && pairCloseRejectionV0.isClosePair(part1, part2, parts, magFieldTesla1, femto_universe_container::EventType::mixed)) { continue; } } @@ -1447,7 +1479,21 @@ struct FemtoUniversePairTaskTrackV0Extended { continue; } if (ConfCPR.confIsCPR.value) { - if (pairCloseRejectionV0.isClosePair(p1, p2, parts, magFieldTesla1, femto_universe_container::EventType::mixed)) { + double rand; + auto part1 = p1; + auto part2 = p2; + + if (ConfCPR.confRandomizeCPR) { + randgen = new TRandom2(0); + rand = randgen->Rndm(); + + if (rand > 0.5) { + part1 = p2; + part2 = p1; + } + delete randgen; + } + if (pairCloseRejectionV0.isClosePair(part1, part2, parts, magFieldTesla1, femto_universe_container::EventType::mixed)) { continue; } } From c104f7adc91008d9fba856735cb077faab89f81a Mon Sep 17 00:00:00 2001 From: Martijn Laarhoven <94106121+MartijnLaarhoven@users.noreply.github.com> Date: Thu, 19 Mar 2026 16:57:29 +0100 Subject: [PATCH 334/347] [PWGCF] Adding the ultra long range correlations to eta dependent studies (#15313) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../Tasks/flowDecorrelation.cxx | 183 +++++++++++++++++- 1 file changed, 180 insertions(+), 3 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/flowDecorrelation.cxx b/PWGCF/TwoParticleCorrelations/Tasks/flowDecorrelation.cxx index 61eb715a0a1..a2b7422f9f4 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/flowDecorrelation.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/flowDecorrelation.cxx @@ -144,8 +144,9 @@ struct FlowDecorrelation { ConfigurableAxis axisDeltaPhi{"axisDeltaPhi", {72, -PIHalf, PIHalf * 3}, "delta phi axis for histograms"}; ConfigurableAxis axisDeltaEtaTpcFt0a{"axisDeltaEtaTpcFt0a", {32, -5.8, -2.6}, "delta eta axis, -5.8~-2.6 for TPC-FT0A,"}; ConfigurableAxis axisDeltaEtaTpcFt0c{"axisDeltaEtaTpcFt0c", {32, 1.2, 4.2}, "delta eta axis, 1.2~4.2 for TPC-FT0C"}; + ConfigurableAxis axisDeltaEtaFt0aFt0c{"axisDeltaEtaFt0aFt0c", {32, 4.2, 8.2}, "delta eta axis, 4.2~8.2 for FT0A-FT0C"}; ConfigurableAxis axisDeltaEtaTpcMft{"axisDeltaEtaTpcMft", {32, 1.3, 4.8}, "delta eta axis, 1.3~4.8 for TPC-MFT"}; - ConfigurableAxis axisDeltaEtaTpcFv0{"axisDeltaEtaTpcFv0", {32, -6.1, -1.2}, "delta eta axis for TPC-FV0 histograms"}; + ConfigurableAxis axisDeltaEtaTpcFv0{"axisDeltaEtaTpcFv0", {32, -1.2, -6.1}, "delta eta axis for TPC-FV0 histograms"}; ConfigurableAxis axisEtaTrigger{"axisEtaTrigger", {VARIABLE_WIDTH, -3.3, -2.1, -0.8, -0.6, -0.4, -0.2, 0, 0.2, 0.4, 0.6, 0.8, 3.5, 4.9}, "eta trigger axis for histograms"}; ConfigurableAxis axisEtaAssoc{"axisEtaAssoc", {VARIABLE_WIDTH, -3.3, -2.1, -0.8, -0.6, -0.4, -0.2, 0, 0.2, 0.4, 0.6, 0.8, 3.5, 4.9}, "eta associated axis for histograms"}; ConfigurableAxis axisVtxMix{"axisVtxMix", {VARIABLE_WIDTH, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "vertex axis for mixed event histograms"}; @@ -250,7 +251,7 @@ struct FlowDecorrelation { LOGF(info, "Starting init"); // Event Counter - if ((doprocessSameTpcFt0a || doprocessSameTpcFt0c || doprocessSameTpcMft || doprocessSameTpcFv0) && cfgUseAdditionalEventCut) { + if ((doprocessSameTpcFt0a || doprocessSameTpcFt0c || doprocessSameFt0aFt0c || doprocessSameTpcMft || doprocessSameTpcFv0) && cfgUseAdditionalEventCut) { registry.add("hEventCountSpecific", "Number of Event;; Count", {HistType::kTH1D, {{12, 0, 12}}}); registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(1, "after sel8"); registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(2, "kNoSameBunchPileup"); @@ -299,7 +300,7 @@ struct FlowDecorrelation { std::string hCentTitle = "Centrality distribution, Estimator " + std::to_string(cfgCentEstimator); // Make histograms to check the distributions after cuts - if (doprocessSameTpcFt0a || doprocessSameTpcFt0c || doprocessSameTpcMft || doprocessSameTpcFv0) { + if (doprocessSameTpcFt0a || doprocessSameTpcFt0c || doprocessSameFt0aFt0c || doprocessSameTpcMft || doprocessSameTpcFv0) { registry.add("Phi", "Phi", {HistType::kTH1D, {axisPhi}}); registry.add("Eta", "Eta", {HistType::kTH1D, {axisEta}}); registry.add("EtaCorrected", "EtaCorrected", {HistType::kTH1D, {axisEta}}); @@ -332,6 +333,13 @@ struct FlowDecorrelation { registry.add("Assoc_amp_mixed_TPC_FT0C", "", {HistType::kTH2D, {axisChannelFt0aAxis, axisAmplitudeFt0a}}); registry.add("Trig_hist_TPC_FT0C", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisEtaTrigger}}}); } + if (doprocessSameFt0aFt0c) { + registry.add("deltaEta_deltaPhi_same_FT0A_FT0C", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaFt0aFt0c}}); // check to see the delta eta and delta phi distribution + registry.add("deltaEta_deltaPhi_mixed_FT0A_FT0C", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaFt0aFt0c}}); + registry.add("Assoc_amp_same_FT0A_FT0C", "", {HistType::kTH2D, {axisChannelFt0aAxis, axisAmplitudeFt0a}}); + registry.add("Assoc_amp_mixed_FT0A_FT0C", "", {HistType::kTH2D, {axisChannelFt0aAxis, axisAmplitudeFt0a}}); + registry.add("Trig_hist_FT0A_FT0C", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisEtaTrigger}}}); + } if (doprocessSameTpcMft) { registry.add("deltaEta_deltaPhi_same_TPC_MFT", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaTpcMft}}); // check to see the delta eta and delta phi distribution registry.add("deltaEta_deltaPhi_mixed_TPC_MFT", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaTpcMft}}); @@ -370,6 +378,13 @@ struct FlowDecorrelation { {axisDeltaPhi, "#Delta#varphi (rad)"}, {axisDeltaEtaTpcFt0c, "#Delta#eta"}}; + std::vector corrAxisFt0aFt0c = {{axisSample, "Sample"}, + {axisVertex, "z-vtx (cm)"}, + {axisEtaTrigger, "#eta"}, + {axisEtaAssoc, "#eta"}, + {axisDeltaPhi, "#Delta#varphi (rad)"}, + {axisDeltaEtaFt0aFt0c, "#Delta#eta"}}; + std::vector corrAxisTpcMft = {{axisSample, "Sample"}, {axisVertex, "z-vtx (cm)"}, {axisEtaTrigger, "#eta"}, @@ -392,6 +407,10 @@ struct FlowDecorrelation { same.setObject(new CorrelationContainer("sameEvent_TPC_FT0C", "sameEvent_TPC_FT0C", corrAxisTpcFt0c, effAxis, userAxis)); mixed.setObject(new CorrelationContainer("mixedEvent_TPC_FT0C", "mixedEvent_TPC_FT0C", corrAxisTpcFt0c, effAxis, userAxis)); } + if (doprocessSameFt0aFt0c) { + same.setObject(new CorrelationContainer("sameEvent_FT0A_FT0C", "sameEvent_FT0A_FT0C", corrAxisFt0aFt0c, effAxis, userAxis)); + mixed.setObject(new CorrelationContainer("mixedEvent_FT0A_FT0C", "mixedEvent_FT0A_FT0C", corrAxisFt0aFt0c, effAxis, userAxis)); + } if (doprocessSameTpcMft) { same.setObject(new CorrelationContainer("sameEvent_TPC_MFT", "sameEvent_TPC_MFT", corrAxisTpcMft, effAxis, userAxis)); mixed.setObject(new CorrelationContainer("mixedEvent_TPC_MFT", "mixedEvent_TPC_MFT", corrAxisTpcMft, effAxis, userAxis)); @@ -750,6 +769,60 @@ struct FlowDecorrelation { } } + template + void fillCorrelationsFT0AFT0C(TFT0s const& ft0Trig, TFT0s const& ft0Assoc, float posZ, int multTrk, int system, float cent, float eventWeight) + { + if (system == SameEvent) { + if (!cfgCentTableUnavailable) + registry.fill(HIST("Centrality_used"), cent); + registry.fill(HIST("Nch_used"), multTrk); + } + + int fSampleIndex = gRandom->Uniform(0, cfgSampleSize); + + for (std::size_t iChA = 0; iChA < ft0Trig.channelA().size(); iChA++) { + int channelIdA = 0; + float amplA = 0.f; + getChannel(ft0Trig, iChA, channelIdA, amplA, kFT0A); + if ((cfgRejectFT0AInside && (channelIdA >= kFT0AInnerRingMin && channelIdA <= kFT0AInnerRingMax)) || (cfgRejectFT0AOutside && (channelIdA >= kFT0AOuterRingMin && channelIdA <= kFT0AOuterRingMax))) { + continue; + } + + const double phiA = getPhiFT0(channelIdA, kFT0A); + const double etaA = getEtaFT0(channelIdA, kFT0A); + + if (system == SameEvent) { + registry.fill(HIST("Trig_hist_FT0A_FT0C"), fSampleIndex, posZ, etaA, eventWeight * amplA); + } + + for (std::size_t iChC = 0; iChC < ft0Assoc.channelC().size(); iChC++) { + int channelIdC = 0; + float amplC = 0.f; + getChannel(ft0Assoc, iChC, channelIdC, amplC, kFT0C); + if ((cfgRejectFT0CInside && (channelIdC >= kFT0CInnerRingMin && channelIdC <= kFT0CInnerRingMax)) || (cfgRejectFT0COutside && (channelIdC >= kFT0COuterRingMin && channelIdC <= kFT0COuterRingMax))) { + continue; + } + + const double phiC = getPhiFT0(channelIdC, kFT0C); + const double etaC = getEtaFT0(channelIdC, kFT0C); + + const float deltaPhi = RecoDecay::constrainAngle(phiA - phiC, -PIHalf); + const float deltaEta = etaA - etaC; + const float pairWeight = amplA * amplC * eventWeight; + + if (system == SameEvent) { + registry.fill(HIST("Assoc_amp_same_FT0A_FT0C"), channelIdC, amplC); + same->getPairHist()->Fill(step, fSampleIndex, posZ, etaA, etaC, deltaPhi, deltaEta, pairWeight); + registry.fill(HIST("deltaEta_deltaPhi_same_FT0A_FT0C"), deltaPhi, deltaEta, pairWeight); + } else if (system == MixedEvent) { + registry.fill(HIST("Assoc_amp_mixed_FT0A_FT0C"), channelIdC, amplC); + mixed->getPairHist()->Fill(step, fSampleIndex, posZ, etaA, etaC, deltaPhi, deltaEta, pairWeight); + registry.fill(HIST("deltaEta_deltaPhi_mixed_FT0A_FT0C"), deltaPhi, deltaEta, pairWeight); + } + } + } + } + template void fillCorrelationsTPCFV0(TTracks tracks1, TFT0s const& fv0, float posZ, int system, float cent, float eventWeight) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms { @@ -1112,6 +1185,110 @@ struct FlowDecorrelation { } PROCESS_SWITCH(FlowDecorrelation, processMixedTpcFt0c, "Process mixed events for TPC-FT0C correlation", false); + void processSameFt0aFt0c(FilteredCollisions::iterator const& collision, FilteredTracks const& tracks, aod::FT0s const&, aod::BCsWithTimestamps const&) + { + if (!collision.sel8()) + return; + auto bc = collision.bc_as(); + float cent = -1.; + float weightCent = 1.0f; + if (!cfgCentTableUnavailable) { + cent = getCentrality(collision); + } + if (cfgUseAdditionalEventCut && !eventSelected(collision, tracks.size(), cent, true)) + return; + if (!collision.has_foundFT0()) + return; + loadAlignParam(bc.timestamp()); + loadGain(bc); + loadCorrection(bc.timestamp()); + if (!cfgCentTableUnavailable) { + getCentralityWeight(weightCent, cent); + registry.fill(HIST("Centrality"), cent); + registry.fill(HIST("CentralityWeighted"), cent, weightCent); + } + registry.fill(HIST("Nch"), tracks.size()); + registry.fill(HIST("zVtx"), collision.posZ()); + + if (cfgSelCollByNch && (tracks.size() < cfgCutMultMin || tracks.size() >= cfgCutMultMax)) { + return; + } + if (!cfgSelCollByNch && !cfgCentTableUnavailable && (cent < cfgCutCentMin || cent >= cfgCutCentMax)) { + return; + } + + registry.fill(HIST("eventcount"), SameEvent); + + same->fillEvent(tracks.size(), CorrelationContainer::kCFStepReconstructed); + const auto& ft0 = collision.foundFT0(); + fillCorrelationsFT0AFT0C(ft0, ft0, collision.posZ(), tracks.size(), SameEvent, cent, weightCent); + } + PROCESS_SWITCH(FlowDecorrelation, processSameFt0aFt0c, "Process same event for FT0A-FT0C correlation", false); + + void processMixedFt0aFt0c(FilteredCollisions const& collisions, FilteredTracks const& tracks, aod::FT0s const&, aod::BCsWithTimestamps const&) + { + auto getTracksSize = [&tracks, this](FilteredCollisions::iterator const& collision) { + auto associatedTracks = tracks.sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), this->cache); + auto mult = associatedTracks.size(); + return mult; + }; + + using MixedBinning = FlexibleBinningPolicy, aod::collision::PosZ, decltype(getTracksSize)>; + + MixedBinning binningOnVtxAndMult{{getTracksSize}, {axisVtxMix, axisMultMix}, true}; + + auto tracksTuple = std::make_tuple(tracks, tracks); + Pair pairs{binningOnVtxAndMult, cfgMixEventNumMin, -1, collisions, tracksTuple, &cache}; + for (auto it = pairs.begin(); it != pairs.end(); it++) { + auto& [collision1, tracks1, collision2, tracks2] = *it; + if (!collision1.sel8() || !collision2.sel8()) + continue; + + if (cfgSelCollByNch && (tracks1.size() < cfgCutMultMin || tracks1.size() >= cfgCutMultMax)) + continue; + + if (cfgSelCollByNch && (tracks2.size() < cfgCutMultMin || tracks2.size() >= cfgCutMultMax)) + continue; + + float cent1 = -1; + float cent2 = -1; + if (!cfgCentTableUnavailable) { + cent1 = getCentrality(collision1); + cent2 = getCentrality(collision2); + } + if (cfgUseAdditionalEventCut && !eventSelected(collision1, tracks1.size(), cent1, false)) + continue; + if (cfgUseAdditionalEventCut && !eventSelected(collision2, tracks2.size(), cent2, false)) + continue; + + if (!cfgSelCollByNch && !cfgCentTableUnavailable && (cent1 < cfgCutCentMin || cent1 >= cfgCutCentMax)) + continue; + + if (!cfgSelCollByNch && !cfgCentTableUnavailable && (cent2 < cfgCutCentMin || cent2 >= cfgCutCentMax)) + continue; + + if (!(collision1.has_foundFT0() && collision2.has_foundFT0())) + continue; + + registry.fill(HIST("eventcount"), MixedEvent); + auto bc = collision1.bc_as(); + loadAlignParam(bc.timestamp()); + loadCorrection(bc.timestamp()); + loadGain(bc); + float eventWeight = 1.0f; + if (cfgUseEventWeights) { + eventWeight = 1.0f / it.currentWindowNeighbours(); + } + float weightCent = 1.0f; + if (!cfgCentTableUnavailable) + getCentralityWeight(weightCent, cent1); + const auto& ft0Trig = collision1.foundFT0(); + const auto& ft0Assoc = collision2.foundFT0(); + fillCorrelationsFT0AFT0C(ft0Trig, ft0Assoc, collision1.posZ(), tracks1.size(), MixedEvent, cent1, eventWeight * weightCent); + } + } + PROCESS_SWITCH(FlowDecorrelation, processMixedFt0aFt0c, "Process mixed events for FT0A-FT0C correlation", false); + template void fillCorrelationsTPCMFT(TTracks tracks1, TTracksAssoc tracks2, float posZ, int system, float cent, float eventWeight) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms { From ed92f9f56c528d2e18e0a13cfcddc37a290b2222 Mon Sep 17 00:00:00 2001 From: Martijn Laarhoven <94106121+MartijnLaarhoven@users.noreply.github.com> Date: Thu, 19 Mar 2026 16:59:07 +0100 Subject: [PATCH 335/347] [PWGCF] Adding the option to only cut ITS layer 0-3 (#15439) --- .../Tasks/longRangeDihadronCor.cxx | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/longRangeDihadronCor.cxx b/PWGCF/TwoParticleCorrelations/Tasks/longRangeDihadronCor.cxx index f50d8f15e6c..b95075d694e 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/longRangeDihadronCor.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/longRangeDihadronCor.cxx @@ -98,6 +98,7 @@ struct LongRangeDihadronCor { O2_DEFINE_CONFIGURABLE(cfgEvSelkIsGoodZvtxFT0vsPV, bool, false, "removes collisions with large differences between z of PV by tracks and z of PV from FT0 A-C time difference, use this cut at low multiplicities with caution") O2_DEFINE_CONFIGURABLE(cfgEvSelkNoCollInTimeRangeStandard, bool, false, "no collisions in specified time range") O2_DEFINE_CONFIGURABLE(cfgEvSelkIsGoodITSLayersAll, bool, true, "cut time intervals with dead ITS staves") + O2_DEFINE_CONFIGURABLE(cfgEvSelkIsGoodITSLayer0123, bool, false, "cut time intervals with dead ITS staves (layers 0-3 only, for pp)") O2_DEFINE_CONFIGURABLE(cfgEvSelkNoCollInRofStandard, bool, false, "no other collisions in this Readout Frame with per-collision multiplicity above threshold") O2_DEFINE_CONFIGURABLE(cfgEvSelkNoHighMultCollInPrevRof, bool, false, "veto an event if FT0C amplitude in previous ITS ROF is above threshold") O2_DEFINE_CONFIGURABLE(cfgEvSelMultCorrelation, bool, true, "Multiplicity correlation cut") @@ -312,7 +313,7 @@ struct LongRangeDihadronCor { // Event Counter if ((doprocessSameTpcFt0a || doprocessSameTpcFt0c || doprocessSameFt0aFt0c) && cfgUseAdditionalEventCut) { - registry.add("hEventCountSpecific", "Number of Event;; Count", {HistType::kTH1D, {{12, 0, 12}}}); + registry.add("hEventCountSpecific", "Number of Event;; Count", {HistType::kTH1D, {{13, 0, 13}}}); registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(1, "after sel8"); registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(2, "kNoSameBunchPileup"); registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(3, "kNoITSROFrameBorder"); @@ -320,11 +321,12 @@ struct LongRangeDihadronCor { registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(5, "kIsGoodZvtxFT0vsPV"); registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(6, "kNoCollInTimeRangeStandard"); registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(7, "kIsGoodITSLayersAll"); - registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(8, "kNoCollInRofStandard"); - registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(9, "kNoHighMultCollInPrevRof"); - registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(10, "occupancy"); - registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(11, "MultCorrelation"); - registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(12, "cfgEvSelV0AT0ACut"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(8, "kIsGoodITSLayer0123"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(9, "kNoCollInRofStandard"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(10, "kNoHighMultCollInPrevRof"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(11, "occupancy"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(12, "MultCorrelation"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(13, "cfgEvSelV0AT0ACut"); } if (cfgEvSelMultCorrelation) { @@ -930,23 +932,29 @@ struct LongRangeDihadronCor { } if (fillCounter && cfgEvSelkIsGoodITSLayersAll) registry.fill(HIST("hEventCountSpecific"), 6.5); + if (cfgEvSelkIsGoodITSLayer0123 && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer0123)) { + // for pp: cut time intervals with dead ITS staves on layers 0-3 only + return 0; + } + if (fillCounter && cfgEvSelkIsGoodITSLayer0123) + registry.fill(HIST("hEventCountSpecific"), 7.5); if (cfgEvSelkNoCollInRofStandard && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { // no other collisions in this Readout Frame with per-collision multiplicity above threshold return 0; } if (fillCounter && cfgEvSelkNoCollInRofStandard) - registry.fill(HIST("hEventCountSpecific"), 7.5); + registry.fill(HIST("hEventCountSpecific"), 8.5); if (cfgEvSelkNoHighMultCollInPrevRof && !collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { // veto an event if FT0C amplitude in previous ITS ROF is above threshold return 0; } if (fillCounter && cfgEvSelkNoHighMultCollInPrevRof) - registry.fill(HIST("hEventCountSpecific"), 8.5); + registry.fill(HIST("hEventCountSpecific"), 9.5); auto occupancy = collision.trackOccupancyInTimeRange(); if (cfgEvSelOccupancy && (occupancy < cfgCutOccupancyLow || occupancy > cfgCutOccupancyHigh)) return 0; if (fillCounter && cfgEvSelOccupancy) - registry.fill(HIST("hEventCountSpecific"), 9.5); + registry.fill(HIST("hEventCountSpecific"), 10.5); auto multNTracksPV = collision.multNTracksPV(); if (cfgEvSelMultCorrelation) { @@ -976,14 +984,14 @@ struct LongRangeDihadronCor { } } if (fillCounter && cfgEvSelMultCorrelation) - registry.fill(HIST("hEventCountSpecific"), 10.5); + registry.fill(HIST("hEventCountSpecific"), 11.5); // V0A T0A 5 sigma cut float sigma = 5.0; if (cfgEvSelV0AT0ACut && (std::fabs(collision.multFV0A() - cfgFuncParas.fT0AV0AMean->Eval(collision.multFT0A())) > sigma * cfgFuncParas.fT0AV0ASigma->Eval(collision.multFT0A()))) return 0; if (fillCounter && cfgEvSelV0AT0ACut) - registry.fill(HIST("hEventCountSpecific"), 11.5); + registry.fill(HIST("hEventCountSpecific"), 12.5); return 1; } From abd7d465a62dc708b37650fc43e01f746cf6800d Mon Sep 17 00:00:00 2001 From: Marvin Hemmer <53471402+mhemmer-cern@users.noreply.github.com> Date: Thu, 19 Mar 2026 17:04:07 +0100 Subject: [PATCH 336/347] [PWGEM] PM: Add spetial resolution plots for EMCal (#15457) --- PWGEM/PhotonMeson/Tasks/photonResoTask.cxx | 28 ++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/PWGEM/PhotonMeson/Tasks/photonResoTask.cxx b/PWGEM/PhotonMeson/Tasks/photonResoTask.cxx index 6de4f8bb17e..7036c3a30de 100644 --- a/PWGEM/PhotonMeson/Tasks/photonResoTask.cxx +++ b/PWGEM/PhotonMeson/Tasks/photonResoTask.cxx @@ -24,6 +24,8 @@ #include "PWGEM/PhotonMeson/Utils/EventHistograms.h" #include "PWGEM/PhotonMeson/Utils/MCUtilities.h" +#include "Common/Core/RecoDecay.h" + #include #include #include @@ -315,12 +317,30 @@ struct PhotonResoTask { const AxisSpec thnAxisCent{thnConfigAxisCent, "Centrality (%)"}; const AxisSpec thnAxisInvMass{thnConfigAxisInvMass, "#it{M}_{#gamma#gamma} (GeV/#it{c}^{2})"}; + const AxisSpec thnAxisEtaGen{280, -0.7, 0.7, "#it{#eta}_{Gen}"}; + const AxisSpec thnAxisEtaRec{280, -0.7, 0.7, "#it{#eta}_{Rec}"}; + + const AxisSpec thnAxisPhiGen{360, 0., o2::constants::math::TwoPI, "#it{#varphi}_{Gen} (rad)"}; + const AxisSpec thnAxisPhiRec{360, 0., o2::constants::math::TwoPI, "#it{#varphi}_{Rec} (rad)"}; + registry.add("EMCal/hPhotonReso", "EMCal photon rec pT vs true pT vs cent", HistType::kTH3D, {thnAxisPtRec, thnAxisPtGen, thnAxisCent}); registry.add("EMCal/hConvPhotonReso", "EMCal conversion photon rec pT vs true pT vs cent ", HistType::kTH3D, {thnAxisPtRec, thnAxisPtGen, thnAxisCent}); registry.add("EMCal/hPi0Reso", "EMCal pi0 rec pT vs true pT vs min vs cent ", HistType::kTHnSparseF, {thnAxisPtRec, thnAxisPtGen, thnConfigAxisInvMass, thnAxisCent}); registry.add("EMCal/hEtaReso", "EMCal eta rec pT vs true pT vs min vs cent ", HistType::kTHnSparseF, {thnAxisPtRec, thnAxisPtGen, thnConfigAxisInvMass, thnAxisCent}); + registry.add("EMCal/hPhotonResoEta", "EMCal photon rec eta vs true eta vs cent", HistType::kTH3D, {thnAxisEtaRec, thnAxisEtaGen, thnAxisCent}); + registry.add("EMCal/hConvPhotonResoEta", "EMCal conversion photon rec eta vs true eta vs cent ", HistType::kTH3D, {thnAxisEtaRec, thnAxisEtaGen, thnAxisCent}); + + registry.add("EMCal/hPi0ResoEta", "EMCal pi0 rec eta vs true eta vs min vs cent ", HistType::kTHnSparseF, {thnAxisEtaRec, thnAxisEtaGen, thnConfigAxisInvMass, thnAxisCent}); + registry.add("EMCal/hEtaResoEta", "EMCal eta rec eta vs true eta vs min vs cent ", HistType::kTHnSparseF, {thnAxisEtaRec, thnAxisEtaGen, thnConfigAxisInvMass, thnAxisCent}); + + registry.add("EMCal/hPhotonResoPhi", "EMCal photon rec phi vs true phi vs cent", HistType::kTH3D, {thnAxisPhiRec, thnAxisPhiGen, thnAxisCent}); + registry.add("EMCal/hConvPhotonResoPhi", "EMCal conversion photon rec phi vs true phi vs cent ", HistType::kTH3D, {thnAxisPhiRec, thnAxisPhiGen, thnAxisCent}); + + registry.add("EMCal/hPi0ResoPhi", "EMCal pi0 rec phi vs true phi vs min vs cent ", HistType::kTHnSparseF, {thnAxisPhiRec, thnAxisPhiGen, thnConfigAxisInvMass, thnAxisCent}); + registry.add("EMCal/hEtaResoPhi", "EMCal eta rec phi vs true phi vs min vs cent ", HistType::kTHnSparseF, {thnAxisPhiRec, thnAxisPhiGen, thnConfigAxisInvMass, thnAxisCent}); + registry.add("PCM/hPhotonReso", "PCM photon rec pT vs true pT vs ", HistType::kTH3D, {thnAxisPtRec, thnAxisPtGen, thnAxisCent}); auto hMesonCuts = registry.add("hMesonCuts", "hMesonCuts;;Counts", kTH1D, {{6, 0.5, 6.5}}, false); @@ -471,11 +491,15 @@ struct PhotonResoTask { if (std::abs(mcPhoton1.pdgCode()) == PDG_t::kGamma) { registry.fill(HIST("EMCal/hPhotonReso"), photonEMC.pt(), mcPhoton1.pt(), cent); + registry.fill(HIST("EMCal/hPhotonResoEta"), photonEMC.eta(), mcPhoton1.eta(), cent); + registry.fill(HIST("EMCal/hPhotonResoPhi"), photonEMC.phi(), mcPhoton1.phi(), cent); } else if (std::abs(mcPhoton1.pdgCode()) == PDG_t::kElectron) { if (!o2::aod::pwgem::photonmeson::utils::mcutil::isMotherPDG(mcPhoton1, PDG_t::kGamma)) { continue; } registry.fill(HIST("EMCal/hConvPhotonReso"), photonEMC.pt(), mcPhoton1.pt(), cent); + registry.fill(HIST("EMCal/hConvPhotonResoEta"), photonEMC.eta(), mcPhoton1.eta(), cent); + registry.fill(HIST("EMCal/hConvPhotonResoPhi"), photonEMC.phi(), mcPhoton1.phi(), cent); } } @@ -567,10 +591,14 @@ struct PhotonResoTask { if (pi0id >= 0) { const auto pi0mc = mcParticles.iteratorAt(pi0id); registry.fill(HIST("EMCal/hPi0Reso"), vMeson.Pt(), pi0mc.pt(), vMeson.M(), cent); + registry.fill(HIST("EMCal/hPi0ResoEta"), vMeson.Eta(), pi0mc.eta(), vMeson.M(), cent); + registry.fill(HIST("EMCal/hPi0ResoPhi"), RecoDecay::constrainAngle(vMeson.Phi()), pi0mc.phi(), vMeson.M(), cent); } if (etaid >= 0) { const auto etamc = mcParticles.iteratorAt(etaid); registry.fill(HIST("EMCal/hEtaReso"), vMeson.Pt(), etamc.pt(), vMeson.M(), cent); + registry.fill(HIST("EMCal/hEtaResoEta"), vMeson.Eta(), etamc.eta(), vMeson.M(), cent); + registry.fill(HIST("EMCal/hEtaResoPhi"), RecoDecay::constrainAngle(vMeson.Phi()), etamc.phi(), vMeson.M(), cent); } } } From 36985c7bc2305db72cdfdc5d105cb75cd71fc86b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrea=20Tavira=20Garc=C3=ADa?= <118979672+atavirag@users.noreply.github.com> Date: Thu, 19 Mar 2026 18:20:18 +0100 Subject: [PATCH 337/347] [PWGHF,PWGJE] Add variables to derivedDataCreatorBplusToD0Pi.cxx (#15349) Co-authored-by: ALICE Action Bot --- PWGHF/DataModel/DerivedTables.h | 23 +++++++++++++ .../derivedDataCreatorBplusToD0Pi.cxx | 33 +++++++++++++++++++ PWGJE/Core/JetHFUtilities.h | 4 +++ 3 files changed, 60 insertions(+) diff --git a/PWGHF/DataModel/DerivedTables.h b/PWGHF/DataModel/DerivedTables.h index 174b435788b..3d15683b218 100644 --- a/PWGHF/DataModel/DerivedTables.h +++ b/PWGHF/DataModel/DerivedTables.h @@ -627,6 +627,25 @@ DECLARE_SOA_TABLE_STAGED(HfBplusParD0s, "HFBPPARD0", //! Table with D0 candidate hf_cand_par_charm::NSigTofKaExpKaCharm, hf_cand_par_charm::NSigTpcTofKaExpKaCharm); +DECLARE_SOA_TABLE_STAGED(HfBplusParD0Es, "HFBPPARD0E", //! Table with additional D0 candidate properties used for selection of B+ + hf_cand_par_charm::Chi2PCACharm, + hf_cand_par_charm::NProngsContributorsPVCharm, + hf_cand_par_charm::InvMassCharm, + hf_cand_par_charm::MaxNormalisedDeltaIPCharm, + hf_cand_par_charm::DecayLengthXYCharm, + hf_cand_par_charm::DecayLengthNormalisedCharm, + hf_cand_par_charm::DecayLengthXYNormalisedCharm, + hf_cand_par_charm::ImpactParameterNormalised0Charm, + hf_cand_par_charm::ImpactParameterNormalised1Charm, + hf_cand_par_charm::PxProng0Charm, + hf_cand_par_charm::PyProng0Charm, + hf_cand_par_charm::PzProng0Charm, + hf_cand_par_charm::PxProng1Charm, + hf_cand_par_charm::PyProng1Charm, + hf_cand_par_charm::PzProng1Charm, + hf_cand_par_charm::PtProng0Charm, + hf_cand_par_charm::PtProng1Charm); + DECLARE_SOA_TABLE_STAGED(HfBplusParEs, "HFBPPARE", //! Table with additional candidate properties used for selection hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, @@ -638,6 +657,10 @@ DECLARE_SOA_TABLE_STAGED(HfBplusParEs, "HFBPPARE", //! Table with additional can hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1, + hf_cand_par::PProng0, + hf_cand::PxProng0, + hf_cand::PyProng0, + hf_cand::PzProng0, hf_cand::ErrorImpactParameter1, hf_cand_par::CosThetaStar, hf_cand_par::Ct, diff --git a/PWGHF/TableProducer/derivedDataCreatorBplusToD0Pi.cxx b/PWGHF/TableProducer/derivedDataCreatorBplusToD0Pi.cxx index 3efeb95a145..5baaec8dafa 100644 --- a/PWGHF/TableProducer/derivedDataCreatorBplusToD0Pi.cxx +++ b/PWGHF/TableProducer/derivedDataCreatorBplusToD0Pi.cxx @@ -72,6 +72,7 @@ struct HfDerivedDataCreatorBplusToD0Pi { // Candidates Produces rowCandidatePar; Produces rowCandidateParD0; + Produces rowCandidateParD0E; Produces rowCandidateParE; Produces rowCandidateSel; Produces rowCandidateMl; @@ -83,6 +84,7 @@ struct HfDerivedDataCreatorBplusToD0Pi { HfConfigurableDerivedData confDerData; Configurable fillCandidatePar{"fillCandidatePar", true, "Fill candidate parameters"}; Configurable fillCandidateParD0{"fillCandidateParD0", true, "Fill D0 candidate parameters"}; + Configurable fillCandidateParD0E{"fillCandidateParD0E", true, "Fill additional D0 candidate parameters"}; Configurable fillCandidateParE{"fillCandidateParE", true, "Fill candidate extended parameters"}; Configurable fillCandidateSel{"fillCandidateSel", true, "Fill candidate selection flags"}; Configurable fillCandidateMl{"fillCandidateMl", true, "Fill candidate selection ML scores"}; @@ -197,6 +199,32 @@ struct HfDerivedDataCreatorBplusToD0Pi { sigmas[HfProngSpecies::Kaon][HfProngSpecies::Kaon][1], sigmas[HfProngSpecies::Kaon][HfProngSpecies::Kaon][2]); } + if (fillCandidateParD0E) { + float invMassD0 = 0.; + if (candFlag == 0) { + invMassD0 = HfHelper::invMassD0ToPiK(prongCharm); + } else if (candFlag == 1) { + invMassD0 = HfHelper::invMassD0barToKPi(prongCharm); + } + rowCandidateParD0E( + prongCharm.chi2PCA(), + prongCharm.nProngsContributorsPV(), + invMassD0, + prongCharm.maxNormalisedDeltaIP(), + prongCharm.decayLengthXY(), + prongCharm.decayLengthNormalised(), + prongCharm.decayLengthXYNormalised(), + prongCharm.impactParameterNormalised0(), + prongCharm.impactParameterNormalised1(), + prongCharm.pxProng0(), + prongCharm.pyProng0(), + prongCharm.pzProng0(), + prongCharm.pxProng1(), + prongCharm.pyProng1(), + prongCharm.pzProng1(), + prongCharm.ptProng0(), + prongCharm.ptProng1()); + } if (fillCandidateParE) { rowCandidateParE( candidate.xSecondaryVertex(), @@ -209,6 +237,10 @@ struct HfDerivedDataCreatorBplusToD0Pi { candidate.pxProng1(), candidate.pyProng1(), candidate.pzProng1(), + RecoDecay::p(candidate.pxProng0(), candidate.pyProng0(), candidate.pzProng0()), + candidate.pxProng0(), + candidate.pyProng0(), + candidate.pzProng0(), candidate.errorImpactParameter1(), HfHelper::cosThetaStarBplus(candidate), ct); @@ -277,6 +309,7 @@ struct HfDerivedDataCreatorBplusToD0Pi { reserveTable(rowCandidatePar, fillCandidatePar, sizeTableCand); reserveTable(rowCandidateParD0, fillCandidateParD0, sizeTableCand); reserveTable(rowCandidateParE, fillCandidateParE, sizeTableCand); + reserveTable(rowCandidateParD0E, fillCandidateParD0E, sizeTableCand); reserveTable(rowCandidateSel, fillCandidateSel, sizeTableCand); reserveTable(rowCandidateMl, fillCandidateMl, sizeTableCand); reserveTable(rowCandidateMlD0, fillCandidateMlD0, sizeTableCand); diff --git a/PWGJE/Core/JetHFUtilities.h b/PWGJE/Core/JetHFUtilities.h index f64725aa241..a018c0c177b 100644 --- a/PWGJE/Core/JetHFUtilities.h +++ b/PWGJE/Core/JetHFUtilities.h @@ -1366,6 +1366,10 @@ void fillBplusCandidateTable(T const& candidate, U& BplusParTable, V& BplusParET candidate.pxProng1(), candidate.pyProng1(), candidate.pzProng1(), + candidate.pProng0(), + candidate.pxProng0(), + candidate.pyProng0(), + candidate.pzProng0(), candidate.errorImpactParameter1(), candidate.cosThetaStar(), candidate.ct()); From bce27b06ac35b415ae8bb032b505dc3761d5bcd8 Mon Sep 17 00:00:00 2001 From: Lorenzo Bernardinis <95907752+lorber98@users.noreply.github.com> Date: Thu, 19 Mar 2026 18:28:03 +0100 Subject: [PATCH 338/347] [PWGLF] Add histograms for efficiency studies and to count number of jets + Add mass rejection cuts for Lambda, K0S (#15455) --- .../Strangeness/strangenessInJetsIons.cxx | 575 +++++++++++++++--- 1 file changed, 484 insertions(+), 91 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/strangenessInJetsIons.cxx b/PWGLF/Tasks/Strangeness/strangenessInJetsIons.cxx index 4cbec3a9a01..cefeec99ce6 100644 --- a/PWGLF/Tasks/Strangeness/strangenessInJetsIons.cxx +++ b/PWGLF/Tasks/Strangeness/strangenessInJetsIons.cxx @@ -133,6 +133,7 @@ struct StrangenessInJetsIons { // Track analysis parameters struct : ConfigurableGroup { + // std::string prefix = "configTracks"; // name in JSON Configurable minITSnCls{"minITSnCls", 4, "Minimum number of ITS clusters"}; Configurable minNCrossedRowsTPC{"minNCrossedRowsTPC", 70, "Minimum number of TPC crossed rows"}; Configurable maxChi2TPC{"maxChi2TPC", 4.0f, "Maximum chi2 per cluster TPC"}; @@ -154,6 +155,7 @@ struct StrangenessInJetsIons { // V0 analysis parameters struct : ConfigurableGroup { + // std::string prefix = "configV0"; // name in JSON Configurable minimumV0Radius{"minimumV0Radius", 1.2f, "Minimum V0 Radius (cm)"}; // Configurable maximumV0Radius{"maximumV0Radius", 40.0f, "Maximum V0 Radius (cm)"}; Configurable v0cospaMin{"v0cospaMin", 0.995f, "Minimum V0 cosine of pointing angle"}; @@ -166,14 +168,21 @@ struct StrangenessInJetsIons { Configurable requireArmenterosCut{"requireArmenterosCut", true, "Require Armenteros Cut"}; Configurable paramArmenterosCut{"paramArmenterosCut", 0.2f, "Parameter Armenteros Cut (K0S only). This parameters multiplies alphaArm (Check if: qtarm >= this * |alphaArm|)"}; Configurable ctauK0s{"ctauK0s", 20.0f, "C tau K0S (cm)"}; + Configurable requireK0sMassCuts{"requireK0sMassCuts", true, "[K0S] Require mass window for K0S selection and for Lambda rejection"}; + Configurable lamRejWindow{"lamRejWindow", 0.005f, "[K0S] Mass window for Lambda rejection"}; + Configurable k0sMassWindow{"k0sMassWindow", 0.1f, "[K0S] Mass window for K0S selection"}; // Lambda/anti-Lambda paramaters Configurable dcaProtonToPVmin{"dcaProtonToPVmin", 0.05f, "Minimum DCA of proton/anti-proton track to primary vertex in Lambda/anti-Lambda decays (cm)"}; Configurable dcaPionToPVmin{"dcaPionToPVmin", 0.2f, "Minimum DCA of pion-/pion+ track to primary vertex in Lambda/anti-Lambda decays (cm)"}; Configurable ctauLambda{"ctauLambda", 30.0f, "C tau Lambda (cm)"}; + Configurable requireLambdaMassCuts{"requireLambdaMassCuts", true, "[Lambda] Require mass window for Lambda selection and for K0S rejection"}; + Configurable k0sRejWindow{"k0sRejWindow", 0.010f, "[Lambda] Mass window for K0S rejection"}; + Configurable lamMassWindow{"lamMassWindow", 0.1f, "[Lambda] Mass window for Lambda selection"}; } configV0; // Cascade analysis parameters struct : ConfigurableGroup { + // std::string prefix = "configCasc"; // name in JSON Configurable minimumCascRadius{"minimumCascRadius", 0.1f, "Minimum cascade radius"}; // Configurable maximumCascRadius{"maximumCascRadius", 40.0f, "Maximum cascade radius"}; Configurable casccospaMin{"casccospaMin", 0.99f, "Minimum cascade cosine of pointing angle"}; @@ -191,6 +200,7 @@ struct StrangenessInJetsIons { ConfigurableAxis multBinning{"multBinning", {VARIABLE_WIDTH, 0, 5, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100}, "Binning of the centrality axis"}; struct : ConfigurableGroup { + // std::string prefix = "longLivedOptions"; // name in JSON ConfigurableAxis longLivedBinsNsigma{"longLivedBinsNsigma", {200, -10.f, 10.f}, "Binning of nSigma axis"}; ConfigurableAxis longLivedBinsPt{"longLivedBinsPt", {VARIABLE_WIDTH, -5.0, -4.8, -4.6, -4.4, -4.2, -4.0, -3.8, -3.6, -3.4, -3.2, -3.0, -2.8, -2.6, -2.4, -2.2, -2.0, -1.9, -1.8, -1.7, -1.6, -1.5, -1.4, -1.3, -1.2, -1.1, -1.0, -0.95, -0.9, -0.85, -0.8, -0.75, -0.7, -0.65, -0.6, -0.55, -0.5, -0.45, -0.4, -0.35, -0.3, -0.25, -0.2, -0.18, -0.16, -0.14, -0.12, -0.1, 0.0, 0.1, 0.12, 0.14, 0.16, 0.18, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0, 4.2, 4.4, 4.6, 4.8, 5.0}, "Binning of the pT axis"}; ConfigurableAxis longLivedBinsDca{"longLivedBinsDca", {VARIABLE_WIDTH, -3.0, -2.95, -2.9, -2.85, -2.8, -2.75, -2.7, -2.65, -2.6, -2.55, -2.5, -2.45, -2.4, -2.35, -2.3, -2.25, -2.2, -2.15, -2.1, -2.05, -2.0, -1.975, -1.95, -1.925, -1.9, -1.875, -1.85, -1.825, -1.8, -1.775, -1.75, -1.725, -1.7, -1.675, -1.65, -1.625, -1.6, -1.575, -1.55, -1.525, -1.5, -1.475, -1.45, -1.425, -1.4, -1.375, -1.35, -1.325, -1.3, -1.275, -1.25, -1.225, -1.2, -1.175, -1.15, -1.125, -1.1, -1.075, -1.05, -1.025, -1.0, -0.99, -0.98, -0.97, -0.96, -0.95, -0.94, -0.93, -0.92, -0.91, -0.9, -0.89, -0.88, -0.87, -0.86, -0.85, -0.84, -0.83, -0.82, -0.81, -0.8, -0.79, -0.78, -0.77, -0.76, -0.75, -0.74, -0.73, -0.72, -0.71, -0.7, -0.69, -0.68, -0.67, -0.66, -0.65, -0.64, -0.63, -0.62, -0.61, -0.6, -0.59, -0.58, -0.57, -0.56, -0.55, -0.54, -0.53, -0.52, -0.51, -0.5, -0.49, -0.48, -0.47, -0.46, -0.45, -0.44, -0.43, -0.42, -0.41, -0.4, -0.396, -0.392, -0.388, -0.384, -0.38, -0.376, -0.372, -0.368, -0.364, -0.36, -0.356, -0.352, -0.348, -0.344, -0.34, -0.336, -0.332, -0.328, -0.324, -0.32, -0.316, -0.312, -0.308, -0.304, -0.3, -0.296, -0.292, -0.288, -0.284, -0.28, -0.276, -0.272, -0.268, -0.264, -0.26, -0.256, -0.252, -0.248, -0.244, -0.24, -0.236, -0.232, -0.228, -0.224, -0.22, -0.216, -0.212, -0.208, -0.204, -0.2, -0.198, -0.196, -0.194, -0.192, -0.19, -0.188, -0.186, -0.184, -0.182, -0.18, -0.178, -0.176, -0.174, -0.172, -0.17, -0.168, -0.166, -0.164, -0.162, -0.16, -0.158, -0.156, -0.154, -0.152, -0.15, -0.148, -0.146, -0.144, -0.142, -0.14, -0.138, -0.136, -0.134, -0.132, -0.13, -0.128, -0.126, -0.124, -0.122, -0.12, -0.118, -0.116, -0.114, -0.112, -0.11, -0.108, -0.106, -0.104, -0.102, -0.1, -0.099, -0.098, -0.097, -0.096, -0.095, -0.094, -0.093, -0.092, -0.091, -0.09, -0.089, -0.088, -0.087, -0.086, -0.085, -0.084, -0.083, -0.082, -0.081, -0.08, -0.079, -0.078, -0.077, -0.076, -0.075, -0.074, -0.073, -0.072, -0.071, -0.07, -0.069, -0.068, -0.067, -0.066, -0.065, -0.064, -0.063, -0.062, -0.061, -0.06, -0.059, -0.058, -0.057, -0.056, -0.055, -0.054, -0.053, -0.052, -0.051, -0.05, -0.049, -0.048, -0.047, -0.046, -0.045, -0.044, -0.043, -0.042, -0.041, -0.04, -0.039, -0.038, -0.037, -0.036, -0.035, -0.034, -0.033, -0.032, -0.031, -0.03, -0.029, -0.028, -0.027, -0.026, -0.025, -0.024, -0.023, -0.022, -0.021, -0.02, -0.019, -0.018, -0.017, -0.016, -0.015, -0.014, -0.013, -0.012, -0.011, -0.01, -0.009, -0.008, -0.007, -0.006, -0.005, -0.004, -0.003, -0.002, -0.001, -0.0, 0.001, 0.002, 0.003, 0.004, 0.005, 0.006, 0.007, 0.008, 0.009, 0.01, 0.011, 0.012, 0.013, 0.014, 0.015, 0.016, 0.017, 0.018, 0.019, 0.02, 0.021, 0.022, 0.023, 0.024, 0.025, 0.026, 0.027, 0.028, 0.029, 0.03, 0.031, 0.032, 0.033, 0.034, 0.035, 0.036, 0.037, 0.038, 0.039, 0.04, 0.041, 0.042, 0.043, 0.044, 0.045, 0.046, 0.047, 0.048, 0.049, 0.05, 0.051, 0.052, 0.053, 0.054, 0.055, 0.056, 0.057, 0.058, 0.059, 0.06, 0.061, 0.062, 0.063, 0.064, 0.065, 0.066, 0.067, 0.068, 0.069, 0.07, 0.071, 0.072, 0.073, 0.074, 0.075, 0.076, 0.077, 0.078, 0.079, 0.08, 0.081, 0.082, 0.083, 0.084, 0.085, 0.086, 0.087, 0.088, 0.089, 0.09, 0.091, 0.092, 0.093, 0.094, 0.095, 0.096, 0.097, 0.098, 0.099, 0.1, 0.102, 0.104, 0.106, 0.108, 0.11, 0.112, 0.114, 0.116, 0.118, 0.12, 0.122, 0.124, 0.126, 0.128, 0.13, 0.132, 0.134, 0.136, 0.138, 0.14, 0.142, 0.144, 0.146, 0.148, 0.15, 0.152, 0.154, 0.156, 0.158, 0.16, 0.162, 0.164, 0.166, 0.168, 0.17, 0.172, 0.174, 0.176, 0.178, 0.18, 0.182, 0.184, 0.186, 0.188, 0.19, 0.192, 0.194, 0.196, 0.198, 0.2, 0.204, 0.208, 0.212, 0.216, 0.22, 0.224, 0.228, 0.232, 0.236, 0.24, 0.244, 0.248, 0.252, 0.256, 0.26, 0.264, 0.268, 0.272, 0.276, 0.28, 0.284, 0.288, 0.292, 0.296, 0.3, 0.304, 0.308, 0.312, 0.316, 0.32, 0.324, 0.328, 0.332, 0.336, 0.34, 0.344, 0.348, 0.352, 0.356, 0.36, 0.364, 0.368, 0.372, 0.376, 0.38, 0.384, 0.388, 0.392, 0.396, 0.4, 0.41, 0.42, 0.43, 0.44, 0.45, 0.46, 0.47, 0.48, 0.49, 0.5, 0.51, 0.52, 0.53, 0.54, 0.55, 0.56, 0.57, 0.58, 0.59, 0.6, 0.61, 0.62, 0.63, 0.64, 0.65, 0.66, 0.67, 0.68, 0.69, 0.7, 0.71, 0.72, 0.73, 0.74, 0.75, 0.76, 0.77, 0.78, 0.79, 0.8, 0.81, 0.82, 0.83, 0.84, 0.85, 0.86, 0.87, 0.88, 0.89, 0.9, 0.91, 0.92, 0.93, 0.94, 0.95, 0.96, 0.97, 0.98, 0.99, 1.0, 1.025, 1.05, 1.075, 1.1, 1.125, 1.15, 1.175, 1.2, 1.225, 1.25, 1.275, 1.3, 1.325, 1.35, 1.375, 1.4, 1.425, 1.45, 1.475, 1.5, 1.525, 1.55, 1.575, 1.6, 1.625, 1.65, 1.675, 1.7, 1.725, 1.75, 1.775, 1.8, 1.825, 1.85, 1.875, 1.9, 1.925, 1.95, 1.975, 2.0, 2.05, 2.1, 2.15, 2.2, 2.25, 2.3, 2.35, 2.4, 2.45, 2.5, 2.55, 2.6, 2.65, 2.7, 2.75, 2.8, 2.85, 2.9, 2.95, 3.0}, "Binning of DCA xy and z axis"}; @@ -227,6 +237,8 @@ struct StrangenessInJetsIons { AxisSpec multAxis = {multBinning, multAxTitle}; const AxisSpec ptAxis{100, 0.0, 10.0, "#it{p}_{T} (GeV/#it{c})"}; + const AxisSpec ptJetAxis{101, 0.0, 100.0, "#it{p}_{T,jet} (GeV/#it{c})"}; + const AxisSpec numJets{21, -0.5, 20.5, "Number of jets per collision"}; const AxisSpec invMassK0sAxis{200, 0.44, 0.56, "m_{#pi#pi} (GeV/#it{c}^{2})"}; const AxisSpec invMassLambdaAxis{200, 1.09, 1.14, "m_{p#pi} (GeV/#it{c}^{2})"}; const AxisSpec invMassXiAxis{200, 1.28, 1.36, "m_{p#pi#pi} (GeV/#it{c}^{2})"}; @@ -255,7 +267,7 @@ struct StrangenessInJetsIons { } // Histograms for checks - registryQC.add("V0_type", "V0_type", HistType::kTH1F, {{10, -0.5, 9.5, "V0 type"}}); + // registryQC.add("V0_type", "V0_type", HistType::kTH1F, {{10, -0.5, 9.5, "V0 type"}}); // Histograms for real data if (doprocessData) { @@ -273,8 +285,12 @@ struct StrangenessInJetsIons { registryData.get(HIST("number_of_events_data"))->GetXaxis()->SetBinLabel(7, "No empty events"); registryData.get(HIST("number_of_events_data"))->GetXaxis()->SetBinLabel(8, "At least one jet"); + // Jet counters + registryData.add("n_jets_vs_mult_pT", "n_jets_vs_mult_pT", HistType::kTH2F, {multAxis, ptJetAxis}); + registryData.add("n_jets_vs_mult", "n_jets_vs_mult", HistType::kTH2F, {multAxis, numJets}); + // Armenteros-Podolanski plot - registryQC.add("ArmenterosPreSel_DATA", "ArmenterosPreSel_DATA", HistType::kTH2F, {alphaArmAxis, qtarmAxis}); + // registryQC.add("ArmenterosPreSel_DATA", "ArmenterosPreSel_DATA", HistType::kTH2F, {alphaArmAxis, qtarmAxis}); // Histograms for analysis of strange hadrons if (particleOfInterestDict[ParticleOfInterest::kV0Particles]) { @@ -323,6 +339,10 @@ struct StrangenessInJetsIons { // Add histogram to store multiplicity of the event registryMC.add("number_of_events_vsmultiplicity_gen", "number of events vs multiplicity", HistType::kTH1D, {{101, -0.5, 100.5, "Multiplicity percentile"}}); + // Jet counters + registryMC.add("n_jets_vs_mult_pT_mc_gen", "n_jets_vs_mult_pT_mc_gen", HistType::kTH2F, {multAxis, ptJetAxis}); + registryMC.add("n_jets_vs_mult_mc_gen", "n_jets_vs_mult_mc_gen", HistType::kTH2F, {multAxis, numJets}); + // Histograms for analysis if (particleOfInterestDict[ParticleOfInterest::kV0Particles]) { registryMC.add("K0s_generated_jet", "K0s_generated_jet", HistType::kTH2F, {multAxis, ptAxis}); @@ -331,6 +351,11 @@ struct StrangenessInJetsIons { registryMC.add("Lambda_generated_ue", "Lambda_generated_ue", HistType::kTH2F, {multAxis, ptAxis}); registryMC.add("AntiLambda_generated_jet", "AntiLambda_generated_jet", HistType::kTH2F, {multAxis, ptAxis}); registryMC.add("AntiLambda_generated_ue", "AntiLambda_generated_ue", HistType::kTH2F, {multAxis, ptAxis}); + + // Histograms for the full event (without jets) + registryMC.add("K0s_generated_MB", "K0s_generated_MB", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("Lambda_generated_MB", "Lambda_generated_MB", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("AntiLambda_generated_MB", "AntiLambda_generated_MB", HistType::kTH2F, {multAxis, ptAxis}); } if (particleOfInterestDict[ParticleOfInterest::kCascades]) { registryMC.add("XiPos_generated_jet", "XiPos_generated_jet", HistType::kTH2F, {multAxis, ptAxis}); @@ -341,18 +366,42 @@ struct StrangenessInJetsIons { registryMC.add("OmegaPos_generated_ue", "OmegaPos_generated_ue", HistType::kTH2F, {multAxis, ptAxis}); registryMC.add("OmegaNeg_generated_jet", "OmegaNeg_generated_jet", HistType::kTH2F, {multAxis, ptAxis}); registryMC.add("OmegaNeg_generated_ue", "OmegaNeg_generated_ue", HistType::kTH2F, {multAxis, ptAxis}); + + // Histograms for the full event (without jets) + registryMC.add("XiPos_generated_MB", "XiPos_generated_MB", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("XiNeg_generated_MB", "XiNeg_generated_MB", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("OmegaPos_generated_MB", "OmegaPos_generated_MB", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("OmegaNeg_generated_MB", "OmegaNeg_generated_MB", HistType::kTH2F, {multAxis, ptAxis}); } if (particleOfInterestDict[ParticleOfInterest::kPions]) { - registryMC.add("Pion_generated_jet", "Pion_generated_jet", HistType::kTH2F, {multAxis, ptAxisLongLived}); - registryMC.add("Pion_generated_ue", "Pion_generated_ue", HistType::kTH2F, {multAxis, ptAxisLongLived}); + registryMC.add("PionPos_generated_jet", "PionPos_generated_jet", HistType::kTH2F, {multAxis, ptAxisLongLived}); + registryMC.add("PionNeg_generated_jet", "PionNeg_generated_jet", HistType::kTH2F, {multAxis, ptAxisLongLived}); + registryMC.add("PionPos_generated_ue", "PionPos_generated_ue", HistType::kTH2F, {multAxis, ptAxisLongLived}); + registryMC.add("PionNeg_generated_ue", "PionNeg_generated_ue", HistType::kTH2F, {multAxis, ptAxisLongLived}); + + // Histograms for the full event (without jets) + registryMC.add("PionPos_generated_MB", "PionPos_generated_MB", HistType::kTH2F, {multAxis, ptAxisLongLived}); + registryMC.add("PionNeg_generated_MB", "PionNeg_generated_MB", HistType::kTH2F, {multAxis, ptAxisLongLived}); } if (particleOfInterestDict[ParticleOfInterest::kKaons]) { - registryMC.add("Kaon_generated_jet", "Kaon_generated_jet", HistType::kTH2F, {multAxis, ptAxisLongLived}); - registryMC.add("Kaon_generated_ue", "Kaon_generated_ue", HistType::kTH2F, {multAxis, ptAxisLongLived}); + registryMC.add("KaonPos_generated_jet", "KaonPos_generated_jet", HistType::kTH2F, {multAxis, ptAxisLongLived}); + registryMC.add("KaonNeg_generated_jet", "KaonNeg_generated_jet", HistType::kTH2F, {multAxis, ptAxisLongLived}); + registryMC.add("KaonPos_generated_ue", "KaonPos_generated_ue", HistType::kTH2F, {multAxis, ptAxisLongLived}); + registryMC.add("KaonNeg_generated_ue", "KaonNeg_generated_ue", HistType::kTH2F, {multAxis, ptAxisLongLived}); + + // Histograms for the full event (without jets) + registryMC.add("KaonPos_generated_MB", "KaonPos_generated_MB", HistType::kTH2F, {multAxis, ptAxisLongLived}); + registryMC.add("KaonNeg_generated_MB", "KaonNeg_generated_MB", HistType::kTH2F, {multAxis, ptAxisLongLived}); } if (particleOfInterestDict[ParticleOfInterest::kProtons]) { - registryMC.add("Proton_generated_jet", "Proton_generated_jet", HistType::kTH2F, {multAxis, ptAxisLongLived}); - registryMC.add("Proton_generated_ue", "Proton_generated_ue", HistType::kTH2F, {multAxis, ptAxisLongLived}); + registryMC.add("ProtonPos_generated_jet", "ProtonPos_generated_jet", HistType::kTH2F, {multAxis, ptAxisLongLived}); + registryMC.add("ProtonNeg_generated_jet", "ProtonNeg_generated_jet", HistType::kTH2F, {multAxis, ptAxisLongLived}); + registryMC.add("ProtonPos_generated_ue", "ProtonPos_generated_ue", HistType::kTH2F, {multAxis, ptAxisLongLived}); + registryMC.add("ProtonNeg_generated_ue", "ProtonNeg_generated_ue", HistType::kTH2F, {multAxis, ptAxisLongLived}); + + // Histograms for the full event (without jets) + registryMC.add("ProtonPos_generated_MB", "ProtonPos_generated_MB", HistType::kTH2F, {multAxis, ptAxisLongLived}); + registryMC.add("ProtonNeg_generated_MB", "ProtonNeg_generated_MB", HistType::kTH2F, {multAxis, ptAxisLongLived}); } } @@ -373,8 +422,12 @@ struct StrangenessInJetsIons { // Add histogram to store multiplicity of the event registryMC.add("number_of_events_vsmultiplicity_rec", "number of events vs multiplicity", HistType::kTH1D, {{101, -0.5, 100.5, "Multiplicity percentile"}}); + // Jet counters + registryMC.add("n_jets_vs_mult_pT_mc_rec", "n_jets_vs_mult_pT_mc_rec", HistType::kTH2F, {multAxis, ptJetAxis}); + registryMC.add("n_jets_vs_mult_mc_rec", "n_jets_vs_mult_mc_rec", HistType::kTH2F, {multAxis, numJets}); + // Armenteros-Podolanski plot - registryQC.add("ArmenterosPreSel_REC", "ArmenterosPreSel_REC", HistType::kTH2F, {alphaArmAxis, qtarmAxis}); + // registryQC.add("ArmenterosPreSel_REC", "ArmenterosPreSel_REC", HistType::kTH2F, {alphaArmAxis, qtarmAxis}); // Histograms for analysis if (particleOfInterestDict[ParticleOfInterest::kV0Particles]) { @@ -384,6 +437,7 @@ struct StrangenessInJetsIons { registryMC.add("Lambda_reconstructed_ue", "Lambda_reconstructed_ue", HistType::kTH2F, {multAxis, ptAxis}); registryMC.add("AntiLambda_reconstructed_jet", "AntiLambda_reconstructed_jet", HistType::kTH2F, {multAxis, ptAxis}); registryMC.add("AntiLambda_reconstructed_ue", "AntiLambda_reconstructed_ue", HistType::kTH2F, {multAxis, ptAxis}); + // Histograms for secondary hadrons registryMC.add("K0s_reconstructed_jet_incl", "K0s_reconstructed_jet_incl", HistType::kTH2F, {multAxis, ptAxis}); registryMC.add("K0s_reconstructed_ue_incl", "K0s_reconstructed_ue_incl", HistType::kTH2F, {multAxis, ptAxis}); @@ -391,6 +445,19 @@ struct StrangenessInJetsIons { registryMC.add("Lambda_reconstructed_ue_incl", "Lambda_reconstructed_ue_incl", HistType::kTH2F, {multAxis, ptAxis}); registryMC.add("AntiLambda_reconstructed_jet_incl", "AntiLambda_reconstructed_jet_incl", HistType::kTH2F, {multAxis, ptAxis}); registryMC.add("AntiLambda_reconstructed_ue_incl", "AntiLambda_reconstructed_ue_incl", HistType::kTH2F, {multAxis, ptAxis}); + + // Histograms for generated particles in reconstructed events + registryMC.add("K0s_gen_recoEvent_jet", "K0s_gen_recoEvent_jet", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("K0s_gen_recoEvent_ue", "K0s_gen_recoEvent_ue", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("Lambda_gen_recoEvent_jet", "Lambda_gen_recoEvent_jet", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("Lambda_gen_recoEvent_ue", "Lambda_gen_recoEvent_ue", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("AntiLambda_gen_recoEvent_jet", "AntiLambda_gen_recoEvent_jet", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("AntiLambda_gen_recoEvent_ue", "AntiLambda_gen_recoEvent_ue", HistType::kTH2F, {multAxis, ptAxis}); + + // Histograms for the full event (without jets) + registryMC.add("K0s_reconstructed_MB", "K0s_reconstructed_MB", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("Lambda_reconstructed_MB", "Lambda_reconstructed_MB", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("AntiLambda_reconstructed_MB", "AntiLambda_reconstructed_MB", HistType::kTH2F, {multAxis, ptAxis}); } if (particleOfInterestDict[ParticleOfInterest::kCascades]) { registryMC.add("XiPos_reconstructed_jet", "XiPos_reconstructed_jet", HistType::kTH2F, {multAxis, ptAxis}); @@ -401,71 +468,39 @@ struct StrangenessInJetsIons { registryMC.add("OmegaPos_reconstructed_ue", "OmegaPos_reconstructed_ue", HistType::kTH2F, {multAxis, ptAxis}); registryMC.add("OmegaNeg_reconstructed_jet", "OmegaNeg_reconstructed_jet", HistType::kTH2F, {multAxis, ptAxis}); registryMC.add("OmegaNeg_reconstructed_ue", "OmegaNeg_reconstructed_ue", HistType::kTH2F, {multAxis, ptAxis}); + + // Histograms for the full event (without jets) + registryMC.add("XiPos_reconstructed_MB", "XiPos_reconstructed_MB", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("XiNeg_reconstructed_MB", "XiNeg_reconstructed_MB", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("OmegaPos_reconstructed_MB", "OmegaPos_reconstructed_MB", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("OmegaNeg_reconstructed_MB", "OmegaNeg_reconstructed_MB", HistType::kTH2F, {multAxis, ptAxis}); } if (particleOfInterestDict[ParticleOfInterest::kPions]) { registryMC.add("Pion_reconstructed_jet", "Pion_reconstructed_jet", HistType::kTH2F, {multAxis, ptAxisLongLived}); registryMC.add("Pion_reconstructed_ue", "Pion_reconstructed_ue", HistType::kTH2F, {multAxis, ptAxisLongLived}); + + // Histograms for the full event (without jets) + registryMC.add("PionPos_reconstructed_MB", "PionPos_reconstructed_MB", HistType::kTH2F, {multAxis, ptAxisLongLived}); + registryMC.add("PionNeg_reconstructed_MB", "PionNeg_reconstructed_MB", HistType::kTH2F, {multAxis, ptAxisLongLived}); } if (particleOfInterestDict[ParticleOfInterest::kKaons]) { registryMC.add("Kaon_reconstructed_jet", "Kaon_reconstructed_jet", HistType::kTH2F, {multAxis, ptAxisLongLived}); registryMC.add("Kaon_reconstructed_ue", "Kaon_reconstructed_ue", HistType::kTH2F, {multAxis, ptAxisLongLived}); + + // Histograms for the full event (without jets) + registryMC.add("KaonPos_reconstructed_MB", "KaonPos_reconstructed_MB", HistType::kTH2F, {multAxis, ptAxisLongLived}); + registryMC.add("KaonNeg_reconstructed_MB", "KaonNeg_reconstructed_MB", HistType::kTH2F, {multAxis, ptAxisLongLived}); } if (particleOfInterestDict[ParticleOfInterest::kProtons]) { registryMC.add("Proton_reconstructed_jet", "Proton_reconstructed_jet", HistType::kTH2F, {multAxis, ptAxisLongLived}); registryMC.add("Proton_reconstructed_ue", "Proton_reconstructed_ue", HistType::kTH2F, {multAxis, ptAxisLongLived}); - } - } - } - - /* - // Calculation of perpendicular axes - void getPerpendicularAxis(TVector3 p, TVector3& u, double sign) - { - // initialization - double ux(0), uy(0), uz(0); - - // components of vector p - const double px = p.X(); - const double py = p.Y(); - const double pz = p.Z(); - - // protection 1 - if (px == 0 && py != 0) { - uy = -(pz * pz) / py; - ux = sign * std::sqrt(py * py - (pz * pz * pz * pz) / (py * py)); - uz = pz; - u.SetXYZ(ux, uy, uz); - return; - } - - // protection 2 - if (py == 0 && px != 0) { - ux = -(pz * pz) / px; - uy = sign * std::sqrt(px * px - (pz * pz * pz * pz) / (px * px)); - uz = pz; - u.SetXYZ(ux, uy, uz); - return; - } - - // equation parameters - const double a = px * px + py * py; - const double b = 2.0 * px * pz * pz; - const double c = pz * pz * pz * pz - py * py * py * py - px * px * py * py; - const double delta = b * b - 4.0 * a * c; - // protection agains delta<0 - if (delta < 0) { - return; + // Histograms for the full event (without jets) + registryMC.add("ProtonPos_reconstructed_MB", "ProtonPos_reconstructed_MB", HistType::kTH2F, {multAxis, ptAxisLongLived}); + registryMC.add("ProtonNeg_reconstructed_MB", "ProtonNeg_reconstructed_MB", HistType::kTH2F, {multAxis, ptAxisLongLived}); + } } - - // solutions - ux = (-b + sign * std::sqrt(delta)) / (2.0 * a); - uy = (-pz * pz - px * ux) / py; - uz = pz; - u.SetXYZ(ux, uy, uz); - return; } - */ // Delta phi calculation double getDeltaPhi(double a1, double a2) @@ -649,10 +684,10 @@ struct StrangenessInJetsIons { return false; if (std::fabs(v0.dcanegtopv()) < configV0.dcaPionToPVmin) return false; - if (v0.v0Type() != configV0.v0type && configV0.requireV0type) { - registryQC.fill(HIST("V0_type"), v0.v0Type()); - return false; - } + // if (v0.v0Type() != configV0.v0type && configV0.requireV0type) { + // registryQC.fill(HIST("V0_type"), v0.v0Type()); + // return false; + // } // PID selections (TPC): positive track = proton, negative track = pion if (ptrack.tpcNSigmaPr() < configTracks.nsigmaTPCmin || ptrack.tpcNSigmaPr() > configTracks.nsigmaTPCmax) @@ -660,6 +695,14 @@ struct StrangenessInJetsIons { if (ntrack.tpcNSigmaPi() < configTracks.nsigmaTPCmin || ntrack.tpcNSigmaPi() > configTracks.nsigmaTPCmax) return false; + if (configV0.requireLambdaMassCuts && + std::abs(v0.mK0Short() - o2::constants::physics::MassK0Short) < configV0.k0sRejWindow) + return false; + + if (configV0.requireLambdaMassCuts && + std::abs(v0.mLambda() - o2::constants::physics::MassLambda) > configV0.lamMassWindow) + return false; + // PID selections (TOF): positive track = proton, negative track = pion if (configTracks.requireTOF) { if (ptrack.tofNSigmaPr() < configTracks.nsigmaTOFmin || ptrack.tofNSigmaPr() > configTracks.nsigmaTOFmax) @@ -702,10 +745,10 @@ struct StrangenessInJetsIons { return false; if (std::fabs(v0.dcanegtopv()) < configV0.dcaProtonToPVmin) return false; - if (v0.v0Type() != configV0.v0type && configV0.requireV0type) { - registryQC.fill(HIST("V0_type"), v0.v0Type()); - return false; - } + // if (v0.v0Type() != configV0.v0type && configV0.requireV0type) { + // registryQC.fill(HIST("V0_type"), v0.v0Type()); + // return false; + // } // PID selections (TPC): negative track = proton, positive track = pion if (ptrack.tpcNSigmaPi() < configTracks.nsigmaTPCmin || ptrack.tpcNSigmaPi() > configTracks.nsigmaTPCmax) @@ -713,6 +756,14 @@ struct StrangenessInJetsIons { if (ntrack.tpcNSigmaPr() < configTracks.nsigmaTPCmin || ntrack.tpcNSigmaPr() > configTracks.nsigmaTPCmax) return false; + if (configV0.requireLambdaMassCuts && + std::abs(v0.mK0Short() - o2::constants::physics::MassK0Short) < configV0.k0sRejWindow) + return false; + + if (configV0.requireLambdaMassCuts && + std::abs(v0.mAntiLambda() - o2::constants::physics::MassLambda) > configV0.lamMassWindow) + return false; + // PID selections (TOF): negative track = proton, positive track = pion if (configTracks.requireTOF) { if (ptrack.tofNSigmaPi() < configTracks.nsigmaTOFmin || ptrack.tofNSigmaPi() > configTracks.nsigmaTOFmax) @@ -760,10 +811,10 @@ struct StrangenessInJetsIons { if (v0.qtarm() < (configV0.paramArmenterosCut * std::abs(v0.alpha())) && (configV0.requireArmenterosCut)) return false; - if (v0.v0Type() != configV0.v0type && configV0.requireV0type) { - registryQC.fill(HIST("V0_type"), v0.v0Type()); - return false; - } + // if (v0.v0Type() != configV0.v0type && configV0.requireV0type) { + // registryQC.fill(HIST("V0_type"), v0.v0Type()); + // return false; + // } // PID selections (TPC) if (ptrack.tpcNSigmaPi() < configTracks.nsigmaTPCmin || ptrack.tpcNSigmaPi() > configTracks.nsigmaTPCmax) @@ -771,6 +822,15 @@ struct StrangenessInJetsIons { if (ntrack.tpcNSigmaPi() < configTracks.nsigmaTPCmin || ntrack.tpcNSigmaPi() > configTracks.nsigmaTPCmax) return false; + if (configV0.requireK0sMassCuts && + (std::abs(v0.mLambda() - o2::constants::physics::MassLambda) < configV0.lamRejWindow || + std::abs(v0.mAntiLambda() - o2::constants::physics::MassLambda) < configV0.lamRejWindow)) + return false; + + if (configV0.requireK0sMassCuts && + std::abs(v0.mK0Short() - o2::constants::physics::MassK0Short) > configV0.k0sMassWindow) + return false; + // PID selections (TOF) if (configTracks.requireTOF) { if (ptrack.tofNSigmaPi() < configTracks.nsigmaTOFmin || ptrack.tofNSigmaPi() > configTracks.nsigmaTOFmax) @@ -1053,6 +1113,241 @@ struct StrangenessInJetsIons { return true; } + void FillFullEventHistoMCGEN(aod::McParticle const& particle, + const double& genMultiplicity) + { + if (particle.isPhysicalPrimary()) { + switch (particle.pdgCode()) { + case kK0Short: + if (particleOfInterestDict[ParticleOfInterest::kV0Particles]) { + registryMC.fill(HIST("K0s_generated_MB"), genMultiplicity, particle.pt()); + } + break; + case kLambda0: + if (particleOfInterestDict[ParticleOfInterest::kV0Particles]) { + registryMC.fill(HIST("Lambda_generated_MB"), genMultiplicity, particle.pt()); + } + break; + case kLambda0Bar: + if (particleOfInterestDict[ParticleOfInterest::kV0Particles]) { + registryMC.fill(HIST("AntiLambda_generated_MB"), genMultiplicity, particle.pt()); + } + break; + case kXiMinus: + if (particleOfInterestDict[ParticleOfInterest::kCascades]) { + registryMC.fill(HIST("XiNeg_generated_MB"), genMultiplicity, particle.pt()); + } + break; + case kXiPlusBar: + if (particleOfInterestDict[ParticleOfInterest::kCascades]) { + registryMC.fill(HIST("XiPos_generated_MB"), genMultiplicity, particle.pt()); + } + break; + case kOmegaMinus: + if (particleOfInterestDict[ParticleOfInterest::kCascades]) { + registryMC.fill(HIST("OmegaNeg_generated_MB"), genMultiplicity, particle.pt()); + } + break; + case kOmegaPlusBar: + if (particleOfInterestDict[ParticleOfInterest::kCascades]) { + registryMC.fill(HIST("OmegaPos_generated_MB"), genMultiplicity, particle.pt()); + } + break; + case kPiPlus: + if (particleOfInterestDict[ParticleOfInterest::kPions]) { + registryMC.fill(HIST("PionPos_generated_MB"), genMultiplicity, particle.pt()); + } + break; + case kKPlus: + if (particleOfInterestDict[ParticleOfInterest::kKaons]) { + registryMC.fill(HIST("KaonPos_generated_MB"), genMultiplicity, particle.pt()); + } + break; + case kProton: + if (particleOfInterestDict[ParticleOfInterest::kProtons]) { + registryMC.fill(HIST("ProtonPos_generated_MB"), genMultiplicity, particle.pt()); + } + break; + case kPiMinus: + if (particleOfInterestDict[ParticleOfInterest::kPions]) { + registryMC.fill(HIST("PionNeg_generated_MB"), genMultiplicity, particle.pt()); + } + break; + case kKMinus: + if (particleOfInterestDict[ParticleOfInterest::kKaons]) { + registryMC.fill(HIST("KaonNeg_generated_MB"), genMultiplicity, particle.pt()); + } + break; + case kProtonBar: + if (particleOfInterestDict[ParticleOfInterest::kProtons]) { + registryMC.fill(HIST("ProtonNeg_generated_MB"), genMultiplicity, particle.pt()); + } + break; + default: + break; + } + } + } + + template + void FillFullEventHistoMCREC(MCRecoCollision collision, + aod::McParticles const& mcParticles, + V0PerColl const& v0sPerColl, + CascPerColl const& cascPerColl, + TracksPerColl const& tracksPerColl, + const double& multiplicity) + { + // V0 particles + if (particleOfInterestDict[ParticleOfInterest::kV0Particles]) { + for (const auto& v0 : v0sPerColl) { + const auto& pos = v0.template posTrack_as(); + const auto& neg = v0.template negTrack_as(); + TVector3 v0dir(v0.px(), v0.py(), v0.pz()); + + // Get MC particles + if (!pos.has_mcParticle() || !neg.has_mcParticle()) + continue; + auto posParticle = pos.template mcParticle_as(); + auto negParticle = neg.template mcParticle_as(); + if (!posParticle.has_mothers() || !negParticle.has_mothers()) + continue; + + // Get Mothers + auto motherPos = mcParticles.iteratorAt(posParticle.mothersIds()[0]); + auto motherNeg = mcParticles.iteratorAt(negParticle.mothersIds()[0]); + if (motherPos != motherNeg) + continue; + if (!motherPos.isPhysicalPrimary()) + continue; + + if (std::abs(motherPos.eta()) > 0.8) + continue; + + // Vertex position vector + TVector3 vtxPos(collision.posX(), collision.posY(), collision.posZ()); + + // K0s + if (passedK0ShortSelection(v0, pos, neg, vtxPos) && motherPos.pdgCode() == kK0Short) { + registryMC.fill(HIST("K0s_reconstructed_MB"), multiplicity, v0.pt()); + } + // Lambda + if (passedLambdaSelection(v0, pos, neg, vtxPos) && motherPos.pdgCode() == kLambda0) { + registryMC.fill(HIST("Lambda_reconstructed_MB"), multiplicity, v0.pt()); + } + // AntiLambda + if (passedAntiLambdaSelection(v0, pos, neg, vtxPos) && motherPos.pdgCode() == kLambda0Bar) { + registryMC.fill(HIST("AntiLambda_reconstructed_MB"), multiplicity, v0.pt()); + } + } + } + + // Cascades + if (particleOfInterestDict[ParticleOfInterest::kCascades]) { + for (const auto& casc : cascPerColl) { + auto bach = casc.template bachelor_as(); + auto pos = casc.template posTrack_as(); + auto neg = casc.template negTrack_as(); + + // Get MC particles + if (!bach.has_mcParticle() || !pos.has_mcParticle() || !neg.has_mcParticle()) + continue; + auto posParticle = pos.template mcParticle_as(); + auto negParticle = neg.template mcParticle_as(); + auto bachParticle = bach.template mcParticle_as(); + if (!posParticle.has_mothers() || !negParticle.has_mothers() || !bachParticle.has_mothers()) + continue; + + // Select particles originating from the same parent + auto motherPos = mcParticles.iteratorAt(posParticle.mothersIds()[0]); + auto motherNeg = mcParticles.iteratorAt(negParticle.mothersIds()[0]); + auto motherBach = mcParticles.iteratorAt(bachParticle.mothersIds()[0]); + if (motherPos != motherNeg) + continue; + if (std::abs(motherPos.pdgCode()) != kLambda0) + continue; + if (!motherBach.isPhysicalPrimary()) + continue; + + if (std::abs(motherPos.eta()) > 0.8) + continue; + + // Xi+ + if (passedXiSelection(casc, pos, neg, bach, collision) && bach.sign() > 0 && motherBach.pdgCode() == kXiPlusBar) { + registryMC.fill(HIST("XiPos_reconstructed_MB"), multiplicity, casc.pt()); + } + // Xi- + if (passedXiSelection(casc, pos, neg, bach, collision) && bach.sign() < 0 && motherBach.pdgCode() == kXiMinus) { + registryMC.fill(HIST("XiNeg_reconstructed_MB"), multiplicity, casc.pt()); + } + // Omega+ + if (passedOmegaSelection(casc, pos, neg, bach, collision) && bach.sign() > 0 && motherBach.pdgCode() == kOmegaPlusBar) { + registryMC.fill(HIST("OmegaPos_reconstructed_MB"), multiplicity, casc.pt()); + } + // Omega- + if (passedOmegaSelection(casc, pos, neg, bach, collision) && bach.sign() < 0 && motherBach.pdgCode() == kOmegaMinus) { + registryMC.fill(HIST("OmegaNeg_reconstructed_MB"), multiplicity, casc.pt()); + } + } + } + + if (particleOfInterestDict[ParticleOfInterest::kPions] || + particleOfInterestDict[ParticleOfInterest::kKaons] || + particleOfInterestDict[ParticleOfInterest::kProtons]) { + for (const auto& trk : tracksPerColl) { + + if (!trk.has_mcParticle()) { + continue; + } + if (!passedSingleTrackSelection(trk)) { + continue; + } + const auto& mcParticle = trk.template mcParticle_as(); + if (!mcParticle.isPhysicalPrimary()) { + continue; + } + + if (std::abs(mcParticle.eta()) > 0.8) { + continue; + } + + switch (mcParticle.pdgCode()) { + case kPiPlus: + if (particleOfInterestDict[ParticleOfInterest::kPions]) { + registryMC.fill(HIST("PionPos_reconstructed_MB"), multiplicity, trk.pt()); + } + break; + case kPiMinus: + if (particleOfInterestDict[ParticleOfInterest::kPions]) { + registryMC.fill(HIST("PionNeg_reconstructed_MB"), multiplicity, trk.pt()); + } + break; + case kKPlus: + if (particleOfInterestDict[ParticleOfInterest::kKaons]) { + registryMC.fill(HIST("KaonPos_reconstructed_MB"), multiplicity, trk.pt()); + } + break; + case kKMinus: + if (particleOfInterestDict[ParticleOfInterest::kKaons]) { + registryMC.fill(HIST("KaonNeg_reconstructed_MB"), multiplicity, trk.pt()); + } + break; + case kProton: + if (particleOfInterestDict[ParticleOfInterest::kProtons]) { + registryMC.fill(HIST("ProtonPos_reconstructed_MB"), multiplicity, trk.pt()); + } + break; + case kProtonBar: + if (particleOfInterestDict[ParticleOfInterest::kProtons]) { + registryMC.fill(HIST("ProtonNeg_reconstructed_MB"), multiplicity, trk.pt()); + } + break; + default: + break; + } + } + } + } + // Process data void processData(SelCollisions::iterator const& collision, aod::V0Datas const& fullV0s, aod::CascDataExt const& Cascades, DaughterTracks const& tracks, @@ -1133,6 +1428,7 @@ struct StrangenessInJetsIons { std::vector selectedJet; std::vector ue1; std::vector ue2; + std::vector jetPt; // Loop over reconstructed jets for (const auto& jet : jets) { @@ -1160,6 +1456,7 @@ struct StrangenessInJetsIons { selectedJet.emplace_back(jetAxis); ue1.emplace_back(ueAxis1); ue2.emplace_back(ueAxis2); + jetPt.emplace_back(jetMinusBkg.pt()); } if (!isAtLeastOneJetSelected) return; @@ -1177,9 +1474,14 @@ struct StrangenessInJetsIons { // Fill event multiplicity registryData.fill(HIST("number_of_events_vsmultiplicity"), multiplicity); + registryData.fill(HIST("n_jets_vs_mult"), multiplicity, static_cast(selectedJet.size())); // Loop over selected jets for (int i = 0; i < static_cast(selectedJet.size()); i++) { + + // Fill jet counter + registryData.fill(HIST("n_jets_vs_mult_pT"), multiplicity, jetPt[i]); + if (particleOfInterestDict[ParticleOfInterest::kV0Particles]) { // V0s for (const auto& v0 : fullV0s) { @@ -1203,7 +1505,7 @@ struct StrangenessInJetsIons { TVector3 vtxPos(collision.posX(), collision.posY(), collision.posZ()); // Fill Armenteros-Podolanski TH2 - registryQC.fill(HIST("ArmenterosPreSel_DATA"), v0.alpha(), v0.qtarm()); + // registryQC.fill(HIST("ArmenterosPreSel_DATA"), v0.alpha(), v0.qtarm()); // K0s if (passedK0ShortSelection(v0, pos, neg, vtxPos)) { @@ -1431,18 +1733,21 @@ struct StrangenessInJetsIons { for (const auto& particle : mcParticlesPerColl) { // Store properties of strange hadrons int pdgAbs = std::abs(particle.pdgCode()); - if (particle.isPhysicalPrimary() && (pdgAbs == kK0Short || pdgAbs == kLambda0 || pdgAbs == kXiMinus || pdgAbs == kOmegaMinus)) { + if (particle.isPhysicalPrimary() && (pdgAbs == kK0Short || pdgAbs == kLambda0 || pdgAbs == kXiMinus || pdgAbs == kOmegaMinus)) { // TODO: add protons, kaons, pions pdg.emplace_back(particle.pdgCode()); strHadronMomentum.emplace_back(particle.px(), particle.py(), particle.pz()); } - // Select physical primary particles or HF decay products - if (!isPhysicalPrimaryOrFromHF(particle, mcParticles)) - continue; - double minPtParticle = 0.1; + double minPtParticle = 0.1f; if (particle.eta() < configTracks.etaMin || particle.eta() > configTracks.etaMax || particle.pt() < minPtParticle) continue; + FillFullEventHistoMCGEN(particle, genMultiplicity); + + // Select physical primary particles or HF decay products + if (!isPhysicalPrimaryOrFromHF(particle, mcParticles)) + continue; + // Build 4-momentum assuming charged pion mass static constexpr float kMassPionChargedSquared = o2::constants::physics::MassPionCharged * o2::constants::physics::MassPionCharged; const double energy = std::sqrt(particle.p() * particle.p() + kMassPionChargedSquared); @@ -1464,6 +1769,7 @@ struct StrangenessInJetsIons { auto [rhoPerp, rhoMPerp] = jetutilities::estimateRhoPerpCone(fjParticles, jets[0], rJet); // Loop over clustered jets + int countSelJet = 0; // number of selected jets for (const auto& jet : jets) { // Jet must be fully contained in acceptance @@ -1477,9 +1783,13 @@ struct StrangenessInJetsIons { // Apply jet pT threshold if (jetMinusBkg.pt() < minJetPt) continue; + countSelJet++; registryMC.fill(HIST("number_of_events_mc_gen"), 3.5); registryMC.fill(HIST("number_of_events_vsmultiplicity_gen"), genMultiplicity); + // Fill jet counter + registryMC.fill(HIST("n_jets_vs_mult_pT_mc_gen"), genMultiplicity, jetMinusBkg.pt()); + // Set up two perpendicular cone axes for underlying event estimation TVector3 jetAxis(jet.px(), jet.py(), jet.pz()); double coneRadius = std::sqrt(jet.area() / PI); @@ -1546,32 +1856,32 @@ struct StrangenessInJetsIons { break; case kPiPlus: if (particleOfInterestDict[ParticleOfInterest::kPions]) { - registryMC.fill(HIST("Pion_generated_jet"), genMultiplicity, hadron.Pt()); + registryMC.fill(HIST("PionPos_generated_jet"), genMultiplicity, hadron.Pt()); } break; case kKPlus: if (particleOfInterestDict[ParticleOfInterest::kKaons]) { - registryMC.fill(HIST("Kaon_generated_jet"), genMultiplicity, hadron.Pt()); + registryMC.fill(HIST("KaonPos_generated_jet"), genMultiplicity, hadron.Pt()); } break; case kProton: if (particleOfInterestDict[ParticleOfInterest::kProtons]) { - registryMC.fill(HIST("Proton_generated_jet"), genMultiplicity, hadron.Pt()); + registryMC.fill(HIST("ProtonPos_generated_jet"), genMultiplicity, hadron.Pt()); } break; case kPiMinus: if (particleOfInterestDict[ParticleOfInterest::kPions]) { - registryMC.fill(HIST("Pion_generated_jet"), genMultiplicity, hadron.Pt() * -1.f); + registryMC.fill(HIST("PionNeg_generated_jet"), genMultiplicity, hadron.Pt()); } break; case kKMinus: if (particleOfInterestDict[ParticleOfInterest::kKaons]) { - registryMC.fill(HIST("Kaon_generated_jet"), genMultiplicity, hadron.Pt() * -1.f); + registryMC.fill(HIST("KaonNeg_generated_jet"), genMultiplicity, hadron.Pt()); } break; case kProtonBar: if (particleOfInterestDict[ParticleOfInterest::kProtons]) { - registryMC.fill(HIST("Proton_generated_jet"), genMultiplicity, hadron.Pt() * -1.f); + registryMC.fill(HIST("ProtonNeg_generated_jet"), genMultiplicity, hadron.Pt()); } break; default: @@ -1619,32 +1929,32 @@ struct StrangenessInJetsIons { break; case kPiPlus: if (particleOfInterestDict[ParticleOfInterest::kPions]) { - registryMC.fill(HIST("Pion_generated_ue"), genMultiplicity, hadron.Pt()); + registryMC.fill(HIST("PionPos_generated_ue"), genMultiplicity, hadron.Pt()); } break; case kKPlus: if (particleOfInterestDict[ParticleOfInterest::kKaons]) { - registryMC.fill(HIST("Kaon_generated_ue"), genMultiplicity, hadron.Pt()); + registryMC.fill(HIST("KaonPos_generated_ue"), genMultiplicity, hadron.Pt()); } break; case kProton: if (particleOfInterestDict[ParticleOfInterest::kProtons]) { - registryMC.fill(HIST("Proton_generated_ue"), genMultiplicity, hadron.Pt()); + registryMC.fill(HIST("ProtonPos_generated_ue"), genMultiplicity, hadron.Pt()); } break; case kPiMinus: if (particleOfInterestDict[ParticleOfInterest::kPions]) { - registryMC.fill(HIST("Pion_generated_ue"), genMultiplicity, hadron.Pt() * -1.f); + registryMC.fill(HIST("PionNeg_generated_ue"), genMultiplicity, hadron.Pt()); } break; case kKMinus: if (particleOfInterestDict[ParticleOfInterest::kKaons]) { - registryMC.fill(HIST("Kaon_generated_ue"), genMultiplicity, hadron.Pt() * -1.f); + registryMC.fill(HIST("KaonNeg_generated_ue"), genMultiplicity, hadron.Pt()); } break; case kProtonBar: if (particleOfInterestDict[ParticleOfInterest::kProtons]) { - registryMC.fill(HIST("Proton_generated_ue"), genMultiplicity, hadron.Pt() * -1.f); + registryMC.fill(HIST("ProtonNeg_generated_ue"), genMultiplicity, hadron.Pt()); } break; default: @@ -1653,6 +1963,8 @@ struct StrangenessInJetsIons { } } } + // Fill jet counter + registryMC.fill(HIST("n_jets_vs_mult_mc_gen"), genMultiplicity, countSelJet); } } PROCESS_SWITCH(StrangenessInJetsIons, processMCgenerated, "Process MC generated events", false); @@ -1661,7 +1973,7 @@ struct StrangenessInJetsIons { void processMCreconstructed(SimCollisions const& collisions, soa::Join const&, DaughterTracksMC const& mcTracks, aod::V0Datas const& fullV0s, - aod::CascDataExt const& Cascades, const aod::McParticles&) + aod::CascDataExt const& Cascades, aod::McParticles const& mcParticles) { // Define per-event containers std::vector fjParticles; @@ -1721,10 +2033,15 @@ struct StrangenessInJetsIons { } else { multiplicity = mcCollision.centFT0M(); } + // Number of V0 and cascades per collision auto v0sPerColl = fullV0s.sliceBy(perCollisionV0, collision.globalIndex()); auto cascPerColl = Cascades.sliceBy(perCollisionCasc, collision.globalIndex()); auto tracksPerColl = mcTracks.sliceBy(perCollisionTrk, collision.globalIndex()); + const auto& mcParticlesPerColl = mcParticles.sliceBy(perMCCollision, mcCollision.globalIndex()); + + FillFullEventHistoMCREC(collision, mcParticles, v0sPerColl, + cascPerColl, tracksPerColl, multiplicity); // Loop over reconstructed tracks for (auto const& track : tracksPerColl) { @@ -1748,6 +2065,7 @@ struct StrangenessInJetsIons { // Jet selection bool isAtLeastOneJetSelected = false; + std::vector jetPt; // Loop over clustered jets for (const auto& jet : jets) { @@ -1775,6 +2093,7 @@ struct StrangenessInJetsIons { selectedJet.emplace_back(jetAxis); ue1.emplace_back(ueAxis1); ue2.emplace_back(ueAxis2); + jetPt.emplace_back(jetMinusBkg.pt()); } if (!isAtLeastOneJetSelected) continue; @@ -1782,10 +2101,83 @@ struct StrangenessInJetsIons { // Fill event counter for events with at least one selected jet registryMC.fill(HIST("number_of_events_mc_rec"), 6.5); registryMC.fill(HIST("number_of_events_vsmultiplicity_rec"), multiplicity); + registryMC.fill(HIST("n_jets_vs_mult_mc_rec"), multiplicity, static_cast(selectedJet.size())); // Loop over selected jets for (int i = 0; i < static_cast(selectedJet.size()); i++) { + // Fill jet counter + registryMC.fill(HIST("n_jets_vs_mult_pT_mc_rec"), multiplicity, jetPt[i]); + + // ------------------------------------------------ + // --- Generated hadrons in reconstructed jets ---- + for (auto& particle : mcParticlesPerColl) { + if (!particle.isPhysicalPrimary() || std::abs(particle.eta()) > 0.8) + continue; + + int absPdg = std::abs(particle.pdgCode()); + if (absPdg != kK0Short && absPdg != kLambda0) + continue; + + TVector3 momVec(particle.px(), particle.py(), particle.pz()); + + // Compute distance of particles from jet and UE axes + const double deltaEtaJet = momVec.Eta() - selectedJet[i].Eta(); + const double deltaPhiJet = getDeltaPhi(momVec.Phi(), selectedJet[i].Phi()); + const double deltaRJet = std::sqrt(deltaEtaJet * deltaEtaJet + deltaPhiJet * deltaPhiJet); + const double deltaEtaUe1 = momVec.Eta() - ue1[i].Eta(); + const double deltaPhiUe1 = getDeltaPhi(momVec.Phi(), ue1[i].Phi()); + const double deltaRUe1 = std::sqrt(deltaEtaUe1 * deltaEtaUe1 + deltaPhiUe1 * deltaPhiUe1); + const double deltaEtaUe2 = momVec.Eta() - ue2[i].Eta(); + const double deltaPhiUe2 = getDeltaPhi(momVec.Phi(), ue2[i].Phi()); + const double deltaRUe2 = std::sqrt(deltaEtaUe2 * deltaEtaUe2 + deltaPhiUe2 * deltaPhiUe2); + + // Select particles inside jet + if (deltaRJet < rJet) { + switch (particle.pdgCode()) { + case kK0Short: + if (particleOfInterestDict[ParticleOfInterest::kV0Particles]) { + registryMC.fill(HIST("K0s_gen_recoEvent_jet"), multiplicity, momVec.Pt()); + } + break; + case kLambda0: + if (particleOfInterestDict[ParticleOfInterest::kV0Particles]) { + registryMC.fill(HIST("Lambda_gen_recoEvent_jet"), multiplicity, momVec.Pt()); + } + break; + case kLambda0Bar: + if (particleOfInterestDict[ParticleOfInterest::kV0Particles]) { + registryMC.fill(HIST("AntiLambda_gen_recoEvent_jet"), multiplicity, momVec.Pt()); + } + break; + default: + break; + } + } + if (deltaRUe1 < rJet || deltaRUe2 < rJet) { + switch (particle.pdgCode()) { + case kK0Short: + if (particleOfInterestDict[ParticleOfInterest::kV0Particles]) { + registryMC.fill(HIST("K0s_gen_recoEvent_ue"), multiplicity, momVec.Pt()); + } + break; + case kLambda0: + if (particleOfInterestDict[ParticleOfInterest::kV0Particles]) { + registryMC.fill(HIST("Lambda_gen_recoEvent_ue"), multiplicity, momVec.Pt()); + } + break; + case kLambda0Bar: + if (particleOfInterestDict[ParticleOfInterest::kV0Particles]) { + registryMC.fill(HIST("AntiLambda_gen_recoEvent_ue"), multiplicity, momVec.Pt()); + } + break; + default: + break; + } + } + } + // ---------------------------------------- + // V0 particles if (particleOfInterestDict[ParticleOfInterest::kV0Particles]) { for (const auto& v0 : v0sPerColl) { @@ -1830,7 +2222,7 @@ struct StrangenessInJetsIons { TVector3 vtxPos(collision.posX(), collision.posY(), collision.posZ()); // Fill Armenteros-Podolanski TH2 - registryQC.fill(HIST("ArmenterosPreSel_REC"), v0.alpha(), v0.qtarm()); + // registryQC.fill(HIST("ArmenterosPreSel_REC"), v0.alpha(), v0.qtarm()); // K0s if (passedK0ShortSelection(v0, pos, neg, vtxPos) && pdgParent == kK0Short && isPhysPrim) { @@ -1978,6 +2370,7 @@ struct StrangenessInJetsIons { } } } + jetPt.clear(); } } PROCESS_SWITCH(StrangenessInJetsIons, processMCreconstructed, "process reconstructed events", false); From 0cd3e2424d774ecfb153d2441a16e24204e82968 Mon Sep 17 00:00:00 2001 From: Maxim Virta <84773378+MaximVirta@users.noreply.github.com> Date: Thu, 19 Mar 2026 21:34:48 +0100 Subject: [PATCH 339/347] [PWGCF] normalisation by hadrons added (#15458) Co-authored-by: MaximVirta Co-authored-by: ALICE Action Bot --- PWGCF/GenericFramework/Tasks/flowGfwV02.cxx | 140 ++++++++++---------- 1 file changed, 71 insertions(+), 69 deletions(-) diff --git a/PWGCF/GenericFramework/Tasks/flowGfwV02.cxx b/PWGCF/GenericFramework/Tasks/flowGfwV02.cxx index 725e86277f4..158880474ae 100644 --- a/PWGCF/GenericFramework/Tasks/flowGfwV02.cxx +++ b/PWGCF/GenericFramework/Tasks/flowGfwV02.cxx @@ -105,6 +105,7 @@ struct FlowGfwV02 { O2_DEFINE_CONFIGURABLE(cfgUseItsPID, bool, true, "Use ITS PID for particle identification") O2_DEFINE_CONFIGURABLE(cfgGetNsigmaQA, bool, true, "Get QA histograms for selection of pions, kaons, and protons") O2_DEFINE_CONFIGURABLE(cfgUseMultiplicityFlowWeights, bool, true, "Enable or disable the use of multiplicity-based event weighting"); + O2_DEFINE_CONFIGURABLE(cfgNormalizeByCharged, bool, true, "Enable or disable the normalization by charged particles"); O2_DEFINE_CONFIGURABLE(cfgConsistentEventFlag, int, 15, "Flag for consistent event selection"); Configurable cfgGFWBinning{"cfgGFWBinning", {40, 16, 72, 300, 0, 3000, 0.2, 10.0, 0.2, 5.0, {0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1, 1.25, 1.5, 1.75, 2, 2.25, 2.5, 2.75, 3, 3.25, 3.5, 3.75, 4, 4.5, 5}, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90}}, "Configuration for binning"}; @@ -174,18 +175,18 @@ struct FlowGfwV02 { using GFWTracks = soa::Filtered>; enum PIDIndex { - kCharged = 0, - kPions, - kKaons, - kProtons + PidCharged = 0, + PidPions, + PidKaons, + PidProtons }; enum PiKpArrayIndex { - iPionUp = 0, - iKaonUp, - iProtonUp, - iPionLow, - iKaonLow, - iProtonLow + IndPionUp = 0, + IndKaonUp, + IndProtonUp, + IndPionLow, + IndKaonLow, + IndProtonLow }; enum DetectorType { kTPC = 0, @@ -196,26 +197,26 @@ struct FlowGfwV02 { void init(InitContext const&) { - pidStates.tpcNsigmaCut[iPionUp] = nSigmas->getData()[iPionUp][kTPC]; - pidStates.tpcNsigmaCut[iKaonUp] = nSigmas->getData()[iKaonUp][kTPC]; - pidStates.tpcNsigmaCut[iProtonUp] = nSigmas->getData()[iProtonUp][kTPC]; - pidStates.tpcNsigmaCut[iPionLow] = nSigmas->getData()[iPionLow][kTPC]; - pidStates.tpcNsigmaCut[iKaonLow] = nSigmas->getData()[iKaonLow][kTPC]; - pidStates.tpcNsigmaCut[iProtonLow] = nSigmas->getData()[iProtonLow][kTPC]; - - pidStates.tofNsigmaCut[iPionUp] = nSigmas->getData()[iPionUp][kTOF]; - pidStates.tofNsigmaCut[iKaonUp] = nSigmas->getData()[iKaonUp][kTOF]; - pidStates.tofNsigmaCut[iProtonUp] = nSigmas->getData()[iProtonUp][kTOF]; - pidStates.tofNsigmaCut[iPionLow] = nSigmas->getData()[iPionLow][kTOF]; - pidStates.tofNsigmaCut[iKaonLow] = nSigmas->getData()[iKaonLow][kTOF]; - pidStates.tofNsigmaCut[iProtonLow] = nSigmas->getData()[iProtonLow][kTOF]; - - pidStates.itsNsigmaCut[iPionUp] = nSigmas->getData()[iPionUp][kITS]; - pidStates.itsNsigmaCut[iKaonUp] = nSigmas->getData()[iKaonUp][kITS]; - pidStates.itsNsigmaCut[iProtonUp] = nSigmas->getData()[iProtonUp][kITS]; - pidStates.itsNsigmaCut[iPionLow] = nSigmas->getData()[iPionLow][kITS]; - pidStates.itsNsigmaCut[iKaonLow] = nSigmas->getData()[iKaonLow][kITS]; - pidStates.itsNsigmaCut[iProtonLow] = nSigmas->getData()[iProtonLow][kITS]; + pidStates.tpcNsigmaCut[IndPionUp] = nSigmas->getData()[IndPionUp][kTPC]; + pidStates.tpcNsigmaCut[IndKaonUp] = nSigmas->getData()[IndKaonUp][kTPC]; + pidStates.tpcNsigmaCut[IndProtonUp] = nSigmas->getData()[IndProtonUp][kTPC]; + pidStates.tpcNsigmaCut[IndPionLow] = nSigmas->getData()[IndPionLow][kTPC]; + pidStates.tpcNsigmaCut[IndKaonLow] = nSigmas->getData()[IndKaonLow][kTPC]; + pidStates.tpcNsigmaCut[IndProtonLow] = nSigmas->getData()[IndProtonLow][kTPC]; + + pidStates.tofNsigmaCut[IndPionUp] = nSigmas->getData()[IndPionUp][kTOF]; + pidStates.tofNsigmaCut[IndKaonUp] = nSigmas->getData()[IndKaonUp][kTOF]; + pidStates.tofNsigmaCut[IndProtonUp] = nSigmas->getData()[IndProtonUp][kTOF]; + pidStates.tofNsigmaCut[IndPionLow] = nSigmas->getData()[IndPionLow][kTOF]; + pidStates.tofNsigmaCut[IndKaonLow] = nSigmas->getData()[IndKaonLow][kTOF]; + pidStates.tofNsigmaCut[IndProtonLow] = nSigmas->getData()[IndProtonLow][kTOF]; + + pidStates.itsNsigmaCut[IndPionUp] = nSigmas->getData()[IndPionUp][kITS]; + pidStates.itsNsigmaCut[IndKaonUp] = nSigmas->getData()[IndKaonUp][kITS]; + pidStates.itsNsigmaCut[IndProtonUp] = nSigmas->getData()[IndProtonUp][kITS]; + pidStates.itsNsigmaCut[IndPionLow] = nSigmas->getData()[IndPionLow][kITS]; + pidStates.itsNsigmaCut[IndKaonLow] = nSigmas->getData()[IndKaonLow][kITS]; + pidStates.itsNsigmaCut[IndProtonLow] = nSigmas->getData()[IndProtonLow][kITS]; if (cfgGetNsigmaQA) { if (!cfgUseItsPID) { @@ -261,14 +262,14 @@ struct FlowGfwV02 { cfgGFWBinning->Print(); // Initialise pt spectra histograms for different particles - pidStates.hPtMid[kCharged] = new TH1D("hPtMid_charged", "hPtMid_charged", o2::analysis::gfw::ptbinning.size() - 1, &o2::analysis::gfw::ptbinning[0]); - pidStates.hPtMid[kPions] = new TH1D("hPtMid_pions", "hPtMid_pions", o2::analysis::gfw::ptbinning.size() - 1, &o2::analysis::gfw::ptbinning[0]); - pidStates.hPtMid[kKaons] = new TH1D("hPtMid_kaons", "hPtMid_kaons", o2::analysis::gfw::ptbinning.size() - 1, &o2::analysis::gfw::ptbinning[0]); - pidStates.hPtMid[kProtons] = new TH1D("hPtMid_protons", "hPtMid_protons", o2::analysis::gfw::ptbinning.size() - 1, &o2::analysis::gfw::ptbinning[0]); - pidStates.hPtMid[kCharged]->SetDirectory(nullptr); - pidStates.hPtMid[kPions]->SetDirectory(nullptr); - pidStates.hPtMid[kKaons]->SetDirectory(nullptr); - pidStates.hPtMid[kProtons]->SetDirectory(nullptr); + pidStates.hPtMid[PidCharged] = new TH1D("hPtMid_charged", "hPtMid_charged", o2::analysis::gfw::ptbinning.size() - 1, &o2::analysis::gfw::ptbinning[0]); + pidStates.hPtMid[PidPions] = new TH1D("hPtMid_pions", "hPtMid_pions", o2::analysis::gfw::ptbinning.size() - 1, &o2::analysis::gfw::ptbinning[0]); + pidStates.hPtMid[PidKaons] = new TH1D("hPtMid_kaons", "hPtMid_kaons", o2::analysis::gfw::ptbinning.size() - 1, &o2::analysis::gfw::ptbinning[0]); + pidStates.hPtMid[PidProtons] = new TH1D("hPtMid_protons", "hPtMid_protons", o2::analysis::gfw::ptbinning.size() - 1, &o2::analysis::gfw::ptbinning[0]); + pidStates.hPtMid[PidCharged]->SetDirectory(nullptr); + pidStates.hPtMid[PidPions]->SetDirectory(nullptr); + pidStates.hPtMid[PidKaons]->SetDirectory(nullptr); + pidStates.hPtMid[PidProtons]->SetDirectory(nullptr); AxisSpec phiAxis = {o2::analysis::gfw::phibins, o2::analysis::gfw::philow, o2::analysis::gfw::phiup, "#phi"}; AxisSpec etaAxis = {o2::analysis::gfw::etabins, -cfgTrackCuts.cfgEtaMax, cfgTrackCuts.cfgEtaMax, "#eta"}; @@ -389,13 +390,13 @@ struct FlowGfwV02 { std::array detectorNsigmaCut = cfgUseItsPID ? pidStates.itsNsigmaCut : pidStates.tpcNsigmaCut; // Choose which nSigma to use: TPC or ITS bool isPion, isKaon, isProton; - bool isDetectedPion = nSigmaToUse[iPionUp] < detectorNsigmaCut[iPionUp] && nSigmaToUse[iPionUp] > detectorNsigmaCut[iPionLow]; - bool isDetectedKaon = nSigmaToUse[iKaonUp] < detectorNsigmaCut[iKaonUp] && nSigmaToUse[iKaonUp] > detectorNsigmaCut[iKaonLow]; - bool isDetectedProton = nSigmaToUse[iProtonUp] < detectorNsigmaCut[iProtonUp] && nSigmaToUse[iProtonUp] > detectorNsigmaCut[iProtonLow]; + bool isDetectedPion = nSigmaToUse[IndPionUp] < detectorNsigmaCut[IndPionUp] && nSigmaToUse[IndPionUp] > detectorNsigmaCut[IndPionLow]; + bool isDetectedKaon = nSigmaToUse[IndKaonUp] < detectorNsigmaCut[IndKaonUp] && nSigmaToUse[IndKaonUp] > detectorNsigmaCut[IndKaonLow]; + bool isDetectedProton = nSigmaToUse[IndProtonUp] < detectorNsigmaCut[IndProtonUp] && nSigmaToUse[IndProtonUp] > detectorNsigmaCut[IndProtonLow]; - bool isTofPion = nSigmaTOF[iPionUp] < pidStates.tofNsigmaCut[iPionUp] && nSigmaTOF[iPionUp] > pidStates.tofNsigmaCut[iPionLow]; - bool isTofKaon = nSigmaTOF[iKaonUp] < pidStates.tofNsigmaCut[iKaonUp] && nSigmaTOF[iKaonUp] > pidStates.tofNsigmaCut[iKaonLow]; - bool isTofProton = nSigmaTOF[iProtonUp] < pidStates.tofNsigmaCut[iProtonUp] && nSigmaTOF[iProtonUp] > pidStates.tofNsigmaCut[iProtonLow]; + bool isTofPion = nSigmaTOF[IndPionUp] < pidStates.tofNsigmaCut[IndPionUp] && nSigmaTOF[IndPionUp] > pidStates.tofNsigmaCut[IndPionLow]; + bool isTofKaon = nSigmaTOF[IndKaonUp] < pidStates.tofNsigmaCut[IndKaonUp] && nSigmaTOF[IndKaonUp] > pidStates.tofNsigmaCut[IndKaonLow]; + bool isTofProton = nSigmaTOF[IndProtonUp] < pidStates.tofNsigmaCut[IndProtonUp] && nSigmaTOF[IndProtonUp] > pidStates.tofNsigmaCut[IndProtonLow]; if (track.pt() > cfgTofPtCut && !track.hasTOF()) { return -1; @@ -414,11 +415,11 @@ struct FlowGfwV02 { } if (isPion) { - pid = kPions; + pid = PidPions; } else if (isKaon) { - pid = kKaons; + pid = PidKaons; } else if (isProton) { - pid = kProtons; + pid = PidProtons; } else { return -1; // no particle satisfies the criteria } @@ -484,21 +485,21 @@ struct FlowGfwV02 { int getPIDIndex(const std::string& corrconfig) { if (boost::ifind_first(corrconfig, "pi")) - return kPions; + return PidPions; if (boost::ifind_first(corrconfig, "ka")) - return kKaons; + return PidKaons; if (boost::ifind_first(corrconfig, "pr")) - return kProtons; - return kCharged; + return PidProtons; + return PidCharged; } GFW::CorrConfig getRelevantCorrName(const int& pidInd) { - if (pidInd == kPions) + if (pidInd == PidPions) return fGFW->GetCorrelatorConfig("piP {2} refN {-2}", "PiGap22", kFALSE); - if (pidInd == kKaons) + if (pidInd == PidKaons) return fGFW->GetCorrelatorConfig("kaP {2} refN {-2}", "KaGap22", kFALSE); - if (pidInd == kProtons) + if (pidInd == PidProtons) return fGFW->GetCorrelatorConfig("prP {2} refN {-2}", "PrGap22", kFALSE); return fGFW->GetCorrelatorConfig("refP {2} refN {-2}", "ChGap22", kFALSE); } @@ -533,8 +534,9 @@ struct FlowGfwV02 { if (corrconfigs.at(l_ind).Head.find("nch") != std::string::npos) val = 1.0; double ptFraction = 0; - if (pidStates.hPtMid[pidInd]->Integral() > 0) { - ptFraction = pidStates.hPtMid[pidInd]->GetBinContent(i) / pidStates.hPtMid[pidInd]->Integral(); + int normIndex = (cfgNormalizeByCharged) ? PidCharged : pidInd; // Configured to normalize by charged particles or the selected particle + if (pidStates.hPtMid[normIndex]->Integral() > 0) { + ptFraction = pidStates.hPtMid[pidInd]->GetBinContent(i) / pidStates.hPtMid[normIndex]->Integral(); if (std::abs(val) < 1.01) fFC->FillProfile(Form("%s_pt_%i", corrconfigs.at(l_ind).Head.c_str(), i), centmult, val * ptFraction, (cfgUseMultiplicityFlowWeights) ? dnx : 1.0, rndm); } @@ -548,8 +550,8 @@ struct FlowGfwV02 { auto val = fGFW->Calculate(corrconfigs.at(0), 0, kFALSE).real() / dnx; for (int i = 1; i <= fSecondAxis->GetNbins(); i++) { double ptFraction = 0; - if (pidStates.hPtMid[kCharged]->Integral() > 0) { - ptFraction = pidStates.hPtMid[kCharged]->GetBinContent(i) / pidStates.hPtMid[kCharged]->Integral(); + if (pidStates.hPtMid[PidCharged]->Integral() > 0) { + ptFraction = pidStates.hPtMid[PidCharged]->GetBinContent(i) / pidStates.hPtMid[PidCharged]->Integral(); if (std::abs(val) < 1) registry.fill(HIST("v02pt"), fSecondAxis->GetBinCenter(i), centmult, val * ptFraction, (cfgUseMultiplicityFlowWeights) ? dnx : 1.0); // printf("bincenter hPtMid: %f, fsecondaxis: %f\n", hPtMid->GetBinCenter(i), fSecondAxis->GetBinCenter(i)); @@ -583,10 +585,10 @@ struct FlowGfwV02 { if (xaxis.multiplicity < cfgFixedMultMin || xaxis.multiplicity > cfgFixedMultMax) return; fGFW->Clear(); - pidStates.hPtMid[kCharged]->Reset(); - pidStates.hPtMid[kPions]->Reset(); - pidStates.hPtMid[kKaons]->Reset(); - pidStates.hPtMid[kProtons]->Reset(); + pidStates.hPtMid[PidCharged]->Reset(); + pidStates.hPtMid[PidPions]->Reset(); + pidStates.hPtMid[PidKaons]->Reset(); + pidStates.hPtMid[PidProtons]->Reset(); float lRandom = fRndm->Rndm(); @@ -594,7 +596,7 @@ struct FlowGfwV02 { AcceptedTracks acceptedTracks{0, 0, 0, 0}; for (const auto& track : tracks) { processTrack(track, vtxz, xaxis.multiplicity, run, acceptedTracks); - pidStates.hPtMid[kCharged]->Fill(track.pt(), getEfficiency(track)); + pidStates.hPtMid[PidCharged]->Fill(track.pt(), getEfficiency(track)); // If PID is identified, fill pt spectrum for the corresponding particle int pidInd = getNsigmaPID(track); if (pidInd != -1 && track.eta() > -0.4 && track.eta() < 0.4) { @@ -663,12 +665,12 @@ struct FlowGfwV02 { // ***Need to add proper weights for each particle!*** if (withinPtRef) fGFW->Fill(track.eta(), fSecondAxis->FindBin(track.pt()) - 1, track.phi(), weff * wacc, 0); - if (withinPtPOI && pidInd == kPions) - fGFW->Fill(track.eta(), fSecondAxis->FindBin(track.pt()) - 1, track.phi(), weff * wacc, kPions); - if (withinPtPOI && pidInd == kKaons) - fGFW->Fill(track.eta(), fSecondAxis->FindBin(track.pt()) - 1, track.phi(), weff * wacc, kKaons); - if (withinPtPOI && pidInd == kProtons) - fGFW->Fill(track.eta(), fSecondAxis->FindBin(track.pt()) - 1, track.phi(), weff * wacc, kProtons); + if (withinPtPOI && pidInd == PidPions) + fGFW->Fill(track.eta(), fSecondAxis->FindBin(track.pt()) - 1, track.phi(), weff * wacc, PidPions); + if (withinPtPOI && pidInd == PidKaons) + fGFW->Fill(track.eta(), fSecondAxis->FindBin(track.pt()) - 1, track.phi(), weff * wacc, PidKaons); + if (withinPtPOI && pidInd == PidProtons) + fGFW->Fill(track.eta(), fSecondAxis->FindBin(track.pt()) - 1, track.phi(), weff * wacc, PidProtons); return; } From af21dbe26820ff04fc6f0fb495b694e0e6f783e8 Mon Sep 17 00:00:00 2001 From: Roman Lietava Date: Fri, 20 Mar 2026 09:09:05 +0100 Subject: [PATCH 340/347] [PWGLF] Omegahm: table for resolution matrix (#15461) --- PWGLF/DataModel/LFNonPromptCascadeTables.h | 10 +++++++++- PWGLF/Tasks/Strangeness/nonPromptCascade.cxx | 10 +++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/PWGLF/DataModel/LFNonPromptCascadeTables.h b/PWGLF/DataModel/LFNonPromptCascadeTables.h index 16c86667ad1..7d0a9c156a8 100644 --- a/PWGLF/DataModel/LFNonPromptCascadeTables.h +++ b/PWGLF/DataModel/LFNonPromptCascadeTables.h @@ -124,6 +124,9 @@ DECLARE_SOA_COLUMN(ToiMask, toiMask, uint32_t); DECLARE_SOA_COLUMN(RunNumber, runNumber, int); DECLARE_SOA_COLUMN(NoSameBunchPileup, noSameBunchPileup, bool); DECLARE_SOA_COLUMN(GlobalBC, globalBC, uint64_t); +DECLARE_SOA_COLUMN(PtGen, ptGen, float); +DECLARE_SOA_COLUMN(PtRec, ptRec, float); +DECLARE_SOA_COLUMN(MultGen, multGen, int); } // namespace NPCascadeTable DECLARE_SOA_TABLE(NPCascTable, "AOD", "NPCASCTABLE", @@ -454,7 +457,12 @@ DECLARE_SOA_TABLE(NPPileUpTable, "AOD", "NPPileUpTABLE", aod::collision::NumContrib, NPCascadeTable::MultNTracksGlobal, NPCascadeTable::CentFT0M, - NPCascadeTable::MultFT0M); + NPCascadeTable::MultFT0M) +DECLARE_SOA_TABLE(NPMCNegativesTable, "AOD", "NPMCNegativesTABLE", + NPCascadeTable::PtGen, + NPCascadeTable::PtRec, + NPCascadeTable::MultNTracksGlobal, + NPCascadeTable::MultGen); } // namespace o2::aod #endif // PWGLF_DATAMODEL_LFNONPROMPTCASCADETABLES_H_ diff --git a/PWGLF/Tasks/Strangeness/nonPromptCascade.cxx b/PWGLF/Tasks/Strangeness/nonPromptCascade.cxx index 4527b2342af..6639404d334 100644 --- a/PWGLF/Tasks/Strangeness/nonPromptCascade.cxx +++ b/PWGLF/Tasks/Strangeness/nonPromptCascade.cxx @@ -183,6 +183,7 @@ struct NonPromptCascadeTask { Produces NPCTableMCNT; Produces NPCTableGen; Produces NPPUTable; + Produces NPMCNTable; using TracksExtData = soa::Join; using TracksExtMC = soa::Join; @@ -743,7 +744,7 @@ struct NonPromptCascadeTask { { fillCandidatesVector(collisions, tracks, cascades, gCandidatesNT); fillMCtable(mcParticles, collisions, gCandidatesNT); - fillMultHistos(collisions); + // fillMultHistos(collisions); } PROCESS_SWITCH(NonPromptCascadeTask, processCascadesMC, "process cascades: MC analysis", false); @@ -794,7 +795,7 @@ struct NonPromptCascadeTask { zorroAccounting(collisions); fillCandidatesVector(collisions, tracks, cascades, gCandidatesNT); fillDataTable(gCandidatesNT); - fillMultHistos(collisions); + // fillMultHistos(collisions); } PROCESS_SWITCH(NonPromptCascadeTask, processCascadesData, "process cascades: Data analysis", false); @@ -950,6 +951,7 @@ struct NonPromptCascadeTask { const float ptMC = mcPar.pt(); mRegistrydNdeta.fill(HIST("hdNdetaRM/hdNdetaRM"), mult, multReco, ptMC, ptReco); + NPMCNTable(ptMC, ptReco, mult, multReco); } // ------------------------------------------------------------ @@ -959,6 +961,7 @@ struct NonPromptCascadeTask { if (!isReco[pid]) { auto mcp = mcParticles.rawIteratorAt(pid); mRegistrydNdeta.fill(HIST("hdNdetaRM/hdNdetaRMNotInRecoTrk"), isRecoMult[pid], mcp.pt()); + NPMCNTable(mcp.pt(), -1, isRecoMult[pid], -1); } } @@ -971,6 +974,7 @@ struct NonPromptCascadeTask { const int mult = mcMult[mcid]; for (auto const& pt : mcptvec) { mRegistrydNdeta.fill(HIST("hdNdetaRM/hdNdetaRMNotInRecoCol"), mult, pt); + NPMCNTable(pt, -2, mult, -2); } } } @@ -1007,7 +1011,7 @@ struct NonPromptCascadeTask { } } }; - PROCESS_SWITCH(NonPromptCascadeTask, processPileUp, "pile up studies", true); + PROCESS_SWITCH(NonPromptCascadeTask, processPileUp, "pile up studies", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) From acf478b097f58599ac7d85b03214cf9eeb345b3a Mon Sep 17 00:00:00 2001 From: YazhenLin Date: Fri, 20 Mar 2026 16:31:50 +0800 Subject: [PATCH 341/347] [PWGDQ] Change some code in the dqEnergyCorrelator_direct.cxx for the energy correlator study (#15454) --- PWGDQ/Core/VarManager.h | 11 ++++++++--- PWGDQ/Tasks/dqEnergyCorrelator_direct.cxx | 5 +++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/PWGDQ/Core/VarManager.h b/PWGDQ/Core/VarManager.h index 6402590ef5a..8af94063bbe 100644 --- a/PWGDQ/Core/VarManager.h +++ b/PWGDQ/Core/VarManager.h @@ -1364,7 +1364,7 @@ class VarManager : public TObject template static void FillEnergyCorrelatorTriple(T1 const& lepton1, T2 const& lepton2, T3 const& hadron, float* values = nullptr, float Translow = 1. / 3, float Transhigh = 2. / 3, bool applyFitMass = false, float sidebandMass = 0.0f); template - static void FillEnergyCorrelatorsUnfoldingTriple(T1 const& lepton1, T2 const& lepton2, T3 const& hadron, T4 const& track, T5 const& t1, float* values = nullptr); + static void FillEnergyCorrelatorsUnfoldingTriple(T1 const& lepton1, T2 const& lepton2, T3 const& hadron, T4 const& track, T5 const& t1, float* values = nullptr, bool applyFitMass = false); template static void FillDileptonPhoton(T1 const& dilepton, T2 const& photon, float* values = nullptr); template @@ -5858,7 +5858,7 @@ void VarManager::FillEnergyCorrelatorTriple(T1 const& lepton1, T2 const& lepton2 } template -void VarManager::FillEnergyCorrelatorsUnfoldingTriple(T1 const& lepton1, T2 const& lepton2, T3 const& hadron, T4 const& track, T5 const& t1, float* values) +void VarManager::FillEnergyCorrelatorsUnfoldingTriple(T1 const& lepton1, T2 const& lepton2, T3 const& hadron, T4 const& track, T5 const& t1, float* values, bool applyFitMass) { if (fgUsedVars[kMCCosChi_gen] || fgUsedVars[kMCWeight_gen] || fgUsedVars[kMCdeltaeta_gen] || fgUsedVars[kMCCosChi_rec] || fgUsedVars[kMCWeight_rec] || fgUsedVars[kMCdeltaeta_rec]) { // energy correlators @@ -5870,6 +5870,11 @@ void VarManager::FillEnergyCorrelatorsUnfoldingTriple(T1 const& lepton1, T2 cons ROOT::Math::PtEtaPhiMVector v_lepton2(lepton2.pt(), lepton2.eta(), lepton2.phi(), m2); ROOT::Math::PtEtaPhiMVector dilepton = v_lepton1 + v_lepton2; + float dileptonmass = o2::constants::physics::MassJPsi; + if (applyFitMass) { + dileptonmass = dilepton.mass(); + } + float MassHadron; if constexpr (pairType == kJpsiHadronMass) { MassHadron = TMath::Sqrt(t1.e() * t1.e() - t1.p() * t1.p()); @@ -5885,7 +5890,7 @@ void VarManager::FillEnergyCorrelatorsUnfoldingTriple(T1 const& lepton1, T2 cons values[kMCWeight_gen] = E_boost_gen / o2::constants::physics::MassJPsi; values[kMCdeltaeta_gen] = track.eta() - t1.eta(); - ROOT::Math::PtEtaPhiMVector v1_rec(dilepton.pt(), dilepton.eta(), dilepton.phi(), dilepton.mass()); + ROOT::Math::PtEtaPhiMVector v1_rec(dilepton.pt(), dilepton.eta(), dilepton.phi(), dileptonmass); ROOT::Math::PtEtaPhiMVector v2_rec(hadron.pt(), hadron.eta(), hadron.phi(), o2::constants::physics::MassPionCharged); values[kMCCosChi_rec] = LorentzTransformJpsihadroncosChi("coschi", v1_rec, v2_rec); float E_boost_rec = LorentzTransformJpsihadroncosChi("weight_boost", v1_rec, v2_rec); diff --git a/PWGDQ/Tasks/dqEnergyCorrelator_direct.cxx b/PWGDQ/Tasks/dqEnergyCorrelator_direct.cxx index b70af0b51d4..b91e9ef5593 100644 --- a/PWGDQ/Tasks/dqEnergyCorrelator_direct.cxx +++ b/PWGDQ/Tasks/dqEnergyCorrelator_direct.cxx @@ -223,6 +223,7 @@ struct AnalysisEnergyCorrelator { for (auto& t : addTrackCuts) { fTrackCuts.push_back(reinterpret_cast(t)); fTrackCutNames.push_back(t->GetName()); + trackCutStr += Form(",%s", t->GetName()); } } @@ -797,13 +798,13 @@ struct AnalysisEnergyCorrelator { groupedMCTracks1.bindInternalIndicesTo(&mcTracks); groupedMCTracks2.bindInternalIndicesTo(&mcTracks); for (auto& t1 : groupedMCTracks1) { - auto t1_raw = groupedMCTracks1.rawIteratorAt(t1.globalIndex()); + auto t1_raw = mcTracks.rawIteratorAt(t1.globalIndex()); for (auto& sig : fGenMCSignals) { if (sig->CheckSignal(true, t1_raw)) { if (t1.mcCollisionId() != event1.mcCollisionId()) { // check that the mc track belongs to the same mc collision as the reconstructed event continue; } - VarManager::FillTrackMC(groupedMCTracks1, t1_raw); + VarManager::FillTrackMC(mcTracks, t1_raw); if (!MixedEvent && !PionMass) { fHistMan->FillHistClass(Form("MCTruthGenSel_%s", sig->GetName()), VarManager::fgValues); } From 189422efa8bfdb6ee7132a0c39e4339bed39fe46 Mon Sep 17 00:00:00 2001 From: "Q.Y. Xia" <91366503+huinaibing@users.noreply.github.com> Date: Fri, 20 Mar 2026 16:40:28 +0800 Subject: [PATCH 342/347] [PWGCF] Add closure test for rho calculation (#15459) --- PWGCF/Flow/Tasks/pidFlowPtCorr.cxx | 57 ++++++++++++++++++++++++------ 1 file changed, 47 insertions(+), 10 deletions(-) diff --git a/PWGCF/Flow/Tasks/pidFlowPtCorr.cxx b/PWGCF/Flow/Tasks/pidFlowPtCorr.cxx index bc38ec4cb09..0266e81304d 100644 --- a/PWGCF/Flow/Tasks/pidFlowPtCorr.cxx +++ b/PWGCF/Flow/Tasks/pidFlowPtCorr.cxx @@ -144,6 +144,7 @@ struct PidFlowPtCorr { O2_DEFINE_CONFIGURABLE(cfgOutPutPtSpectra, bool, false, "output pt spectra for data, MC and RECO"); O2_DEFINE_CONFIGURABLE(cfgCheck2MethodDiff, bool, false, "check difference between v2' && v2''"); O2_DEFINE_CONFIGURABLE(cfgUseITSOnly4MeanPt, bool, false, "use ITS only to calculate mean pt"); + O2_DEFINE_CONFIGURABLE(cfgClosureTest, int, 0, "choose (val) percent particle from charged to pass Pion PID selection"); } switchsOpts; /** @@ -566,14 +567,23 @@ struct PidFlowPtCorr { registry.add("meanptCentNbs/hChargedPionWithNpair", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); registry.add("meanptCentNbs/hChargedPionFull", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); registry.add("meanptCentNbs/hPion", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); + registry.add("meanptCentNbs/hPionMeanptWeightPidflow", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); + + if (switchsOpts.cfgClosureTest.value != 0) { + registry.add("meanptCentNbs/hPionMeanptWeightC22pure", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); + registry.add("meanptCentNbs/hPionMeanptWeightMeanpt", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); + registry.add("meanptCentNbs/hPionMeanptWeightC22prime", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); + } registry.add("meanptCentNbs/hChargedKaonWithNpair", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); registry.add("meanptCentNbs/hChargedKaonFull", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); registry.add("meanptCentNbs/hKaon", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); + registry.add("meanptCentNbs/hKaonMeanptWeightPidflow", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); registry.add("meanptCentNbs/hChargedProtonWithNpair", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); registry.add("meanptCentNbs/hChargedProtonFull", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); registry.add("meanptCentNbs/hProton", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); + registry.add("meanptCentNbs/hProtonMeanptWeightPidflow", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); // end pid // end init tprofile3d for <2'> - meanpt @@ -715,6 +725,13 @@ struct PidFlowPtCorr { template bool isPion(TrackObject const& track) { + if (switchsOpts.cfgClosureTest.value != 0) { + float rnd4test = fRndm->Rndm() * 100; + if (rnd4test < switchsOpts.cfgClosureTest.value) { + return true; + } + } // closure test + bool resultPion = true; // Declare ITSResponse object internally to get ITS Sigma @@ -911,20 +928,19 @@ struct PidFlowPtCorr { return; registry.fill(HIST("meanptCentNbs/hCharged"), ptSum / nch, cent, rndm * cfgFlowNbootstrap, val, nch * dnx); - registry.fill(HIST("meanptCentNbs/hChargedMeanpt"), ptSum / nch, cent, rndm * cfgFlowNbootstrap, ptSum / nch, nch * dnx); + registry.fill(HIST("meanptCentNbs/hChargedMeanpt"), ptSum / nch, cent, rndm * cfgFlowNbootstrap, ptSum / nch, nch * dnx * val); } /** - * @brief note that the graph's x axis is pid meanpt, for <2'> weight is nPid * npairPID, for <2> weight is nch * npair + * @brief note that the graph's x axis is pid meanpt, for <2'> weight is nPid * npairPID, for <2> weight is nPid * npair * * @param cent - * @param nch * @param rndm * @param type * @param pidPtSum * @param nPid */ - void fillFC4PtC22(const double& cent, const double& nch, const double& rndm, MyParticleType type, const double& pidPtSum, const double& nPid) + void fillFC4PtC22(const double& cent, const double& rndm, MyParticleType type, const double& pidPtSum, const double& nPid) { // <2> double dnx, val; @@ -951,8 +967,27 @@ struct PidFlowPtCorr { return; registry.fill(HIST("meanptCentNbs/hPion"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, pidc22, nPid * npairPid); - registry.fill(HIST("meanptCentNbs/hChargedPionFull"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, val, dnx * nch); + registry.fill(HIST("meanptCentNbs/hChargedPionFull"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, val, dnx * nPid); registry.fill(HIST("meanptCentNbs/hChargedPionWithNpair"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, val, dnx); + registry.fill(HIST("meanptCentNbs/hPionMeanptWeightPidflow"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, pidPtSum / nPid, nPid * npairPid * pidc22 * pidc22 / val); + + if (switchsOpts.cfgClosureTest.value != 0) { + double npair4c22pure = fGFW->Calculate(corrconfigs.at(29), 0, kTRUE).real(); + if (npair4c22pure > 1e-3) + registry.fill(HIST("meanptCentNbs/hPionMeanptWeightC22pure"), + pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, + pidPtSum / nPid, + nPid * npairPid * fGFW->Calculate(corrconfigs.at(29), 0, kFALSE).real() / npair4c22pure); + + registry.fill(HIST("meanptCentNbs/hPionMeanptWeightMeanpt"), + pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, + pidPtSum / nPid, + nPid * npairPid * pidPtSum / nPid); + registry.fill(HIST("meanptCentNbs/hPionMeanptWeightC22prime"), + pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, + pidPtSum / nPid, + nPid * npairPid * pidc22); + } break; // end pion @@ -967,8 +1002,9 @@ struct PidFlowPtCorr { return; registry.fill(HIST("meanptCentNbs/hKaon"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, pidc22, nPid * npairPid); - registry.fill(HIST("meanptCentNbs/hChargedKaonFull"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, val, dnx * nch); + registry.fill(HIST("meanptCentNbs/hChargedKaonFull"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, val, dnx * nPid); registry.fill(HIST("meanptCentNbs/hChargedKaonWithNpair"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, val, dnx); + registry.fill(HIST("meanptCentNbs/hKaonMeanptWeightPidflow"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, pidPtSum / nPid, nPid * npairPid * pidc22 * pidc22 / val); break; // end kaon @@ -983,8 +1019,9 @@ struct PidFlowPtCorr { return; registry.fill(HIST("meanptCentNbs/hProton"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, pidc22, nPid * npairPid); - registry.fill(HIST("meanptCentNbs/hChargedProtonFull"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, val, dnx * nch); + registry.fill(HIST("meanptCentNbs/hChargedProtonFull"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, val, dnx * nPid); registry.fill(HIST("meanptCentNbs/hChargedProtonWithNpair"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, val, dnx); + registry.fill(HIST("meanptCentNbs/hProtonMeanptWeightPidflow"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, pidPtSum / nPid, nPid * npairPid * pidc22 * pidc22 / val); break; // end proton @@ -2066,13 +2103,13 @@ struct PidFlowPtCorr { fillFC4PtC22(cent, ptSum, nch, rndm); if (nPionWeighted > 0) - fillFC4PtC22(cent, nch, rndm, MyParticleType::kPion, pionPtSum, nPionWeighted); + fillFC4PtC22(cent, rndm, MyParticleType::kPion, pionPtSum, nPionWeighted); if (nKaonWeighted > 0) - fillFC4PtC22(cent, nch, rndm, MyParticleType::kKaon, kaonPtSum, nKaonWeighted); + fillFC4PtC22(cent, rndm, MyParticleType::kKaon, kaonPtSum, nKaonWeighted); if (nProtonWeighted > 0) - fillFC4PtC22(cent, nch, rndm, MyParticleType::kProton, protonPtSum, nProtonWeighted); + fillFC4PtC22(cent, rndm, MyParticleType::kProton, protonPtSum, nProtonWeighted); if (switchsOpts.cfgOutPutPtSpectra.value) { // charged calculation From 8cd03406d898904080e63beb5a65f4dfb26c59df Mon Sep 17 00:00:00 2001 From: Thorkj <154221526+Thorkj@users.noreply.github.com> Date: Fri, 20 Mar 2026 09:41:15 +0100 Subject: [PATCH 343/347] [PWGCF] small bug fixes in regard to TPC-FIT correlations, and the created histograms (#15450) Co-authored-by: ALICE Action Bot --- .../Tasks/corrSparse.cxx | 92 +++++++++++++------ 1 file changed, 66 insertions(+), 26 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/corrSparse.cxx b/PWGCF/TwoParticleCorrelations/Tasks/corrSparse.cxx index e0c75ff22a6..6c6e7464216 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/corrSparse.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/corrSparse.cxx @@ -100,6 +100,7 @@ struct CorrSparse { O2_DEFINE_CONFIGURABLE(processFT0A, bool, true, "Process FT0A correlations") O2_DEFINE_CONFIGURABLE(processFT0C, bool, true, "Process FT0C correlations") O2_DEFINE_CONFIGURABLE(processMFT, bool, true, "Process MFT correlations") + O2_DEFINE_CONFIGURABLE(withGain, bool, true, "Use gain for FT0A and FT0C") } cfgDetectorConfig; @@ -143,9 +144,7 @@ struct CorrSparse { O2_DEFINE_CONFIGURABLE(cfgRejectFT0CInside, bool, false, "Rejection of inner ring channels of the FT0C detector") O2_DEFINE_CONFIGURABLE(cfgRejectFT0COutside, bool, false, "Rejection of outer ring channels of the FT0C detector") O2_DEFINE_CONFIGURABLE(cfgRemapFT0ADeadChannels, bool, false, "If true, remap FT0A channels 60-63 to amplitudes from 92-95 respectively") - O2_DEFINE_CONFIGURABLE(cfgRemapFT0CDeadChannels, bool, false, "If true, remap FT0C channels 177->145, 176->144, 178->146, 179->147, 139->115") - - } cfgFITConfig; + O2_DEFINE_CONFIGURABLE(cfgRemapFT0CDeadChannels, bool, false, "If true, remap FT0C channels 177->145, 176->144, 178->146, 179->147, 139->115")} cfgFITConfig; O2_DEFINE_CONFIGURABLE(cfgMinMixEventNum, int, 5, "Minimum number of events to mix") O2_DEFINE_CONFIGURABLE(cfgMergingCut, float, 0.02, "Merging cut on track merge") @@ -157,7 +156,6 @@ struct CorrSparse { O2_DEFINE_CONFIGURABLE(cfgCentralityWeight, std::string, "", "CCDB path to centrality weight object") O2_DEFINE_CONFIGURABLE(cfgLocalEfficiency, bool, false, "Use local efficiency object") O2_DEFINE_CONFIGURABLE(cfgUseEventWeights, bool, false, "Use event weights for mixed event") - O2_DEFINE_CONFIGURABLE(cfgCollType, int, 0, "Collision type: 0 = pp, 1 = pPb, 2 = pO, 3 = OO") struct : ConfigurableGroup { O2_DEFINE_CONFIGURABLE(cfgMultCentHighCutFunction, std::string, "[0] + [1]*x + [2]*x*x + [3]*x*x*x + [4]*x*x*x*x + 10.*([5] + [6]*x + [7]*x*x + [8]*x*x*x + [9]*x*x*x*x)", "Functional for multiplicity correlation cut"); @@ -190,6 +188,11 @@ struct CorrSparse { TF1* fT0AV0ASigma = nullptr; } cfgFuncParas; + Configurable cfgCutFV0{"cfgCutFV0", 50., "FV0A threshold"}; + Configurable cfgCutFT0A{"cfgCutFT0A", 150., "FT0A threshold"}; + Configurable cfgCutFT0C{"cfgCutFT0C", 50., "FT0C threshold"}; + Configurable cfgCutZDC{"cfgCutZDC", 10., "ZDC threshold"}; + SliceCache cache; SliceCache cacheNch; @@ -236,7 +239,7 @@ struct CorrSparse { // make the filters and cuts. Filter collisionFilter = (nabs(aod::collision::posZ) < cfgZVtxCut); - Filter trackFilter = (nabs(aod::track::eta) < cfgTrackCuts.cfgEtaCut) && (cfgTrackCuts.cfgPtCutMin < aod::track::pt) && (cfgTrackCuts.cfgPtCutMax > aod::track::pt) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)) && (aod::track::tpcChi2NCl < cfgTrackCuts.cfgCutChi2prTPCcls) && (aod::track::dcaZ < cfgTrackCuts.cfgCutDCAz); + Filter trackFilter = (nabs(aod::track::eta) < cfgTrackCuts.cfgEtaCut) && (cfgTrackCuts.cfgPtCutMin < aod::track::pt) && (cfgTrackCuts.cfgPtCutMax > aod::track::pt) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t)true)) && (aod::track::tpcChi2NCl < cfgTrackCuts.cfgCutChi2prTPCcls) && (aod::track::dcaZ < cfgTrackCuts.cfgCutDCAz); Filter mftTrackEtaFilter = ((aod::fwdtrack::eta < cfgMftConfig.etaMftTrackMaxFilter) && (aod::fwdtrack::eta > cfgMftConfig.etaMftTrackMinFilter)); @@ -399,22 +402,22 @@ struct CorrSparse { if (cfgDetectorConfig.processFT0A) { registry.add("deltaEta_deltaPhi_same_TPC_FT0A", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaTpcFt0a}}); // check to see the delta eta and delta phi distribution registry.add("deltaEta_deltaPhi_mixed_TPC_FT0A", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaTpcFt0a}}); - registry.add("Assoc_amp_same_TPC_FT0A", "", {HistType::kTH2D, {axisChannelFt0aAxis, axisAmplitudeFt0a}}); - registry.add("Assoc_amp_mixed_TPC_FT0A", "", {HistType::kTH2D, {axisChannelFt0aAxis, axisAmplitudeFt0a}}); - registry.add("Trig_hist_TPC_FT0A", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisPtTrigger}}}); + registry.add("Assoc_amp_same", "", {HistType::kTH2D, {axisChannelFt0aAxis, axisAmplitudeFt0a}}); + registry.add("Assoc_amp_mixed", "", {HistType::kTH2D, {axisChannelFt0aAxis, axisAmplitudeFt0a}}); + registry.add("Trig_hist", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisPtTrigger}}}); } if (cfgDetectorConfig.processFT0C) { registry.add("deltaEta_deltaPhi_same_TPC_FT0C", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaTpcFt0c}}); // check to see the delta eta and delta phi distribution registry.add("deltaEta_deltaPhi_mixed_TPC_FT0C", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaTpcFt0c}}); - registry.add("Assoc_amp_same_TPC_FT0C", "", {HistType::kTH2D, {axisChannelFt0aAxis, axisAmplitudeFt0a}}); - registry.add("Assoc_amp_mixed_TPC_FT0C", "", {HistType::kTH2D, {axisChannelFt0aAxis, axisAmplitudeFt0a}}); - registry.add("Trig_hist_TPC_FT0C", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisPtTrigger}}}); + registry.add("Assoc_amp_same", "", {HistType::kTH2D, {axisChannelFt0aAxis, axisAmplitudeFt0a}}); + registry.add("Assoc_amp_mixed", "", {HistType::kTH2D, {axisChannelFt0aAxis, axisAmplitudeFt0a}}); + registry.add("Trig_hist", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisPtTrigger}}}); } if (cfgDetectorConfig.processFV0) { registry.add("deltaEta_deltaPhi_same_TPC_FV0", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaTpcFv0}}); // check to see the delta eta and delta phi distribution registry.add("deltaEta_deltaPhi_same_TPC_FV0", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaTpcFv0}}); // check to see the delta eta and delta phi distribution registry.add("deltaEta_deltaPhi_mixed_TPC_FV0", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaTpcFv0}}); - registry.add("Trig_hist_FT0A_FT0C", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisPtTrigger}}}); + registry.add("Trig_hist", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisPtTrigger}}}); } } @@ -768,7 +771,7 @@ struct CorrSparse { auto theta = std::atan2(r, z); return -std::log(std::tan(0.5 * theta)); } - + // checks if it is an accepted mft track template bool isAcceptedMftTrack(TTrack const& mftTrack) { @@ -1065,13 +1068,23 @@ struct CorrSparse { float deltaEta = track1.eta() - eta; if (system == SameEvent) { + if (cfgDetectorConfig.processMFT) { + registry.fill(HIST("deltaEta_deltaPhi_same_MFT_FV0"), deltaPhi, deltaEta, amplitude * triggerWeight); + } else { + registry.fill(HIST("deltaEta_deltaPhi_same_TPC_FV0"), deltaPhi, deltaEta, amplitude * triggerWeight); + } + registry.fill(HIST("Assoc_amp_same"), channelID, amplitude); same->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track1.pt(), deltaPhi, deltaEta, amplitude * triggerWeight); - registry.fill(HIST("deltaEta_deltaPhi_same_MFT_FV0"), deltaPhi, deltaEta, amplitude * triggerWeight); + } else if (system == MixedEvent) { + if (cfgDetectorConfig.processMFT) { + registry.fill(HIST("deltaEta_deltaPhi_mixed_MFT_FV0"), deltaPhi, deltaEta, amplitude); + } else { + registry.fill(HIST("deltaEta_deltaPhi_mixed_TPC_FV0"), deltaPhi, deltaEta, amplitude); + } registry.fill(HIST("Assoc_amp_mixed"), channelID, amplitude); mixed->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track1.pt(), deltaPhi, deltaEta, amplitude); - registry.fill(HIST("deltaEta_deltaPhi_mixed_MFT_FV0"), deltaPhi, deltaEta, amplitude); } } } @@ -1091,7 +1104,11 @@ struct CorrSparse { for (std::size_t iCh = 0; iCh < channelSize; iCh++) { int channelID = 0; float amplitude = 0.; - getChannelWithGain(tracks2, iCh, channelID, amplitude, corType); + if (cfgDetectorConfig.withGain) { + getChannelWithGain(tracks2, iCh, channelID, amplitude, corType); + } else { + getChannelFT0(tracks2, iCh, channelID, amplitude, corType); + } // reject depending on FT0C/FT0A rings if (corType == kFT0C) { @@ -1111,25 +1128,41 @@ struct CorrSparse { if (system == SameEvent) { if (corType == kFT0A) { + if (cfgDetectorConfig.processMFT) { + registry.fill(HIST("deltaEta_deltaPhi_same_MFT_FT0A"), deltaPhi, deltaEta, amplitude * triggerWeight); + } else { + registry.fill(HIST("deltaEta_deltaPhi_same_TPC_FT0A"), deltaPhi, deltaEta, amplitude * triggerWeight); + } registry.fill(HIST("Assoc_amp_same"), channelID, amplitude); same->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track1.pt(), deltaPhi, deltaEta, amplitude * triggerWeight); - registry.fill(HIST("deltaEta_deltaPhi_same_MFT_FT0A"), deltaPhi, deltaEta, amplitude * triggerWeight); } if (corType == kFT0C) { + if (cfgDetectorConfig.processMFT) { + registry.fill(HIST("deltaEta_deltaPhi_same_MFT_FT0C"), deltaPhi, deltaEta, amplitude * triggerWeight); + } else { + registry.fill(HIST("deltaEta_deltaPhi_same_TPC_FT0C"), deltaPhi, deltaEta, amplitude * triggerWeight); + } registry.fill(HIST("Assoc_amp_same"), channelID, amplitude); same->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track1.pt(), deltaPhi, deltaEta, amplitude * triggerWeight); - registry.fill(HIST("deltaEta_deltaPhi_same_MFT_FT0C"), deltaPhi, deltaEta, amplitude * triggerWeight); } } else if (system == MixedEvent) { if (corType == kFT0A) { + if (cfgDetectorConfig.processMFT) { + registry.fill(HIST("deltaEta_deltaPhi_mixed_MFT_FT0A"), deltaPhi, deltaEta, amplitude); + } else { + registry.fill(HIST("deltaEta_deltaPhi_mixed_TPC_FT0A"), deltaPhi, deltaEta, amplitude); + } registry.fill(HIST("Assoc_amp_mixed"), channelID, amplitude); mixed->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track1.pt(), deltaPhi, deltaEta, amplitude); - registry.fill(HIST("deltaEta_deltaPhi_mixed_MFT_FT0A"), deltaPhi, deltaEta, amplitude); } if (corType == kFT0C) { + if (cfgDetectorConfig.processMFT) { + registry.fill(HIST("deltaEta_deltaPhi_mixed_MFT_FT0C"), deltaPhi, deltaEta, amplitude); + } else { + registry.fill(HIST("deltaEta_deltaPhi_mixed_TPC_FT0C"), deltaPhi, deltaEta, amplitude); + } registry.fill(HIST("Assoc_amp_mixed"), channelID, amplitude); mixed->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track1.pt(), deltaPhi, deltaEta, amplitude); - registry.fill(HIST("deltaEta_deltaPhi_mixed_MFT_FT0C"), deltaPhi, deltaEta, amplitude); } } } @@ -1482,7 +1515,10 @@ struct CorrSparse { if (!collision.has_foundFT0()) return; loadAlignParam(bc.timestamp()); - loadGain(bc); + if (cfgDetectorConfig.withGain) { + loadGain(bc); + } + loadCorrection(bc.timestamp()); if ((tpctracks.size() < cfgEventSelection.cfgMinMult || tpctracks.size() >= cfgEventSelection.cfgMaxMult)) { @@ -1571,7 +1607,7 @@ struct CorrSparse { } } } - PROCESS_SWITCH(CorrSparse, processSameMftReassociated2DFIT, "Process same event for MFT-FIT correlation with reassociated tracks", true); + PROCESS_SWITCH(CorrSparse, processSameMftReassociated2DFIT, "Process same event for MFT-FIT correlation with reassociated tracks", false); ///////////////////////// ////////Mid-Mid////////// @@ -1588,14 +1624,15 @@ struct CorrSparse { if (cfgUseAdditionalEventCut && !eventSelected(collision, tracks.size(), true)) return; - registry.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin + loadCorrection(bc.timestamp()); + + fillYield(collision, tracks); if (tracks.size() < cfgEventSelection.cfgMinMult || tracks.size() >= cfgEventSelection.cfgMaxMult) { return; } - loadCorrection(bc.timestamp()); - fillYield(collision, tracks); + registry.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin fillCorrelations(tracks, tracks, collision.posZ(), tracks.size(), SameEvent, getMagneticField(bc.timestamp())); } @@ -1623,7 +1660,10 @@ struct CorrSparse { } loadAlignParam(bc.timestamp()); - // loadGain(bc); + if (cfgDetectorConfig.withGain) { + loadGain(bc); + } + loadCorrection(bc.timestamp()); registry.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin From fe3e5955b6f7e50409f5afa48c0367b30ffbff50 Mon Sep 17 00:00:00 2001 From: smaff92 <33285879+smaff92@users.noreply.github.com> Date: Fri, 20 Mar 2026 18:04:19 +0900 Subject: [PATCH 344/347] =?UTF-8?q?[PWGJE]=20Temporary=20functions=20to=20?= =?UTF-8?q?quickly=20QA=20Prompt=20Photon=20MC=20production.=20Will=20m?= =?UTF-8?q?=E2=80=A6=20(#15462)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ALICE Action Bot --- PWGJE/Tasks/statPromptPhoton.cxx | 467 ++++++++++++++++++++++++++++++- 1 file changed, 466 insertions(+), 1 deletion(-) diff --git a/PWGJE/Tasks/statPromptPhoton.cxx b/PWGJE/Tasks/statPromptPhoton.cxx index 98c52aa45e7..4e13332dcfe 100644 --- a/PWGJE/Tasks/statPromptPhoton.cxx +++ b/PWGJE/Tasks/statPromptPhoton.cxx @@ -51,9 +51,9 @@ #include #include +#include #include #include - using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; @@ -96,6 +96,7 @@ struct statPromptPhoton { Configurable cfgTrackFilter{"cfgTrackFilter", "globalTracks", "set track selections"}; Configurable cfgJETracks{"cfgJETracks", false, "Enables running on derived JE data"}; Configurable cfgGenHistograms{"cfgGenHistograms", false, "Enables Generated histograms"}; + Configurable cfgGenReqRec{"cfgGenReqRec", false, "Only consider generated events which are successfully reconstructed"}; Configurable cfgRecHistograms{"cfgRecHistograms", false, "Enables Reconstructed histograms"}; Configurable cfgDataHistograms{"cfgDataHistograms", false, "Enables Data histograms"}; Configurable cfgTriggerMasks{"cfgTriggerMasks", "", "possible JE Trigger masks: fJetChLowPt,fJetChHighPt,fTrackLowPt,fTrackHighPt,fJetD0ChLowPt,fJetD0ChHighPt,fJetLcChLowPt,fJetLcChHighPt,fEMCALReadout,fJetFullHighPt,fJetFullLowPt,fJetNeutralHighPt,fJetNeutralLowPt,fGammaVeryHighPtEMCAL,fGammaVeryHighPtDCAL,fGammaHighPtEMCAL,fGammaHighPtDCAL,fGammaLowPtEMCAL,fGammaLowPtDCAL,fGammaVeryLowPtEMCAL,fGammaVeryLowPtDCAL"}; @@ -191,9 +192,52 @@ struct statPromptPhoton { histos.add("REC_TrueTrigger_V_PtHadSum_Photon", "REC_Trigger_V_PtHadSum_Photon", kTH2F, {{100, 0, 100}, pthadAxis}); histos.add("REC_dR_Photon", "REC_dR_Photon", kTH1F, {{628, 0.0, 2 * TMath::Pi()}}); histos.add("REC_dR_Stern", "REC_dR_Stern", kTH1F, {{628, 0.0, 2 * TMath::Pi()}}); + histos.add("REC_prompt_phiQA", "REC_prompt_phiQA", kTH1F, {{640 * 2, 0, 2 * TMath::Pi()}}); + histos.add("REC_prompt_etaQA", "REC_prompt_etaQA", kTH1F, {{100, -1, 1}}); + histos.add("REC_prompt_ptQA", "REC_prompt_ptQA", kTH1F, {{82, -1.0, 40.0}}); + histos.add("REC_decay_phiQA", "REC_decay_phiQA", kTH1F, {{640 * 2, 0, 2 * TMath::Pi()}}); + histos.add("REC_decay_etaQA", "REC_decay_etaQA", kTH1F, {{100, -1, 1}}); + histos.add("REC_decay_ptQA", "REC_decay_ptQA", kTH1F, {{82, -1.0, 40.0}}); + histos.add("REC_frag_phiQA", "REC_frag_phiQA", kTH1F, {{640 * 2, 0, 2 * TMath::Pi()}}); + histos.add("REC_frag_etaQA", "REC_frag_etaQA", kTH1F, {{100, -1, 1}}); + histos.add("REC_frag_ptQA", "REC_frag_ptQA", kTH1F, {{82, -1.0, 40.0}}); + histos.add("REC_direct_phiQA", "REC_direct_phiQA", kTH1F, {{640 * 2, 0, 2 * TMath::Pi()}}); + histos.add("REC_direct_etaQA", "REC_direct_etaQA", kTH1F, {{100, -1, 1}}); + histos.add("REC_direct_ptQA", "REC_direct_ptQA", kTH1F, {{82, -1.0, 40.0}}); + histos.add("REC_cluster_phiQA", "REC_cluster_phiQA", kTH1F, {{640 * 2, 0, 2 * TMath::Pi()}}); + histos.add("REC_cluster_etaQA", "REC_cluster_etaQA", kTH1F, {{100, -1, 1}}); + histos.add("REC_cluster_energyQA", "REC_cluster_energyQA", kTH1F, {{82, -1.0, 40.0}}); + histos.add("REC_clusteriso_phiQA", "REC_clusteriso_phiQA", kTH1F, {{640 * 2, 0, 2 * TMath::Pi()}}); + histos.add("REC_clusteriso_etaQA", "REC_clusteriso_etaQA", kTH1F, {{100, -1, 1}}); + histos.add("REC_clusteriso_energyQA", "REC_clusteriso_energyQA", kTH1F, {{82, -1.0, 40.0}}); + histos.add("REC_track_phiQA", "REC_track_phiQA", kTH1F, {{640 * 2, 0, 2 * TMath::Pi()}}); + histos.add("REC_track_etaQA", "REC_track_etaQA", kTH1F, {{100, -1, 1}}); + histos.add("REC_track_ptQA", "REC_track_ptQA", kTH1F, {{82, -1.0, 40.0}}); + histos.add("REC_cluster_direct_phiQA", "REC_cluster_direct_phiQA", kTH1F, {{640 * 2, 0, 2 * TMath::Pi()}}); + histos.add("REC_cluster_direct_etaQA", "REC_cluster_direct_etaQA", kTH1F, {{100, -1, 1}}); + histos.add("REC_cluster_direct_energyQA", "REC_cluster_direct_energyQA", kTH1F, {{82, -1.0, 40.0}}); + histos.add("REC_cluster_frag_phiQA", "REC_cluster_frag_phiQA", kTH1F, {{640 * 2, 0, 2 * TMath::Pi()}}); + histos.add("REC_cluster_frag_etaQA", "REC_cluster_frag_etaQA", kTH1F, {{100, -1, 1}}); + histos.add("REC_cluster_frag_energyQA", "REC_cluster_frag_energyQA", kTH1F, {{82, -1.0, 40.0}}); + histos.add("REC_cluster_both_phiQA", "REC_cluster_both_phiQA", kTH1F, {{640 * 2, 0, 2 * TMath::Pi()}}); + histos.add("REC_cluster_both_etaQA", "REC_cluster_both_etaQA", kTH1F, {{100, -1, 1}}); + histos.add("REC_cluster_both_energyQA", "REC_cluster_both_energyQA", kTH1F, {{82, -1.0, 40.0}}); } if (cfgGenHistograms) { + histos.add("GEN_prompt_phiQA", "GEN_prompt_phiQA", kTH1F, {{640 * 2, 0, 2 * TMath::Pi()}}); + histos.add("GEN_prompt_etaQA", "GEN_prompt_etaQA", kTH1F, {{100, -1, 1}}); + histos.add("GEN_prompt_ptQA", "GEN_prompt_ptQA", kTH1F, {{82, -1.0, 40.0}}); + histos.add("GEN_decay_phiQA", "GEN_decay_phiQA", kTH1F, {{640 * 2, 0, 2 * TMath::Pi()}}); + histos.add("GEN_decay_etaQA", "GEN_decay_etaQA", kTH1F, {{100, -1, 1}}); + histos.add("GEN_decay_ptQA", "GEN_decay_ptQA", kTH1F, {{82, -1.0, 40.0}}); + histos.add("GEN_frag_phiQA", "GEN_frag_phiQA", kTH1F, {{640 * 2, 0, 2 * TMath::Pi()}}); + histos.add("GEN_frag_etaQA", "GEN_frag_etaQA", kTH1F, {{100, -1, 1}}); + histos.add("GEN_frag_ptQA", "GEN_frag_ptQA", kTH1F, {{82, -1.0, 40.0}}); + histos.add("GEN_direct_phiQA", "GEN_direct_phiQA", kTH1F, {{640 * 2, 0, 2 * TMath::Pi()}}); + histos.add("GEN_direct_etaQA", "GEN_direct_etaQA", kTH1F, {{100, -1, 1}}); + histos.add("GEN_direct_ptQA", "GEN_direct_ptQA", kTH1F, {{82, -1.0, 40.0}}); histos.add("GEN_nEvents", "GEN_nEvents", kTH1F, {{4, 0.0, 4.0}}); + histos.add("GEN_nEvents_simple", "GEN_nEvents", kTH1F, {{4, 0.0, 4.0}}); histos.add("GEN_True_Trigger_Energy", "GEN_True_Trigger_Energy", kTH1F, {{82, -1.0, 40.0}}); histos.add("GEN_Particle_Pt", "GEN_Particle_Pt", kTH1F, {{82, -1.0, 40.0}}); histos.add("GEN_True_Photon_Energy", "GEN_True_Photon_Energy", kTH1F, {{8200, -1.0, 40.0}}); @@ -420,6 +464,71 @@ struct statPromptPhoton { }; // end of track selection ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// + // Below is shamelessly stolen from Florian's gammetreeproducer code. + template + T iTopCopy(const T& particle) const + { + int iUp = particle.globalIndex(); + T currentParticle = particle; + int pdgCode = particle.pdgCode(); + auto mothers = particle.template mothers_as(); + while (iUp > 0 && mothers.size() == 1 && mothers[0].globalIndex() > 0 && mothers[0].pdgCode() == pdgCode) { + iUp = mothers[0].globalIndex(); + currentParticle = mothers[0]; + mothers = currentParticle.template mothers_as(); + } + return currentParticle; + } + + /// \brief Checks if a particle is a prompt photon + /// \param particle The MC particle to check + /// \return true if particle is a prompt photon, false otherwise + bool isPromptPhoton(const auto& particle) + { + if (particle.pdgCode() == PDG_t::kGamma && particle.isPhysicalPrimary() && std::abs(particle.getGenStatusCode()) < 90) { + return true; + } + return false; + } + /// \brief Checks if a particle is a direct prompt photon + /// \param particle The particle to check + /// \return true if particle is a direct prompt photon, false otherwise + bool isDirectPromptPhoton(const auto& particle) + { + // check if particle isa prompt photon + if (particle.pdgCode() == PDG_t::kGamma && particle.isPhysicalPrimary() && std::abs(particle.getGenStatusCode()) < 90) { + // find the top carbon copy + auto topCopy = iTopCopy(particle); + if (topCopy.pdgCode() == PDG_t::kGamma && std::abs(topCopy.getGenStatusCode()) < 40) { // < 40 is particle directly produced in hard scattering + return true; + } + } + return false; + } + /// \brief Checks if a particle is a fragmentation photon + /// \param particle The particle to check + /// \return true if particle is a fragmentation photon, false otherwise + bool isFragmentationPhoton(const auto& particle) + { + if (particle.pdgCode() == PDG_t::kGamma && particle.isPhysicalPrimary() && std::abs(particle.getGenStatusCode()) < 90) { + // find the top carbon copy + auto topCopy = iTopCopy(particle); + if (topCopy.pdgCode() == PDG_t::kGamma && std::abs(topCopy.getGenStatusCode()) >= 40) { // frag photon + return true; + } + } + return false; + } + /// \brief Checks if a particle is a decay photon + /// \param particle The particle to check + /// \return true if particle is a decay photon, false otherwise + bool isDecayPhoton(const auto& particle) + { + if (particle.pdgCode() == PDG_t::kGamma && particle.isPhysicalPrimary() && std::abs(particle.getGenStatusCode()) >= 90) { + return true; + } + return false; + } ///////////////////////////////////////////////////////////////////////////// // PROCESS @@ -1364,6 +1473,362 @@ struct statPromptPhoton { PROCESS_SWITCH(statPromptPhoton, processData, "processJE data", false); + int nEventsGenMC_Simple = 0; + void processMCGen_simple(filteredMCCollisions::iterator const& collision, soa::SmallGroups> const& recocolls, aod::JMcParticles const& mcParticles, jfilteredMCClusters const&) + { + nEventsGenMC_Simple++; + if (cfgDebug) { + if ((nEventsGenMC_Simple + 1) % 10000 == 0) { + std::cout << "Processed Gen MC Events: " << nEventsGenMC_Simple << std::endl; + } + } + histos.fill(HIST("GEN_nEvents_simple"), 0.5); + if (fabs(collision.posZ()) > cfgVtxCut) + return; + + if (cfgGenReqRec) { + if (recocolls.size() <= 0) // not reconstructed + return; + for (auto& recocoll : recocolls) { // poorly reconstructed + if (!recocoll.sel8()) + return; + if (fabs(recocoll.posZ()) > cfgVtxCut) + + return; + histos.fill(HIST("GEN_nEvents_simple"), 1.5); + + if (cfgEmcTrigger) { + if (!recocoll.isEmcalReadout()) + return; + } + histos.fill(HIST("GEN_nEvents_simple"), 2.5); + } + } + + // First pass: find all status -23 particles + for (auto& hardParticle : mcParticles) { + if (hardParticle.getGenStatusCode() != -23) + continue; + + bool isPhoton23 = (hardParticle.pdgCode() == 22); + + // For prompt: find the final-state photon descending from this -23 photon// + // For frag: find any final-state photon descending from this -23 non-photon// + // We search all final-state photons and check if they trace back here// + + for (auto& mcParticle : mcParticles) { + if (mcParticle.pdgCode() != 22) + continue; + if (mcParticle.getGenStatusCode() < 0) + continue; + if (std::fabs(mcParticle.getGenStatusCode()) >= 81 || !mcParticle.isPhysicalPrimary()) + continue; + + // Chase this final-state photon upward + int chaseindex = -1; + for (auto& mom : mcParticle.mothers_as()) { + chaseindex = mom.globalIndex(); + break; + } + if (chaseindex < 0) + continue; + + std::set visited; + bool chase = true; + bool hadronInChain = false; + bool reachedThisHard = false; + bool cleanPhotonChain = true; // all intermediates are photons + + while (chase) { + if (visited.count(chaseindex)) { + chase = false; + break; + } + visited.insert(chaseindex); + + for (auto& particle : mcParticles) { + if (particle.globalIndex() != chaseindex) + continue; + + if (particle.globalIndex() == hardParticle.globalIndex()) { + reachedThisHard = true; + chase = false; + break; + } + + int abspdg = std::abs(particle.pdgCode()); + if (abspdg > 100) + hadronInChain = true; + if (abspdg != 22) + cleanPhotonChain = false; + + int nextindex = -1; + for (auto& mom : particle.mothers_as()) { + nextindex = mom.globalIndex(); + break; + } + if (nextindex < 0) { + chase = false; + } else { + chaseindex = nextindex; + } + break; + } + } + + if (!reachedThisHard) + continue; + + if (isPhoton23 && cleanPhotonChain) { + // Case 1: -23 photon, clean photon chain — direct prompt + histos.fill(HIST("GEN_direct_phiQA"), mcParticle.phi()); + histos.fill(HIST("GEN_direct_etaQA"), mcParticle.eta()); + histos.fill(HIST("GEN_direct_ptQA"), mcParticle.pt()); + } else if (!isPhoton23 && !hadronInChain) { + // Case 2: -23 non-photon, no hadrons — fragmentation + histos.fill(HIST("GEN_frag_phiQA"), mcParticle.phi()); + histos.fill(HIST("GEN_frag_etaQA"), mcParticle.eta()); + histos.fill(HIST("GEN_frag_ptQA"), mcParticle.pt()); + } + } // final-state photon loop + } // hard particle loop + } + PROCESS_SWITCH(statPromptPhoton, processMCGen_simple, "processMC_QA_Gen", false); + int nEventsRecMC_simple = 0; + void processMCRec_simple(jfilteredCollisions::iterator const& collision, jfilteredMCClusters const& mcclusters, jTrackCandidates const&, soa::Join const&, TrackCandidates const&, aod::JMcParticles const& mcparticles, BcCandidates const&, jEMCtracks const& emctracks, aod::JetMcCollisions const&) + { + nEventsRecMC_simple++; + if (cfgDebug) { + if ((nEventsRecMC_simple + 1) % 10000 == 0) { + std::cout << "Processed JE Rec MC Events: " << nEventsRecMC_simple << std::endl; + } + } + histos.fill(HIST("REC_nEvents"), 0.5); + if (fabs(collision.posZ()) > cfgVtxCut) + return; + if (!collision.sel8()) + return; + histos.fill(HIST("REC_nEvents"), 1.5); + if (cfgEmcTrigger) { + if (!collision.isEmcalReadout()) + return; + } + histos.fill(HIST("REC_nEvents"), 2.5); + if (!jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) + return; + + for (auto& mccluster : mcclusters) { + histos.fill(HIST("REC_M02_BC"), mccluster.m02()); + if (mccluster.m02() < cfgLowM02) + continue; + if (mccluster.m02() > cfgHighM02) + continue; + if (mccluster.energy() < cfgLowClusterE) + continue; + if (mccluster.energy() > cfgHighClusterE) + continue; + if (fabs(mccluster.eta()) > cfgtrkMaxEta) + continue; + int ClusterHasDirectPhoton = 0; + int ClusterHasFragPhoton = 0; + auto ClusterParticles = mccluster.mcParticles_as(); + for (auto& clusterparticle : ClusterParticles) { + if (clusterparticle.pdgCode() != 22 && std::fabs(clusterparticle.pdgCode()) != 13) + continue; + if (clusterparticle.getGenStatusCode() < 0) + continue; + if (std::fabs(clusterparticle.getGenStatusCode()) >= 81) + continue; + + int chaseindex = -1; + for (auto& mom : clusterparticle.mothers_as()) { + chaseindex = mom.globalIndex(); + break; + } + if (chaseindex < 0) + continue; + + std::set visited; + bool chase = true; + bool hadronInChain = false; + bool cleanPhotonChain = true; + bool adrianprompt = false; + bool adrianfrag = false; + + while (chase) { + if (visited.count(chaseindex)) { + chase = false; + break; + } + visited.insert(chaseindex); + + for (auto& particle : mcparticles) { + if (particle.globalIndex() != chaseindex) + continue; + + if (particle.getGenStatusCode() == -23) { + if (particle.pdgCode() == 22 && cleanPhotonChain) { + adrianprompt = true; + } else if (particle.pdgCode() != 22 && !hadronInChain) { + adrianfrag = true; + } + chase = false; + break; + } + + int abspdg = std::abs(particle.pdgCode()); + if (abspdg > 100) + hadronInChain = true; + if (abspdg != 22) + cleanPhotonChain = false; + + int nextindex = -1; + for (auto& mom : particle.mothers_as()) { + nextindex = mom.globalIndex(); + break; + } + if (nextindex < 0) { + chase = false; + } else { + chaseindex = nextindex; + } + break; + } + } // chase + + if (adrianprompt) { + ClusterHasDirectPhoton++; + histos.fill(HIST("REC_direct_phiQA"), clusterparticle.phi()); + histos.fill(HIST("REC_direct_etaQA"), clusterparticle.eta()); + histos.fill(HIST("REC_direct_ptQA"), clusterparticle.pt()); + } + if (adrianfrag) { + ClusterHasFragPhoton++; + histos.fill(HIST("REC_frag_phiQA"), clusterparticle.phi()); + histos.fill(HIST("REC_frag_etaQA"), clusterparticle.eta()); + histos.fill(HIST("REC_frag_ptQA"), clusterparticle.pt()); + } + } // clusterparticle loop + + if (ClusterHasFragPhoton > 0) { + histos.fill(HIST("REC_cluster_frag_phiQA"), mccluster.phi()); + histos.fill(HIST("REC_cluster_frag_etaQA"), mccluster.eta()); + histos.fill(HIST("REC_cluster_frag_energyQA"), mccluster.energy()); + } + if (ClusterHasDirectPhoton > 0) { + histos.fill(HIST("REC_cluster_direct_phiQA"), mccluster.phi()); + histos.fill(HIST("REC_cluster_direct_etaQA"), mccluster.eta()); + histos.fill(HIST("REC_cluster_direct_energyQA"), mccluster.energy()); + } + if (ClusterHasDirectPhoton > 0 && ClusterHasFragPhoton > 0) { + histos.fill(HIST("REC_cluster_both_phiQA"), mccluster.phi()); + histos.fill(HIST("REC_cluster_both_etaQA"), mccluster.eta()); + histos.fill(HIST("REC_cluster_both_energyQA"), mccluster.energy()); + } + + // now we do cluster tracks + bool photontrigger = false; // is a neutral cluster + bool chargetrigger = false; // is definitely not a neutral cluster + auto tracksofcluster = mccluster.matchedTracks_as>(); + // first, we check if veto is required + double sumptT = 0; + bool clusterqa = false; + for (auto& ctrack : tracksofcluster) { + double etaT, phiT; + if (cfgJETracks) { + if (!jetderiveddatautilities::selectTrack(ctrack, trackFilter)) { + continue; + } + auto emctracksPerTrack = emctracks.sliceBy(EMCTrackPerTrack, ctrack.globalIndex()); + auto emctrack = emctracksPerTrack.iteratorAt(0); + etaT = emctrack.etaEmcal(); + phiT = emctrack.phiEmcal(); + } else { + auto ogtrack = ctrack.track_as(); + if (!trackSelection(ogtrack)) { + continue; + } + if (!ogtrack.isGlobalTrack()) { + continue; + } + etaT = ogtrack.trackEtaEmcal(); + phiT = ogtrack.trackPhiEmcal(); + } + + double etaC = mccluster.eta(); + double phiC = mccluster.phi(); + double ptT = ctrack.pt(); + bool etatrigger = false; + bool phitrigger = false; + double phidiff = TVector2::Phi_mpi_pi(mccluster.phi() - ctrack.phi()); + double etadiff = mccluster.eta() - ctrack.eta(); + + if (cfgPtClusterCut) { + if (fabs(etaT - etaC) < (0.010 + pow(ptT + 4.07, -2.5))) { + etatrigger = true; + } + + if (fabs(TVector2::Phi_mpi_pi(phiT - phiC)) < (0.015 + pow(ptT + 3.65, -2.0))) { + phitrigger = true; + } + } else { + if (fabs(etadiff) < 0.05) { + etatrigger = true; + } + + if (fabs(phidiff) < 0.05) { + phitrigger = true; + } + } + + if (etatrigger && phitrigger) { + chargetrigger = true; + sumptT += ptT; + } + if (chargetrigger) { + if (!clusterqa) { + histos.fill(HIST("REC_Cluster_QA"), 1.5); + clusterqa = true; + } + } + histos.fill(HIST("REC_Track_v_Cluster_Phi"), phidiff); + histos.fill(HIST("REC_Track_v_Cluster_Eta"), etadiff); + histos.fill(HIST("REC_Track_v_Cluster_Phi_Eta"), phidiff, etadiff); + histos.fill(HIST("REC_track_phiQA"), ctrack.phi()); + histos.fill(HIST("REC_track_etaQA"), ctrack.eta()); + histos.fill(HIST("REC_track_ptQA"), ctrack.pt()); + } // track of cluster loop + + if (chargetrigger && sumptT > 0) { + double mccluster_over_sumptT = mccluster.energy() / sumptT; + histos.fill(HIST("REC_SumPt_BC"), mccluster_over_sumptT); + if (mccluster_over_sumptT < 1.7) { + histos.fill(HIST("REC_Cluster_QA"), 2.5); // veto fails, cluster is charged + } else { + histos.fill(HIST("REC_Cluster_QA"), 3.5); // veto is good, cluster is converted to neutral cluster + // chargetrigger = false; + histos.fill(HIST("REC_SumPt_AC"), mccluster_over_sumptT); + } + } // sumptT check + + if (!chargetrigger) { + photontrigger = true; + } + + if (photontrigger) { + histos.fill(HIST("REC_clusteriso_phiQA"), mccluster.phi()); + histos.fill(HIST("REC_clusteriso_etaQA"), mccluster.eta()); + histos.fill(HIST("REC_clusteriso_energyQA"), mccluster.energy()); + } + if (chargetrigger) { + histos.fill(HIST("REC_cluster_phiQA"), mccluster.phi()); + histos.fill(HIST("REC_cluster_etaQA"), mccluster.eta()); + histos.fill(HIST("REC_cluster_energyQA"), mccluster.energy()); + } + } // clusters + } // main function + PROCESS_SWITCH(statPromptPhoton, processMCRec_simple, "processMC_QA_Rce", false); + }; // end of main struct WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) From 362e9aa31424b1041db9ea7aa76a0798af295520 Mon Sep 17 00:00:00 2001 From: mcoquet642 <74600025+mcoquet642@users.noreply.github.com> Date: Fri, 20 Mar 2026 10:49:51 +0100 Subject: [PATCH 345/347] [PWGDQ] Adding check if MC particle exists in mftMchMatcher (#15456) Co-authored-by: Maurice Coquet --- PWGDQ/Tasks/mftMchMatcher.cxx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/PWGDQ/Tasks/mftMchMatcher.cxx b/PWGDQ/Tasks/mftMchMatcher.cxx index a3b3779a83a..efabe3b2d51 100644 --- a/PWGDQ/Tasks/mftMchMatcher.cxx +++ b/PWGDQ/Tasks/mftMchMatcher.cxx @@ -544,6 +544,10 @@ struct mftMchMatcher { auto const& mchTrack = muonTrack.template matchMCHTrack_as(); auto const& mftTrack = muonTrack.template matchMFTTrack_as(); + if (!muonTrack.has_mcParticle() || !mftTrack.has_mcParticle()) { + return result; + } + bool isPaired = isPairedMuon(mchTrack.globalIndex(), matchablePairs); std::pair matchPair{mchTrack.globalIndex(), mftTrack.globalIndex()}; bool isTrueMatch = std::find(matchablePairs.begin(), matchablePairs.end(), matchPair) != matchablePairs.end(); From 7acdf2bba172dc06e8004a0a985c53b4ef5bd8e8 Mon Sep 17 00:00:00 2001 From: chengtt0406 <39661669+chengtt0406@users.noreply.github.com> Date: Fri, 20 Mar 2026 16:58:28 +0700 Subject: [PATCH 346/347] [PWGHF] Add MC matching for new decay channels (#15409) --- PWGHF/Core/DecayChannelsLegacy.h | 3 +- PWGHF/TableProducer/treeCreatorOmegacSt.cxx | 242 ++++++++++++++------ 2 files changed, 172 insertions(+), 73 deletions(-) diff --git a/PWGHF/Core/DecayChannelsLegacy.h b/PWGHF/Core/DecayChannelsLegacy.h index 675417d975b..0f0f8892a75 100644 --- a/PWGHF/Core/DecayChannelsLegacy.h +++ b/PWGHF/Core/DecayChannelsLegacy.h @@ -26,7 +26,8 @@ enum DecayType { OmegaczeroToXiPi, OmegaczeroToOmegaPi, OmegaczeroToOmegaK, - OmegaczeroToOmegaPiOneMu + OmegaczeroToOmegaPiOneMu, + XiczeroToOmegaK }; } // namespace hf_cand_xic0_omegac0 diff --git a/PWGHF/TableProducer/treeCreatorOmegacSt.cxx b/PWGHF/TableProducer/treeCreatorOmegacSt.cxx index 448e67f7eec..5fb90429589 100644 --- a/PWGHF/TableProducer/treeCreatorOmegacSt.cxx +++ b/PWGHF/TableProducer/treeCreatorOmegacSt.cxx @@ -10,11 +10,12 @@ // or submit itself to any jurisdiction. /// \file treeCreatorOmegacSt.cxx -/// \brief Task to reconstruct Ωc from strangeness-tracked Ω and pion/kaon +/// \brief Task to reconstruct Ωc/Ξc from strangeness-tracked Ω/Ξ and pion/kaon /// /// \author Jochen Klein /// \author Tiantian Cheng +#include "PWGHF/Core/DecayChannelsLegacy.h" #include "PWGHF/DataModel/TrackIndexSkimmingTables.h" #include "PWGHF/Utils/utilsTrkCandHf.h" #include "PWGLF/DataModel/LFStrangenessTables.h" @@ -306,6 +307,8 @@ struct HfTreeCreatorOmegacSt { {"hMassOmegaPiVsPt", "inv. mass #Omega + #pi;inv. mass (GeV/#it{c}^{2});p_{T} (GeV/#it{c})", {HistType::kTH2D, {{400, 1.5, 3.}, {10, 0., 10.}}}}, {"hMassOmegaK", "inv. mass #Omega + K;inv. mass (GeV/#it{c}^{2})", {HistType::kTH1D, {{400, 1.5, 3.}}}}, {"hMassOmegaKVsPt", "inv. mass #Omega + K;inv. mass (GeV/#it{c}^{2});p_{T} (GeV/#it{c})", {HistType::kTH2D, {{400, 1.5, 3.}, {10, 0., 10.}}}}, + {"hMassXiPi", "inv. mass #Xi + #pi;inv. mass (GeV/#it{c}^{2})", {HistType::kTH1D, {{400, 1.2, 3.2}}}}, + {"hMassXiPiVsPt", "inv. mass #Xi + #pi;inv. mass (GeV/#it{c}^{2});p_{T} (GeV/#it{c})", {HistType::kTH2D, {{400, 1.2, 3.2}, {10, 0., 10.}}}}, {"hMassOmegacId", "inv. mass #Omega + #pi (MC ID);inv. mass (GeV/#it{c}^{2})", {HistType::kTH1D, {{400, 1.5, 3.}}}}, {"hMassOmegacGen", "inv. mass #Omega + #pi (from MC);inv. mass (GeV/#it{c}^{2})", {HistType::kTH1D, {{400, 1.5, 3.}}}}, {"hPtVsMassOmega", "#Omega mass;p_{T} (GeV/#it{c});m (GeV/#it{c}^3)", {HistType::kTH2D, {{200, 0., 10.}, {1000, 1., 3.}}}}, @@ -366,70 +369,111 @@ struct HfTreeCreatorOmegacSt { for (const auto& mcParticle : mcParticles) { const bool isOmegaC = std::abs(mcParticle.pdgCode()) == constants::physics::Pdg::kOmegaC0; const bool isXiC = std::abs(mcParticle.pdgCode()) == constants::physics::Pdg::kXiC0; - if (isOmegaC || isXiC) { - const auto daughters = mcParticle.daughters_as(); - if (daughters.size() == NDaughters) { - int idxPionDaughter = -1; - int idxCascDaughter = -1; - int idxKaonDaughter = -1; - const auto daughters = mcParticle.daughters_as(); - for (const auto& daughter : daughters) { - if (idxCascDaughter < 0 && (std::abs(daughter.pdgCode()) == (isOmegaC ? kOmegaMinus : kXiMinus))) { - idxCascDaughter = daughter.globalIndex(); - } - if (idxPionDaughter < 0 && (std::abs(daughter.pdgCode()) == kPiPlus)) { - idxPionDaughter = daughter.globalIndex(); - } - if (idxKaonDaughter < 0 && (std::abs(daughter.pdgCode()) == kKPlus)) { - idxKaonDaughter = daughter.globalIndex(); - } - } - if (idxPionDaughter >= 0 && idxCascDaughter >= 0) { - decayChannel = o2::aod::hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaPi; // OmegaC -> Omega + Pi - } else if (idxKaonDaughter >= 0 && idxCascDaughter >= 0) { - decayChannel = o2::aod::hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaK; // OmegaC -> Omega + K - } else { - decayChannel = -1; // LOG(warning) << "Decay channel not recognized!"; + if (!isOmegaC && !isXiC) { + continue; + } + const auto daughters = mcParticle.daughters_as(); + if (daughters.size() != NDaughters) { + continue; + } + int idxPionDaughter = -1; + int idxCascDaughter = -1; + int idxKaonDaughter = -1; + for (const auto& daughter : daughters) { + const int absDauPdg = std::abs(daughter.pdgCode()); + if (idxCascDaughter < 0) { + if (absDauPdg == kOmegaMinus || absDauPdg == kXiMinus) { + idxCascDaughter = daughter.globalIndex(); } - if (decayChannel != -1) { - int const idxDaughter = (decayChannel == o2::aod::hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaPi) ? idxPionDaughter : idxKaonDaughter; - auto particle = mcParticles.rawIteratorAt(idxDaughter); - origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle, false, &idxBhadMothers); + } + if (idxPionDaughter < 0 && absDauPdg == kPiPlus) { + idxPionDaughter = daughter.globalIndex(); + } + if (idxKaonDaughter < 0 && absDauPdg == kKPlus) { + idxKaonDaughter = daughter.globalIndex(); + } + } - const auto& cascDaughter = mcParticles.iteratorAt(idxCascDaughter); - const auto& mcColl = mcParticle.mcCollision(); - std::array const primaryVertexPosGen = {mcColl.posX(), mcColl.posY(), mcColl.posZ()}; - std::array const secondaryVertexGen = {cascDaughter.vx(), cascDaughter.vy(), cascDaughter.vz()}; - float decayLengthCascGen = -1.; - float decayLengthXYCascGen = -1.; - if (cascDaughter.has_daughters()) { - const auto& cascDecayDaughter = cascDaughter.daughters_as().iteratorAt(0); - std::array const tertiaryVertexGen = {cascDecayDaughter.vx(), cascDecayDaughter.vy(), cascDecayDaughter.vz()}; - decayLengthCascGen = RecoDecay::distance(tertiaryVertexGen, primaryVertexPosGen); - decayLengthXYCascGen = RecoDecay::distanceXY(tertiaryVertexGen, primaryVertexPosGen); - } - const auto decayLengthGen = RecoDecay::distance(secondaryVertexGen, primaryVertexPosGen); - const auto decayLengthXYGen = RecoDecay::distanceXY(secondaryVertexGen, primaryVertexPosGen); - registry.fill(HIST("hDecayLengthScaledMc"), decayLengthGen * o2::constants::physics::MassOmegaC0 / mcParticle.mothers_first_as().p() * 1e4); - outputTableGen( - mcParticle.px(), - mcParticle.py(), - mcParticle.pz(), - mcParticle.pdgCode(), - cascDaughter.px(), - cascDaughter.py(), - cascDaughter.pz(), - cascDaughter.pdgCode(), - decayLengthGen, - decayLengthXYGen, - decayLengthCascGen, - decayLengthXYCascGen, - origin, - decayChannel); - mapMcPartToGenTable[mcParticle.globalIndex()] = outputTableGen.lastIndex(); + if (idxCascDaughter < 0) { + continue; + } + + int decayChannel = -1; + const int pdgCasc = std::abs(mcParticles.iteratorAt(idxCascDaughter).pdgCode()); + + if (isOmegaC) { + // Omegac0 -> Omega- pi+ or Xi- pi+ + if (idxPionDaughter >= 0) { + if (pdgCasc == kOmegaMinus) { + decayChannel = o2::aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToOmegaPi; + } else if (pdgCasc == kXiMinus) { + decayChannel = o2::aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToXiPi; } } + } else if (isXiC) { + // Xic0 -> Omega- K+ or Xi- pi+ + if (pdgCasc == kOmegaMinus && idxKaonDaughter >= 0) { + decayChannel = o2::aod::hf_cand_xic0_omegac0::DecayType::XiczeroToOmegaK; + } else if (pdgCasc == kXiMinus && idxPionDaughter >= 0) { + decayChannel = o2::aod::hf_cand_xic0_omegac0::DecayType::XiczeroToXiPi; + } + } + + if (decayChannel == -1) { + continue; + } + + int idxDaughter = -1; + switch (decayChannel) { + case o2::aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToOmegaPi: + case o2::aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToXiPi: + case o2::aod::hf_cand_xic0_omegac0::DecayType::XiczeroToXiPi: + idxDaughter = idxPionDaughter; + break; + case o2::aod::hf_cand_xic0_omegac0::DecayType::XiczeroToOmegaK: + idxDaughter = idxKaonDaughter; + break; + default: + idxDaughter = -1; + break; + } + + if (idxDaughter >= 0) { + auto particle = mcParticles.rawIteratorAt(idxDaughter); + origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle, false, &idxBhadMothers); } + + const auto& cascDaughter = mcParticles.iteratorAt(idxCascDaughter); + const auto& mcColl = mcParticle.mcCollision(); + std::array const primaryVertexPosGen = {mcColl.posX(), mcColl.posY(), mcColl.posZ()}; + std::array const secondaryVertexGen = {cascDaughter.vx(), cascDaughter.vy(), cascDaughter.vz()}; + float decayLengthCascGen = -1.; + float decayLengthXYCascGen = -1.; + if (cascDaughter.has_daughters()) { + const auto& cascDecayDaughter = cascDaughter.daughters_as().iteratorAt(0); + std::array const tertiaryVertexGen = {cascDecayDaughter.vx(), cascDecayDaughter.vy(), cascDecayDaughter.vz()}; + decayLengthCascGen = RecoDecay::distance(tertiaryVertexGen, primaryVertexPosGen); + decayLengthXYCascGen = RecoDecay::distanceXY(tertiaryVertexGen, primaryVertexPosGen); + } + const auto decayLengthGen = RecoDecay::distance(secondaryVertexGen, primaryVertexPosGen); + const auto decayLengthXYGen = RecoDecay::distanceXY(secondaryVertexGen, primaryVertexPosGen); + registry.fill(HIST("hDecayLengthScaledMc"), decayLengthGen * o2::constants::physics::MassOmegaC0 / mcParticle.mothers_first_as().p() * 1e4); + outputTableGen( + mcParticle.px(), + mcParticle.py(), + mcParticle.pz(), + mcParticle.pdgCode(), + cascDaughter.px(), + cascDaughter.py(), + cascDaughter.pz(), + cascDaughter.pdgCode(), + decayLengthGen, + decayLengthXYGen, + decayLengthCascGen, + decayLengthXYCascGen, + origin, + decayChannel); + mapMcPartToGenTable[mcParticle.globalIndex()] = outputTableGen.lastIndex(); } } PROCESS_SWITCH(HfTreeCreatorOmegacSt, processMc, "Process MC", true); @@ -476,7 +520,6 @@ struct HfTreeCreatorOmegacSt { } } } - const auto primaryVertex = getPrimaryVertex(collision); const std::array primaryVertexPos = {primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}; @@ -570,7 +613,6 @@ struct HfTreeCreatorOmegacSt { const auto massXi = RecoDecay::m(momentaCascDaughters, massesXiDaughters); std::array const massesOmegaDaughters = {o2::constants::physics::MassLambda0, o2::constants::physics::MassKPlus}; const auto massOmega = RecoDecay::m(momentaCascDaughters, massesOmegaDaughters); - registry.fill(HIST("hDca"), std::sqrt(impactParameterCasc.getR2())); registry.fill(HIST("hDcaXY"), impactParameterCasc.getY()); registry.fill(HIST("hDcaXYVsPt"), trackParCovCasc.getPt(), impactParameterCasc.getY()); @@ -588,7 +630,8 @@ struct HfTreeCreatorOmegacSt { std::array const massesOmegacToOmegaPi{o2::constants::physics::MassOmegaMinus, o2::constants::physics::MassPiPlus}; std::array const massesOmegacToOmegaK{o2::constants::physics::MassOmegaMinus, o2::constants::physics::MassKPlus}; - std::array const massesXicDaughters{o2::constants::physics::MassXiMinus, o2::constants::physics::MassPiPlus}; + // std::array const massesXicDaughters{o2::constants::physics::MassXiMinus, o2::constants::physics::MassPiPlus}; + std::array massesXicOrOmegacToXiPi{o2::constants::physics::MassXiMinus, o2::constants::physics::MassPiPlus}; std::array, NDaughters> momenta{}; auto trackParCovPr = getTrackParCov(v0TrackPr); @@ -662,11 +705,15 @@ struct HfTreeCreatorOmegacSt { df2.getTrackParamAtPCA(1).getPxPyPzGlo(momenta[1]); const auto massOmegaPi = RecoDecay::m(momenta, massesOmegacToOmegaPi); const auto massOmegaK = RecoDecay::m(momenta, massesOmegacToOmegaK); - const auto massXiC = RecoDecay::m(momenta, massesXicDaughters); + // const auto massXiC = RecoDecay::m(momenta, massesXicDaughters); + const auto massXiPi = RecoDecay::m(momenta, massesXicOrOmegacToXiPi); + registry.fill(HIST("hMassOmegaPi"), massOmegaPi); registry.fill(HIST("hMassOmegaPiVsPt"), massOmegaPi, RecoDecay::pt(momenta[0], momenta[1])); registry.fill(HIST("hMassOmegaK"), massOmegaK); registry.fill(HIST("hMassOmegaKVsPt"), massOmegaK, RecoDecay::pt(momenta[0], momenta[1])); + registry.fill(HIST("hMassXiPi"), massXiPi); + registry.fill(HIST("hMassXiPiVsPt"), massXiPi, RecoDecay::pt(momenta[0], momenta[1])); //--- do the MC Rec match if (mcParticles) { @@ -684,7 +731,7 @@ struct HfTreeCreatorOmegacSt { v0.posTrack_as(), // p <- lambda v0.negTrack_as()}; // pi <- lambda - if (decayChannel == o2::aod::hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaPi) { + if (decayChannel == o2::aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToOmegaPi) { // Match Omegac0 → Omega- + Pi+ indexRec = RecoDecay::getMatchedMCRec(mcParticles->get(), arrayDaughters, o2::constants::physics::kOmegaC0, std::array{+kPiPlus, +kKMinus, +kProton, +kPiMinus}, true, &sign, 3, &nPiToMuOmegac0, &nKaToPiOmegac0); @@ -700,17 +747,65 @@ struct HfTreeCreatorOmegacSt { } } } - } else if (decayChannel == o2::aod::hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaK) { - // Match Omegac0 → Omega- + K+ + // } else if (decayChannel == o2::aod::hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaK) { + // // Match Omegac0 → Omega- + K+ + // indexRec = RecoDecay::getMatchedMCRec(mcParticles->get(), arrayDaughters, o2::constants::physics::kOmegaC0, + // std::array{+kKPlus, +kKMinus, +kProton, +kPiMinus}, true, &sign, 3, &nPiToMuOmegac0, &nKaToPiOmegac0); + // indexRecCharmBaryon = indexRec; + // if (indexRec > -1) { + // // Omega- → K pi p (Cascade match) + // indexRec = RecoDecay::getMatchedMCRec(mcParticles->get(), arrayDaughtersCasc, +kOmegaMinus, std::array{+kKMinus, +kProton, +kPiMinus}, true, &signCasc, 2, &nPiToMuCasc, &nKaToPiCasc); + // if (indexRec > -1) { + // // Lambda → p pi (Lambda match) + // indexRec = RecoDecay::getMatchedMCRec(mcParticles->get(), arrayDaughtersV0, +kLambda0, std::array{+kProton, +kPiMinus}, true, &signV0, 1, &nPiToMuV0); + // if (indexRec > -1) { + // isMatched = true; + // } + // } + // } + } else if (decayChannel == o2::aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToXiPi) { + // Match Omegac0 -> Xi Pion indexRec = RecoDecay::getMatchedMCRec(mcParticles->get(), arrayDaughters, o2::constants::physics::kOmegaC0, - std::array{+kKPlus, +kKMinus, +kProton, +kPiMinus}, true, &sign, 3, &nPiToMuOmegac0, &nKaToPiOmegac0); + std::array{+kPiPlus, +kPiMinus, +kProton, +kPiMinus}, true, &sign, 3); + indexRecCharmBaryon = indexRec; + if (indexRec > -1) { + // Xi- → pi pi p (Cascade match) + indexRec = RecoDecay::getMatchedMCRec(mcParticles->get(), arrayDaughtersCasc, +kXiMinus, std::array{+kPiMinus, +kProton, +kPiMinus}, true, &signCasc, 2); + if (indexRec > -1) { + // Lambda → p pi (Lambda match) + indexRec = RecoDecay::getMatchedMCRec(mcParticles->get(), arrayDaughtersV0, +kLambda0, std::array{+kProton, +kPiMinus}, true, &signV0, 1); + if (indexRec > -1) { + isMatched = true; + } + } + } + } else if (decayChannel == o2::aod::hf_cand_xic0_omegac0::DecayType::XiczeroToOmegaK) { + // Match Xic0 → Omega- + K+ + indexRec = RecoDecay::getMatchedMCRec(mcParticles->get(), arrayDaughters, o2::constants::physics::kXiC0, + std::array{+kKPlus, +kKMinus, +kProton, +kPiMinus}, true, &sign, 3); indexRecCharmBaryon = indexRec; if (indexRec > -1) { // Omega- → K pi p (Cascade match) - indexRec = RecoDecay::getMatchedMCRec(mcParticles->get(), arrayDaughtersCasc, +kOmegaMinus, std::array{+kKMinus, +kProton, +kPiMinus}, true, &signCasc, 2, &nPiToMuCasc, &nKaToPiCasc); + indexRec = RecoDecay::getMatchedMCRec(mcParticles->get(), arrayDaughtersCasc, +kOmegaMinus, std::array{+kKMinus, +kProton, +kPiMinus}, true, &signCasc, 2); if (indexRec > -1) { // Lambda → p pi (Lambda match) - indexRec = RecoDecay::getMatchedMCRec(mcParticles->get(), arrayDaughtersV0, +kLambda0, std::array{+kProton, +kPiMinus}, true, &signV0, 1, &nPiToMuV0); + indexRec = RecoDecay::getMatchedMCRec(mcParticles->get(), arrayDaughtersV0, +kLambda0, std::array{+kProton, +kPiMinus}, true, &signV0, 1); + if (indexRec > -1) { + isMatched = true; + } + } + } + } else if (decayChannel == o2::aod::hf_cand_xic0_omegac0::DecayType::XiczeroToXiPi) { + // Match Xic0 -> Xi Pion + indexRec = RecoDecay::getMatchedMCRec(mcParticles->get(), arrayDaughters, o2::constants::physics::kXiC0, + std::array{+kPiPlus, +kPiMinus, +kProton, +kPiMinus}, true, &sign, 3); + indexRecCharmBaryon = indexRec; + if (indexRec > -1) { + // Xi- → pi pi p (Cascade match) + indexRec = RecoDecay::getMatchedMCRec(mcParticles->get(), arrayDaughtersCasc, +kXiMinus, std::array{+kPiMinus, +kProton, +kPiMinus}, true, &signCasc, 2); + if (indexRec > -1) { + // Lambda → p pi (Lambda match) + indexRec = RecoDecay::getMatchedMCRec(mcParticles->get(), arrayDaughtersV0, +kLambda0, std::array{+kProton, +kPiMinus}, true, &signV0, 1); if (indexRec > -1) { isMatched = true; } @@ -723,9 +818,12 @@ struct HfTreeCreatorOmegacSt { } } - if ((std::abs(massOmegaK - o2::constants::physics::MassOmegaC0) < massWindowOmegaC) || + if ((std::abs(massOmegaK - o2::constants::physics::MassXiC0) < massWindowXiC) || (std::abs(massOmegaPi - o2::constants::physics::MassOmegaC0) < massWindowOmegaC) || - (std::abs(massXiC - o2::constants::physics::MassXiC0) < massWindowXiC)) { + (std::abs(massXiPi - o2::constants::physics::MassXiC0) < massWindowXiC) || + (std::abs(massXiPi - o2::constants::physics::MassOmegaC0) < massWindowOmegaC) + + ) { registry.fill(HIST("hDecayLength"), decayLength * 1e4); registry.fill(HIST("hDecayLengthScaled"), decayLength * o2::constants::physics::MassOmegaC0 / RecoDecay::p(momenta[0], momenta[1]) * 1e4); outputTable(massOmega, From a82e0244e49aa626a8ea5f5a1adcebfbebdab603 Mon Sep 17 00:00:00 2001 From: scannito Date: Fri, 20 Mar 2026 12:56:29 +0100 Subject: [PATCH 347/347] Fix --- .../Strangeness/phiStrangeCorrelation.cxx | 30 ++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx b/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx index d5d30fe0841..89e06f7e192 100644 --- a/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx +++ b/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx @@ -412,11 +412,14 @@ struct PhiStrangenessCorrelation { if (analysisMode == kMassvsMass) { processCorrelations( [&](const auto& k0s, float w) { - histos.fill(HIST("phiK0S/h6PhiK0SData"), multiplicity, phiCand.pt(), k0s.pt(), phiCand.y() - k0s.y(), phiCand.m(), k0s.m(), w); + auto histID = HIST("phiK0S/h6PhiK0SData"); + histos.fill(histID, multiplicity, phiCand.pt(), k0s.pt(), phiCand.y() - k0s.y(), phiCand.m(), k0s.m(), w); }, [&](const auto& pion, float w) { - histos.fill(HIST("phiPi/h6PhiPiTPCData"), multiplicity, phiCand.pt(), pion.pt(), phiCand.y() - pion.y(), phiCand.m(), pion.nSigmaTPC(), w); - histos.fill(HIST("phiPi/h6PhiPiTOFData"), multiplicity, phiCand.pt(), pion.pt(), phiCand.y() - pion.y(), phiCand.m(), pion.nSigmaTOF(), w); + auto histID1 = HIST("phiPi/h6PhiPiTPCData"); + histos.fill(histID1, multiplicity, phiCand.pt(), pion.pt(), phiCand.y() - pion.y(), phiCand.m(), pion.nSigmaTPC(), w); + auto histID2 = HIST("phiPi/h6PhiPiTOFData"); + histos.fill(histID2, multiplicity, phiCand.pt(), pion.pt(), phiCand.y() - pion.y(), phiCand.m(), pion.nSigmaTOF(), w); }); } else if (analysisMode == kDeltaYvsDeltaPhi) { static_for<0, phiMassRegionLabels.size() - 1>([&](auto i_idx) { @@ -428,10 +431,12 @@ struct PhiStrangenessCorrelation { processCorrelations( [&](const auto& k0s, float w) { - histos.fill(HIST("phiK0S/h5PhiK0SData") + HIST(phiMassRegionLabels[i]), multiplicity, phiCand.pt(), k0s.pt(), phiCand.y() - k0s.y(), getDeltaPhi(phiCand.phi(), k0s.phi()), w); + auto histID = HIST("phiK0S/h5PhiK0SData") + HIST(phiMassRegionLabels[i]); + histos.fill(histID, multiplicity, phiCand.pt(), k0s.pt(), phiCand.y() - k0s.y(), getDeltaPhi(phiCand.phi(), k0s.phi()), w); }, [&](const auto& pion, float w) { - histos.fill(HIST("phiPi/h5PhiPiData") + HIST(phiMassRegionLabels[i]), multiplicity, phiCand.pt(), pion.pt(), phiCand.y() - pion.y(), getDeltaPhi(phiCand.phi(), pion.phi()), w); + auto histID = HIST("phiPi/h5PhiPiData") + HIST(phiMassRegionLabels[i]); + histos.fill(histID, multiplicity, phiCand.pt(), pion.pt(), phiCand.y() - pion.y(), getDeltaPhi(phiCand.phi(), pion.phi()), w); }); }); } @@ -522,7 +527,8 @@ struct PhiStrangenessCorrelation { if (analysisMode == kMassvsMass) { processCorrelations( [&](const auto& k0s, float w) { - histos.fill(HIST("phiK0S/h6PhiK0SDataMe"), multiplicity, phiCand.pt(), k0s.pt(), phiCand.y() - k0s.y(), phiCand.m(), k0s.m(), w); + auto histID = HIST("phiK0S/h6PhiK0SDataME"); + histos.fill(histID, multiplicity, phiCand.pt(), k0s.pt(), phiCand.y() - k0s.y(), phiCand.m(), k0s.m(), w); }); } else if (analysisMode == kDeltaYvsDeltaPhi) { static_for<0, phiMassRegionLabels.size() - 1>([&](auto i_idx) { @@ -534,7 +540,8 @@ struct PhiStrangenessCorrelation { processCorrelations( [&](const auto& k0s, float w) { - histos.fill(HIST("phiK0S/h5PhiK0SDataME") + HIST(phiMassRegionLabels[i]), multiplicity, phiCand.pt(), k0s.pt(), phiCand.y() - k0s.y(), getDeltaPhi(phiCand.phi(), k0s.phi()), w); + auto histID = HIST("phiK0S/h5PhiK0SDataME") + HIST(phiMassRegionLabels[i]); + histos.fill(histID, multiplicity, phiCand.pt(), k0s.pt(), phiCand.y() - k0s.y(), getDeltaPhi(phiCand.phi(), k0s.phi()), w); }); }); } @@ -611,8 +618,10 @@ struct PhiStrangenessCorrelation { if (analysisMode == kMassvsMass) { processCorrelations( [&](const auto& pion, float w) { - histos.fill(HIST("phiPi/h6PhiPiTPCDataME"), multiplicity, phiCand.pt(), pion.pt(), phiCand.y() - pion.y(), phiCand.m(), pion.nSigmaTPC(), w); - histos.fill(HIST("phiPi/h6PhiPiTOFDataME"), multiplicity, phiCand.pt(), pion.pt(), phiCand.y() - pion.y(), phiCand.m(), pion.nSigmaTOF(), w); + auto histID1 = HIST("phiPi/h6PhiPiTPCDataME"); + histos.fill(histID1, multiplicity, phiCand.pt(), pion.pt(), phiCand.y() - pion.y(), phiCand.m(), pion.nSigmaTPC(), w); + auto histID2 = HIST("phiPi/h6PhiPiTOFDataME"); + histos.fill(histID2, multiplicity, phiCand.pt(), pion.pt(), phiCand.y() - pion.y(), phiCand.m(), pion.nSigmaTOF(), w); }); } else if (analysisMode == kDeltaYvsDeltaPhi) { static_for<0, phiMassRegionLabels.size() - 1>([&](auto i_idx) { @@ -624,7 +633,8 @@ struct PhiStrangenessCorrelation { processCorrelations( [&](const auto& pion, float w) { - histos.fill(HIST("phiPi/h5PhiPiDataME") + HIST(phiMassRegionLabels[i]), multiplicity, phiCand.pt(), pion.pt(), phiCand.y() - pion.y(), getDeltaPhi(phiCand.phi(), pion.phi()), w); + auto histID = HIST("phiPi/h5PhiPiDataME") + HIST(phiMassRegionLabels[i]); + histos.fill(histID, multiplicity, phiCand.pt(), pion.pt(), phiCand.y() - pion.y(), getDeltaPhi(phiCand.phi(), pion.phi()), w); }); }); }